1 /*
2  * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * @file	device.h
9  * @brief	Bus abstraction for libmetal.
10  */
11 
12 #ifndef __METAL_BUS__H__
13 #define __METAL_BUS__H__
14 
15 #include <stdint.h>
16 #include <metal/io.h>
17 #include <metal/list.h>
18 #include <metal/dma.h>
19 #include <metal/sys.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /** \defgroup device Bus Abstraction
26  *  @{
27  */
28 
29 #ifndef METAL_MAX_DEVICE_REGIONS
30 #define METAL_MAX_DEVICE_REGIONS	32
31 #endif
32 
33 struct metal_bus;
34 struct metal_device;
35 
36 /** Bus operations. */
37 struct metal_bus_ops {
38 	void		(*bus_close)(struct metal_bus *bus);
39 	int		(*dev_open)(struct metal_bus *bus,
40 				    const char *dev_name,
41 				    struct metal_device **device);
42 	void		(*dev_close)(struct metal_bus *bus,
43 				     struct metal_device *device);
44 	void		(*dev_irq_ack)(struct metal_bus *bus,
45 				       struct metal_device *device,
46 				       int irq);
47 	int		(*dev_dma_map)(struct metal_bus *bus,
48 				       struct metal_device *device,
49 				       uint32_t dir,
50 				       struct metal_sg *sg_in,
51 				       int nents_in,
52 				       struct metal_sg *sg_out);
53 	void		(*dev_dma_unmap)(struct metal_bus *bus,
54 					 struct metal_device *device,
55 					 uint32_t dir,
56 					 struct metal_sg *sg,
57 					 int nents);
58 };
59 
60 /** Libmetal bus structure. */
61 struct metal_bus {
62 	const char		*name;
63 	struct metal_bus_ops	ops;
64 	struct metal_list	devices;
65 	struct metal_list	node;
66 };
67 
68 /** Libmetal generic bus. */
69 extern struct metal_bus metal_generic_bus;
70 
71 /** Libmetal device structure. */
72 struct metal_device {
73 	const char             *name;       /**< Device name */
74 	struct metal_bus       *bus;        /**< Bus that contains device */
75 	unsigned int           num_regions; /**< Number of I/O regions in
76 						 device */
77 	struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of
78 							I/O regions in device*/
79 	struct metal_list      node;       /**< Node on bus' list of devices */
80 	int                    irq_num;    /**< Number of IRQs per device */
81 	void                   *irq_info;  /**< IRQ ID */
82 };
83 
84 /**
85  * @brief	Register a libmetal bus.
86  * @param[in]	bus	Pre-initialized bus structure.
87  * @return 0 on success, or -errno on failure.
88  */
89 int metal_bus_register(struct metal_bus *bus);
90 
91 /**
92  * @brief	Unregister a libmetal bus.
93  * @param[in]	bus	Pre-registered bus structure.
94  * @return 0 on success, or -errno on failure.
95  */
96 int metal_bus_unregister(struct metal_bus *bus);
97 
98 /**
99  * @brief	Find a libmetal bus by name.
100  * @param[in]	name	Bus name.
101  * @param[out]	bus	Returned bus handle.
102  * @return 0 on success, or -errno on failure.
103  */
104 int metal_bus_find(const char *name, struct metal_bus **bus);
105 
106 /**
107  * @brief	Statically register a generic libmetal device.
108  *
109  * In non-Linux systems, devices are always required to be statically
110  * registered at application initialization.
111  * In Linux system, devices can be dynamically opened via sysfs or libfdt based
112  * enumeration at runtime.
113  * This interface is used for static registration of devices. Subsequent calls
114  * to metal_device_open() look up in this list of pre-registered devices on the
115  * "generic" bus.
116  * "generic" bus is used on non-Linux system to group the memory mapped devices.
117  *
118  * @param[in]	device	Generic device.
119  * @return 0 on success, or -errno on failure.
120  */
121 int metal_register_generic_device(struct metal_device *device);
122 
123 /**
124  * @brief	Open a libmetal device by name.
125  * @param[in]	bus_name	Bus name.
126  * @param[in]	dev_name	Device name.
127  * @param[out]	device		Returned device handle.
128  * @return 0 on success, or -errno on failure.
129  */
130 int metal_device_open(const char *bus_name, const char *dev_name,
131 		      struct metal_device **device);
132 
133 /**
134  * @brief	Close a libmetal device.
135  * @param[in]	device		Device handle.
136  */
137 void metal_device_close(struct metal_device *device);
138 
139 /**
140  * @brief	Get an I/O region accessor for a device region.
141  *
142  * @param[in]	device		Device handle.
143  * @param[in]	index		Region index.
144  * @return I/O accessor handle, or NULL on failure.
145  */
146 static inline struct metal_io_region *
metal_device_io_region(struct metal_device * device,unsigned int index)147 metal_device_io_region(struct metal_device *device, unsigned int index)
148 {
149 	return (index < device->num_regions
150 		? &device->regions[index]
151 		: NULL);
152 }
153 
154 /** @} */
155 
156 #ifdef METAL_INTERNAL
157 int metal_generic_dev_sys_open(struct metal_device *dev);
158 int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name,
159 			   struct metal_device **device);
160 int metal_generic_dev_dma_map(struct metal_bus *bus,
161 			      struct metal_device *device,
162 			      uint32_t dir, struct metal_sg *sg_in,
163 			      int nents_in, struct metal_sg *sg_out);
164 void metal_generic_dev_dma_unmap(struct metal_bus *bus,
165 				 struct metal_device *device,
166 				 uint32_t dir, struct metal_sg *sg, int nents);
167 #endif /* METAL_INTERNAL */
168 
169 #ifdef __cplusplus
170 }
171 #endif
172 
173 #endif /* __METAL_BUS__H__ */
174