embox

Форк
0
188 строк · 3.8 Кб
1
/**
2
 * @file spi.c
3
 * @brief NOTE: When you use spi.core without spi.devfs
4
 * you should make sure device-specific stuff is initialized
5
 * somehow else
6
 *
7
 * @author Denis Deryugin <deryugin.denis@gmail.com>
8
 * @version
9
 * @date 03.12.2018
10
 */
11

12
#include <assert.h>
13
#include <errno.h>
14

15
#include <drivers/char_dev.h>
16
#include <drivers/spi.h>
17
#include <embox/unit.h>
18
#include <framework/mod/options.h>
19
#include <util/log.h>
20

21
/* Assume we have 4 SPI devices at most */
22
#if SPI_REGISTRY_SZ > 0
23
struct spi_device spi_device0 __attribute__((weak));
24
#endif
25
#if SPI_REGISTRY_SZ > 1
26
struct spi_device spi_device1 __attribute__((weak));
27
#endif
28
#if SPI_REGISTRY_SZ > 2
29
struct spi_device spi_device2 __attribute__((weak));
30
#endif
31
#if SPI_REGISTRY_SZ > 3
32
struct spi_device spi_device3 __attribute__((weak));
33
#endif
34
#if SPI_REGISTRY_SZ > 4
35
struct spi_device spi_device4 __attribute__((weak));
36
#endif
37
#if SPI_REGISTRY_SZ > 5
38
struct spi_device spi_device5 __attribute__((weak));
39
#endif
40

41
/* Note: it's array of pointers, not structures as usual */
42
struct spi_device *spi_device_registry[SPI_REGISTRY_SZ] = {
43
#if SPI_REGISTRY_SZ > 0
44
    &spi_device0,
45
#endif
46
#if SPI_REGISTRY_SZ > 1
47
    &spi_device1,
48
#endif
49
#if SPI_REGISTRY_SZ > 1
50
    &spi_device2,
51
#endif
52
#if SPI_REGISTRY_SZ > 1
53
    &spi_device3,
54
#endif
55
#if SPI_REGISTRY_SZ > 1
56
    &spi_device4,
57
#endif
58
#if SPI_REGISTRY_SZ > 1
59
    &spi_device5
60
#endif
61
};
62

63
/**
64
 * @brief Call device-specific init handlers for all
65
 * registered SPI devices.
66
 *
67
 * @return Always 0
68
 */
69
static int spi_init(void) {
70
	struct spi_device *dev;
71

72
	for (int i = 0; i < SPI_REGISTRY_SZ; i++) {
73
		dev = spi_device_registry[i];
74

75
		assert(dev);
76

77
		if (!dev->spi_ops) {
78
			continue;
79
		}
80

81
		if (dev->spi_ops->init) {
82
			dev->spi_ops->init(dev);
83
		}
84
		else {
85
			log_warning("SPI%d has no init funcion", i);
86
		}
87
	}
88

89
	return 0;
90
}
91
EMBOX_UNIT_INIT(spi_init);
92

93
/**
94
 * @brief Get SPI device pointer by it's ID
95
 */
96
struct spi_device *spi_dev_by_id(int id) {
97
	if (id < 0 || id >= SPI_REGISTRY_SZ) {
98
		return NULL;
99
	}
100

101
	if (spi_device_registry[id]->spi_ops != NULL) {
102
		return spi_device_registry[id];
103
	}
104
	else {
105
		return NULL;
106
	}
107
}
108

109
/**
110
 * @brief Return device ID by it's pointer
111
 */
112
int spi_dev_id(struct spi_device *dev) {
113
	for (int i = 0; i < SPI_REGISTRY_SZ; i++) {
114
		if (dev == spi_device_registry[i]
115
		    && spi_device_registry[i]->spi_ops != NULL) {
116
			return i;
117
		}
118
	}
119

120
	log_error("Wrong SPI device pointer: %p", dev);
121
	return -1;
122
}
123

124
/**
125
 * @brief Perform device-dependent SPI transfer operation
126
 *
127
 * @param dev SPI device
128
 * @param in  Data which is passed to controller
129
 * @param out Data which is received from controller
130
 * @param cnt Number of bytes to be passed
131
 *
132
 * @return Error code
133
 */
134
int spi_transfer(struct spi_device *dev, uint8_t *in, uint8_t *out, int cnt) {
135
	assert(dev);
136
	assert(dev->spi_ops);
137
	assert(in || out);
138

139
	if (dev->spi_ops->transfer == NULL) {
140
		log_debug("Transfer operation is not supported for SPI%d",
141
		    spi_dev_id(dev));
142
		return -ENOSUPP;
143
	}
144

145
	return dev->spi_ops->transfer(dev, in, out, cnt);
146
}
147

148
/**
149
 * @brief Perform device-spefic chip select operation
150
 */
151
int spi_select(struct spi_device *dev, int cs) {
152
	assert(dev);
153
	assert(dev->spi_ops);
154

155
	if (dev->spi_ops->select == NULL) {
156
		log_debug("Select operation is not supported for SPI%d",
157
		    spi_dev_id(dev));
158
		return -ENOSUPP;
159
	}
160

161
	return dev->spi_ops->select(dev, cs);
162
}
163

164
/**
165
 * @brief Set device to master or slave mode
166
 */
167
static int spi_set_mode(struct spi_device *dev, bool is_master) {
168
	assert(dev);
169
	assert(dev->spi_ops);
170

171
	if (dev->spi_ops->set_mode == NULL) {
172
		log_debug("SPI mode setting is not supported for SPI%d",
173
		    spi_dev_id(dev));
174
		return -ENOSUPP;
175
	}
176

177
	dev->is_master = is_master;
178

179
	return dev->spi_ops->set_mode(dev, is_master);
180
}
181

182
int spi_set_master_mode(struct spi_device *dev) {
183
	return spi_set_mode(dev, true);
184
}
185

186
int spi_set_slave_mode(struct spi_device *dev) {
187
	return spi_set_mode(dev, false);
188
}
189

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.