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