【dd2.0】Support the Core API for dd2.0 (#7791)

This commit is contained in:
ErikChanHub 2023-07-13 14:49:35 +08:00 committed by GitHub
parent 259431ace3
commit 2f5e4ac27e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1093 additions and 231 deletions

View File

@ -4,11 +4,14 @@ cwd = GetCurrentDir()
src = ['device.c']
CPPPATH = [cwd + '/../include']
if GetDepend(['RT_USING_DEV_BUS']):
if GetDepend(['RT_USING_DEV_BUS']) or GetDepend(['RT_USING_DM']):
src = src + ['bus.c']
if GetDepend(['RT_USING_DM']):
src = src + ['dm.c', 'driver.c']
src = src + ['dm.c', 'driver.c', 'platform.c']
if GetDepend(['RT_USING_OFW']):
src += ['platform_ofw.c']
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DEVICE'], CPPPATH = CPPPATH)

View File

@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2022-10-13 flybreak the first version
* 2023-04-12 ErikChan support rt_bus
*/
#include <rtthread.h>
@ -18,6 +19,18 @@
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifdef RT_USING_DM
#include <drivers/core/bus.h>
static struct rt_bus bus_root =
{
.name = "root",
.children = RT_LIST_OBJECT_INIT(bus_root.children),
};
#endif
#ifdef RT_USING_DEV_BUS
#if defined(RT_USING_POSIX_DEVIO)
#include <unistd.h>
#include <fcntl.h>
@ -78,3 +91,320 @@ rt_err_t rt_device_bus_destroy(rt_device_t dev)
LOG_D("bus destroy");
return RT_EOK;
}
#endif
#ifdef RT_USING_DM
/**
* @brief This function get the root bus
*/
rt_bus_t rt_bus_root(void)
{
return &bus_root;
}
/**
* @brief This function loop the dev_list of the bus, and call fn in each loop
*
* @param bus the target bus
*
* @param drv the target drv to be matched
*
* @param fn the function callback in each loop
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_for_each_dev(rt_bus_t bus, rt_driver_t drv, int (*fn)(rt_driver_t drv, rt_device_t dev))
{
rt_base_t level;
rt_device_t dev;
RT_ASSERT(bus != RT_NULL);
RT_ASSERT(drv != RT_NULL);
level = rt_spin_lock_irqsave(&bus->spinlock);
rt_list_for_each_entry(dev, &bus->dev_list, node)
{
fn(drv, dev);
}
rt_spin_unlock_irqrestore(&bus->spinlock, level);
return RT_EOK;
}
/**
* @brief This function loop the drv_list of the bus, and call fn in each loop
*
* @param bus the target bus
*
* @param dev the target dev to be matched
*
* @param fn the function callback in each loop
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_for_each_drv(rt_bus_t bus, rt_device_t dev, int (*fn)(rt_driver_t drv, rt_device_t dev))
{
rt_err_t err;
rt_base_t level;
rt_driver_t drv;
RT_ASSERT(bus != RT_NULL);
RT_ASSERT(dev != RT_NULL);
if (rt_list_isempty(&bus->drv_list))
{
return RT_EOK;
}
err = -RT_ERROR;
level = rt_spin_lock_irqsave(&bus->spinlock);
rt_list_for_each_entry(drv, &bus->drv_list, node)
{
if (fn(drv, dev))
{
err = -RT_EOK;
break;
}
}
rt_spin_unlock_irqrestore(&bus->spinlock, level);
return err;
}
/**
* @brief This function add a bus to the root
*
* @param bus_node the bus to be added
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_add(rt_bus_t bus_node)
{
rt_base_t level;
RT_ASSERT(bus_node != RT_NULL);
bus_node->bus = &bus_root;
rt_list_init(&bus_node->list);
level = rt_spin_lock_irqsave(&bus_node->spinlock);
rt_list_insert_before(&bus_root.children, &bus_node->list);
rt_spin_unlock_irqrestore(&bus_node->spinlock, level);
return RT_EOK;
}
/**
* @brief This function match the device and driver, probe them if match successed
*
* @param drv the drv to match/probe
*
* @param dev the dev to match/probe
*
* @return the result of probe, 1 on added successfully.
*/
static int rt_bus_probe(rt_driver_t drv, rt_device_t dev)
{
int ret = 0;
rt_bus_t bus = drv->bus;
if (!bus)
{
bus = dev->bus;
}
RT_ASSERT(bus != RT_NULL);
if (!dev->drv && bus->match(drv, dev))
{
dev->drv = drv;
ret = bus->probe(dev);
if (ret)
{
dev->drv = RT_NULL;
}
}
return ret;
}
/**
* @brief This function add a driver to the drv_list of a specific bus
*
* @param bus the bus to add
*
* @param drv the driver to be added
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_add_driver(rt_bus_t bus, rt_driver_t drv)
{
rt_base_t level;
RT_ASSERT(bus != RT_NULL);
RT_ASSERT(drv != RT_NULL);
drv->bus = bus;
level = rt_spin_lock_irqsave(&bus->spinlock);
rt_list_insert_before(&bus->drv_list, &drv->node);
rt_spin_unlock_irqrestore(&bus->spinlock, level);
rt_bus_for_each_dev(drv->bus, drv, rt_bus_probe);
return RT_EOK;
}
/**
* @brief This function add a device to the dev_list of a specific bus
*
* @param bus the bus to add
*
* @param dev the device to be added
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_add_device(rt_bus_t bus, rt_device_t dev)
{
rt_base_t level;
RT_ASSERT(bus != RT_NULL);
RT_ASSERT(dev != RT_NULL);
dev->bus = bus;
level = rt_spin_lock_irqsave(&bus->spinlock);
rt_list_insert_before(&bus->dev_list, &dev->node);
rt_spin_unlock_irqrestore(&bus->spinlock, level);
rt_bus_for_each_drv(dev->bus, dev, rt_bus_probe);
return RT_EOK;
}
/**
* @brief This function remove a driver from bus
*
* @param drv the driver to be removed
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_remove_driver(rt_driver_t drv)
{
RT_ASSERT(drv->bus != RT_NULL);
LOG_D("Bus(%s) remove driver %s", drv->bus->name, drv->name);
rt_list_remove(&drv->node);
return RT_EOK;
}
/**
* @brief This function remove a device from bus
*
* @param dev the device to be removed
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_remove_device(rt_device_t dev)
{
RT_ASSERT(dev->bus != RT_NULL);
LOG_D("Bus(%s) remove device %s", dev->bus->name, dev->name);
rt_list_remove(&dev->node);
return RT_EOK;
}
/**
* @brief This function find a bus by name
* @param bus the name to be finded
*
* @return the bus finded by name.
*/
rt_bus_t rt_bus_find_by_name(char *name)
{
rt_bus_t bus = RT_NULL;
struct rt_list_node *node = RT_NULL;
if (!rt_list_isempty(&bus_root.children))
{
rt_list_for_each(node, &bus_root.children)
{
bus = rt_list_entry(node, struct rt_bus, list);
if (!rt_strncmp(bus->name, name, RT_NAME_MAX))
{
return bus;
}
}
}
return bus;
}
/**
* @brief This function transfer dev_list and drv_list to the other bus
*
* @param new_bus the bus to transfer
*
* @param dev the target device
*
* @return the error code, RT_EOK on added successfully.
*/
rt_err_t rt_bus_reload_driver_device(rt_bus_t new_bus, rt_device_t dev)
{
rt_base_t level;
RT_ASSERT(new_bus != RT_NULL);
RT_ASSERT(dev != RT_NULL);
level = rt_spin_lock_irqsave(&new_bus->spinlock);
rt_list_remove(&dev->node);
rt_list_insert_before(&new_bus->dev_list, &dev->node);
rt_list_remove(&dev->drv->node);
rt_list_insert_before(&new_bus->drv_list, &dev->drv->node);
rt_spin_unlock_irqrestore(&new_bus->spinlock, level);
return RT_EOK;
}
/**
* @brief This function register a bus
* @param bus the bus to be registered
*
* @return the error code, RT_EOK on registeration successfully.
*/
rt_err_t rt_bus_register(rt_bus_t bus)
{
rt_list_init(&bus->children);
rt_list_init(&bus->dev_list);
rt_list_init(&bus->drv_list);
rt_spin_lock_init(&bus->spinlock);
rt_bus_add(bus);
return RT_EOK;
}
#endif

