blob: 12eacc80cc15ca7605c9562ca98e7767f3d23fa4 [file] [log] [blame]
Tomasz Bursztykad96943b2015-08-21 13:01:08 +03001/* intel_spi.c - Driver implementation for Intel SPI controller */
2
3/*
4 * Copyright (c) 2015 Intel Corporation.
5 *
Javier B Perez Hernandezf7fffae2015-10-06 11:00:37 -05006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
Tomasz Bursztykad96943b2015-08-21 13:01:08 +03009 *
Javier B Perez Hernandezf7fffae2015-10-06 11:00:37 -050010 * http://www.apache.org/licenses/LICENSE-2.0
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030011 *
Javier B Perez Hernandezf7fffae2015-10-06 11:00:37 -050012 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030017 */
18
19#include <nanokernel.h>
20#include <arch/cpu.h>
21
22#include <misc/__assert.h>
23#include <board.h>
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +030024#include <init.h>
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030025
26#include <sys_io.h>
27
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030028#include <spi.h>
29#include <spi/intel_spi.h>
30#include "intel_spi_priv.h"
31
Daniel Leungc71dddb2015-12-10 09:52:56 -080032#ifdef CONFIG_IOAPIC
33#include <drivers/ioapic.h>
34#endif
35
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030036#ifndef CONFIG_SPI_DEBUG
Dan Kalowsky39063592015-10-14 13:34:31 -070037#define DBG(...) { ; }
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030038#else
39#if defined(CONFIG_STDOUT_CONSOLE)
40#include <stdio.h>
41#define DBG printf
42#else
43#include <misc/printk.h>
44#define DBG printk
45#endif /* CONFIG_STDOUT_CONSOLE */
46#endif /* CONFIG_SPI_DEBUG */
47
48#define DEFINE_MM_REG_READ(__reg, __off, __sz) \
49 static inline uint32_t read_##__reg(uint32_t addr) \
50 { \
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030051 return sys_read##__sz(addr + __off); \
52 }
53#define DEFINE_MM_REG_WRITE(__reg, __off, __sz) \
54 static inline void write_##__reg(uint32_t data, uint32_t addr) \
55 { \
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030056 sys_write##__sz(data, addr + __off); \
57 }
58
59DEFINE_MM_REG_WRITE(sscr0, INTEL_SPI_REG_SSCR0, 32)
shuang.he@intel.comf6d62ec2015-10-16 11:02:26 -040060DEFINE_MM_REG_WRITE(sscr1, INTEL_SPI_REG_SSCR1, 32)
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030061DEFINE_MM_REG_READ(sssr, INTEL_SPI_REG_SSSR, 32)
62DEFINE_MM_REG_READ(ssdr, INTEL_SPI_REG_SSDR, 32)
63DEFINE_MM_REG_WRITE(ssdr, INTEL_SPI_REG_SSDR, 32)
64DEFINE_MM_REG_WRITE(dds_rate, INTEL_SPI_REG_DDS_RATE, 32)
65
66#define DEFINE_SET_BIT_OP(__reg_bit, __reg_off, __bit) \
67 static inline void set_bit_##__reg_bit(uint32_t addr) \
68 { \
69 sys_set_bit(addr + __reg_off, __bit); \
70 }
71
72#define DEFINE_CLEAR_BIT_OP(__reg_bit, __reg_off, __bit) \
73 static inline void clear_bit_##__reg_bit(uint32_t addr) \
74 { \
75 sys_clear_bit(addr + __reg_off, __bit); \
76 }
77
78#define DEFINE_TEST_BIT_OP(__reg_bit, __reg_off, __bit) \
79 static inline int test_bit_##__reg_bit(uint32_t addr) \
80 { \
81 return sys_test_bit(addr + __reg_off, __bit); \
82 }
83
84DEFINE_SET_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT)
85DEFINE_CLEAR_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT)
86DEFINE_TEST_BIT_OP(sscr0_sse, INTEL_SPI_REG_SSCR0, INTEL_SPI_SSCR0_SSE_BIT)
87DEFINE_TEST_BIT_OP(sssr_bsy, INTEL_SPI_REG_SSSR, INTEL_SPI_SSSR_BSY_BIT)
shuang.he@intel.comf6d62ec2015-10-16 11:02:26 -040088DEFINE_CLEAR_BIT_OP(sscr1_tie, INTEL_SPI_REG_SSCR1, INTEL_SPI_SSCR1_TIE_BIT)
Tomasz Bursztyka9b936712015-11-03 19:28:36 +020089DEFINE_TEST_BIT_OP(sscr1_tie, INTEL_SPI_REG_SSCR1, INTEL_SPI_SSCR1_TIE_BIT)
90DEFINE_CLEAR_BIT_OP(sssr_ror, INTEL_SPI_REG_SSSR, INTEL_SPI_SSSR_ROR_BIT)
Tomasz Bursztykad96943b2015-08-21 13:01:08 +030091
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +030092#ifdef CONFIG_SPI_INTEL_CS_GPIO
93
94#include <gpio.h>
95
96static inline void _spi_config_cs(struct device *dev)
97{
98 struct spi_intel_config *info = dev->config->config_info;
99 struct spi_intel_data *spi = dev->driver_data;
100 struct device *gpio;
101
102 gpio = device_get_binding(info->cs_gpio_name);
103 if (!gpio) {
104 spi->cs_gpio_port = NULL;
105 return;
106 }
107
108 gpio_pin_configure(gpio, info->cs_gpio_pin, GPIO_DIR_OUT);
109 /* Default CS line to high (idling) */
110 gpio_pin_write(gpio, info->cs_gpio_pin, 1);
111
112 spi->cs_gpio_port = gpio;
113}
114
115static inline void _spi_control_cs(struct device *dev, int on)
116{
117 struct spi_intel_config *info = dev->config->config_info;
118 struct spi_intel_data *spi = dev->driver_data;
119
120 if (!spi->cs_gpio_port) {
121 return;
122 }
123
124 gpio_pin_write(spi->cs_gpio_port, info->cs_gpio_pin, !on);
125}
126#else
Dan Kalowsky39063592015-10-14 13:34:31 -0700127#define _spi_control_cs(...) { ; }
128#define _spi_config_cs(...) { ; }
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +0300129#endif /* CONFIG_SPI_INTEL_CS_GPIO */
130
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300131static void completed(struct device *dev, uint32_t error)
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300132{
133 struct spi_intel_config *info = dev->config->config_info;
134 struct spi_intel_data *spi = dev->driver_data;
135 enum spi_cb_type cb_type;
136
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300137 if (error) {
138 cb_type = SPI_CB_ERROR;
139 goto out;
140 }
141
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200142 if (spi->tx_buf == spi->tx_buf_end && !spi->rx_buf) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300143 cb_type = SPI_CB_WRITE;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200144 } else if (spi->rx_buf == spi->rx_buf_end && !spi->tx_buf) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300145 cb_type = SPI_CB_READ;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200146 } else if (spi->tx_buf == spi->tx_buf_end &&
147 spi->rx_buf == spi->rx_buf_end) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300148 cb_type = SPI_CB_TRANSCEIVE;
149 } else {
150 return;
151 }
152
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300153out:
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200154 spi->tx_buf = spi->rx_buf = spi->tx_buf_end = spi->rx_buf_end = NULL;
155 spi->t_len = spi->r_buf_len = 0;
156
157 _spi_control_cs(dev, 0);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300158
159 write_sscr1(spi->sscr1, info->regs);
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300160 clear_bit_sscr0_sse(info->regs);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300161
162 if (spi->callback) {
Tomasz Bursztyka524a50e2015-10-05 18:02:16 +0300163 spi->callback(dev, cb_type, spi->user_data);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300164 }
165}
166
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200167static void pull_data(struct device *dev)
168{
169 struct spi_intel_config *info = dev->config->config_info;
170 struct spi_intel_data *spi = dev->driver_data;
171 uint32_t cnt = 0;
172 uint8_t data = 0;
173
174 while (read_sssr(info->regs) & INTEL_SPI_SSSR_RNE) {
175 data = (uint8_t) read_ssdr(info->regs);
176 cnt++;
177
178 if (spi->rx_buf < spi->rx_buf_end) {
179 *(uint8_t *)(spi->rx_buf) = data;
180 spi->rx_buf++;
181 }
182 }
183
184 DBG("Pulled: %d (total: %d)\n",
185 cnt, spi->r_buf_len - (spi->rx_buf_end - spi->rx_buf));
186}
187
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300188static void push_data(struct device *dev)
189{
190 struct spi_intel_config *info = dev->config->config_info;
191 struct spi_intel_data *spi = dev->driver_data;
192 uint32_t cnt = 0;
193 uint8_t data;
194
Dan Kalowsky39063592015-10-14 13:34:31 -0700195 while (read_sssr(info->regs) & INTEL_SPI_SSSR_TNF) {
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200196 if (spi->tx_buf < spi->tx_buf_end) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300197 data = *(uint8_t *)(spi->tx_buf);
198 spi->tx_buf++;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200199 } else if (spi->t_len + cnt < spi->r_buf_len) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300200 data = 0;
201 } else {
202 /* Nothing to push anymore for now */
203 break;
204 }
205
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300206 cnt++;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200207 DBG("Pushing 1 byte (total: %d)\n", cnt);
208 write_ssdr(data, info->regs);
209
210 pull_data(dev);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300211 }
212
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300213 spi->t_len += cnt;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200214 DBG("Pushed: %d (total: %d)\n", cnt, spi->t_len);
Tomasz Bursztykaad35e5d2015-09-11 14:23:21 +0300215
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200216 if (spi->tx_buf == spi->tx_buf_end) {
Tomasz Bursztykaad35e5d2015-09-11 14:23:21 +0300217 clear_bit_sscr1_tie(info->regs);
218 }
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300219}
220
Tomasz Bursztyka524a50e2015-10-05 18:02:16 +0300221static int spi_intel_configure(struct device *dev,
222 struct spi_config *config, void *user_data)
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300223{
224 struct spi_intel_config *info = dev->config->config_info;
225 struct spi_intel_data *spi = dev->driver_data;
226 uint32_t flags = config->config;
227 uint32_t mode;
228
229 DBG("spi_intel_configure: %p (0x%x), %p\n", dev, info->regs, config);
230
231 /* Check status */
232 if (test_bit_sscr0_sse(info->regs) && test_bit_sssr_bsy(info->regs)) {
233 DBG("spi_intel_transceive: Controller is busy\n");
234 return DEV_USED;
235 }
236
237 /* Pre-configuring the registers to a clean state*/
238 spi->sscr0 = spi->sscr1 = 0;
239 write_sscr0(spi->sscr0, info->regs);
240 write_sscr1(spi->sscr1, info->regs);
241
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200242 DBG("spi_intel_configure: WS: %d, DDS_RATE: 0x%x SCR: %d\n",
243 SPI_WORD_SIZE_GET(flags),
Tomasz Bursztyka75a11272015-10-23 15:04:02 +0300244 INTEL_SPI_DSS_RATE(config->max_sys_freq),
245 INTEL_SPI_SSCR0_SCR(config->max_sys_freq) >> 8);
Tomasz Bursztyka15058e22015-10-09 17:14:58 +0300246
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300247 /* Word size and clock rate */
248 spi->sscr0 = INTEL_SPI_SSCR0_DSS(SPI_WORD_SIZE_GET(flags)) |
249 INTEL_SPI_SSCR0_SCR(config->max_sys_freq);
250
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200251 /* Tx/Rx thresholds
252 * Note: Rx thresholds needs to be 1, it does not seem to be able
253 * to trigger reliably any interrupt with another value though the
254 * rx fifo would be full
255 */
256 spi->sscr1 |= INTEL_SPI_SSCR1_TFT(INTEL_SPI_SSCR1_TFT_DFLT) |
257 INTEL_SPI_SSCR1_RFT(INTEL_SPI_SSCR1_RFT_DFLT);
258
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300259 /* SPI mode */
260 mode = SPI_MODE(flags);
261 if (mode & SPI_MODE_CPOL) {
262 spi->sscr1 |= INTEL_SPI_SSCR1_SPO;
263 }
264
265 if (mode & SPI_MODE_CPHA) {
266 spi->sscr1 |= INTEL_SPI_SSCR1_SPH;
267 }
268
269 if (mode & SPI_MODE_LOOP) {
270 spi->sscr1 |= INTEL_SPI_SSCR1_LBM;
271 }
272
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300273 /* Configuring the rate */
274 write_dds_rate(INTEL_SPI_DSS_RATE(config->max_sys_freq), info->regs);
275
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200276 spi->tx_buf = spi->tx_buf_end = spi->rx_buf = spi->rx_buf_end = NULL;
277 spi->t_len = spi->r_buf_len = 0;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300278 spi->callback = config->callback;
Tomasz Bursztyka524a50e2015-10-05 18:02:16 +0300279 spi->user_data = user_data;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300280
281 return DEV_OK;
282}
283
284static int spi_intel_transceive(struct device *dev,
285 uint8_t *tx_buf, uint32_t tx_buf_len,
286 uint8_t *rx_buf, uint32_t rx_buf_len)
287{
288 struct spi_intel_config *info = dev->config->config_info;
289 struct spi_intel_data *spi = dev->driver_data;
290
291 DBG("spi_dw_transceive: %p, %p, %u, %p, %u\n",
292 dev, tx_buf, tx_buf_len, rx_buf, rx_buf_len);
293
294 /* Check status */
295 if (test_bit_sscr0_sse(info->regs) && test_bit_sssr_bsy(info->regs)) {
296 DBG("spi_intel_transceive: Controller is busy\n");
297 return DEV_USED;
298 }
299
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200300 /* Flushing recv fifo */
301 spi->rx_buf = spi->rx_buf_end = NULL;
302 pull_data(dev);
303
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300304 /* Set buffers info */
305 spi->tx_buf = tx_buf;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200306 spi->tx_buf_end = tx_buf + tx_buf_len;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300307 spi->rx_buf = rx_buf;
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200308 spi->rx_buf_end = rx_buf + rx_buf_len;
309 spi->r_buf_len = rx_buf_len;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300310
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +0300311 _spi_control_cs(dev, 1);
312
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200313 /* Enabling the controller */
314 write_sscr0(spi->sscr0 | INTEL_SPI_SSCR0_SSE, info->regs);
315
316 /* Installing the registers */
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300317 write_sscr1(spi->sscr1 | INTEL_SPI_SSCR1_RIE |
318 INTEL_SPI_SSCR1_TIE, info->regs);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300319
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300320 return DEV_OK;
321}
322
323static int spi_intel_suspend(struct device *dev)
324{
325 struct spi_intel_config *info = dev->config->config_info;
326
327 DBG("spi_intel_suspend: %p\n", dev);
328
329 clear_bit_sscr0_sse(info->regs);
330 irq_disable(info->irq);
331
332 return DEV_OK;
333}
334
335static int spi_intel_resume(struct device *dev)
336{
337 struct spi_intel_config *info = dev->config->config_info;
338
339 DBG("spi_intel_resume: %p\n", dev);
340
341 set_bit_sscr0_sse(info->regs);
342 irq_enable(info->irq);
343
344 return DEV_OK;
345}
346
347void spi_intel_isr(void *arg)
348{
349 struct device *dev = arg;
350 struct spi_intel_config *info = dev->config->config_info;
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300351 uint32_t error = 0;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300352 uint32_t status;
353
354 DBG("spi_intel_isr: %p\n", dev);
355
356 status = read_sssr(info->regs);
357
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300358 if (status & INTEL_SPI_SSSR_ROR) {
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200359 /* Unrecoverable error, ack it */
360 clear_bit_sssr_ror(info->regs);
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300361 error = 1;
362 goto out;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300363 }
364
Tomasz Bursztykaded73a42015-10-08 17:48:23 +0300365 if (status & INTEL_SPI_SSSR_RFS) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300366 pull_data(dev);
367 }
368
Tomasz Bursztyka9b936712015-11-03 19:28:36 +0200369 if (test_bit_sscr1_tie(info->regs)) {
370 if (status & INTEL_SPI_SSSR_TFS) {
371 push_data(dev);
372 }
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300373 }
Tomasz Bursztyka9d0af1c2015-09-08 11:26:12 +0300374out:
375 completed(dev, error);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300376}
377
378static struct spi_driver_api intel_spi_api = {
379 .configure = spi_intel_configure,
380 .slave_select = NULL,
381 .transceive = spi_intel_transceive,
382 .suspend = spi_intel_suspend,
383 .resume = spi_intel_resume,
384};
385
386#ifdef CONFIG_PCI
387static inline int spi_intel_setup(struct device *dev)
388{
389 struct spi_intel_config *info = dev->config->config_info;
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300390
391 pci_bus_scan_init();
392
Tomasz Bursztykae4479cd2015-08-25 19:41:42 +0300393 if (!pci_bus_scan(&info->pci_dev)) {
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300394 DBG("Could not find device\n");
395 return 0;
396 }
397
Tomasz Bursztykae4479cd2015-08-25 19:41:42 +0300398#ifdef CONFIG_PCI_ENUMERATION
399 info->regs = info->pci_dev.addr;
400 info->irq = info->pci_dev.irq;
401#endif
Tomasz Bursztykad2669b72015-10-07 16:24:18 +0300402
Tomasz Bursztykae4479cd2015-08-25 19:41:42 +0300403 pci_enable_regs(&info->pci_dev);
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300404
Tomasz Bursztykae4479cd2015-08-25 19:41:42 +0300405 pci_show(&info->pci_dev);
Tomasz Bursztykaff3f81b2015-08-25 21:45:14 +0300406
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300407 return 1;
408}
409#else
Tomasz Bursztyka3e32b292015-08-27 11:04:41 +0300410#define spi_intel_setup(_unused_) (1)
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300411#endif /* CONFIG_PCI */
412
413int spi_intel_init(struct device *dev)
414{
415 struct spi_intel_config *info = dev->config->config_info;
416
417 dev->driver_api = &intel_spi_api;
418
419 if (!spi_intel_setup(dev)) {
420 return DEV_NOT_CONFIG;
421 }
422
Andrew Boied9cfbd52016-01-08 00:46:14 -0800423 info->config_func();
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300424
Tomasz Bursztykaf18275a2015-10-08 14:15:28 +0300425 _spi_config_cs(dev);
426
Tomasz Bursztykad96943b2015-08-21 13:01:08 +0300427 irq_enable(info->irq);
428
429 DBG("SPI Intel Driver initialized on device: %p\n", dev);
430
431 return DEV_OK;
432}
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700433
Daniel Leungc71dddb2015-12-10 09:52:56 -0800434#ifdef CONFIG_IOAPIC
435 #if defined(CONFIG_SPI_INTEL_FALLING_EDGE)
436 #define SPI_INTEL_IRQ_FLAGS (IOAPIC_EDGE | IOAPIC_LOW)
437 #elif defined(CONFIG_SPI_INTEL_RISING_EDGE)
438 #define SPI_INTEL_IRQ_FLAGS (IOAPIC_EDGE | IOAPIC_HIGH)
439 #elif defined(CONFIG_SPI_INTEL_LEVEL_HIGH)
440 #define SPI_INTEL_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_HIGH)
441 #elif defined(CONFIG_SPI_INTEL_LEVEL_LOW)
442 #define SPI_INTEL_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW)
443 #endif
444#else
445 #define SPI_INTEL_IRQ_FLAGS 0
446#endif /* CONFIG_IOAPIC */
447
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700448/* system bindings */
449#ifdef CONFIG_SPI_INTEL_PORT_0
450
Andrew Boied9cfbd52016-01-08 00:46:14 -0800451void spi_config_0_irq(void);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700452
453struct spi_intel_data spi_intel_data_port_0;
454
455struct spi_intel_config spi_intel_config_0 = {
456 .regs = CONFIG_SPI_INTEL_PORT_0_REGS,
457 .irq = CONFIG_SPI_INTEL_PORT_0_IRQ,
458#if CONFIG_PCI
Javier B Perez Hernandez02812f42015-12-29 16:34:58 -0600459 .pci_dev.class_type = CONFIG_SPI_INTEL_CLASS,
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700460 .pci_dev.bus = CONFIG_SPI_INTEL_PORT_0_BUS,
461 .pci_dev.dev = CONFIG_SPI_INTEL_PORT_0_DEV,
462 .pci_dev.vendor_id = CONFIG_SPI_INTEL_VENDOR_ID,
463 .pci_dev.device_id = CONFIG_SPI_INTEL_DEVICE_ID,
464 .pci_dev.function = CONFIG_SPI_INTEL_PORT_0_FUNCTION,
465#endif
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +0300466#ifdef CONFIG_SPI_INTEL_CS_GPIO
467 .cs_gpio_name = CONFIG_SPI_INTEL_PORT_0_CS_GPIO_PORT,
468 .cs_gpio_pin = CONFIG_SPI_INTEL_PORT_0_CS_GPIO_PIN,
469#endif
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700470 .config_func = spi_config_0_irq
471};
472
473DECLARE_DEVICE_INIT_CONFIG(spi_intel_port_0, CONFIG_SPI_INTEL_PORT_0_DRV_NAME,
474 spi_intel_init, &spi_intel_config_0);
475
Dmitriy Korovkin57f27412015-10-26 15:56:02 -0400476/* SPI may use GPIO pin for CS, thus it needs to be initialized after GPIO */
477SYS_DEFINE_DEVICE(spi_intel_port_0, &spi_intel_data_port_0, SECONDARY,
478 CONFIG_SPI_INTEL_INIT_PRIORITY);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700479
Andrew Boied9cfbd52016-01-08 00:46:14 -0800480void spi_config_0_irq(void)
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700481{
Andrew Boied9cfbd52016-01-08 00:46:14 -0800482 irq_connect(CONFIG_SPI_INTEL_PORT_0_IRQ, CONFIG_SPI_INTEL_PORT_0_PRI,
483 spi_intel_isr, SYS_GET_DEVICE(spi_intel_port_0),
484 SPI_INTEL_IRQ_FLAGS);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700485}
486
487#endif /* CONFIG_SPI_INTEL_PORT_0 */
488#ifdef CONFIG_SPI_INTEL_PORT_1
489
Andrew Boied9cfbd52016-01-08 00:46:14 -0800490void spi_config_1_irq(void);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700491
492struct spi_intel_data spi_intel_data_port_1;
493
494struct spi_intel_config spi_intel_config_1 = {
495 .regs = CONFIG_SPI_INTEL_PORT_1_REGS,
496 .irq = CONFIG_SPI_INTEL_PORT_1_IRQ,
497#if CONFIG_PCI
Javier B Perez Hernandez02812f42015-12-29 16:34:58 -0600498 .pci_dev.class_type = CONFIG_SPI_INTEL_CLASS,
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700499 .pci_dev.bus = CONFIG_SPI_INTEL_PORT_1_BUS,
500 .pci_dev.dev = CONFIG_SPI_INTEL_PORT_1_DEV,
501 .pci_dev.function = CONFIG_SPI_INTEL_PORT_1_FUNCTION,
502 .pci_dev.vendor_id = CONFIG_SPI_INTEL_VENDOR_ID,
503 .pci_dev.device_id = CONFIG_SPI_INTEL_DEVICE_ID,
504#endif
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +0300505#ifdef CONFIG_SPI_INTEL_CS_GPIO
Tomasz Bursztyka95116ab2015-10-15 13:01:03 +0300506 .cs_gpio_name = CONFIG_SPI_INTEL_PORT_1_CS_GPIO_PORT,
507 .cs_gpio_pin = CONFIG_SPI_INTEL_PORT_1_CS_GPIO_PIN,
Tomasz Bursztyka4cace6d2015-09-24 12:42:37 +0300508#endif
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700509 .config_func = spi_config_1_irq
510};
511
512DECLARE_DEVICE_INIT_CONFIG(spi_intel_port_1, CONFIG_SPI_INTEL_PORT_1_DRV_NAME,
513 spi_intel_init, &spi_intel_config_1);
514
Dmitriy Korovkin57f27412015-10-26 15:56:02 -0400515/* SPI may use GPIO pin for CS, thus it needs to be initialized after GPIO */
516SYS_DEFINE_DEVICE(spi_intel_port_1, &spi_intel_data_port_1, SECONDARY,
517 CONFIG_SPI_INTEL_INIT_PRIORITY);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700518
Andrew Boied9cfbd52016-01-08 00:46:14 -0800519void spi_config_1_irq(void);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700520{
Andrew Boied9cfbd52016-01-08 00:46:14 -0800521 irq_connect(CONFIG_SPI_INTEL_PORT_1_IRQ, CONFIG_SPI_INTEL_PORT_1_PRI,
522 spi_intel_isr, SYS_GET_DEVICE(spi_intel_port_1),
523 SPI_INTEL_IRQ_FLAGS);
Dirk Brandewief4ded7a2015-09-17 06:32:31 -0700524}
525
526#endif /* CONFIG_SPI_INTEL_PORT_1 */