1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include "spi.h"
#include "gpio.h"
#include "register.h"
#define WRITE_SPI_REG(spi, reg, value) (WRITE_REGISTER(spi_base_addresses[spi], reg, value))
#define READ_SPI_REG(spi, reg) (READ_REGISTER(spi_base_addresses[spi], reg))
enum spi_register {
TASKS_START = 0x10,
TASKS_STOP = 0x14,
TASKS_SUSPEND = 0x1c,
TASKS_RESUME = 0x20,
EVENTS_STOPPED = 0x104,
EVENTS_ENDRX = 0x110,
EVENTS_END = 0x118,
EVENTS_ENDTX = 0x120,
EVENTS_STARTED = 0x14c,
SHORTS = 0x200,
INTENSET = 0x304,
INTENCLR = 0x308,
ENABLE = 0x500,
PSEL_SCK = 0x508,
PSEL_MOSI = 0x50c,
PSEL_MISO = 0x510,
FREQUENCY = 0x524,
RXD_PTR = 0x534,
RXD_MAXCNT = 0x538,
RXD_AMOUNT = 0x53c,
RXD_LIST = 0x540,
TXD_PTR = 0x544,
TXD_MAXCNT = 0x548,
TXD_AMOUNT = 0x54c,
TXD_LIST = 0x550,
CONFIG = 0x544,
ORC = 0x5c0,
};
static const hwaddr spi_base_addresses[] = {
[SPI_0] = 0x40003000,
[SPI_1] = 0x40004000,
[SPI_2] = 0x40023000,
};
static const u32 frequency_register_values[] = {
[K125] = 0x02000000,
[K250] = 0x04000000,
[K500] = 0x08000000,
[M1] = 0x10000000,
[M2] = 0x20000000,
[M4] = 0x40000000,
[M8] = 0x80000000,
};
void spi_master_init(enum spi_interface spi, enum gpio_pin clock, enum gpio_pin mosi, enum gpio_pin miso, enum spi_bits_order order, enum spi_clock_polarity polarity, enum spi_clock_phase phase, enum spi_frequency frequency, char overread_char) {
/* Setup GPIO pins */
gpio_output_pin_init(clock, S0S1);
WRITE_SPI_REG(spi, PSEL_SCK, (0xffffffff >> 1) & (0xffffffe0 | clock));
gpio_output_pin_init(mosi, S0S1);
WRITE_SPI_REG(spi, PSEL_MOSI, (0xffffffff >> 1) & (0xffffffe0 | mosi));
gpio_input_pin_init(miso, PULL_DOWN, HIGH);
WRITE_SPI_REG(spi, PSEL_MISO, (0xffffffff >> 1) & (0xffffffe0 | miso));
/* Configure communication behaviour */
u32 spi_config = 0x0;
spi_config |= order;
spi_config |= phase << 1;
spi_config |= polarity << 2;
WRITE_SPI_REG(spi, CONFIG, spi_config);
WRITE_SPI_REG(spi, RXD_MAXCNT, MAX_TRANSFER_SIZE);
WRITE_SPI_REG(spi, TXD_MAXCNT, MAX_TRANSFER_SIZE);
WRITE_SPI_REG(spi, FREQUENCY, frequency_register_values[frequency]);
WRITE_SPI_REG(spi, ORC, overread_char);
/* Enable SPI Master */
WRITE_SPI_REG(spi, ENABLE, 0x7);
}
u8 spi_master_transfer(enum spi_interface spi, u8 tx_size, u8 tx[], u8 rx_size, u8 rx[]) {
u32 events_started_reg = 0;
u32 events_end_reg = 0;
WRITE_SPI_REG(spi, RXD_MAXCNT, rx_size & 0xff);
WRITE_SPI_REG(spi, TXD_MAXCNT, tx_size & 0xff);
WRITE_SPI_REG(spi, RXD_PTR, (hwaddr) rx);
WRITE_SPI_REG(spi, TXD_PTR, (hwaddr) tx);
WRITE_SPI_REG(spi, TASKS_START, 0x1);
do {
events_started_reg = READ_SPI_REG(spi, EVENTS_STARTED);
} while (events_started_reg == 0);
do {
events_end_reg = READ_SPI_REG(spi, EVENTS_END);
} while (events_end_reg == 0);
return 0;
}
void spi_master_stop(enum spi_interface spi, enum gpio_pin clock, enum gpio_pin mosi, enum gpio_pin miso) {
u32 events_stopped_reg = 0;
WRITE_SPI_REG(spi, TASKS_STOP, 0x1);
do {
events_stopped_reg = READ_SPI_REG(spi, EVENTS_STOPPED);
} while (events_stopped_reg == 0);
/* Disable SPI*/
WRITE_SPI_REG(spi, ENABLE, 0x0);
/* Set configuration registers to reset values */
WRITE_SPI_REG(spi, CONFIG, 0x0);
WRITE_SPI_REG(spi, RXD_MAXCNT, 0x0);
WRITE_SPI_REG(spi, TXD_MAXCNT, 0x0);
WRITE_SPI_REG(spi, FREQUENCY, frequency_register_values[K250]);
WRITE_SPI_REG(spi, ORC, 0x0);
/* Free GPIO pins */
WRITE_SPI_REG(spi, PSEL_SCK, 0xffffffff);
gpio_pin_disable(clock);
WRITE_SPI_REG(spi, PSEL_MOSI, 0xffffffff);
gpio_pin_disable(mosi);
WRITE_SPI_REG(spi, PSEL_MISO, 0xffffffff);
gpio_pin_disable(miso);
}
|