View File

@ -470,87 +470,4 @@ rt_err_t rt_device_set_tx_complete(rt_device_t dev,
}
RTM_EXPORT(rt_device_set_tx_complete);
#ifdef RT_USING_DM
/**
* This function bind drvier and device
*
* @param device the pointer of device structure
* @param driver the pointer of driver structure
* @param node the pointer of fdt node structure
*
* @return the error code, RT_EOK on successfully.
*/
rt_err_t rt_device_bind_driver(rt_device_t device, rt_driver_t driver, void *node)
{
if((!driver) || (!device))
{
return -RT_EINVAL;
}
device->drv = driver;
#ifdef RT_USING_DEVICE_OPS
device->ops = driver->dev_ops;
#endif
device->dtb_node = node;
return RT_EOK;
}
RTM_EXPORT(rt_device_bind_driver);
/**
* This function create rt_device according to driver infomation
*
* @param drv the pointer of driver structure
* @param device_id specify the ID of the rt_device
*
* @return the error code, RT_EOK on successfully.
*/
rt_device_t rt_device_create_since_driver(rt_driver_t drv,int device_id)
{
rt_device_t device;
if (!drv)
{
return RT_NULL;
}
device = (rt_device_t)rt_calloc(1,drv->device_size);
if(device == RT_NULL)
{
return RT_NULL;
}
device->device_id = device_id;
rt_snprintf(device->parent.name, sizeof(device->parent.name), "%s%d", drv->name, device_id);
return device;
}
RTM_EXPORT(rt_device_create_since_driver);
/**
* This function rt_device probe and init
*
* @param device the pointer of rt_device structure
* @return the error code, RT_EOK on successfully.
*/
rt_err_t rt_device_probe_and_init(rt_device_t device)
{
int ret = -RT_ERROR;
if (!device)
{
return -RT_EINVAL;
}
if(!device->drv)
{
return -RT_ERROR;
}
if(device->drv->probe)
{
ret = device->drv->probe((rt_device_t)device);
}
if(device->drv->probe_init)
{
ret = device->drv->probe_init((rt_device_t)device);
}
return ret;
}
RTM_EXPORT(rt_device_probe_and_init);
#endif /* RT_USING_DM */
#endif /* RT_USING_DEVICE */

