238 lines
5.9 KiB
C
238 lines
5.9 KiB
C
/*
|
|
* File : drv_adc.c
|
|
* This file is part of GK710X BSP for RT-Thread distribution.
|
|
*
|
|
* Copyright (c) 2017 GOKE Microelectronics Co., Ltd.
|
|
* All rights reserved
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Visit http://www.goke.com to get contact with Goke.
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
*/
|
|
|
|
#include "drv_adc.h"
|
|
#ifdef RT_USING_ADC
|
|
#include "gtypes.h"
|
|
#include "gd_adc.h"
|
|
#include "platform.h"
|
|
|
|
#include <rtdef.h>
|
|
#include <rtthread.h>
|
|
|
|
#define GK_TEST_ADC
|
|
|
|
#define IOCTL_GET_ADC_DATA 1
|
|
#define IOCTL_ADC_POWER_DOWN 0xff
|
|
#define ADC_WRAP_BASE (0xf1200000)
|
|
#define ADC_IRQn (23)
|
|
#define ADC_MAX_CONTROLLER (1)
|
|
#define ADC_STATUS_COLESD (0)
|
|
#define ADC_STATUS_OPEN (1)
|
|
|
|
static rt_err_t gk_adc_read_data(struct wrap_adc_obj *adc, rt_uint32_t channel,
|
|
rt_uint32_t *buf)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
|
|
ret = GD_ADC_Read((GD_HANDLE*)&(adc->handle), buf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static rt_err_t gk_adc_init(rt_device_t dev)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
|
|
ret = (rt_err_t)GD_ADC_Init();
|
|
|
|
return ret;
|
|
}
|
|
|
|
static rt_err_t gk_adc_open(rt_device_t dev, rt_uint16_t oflag)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
GD_ADC_OPEN_PARAMS_S openParams;
|
|
|
|
struct wrap_adc_obj *adc_pri = (struct wrap_adc_obj *)dev->user_data;
|
|
rt_memset(&openParams, 0, sizeof(GD_ADC_OPEN_PARAMS_S));
|
|
openParams.channel = adc_pri->active_channel_no;
|
|
|
|
ret = (rt_err_t)GD_ADC_Open(&openParams, (GD_HANDLE*)&(adc_pri->handle));
|
|
|
|
return ret;
|
|
}
|
|
|
|
static rt_err_t gk_adc_close(rt_device_t dev)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
|
|
struct wrap_adc_obj *adc_pri = (struct wrap_adc_obj *)dev->user_data;
|
|
|
|
ret = (rt_err_t)GD_ADC_Close((GD_HANDLE*)(adc_pri->handle));
|
|
|
|
return ret;
|
|
}
|
|
|
|
static rt_err_t gk_adc_ioctl(rt_device_t dev, int cmd, void *arg)
|
|
{
|
|
rt_uint32_t control_reg;
|
|
struct wrap_adc_obj *adc_pri = (struct wrap_adc_obj *)dev->user_data;
|
|
rt_uint32_t ad_data;
|
|
|
|
ADC_INFO *adc_info = (ADC_INFO *)arg;
|
|
rt_err_t ret;
|
|
|
|
switch (cmd)
|
|
{
|
|
case ADC_CMD_READ_RAW_DATA:
|
|
ret = gk_adc_read_data(adc_pri, adc_info->channel, &ad_data);
|
|
if (ret != RT_EOK)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
adc_info->adc_data = ad_data;
|
|
|
|
break;
|
|
|
|
case ADC_CMD_DISABLE:
|
|
gk_adc_close(dev);
|
|
|
|
break;
|
|
|
|
default:
|
|
rt_kprintf("wrong para...\n");
|
|
return RT_EIO;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
int gk_adc_probe(void *priv_data)
|
|
{
|
|
rt_device_t adc_dev;
|
|
// check if the hw is init already...
|
|
// caution this is a read only data...if the driver want to use.malloc and
|
|
// copy it..
|
|
struct wrap_adc_obj *adc_obj = (struct wrap_adc_obj *)priv_data;
|
|
if (adc_obj->init_flag == ADC_INIT_ALREADY) return RT_EFULL;
|
|
|
|
// malloc a rt device..
|
|
adc_dev = RT_KERNEL_MALLOC(sizeof(struct rt_device));
|
|
if (!adc_dev)
|
|
{
|
|
return RT_ENOMEM;
|
|
}
|
|
rt_memset(adc_dev, 0, sizeof(struct rt_device));
|
|
rt_kprintf("id:%d\n", adc_obj->id);
|
|
|
|
// bind rtdev to obj data...
|
|
// caution ...this is used to free mem when exit....
|
|
// free step:1:get adc obj...2:free adc_obj->rt_dev->user_data..3:free
|
|
// adc_obj->rt_dev 4:adc_obj->rt_dev = NULL
|
|
adc_obj->rt_dev = adc_dev;
|
|
|
|
// malloc a private data adc use only...copy data from platform...
|
|
struct wrap_adc_obj *adc_pri =
|
|
RT_KERNEL_MALLOC(sizeof(struct wrap_adc_obj));
|
|
if (!adc_pri)
|
|
{
|
|
RT_KERNEL_FREE(adc_dev);
|
|
return RT_ENOMEM;
|
|
}
|
|
|
|
// copy platform data to pri data..
|
|
rt_memcpy(adc_pri, adc_obj, sizeof(struct wrap_adc_obj));
|
|
|
|
rt_kprintf("id:%d\n", adc_pri->id);
|
|
|
|
// bind pri data to rt_adc_dev...
|
|
adc_dev->user_data = (void *)adc_pri;
|
|
adc_dev->open = gk_adc_open;
|
|
adc_dev->close = gk_adc_close;
|
|
adc_dev->control = gk_adc_ioctl;
|
|
adc_dev->init = gk_adc_init;
|
|
adc_dev->type = RT_Device_Class_Miscellaneous;
|
|
|
|
rt_device_register(adc_dev, "adc", RT_DEVICE_FLAG_RDWR);
|
|
|
|
adc_obj->init_flag = ADC_INIT_ALREADY;
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
int gk_adc_exit(void *priv_data)
|
|
{
|
|
struct wrap_adc_obj *adc_obj = (struct wrap_adc_obj *)priv_data;
|
|
|
|
struct wrap_adc_obj *adc_pri = adc_obj->rt_dev->user_data;
|
|
|
|
RT_KERNEL_FREE(adc_obj->rt_dev->user_data);
|
|
|
|
adc_obj->rt_dev->user_data = RT_NULL;
|
|
RT_KERNEL_FREE(adc_obj->rt_dev);
|
|
adc_obj->rt_dev = RT_NULL;
|
|
|
|
GD_ADC_Exit();
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct gk_platform_driver adc_driver_ops = {
|
|
.name = "adc", .probe = gk_adc_probe, .remove = gk_adc_exit,
|
|
};
|
|
|
|
void rt_hw_adc_init(void)
|
|
{
|
|
gk_platform_driver_init(&adc_driver_ops);
|
|
}
|
|
|
|
#ifdef GK_TEST_ADC
|
|
int gk_adc_test(void)
|
|
{
|
|
rt_device_t adc_dev;
|
|
ADC_INFO info;
|
|
info.channel = 0;
|
|
info.adc_data = 0;
|
|
adc_dev = rt_device_find("adc");
|
|
if (!adc_dev)
|
|
{
|
|
rt_kprintf("cann't find the adc dev\n");
|
|
return -1;
|
|
}
|
|
adc_dev->init(adc_dev);
|
|
adc_dev->open(adc_dev, 0);
|
|
while (1)
|
|
{
|
|
adc_dev->control(adc_dev, ADC_CMD_READ_RAW_DATA, &info);
|
|
rt_kprintf("channel:%d, data:0x%x\n", info.channel, info.adc_data);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef RT_USING_FINSH
|
|
#include <finsh.h>
|
|
#ifdef GK_TEST_ADC
|
|
FINSH_FUNCTION_EXPORT(gk_adc_test, gk_adc_test);
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|