embox

Форк
0
/
imx6_ecspi.c 
151 строка · 4.1 Кб
1
/**
2
 * @file
3
 * @brief i.MX6 Enhanced Configurable SPI driver
4
 * @author Denis Deryugin <deryugin.denis@gmail.com>
5
 * @version 0.1
6
 * @date 12.06.2017
7
 */
8

9
#include <drivers/gpio/gpio.h>
10
#include <drivers/spi.h>
11
#include <embox/unit.h>
12
#include <errno.h>
13
#include <assert.h>
14
#include <hal/reg.h>
15
#include <util/log.h>
16

17
#include "imx6_ecspi.h"
18

19
#define ECSPI_RXDATA(dev)                 ((dev)->base_addr + 0x00)
20
#define ECSPI_TXDATA(dev)                 ((dev)->base_addr + 0x04)
21
#define ECSPI_CONREG(dev)                 ((dev)->base_addr + 0x08)
22
# define ECSPI_CONREG_EN                  (1 << 0)
23
# define ECSPI_CONREG_XCH                 (1 << 2)
24
# define ECSPI_CONREG_BURST_LENGTH_OFFT   20
25
# define ECSPI_CONREG_BURST_LENGTH_MASK   0xFFF00000
26
# define ECSPI_CONREG_CHANNEL_SELECT_OFFT 18
27
# define ECSPI_CONREG_CHANNEL_SELECT_MASK 0x000C0000
28
#define ECSPI_CONFIGREG(dev)              ((dev)->base_addr + 0x0C)
29
#define ECSPI_INTREG(devv)                ((dev)->base_addr + 0x10)
30
#define ECSPI_DMAREG(dev)                 ((dev)->base_addr + 0x14)
31
#define ECSPI_STATREG(dev)                ((dev)->base_addr + 0x18)
32
# define ECSPI_STATREG_RR                 (1 << 3)
33
#define ECSPI_PERIODREG(dev)              ((dev)->base_addr + 0x1C)
34
#define ECSPI_TESTREG(dev)                ((dev)->base_addr + 0x20)
35
#define ECSPI_MSGDATA(dev)                ((dev)->base_addr + 0x40)
36

37
#define TIMEOUT_LIMIT		100000
38

39
#define SPI_FIFO_LEN		64
40

41
static void imx6_ecspi_show_regs(struct imx6_ecspi *dev) {
42
	log_debug("SPI Registers:");
43
	log_debug("ECSPI_CONREG    = 0x%08x", REG32_LOAD(ECSPI_CONREG(dev)));
44
	log_debug("ECSPI_CONFIGREG = 0x%08x", REG32_LOAD(ECSPI_CONFIGREG(dev)));
45
	log_debug("ECSPI_STATREG   = 0x%08x", REG32_LOAD(ECSPI_STATREG(dev)));
46
}
47

48
int imx6_ecspi_init(struct imx6_ecspi *dev) {
49
	/* Disable SPI block */
50
	REG32_CLEAR(ECSPI_CONREG(dev), ECSPI_CONREG_EN);
51
	/* Enable clocks */
52
	/* Put SPI out of reset */
53
	REG32_ORIN(ECSPI_CONREG(dev), ECSPI_CONREG_EN);
54

55
	/* IOMUX configuration */
56
	/* Configure ECSPI as a master */
57
	REG32_ORIN(ECSPI_CONREG(dev), 0xF << 4);
58
	/* Set burst length to 8 bits so we work with bytes */
59
	REG32_CLEAR(ECSPI_CONREG(dev), ECSPI_CONREG_BURST_LENGTH_MASK);
60
	REG32_ORIN(ECSPI_CONREG(dev), 7 << ECSPI_CONREG_BURST_LENGTH_OFFT);
61

62
	/* Set default speed */
63
	REG32_ORIN(ECSPI_CONREG(dev), 0x2 << 12);
64

65
	/* SCLK_CTL */
66
	REG32_ORIN(ECSPI_CONFIGREG(dev), 0xf << 20);
67
	/* DATA_CTL */
68
	REG32_ORIN(ECSPI_CONFIGREG(dev), 0xf << 16);
69
	/* SCLK_POL */
70
	REG32_ORIN(ECSPI_CONFIGREG(dev), 0xf << 4);
71
	/* SCLK_PHA */
72
	REG32_ORIN(ECSPI_CONFIGREG(dev), 0xf << 0);
73

74
	imx6_ecspi_show_regs(dev);
75

76
	return 0;
77
}
78

79
static void imx6_ecspi_set_cs(struct imx6_ecspi *dev, int state) {
80
	int gpio_n = 0;
81
	int port = 0;
82

83
	assert(dev->cs < dev->cs_count);
84

85
	REG32_CLEAR(ECSPI_CONREG(dev), ECSPI_CONREG_CHANNEL_SELECT_MASK);
86
	REG32_ORIN(ECSPI_CONREG(dev), dev->cs << ECSPI_CONREG_CHANNEL_SELECT_OFFT);
87

88
	gpio_n = dev->cs_array[dev->cs][0];
89
	port   = dev->cs_array[dev->cs][1];
90

91
	gpio_set(gpio_n, 1 << port, state);
92
}
93

94
static uint8_t imx6_ecspi_transfer_byte(struct imx6_ecspi *dev, uint8_t val) {
95
	int timeout;
96

97
	REG32_STORE(ECSPI_TXDATA(dev), val);
98
	REG32_ORIN(ECSPI_CONREG(dev), ECSPI_CONREG_XCH);
99

100
	timeout = TIMEOUT_LIMIT;
101
	while ((REG32_LOAD(ECSPI_CONREG(dev)) & ECSPI_CONREG_XCH) && timeout--);
102

103
	if (timeout == 0)
104
		log_debug("transmit timeout");
105

106
	return REG32_LOAD(ECSPI_RXDATA(dev));
107
}
108

109
static int imx6_ecspi_select(struct spi_device *dev, int cs) {
110
	struct imx6_ecspi *priv = dev->priv;
111

112
	if (cs < 0 || cs > priv->cs_count) {
113
		log_error("Only cs=0..%d are available!", priv->cs_count - 1);
114
		return -EINVAL;
115
	}
116

117
	priv->cs = cs;
118

119
	return 0;
120
}
121

122
static int imx6_ecspi_transfer(struct spi_device *dev, uint8_t *inbuf,
123
		uint8_t *outbuf, int count) {
124
	struct imx6_ecspi *priv = dev->priv;
125
	uint8_t val;
126

127
	if (dev->flags & SPI_CS_ACTIVE) {
128
		imx6_ecspi_set_cs(priv, 0);
129
	}
130

131
	while (count--) {
132
		val = inbuf ? *inbuf++ : 0;
133
		log_debug("tx %02x", val);
134
		val = imx6_ecspi_transfer_byte(priv, val);
135

136
		log_debug("rx %02x", val);
137
		if (outbuf)
138
			*outbuf++ = val;
139
	}
140

141
	if (dev->flags & SPI_CS_INACTIVE) {
142
		imx6_ecspi_set_cs(priv, 1);
143
	}
144

145
	return 0;
146
}
147

148
struct spi_ops imx6_ecspi_ops = {
149
	.select   = imx6_ecspi_select,
150
	.transfer = imx6_ecspi_transfer
151
};
152

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

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

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

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