View File

@ -10,7 +10,7 @@
#include <rtthread.h>
#include <drivers/core/rtdm.h>
#include <drivers/core/dm.h>
#ifdef RT_USING_SMP
static int rti_secondary_cpu_start(void)

View File

@ -5,109 +5,49 @@
*/
#include <rtthread.h>
#include <drivers/core/bus.h>
#ifdef RT_USING_DM
#ifdef RT_USING_FDT
#include <dtb_node.h>
#if defined(RT_USING_POSIX_DEVIO)
#include <rtdevice.h> /* for wqueue_init */
#endif
/**
* This function driver device match with id
* This function attach a driver to bus
*
* @param drv the pointer of driver structure
* @param device_id the id of the device
*
* @return the error code, RT_EOK on successfully.
* @param drv the driver to be attached
*/
rt_err_t rt_driver_match_with_id(const rt_driver_t drv,int device_id)
rt_err_t rt_driver_register(rt_driver_t drv)
{
rt_device_t device;
int ret;
if (!drv)
rt_err_t ret;
struct rt_bus *bus = RT_NULL;
RT_ASSERT(drv != RT_NULL);
if (drv->bus)
{
return -RT_EINVAL;
bus = drv->bus;
ret = rt_bus_add_driver(bus, drv);
}
device = rt_device_create_since_driver(drv,device_id);
if(!device)
else
{
return -RT_ERROR;
}
ret = rt_device_bind_driver(device,drv,RT_NULL);
if(ret != 0)
{
return -RT_ERROR;
}
ret = rt_device_probe_and_init(device);
if(ret != 0)
{
return -RT_ERROR;
ret = -RT_EINVAL;
}
return ret;
}
RTM_EXPORT(rt_driver_match_with_id);
RTM_EXPORT(rt_driver_register);
#ifdef RT_USING_FDT
/**
* This function driver device match with dtb_node
* This function remove driver from system.
*
* @param drv the pointer of driver structure
* @param from_node dtb node entry
* @param max_dev_num the max device support
*
* @return the error code, RT_EOK on successfully.
* @param drv the driver to be removed
*/
rt_err_t rt_driver_match_with_dtb(const rt_driver_t drv,void *from_node,int max_dev_num)
rt_err_t rt_driver_unregister(rt_driver_t drv)
{
struct dtb_node** node_list;
rt_device_t device;
int ret,i;
int total_dev_num = 0;
if ((!drv)||(!drv->dev_match)||(!drv->dev_match->compatible)||(!from_node)||(!drv->device_size))
{
return -RT_EINVAL;
}
rt_err_t ret;
node_list = rt_calloc(max_dev_num,sizeof(void *));
if(!node_list)
{
return -RT_ERROR;
}
ret = rt_bus_remove_driver(drv);
ret = dtb_node_find_all_compatible_node(from_node,drv->dev_match->compatible,node_list,max_dev_num,&total_dev_num);
if((ret != 0) || (!total_dev_num))
{
return -RT_ERROR;
}
for(i = 0; i < total_dev_num; i ++)
{
if (!dtb_node_device_is_available(node_list[i]))
{
continue;
}
device = rt_device_create_since_driver(drv,i);
if(!device)
{
continue;
}
ret = rt_device_bind_driver(device,drv,node_list[i]);
if(ret != 0)
{
continue;
}
ret = rt_device_probe_and_init(device);
if(ret != 0)
{
continue;
}
}
rt_free(node_list);
return ret;
}
RTM_EXPORT(rt_driver_match_with_dtb);
#endif /* RT_USING_FDT */
#endif /* RT_USING_DM */
RTM_EXPORT(rt_driver_register);

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-12 ErikChan the first version
*/
#include <rtthread.h>
#include <drivers/platform.h>
#include <drivers/core/bus.h>
#include <drivers/core/dm.h>
static struct rt_bus platform_bus;
/**
* @brief This function create a platform device.
*
* @param name is name of the platform device.
*
* @return a new platform device.
*/
struct rt_platform_device *rt_platform_device_alloc(const char *name)
{
struct rt_platform_device *pdev = rt_calloc(1, sizeof(*pdev));
pdev->parent.bus = &platform_bus;
pdev->name = name;
return pdev;
}
/**
* @brief This function register a rt_driver to platform bus.
*
* @return the error code, RT_EOK on successfully.
*/
rt_err_t rt_platform_driver_register(struct rt_platform_driver *pdrv)
{
RT_ASSERT(pdrv != RT_NULL);
pdrv->parent.bus = &platform_bus;
return rt_driver_register(&pdrv->parent);
}
/**
* @brief This function register a rt_device to platform bus.
*
* @return the error code, RT_EOK on successfully.
*/
rt_err_t rt_platform_device_register(struct rt_platform_device *pdev)
{
RT_ASSERT(pdev != RT_NULL);
return rt_bus_add_device(&platform_bus, &pdev->parent);
}
static rt_bool_t platform_match(rt_driver_t drv, rt_device_t dev)
{
struct rt_ofw_node *np = dev->ofw_node;
struct rt_platform_driver *pdrv = rt_container_of(drv, struct rt_platform_driver, parent);
struct rt_platform_device *pdev = rt_container_of(dev, struct rt_platform_device, parent);
if (np)
{
/* 1、match with ofw node */
pdev->id = rt_ofw_node_match(np, pdrv->ids);
return !!pdev->id;
}
else if (pdev->name && pdrv->name)
{
/* 2、match with name */
if (pdev->name == pdrv->name)
{
return RT_TRUE;
}
else
{
return !rt_strcmp(pdrv->name, pdev->name);
}
}
return RT_FALSE;
}
static rt_err_t platform_probe(rt_device_t dev)
{
rt_err_t err;
struct rt_ofw_node *np = dev->ofw_node;
struct rt_platform_driver *pdrv = rt_container_of(dev->drv, struct rt_platform_driver, parent);
struct rt_platform_device *pdev = rt_container_of(dev, struct rt_platform_device, parent);
err = pdrv->probe(pdev);
if (!err)
{
if (np)
{
rt_ofw_node_set_flag(np, RT_OFW_F_READLY);
}
}
else
{
if (np)
{
rt_ofw_data(np) = &pdev->parent;
}
}
return err;
}
static struct rt_bus platform_bus =
{
.name = "platform",
.match = platform_match,
.probe = platform_probe,
};
static int platform_bus_init(void)
{
rt_bus_register(&platform_bus);
return 0;
}
INIT_CORE_EXPORT(platform_bus_init);

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-06-04 GuEe-GUI the first version
*/
#include <rtthread.h>
#define DBG_TAG "drv.platform"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <drivers/platform.h>
#include <drivers/core/dm.h>
static const struct rt_ofw_node_id platform_ofw_ids[] =
{
{ .compatible = "simple-bus", },
#ifdef RT_USING_MFD
{ .compatible = "simple-mfd", },
#endif
#ifdef RT_USING_ISA
{ .compatible = "isa", },
#endif
#ifdef RT_USING_AMBA_BUS
/*
* Maybe ARM has replaced it with compatible: "arm,primecell" and will not
* used anymore in the future.
*/
{ .compatible = "arm,amba-bus", },
#endif
{ /* sentinel */ }
};
static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
{
rt_err_t err = RT_EOK;
struct rt_ofw_node *np, *child;
struct rt_platform_device *pdev;
rt_ofw_foreach_available_child_node(parent_np, np)
{
const char *name;
struct rt_ofw_node_id *id;
struct rt_ofw_prop *compat_prop = RT_NULL;
/* Is system node or have driver */
if (rt_ofw_node_test_flag(np, RT_OFW_F_SYSTEM) ||
rt_ofw_node_test_flag(np, RT_OFW_F_READLY))
{
continue;
}
compat_prop = rt_ofw_get_prop(np, "compatible", RT_NULL);
name = rt_ofw_node_name(np);
/* Not have name and compatible */
if (!compat_prop && (name == (const char *)"<NULL>" || !rt_strcmp(name, "<NULL>")))
{
continue;
}
id = rt_ofw_prop_match(compat_prop, platform_ofw_ids);
if (id && (child = rt_ofw_get_next_child(np, RT_NULL)))
{
/* scan next level */
err = platform_ofw_device_probe_once(child);
rt_ofw_node_put(child);
if (err)
{
LOG_E("%s bus probe fail", np->full_name);
break;
}
}
pdev = rt_platform_device_alloc(np->name);
if (!pdev)
{
err = -RT_ENOMEM;
break;
}
/* inc reference of dt-node */
rt_ofw_node_get(np);
rt_ofw_node_set_flag(np, RT_OFW_F_PLATFORM);
pdev->parent.ofw_node = np;
rt_platform_device_register(pdev);
}
return err;
}
static int platform_ofw_device_probe(void)
{
rt_err_t err = RT_EOK;
struct rt_ofw_node *root_np;
root_np = rt_ofw_find_node_by_path("/");
if (root_np)
{
err = platform_ofw_device_probe_once(root_np);
rt_ofw_node_put(root_np);
}
else
{
err = -RT_ENOSYS;
}
return (int)err;
}
INIT_PLATFORM_EXPORT(platform_ofw_device_probe);

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-12 ErikChan the first version
*/
#ifndef __BUS_H__
#define __BUS_H__
#include <rthw.h>
#include <drivers/core/device.h>
#include <drivers/core/driver.h>
typedef struct rt_bus *rt_bus_t;
struct rt_bus
{
struct rt_object parent; /**< inherit from rt_object */
char *name;
struct rt_bus *bus;
rt_list_t list;
rt_list_t children;
rt_list_t dev_list;
rt_list_t drv_list;
struct rt_spinlock spinlock;
rt_bool_t (*match)(rt_driver_t drv, rt_device_t dev);
rt_err_t (*probe)(rt_device_t dev);
};
rt_bus_t rt_bus_root(void);
rt_err_t rt_bus_for_each_dev(rt_bus_t bus, rt_driver_t drv, int (*fn)(rt_driver_t drv, rt_device_t dev));
rt_err_t rt_bus_for_each_drv(rt_bus_t bus, rt_device_t dev, int (*fn)(rt_driver_t drv, rt_device_t dev));
rt_err_t rt_bus_add(rt_bus_t bus);
rt_err_t rt_bus_add_driver(rt_bus_t bus, rt_driver_t drv);
rt_err_t rt_bus_add_device(rt_bus_t bus, rt_device_t dev);
rt_err_t rt_bus_remove_driver(rt_driver_t drv);
rt_err_t rt_bus_remove_device(rt_device_t dev);
rt_bus_t rt_bus_find_by_name(char *name);
rt_err_t rt_bus_reload_driver_device(rt_bus_t new_bus, rt_device_t dev);
rt_err_t rt_bus_register(rt_bus_t bus);
#endif /* __BUS_H__ */

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-12 ErikChan the first version
*/
#ifndef __DEVICE_H__
#define __DEVICE_H__
#include <rtdef.h>
typedef struct rt_driver *rt_driver_t;
typedef struct rt_device *rt_device_t;
/**
* Notify structure
*/
struct rt_device_notify
{
void (*notify)(rt_device_t dev);
struct rt_device *dev;
};
/**
* Device structure
*/
struct rt_device
{
struct rt_object parent; /**< inherit from rt_object */
rt_list_t node;
struct rt_bus *bus;
void *priv;
#ifdef RT_USING_DM
rt_driver_t drv;
void *ofw_node;
#endif
enum rt_device_class_type type; /**< device type */
rt_uint16_t flag; /**< device flag */
rt_uint16_t open_flag; /**< device open flag */
rt_uint8_t ref_count; /**< reference count */
rt_uint8_t device_id; /**< 0 - 255 */
/* device call back */
rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);
rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);
#ifdef RT_USING_DEVICE_OPS
const struct rt_device_ops *ops;
#else
/* common device interface */
rt_err_t (*init) (rt_device_t dev);
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
rt_err_t (*close) (rt_device_t dev);
rt_ssize_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
rt_ssize_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
#endif /* RT_USING_DEVICE_OPS */
#ifdef RT_USING_POSIX_DEVIO
const struct dfs_file_ops *fops;
struct rt_wqueue wait_queue;
#endif /* RT_USING_POSIX_DEVIO */
void *user_data; /**< device private data */
};
#ifdef RT_USING_DEVICE_OPS
/**
* operations set for device object
*/
struct rt_device_ops
{
/* common device interface */
rt_err_t (*init) (rt_device_t dev);
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
rt_err_t (*close) (rt_device_t dev);
rt_ssize_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
rt_ssize_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
};
#endif /* RT_USING_DEVICE_OPS */
#endif /* __DEVICE_H__ */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-20 ErikChan the first version
*/
#ifndef __RT_DM_H__
#define __RT_DM_H__
#include <rthw.h>
#include <rtdef.h>
#include <drivers/misc.h>
#include <drivers/byteorder.h>
#ifndef RT_CPUS_NR
#define RT_CPUS_NR 1
#endif
#ifndef RT_USING_SMP
extern int rt_hw_cpu_id(void);
#endif
void rt_dm_secondary_cpu_init(void);
int rt_dm_set_dev_name_auto(rt_device_t dev, const char *prefix);
int rt_dm_get_dev_name_id(rt_device_t dev);
int rt_dm_set_dev_name(rt_device_t dev, const char *format, ...);
const char *rt_dm_get_dev_name(rt_device_t dev);
#endif /* __RT_DM_H__ */

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-12 ErikChan the first version
*/
#ifndef __DRIVER_H__
#define __DRIVER_H__
#include <drivers/core/device.h>
struct rt_driver
{
struct rt_bus *bus;
rt_list_t node;
#ifdef RT_USING_DEVICE_OPS
const struct rt_device_ops *dev_ops;
#else
/* common device interface */
rt_err_t (*init) (rt_device_t dev);
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
rt_err_t (*close) (rt_device_t dev);
rt_ssize_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
rt_ssize_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
#endif
const struct filesystem_ops *fops;
const char *name;
int (*probe)(struct rt_device *dev);
int (*remove)(struct rt_device *dev);
void *priv;
};
int rt_driver_probe_device(struct rt_driver *drv, struct rt_device *dev);
rt_err_t rt_driver_register(rt_driver_t drv);
rt_err_t rt_driver_unregister(rt_driver_t drv);
#define RT_DRIVER_EXPORT(driver, bus_name, mode) \
static int ___##driver##_register(void) \
{ \
rt_##bus_name##_driver_register(&driver); \
return 0; \
} \
INIT_DEVICE_EXPORT(___##driver##_register); \
#endif /* __DRIVER_H__ */

View File

@ -15,7 +15,7 @@
#include <bitmap.h>
#include <drivers/ofw.h>
#include <drivers/core/rtdm.h>
#include <drivers/core/dm.h>
struct rt_pci_msi_desc;
struct rt_pci_msi_msg;

View File

@ -170,7 +170,7 @@ extern "C" {
#endif
#ifdef RT_USING_DM
#include "drivers/core/rtdm.h"
#include "drivers/core/dm.h"
#ifdef RT_USING_OFW
#include "drivers/ofw.h"

View File

@ -13,7 +13,7 @@
#include <drivers/ofw_fdt.h>
#include <drivers/ofw_raw.h>
#include <drivers/core/rtdm.h>
#include <drivers/core/dm.h>
#define DBG_TAG "rtdm.ofw"
#define DBG_LVL DBG_INFO
@ -79,14 +79,13 @@ rt_uint64_t rt_fdt_translate_address(void *fdt, int nodeoffset, rt_uint64_t addr
int addr_cells;
int size_cells;
} local, cpu;
int parent, length, group_len;
int parent, length = 0, group_len;
const fdt32_t *ranges = RT_NULL;
parent = fdt_parent_offset(fdt, nodeoffset);
if (parent >= 0)
{
length = 0;
ranges = fdt_getprop(fdt, nodeoffset, "ranges", &length);
}

View File

@ -54,9 +54,9 @@ static rt_list_t _traps_nodes = RT_LIST_OBJECT_INIT(_traps_nodes);
static struct rt_pic_irq *irq2pirq(int irq)
{
struct rt_pic_irq *pirq;
struct rt_pic_irq *pirq = RT_NULL;
if (irq >= 0 && irq < MAX_HANDLERS)
if ((irq >= 0) && (irq < MAX_HANDLERS))
{
pirq = &_pirq_hash[irq];
@ -453,7 +453,7 @@ rt_err_t rt_pic_do_traps(void)
rt_err_t rt_pic_handle_isr(struct rt_pic_irq *pirq)
{
rt_err_t err;
rt_err_t err = RT_EOK;
rt_list_t *handler_nodes;
struct rt_irq_desc *action;
@ -547,49 +547,101 @@ rt_err_t rt_pic_irq_finit(void)
return err;
}
#define _irq_call_helper(irq, fn) \
({ \
struct rt_pic_irq *pirq; \
if ((pirq = irq2pirq(irq))) \
{ \
rt_spin_lock(&pirq->rw_lock); \
if (pirq->pic->ops->fn) \
pirq->pic->ops->fn(pirq); \
rt_spin_unlock(&pirq->rw_lock); \
} \
})
void rt_pic_irq_enable(int irq)
{
_irq_call_helper(irq, irq_enable);
struct rt_pic_irq *pirq = irq2pirq(irq);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (pirq->pic->ops->irq_enable)
{
pirq->pic->ops->irq_enable(pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_disable(int irq)
{
_irq_call_helper(irq, irq_disable);
struct rt_pic_irq *pirq = irq2pirq(irq);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (pirq->pic->ops->irq_disable)
{
pirq->pic->ops->irq_disable(pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_ack(int irq)
{
_irq_call_helper(irq, irq_ack);
struct rt_pic_irq *pirq = irq2pirq(irq);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (pirq->pic->ops->irq_ack)
{
pirq->pic->ops->irq_ack(pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_mask(int irq)
{
_irq_call_helper(irq, irq_mask);
struct rt_pic_irq *pirq = irq2pirq(irq);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (pirq->pic->ops->irq_mask)
{
pirq->pic->ops->irq_mask(pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_unmask(int irq)
{
_irq_call_helper(irq, irq_unmask);
struct rt_pic_irq *pirq = irq2pirq(irq);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (pirq->pic->ops->irq_unmask)
{
pirq->pic->ops->irq_unmask(pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_eoi(int irq)
{
_irq_call_helper(irq, irq_eoi);
}
struct rt_pic_irq *pirq = irq2pirq(irq);
#undef _irq_call_helper
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (pirq->pic->ops->irq_eoi)
{
pirq->pic->ops->irq_eoi(pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
rt_err_t rt_pic_irq_set_priority(int irq, rt_uint32_t priority)
{
@ -747,58 +799,145 @@ void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask)
}
}
#define _pirq_parent_call_helper(ppic, pirq, fn, ret,...) \
({ \
if (ppic && pirq) \
{ \
rt_spin_lock(&pirq->rw_lock); \
if (ppic->ops->fn) \
{ \
struct rt_pic *cpic; \
cpic = pirq->pic; /* push old pic */ \
pirq->pic = ppic; \
ret ppic->ops->fn(pirq __VA_ARGS__); \
pirq->pic = cpic; /* pop old pic */ \
} \
rt_spin_unlock(&pirq->rw_lock); \
} \
})
#define _pic_push(stack, pirq, ppic) struct rt_pic *(stack) = (pirq)->pic; (pirq)->pic = ppic;
#define _pic_pop(stack, pirq) (pirq)->pic = (stack)
void rt_pic_irq_parent_enable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
{
_pirq_parent_call_helper(ppic, pirq, irq_enable,,);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_enable)
{
_pic_push(pic_stack, pirq, ppic);
ppic->ops->irq_enable(pirq);
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_parent_disable(struct rt_pic *ppic, struct rt_pic_irq *pirq)
{
_pirq_parent_call_helper(ppic, pirq, irq_disable,,);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_disable)
{
_pic_push(pic_stack, pirq, ppic);
ppic->ops->irq_disable(pirq);
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_parent_ack(struct rt_pic *ppic, struct rt_pic_irq *pirq)
{
_pirq_parent_call_helper(ppic, pirq, irq_ack,,);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_ack)
{
_pic_push(pic_stack, pirq, ppic);
ppic->ops->irq_ack(pirq);
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_parent_mask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
{
_pirq_parent_call_helper(ppic, pirq, irq_mask,,);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_mask)
{
_pic_push(pic_stack, pirq, ppic);
ppic->ops->irq_mask(pirq);
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_parent_unmask(struct rt_pic *ppic, struct rt_pic_irq *pirq)
{
_pirq_parent_call_helper(ppic, pirq, irq_unmask,,);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_unmask)
{
_pic_push(pic_stack, pirq, ppic);
ppic->ops->irq_unmask(pirq);
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
void rt_pic_irq_parent_eoi(struct rt_pic *ppic, struct rt_pic_irq *pirq)
{
_pirq_parent_call_helper(ppic, pirq, irq_eoi,,);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_eoi)
{
_pic_push(pic_stack, pirq, ppic);
ppic->ops->irq_eoi(pirq);
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
}
rt_err_t rt_pic_irq_parent_set_priority(struct rt_pic *ppic, struct rt_pic_irq *pirq, rt_uint32_t priority)
{
rt_err_t err = -RT_ENOSYS;
_pirq_parent_call_helper(ppic, pirq, irq_set_priority, err = , ,priority);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_set_priority)
{
_pic_push(pic_stack, pirq, ppic);
if (!(err = ppic->ops->irq_set_priority(pirq, priority)))
{
pirq->priority = priority;
}
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
return err;
}
@ -807,7 +946,24 @@ rt_err_t rt_pic_irq_parent_set_affinity(struct rt_pic *ppic, struct rt_pic_irq *
{
rt_err_t err = -RT_ENOSYS;
_pirq_parent_call_helper(ppic, pirq, irq_set_affinity, err = , ,affinity);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_set_affinity)
{
_pic_push(pic_stack, pirq, ppic);
if (!(err = ppic->ops->irq_set_affinity(pirq, affinity)))
{
rt_memcpy(pirq->affinity, affinity, sizeof(pirq->affinity));
}
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
return err;
}
@ -816,12 +972,30 @@ rt_err_t rt_pic_irq_parent_set_triger_mode(struct rt_pic *ppic, struct rt_pic_ir
{
rt_err_t err = -RT_ENOSYS;
_pirq_parent_call_helper(ppic, pirq, irq_set_triger_mode, err = , ,mode);
RT_ASSERT(ppic != RT_NULL);
RT_ASSERT(pirq != RT_NULL);
rt_spin_lock(&pirq->rw_lock);
if (ppic->ops->irq_set_triger_mode)
{
_pic_push(pic_stack, pirq, ppic);
if (!(err = ppic->ops->irq_set_triger_mode(pirq, mode)))
{
pirq->mode = mode;
}
_pic_pop(pic_stack, pirq);
}
rt_spin_unlock(&pirq->rw_lock);
return err;
}
#undef _pirq_parent_call_helper
#undef _pic_push
#undef _pic_pop
#ifdef RT_USING_OFW
RT_OFW_STUB_RANGE_EXPORT(pic, _pic_ofw_start, _pic_ofw_end);

View File

@ -318,6 +318,17 @@ typedef int (*init_fn_t)(void);
/* board init routines will be called in board_init() function */
#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
/* init cpu, memory, interrupt-controller, bus... */
#define INIT_CORE_EXPORT(fn) INIT_EXPORT(fn, "1.0")
/* init pci/pcie, usb platform driver... */
#define INIT_FRAMEWORK_EXPORT(fn) INIT_EXPORT(fn, "1.1")
/* init platform, user code... */
#define INIT_PLATFORM_EXPORT(fn) INIT_EXPORT(fn, "1.2")
/* init sys-timer, clk, pinctrl... */
#define INIT_SUBSYS_EXPORT(fn) INIT_EXPORT(fn, "1.3")
/* init early drivers */
#define INIT_DRIVER_EARLY_EXPORT(fn) INIT_EXPORT(fn, "1.4")
/* pre/device/component/env/app init routines will be called in init_thread */
/* components pre-initialization (pure software initialization) */
#define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2")
@ -330,6 +341,11 @@ typedef int (*init_fn_t)(void);
/* application initialization (rtgui application etc ...) */
#define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6")
/* init after mount fs */
#define INIT_FS_EXPORT(fn) INIT_EXPORT(fn, "6.0")
/* init in secondary_cpu_c_start */
#define INIT_SECONDARY_CPU_EXPORT(fn) INIT_EXPORT(fn, "7")
#if !defined(RT_USING_FINSH)
/* define these to empty, even if not include finsh.h file */
#define FINSH_FUNCTION_EXPORT(name, desc)

View File

@ -602,14 +602,7 @@ rt_ssize_t rt_device_write(rt_device_t dev,
const void *buffer,
rt_size_t size);
rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg);
#ifdef RT_USING_DM
rt_err_t rt_device_bind_driver(rt_device_t device, rt_driver_t driver, void *node);
rt_device_t rt_device_create_since_driver(rt_driver_t drv,int device_id);
rt_err_t rt_device_probe_and_init(rt_device_t device);
rt_err_t rt_driver_match_with_id(const rt_driver_t drv,int device_id);
rt_err_t rt_driver_match_with_dtb(const rt_driver_t drv,void *from_node,int max_dev_num);
#endif
/**@}*/
#endif