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