rt-thread/bsp/gkipc/drivers/drv_mmc.c

343 lines
11 KiB
C

/*
* File : drv_mmc.c
* This file is part of gkipc BSP for RT-Thread distribution.
*
* Copyright (c) 2017 chengdu goke Microelectronics Co., Ltd.
* All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Visit http://www.goke.com to get contact with goke.
*
* Change Logs:
* Date Author Notes
*/
#include "platform.h"
#include <rtdef.h>
#include <rtdevice.h>
#include <drivers/mmcsd_core.h>
#include <dfs_fs.h>
#include "gd_sdio.h"
#include "drv_mmc.h"
//#define GK_MMC_DEBUG
#if defined(GK_MMC_DEBUG) && defined(RT_DEBUG)
#define PRINT_MMC_DBG(fmt, args...) \
do \
{ \
rt_kprintf("FH_MMC_DEBUG: tick-%d, ", rt_tick_get()); \
rt_kprintf(fmt, ##args); \
} while (0)
#else
#define PRINT_MMC_DBG(fmt, args...) \
do \
{ \
} while (0)
#endif
#define RT_SDIO_MAX_BLOCK_LEN 512 /*block size*/
/*GLOBAL SD DEVICE PONITER*/
static gk_mmc_driver_s sd_driver;
fs_sdio_notify_func_t notifyFunc = NULL;
static rt_err_t rt_sdcard_init(rt_device_t dev)
{
gk_mmc_driver_s *mmc_drv = (gk_mmc_driver_s *)dev->user_data;
rt_uint32_t index = mmc_drv->handle.index;
rt_uint32_t retVal = RT_EOK;
return RT_EOK;
}
static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
{
gk_mmc_driver_s *mmc_drv = (gk_mmc_driver_s *)dev->user_data;
rt_uint32_t index = mmc_drv->handle.index;
rt_uint32_t retVal = RT_EOK;
if (mmc_drv->handle.inUse == 0)
{
mmc_drv->openParams.isUseDmaWay = 0;
retVal = GD_SDIO_Open((GD_SDIO_OpenParamsT *)&mmc_drv->openParams,(sdioHandleT *)&mmc_drv->handle,index);
if (retVal != RT_EOK) {
rt_kprintf("[%s:%d]GD_SDIO_Open failed!\n",__func__,__LINE__);
return-RT_ENOMEM;
}
}
else
{
PRINT_MMC_DBG("----ALREADY_OPEN SDIO_%d----\n",index);
}
return RT_EOK;
}
static rt_err_t rt_sdcard_close(rt_device_t dev)
{
gk_mmc_driver_s *mmc_drv = (gk_mmc_driver_s *)dev->user_data;
rt_uint32_t index = mmc_drv->handle.index;
rt_uint32_t retVal = RT_EOK;
retVal = GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
if (retVal != RT_EOK)
{
rt_kprintf("[%s-%s:%d] failed!,retVal = %d\n",__FILE__,__func__,__LINE__,retVal);
return-RT_ENOMEM;
}
rt_device_unregister(mmc_drv->deviceP[index]);
if (mmc_drv->deviceP[index] != NULL){
rt_free(mmc_drv->deviceP[index]);
mmc_drv->deviceP[index] = NULL;
}
if (mmc_drv->partP[index] != NULL)
{
rt_free(mmc_drv->partP[index]);
mmc_drv->partP[index] = NULL;
}
return RT_EOK;
}
static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
gk_mmc_driver_s *mmc_drv = (gk_mmc_driver_s *)dev->user_data;
rt_uint32_t index = mmc_drv->handle.index;
struct dfs_partition *part = (struct dfs_partition *)mmc_drv->partP[index];
rt_uint32_t retVal = RT_EOK;
rt_sem_take(part->lock, RT_WAITING_FOREVER);
retVal = GD_SDIO_ReadSector((sdioHandleT *)&mmc_drv->handle, pos, buffer, size);
if (retVal != RT_EOK)
{
rt_kprintf("[%s-%s:%d]error!,retVal = %d\n",__FILE__,__func__,__LINE__,retVal);
rt_sem_release(part->lock);
return -RT_ENOMEM;
}
rt_sem_release(part->lock);
return size;
}
static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
gk_mmc_driver_s *mmc_drv = (gk_mmc_driver_s *)dev->user_data;
rt_uint32_t index = mmc_drv->handle.index;
struct dfs_partition *part = (struct dfs_partition *)mmc_drv->partP[index];
rt_uint32_t retVal = RT_EOK;
rt_sem_take(part->lock, RT_WAITING_FOREVER);
retVal = GD_SDIO_WriteSector((sdioHandleT *)&mmc_drv->handle,pos,(void*)buffer,size);
if (retVal != RT_EOK)
{
rt_kprintf("[%s-%s:%d]GD_SDIO_WriteSector failed!\n",__FILE__,__func__,__LINE__);
rt_sem_release(part->lock);
return -RT_ENOMEM;
}
rt_sem_release(part->lock);
return size;
}
static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
{
gk_mmc_driver_s *mmc_drv = (gk_mmc_driver_s *)dev->user_data;
rt_uint32_t index = mmc_drv->handle.index;
struct dfs_partition *part = (struct dfs_partition *)mmc_drv->partP[index];
rt_uint32_t retVal = RT_EOK;
switch(cmd)
{
case RT_DEVICE_CTRL_BLK_GETGEOME:
{
struct rt_device_blk_geometry *geometry;
GD_SDIO_VolumeInfoT sdInfo;
rt_memset(&sdInfo,0,sizeof(sdInfo));
geometry = (struct rt_device_blk_geometry *)args;
retVal = GD_SDIO_GetCardInfo((sdioHandleT *)&mmc_drv->handle,&sdInfo,index);
if (retVal != RT_EOK)
{
rt_kprintf("[%s:%d]GD_SDIO_GetCardInfo failed!\n",__func__,__LINE__);
return-RT_ENOMEM;
}
geometry->block_size = sdInfo.sectorSize;
geometry->sector_count = sdInfo.sectorCount;
geometry->bytes_per_sector = sdInfo.sectorSize;
PRINT_MMC_DBG("[%s:%d]sd card block_size:%d,sector_count:%d!\n",__func__,__LINE__,
geometry->block_size,geometry->sector_count);
break;
}
case RT_DEVICE_CTRL_BLK_ERASE:
{
unsigned int eraseAdress = 0x00;
unsigned short blkcnt = *(unsigned short *)args;
retVal = GD_SDIO_EraseSector((sdioHandleT *)&mmc_drv->handle,eraseAdress,blkcnt);
if (retVal != RT_EOK)
{
rt_kprintf("[%s-%s:%d]GD_SDIO_EraseSector failed!\n",__FILE__,__func__,__LINE__);
return-RT_ENOMEM;
}
break;
}
default:break;
}
return RT_EOK;
}
int rt_hw_mmc_init(gk_mmc_driver_s *pMmcParams)
{
gk_mmc_driver_s *mmc_drv = &sd_driver;
rt_uint32_t index = pMmcParams->handle.index;
rt_uint32_t retVal = RT_EOK;
rt_uint8_t *sector = NULL;
rt_uint8_t sname[8] = {0};
rt_uint8_t sdDeviceName[4] = {0};
if (pMmcParams == NULL)
{
rt_kprintf("[%s:%d] sdio init params is error!\n",__func__,__LINE__);
return -RT_ENOMEM;
}
mmc_drv->openParams.isUseDmaWay = pMmcParams->openParams.isUseDmaWay;
mmc_drv->openParams.notifyFunc = pMmcParams->openParams.notifyFunc;
mmc_drv->openParams.notifyFuncOptPtr = pMmcParams->openParams.notifyFuncOptPtr;
retVal = GD_SDIO_Open((GD_SDIO_OpenParamsT *)&mmc_drv->openParams,(sdioHandleT *)&mmc_drv->handle,index);
if (retVal != RT_EOK) {
rt_kprintf("[%s:%d]GD_SDIO_Open failed!\n",__func__,__LINE__);
return -RT_ENOMEM;
}
/* get the first sector to read partition table */
sector = (rt_uint8_t*) rt_malloc (RT_SDIO_MAX_BLOCK_LEN);
if (sector == RT_NULL)
{
rt_kprintf("allocate partition sector buffer failed\n");
GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
return -RT_ENOMEM;
}
/*alloc device buffer*/
mmc_drv->deviceP[index] = (struct rt_device*)rt_malloc(sizeof(struct rt_device));
if(mmc_drv->deviceP[index] == RT_NULL)
{
rt_kprintf("[%s:%d]allocate device failed\n",__func__,__LINE__);
GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
return -RT_ENOMEM;
}
mmc_drv->partP[index] = (struct dfs_partition*)rt_malloc(sizeof(struct dfs_partition));
if(mmc_drv->partP[index] == RT_NULL)
{
rt_kprintf("[%s:%d]allocate partP failed\n",__func__,__LINE__);
GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
return -RT_ENOMEM;
}
retVal = GD_SDIO_ReadSector((sdioHandleT *)&mmc_drv->handle, 0, sector, 1);
if (retVal != RT_EOK)
{
rt_kprintf("[%s-%s:%d]GD_SDIO_ReadSector failed!\n",__FILE__,__func__,__LINE__);
GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
goto err;
}
/* get the first partition */
retVal = dfs_filesystem_get_partition(mmc_drv->partP[index], sector, 0);
if (retVal != RT_EOK)
{
rt_kprintf("[%s-%s:%d] failed!,retVal = %d\n",__FILE__,__func__,__LINE__,retVal);
GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
goto err;
}
rt_snprintf(sname, 8, "sem_sd%d", index);
mmc_drv->partP[index]->lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
/* sdcard hardware init */
rt_memset(mmc_drv->deviceP[index],0,sizeof(struct rt_device));
mmc_drv->deviceP[index]->type = RT_Device_Class_Block;
mmc_drv->deviceP[index]->init = rt_sdcard_init;
mmc_drv->deviceP[index]->open = rt_sdcard_open;
mmc_drv->deviceP[index]->close = rt_sdcard_close;
mmc_drv->deviceP[index]->read = rt_sdcard_read;
mmc_drv->deviceP[index]->write = rt_sdcard_write;
mmc_drv->deviceP[index]->control = rt_sdcard_control;
mmc_drv->deviceP[index]->user_data = (void *)mmc_drv;
rt_snprintf(sdDeviceName, 4, "sd%d",index);
retVal = rt_device_register(mmc_drv->deviceP[index], sdDeviceName,
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
if (retVal != RT_EOK)
{
rt_kprintf("[%s:%d]rt_device_register name :%s failed!\n",__func__,__LINE__,sdDeviceName);
GD_SDIO_Close((sdioHandleT *)&mmc_drv->handle,index);
goto err;
}
/* release sector buffer */
if (sector != NULL){
rt_free(sector);
sector = NULL;
}
return RT_EOK;
err:
if (mmc_drv->deviceP[index] != NULL){
rt_free(mmc_drv->deviceP[index]);
mmc_drv->deviceP[index] = NULL;
}
if (mmc_drv->partP[index] != NULL)
{
rt_free(mmc_drv->partP[index]);
mmc_drv->partP[index] = NULL;
}
if (sector != NULL){
rt_free(sector);
sector = NULL;
}
return -RT_ETIMEOUT;
}