mirror of
https://github.com/openharmony/drivers_framework.git
synced 2026-07-20 00:33:44 -04:00
new mmc code update
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include "platform_common.h"
|
||||
#include "platform_device.h"
|
||||
#include "platform_manager.h"
|
||||
#include "platform_queue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PLATFORM_H */
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_COMMON_H
|
||||
#define PLATFORM_COMMON_H
|
||||
|
||||
#include "hdf_base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
enum PlatformModuleType {
|
||||
PLATFORM_MODULE_GPIO,
|
||||
PLATFORM_MODULE_I2C,
|
||||
PLATFORM_MODULE_SPI,
|
||||
PLATFORM_MODULE_PIN,
|
||||
PLATFORM_MODULE_CLOCK,
|
||||
PLATFORM_MODULE_REGULATOR,
|
||||
PLATFORM_MODULE_MIPI_DSI,
|
||||
PLATFORM_MODULE_UART,
|
||||
PLATFORM_MODULE_SDIO,
|
||||
PLATFORM_MODULE_MDIO,
|
||||
PLATFORM_MODULE_APB,
|
||||
PLATFORM_MODULE_PCIE,
|
||||
PLATFORM_MODULE_PCM,
|
||||
PLATFORM_MODULE_I2S,
|
||||
PLATFORM_MODULE_PWM,
|
||||
PLATFORM_MODULE_DMA,
|
||||
PLATFORM_MODULE_ADC,
|
||||
PLATFORM_MODULE_RTC,
|
||||
PLATFORM_MODULE_WDT,
|
||||
PLATFORM_MODULE_I3C,
|
||||
PLATFORM_MODULE_CAN,
|
||||
PLATFORM_MODULE_HDMI,
|
||||
PLATFORM_MODULE_MMC,
|
||||
PLATFORM_MODULE_MTD,
|
||||
PLATFORM_MODULE_DEFAULT,
|
||||
PLATFORM_MODULE_MAX,
|
||||
};
|
||||
|
||||
struct PlatformModuleInfo {
|
||||
enum PlatformModuleType moduleType;
|
||||
const char *moduleName;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct PlatformModuleInfo *PlatformModuleInfoGet(enum PlatformModuleType moduleType);
|
||||
int32_t PlatformModuleInfoCount(void);
|
||||
|
||||
enum PlatformErrno {
|
||||
#define HDF_PLT_ERR_START HDF_BSP_ERR_START /**< Error number start of platform. */
|
||||
#define HDF_PLT_ERR_NUM(v) (HDF_PLT_ERR_START + (v))
|
||||
HDF_PLT_ERR_OS_API = HDF_ERR_BSP_PLT_API_ERR,
|
||||
HDF_PLT_ERR_OPEN_DEV = HDF_PAL_ERR_DEV_CREATE, /**< Failed to open a device. */
|
||||
HDF_PLT_ERR_INNER = HDF_PAL_ERR_INNER, /**< Internal error of platform framework. */
|
||||
|
||||
HDF_PLT_ERR_NO_DEV = HDF_PLT_ERR_NUM(-5), /**< There is no device present. */
|
||||
HDF_PLT_ERR_DEV_TYPE = HDF_PLT_ERR_NUM(-6), /**< invalid device type */
|
||||
HDF_PLT_ERR_DEV_GET = HDF_PLT_ERR_NUM(-7), /**< err on device get */
|
||||
HDF_PLT_ERR_DEV_ADD = HDF_PLT_ERR_NUM(-8), /**< err on device add */
|
||||
HDF_PLT_ERR_DEV_FULL = HDF_PLT_ERR_NUM(-9), /**< id number conflict */
|
||||
HDF_PLT_ERR_ID_REPEAT = HDF_PLT_ERR_NUM(-10), /**< id number conflict */
|
||||
#define HDF_MMC_ERR_START (HDF_PLT_ERR_START - 50) /**< Error number start for mmc. */
|
||||
#define HDF_MMC_ERR_NUM(v) (HDF_MMC_ERR_START + (v))
|
||||
HDF_MMC_ERR_SWITCH_FAIL = HDF_MMC_ERR_NUM(-1),
|
||||
HDF_MMC_ERR_OTHER_CMD_IS_RUNNING = HDF_MMC_ERR_NUM(-2),
|
||||
HDF_MMC_ERR_ILLEGAL_SEQ = HDF_MMC_ERR_NUM(-3),
|
||||
};
|
||||
|
||||
void PlatformGlobalLock(void);
|
||||
void PlatformGlobalUnlock(void);
|
||||
|
||||
/* Os adapt */
|
||||
bool PlatInIrqContext(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PLATFORM_COMMON_H */
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEVICE_H
|
||||
#define PLATFORM_DEVICE_H
|
||||
|
||||
#include "hdf_base.h"
|
||||
#include "hdf_dlist.h"
|
||||
#include "hdf_sref.h"
|
||||
#include "osal_sem.h"
|
||||
#include "osal_spinlock.h"
|
||||
#include "platform_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct PlatformManager;
|
||||
|
||||
struct PlatformDevice {
|
||||
struct HdfDeviceObject *hdfDev; /* releated to an hdf device object */
|
||||
struct PlatformManager *manager; /* the platform manager it belongs to */
|
||||
uint32_t magic; /* magic number of the device instance */
|
||||
const char *name; /* name of the device instance */
|
||||
struct HdfSRef ref; /* used for reference count */
|
||||
struct DListHead node; /* linked to the list of a manager */
|
||||
struct DListHead notifiers; /* list of notifier nodes */
|
||||
bool ready; /* indicates whether initialized */
|
||||
OsalSpinlock spin; /* for member protection */
|
||||
struct OsalSem released; /* for death notification */
|
||||
};
|
||||
|
||||
enum PlatformEventType {
|
||||
PLAT_EVENT_DEAD = 0, /* a platform device going to die */
|
||||
};
|
||||
|
||||
struct PlatformNotifier {
|
||||
void *data; /* private data u can take */
|
||||
/**
|
||||
* @brief the event handle funciton of this notifier.
|
||||
*
|
||||
* make sure it can be called in irq context.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
* @param event Indicates the event type of this handling process.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void (*handle)(struct PlatformDevice *device, enum PlatformEventType event, void *data);
|
||||
};
|
||||
|
||||
struct PlatformNotifierNode {
|
||||
struct DListHead node; /* link to notfifier node list */
|
||||
struct PlatformNotifier *notifier; /* pointer to the notifier instance */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize a platform device.
|
||||
*
|
||||
* Initialize members of a platform device.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformDeviceInit(struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Uninitialize a platform device.
|
||||
*
|
||||
* Uninitialize members of a platform device.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformDeviceUninit(struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Increase reference count for a platform device.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @return Returns the pointer to the paltform device on success; returns NULL otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
struct PlatformDevice *PlatformDeviceGet(struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Decrease reference count for a platform device.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformDevicePut(struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Register a notifier to a platform device.
|
||||
*
|
||||
* Subscribe the events of a platform device by registering a notfier.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
* @param notifier Indicates the pointer to the platform notifier.
|
||||
*
|
||||
* @return Returns 0 if the notifier registered successfully; returns a negative value otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
int32_t PlatformDeviceRegNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier);
|
||||
|
||||
/**
|
||||
* @brief Unregister a notifier to a platform device.
|
||||
*
|
||||
* Unsubscribe the events of a platform device by unregistering the notfier.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
* @param notifier Indicates the pointer to the platform notifier.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformDeviceUnregNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier);
|
||||
|
||||
/**
|
||||
* @brief Unregister all notifiers to a platform device.
|
||||
*
|
||||
* Unsubscribe all the events of a platform device by clearing the notfiers.
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformDeviceClearNotifier(struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Add a platform device by module type.
|
||||
*
|
||||
* do not call in irq context cause can sleep
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @return Returns 0 if add successfully; returns a negative value otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
int32_t PlatformDeviceAdd(struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Remove a platform device by module type.
|
||||
*
|
||||
* do not call in irq context cause can sleep
|
||||
*
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformDeviceDel(struct PlatformDevice *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PLATFORM_DEVICE_H */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_ERRNO_H
|
||||
#define PLATFORM_ERRNO_H
|
||||
|
||||
#include "hdf_base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
enum PlatformErrno {
|
||||
#define HDF_PLT_ERR_START HDF_BSP_ERR_START /**< Error number start of platform. */
|
||||
#define HDF_PLT_ERR_NUM(v) (HDF_PLT_ERR_START + (v))
|
||||
HDF_PLT_ERR_OS_API = HDF_ERR_BSP_PLT_API_ERR,
|
||||
HDF_PLT_ERR_OPEN_DEV = HDF_PAL_ERR_DEV_CREATE, /**< Failed to open a device. */
|
||||
HDF_PLT_ERR_INNER = HDF_PAL_ERR_INNER, /**< Internal error of platform framework. */
|
||||
|
||||
HDF_PLT_ERR_NO_DEV = HDF_PLT_ERR_NUM(-5), /**< There is no device present. */
|
||||
HDF_PLT_ERR_DEV_TYPE = HDF_PLT_ERR_NUM(-6), /**< invalid device type */
|
||||
HDF_PLT_ERR_DEV_GET = HDF_PLT_ERR_NUM(-7), /**< err on device get */
|
||||
HDF_PLT_ERR_DEV_ADD = HDF_PLT_ERR_NUM(-8), /**< err on device add */
|
||||
HDF_PLT_ERR_DEV_FULL = HDF_PLT_ERR_NUM(-9), /**< id number conflict */
|
||||
HDF_PLT_ERR_ID_REPEAT = HDF_PLT_ERR_NUM(-10), /**< id number conflict */
|
||||
#define HDF_MMC_ERR_START (HDF_PLT_ERR_START - 50) /**< Error number start for mmc. */
|
||||
#define HDF_MMC_ERR_NUM(v) (HDF_MMC_ERR_START + (v))
|
||||
HDF_MMC_ERR_SWITCH_FAIL = HDF_MMC_ERR_NUM(-1),
|
||||
HDF_MMC_ERR_OTHER_CMD_IS_RUNNING = HDF_MMC_ERR_NUM(-2),
|
||||
HDF_MMC_ERR_ILLEGAL_SEQ = HDF_MMC_ERR_NUM(-3),
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PLATFORM_ERRNO_H */
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_MANAGER_H
|
||||
#define PLATFORM_MANAGER_H
|
||||
|
||||
#include "hdf_base.h"
|
||||
#include "hdf_dlist.h"
|
||||
#include "osal_spinlock.h"
|
||||
#include "platform_device.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct PlatformManager {
|
||||
const char *name; /* name of the manager */
|
||||
struct DListHead devices; /* list to keep all it's device instances */
|
||||
OsalSpinlock spin; /* for member protection */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a platform manager.
|
||||
*
|
||||
* Create a platform manager with member initialized.
|
||||
*
|
||||
* @param name Indicates the name of the manager.
|
||||
*
|
||||
* @return Returns the pointer to the paltform manager on success; returns NULL otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
struct PlatformManager *PlatformManagerCreate(const char *name);
|
||||
|
||||
/**
|
||||
* @brief Get a platform manager by module type.
|
||||
*
|
||||
* @param module Indicates the module type of the manager.
|
||||
*
|
||||
* @return Returns the pointer to the paltform manager on success; returns NULL otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
struct PlatformManager *PlatformManagerGet(enum PlatformModuleType module);
|
||||
|
||||
/**
|
||||
* @brief Add a platform device to a platform manager.
|
||||
*
|
||||
* Add a platform device to make it managed by platform core.
|
||||
*
|
||||
* @param manager Indicates the pointer to the platform manager.
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @return Returns 0 if the devcie added successfully; returns a negative value otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
int32_t PlatformManagerAddDevice(struct PlatformManager *manager, struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Remove a platform device from a platform manager.
|
||||
*
|
||||
* Remove a platform device to make it away from management of platform core.
|
||||
*
|
||||
* @param manager Indicates the pointer to the platform manager.
|
||||
* @param device Indicates the pointer to the platform device.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
void PlatformManagerDelDevice(struct PlatformManager *manager, struct PlatformDevice *device);
|
||||
|
||||
/**
|
||||
* @brief Find a particular device from the manager.
|
||||
*
|
||||
* Locate a particular device from the manager by a matching function, witch will be called for
|
||||
* each device, untill it returns true indicatting a device is "found".
|
||||
* The device found will be returned with reference count increased.
|
||||
*
|
||||
* @param manager Indicates the pointer to the platform manager.
|
||||
* @param data Indicates the pointer to the data passed to match function.
|
||||
* @param match Indicates the pointer to the match function.
|
||||
*
|
||||
* @return Returns the pointer to the paltform device on success; returns NULL otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
struct PlatformDevice *PlatformManagerFindDevice(struct PlatformManager *manager, void *data,
|
||||
bool (*match)(struct PlatformDevice *pdevice, void *data));
|
||||
|
||||
/**
|
||||
* @brief Get a platform device from the manager by magic.
|
||||
*
|
||||
* The device got will be returned with reference count increased.
|
||||
*
|
||||
* @param manager Indicates the pointer to the platform manager.
|
||||
* @param magic Indicates the magic number of the target platform device.
|
||||
*
|
||||
* @return Returns the pointer to the paltform device on success; returns NULL otherwise.
|
||||
* @since 1.0
|
||||
*/
|
||||
struct PlatformDevice *PlatformManagerGetDeviceByMagic(struct PlatformManager *manager, uint32_t magic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PLATFORM_MANAGER_H */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_QUEUE_H
|
||||
#define PLATFORM_QUEUE_H
|
||||
|
||||
#include "hdf_dlist.h"
|
||||
#include "osal_thread.h"
|
||||
#include "osal_sem.h"
|
||||
#include "osal_spinlock.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct PlatformMsg;
|
||||
struct PlatformQueue;
|
||||
|
||||
struct PlatformMsg {
|
||||
struct DListHead node;
|
||||
struct OsalSem sem;
|
||||
int32_t code;
|
||||
int32_t error;
|
||||
bool block; /* whether need to block thread */
|
||||
void *data;
|
||||
};
|
||||
|
||||
int32_t PlatformMsgWait(struct PlatformMsg *msg);
|
||||
typedef int32_t (*PlatformMsgHandle)(struct PlatformQueue *queue, struct PlatformMsg *msg);
|
||||
|
||||
struct PlatformQueue {
|
||||
const char *name;
|
||||
OsalSpinlock spin;
|
||||
struct OsalSem sem;
|
||||
struct DListHead msgs;
|
||||
struct OsalThread thread; /* the worker thread of this queue */
|
||||
PlatformMsgHandle handle;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void PlatformQueueAddMsg(struct PlatformQueue *queue, struct PlatformMsg *msg);
|
||||
struct PlatformQueue *PlatformQueueCreate(PlatformMsgHandle handle, const char *name, void *data);
|
||||
void PlatformQueueDestroy(struct PlatformQueue *queue);
|
||||
int32_t PlatformQueueStart(struct PlatformQueue *queue);
|
||||
int32_t PlatformQueueSuspend(struct PlatformQueue *queue);
|
||||
int32_t PlatformQueueResume(struct PlatformQueue *queue);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PLATFORM_QUEUE_H */
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_BLOCK_H
|
||||
#define MMC_BLOCK_H
|
||||
|
||||
#include "mmc_corex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int32_t MmcBlockAdd(struct MmcDevice *mmc);
|
||||
void MmcBlockDel(struct MmcDevice *mmc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MMC_BLOCK_H */
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_CAPS_H
|
||||
#define MMC_CAPS_H
|
||||
|
||||
#include "hdf_base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
enum MmcVolt { VOLT_3V3 = 0, VOLT_1V8, VOLT_1V2 };
|
||||
|
||||
enum MmcPowerMode { MMC_POWER_MODE_POWER_OFF = 0, MMC_POWER_MODE_POWER_UP, MMC_POWER_MODE_POWER_ON };
|
||||
|
||||
enum MmcBusWidth { BUS_WIDTH1 = 0, BUS_WIDTH4 = 2, BUS_WIDTH8 = 3 };
|
||||
|
||||
enum MmcBusTiming {
|
||||
BUS_TIMING_MMC_DS = 0,
|
||||
BUS_TIMING_MMC_HS,
|
||||
BUS_TIMING_SD_HS,
|
||||
BUS_TIMING_UHS_SDR12,
|
||||
BUS_TIMING_UHS_SDR25,
|
||||
BUS_TIMING_UHS_SDR50,
|
||||
BUS_TIMING_UHS_SDR104,
|
||||
BUS_TIMING_UHS_DDR50,
|
||||
BUS_TIMING_UHS_DDR52,
|
||||
BUS_TIMING_MMC_HS200, /* for emmc */
|
||||
BUS_TIMING_MMC_HS400, /* for emmc */
|
||||
};
|
||||
|
||||
union MmcCaps {
|
||||
uint32_t capsData;
|
||||
struct CapsBitsData {
|
||||
uint32_t cap4Bit : 1; /* bit:0 support 4 bit transfer */
|
||||
uint32_t cap8Bit : 1; /* bit:1 support 8 bit transfer */
|
||||
uint32_t highSpeed : 1; /* bit:2 support high-speed timing */
|
||||
uint32_t sdioIrq : 1; /* bit:3 signal pending SDIO irqs */
|
||||
uint32_t onlySpi : 1; /* bit:4 only support spi protocols */
|
||||
uint32_t needPoll : 1; /* bit:5 need polling for card-detection */
|
||||
uint32_t nonremovable : 1; /* bit:6 Nonremoveable eg. eMMC */
|
||||
uint32_t waitWhileBusy : 1; /* bit:7 waits while card is busy */
|
||||
uint32_t erase : 1; /* bit:8 allow erase */
|
||||
uint32_t ddr1v8 : 1; /* bit:9 support ddr mode at 1.8V */
|
||||
uint32_t ddr1v2 : 1; /* bit:10 support ddr mode at 1.2V */
|
||||
uint32_t powerOffCard : 1; /* bit:11 support power off after boot */
|
||||
uint32_t busWidthTest : 1; /* bit:12 CMD14/CMD19 bus width ok */
|
||||
uint32_t uhsSdr12 : 1; /* bit:13 support UHS SDR12 mode */
|
||||
uint32_t uhsSdr25 : 1; /* bit:14 support UHS SDR25 mode */
|
||||
uint32_t uhsSdr50 : 1; /* bit:15 support UHS SDR50 mode */
|
||||
uint32_t uhsSdr104 : 1; /* bit:16 support UHS SDR104 mode */
|
||||
uint32_t uhsDdr50 : 1; /* bit:17 support UHS DDR50 mode */
|
||||
uint32_t xpc330 : 1; /* bit:18 support >150mA current at 3.3V */
|
||||
uint32_t xpc300 : 1; /* bit:19 support >150mA current at 3.0V */
|
||||
uint32_t xpc180 : 1; /* bit:20 support >150mA current at 1.8V */
|
||||
uint32_t driverTypeA : 1; /* bit:21 support driver type A */
|
||||
uint32_t driverTypeC : 1; /* bit:22 support driver type C */
|
||||
uint32_t driverTypeD : 1; /* bit:23 support driver type D */
|
||||
uint32_t maxCurrentLimit200 : 1; /* bit:24 max current limit 200mA */
|
||||
uint32_t maxCurrentLimit400 : 1; /* bit:25 max current limit 400mA */
|
||||
uint32_t maxCurrentLimit600 : 1; /* bit:26 max current limit 600mA */
|
||||
uint32_t maxCurrentLimit800 : 1; /* bit:27 max current limit 800mA */
|
||||
uint32_t cmd23 : 1; /* bit:28 support CMD23 */
|
||||
uint32_t hardwareReset : 1; /* bit:29 support hardware reset */
|
||||
uint32_t sdSupportProtocol3 : 1; /* bit:30 SD support Protocol 3.0 */
|
||||
uint32_t cmdStop : 1; /* bit:31 support cmd stop */
|
||||
} bits;
|
||||
};
|
||||
|
||||
union MmcCaps2 {
|
||||
uint32_t caps2Data;
|
||||
struct Caps2BitsData {
|
||||
uint32_t bootPartNoAcc : 1; /* bit:0 boot partition no access */
|
||||
uint32_t cacheCtrl : 1; /* bit:1 allow cache control */
|
||||
uint32_t poweroffNotify : 1; /* bit:2 support notify power off */
|
||||
uint32_t noMultiRead : 1; /* bit:3 not support multiblock read */
|
||||
uint32_t noSleepCmd : 1; /* bit:4 not support sleep command */
|
||||
uint32_t hs200Sdr1v8 : 1; /* bit:5 support hs200 sdr 1.8V */
|
||||
uint32_t hs200Sdr1v2 : 1; /* bit:6 support sdr hs200 1.2V */
|
||||
uint32_t brokenVoltage : 1; /* bit:7 use broken voltage */
|
||||
uint32_t detectNoErr : 1; /* bit:8 I/O err check card removal */
|
||||
uint32_t hcEraseSize : 1; /* bit:9 High-capacity erase size */
|
||||
uint32_t hs400Support1v8 : 1; /* bit:10 support hs400 1.8V */
|
||||
uint32_t hs400Support1v2 : 1; /* bit:11 support hs400 1.2V */
|
||||
uint32_t hs400EnhancedStrobe : 1; /* bit:12 support hs400 enhanced strobe */
|
||||
uint32_t reserved : 18; /* bits:13~31, reserved */
|
||||
} bits;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _MMC_CAPS_H */
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_CORE_H
|
||||
#define MMC_CORE_H
|
||||
|
||||
#include "hdf_base.h"
|
||||
#include "hdf_device_desc.h"
|
||||
#include "hdf_log.h"
|
||||
#include "mmc_caps.h"
|
||||
#include "mmc_protocol.h"
|
||||
#include "osal_mem.h"
|
||||
#include "osal_mutex.h"
|
||||
#include "osal_time.h"
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define MMC_CNTLR_NR_MAX 3
|
||||
#define MMC_DEV_NR_MAX 3
|
||||
#define MMC_SEC_SIZE 512
|
||||
|
||||
#define MMC_MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define MMC_MAX(x, y) (((x) < (y)) ? (y) : (x))
|
||||
|
||||
struct MmcCntlr;
|
||||
struct MmcCntlrOps;
|
||||
struct MmcDevice;
|
||||
struct MmcMsg;
|
||||
struct MmcData;
|
||||
struct MmcCmd;
|
||||
enum MmcMsgCode;
|
||||
enum MmcCmdCode;
|
||||
union MmcDevState;
|
||||
|
||||
enum MmcDevType {
|
||||
MMC_DEV_EMMC = 0,
|
||||
MMC_DEV_SD,
|
||||
MMC_DEV_SDIO,
|
||||
MMC_DEV_COMBO,
|
||||
MMC_DEV_INVALID
|
||||
};
|
||||
|
||||
struct MmcCntlr {
|
||||
struct IDeviceIoService service;
|
||||
struct HdfDeviceObject *hdfDevObj;
|
||||
struct PlatformDevice device;
|
||||
struct OsalMutex mutex;
|
||||
struct OsalSem released;
|
||||
uint32_t devType;
|
||||
struct MmcDevice *curDev;
|
||||
struct MmcCntlrOps *ops;
|
||||
struct PlatformQueue *msgQueue;
|
||||
uint16_t index;
|
||||
uint16_t voltDef;
|
||||
uint32_t vddBit;
|
||||
uint32_t freqMin;
|
||||
uint32_t freqMax;
|
||||
uint32_t freqDef;
|
||||
union MmcOcr ocrDef;
|
||||
union MmcCaps caps;
|
||||
union MmcCaps2 caps2;
|
||||
uint32_t maxBlkNum;
|
||||
uint32_t maxBlkSize;
|
||||
uint32_t maxReqSize;
|
||||
bool devPluged;
|
||||
bool detecting;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct MmcCntlrOps {
|
||||
int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
|
||||
int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock);
|
||||
int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode);
|
||||
int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width);
|
||||
int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
|
||||
int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable);
|
||||
int32_t (*hardwareReset)(struct MmcCntlr *cntlr);
|
||||
int32_t (*systemInit)(struct MmcCntlr *cntlr);
|
||||
int32_t (*setEnhanceSrobe)(struct MmcCntlr *cntlr, bool enable);
|
||||
int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt);
|
||||
bool (*devReadOnly)(struct MmcCntlr *cntlr);
|
||||
bool (*devPluged)(struct MmcCntlr *cntlr);
|
||||
bool (*devBusy)(struct MmcCntlr *cntlr);
|
||||
int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode);
|
||||
int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr);
|
||||
};
|
||||
|
||||
/* controller management */
|
||||
int32_t MmcCntlrAdd(struct MmcCntlr *cntlr);
|
||||
void MmcCntlrRemove(struct MmcCntlr *cntlr);
|
||||
struct MmcDevice *MmcCntlrGetDevice(struct MmcCntlr *cntlr);
|
||||
|
||||
static inline struct MmcCntlr *MmcCntlrGet(struct MmcCntlr *cntlr)
|
||||
{
|
||||
if (cntlr != NULL && PlatformDeviceGet(&cntlr->device) != NULL) {
|
||||
return cntlr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct MmcCntlr *MmcCntlrGetByNr(uint16_t number)
|
||||
{
|
||||
struct PlatformDevice *device = PlatformManagerGetDeviceByMagic(PlatformManagerGet(PLATFORM_MODULE_MMC), number);
|
||||
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return CONTAINER_OF(device, struct MmcCntlr, device);
|
||||
}
|
||||
|
||||
static inline void MmcCntlrPut(struct MmcCntlr *cntlr)
|
||||
{
|
||||
if (cntlr != NULL) {
|
||||
PlatformDevicePut(&cntlr->device);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool MmcCntlrDevPresent(struct MmcCntlr *cntlr)
|
||||
{
|
||||
return (cntlr != NULL && cntlr->curDev != NULL);
|
||||
}
|
||||
|
||||
static inline void MmcCntlrLock(struct MmcCntlr *cntlr)
|
||||
{
|
||||
if (cntlr != NULL) {
|
||||
(void)OsalMutexLock(&cntlr->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void MmcCntlrUnlock(struct MmcCntlr *cntlr)
|
||||
{
|
||||
if (cntlr != NULL) {
|
||||
(void)OsalMutexUnlock(&cntlr->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* controller common bussiness */
|
||||
int32_t MmcCntlrDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
|
||||
int32_t MmcCntlrAddMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd, int32_t code, bool block);
|
||||
int32_t MmcCntlrAddRequestMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
|
||||
int32_t MmcCntlrAddDetectMsgToQueue(struct MmcCntlr *cntlr);
|
||||
int32_t MmcCntlrAddPlugMsgToQueue(struct MmcCntlr *cntlr);
|
||||
int32_t MmcCntlrAddSdioRescanMsgToQueue(struct MmcCntlr *cntlr);
|
||||
int32_t MmcCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj);
|
||||
int32_t MmcCntlrCreatSdioIrqThread(struct MmcCntlr *cntlr);
|
||||
void MmcCntlrDestroySdioIrqThread(struct MmcCntlr *cntlr);
|
||||
void MmcCntlrNotifySdioIrqThread(struct MmcCntlr *cntlr);
|
||||
|
||||
/* controller private bussiness */
|
||||
void MmcCntlrSetClock(struct MmcCntlr *cntlr, uint32_t clock);
|
||||
void MmcCntlrSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width);
|
||||
void MmcCntlrSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
|
||||
void MmcCntlrSetEnhanceSrobe(struct MmcCntlr *cntlr, bool enable);
|
||||
int32_t MmcCntlrSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt voltage);
|
||||
bool MmcCntlrDevReadOnly(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrDevBusy(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrDevPluged(struct MmcCntlr *cntlr);
|
||||
int32_t MmcCntlrTune(struct MmcCntlr *cntlr, uint32_t cmdCode);
|
||||
void MmcCntlrSelectWorkVoltage(struct MmcCntlr *cntlr, union MmcOcr *ocr);
|
||||
void MmcCntlrPowerUp(struct MmcCntlr *cntlr);
|
||||
void MmcCntlrPowerOff(struct MmcCntlr *cntlr);
|
||||
int32_t MmcCntlrAllocDev(struct MmcCntlr *cntlr, enum MmcDevType devType);
|
||||
void MmcCntlrFreeDev(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrSupportUhs(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrSupportHighSpeed400EnhancedStrobe(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrSupportHighSpeed400(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrSupportHighSpeed200(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrSdSupportCmd23(struct MmcCntlr *cntlr);
|
||||
bool MmcCntlrEmmcSupportCmd23(struct MmcCntlr *cntlr);
|
||||
|
||||
struct MmcDeviceWorkParam {
|
||||
uint32_t clock;
|
||||
enum MmcBusWidth width;
|
||||
enum MmcBusTiming timing;
|
||||
};
|
||||
|
||||
struct MmcRegister {
|
||||
union MmcOcr ocr;
|
||||
uint32_t rca;
|
||||
uint32_t rawCid[CID_LEN];
|
||||
uint32_t rawCsd[CSD_LEN];
|
||||
struct MmcCid cid;
|
||||
struct MmcCsd csd;
|
||||
};
|
||||
|
||||
union MmcDevState {
|
||||
uint32_t stateData;
|
||||
struct StateBitsData {
|
||||
uint32_t present : 1;
|
||||
uint32_t readonly : 1;
|
||||
uint32_t highSpeed : 1;
|
||||
uint32_t blockAddr : 1;
|
||||
uint32_t ddrMode : 1;
|
||||
uint32_t highSpeedDdr : 1;
|
||||
uint32_t uhs : 1;
|
||||
uint32_t sdxc : 1;
|
||||
uint32_t hs200 : 1;
|
||||
uint32_t sleep : 1;
|
||||
uint32_t removeable : 1;
|
||||
uint32_t blkszForByteMode : 1;
|
||||
uint32_t hs400 : 1;
|
||||
uint32_t hs400es : 1;
|
||||
uint32_t reserverd : 17;
|
||||
} bits;
|
||||
};
|
||||
|
||||
struct MmcDevice {
|
||||
struct PlatformDevice device;
|
||||
struct MmcCntlr *cntlr;
|
||||
struct MmcRegister reg;
|
||||
struct MmcDeviceWorkParam workPara;
|
||||
union MmcDevState state;
|
||||
enum MmcDevType type;
|
||||
size_t secSize; // by bytes
|
||||
size_t capacity; // by sectors
|
||||
size_t eraseSize; // by sectors
|
||||
struct StorageBlock *sb;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/* device management */
|
||||
int32_t MmcDeviceAdd(struct MmcDevice *mmc);
|
||||
void MmcDeviceAddOps(struct MmcDevice *mmc, void *ops);
|
||||
void MmcDeviceRemove(struct MmcDevice *mmc);
|
||||
struct MmcDevice *MmcDeviceGet(struct MmcDevice *mmc);
|
||||
void MmcDevicePut(struct MmcDevice *mmc);
|
||||
|
||||
/* device business */
|
||||
ssize_t MmcDeviceRead(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec);
|
||||
ssize_t MmcDeviceWrite(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec);
|
||||
ssize_t MmcDeviceErase(struct MmcDevice *mmc, size_t startSec, size_t nSec);
|
||||
|
||||
static inline bool MmcDeviceIsPresent(struct MmcDevice *mmc)
|
||||
{
|
||||
return (mmc != NULL && mmc->state.bits.present);
|
||||
}
|
||||
|
||||
struct MmcCmd {
|
||||
uint32_t cmdCode;
|
||||
uint32_t argument;
|
||||
uint32_t resp[MMC_CMD_RESP_SIZE];
|
||||
uint32_t respType;
|
||||
int32_t returnError;
|
||||
struct MmcData *data;
|
||||
};
|
||||
|
||||
#define DATA_WRITE (0x1 << 0)
|
||||
#define DATA_READ (0x1 << 1)
|
||||
#define DATA_STREAM (0x1 << 2)
|
||||
struct MmcData {
|
||||
uint32_t blockSize; /* data block size, byte */
|
||||
uint32_t blockNum;
|
||||
int32_t returnError;
|
||||
uint8_t *dataBuffer;
|
||||
void *scatter;
|
||||
uint32_t scatterLen;
|
||||
uint32_t dataFlags;
|
||||
struct MmcCmd stopCmd; /* stop command */
|
||||
bool sendStopCmd;
|
||||
};
|
||||
|
||||
enum MmcMsgCode {
|
||||
MMC_MSG_REQUEST,
|
||||
MMC_MSG_PLUG,
|
||||
MMC_MSG_UNPLUG,
|
||||
MMC_MSG_SDIO_RESCAN,
|
||||
};
|
||||
|
||||
struct MmcMsg {
|
||||
struct PlatformMsg msg;
|
||||
struct MmcCmd *mmcCmd;
|
||||
};
|
||||
|
||||
struct MmcRwData {
|
||||
uint8_t *buf;
|
||||
bool writeFlag;
|
||||
size_t startSector;
|
||||
size_t sectors;
|
||||
};
|
||||
|
||||
int32_t MmcDoDetect(struct MmcCntlr *cntlr);
|
||||
void MmcDeleteDev(struct MmcCntlr *cntlr);
|
||||
int32_t MmcSendStatus(struct MmcCntlr *cntlr, uint32_t *status);
|
||||
int32_t MmcStopTransmission(struct MmcCntlr *cntlr, bool writeFlag, uint32_t *stopStatus);
|
||||
int32_t MmcSendTuning(struct MmcCntlr *cntlr, uint32_t cmdCode, bool sendStop);
|
||||
int32_t MmcSendErase(struct MmcCntlr *cntlr, uint32_t startSec, uint32_t nSec);
|
||||
void MmcSetupReadWriteBlocksCmd(struct MmcDevice *mmc, struct MmcCmd *cmd, struct MmcRwData *info);
|
||||
int32_t MmcSendReadWriteBlocks(struct MmcCntlr *cntlr, struct MmcRwData *info);
|
||||
int32_t SdioReinit(struct MmcCntlr *cntlr);
|
||||
int32_t SdioReadCccrIoEnable(struct MmcCntlr *cntlr, uint8_t *val);
|
||||
int32_t SdioCccrIntEnable(struct MmcCntlr *cntlr);
|
||||
int32_t SdioCccrIntDisable(struct MmcCntlr *cntlr);
|
||||
int32_t SdioCccrIoEnable(struct MmcCntlr *cntlr);
|
||||
int32_t SdioCccrIoDisable(struct MmcCntlr *cntlr);
|
||||
int32_t SdioReadCccrIntPending(struct MmcCntlr *cntlr, uint8_t *val);
|
||||
int32_t SdioReadCccrIoReady(struct MmcCntlr *cntlr, uint8_t *val);
|
||||
int32_t SdioSetFbrIoBlockSize(struct MmcCntlr *cntlr, uint32_t blkSize);
|
||||
int32_t SdioReadWriteByte(struct MmcCntlr *cntlr, bool writeFlag,
|
||||
uint32_t funcNum, uint32_t addr, uint8_t *data);
|
||||
int32_t SdioReadWriteBlock(struct MmcCntlr *cntlr, struct SdioRwBlockInfo *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MMC_CORE_H */
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_DISPATCH_H
|
||||
#define MMC_DISPATCH_H
|
||||
|
||||
#ifndef __USER__
|
||||
#include "devsvc_manager_clnt.h"
|
||||
#endif
|
||||
|
||||
#ifdef __USER__
|
||||
#include "hdf_io_service_if.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef __USER__
|
||||
int32_t MmcIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MMC_DISPATCH_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_EMMC_H
|
||||
#define MMC_EMMC_H
|
||||
|
||||
#include "emmc_if.h"
|
||||
#include "mmc_corex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct EmmcRegister {
|
||||
struct EmmcExtCsd extCsd;
|
||||
};
|
||||
|
||||
struct EmmcDevice {
|
||||
struct MmcDevice mmc;
|
||||
struct EmmcDeviceOps *emmcOps;
|
||||
struct EmmcRegister emmcReg;
|
||||
};
|
||||
|
||||
struct EmmcDeviceOps {
|
||||
int32_t (*getCid)(struct EmmcDevice *, uint8_t *, uint32_t);
|
||||
};
|
||||
|
||||
int32_t EmmcDeviceGetCid(struct EmmcDevice *dev, uint8_t *cid, uint32_t len);
|
||||
void EmmcDeviceAddOps(struct EmmcDevice *dev, void *ops);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MMC_EMMC_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_SD_H
|
||||
#define MMC_SD_H
|
||||
|
||||
#include "mmc_corex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct SdRegister {
|
||||
uint32_t rawScr[SCR_LEN];
|
||||
uint16_t rawDsr;
|
||||
struct SdScr scr;
|
||||
struct SdSsr ssr;
|
||||
struct SdSwitchCaps swCaps;
|
||||
};
|
||||
|
||||
struct SdDevice {
|
||||
struct MmcDevice mmc;
|
||||
enum SdBusSpeedMode busSpeedMode;
|
||||
struct SdRegister reg;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MMC_SD_H */
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef MMC_SDIO_H
|
||||
#define MMC_SDIO_H
|
||||
|
||||
#include "mmc_sd.h"
|
||||
#include "osal_thread.h"
|
||||
#include "sdio_if.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct SdioFunction {
|
||||
struct SdioDevice *dev;
|
||||
uint32_t maxBlkSize;
|
||||
uint32_t curBlkSize;
|
||||
uint32_t funcNum;
|
||||
uint8_t funcClass;
|
||||
uint16_t vendorId;
|
||||
uint16_t deviceId;
|
||||
uint32_t timeOut;
|
||||
SdioIrqHandler *irqHandler;
|
||||
};
|
||||
|
||||
struct SdioRegister {
|
||||
struct SdioCccr cccr;
|
||||
struct SdioCis cis;
|
||||
};
|
||||
|
||||
struct SdioDevice {
|
||||
struct SdDevice sd;
|
||||
struct SdioDeviceOps *sdioOps;
|
||||
struct SdioRegister sdioReg;
|
||||
uint32_t functions;
|
||||
struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER];
|
||||
struct SdioFunction *curFunction;
|
||||
struct OsalThread thread; /* irq thread */
|
||||
struct OsalSem sem;
|
||||
bool irqPending;
|
||||
bool threadRunning;
|
||||
};
|
||||
|
||||
struct SdioDeviceOps {
|
||||
int32_t (*incrAddrReadBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t);
|
||||
int32_t (*incrAddrWriteBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t);
|
||||
int32_t (*fixedAddrReadBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t, uint32_t);
|
||||
int32_t (*fixedAddrWriteBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t, uint32_t);
|
||||
int32_t (*func0ReadBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t);
|
||||
int32_t (*func0WriteBytes)(struct SdioDevice *, uint8_t *, uint32_t, uint32_t);
|
||||
int32_t (*setBlockSize)(struct SdioDevice *, uint32_t);
|
||||
int32_t (*getCommonInfo)(struct SdioDevice *, SdioCommonInfo *, uint32_t);
|
||||
int32_t (*setCommonInfo)(struct SdioDevice *, SdioCommonInfo *, uint32_t);
|
||||
int32_t (*flushData)(struct SdioDevice *);
|
||||
int32_t (*enableFunc)(struct SdioDevice *);
|
||||
int32_t (*disableFunc)(struct SdioDevice *);
|
||||
int32_t (*claimIrq)(struct SdioDevice *, SdioIrqHandler *);
|
||||
int32_t (*releaseIrq)(struct SdioDevice *);
|
||||
int32_t (*findFunc)(struct SdioDevice *, struct SdioFunctionConfig *);
|
||||
int32_t (*claimHost)(struct SdioDevice *);
|
||||
int32_t (*releaseHost)(struct SdioDevice *);
|
||||
};
|
||||
|
||||
int32_t SdioDeviceFindFunction(struct SdioDevice *sdio, struct SdioFunctionConfig *config);
|
||||
int32_t SdioDeviceIncrAddrReadBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size);
|
||||
int32_t SdioDeviceIncrAddrWriteBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size);
|
||||
int32_t SdioDeviceFixedAddrReadBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
|
||||
int32_t SdioDeviceFixedAddrWriteBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
|
||||
int32_t SdioDeviceFunc0ReadBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size);
|
||||
int32_t SdioDeviceFunc0WriteBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size);
|
||||
int32_t SdioDeviceSetBlockSize(struct SdioDevice *sdio, uint32_t blockSize);
|
||||
int32_t SdioDeviceGetCommonInfo(struct SdioDevice *sdio,
|
||||
SdioCommonInfo *info, SdioCommonInfoType infoType);
|
||||
int32_t SdioDeviceSetCommonInfo(struct SdioDevice *sdio,
|
||||
SdioCommonInfo *info, SdioCommonInfoType infoType);
|
||||
int32_t SdioDeviceFlushData(struct SdioDevice *sdio);
|
||||
int32_t SdioDeviceClaimHost(struct SdioDevice *sdio);
|
||||
int32_t SdioDeviceReleaseHost(struct SdioDevice *sdio);
|
||||
int32_t SdioDeviceEnableFunc(struct SdioDevice *sdio);
|
||||
int32_t SdioDeviceDisableFunc(struct SdioDevice *sdio);
|
||||
int32_t SdioDeviceClaimIrq(struct SdioDevice *sdio, SdioIrqHandler *irqHandler);
|
||||
int32_t SdioDeviceReleaseIrq(struct SdioDevice *sdio);
|
||||
|
||||
void SdioDeviceAddOps(struct SdioDevice *sdio, void *ops);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MMC_SDIO_H */
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "hdf_log.h"
|
||||
#include "osal_spinlock.h"
|
||||
#include "platform_common.h"
|
||||
|
||||
static struct PlatformModuleInfo g_platformModules[] = {
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_GPIO)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_GPIO,
|
||||
.moduleName = "PLATFORM_MODULE_GPIO",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2C)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_I2C,
|
||||
.moduleName = "PLATFORM_MODULE_I2C",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SPI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SPI)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_SPI,
|
||||
.moduleName = "PLATFORM_MODULE_SPI",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PIN) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PIN)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_PIN,
|
||||
.moduleName = "PLATFORM_MODULE_PIN",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_CLOCK) || defined(CONFIG_DRIVERS_HDF_PLATFORM_CLOCK)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_CLOCK,
|
||||
.moduleName = "PLATFORM_MODULE_CLOCK",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_REGULATOR) || defined(CONFIG_DRIVERS_HDF_PLATFORM_REGULATOR)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_REGULATOR,
|
||||
.moduleName = "PLATFORM_MODULE_REGULATOR",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MIPI_DSI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_MIPI_DSI,
|
||||
.moduleName = "PLATFORM_MODULE_MIPI_DSI",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART) || defined(CONFIG_DRIVERS_HDF_PLATFORM_UART)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_UART,
|
||||
.moduleName = "PLATFORM_MODULE_UART",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SDIO)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_SDIO,
|
||||
.moduleName = "PLATFORM_MODULE_SDIO",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MDIO)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_MDIO,
|
||||
.moduleName = "PLATFORM_MODULE_MDIO",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_APB) || defined(CONFIG_DRIVERS_HDF_PLATFORM_APB)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_APB,
|
||||
.moduleName = "PLATFORM_MODULE_APB",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PCIE) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PCIE)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_PCIE,
|
||||
.moduleName = "PLATFORM_MODULE_PCIE",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PCM) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PCM)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_PCM,
|
||||
.moduleName = "PLATFORM_MODULE_PCM",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2S) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2S)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_I2S,
|
||||
.moduleName = "PLATFORM_MODULE_I2S",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PWM) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PWM)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_PWM,
|
||||
.moduleName = "PLATFORM_MODULE_PWM",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_DMA) || defined(CONFIG_DRIVERS_HDF_PLATFORM_DMA)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_DMA,
|
||||
.moduleName = "PLATFORM_MODULE_DMA",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_ADC)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_ADC,
|
||||
.moduleName = "PLATFORM_MODULE_ADC",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_RTC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_RTC)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_RTC,
|
||||
.moduleName = "PLATFORM_MODULE_RTC",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_WDT) || defined(CONFIG_DRIVERS_HDF_PLATFORM_WDT)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_WDT,
|
||||
.moduleName = "PLATFORM_MODULE_WDT",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I3C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I3C)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_I3C,
|
||||
.moduleName = "PLATFORM_MODULE_I3C",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_CAN) || defined(CONFIG_DRIVERS_HDF_PLATFORM_CAN)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_CAN,
|
||||
.moduleName = "PLATFORM_MODULE_CAN",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_HDMI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_HDMI)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_HDMI,
|
||||
.moduleName = "PLATFORM_MODULE_HDMI",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MMC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MMC)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_MMC,
|
||||
.moduleName = "PLATFORM_MODULE_MMC",
|
||||
},
|
||||
#endif
|
||||
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_MTD) || defined(CONFIG_DRIVERS_HDF_PLATFORM_MTD)
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_MTD,
|
||||
.moduleName = "PLATFORM_MODULE_MTD",
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.moduleType = PLATFORM_MODULE_DEFAULT,
|
||||
.moduleName = "PLATFORM_MODULE_DEFAULT",
|
||||
},
|
||||
};
|
||||
|
||||
static OsalSpinlock g_platformSpin;
|
||||
static bool g_platformReady;
|
||||
|
||||
void PlatformGlobalLock(void)
|
||||
{
|
||||
if (g_platformReady == false) {
|
||||
(void)OsalSpinInit(&g_platformSpin);
|
||||
g_platformReady = true;
|
||||
}
|
||||
(void)OsalSpinLock(&g_platformSpin);
|
||||
}
|
||||
|
||||
void PlatformGlobalUnlock(void)
|
||||
{
|
||||
(void)OsalSpinUnlock(&g_platformSpin);
|
||||
}
|
||||
|
||||
struct PlatformModuleInfo *PlatformModuleInfoGet(enum PlatformModuleType moduleType)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < PlatformModuleInfoCount(); i++) {
|
||||
if (g_platformModules[i].moduleType == moduleType) {
|
||||
return &g_platformModules[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t PlatformModuleInfoCount(void)
|
||||
{
|
||||
return sizeof(g_platformModules) / sizeof(g_platformModules[0]);
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "platform_common.h"
|
||||
#include "platform_device.h"
|
||||
#include "platform_manager.h"
|
||||
|
||||
#define PLATFORM_DEV_NAME_DEFAULT "platform_device"
|
||||
|
||||
static void PlatformDeviceOnFirstGet(struct HdfSRef *sref)
|
||||
{
|
||||
(void)sref;
|
||||
}
|
||||
|
||||
static void PlatformDeviceOnLastPut(struct HdfSRef *sref)
|
||||
{
|
||||
struct PlatformDevice *device = NULL;
|
||||
struct PlatformNotifierNode *pos = NULL;
|
||||
struct PlatformNotifierNode *tmp = NULL;
|
||||
|
||||
if (sref == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
device = CONTAINER_OF(sref, struct PlatformDevice, ref);
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("PlatformDeviceOnLastPut: get device is NULL!");
|
||||
return;
|
||||
}
|
||||
(void)OsalSpinLock(&device->spin);
|
||||
device->ready = false;
|
||||
|
||||
DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &device->notifiers, struct PlatformNotifierNode, node) {
|
||||
if (pos != NULL && pos->notifier != NULL && pos->notifier->handle != NULL) {
|
||||
pos->notifier->handle(device, PLAT_EVENT_DEAD, pos->notifier->data);
|
||||
}
|
||||
}
|
||||
|
||||
(void)OsalSpinUnlock(&device->spin);
|
||||
}
|
||||
|
||||
struct IHdfSRefListener g_platObjListener = {
|
||||
.OnFirstAcquire = PlatformDeviceOnFirstGet,
|
||||
.OnLastRelease = PlatformDeviceOnLastPut,
|
||||
};
|
||||
|
||||
static void PlatformEventHandle(struct PlatformDevice *device, enum PlatformEventType event, void *data)
|
||||
{
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
if (event == PLAT_EVENT_DEAD) {
|
||||
(void)OsalSemPost(&device->released);
|
||||
}
|
||||
}
|
||||
|
||||
static struct PlatformNotifier g_platformEventNotifier = {
|
||||
.data = NULL,
|
||||
.handle = PlatformEventHandle,
|
||||
};
|
||||
|
||||
void PlatformDeviceInit(struct PlatformDevice *device)
|
||||
{
|
||||
if (device == NULL) {
|
||||
HDF_LOGW("PlatformDeviceInit: device is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->name == NULL) {
|
||||
device->name = PLATFORM_DEV_NAME_DEFAULT;
|
||||
}
|
||||
|
||||
(void)OsalSpinInit(&device->spin);
|
||||
(void)OsalSemInit(&device->released, 0);
|
||||
DListHeadInit(&device->node);
|
||||
DListHeadInit(&device->notifiers);
|
||||
HdfSRefConstruct(&device->ref, &g_platObjListener);
|
||||
|
||||
if (PlatformDeviceRegNotifier(device, &g_platformEventNotifier) != HDF_SUCCESS) {
|
||||
HDF_LOGE("PlatformDeviceInit: reg notifier fail");
|
||||
}
|
||||
device->ready = true;
|
||||
}
|
||||
|
||||
void PlatformDeviceUninit(struct PlatformDevice *device)
|
||||
{
|
||||
if (device == NULL) {
|
||||
HDF_LOGW("PlatformDevice: device is NULL");
|
||||
return;
|
||||
}
|
||||
device->ready = false;
|
||||
|
||||
/* make sure no reference anymore before exit. */
|
||||
(void)OsalSemWait(&device->released, HDF_WAIT_FOREVER);
|
||||
PlatformDeviceClearNotifier(device);
|
||||
(void)OsalSemDestroy(&device->released);
|
||||
(void)OsalSpinDestroy(&device->spin);
|
||||
}
|
||||
|
||||
struct PlatformDevice *PlatformDeviceGet(struct PlatformDevice *device)
|
||||
{
|
||||
if (device == NULL) {
|
||||
HDF_LOGE("PlatformDeviceGet: device is NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HdfSRefAcquire(&device->ref);
|
||||
return device;
|
||||
}
|
||||
|
||||
void PlatformDevicePut(struct PlatformDevice *device)
|
||||
{
|
||||
if (device != NULL) {
|
||||
HdfSRefRelease(&device->ref);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t PlatformDeviceRegNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier)
|
||||
{
|
||||
struct PlatformNotifierNode *pNode = NULL;
|
||||
|
||||
if (device == NULL || notifier == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
pNode = (struct PlatformNotifierNode *)OsalMemCalloc(sizeof(*pNode));
|
||||
if (pNode == NULL) {
|
||||
HDF_LOGE("PlatformDeviceRegNotifier: alloc pNode fail");
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
pNode->notifier = notifier;
|
||||
(void)OsalSpinLock(&device->spin);
|
||||
DListInsertTail(&pNode->node, &device->notifiers);
|
||||
(void)OsalSpinUnlock(&device->spin);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void PlatformDeviceRemoveNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier)
|
||||
{
|
||||
struct PlatformNotifierNode *pos = NULL;
|
||||
struct PlatformNotifierNode *tmp = NULL;
|
||||
|
||||
if (device->notifiers.next == NULL || device->notifiers.prev == NULL) {
|
||||
HDF_LOGD("PlatformDeviceRemoveNotifier: notifiers not init.");
|
||||
return;
|
||||
}
|
||||
|
||||
(void)OsalSpinLock(&device->spin);
|
||||
DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &device->notifiers, struct PlatformNotifierNode, node) {
|
||||
if (pos != NULL && pos->notifier != NULL) {
|
||||
/* if notifier not set, we remove all the notifier nodes. */
|
||||
if (notifier == NULL || notifier == pos->notifier) {
|
||||
DListRemove(&pos->node);
|
||||
OsalMemFree(pos);
|
||||
}
|
||||
if (notifier == pos->notifier) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)OsalSpinUnlock(&device->spin);
|
||||
}
|
||||
|
||||
|
||||
void PlatformDeviceUnregNotifier(struct PlatformDevice *device, struct PlatformNotifier *notifier)
|
||||
{
|
||||
if (device == NULL || notifier == NULL) {
|
||||
return;
|
||||
}
|
||||
PlatformDeviceRemoveNotifier(device, notifier);
|
||||
}
|
||||
|
||||
void PlatformDeviceClearNotifier(struct PlatformDevice *device)
|
||||
{
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
PlatformDeviceRemoveNotifier(device, NULL);
|
||||
}
|
||||
|
||||
int32_t PlatformDeviceAdd(struct PlatformDevice *device)
|
||||
{
|
||||
struct PlatformManager *manager = NULL;
|
||||
|
||||
if (device == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
PlatformDeviceInit(device);
|
||||
manager = device->manager;
|
||||
if (manager == NULL) {
|
||||
manager = PlatformManagerGet(PLATFORM_MODULE_DEFAULT);
|
||||
}
|
||||
return PlatformManagerAddDevice(manager, device);
|
||||
}
|
||||
|
||||
void PlatformDeviceDel(struct PlatformDevice *device)
|
||||
{
|
||||
struct PlatformManager *manager = NULL;
|
||||
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
manager = device->manager;
|
||||
if (manager == NULL) {
|
||||
manager = PlatformManagerGet(PLATFORM_MODULE_DEFAULT);
|
||||
}
|
||||
PlatformManagerDelDevice(manager, device);
|
||||
PlatformDeviceUninit(device);
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "osal_sem.h"
|
||||
#include "platform_common.h"
|
||||
#include "platform_device.h"
|
||||
#include "platform_manager.h"
|
||||
|
||||
#define PLATFORM_MANAGER_NAME_DEFAULT "PlatformManagerDefault"
|
||||
|
||||
static void PlatformManagerInit(struct PlatformManager *manager)
|
||||
{
|
||||
if (manager->name == NULL) {
|
||||
manager->name = PLATFORM_MANAGER_NAME_DEFAULT;
|
||||
}
|
||||
|
||||
OsalSpinInit(&manager->spin);
|
||||
DListHeadInit(&manager->devices);
|
||||
}
|
||||
|
||||
struct PlatformManager *PlatformManagerCreate(const char *name)
|
||||
{
|
||||
struct PlatformManager *manager = NULL;
|
||||
|
||||
manager = (struct PlatformManager *)OsalMemCalloc(sizeof(*manager));
|
||||
if (manager == NULL) {
|
||||
HDF_LOGE("PlatformManagerCreate: malloc fail!");
|
||||
return NULL;
|
||||
}
|
||||
manager->name = name;
|
||||
PlatformManagerInit(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
struct PlatformManager *PlatformManagerGet(enum PlatformModuleType module)
|
||||
{
|
||||
struct PlatformManager *manager = NULL;
|
||||
struct PlatformModuleInfo *info = NULL;
|
||||
|
||||
info = PlatformModuleInfoGet(module);
|
||||
if (info == NULL) {
|
||||
HDF_LOGE("PlatformManagerGet: get module(%d) info failed", module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PlatformGlobalLock();
|
||||
if (info->priv == NULL) {
|
||||
manager = PlatformManagerCreate(info->moduleName);
|
||||
info->priv = manager;
|
||||
} else {
|
||||
manager = (struct PlatformManager *)info->priv;
|
||||
}
|
||||
PlatformGlobalUnlock();
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
int32_t PlatformManagerAddDevice(struct PlatformManager *manager, struct PlatformDevice *device)
|
||||
{
|
||||
struct PlatformDevice *tmp = NULL;
|
||||
bool repeatId = false;
|
||||
|
||||
if (manager == NULL || device == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
device->manager = manager;
|
||||
|
||||
if (PlatformDeviceGet(device) == NULL) { // keep a reference by manager
|
||||
return HDF_PLT_ERR_DEV_GET;
|
||||
}
|
||||
|
||||
(void)OsalSpinLock(&manager->spin);
|
||||
DLIST_FOR_EACH_ENTRY(tmp, &manager->devices, struct PlatformDevice, node) {
|
||||
if (tmp != NULL && tmp->magic == device->magic) {
|
||||
repeatId = true;
|
||||
HDF_LOGE("PlatformManagerAddDevice: repeated magic:%u!", device->magic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!repeatId) {
|
||||
DListInsertTail(&device->node, &manager->devices);
|
||||
}
|
||||
(void)OsalSpinUnlock(&manager->spin);
|
||||
|
||||
if (repeatId) {
|
||||
PlatformDevicePut(device);
|
||||
}
|
||||
return repeatId ? HDF_PLT_ERR_ID_REPEAT : HDF_SUCCESS;
|
||||
}
|
||||
|
||||
void PlatformManagerDelDevice(struct PlatformManager *manager, struct PlatformDevice *device)
|
||||
{
|
||||
if (manager == NULL || device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->manager != manager) {
|
||||
HDF_LOGE("PlatformManagerDelDevice: manager mismatch!");
|
||||
return;
|
||||
}
|
||||
|
||||
(void)OsalSpinLock(&manager->spin);
|
||||
if (!DListIsEmpty(&device->node)) {
|
||||
DListRemove(&device->node);
|
||||
}
|
||||
(void)OsalSpinUnlock(&manager->spin);
|
||||
PlatformDevicePut(device); // put the reference hold by manager
|
||||
}
|
||||
|
||||
struct PlatformDevice *PlatformManagerFindDevice(struct PlatformManager *manager, void *data,
|
||||
bool (*match)(struct PlatformDevice *pdevice, void *data))
|
||||
{
|
||||
struct PlatformDevice *tmp = NULL;
|
||||
struct PlatformDevice *pdevice = NULL;
|
||||
|
||||
if (manager == NULL || match == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (manager->devices.prev == NULL || manager->devices.next == NULL) {
|
||||
HDF_LOGD("PlatformManagerFindDevice: devices not init.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void)OsalSpinLock(&manager->spin);
|
||||
DLIST_FOR_EACH_ENTRY(tmp, &manager->devices, struct PlatformDevice, node) {
|
||||
if (tmp != NULL && match(tmp, data)) {
|
||||
pdevice = PlatformDeviceGet(tmp);
|
||||
}
|
||||
}
|
||||
(void)OsalSpinUnlock(&manager->spin);
|
||||
|
||||
return pdevice;
|
||||
}
|
||||
|
||||
static bool PlatformDeviceMatchByMagic(struct PlatformDevice *device, void *data)
|
||||
{
|
||||
uint32_t magic = (uint32_t)(uintptr_t)data;
|
||||
|
||||
return (device != NULL && device->magic == magic);
|
||||
}
|
||||
|
||||
struct PlatformDevice *PlatformManagerGetDeviceByMagic(struct PlatformManager *manager, uint32_t magic)
|
||||
{
|
||||
if (manager == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return PlatformManagerFindDevice(manager, (void *)(uintptr_t)magic, PlatformDeviceMatchByMagic);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "platform_queue.h"
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "osal_mutex.h"
|
||||
#include "osal_thread.h"
|
||||
|
||||
#define MMC_QUEUE_THREAD_STAK 20000
|
||||
|
||||
static int32_t PlatformQueueThreadWorker(void *data)
|
||||
{
|
||||
int32_t ret;
|
||||
struct PlatformQueue *queue = (struct PlatformQueue *)data;
|
||||
struct PlatformMsg *msg = NULL;
|
||||
|
||||
while (true) {
|
||||
/* wait envent */
|
||||
ret = OsalSemWait(&queue->sem, HDF_WAIT_FOREVER);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)OsalSpinLock(&queue->spin);
|
||||
if (DListIsEmpty(&queue->msgs)) {
|
||||
msg = NULL;
|
||||
} else {
|
||||
msg = DLIST_FIRST_ENTRY(&queue->msgs, struct PlatformMsg, node);
|
||||
DListRemove(&msg->node);
|
||||
}
|
||||
(void)OsalSpinUnlock(&queue->spin);
|
||||
/* message process */
|
||||
if (msg != NULL) {
|
||||
(void)(queue->handle(queue, msg));
|
||||
if (msg->block == true) {
|
||||
(void)OsalSemPost(&msg->sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
struct PlatformQueue *PlatformQueueCreate(PlatformMsgHandle handle, const char *name, void *data)
|
||||
{
|
||||
int32_t ret;
|
||||
struct PlatformQueue *queue = NULL;
|
||||
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
queue = (struct PlatformQueue *)OsalMemCalloc(sizeof(*queue));
|
||||
if (queue == NULL) {
|
||||
HDF_LOGE("PlatformQueueCreate: alloc queue fail!");
|
||||
return NULL;
|
||||
}
|
||||
(void)OsalSpinInit(&queue->spin);
|
||||
(void)OsalSemInit(&queue->sem, 0);
|
||||
DListHeadInit(&queue->msgs);
|
||||
|
||||
ret = OsalThreadCreate(&queue->thread, (OsalThreadEntry)PlatformQueueThreadWorker, (void *)queue);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("PlatformQueueCreate: create thread fail!");
|
||||
OsalMemFree(queue);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
queue->name = (name == NULL) ? "PlatformWorkerThread" : name;
|
||||
queue->handle = handle;
|
||||
queue->data = data;
|
||||
return queue;
|
||||
}
|
||||
|
||||
void PlatformQueueDestroy(struct PlatformQueue *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)OsalThreadDestroy(&queue->thread);
|
||||
(void)OsalSemDestroy(&queue->sem);
|
||||
(void)OsalSpinDestroy(&queue->spin);
|
||||
OsalMemFree(queue);
|
||||
}
|
||||
|
||||
int32_t PlatformQueueStart(struct PlatformQueue *queue)
|
||||
{
|
||||
int32_t ret;
|
||||
struct OsalThreadParam cfg;
|
||||
|
||||
if (queue == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cfg.name = (char *)queue->name;
|
||||
cfg.priority = OSAL_THREAD_PRI_HIGHEST;
|
||||
cfg.stackSize = MMC_QUEUE_THREAD_STAK;
|
||||
ret = OsalThreadStart(&queue->thread, &cfg);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("PlatformQueueStart: start thread fail:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t PlatformQueueSuspend(struct PlatformQueue *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
return OsalThreadSuspend(&queue->thread);
|
||||
}
|
||||
|
||||
int32_t PlatformQueueResume(struct PlatformQueue *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
return OsalThreadResume(&queue->thread);
|
||||
}
|
||||
|
||||
void PlatformQueueAddMsg(struct PlatformQueue *queue, struct PlatformMsg *msg)
|
||||
{
|
||||
if (queue == NULL || msg == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->block == true) {
|
||||
(void)OsalSemInit(&msg->sem, 0);
|
||||
}
|
||||
DListHeadInit(&msg->node);
|
||||
msg->error = HDF_SUCCESS;
|
||||
(void)OsalSpinLock(&queue->spin);
|
||||
DListInsertTail(&msg->node, &queue->msgs);
|
||||
(void)OsalSpinUnlock(&queue->spin);
|
||||
/* notify the worker thread */
|
||||
(void)OsalSemPost(&queue->sem);
|
||||
}
|
||||
|
||||
int32_t PlatformMsgWait(struct PlatformMsg *msg)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (msg->block == false) {
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
return OsalSemWait(&msg->sem, HDF_WAIT_FOREVER);
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#ifndef __USER__
|
||||
#include "devsvc_manager_clnt.h"
|
||||
#include "mmc_emmc.h"
|
||||
#endif
|
||||
#include "emmc_if.h"
|
||||
#include "hdf_base.h"
|
||||
#ifdef __USER__
|
||||
#include "hdf_io_service_if.h"
|
||||
#endif
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HDF_LOG_TAG emmc_if_c
|
||||
|
||||
#ifdef __USER__
|
||||
static int32_t EmmcGetCidReadReplyData(struct HdfSBuf *reply, uint8_t *cid, uint32_t size)
|
||||
{
|
||||
uint32_t rLen;
|
||||
const void *rBuf = NULL;
|
||||
|
||||
if (HdfSbufReadBuffer(reply, &rBuf, &rLen) == false) {
|
||||
HDF_LOGE("EmmcGetCidReadReplyData: read rBuf fail!");
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
if (size != rLen) {
|
||||
HDF_LOGE("EmmcGetCidReadReplyData: err len:%u, rLen:%u", size, rLen);
|
||||
if (rLen > size) {
|
||||
rLen = size;
|
||||
}
|
||||
}
|
||||
|
||||
if (memcpy_s(cid, size, rBuf, rLen) != EOK) {
|
||||
HDF_LOGE("EmmcGetCidReadReplyData: memcpy rBuf fail!");
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t EmmcServiceGetCid(struct HdfIoService *service, uint8_t *cid, uint32_t size)
|
||||
{
|
||||
int32_t ret;
|
||||
struct HdfSBuf *reply = NULL;
|
||||
|
||||
reply = HdfSBufObtainDefaultSize();
|
||||
if (reply == NULL) {
|
||||
HDF_LOGE("EmmcServiceGetCid: failed to obtain reply!");
|
||||
ret = HDF_ERR_MALLOC_FAIL;
|
||||
goto __EXIT;
|
||||
}
|
||||
|
||||
if (service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
|
||||
HDF_LOGE("EmmcServiceGetCid: dispatcher or Dispatch is NULL!");
|
||||
ret = HDF_ERR_NOT_SUPPORT;
|
||||
goto __EXIT;
|
||||
}
|
||||
|
||||
ret = service->dispatcher->Dispatch(&service->object, EMMC_CMD_GET_CID, NULL, reply);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("EmmcServiceGetCid: failed to send service call:%d", ret);
|
||||
goto __EXIT;
|
||||
}
|
||||
|
||||
ret = EmmcGetCidReadReplyData(reply, cid, size);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
goto __EXIT;
|
||||
}
|
||||
HDF_LOGD("EmmcServiceGetCid: success");
|
||||
|
||||
__EXIT:
|
||||
if (reply != NULL) {
|
||||
HdfSBufRecycle(reply);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
static int32_t EmmcDeviceGetFromHandle(DevHandle handle, struct EmmcDevice **emmc)
|
||||
{
|
||||
struct MmcDevice *mmc = NULL;
|
||||
|
||||
if (handle == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (emmc == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
mmc = MmcCntlrGetDevice((struct MmcCntlr *)handle);
|
||||
if (mmc == NULL) {
|
||||
return HDF_PLT_ERR_NO_DEV;
|
||||
}
|
||||
if (mmc->type != MMC_DEV_EMMC) {
|
||||
MmcDevicePut(mmc);
|
||||
return HDF_PLT_ERR_DEV_TYPE;
|
||||
}
|
||||
|
||||
*emmc = (struct EmmcDevice *)mmc;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32_t EmmcGetCid(DevHandle handle, uint8_t *cid, uint32_t size)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
HDF_LOGE("EmmcGetCid: handle is NULL!");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (cid == NULL || size < EMMC_CID_LEN) {
|
||||
HDF_LOGE("EmmcGetCid: error parms!");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
#ifdef __USER__
|
||||
return EmmcServiceGetCid((struct HdfIoService *)handle, cid, size);
|
||||
#else
|
||||
struct EmmcDevice *emmc = NULL;
|
||||
int32_t ret;
|
||||
|
||||
if (EmmcDeviceGetFromHandle(handle, &emmc) != HDF_SUCCESS) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
ret = EmmcDeviceGetCid(emmc, cid, size);
|
||||
MmcDevicePut((struct MmcDevice *)emmc);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EmmcGetHuid(uint8_t *cid, uint32_t size)
|
||||
{
|
||||
DevHandle handle = NULL;
|
||||
if (cid == NULL || size == 0) {
|
||||
HDF_LOGE("EmmcGetUdid: error parms!");
|
||||
return;
|
||||
}
|
||||
if (memset_s(cid, sizeof(uint8_t) * size, 0, sizeof(uint8_t) * size) != EOK) {
|
||||
HDF_LOGE("EmmcGetUdid: memset_s fail!");
|
||||
return;
|
||||
}
|
||||
handle = EmmcOpen(0);
|
||||
if (handle == NULL) {
|
||||
HDF_LOGD("EmmcGetUdid: open fail, use default value!");
|
||||
return;
|
||||
}
|
||||
if (EmmcGetCid(handle, cid, size) != HDF_SUCCESS) {
|
||||
HDF_LOGD("EmmcGetUdid: get fail, use default value!");
|
||||
}
|
||||
EmmcClose(handle);
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "storage_block.h"
|
||||
#include "hdf_base.h"
|
||||
#include "hdf_log.h"
|
||||
#include "mmc_corex.h"
|
||||
#include "mmc_sd.h"
|
||||
#include "osal_mem.h"
|
||||
#include "securec.h"
|
||||
|
||||
static ssize_t MmcBlockRead(struct StorageBlock *sb, uint8_t *buf, size_t secStart, size_t nSec)
|
||||
{
|
||||
if (sb == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sb->type == MEDIA_MMC) {
|
||||
return MmcDeviceRead((struct MmcDevice *)sb->media, buf, secStart, nSec);
|
||||
}
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
static ssize_t MmcBlockWrite(struct StorageBlock *sb, const uint8_t *buf, size_t secStart, size_t nSec)
|
||||
{
|
||||
if (sb == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sb->type == MEDIA_MMC) {
|
||||
return MmcDeviceWrite((struct MmcDevice *)sb->media, (uint8_t *)buf, secStart, nSec);
|
||||
}
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
static ssize_t MmcBlockErase(struct StorageBlock *sb, size_t secStart, size_t nSec)
|
||||
{
|
||||
if (sb == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sb->type == MEDIA_MMC) {
|
||||
return MmcDeviceErase((struct MmcDevice *)sb->media, secStart, nSec);
|
||||
}
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
static uint32_t MmcBlockGetAuSize(struct StorageBlock *sb)
|
||||
{
|
||||
struct MmcDevice *mmc = NULL;
|
||||
struct SdDevice *sd = NULL;
|
||||
|
||||
if (sb == NULL || sb->media == NULL) {
|
||||
HDF_LOGE("MmcBlockGetAuSize: invalid sb or media!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sb->type != MEDIA_MMC) {
|
||||
HDF_LOGE("MmcBlockGetAuSize: media is not mmc!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmc = (struct MmcDevice *)sb->media;
|
||||
if (mmc->type != MMC_DEV_SD) {
|
||||
HDF_LOGE("MmcBlockGetAuSize: media is not sd!");
|
||||
return 0;
|
||||
}
|
||||
sd = (struct SdDevice *)mmc;
|
||||
|
||||
return sd->reg.ssr.auSize;
|
||||
}
|
||||
|
||||
static bool MmcBlockIsPresent(struct StorageBlock *sb)
|
||||
{
|
||||
return (sb != NULL && sb->type == MEDIA_MMC &&
|
||||
MmcDeviceIsPresent((struct MmcDevice *)sb->media));
|
||||
}
|
||||
|
||||
static struct StorageBlockMethod g_mmcBlockOps = {
|
||||
.read = MmcBlockRead,
|
||||
.write = MmcBlockWrite,
|
||||
.erase = MmcBlockErase,
|
||||
.getAuSize = MmcBlockGetAuSize,
|
||||
.isPresent = MmcBlockIsPresent,
|
||||
};
|
||||
|
||||
static int32_t MmcBlockInit(struct StorageBlock *sb, struct MmcDevice *mmc)
|
||||
{
|
||||
int32_t ret;
|
||||
size_t nameSize;
|
||||
|
||||
if (PlatformDeviceGet(&mmc->device) == NULL) {
|
||||
return HDF_PLT_ERR_DEV_GET;
|
||||
}
|
||||
mmc->sb = sb;
|
||||
sb->type = MEDIA_MMC;
|
||||
sb->media = mmc;
|
||||
sb->secSize = mmc->secSize;
|
||||
sb->capacity = mmc->capacity;
|
||||
sb->removeable = (mmc->state.bits.removeable == 0) ? false : true;
|
||||
sb->ops = &g_mmcBlockOps;
|
||||
nameSize = sizeof(sb->name);
|
||||
ret = snprintf_s(sb->name, nameSize, nameSize - 1, "/dev/mmcblk%0d", mmc->cntlr->index);
|
||||
if (ret <= 0) {
|
||||
PlatformDevicePut(&mmc->device);
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static void MmcBlockUninit(struct StorageBlock *sb)
|
||||
{
|
||||
struct MmcDevice *mmc = (struct MmcDevice *)sb->media;
|
||||
|
||||
mmc->sb = NULL;
|
||||
PlatformDevicePut(&mmc->device);
|
||||
}
|
||||
|
||||
int32_t MmcBlockAdd(struct MmcDevice *mmc)
|
||||
{
|
||||
int32_t ret;
|
||||
struct StorageBlock *sb = NULL;
|
||||
|
||||
if (mmc == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
sb = (struct StorageBlock *)OsalMemCalloc(sizeof(*sb));
|
||||
if (sb == NULL) {
|
||||
return HDF_ERR_MALLOC_FAIL;
|
||||
}
|
||||
|
||||
ret = MmcBlockInit(sb, mmc);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
OsalMemFree(sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = StorageBlockAdd(sb);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
MmcBlockUninit(sb);
|
||||
OsalMemFree(sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
void MmcBlockDel(struct MmcDevice *mmc)
|
||||
{
|
||||
struct StorageBlock *sb = NULL;
|
||||
|
||||
if (mmc == NULL) {
|
||||
return;
|
||||
}
|
||||
sb = mmc->sb;
|
||||
if (sb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
StorageBlockDel(sb);
|
||||
MmcBlockUninit(sb);
|
||||
OsalMemFree(sb);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "mmc_dispatch.h"
|
||||
#include "hdf_log.h"
|
||||
#include "mmc_corex.h"
|
||||
#include "mmc_emmc.h"
|
||||
#include "mmc_sdio.h"
|
||||
|
||||
static int32_t MmcCmdDevPresent(struct MmcCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
(void)data;
|
||||
if (reply == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (!HdfSbufWriteUint8(reply, MmcCntlrDevPresent(cntlr))) {
|
||||
HDF_LOGE("MmcCmdDevPresent: write reply sbuf fail!");
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t MmcDispatch(struct MmcCntlr *cntlr, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
switch (cmd) {
|
||||
case MMC_CMD_DEV_PRESENT:
|
||||
ret = MmcCmdDevPresent(cntlr, data, reply);
|
||||
break;
|
||||
default:
|
||||
ret = HDF_ERR_NOT_SUPPORT;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t EmmcCmdGetCid(struct MmcCntlr *cntlr, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
uint8_t cid[EMMC_CID_LEN] = {0};
|
||||
|
||||
if (reply == NULL || cntlr == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret = EmmcDeviceGetCid((struct EmmcDevice *)cntlr->curDev, cid, EMMC_CID_LEN);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("MmcCmdGetCid: get cid fail!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (HdfSbufWriteBuffer(reply, cid, EMMC_CID_LEN) == false) {
|
||||
HDF_LOGE("MmcCmdGetCid: write back cid fail!");
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t EmmcDispatch(struct MmcCntlr *cntlr, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
(void)data;
|
||||
|
||||
switch (cmd) {
|
||||
case EMMC_CMD_GET_CID:
|
||||
ret = EmmcCmdGetCid(cntlr, reply);
|
||||
break;
|
||||
default:
|
||||
ret = HDF_ERR_NOT_SUPPORT;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t SdioDispatch(struct MmcCntlr *cntlr, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
(void)cntlr;
|
||||
(void)cmd;
|
||||
(void)data;
|
||||
(void)reply;
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
int32_t MmcIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
|
||||
{
|
||||
int32_t ret;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
|
||||
if (client == NULL || client->device == NULL) {
|
||||
HDF_LOGE("MmcIoDispatch: client or hdf dev obj is NULL");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cntlr = (struct MmcCntlr *)client->device->service;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("MmcIoDispatch: service is NULL");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (cmd < MMC_CMD_MAX) {
|
||||
ret = MmcDispatch(cntlr, cmd, data, reply);
|
||||
} else if (cmd < EMMC_CMD_MAX) {
|
||||
ret = EmmcDispatch(cntlr, cmd, data, reply);
|
||||
} else if (cmd < SDIO_CMD_MAX) {
|
||||
ret = SdioDispatch(cntlr, cmd, data, reply);
|
||||
} else {
|
||||
ret = HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "mmc_emmc.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HDF_LOG_TAG mmc_emmc_c
|
||||
|
||||
static int32_t EmmcDeviceDefaultGetCid(struct EmmcDevice *dev, uint8_t *cid, uint32_t len)
|
||||
{
|
||||
struct MmcDevice *mmc = (struct MmcDevice *)dev;
|
||||
|
||||
if (memcpy_s(cid, sizeof(uint8_t) * len, (uint8_t *)(mmc->reg.rawCid),
|
||||
sizeof(mmc->reg.rawCid)) != EOK) {
|
||||
HDF_LOGE("EmmcDeviceDefaultGetCid: memcpy_s fail, size = %d!", len);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static struct EmmcDeviceOps g_emmcOps = {
|
||||
.getCid = EmmcDeviceDefaultGetCid,
|
||||
};
|
||||
|
||||
int32_t EmmcDeviceGetCid(struct EmmcDevice *dev, uint8_t *cid, uint32_t len)
|
||||
{
|
||||
if (dev == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (cid == NULL || len == 0) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (dev->emmcOps == NULL || dev->emmcOps->getCid == NULL) {
|
||||
HDF_LOGE("EmmcDeviceGetCid: ops or getCid is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
return dev->emmcOps->getCid(dev, cid, len);
|
||||
}
|
||||
|
||||
void EmmcDeviceAddOps(struct EmmcDevice *dev, void *ops)
|
||||
{
|
||||
if (dev == NULL) {
|
||||
HDF_LOGE("EmmcDeviceAddOps: dev is NULL.");
|
||||
return;
|
||||
}
|
||||
if (ops == NULL) {
|
||||
dev->emmcOps = &g_emmcOps;
|
||||
HDF_LOGD("EmmcDeviceAddOps: use default ops.");
|
||||
} else {
|
||||
dev->emmcOps = (struct EmmcDeviceOps *)ops;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "mmc_if.h"
|
||||
#ifndef __USER__
|
||||
#include "devsvc_manager_clnt.h"
|
||||
#include "mmc_corex.h"
|
||||
#endif
|
||||
#include "hdf_base.h"
|
||||
#ifdef __USER__
|
||||
#include "hdf_io_service_if.h"
|
||||
#endif
|
||||
#include "hdf_log.h"
|
||||
#include "osal_mem.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HDF_LOG_TAG mmc_if_c
|
||||
|
||||
#define MMC_SVC_NAME_LEN 32
|
||||
|
||||
static void *MmcCntlrObjGetByNumber(int16_t id)
|
||||
{
|
||||
void *object = NULL;
|
||||
char *serviceName = NULL;
|
||||
|
||||
if (id < 0) {
|
||||
HDF_LOGE("MmcCntlrObjGetByNumber: invalid id:%d", id);
|
||||
return NULL;
|
||||
}
|
||||
serviceName = OsalMemCalloc(MMC_SVC_NAME_LEN + 1);
|
||||
if (serviceName == NULL) {
|
||||
HDF_LOGE("MmcCntlrObjGetByNumber: OsalMemCalloc fail!");
|
||||
return NULL;
|
||||
}
|
||||
if (snprintf_s(serviceName, MMC_SVC_NAME_LEN + 1, MMC_SVC_NAME_LEN,
|
||||
"HDF_PLATFORM_MMC_%d", id) < 0) {
|
||||
HDF_LOGE("MmcCntlrObjGetByNumber: format service name fail!");
|
||||
goto __ERR;
|
||||
}
|
||||
|
||||
#ifdef __USER__
|
||||
object = (void *)HdfIoServiceBind(serviceName);
|
||||
#else
|
||||
object = (void *)MmcCntlrGetByNr(id);
|
||||
#endif
|
||||
if (object == NULL) {
|
||||
HDF_LOGE("MmcCntlrObjGetByNumber: get service fail!");
|
||||
} else {
|
||||
HDF_LOGD("MmcCntlrObjGetByNumber: success");
|
||||
}
|
||||
|
||||
__ERR:
|
||||
OsalMemFree(serviceName);
|
||||
return object;
|
||||
}
|
||||
|
||||
DevHandle MmcOpen(int16_t id)
|
||||
{
|
||||
return (DevHandle)MmcCntlrObjGetByNumber(id);
|
||||
}
|
||||
|
||||
void MmcClose(DevHandle handle)
|
||||
{
|
||||
if (handle != NULL) {
|
||||
#ifdef __USER__
|
||||
HdfIoServiceRecycle((struct HdfIoService *)handle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool MmcDevPresent(DevHandle handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return false;
|
||||
}
|
||||
#ifdef __USER__
|
||||
int32_t ret;
|
||||
uint8_t present = 0;
|
||||
struct HdfSBuf *reply = NULL;
|
||||
struct HdfIoService *service = (struct HdfIoService *)handle;
|
||||
|
||||
reply = HdfSBufObtainDefaultSize();
|
||||
if (reply == NULL) {
|
||||
HDF_LOGE("MmcDevPresent: failed to obtain reply!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
|
||||
HDF_LOGE("MmcDevPresent: dispatcher or Dispatch is NULL!");
|
||||
goto __EXIT;
|
||||
}
|
||||
ret = service->dispatcher->Dispatch(&service->object, MMC_CMD_DEV_PRESENT,
|
||||
NULL, reply);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("MmcDevPresent: failed to send service call:%d", ret);
|
||||
goto __EXIT;
|
||||
}
|
||||
|
||||
if (HdfSbufReadUint8(reply, &present) == false) {
|
||||
HDF_LOGE("MmcDevPresent: read present fail!");
|
||||
goto __EXIT;
|
||||
}
|
||||
__EXIT:
|
||||
HdfSBufRecycle(reply);
|
||||
return (present != 0);
|
||||
#else
|
||||
return MmcCntlrDevPresent((struct MmcCntlr *)handle);
|
||||
#endif
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,757 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "mmc_sdio.h"
|
||||
|
||||
#define HDF_LOG_TAG mmc_sdio_c
|
||||
#define SDIO_READ_IO_READY_RETRY_TIMES 10000
|
||||
|
||||
static int32_t SdioDeviceDefaultIncrAddrReadBytes(struct SdioDevice *dev,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioRwBlockInfo info = {0};
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (data == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, data is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
return SdioReadWriteByte(cntlr, false, func->funcNum, addr, data);
|
||||
} else if (size > 1) {
|
||||
info.addr = addr;
|
||||
info.buf = data;
|
||||
info.incrAddrFlag = true;
|
||||
info.size = size;
|
||||
info.writeFlag = false;
|
||||
return SdioReadWriteBlock(cntlr, &info);
|
||||
}
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrReadBytes fail, data size is 0.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultIncrAddrWriteBytes(struct SdioDevice *dev,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioRwBlockInfo info = {0};
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (data == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, data is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
return SdioReadWriteByte(cntlr, true, func->funcNum, addr, data);
|
||||
} else if (size > 1) {
|
||||
info.addr = addr;
|
||||
info.buf = data;
|
||||
info.incrAddrFlag = true;
|
||||
info.size = size;
|
||||
info.writeFlag = true;
|
||||
return SdioReadWriteBlock(cntlr, &info);
|
||||
}
|
||||
HDF_LOGE("SdioDeviceDefaultIncrAddrWriteBytes fail, data size is 0.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultFixedAddrReadBytes(struct SdioDevice *dev,
|
||||
uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioRwBlockInfo info = {0};
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFixedAddrReadBytes fail, func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (data == NULL || size == 0) {
|
||||
HDF_LOGE("SdioDeviceDefaultFixedAddrReadBytes fail, param is invalid.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFixedAddrReadBytes fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
info.addr = addr;
|
||||
info.buf = data;
|
||||
info.incrAddrFlag = false;
|
||||
info.size = size;
|
||||
info.writeFlag = false;
|
||||
if (scatterLen > 0) {
|
||||
info.scatterFlag = true;
|
||||
info.scatterLen = scatterLen;
|
||||
}
|
||||
return SdioReadWriteBlock(cntlr, &info);
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultFixedAddrWriteBytes(struct SdioDevice *dev,
|
||||
uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioRwBlockInfo info = {0};
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFixedAddrWriteBytes fail, func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (data == NULL || size == 0) {
|
||||
HDF_LOGE("SdioDeviceDefaultFixedAddrWriteBytes fail, param is invalid.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFixedAddrWriteBytes fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
info.addr = addr;
|
||||
info.buf = data;
|
||||
info.incrAddrFlag = false;
|
||||
info.size = size;
|
||||
info.writeFlag = true;
|
||||
if (scatterLen > 0) {
|
||||
info.scatterFlag = true;
|
||||
info.scatterLen = scatterLen;
|
||||
}
|
||||
return SdioReadWriteBlock(cntlr, &info);
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultFunc0ReadBytes(struct SdioDevice *dev,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
uint32_t i;
|
||||
int32_t ret;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (data == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, data is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
ret = SdioReadWriteByte(cntlr, false, 0, (addr + i), &data[i]);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0ReadBytes fail, i = %d.", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultFunc0WriteBytes(struct SdioDevice *dev,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
int32_t ret;
|
||||
uint32_t i;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (data == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, data is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
ret = SdioReadWriteByte(cntlr, true, 0, (addr + i), &data[i]);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioDeviceDefaultFunc0WriteBytes fail, i = %d.", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultSetBlockSize(struct SdioDevice *dev, uint32_t blkSize)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
uint32_t blockSize = blkSize;
|
||||
int32_t ret;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultSetBlockSize: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (blockSize == 0) {
|
||||
blockSize = ((func->maxBlkSize < cntlr->maxBlkSize) ? func->maxBlkSize : cntlr->maxBlkSize);
|
||||
}
|
||||
blockSize = MMC_MIN(blockSize, MMC_SEC_SIZE);
|
||||
|
||||
ret = SdioSetFbrIoBlockSize(cntlr, blockSize);
|
||||
if (ret == HDF_SUCCESS) {
|
||||
func->curBlkSize = blockSize;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultGetCommonInfo(struct SdioDevice *dev,
|
||||
SdioCommonInfo *info, SdioCommonInfoType infoType)
|
||||
{
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultGetCommonInfo: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (info == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultGetCommonInfo: info is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (infoType != SDIO_FUNC_INFO) {
|
||||
HDF_LOGE("SdioDeviceDefaultGetCommonInfo: cur type %d is not support.", infoType);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultGetCommonInfo fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
info->funcInfo.enTimeout = func->timeOut;
|
||||
info->funcInfo.maxBlockNum = cntlr->maxBlkNum;
|
||||
info->funcInfo.maxBlockSize = cntlr->maxBlkSize;
|
||||
info->funcInfo.maxRequestSize = cntlr->maxReqSize;
|
||||
info->funcInfo.funcNum = func->funcNum;
|
||||
info->funcInfo.irqCap = cntlr->caps.bits.sdioIrq;
|
||||
info->funcInfo.data = (void *)func;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultSetCommonInfo(struct SdioDevice *dev,
|
||||
SdioCommonInfo *info, SdioCommonInfoType infoType)
|
||||
{
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultSetCommonInfo: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (info == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultSetCommonInfo: info is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (infoType != SDIO_FUNC_INFO) {
|
||||
HDF_LOGE("SdioDeviceDefaultSetCommonInfo: cur type %d is not support.", infoType);
|
||||
return HDF_ERR_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultSetCommonInfo fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
func->timeOut = info->funcInfo.enTimeout;
|
||||
cntlr->maxBlkNum = info->funcInfo.maxBlockNum;
|
||||
cntlr->maxBlkSize = info->funcInfo.maxBlockSize;
|
||||
cntlr->maxReqSize = info->funcInfo.maxRequestSize;
|
||||
func->funcNum = info->funcInfo.funcNum;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultFlushData(struct SdioDevice *dev)
|
||||
{
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultFlushData fail, cntlr is null.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
return SdioReinit(cntlr);
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultEnableFunc(struct SdioDevice *dev)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
int32_t ret;
|
||||
uint32_t i;
|
||||
uint8_t val;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultEnableFunc: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
ret = SdioCccrIoEnable(dev->sd.mmc.cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioDeviceDefaultEnableFunc: Io Enable fail.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < SDIO_READ_IO_READY_RETRY_TIMES; i++) {
|
||||
ret = SdioReadCccrIoReady(dev->sd.mmc.cntlr, &val);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioDeviceDefaultEnableFunc: read Io Ready fail.");
|
||||
return ret;
|
||||
}
|
||||
if ((val & (1 << func->funcNum)) > 0) {
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
HDF_LOGE("SdioDeviceDefaultEnableFunc: Io not Ready.");
|
||||
return HDF_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultDisableFunc(struct SdioDevice *dev)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultDisableFunc: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
return SdioCccrIoDisable(dev->sd.mmc.cntlr);
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultClaimIrq(struct SdioDevice *dev, SdioIrqHandler *irqHandler)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
int32_t ret;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultClaimIrq: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (func->irqHandler != NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultClaimIrq: irq has been registered.");
|
||||
return HDF_ERR_DEVICE_BUSY;
|
||||
}
|
||||
if (irqHandler == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultClaimIrq: irqHandler is NULL.");
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultClaimIrq: cntlr is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
ret = SdioCccrIntEnable(cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
func->irqHandler = irqHandler;
|
||||
if (cntlr->caps.bits.sdioIrq > 0) {
|
||||
ret = MmcCntlrCreatSdioIrqThread(cntlr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultReleaseIrq(struct SdioDevice *dev)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultReleaseIrq: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultReleaseIrq: cntlr is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (func->irqHandler != NULL) {
|
||||
func->irqHandler = NULL;
|
||||
MmcCntlrDestroySdioIrqThread(cntlr);
|
||||
}
|
||||
if (cntlr->caps.bits.sdioIrq > 0 && cntlr->ops != NULL && cntlr->ops->setSdioIrq != NULL) {
|
||||
(void)cntlr->ops->setSdioIrq(cntlr, false);
|
||||
}
|
||||
return SdioCccrIntDisable(cntlr);
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultFindFunc(struct SdioDevice *dev, struct SdioFunctionConfig *cfg)
|
||||
{
|
||||
uint32_t i;
|
||||
struct SdioFunction *func = NULL;
|
||||
|
||||
if (dev->functions > SDIO_MAX_FUNCTION_NUMBER) {
|
||||
HDF_LOGE("SdioDeviceDefaultFindFunc: functions = %d, error!", dev->functions);
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->functions; i++) {
|
||||
func = dev->sdioFunc[i];
|
||||
if (func == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (cfg->deviceId == func->deviceId &&
|
||||
cfg->vendorId == func->vendorId &&
|
||||
cfg->funcNr == func->funcNum) {
|
||||
dev->curFunction = func;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
HDF_LOGE("SdioDeviceDefaultFindFunc: find func fail!");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultClaimHost(struct SdioDevice *dev)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultClaimHost: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultClaimHost: cntlr is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
MmcCntlrLock(cntlr);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t SdioDeviceDefaultReleaseHost(struct SdioDevice *dev)
|
||||
{
|
||||
struct SdioFunction *func = dev->curFunction;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
|
||||
if (func == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultReleaseHost: func is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
cntlr = dev->sd.mmc.cntlr;
|
||||
if (cntlr == NULL) {
|
||||
HDF_LOGE("SdioDeviceDefaultReleaseHost: cntlr is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
MmcCntlrUnlock(cntlr);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static struct SdioDeviceOps g_sdioDefaultOps = {
|
||||
.incrAddrReadBytes = SdioDeviceDefaultIncrAddrReadBytes,
|
||||
.incrAddrWriteBytes = SdioDeviceDefaultIncrAddrWriteBytes,
|
||||
.fixedAddrReadBytes = SdioDeviceDefaultFixedAddrReadBytes,
|
||||
.fixedAddrWriteBytes = SdioDeviceDefaultFixedAddrWriteBytes,
|
||||
.func0ReadBytes = SdioDeviceDefaultFunc0ReadBytes,
|
||||
.func0WriteBytes = SdioDeviceDefaultFunc0WriteBytes,
|
||||
.setBlockSize = SdioDeviceDefaultSetBlockSize,
|
||||
.getCommonInfo = SdioDeviceDefaultGetCommonInfo,
|
||||
.setCommonInfo = SdioDeviceDefaultSetCommonInfo,
|
||||
.flushData = SdioDeviceDefaultFlushData,
|
||||
.enableFunc = SdioDeviceDefaultEnableFunc,
|
||||
.disableFunc = SdioDeviceDefaultDisableFunc,
|
||||
.claimIrq = SdioDeviceDefaultClaimIrq,
|
||||
.releaseIrq = SdioDeviceDefaultReleaseIrq,
|
||||
.findFunc = SdioDeviceDefaultFindFunc,
|
||||
.claimHost = SdioDeviceDefaultClaimHost,
|
||||
.releaseHost = SdioDeviceDefaultReleaseHost,
|
||||
};
|
||||
|
||||
int32_t SdioDeviceFindFunction(struct SdioDevice *sdio, struct SdioFunctionConfig *config)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceFindFunction: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->findFunc == NULL) {
|
||||
HDF_LOGE("SdioDeviceFindFunction: func is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->findFunc(sdio, config);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceIncrAddrReadBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceIncrAddrReadBytes: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->incrAddrReadBytes == NULL) {
|
||||
HDF_LOGE("SdioDeviceIncrAddrReadBytes: incrAddrReadBytes is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->incrAddrReadBytes(sdio, data, addr, size);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceIncrAddrWriteBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceIncrAddrWriteBytes: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->incrAddrWriteBytes == NULL) {
|
||||
HDF_LOGE("SdioDeviceIncrAddrWriteBytes: incrAddrWriteBytes is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->incrAddrWriteBytes(sdio, data, addr, size);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceFixedAddrReadBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceFixedAddrReadBytes: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->fixedAddrReadBytes == NULL) {
|
||||
HDF_LOGE("SdioDeviceFixedAddrReadBytes: fixedAddrReadBytes is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->fixedAddrReadBytes(sdio, data, addr, size, scatterLen);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceFixedAddrWriteBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceFixedAddrWriteBytes: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->fixedAddrWriteBytes == NULL) {
|
||||
HDF_LOGE("SdioDeviceFixedAddrWriteBytes: fixedAddrWriteBytes is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->fixedAddrWriteBytes(sdio, data, addr, size, scatterLen);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceFunc0ReadBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceFunc0ReadBytes: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->func0ReadBytes == NULL) {
|
||||
HDF_LOGE("SdioDeviceFunc0ReadBytes: func0ReadBytes is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->func0ReadBytes(sdio, data, addr, size);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceFunc0WriteBytes(struct SdioDevice *sdio,
|
||||
uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceFunc0WriteBytes: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->func0WriteBytes == NULL) {
|
||||
HDF_LOGE("SdioDeviceFunc0WriteBytes: func0WriteBytes is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->func0WriteBytes(sdio, data, addr, size);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceSetBlockSize(struct SdioDevice *sdio, uint32_t blockSize)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceSetBlockSize: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->setBlockSize == NULL) {
|
||||
HDF_LOGE("SdioDeviceSetBlockSize: setBlockSize is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->setBlockSize(sdio, blockSize);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceGetCommonInfo(struct SdioDevice *sdio,
|
||||
SdioCommonInfo *info, SdioCommonInfoType infoType)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceGetCommonInfo: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->getCommonInfo == NULL) {
|
||||
HDF_LOGE("SdioDeviceGetCommonInfo: getCommonInfo is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->getCommonInfo(sdio, info, infoType);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceSetCommonInfo(struct SdioDevice *sdio,
|
||||
SdioCommonInfo *info, SdioCommonInfoType infoType)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceSetCommonInfo: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->setCommonInfo == NULL) {
|
||||
HDF_LOGE("SdioDeviceSetCommonInfo: setCommonInfo is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->setCommonInfo(sdio, info, infoType);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceFlushData(struct SdioDevice *sdio)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceFlushData: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->flushData == NULL) {
|
||||
HDF_LOGE("SdioDeviceFlushData: flushData is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->flushData(sdio);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceClaimHost(struct SdioDevice *sdio)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceClaimHost: cntlr is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (sdio->sdioOps->claimHost != NULL) {
|
||||
return sdio->sdioOps->claimHost(sdio);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t SdioDeviceReleaseHost(struct SdioDevice *sdio)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceReleaseHost: cntlr is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (sdio->sdioOps->releaseHost != NULL) {
|
||||
return sdio->sdioOps->releaseHost(sdio);
|
||||
}
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t SdioDeviceEnableFunc(struct SdioDevice *sdio)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceEnableFunc: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->enableFunc == NULL) {
|
||||
HDF_LOGE("SdioDeviceEnableFunc: enableFunc is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->enableFunc(sdio);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceDisableFunc(struct SdioDevice *sdio)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceDisableFunc: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->disableFunc == NULL) {
|
||||
HDF_LOGE("SdioDeviceDisableFunc: disableFunc is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->disableFunc(sdio);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceClaimIrq(struct SdioDevice *sdio, SdioIrqHandler *irqHandler)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceClaimIrq: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->claimIrq == NULL) {
|
||||
HDF_LOGE("SdioDeviceClaimIrq: claimIrq is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->claimIrq(sdio, irqHandler);
|
||||
}
|
||||
|
||||
int32_t SdioDeviceReleaseIrq(struct SdioDevice *sdio)
|
||||
{
|
||||
if (sdio->sdioOps == NULL) {
|
||||
HDF_LOGE("SdioDeviceReleaseIrq: ops is NULL.");
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
if (sdio->sdioOps->releaseIrq == NULL) {
|
||||
HDF_LOGE("SdioDeviceReleaseIrq: releaseIrq is NULL.");
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
return sdio->sdioOps->releaseIrq(sdio);
|
||||
}
|
||||
|
||||
void SdioDeviceAddOps(struct SdioDevice *sdio, void *ops)
|
||||
{
|
||||
if (sdio == NULL) {
|
||||
HDF_LOGE("SdioDeviceAddOps: sdio is NULL.");
|
||||
return;
|
||||
}
|
||||
if (ops == NULL) {
|
||||
sdio->sdioOps = &g_sdioDefaultOps;
|
||||
HDF_LOGD("SdioDeviceAddOps: use default ops.");
|
||||
} else {
|
||||
sdio->sdioOps = (struct SdioDeviceOps *)ops;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include "sdio_if.h"
|
||||
#include "hdf_base.h"
|
||||
#include "hdf_log.h"
|
||||
#include "mmc_sdio.h"
|
||||
#include "osal_mem.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HDF_LOG_TAG sdio_if_c
|
||||
|
||||
static int32_t SdioDeviceGetFromHandle(DevHandle handle, struct SdioDevice **sdio)
|
||||
{
|
||||
struct MmcDevice *mmc = NULL;
|
||||
|
||||
if (handle == NULL) {
|
||||
return HDF_ERR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
if (sdio == NULL) {
|
||||
return HDF_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
mmc = MmcCntlrGetDevice((struct MmcCntlr *)handle);
|
||||
if (mmc == NULL) {
|
||||
return HDF_PLT_ERR_NO_DEV;
|
||||
}
|
||||
if (mmc->type != MMC_DEV_SDIO && mmc->type != MMC_DEV_COMBO) {
|
||||
MmcDevicePut(mmc);
|
||||
return HDF_PLT_ERR_DEV_TYPE;
|
||||
}
|
||||
|
||||
*sdio = (struct SdioDevice *)mmc;
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config)
|
||||
{
|
||||
int32_t ret;
|
||||
struct MmcCntlr *cntlr = NULL;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
DevHandle handle = NULL;
|
||||
|
||||
if (config == NULL) {
|
||||
HDF_LOGE("SdioOpen: config can't be null!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle = MmcOpen(mmcBusNum);
|
||||
if (handle == NULL) {
|
||||
HDF_LOGE("SdioOpen: SdioGetCntlrByBusNum fail!");
|
||||
return NULL;
|
||||
}
|
||||
cntlr = (struct MmcCntlr *)handle;
|
||||
if (cntlr != NULL && cntlr->ops != NULL && cntlr->ops->rescanSdioDev != NULL) {
|
||||
ret = cntlr->ops->rescanSdioDev(cntlr);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioOpen: sdio rescan fail!");
|
||||
MmcClose(handle);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioOpen: get sdio dev fail!");
|
||||
MmcClose(handle);
|
||||
return NULL;
|
||||
}
|
||||
ret = SdioDeviceFindFunction(sdio, config);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioOpen: set function fail!");
|
||||
MmcClose(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (DevHandle)cntlr;
|
||||
}
|
||||
|
||||
void SdioClose(DevHandle handle)
|
||||
{
|
||||
(void)handle;
|
||||
}
|
||||
|
||||
int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioReadBytes: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceIncrAddrReadBytes(sdio, data, addr, size);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioWriteBytes: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceIncrAddrWriteBytes(sdio, data, addr, size);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data,
|
||||
uint32_t addr, uint32_t size, uint32_t scatterLen)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioReadBytesFromFixedAddr: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceFixedAddrReadBytes(sdio, data, addr, size, scatterLen);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data,
|
||||
uint32_t addr, uint32_t size, uint32_t scatterLen)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioWriteBytesToFixedAddr: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceFixedAddrWriteBytes(sdio, data, addr, size, scatterLen);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioReadBytesFromFunc0: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceFunc0ReadBytes(sdio, data, addr, size);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioWriteBytesToFunc0: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceFunc0WriteBytes(sdio, data, addr, size);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioSetBlockSize(DevHandle handle, uint32_t blockSize)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioSetBlockSize: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceSetBlockSize(sdio, blockSize);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioGetCommonInfo(DevHandle handle, SdioCommonInfo *info, SdioCommonInfoType infoType)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioGetCommonInfo: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceGetCommonInfo(sdio, info, infoType);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioSetCommonInfo(DevHandle handle, SdioCommonInfo *info, SdioCommonInfoType infoType)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioSetCommonInfo: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceSetCommonInfo(sdio, info, infoType);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioFlushData(DevHandle handle)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioFlushData: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceFlushData(sdio);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SdioClaimHost(DevHandle handle)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioClaimHost: get sdio dev fail!");
|
||||
return;
|
||||
}
|
||||
ret = SdioDeviceClaimHost(sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioClaimHost: claim host fail!");
|
||||
}
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
}
|
||||
|
||||
void SdioReleaseHost(DevHandle handle)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioReleaseHost: get sdio dev fail!");
|
||||
return;
|
||||
}
|
||||
ret = SdioDeviceReleaseHost(sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioReleaseHost: claim host fail!");
|
||||
}
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
}
|
||||
|
||||
int32_t SdioEnableFunc(DevHandle handle)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioEnableFunc: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceEnableFunc(sdio);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioDisableFunc(DevHandle handle)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioDisableFunc: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceDisableFunc(sdio);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *irqHandler)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioClaimIrq: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceClaimIrq(sdio, irqHandler);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SdioReleaseIrq(DevHandle handle)
|
||||
{
|
||||
int32_t ret;
|
||||
struct SdioDevice *sdio = NULL;
|
||||
|
||||
ret = SdioDeviceGetFromHandle(handle, &sdio);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("SdioReleaseIrq: get sdio dev fail!");
|
||||
return ret;
|
||||
}
|
||||
ret = SdioDeviceReleaseIrq(sdio);
|
||||
MmcDevicePut((struct MmcDevice *)sdio);
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user