Contiki 3.x
i2c.c
1 /*
2  * Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "contiki.h"
32 #include "i2c.h"
33 
34 #include "i2c-registers.h"
35 #include "paging.h"
36 #include "shared-isr.h"
37 #include "syscalls.h"
38 
39 #define I2C_CLOCK_SPEED 25 /* kHz */
40 #define I2C_FIFO_DEPTH 16
41 
42 #define I2C_STD_HCNT (I2C_CLOCK_SPEED * 4)
43 #define I2C_STD_LCNT (I2C_CLOCK_SPEED * 5)
44 #define I2C_FS_HCNT (I2C_CLOCK_SPEED)
45 #define I2C_FS_LCNT (I2C_CLOCK_SPEED)
46 
47 #define I2C_FS_SPKLEN_LCNT_OFFSET 8
48 #define I2C_FS_SPKLEN_HCNT_OFFSET 6
49 
50 #define I2C_POLLING_TIMEOUT (CLOCK_SECOND / 10)
51 
52 #define I2C_IRQ 9
53 
54 #if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
55 #define MMIO_SZ MIN_PAGE_SIZE
56 #else
57 #define MMIO_SZ (QUARKX1000_IC_HIGHEST + 4)
58 #endif
59 
60 typedef enum {
61  I2C_DIRECTION_READ,
62  I2C_DIRECTION_WRITE
63 } I2C_DIRECTION;
64 
65 PROT_DOMAINS_ALLOC(pci_driver_t, drv);
66 
67 struct quarkX1000_i2c_config {
68  QUARKX1000_I2C_SPEED speed;
69  QUARKX1000_I2C_ADDR_MODE addressing_mode;
70 
71  quarkX1000_i2c_callback cb_rx;
72  quarkX1000_i2c_callback cb_tx;
73  quarkX1000_i2c_callback cb_err;
74 };
75 
76 struct i2c_internal_data {
77  struct quarkX1000_i2c_config config;
78 
79  I2C_DIRECTION direction;
80 
81  uint8_t rx_len;
82  uint8_t *rx_buffer;
83  uint8_t tx_len;
84  uint8_t *tx_buffer;
85  uint8_t rx_tx_len;
86 
87  uint32_t hcnt;
88  uint32_t lcnt;
89 };
90 
91 static struct i2c_internal_data device;
92 
93 static int inited = 0;
94 
95 void quarkX1000_i2c_mmin(uint32_t offset, uint32_t *res);
96 SYSCALLS_DEFINE_SINGLETON(quarkX1000_i2c_mmin, drv,
97  uint32_t offset, uint32_t *res)
98 {
99  uint32_t *loc_res;
100 
101  PROT_DOMAINS_VALIDATE_PTR(loc_res, res, sizeof(*res));
102  if(QUARKX1000_IC_HIGHEST < offset) {
103  halt();
104  }
105 
106  prot_domains_enable_mmio();
107  PCI_MMIO_READL(drv, *loc_res, offset);
108  prot_domains_disable_mmio();
109 }
110 
111 static inline uint32_t
112 read(uint32_t offset)
113 {
114  uint32_t res;
115  quarkX1000_i2c_mmin(offset, &res);
116 
117  return res;
118 }
119 
120 void quarkX1000_i2c_mmout(uint32_t offset, uint32_t val);
121 SYSCALLS_DEFINE_SINGLETON(quarkX1000_i2c_mmout, drv,
122  uint32_t offset, uint32_t val)
123 {
124  if(QUARKX1000_IC_HIGHEST < offset) {
125  halt();
126  }
127 
128  prot_domains_enable_mmio();
129  PCI_MMIO_WRITEL(drv, offset, val);
130  prot_domains_disable_mmio();
131 }
132 
133 static inline void
134 write(uint32_t offset, uint32_t val)
135 {
136  quarkX1000_i2c_mmout(offset, val);
137 }
138 
139 static uint32_t
140 get_value(uint32_t offset, uint32_t mask, uint32_t shift)
141 {
142  uint32_t register_value = read(offset);
143 
144  register_value &= ~(0xFFFFFFFF - mask);
145 
146  return register_value >> shift;
147 }
148 
149 static void
150 set_value(uint32_t offset, uint32_t mask, uint32_t shift, uint32_t value)
151 {
152  uint32_t register_value = read(offset);
153 
154  register_value &= ~mask;
155  register_value |= value << shift;
156 
157  write(offset, register_value);
158 }
159 
160 static void
161 i2c_data_read(void)
162 {
163  uint8_t i, rx_cnt;
164 
165  if (device.rx_len == 0)
166  return;
167 
168  rx_cnt = get_value(QUARKX1000_IC_RXFLR,
169  QUARKX1000_IC_RXFLR_MASK, QUARKX1000_IC_RXFLR_SHIFT);
170 
171  if (rx_cnt > device.rx_len)
172  rx_cnt = device.rx_len;
173 
174  for (i = 0; i < rx_cnt; i++) {
175  device.rx_buffer[i] = get_value(QUARKX1000_IC_DATA_CMD,
176  QUARKX1000_IC_DATA_CMD_DAT_MASK, QUARKX1000_IC_DATA_CMD_DAT_SHIFT);
177  }
178 
179  device.rx_buffer += i;
180  device.rx_len -= i;
181 }
182 
183 static void
184 i2c_data_send(void)
185 {
186  uint32_t data = 0;
187  uint8_t i, tx_cnt;
188 
189  if (device.rx_tx_len == 0)
190  return;
191 
192  tx_cnt = I2C_FIFO_DEPTH - get_value(QUARKX1000_IC_TXFLR,
193  QUARKX1000_IC_TXFLR_MASK, QUARKX1000_IC_TXFLR_SHIFT);
194 
195  if (tx_cnt > device.rx_tx_len)
196  tx_cnt = device.rx_tx_len;
197 
198  for (i = 0; i < tx_cnt; i++) {
199  if (device.tx_len > 0) {
200  data = device.tx_buffer[i];
201 
202  if (device.tx_len == 1)
203  data |= (device.rx_len > 0) ? QUARKX1000_IC_DATA_CMD_RESTART_MASK : QUARKX1000_IC_DATA_CMD_STOP_MASK;
204 
205  device.tx_len -= 1;
206  } else {
207  data = QUARKX1000_IC_DATA_CMD_CMD_MASK;
208 
209  if (device.rx_tx_len == 1)
210  data |= QUARKX1000_IC_DATA_CMD_STOP_MASK;
211  }
212 
213  write(QUARKX1000_IC_DATA_CMD, data);
214  device.rx_tx_len -= 1;
215  }
216 
217  device.tx_buffer += i;
218 }
219 
220 static bool
221 i2c_isr(void)
222 {
223  bool handled = false;
224 
225  if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK) {
226  i2c_data_read();
227 
228  write(QUARKX1000_IC_INTR_MASK, 0);
229  read(QUARKX1000_IC_CLR_INTR);
230 
231  if (device.direction == I2C_DIRECTION_WRITE) {
232  if (device.config.cb_tx)
233  device.config.cb_tx();
234  } else {
235  if (device.config.cb_rx)
236  device.config.cb_rx();
237  }
238 
239  handled = true;
240  }
241 
242  if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK) {
243  i2c_data_send();
244  if (device.rx_tx_len <= 0) {
245  set_value(QUARKX1000_IC_INTR_MASK,
246  QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK, QUARKX1000_IC_INTR_STAT_TX_EMPTY_SHIFT, 0);
247  set_value(QUARKX1000_IC_INTR_MASK,
248  QUARKX1000_IC_INTR_STAT_STOP_DET_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT, 1);
249  }
250 
251  handled = true;
252  }
253 
254  if(read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_RX_FULL_MASK) {
255  i2c_data_read();
256 
257  handled = true;
258  }
259 
260  if (read(QUARKX1000_IC_INTR_STAT) & (QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK
261  | QUARKX1000_IC_INTR_STAT_TX_OVER_MASK | QUARKX1000_IC_INTR_STAT_RX_OVER_MASK
262  | QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK)) {
263  write(QUARKX1000_IC_INTR_MASK, 0);
264  read(QUARKX1000_IC_CLR_INTR);
265 
266  if (device.config.cb_err)
267  device.config.cb_err();
268 
269  handled = true;
270  }
271 
272  return handled;
273 }
274 
275 void
276 quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED speed,
277  QUARKX1000_I2C_ADDR_MODE addressing_mode)
278 {
279  uint32_t hcnt, lcnt;
280  uint8_t ic_fs_spklen;
281 
282  device.config.speed = speed;
283  device.config.addressing_mode = addressing_mode;
284 
285  if (device.config.speed == QUARKX1000_I2C_SPEED_STANDARD) {
286  lcnt = I2C_STD_LCNT;
287  hcnt = I2C_STD_HCNT;
288  } else {
289  lcnt = I2C_FS_LCNT;
290  hcnt = I2C_FS_HCNT;
291  }
292 
293  ic_fs_spklen = get_value(QUARKX1000_IC_FS_SPKLEN,
294  QUARKX1000_IC_FS_SPKLEN_MASK, QUARKX1000_IC_FS_SPKLEN_SHIFT);
295 
296  /* We adjust the Low Count and High Count based on the Spike Suppression Limit */
297  device.lcnt = (lcnt < (ic_fs_spklen + I2C_FS_SPKLEN_LCNT_OFFSET)) ? ic_fs_spklen + I2C_FS_SPKLEN_LCNT_OFFSET : lcnt;
298  device.hcnt = (hcnt < (ic_fs_spklen + I2C_FS_SPKLEN_HCNT_OFFSET)) ? ic_fs_spklen + I2C_FS_SPKLEN_HCNT_OFFSET : hcnt;
299 
300  /* Clear interrupts. */
301  read(QUARKX1000_IC_CLR_INTR);
302 }
303 
304 void
305 quarkX1000_i2c_set_callbacks(quarkX1000_i2c_callback rx,
306  quarkX1000_i2c_callback tx,
307  quarkX1000_i2c_callback err)
308 {
309  device.config.cb_rx = rx;
310  device.config.cb_tx = tx;
311  device.config.cb_err = err;
312 }
313 
314 static int
315 i2c_setup(void)
316 {
317  /* Clear all values */
318  write(QUARKX1000_IC_CON, 0);
319 
320  /* Clear interrupts */
321  read(QUARKX1000_IC_CLR_INTR);
322 
323  /* Quark X1000 SoC I2C only supports master mode. */
324  set_value(QUARKX1000_IC_CON,
325  QUARKX1000_IC_CON_MASTER_MODE_MASK, QUARKX1000_IC_CON_MASTER_MODE_SHIFT, 1);
326 
327  /* Set restart enable */
328  set_value(QUARKX1000_IC_CON,
329  QUARKX1000_IC_CON_RESTART_EN_MASK, QUARKX1000_IC_CON_RESTART_EN_SHIFT, 1);
330 
331  /* Set addressing mode */
332  if (device.config.addressing_mode == QUARKX1000_I2C_ADDR_MODE_10BIT) {
333  set_value(QUARKX1000_IC_CON,
334  QUARKX1000_IC_CON_10BITADDR_MASTER_MASK, QUARKX1000_IC_CON_10BITADDR_MASTER_SHIFT, 1);
335  }
336 
337  if (device.config.speed == QUARKX1000_I2C_SPEED_STANDARD) {
338  set_value(QUARKX1000_IC_SS_SCL_LCNT,
339  QUARKX1000_IC_SS_SCL_LCNT_MASK, QUARKX1000_IC_SS_SCL_LCNT_SHIFT, device.lcnt);
340  set_value(QUARKX1000_IC_SS_SCL_HCNT,
341  QUARKX1000_IC_SS_SCL_HCNT_MASK, QUARKX1000_IC_SS_SCL_HCNT_SHIFT, device.hcnt);
342  set_value(QUARKX1000_IC_CON,
343  QUARKX1000_IC_CON_SPEED_MASK, QUARKX1000_IC_CON_SPEED_SHIFT, 0x1);
344  } else {
345  set_value(QUARKX1000_IC_FS_SCL_LCNT,
346  QUARKX1000_IC_FS_SCL_LCNT_MASK, QUARKX1000_IC_FS_SCL_LCNT_SHIFT, device.lcnt);
347  set_value(QUARKX1000_IC_FS_SCL_HCNT,
348  QUARKX1000_IC_FS_SCL_HCNT_MASK, QUARKX1000_IC_FS_SCL_HCNT_SHIFT, device.hcnt);
349  set_value(QUARKX1000_IC_CON,
350  QUARKX1000_IC_CON_SPEED_MASK, QUARKX1000_IC_CON_SPEED_SHIFT, 0x2);
351  }
352 
353  return 0;
354 }
355 
356 static void
357 i2c_operation_setup(uint8_t *write_buf, uint8_t write_len,
358  uint8_t *read_buf, uint8_t read_len, uint16_t addr)
359 {
360  device.rx_len = read_len;
361  device.rx_buffer = read_buf;
362  device.tx_len = write_len;
363  device.tx_buffer = write_buf;
364  device.rx_tx_len = device.rx_len + device.tx_len;
365 
366  /* Disable controller */
367  set_value(QUARKX1000_IC_ENABLE,
368  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
369 
370  i2c_setup();
371 
372  /* Disable interrupts */
373  write(QUARKX1000_IC_INTR_MASK, 0);
374 
375  /* Clear interrupts */
376  read(QUARKX1000_IC_CLR_INTR);
377 
378  /* Set address of target slave */
379  set_value(QUARKX1000_IC_TAR,
380  QUARKX1000_IC_TAR_MASK, QUARKX1000_IC_TAR_SHIFT, addr);
381 }
382 
383 /* This is an interrupt based operation */
384 static int
385 i2c_operation(uint8_t *write_buf, uint8_t write_len,
386  uint8_t *read_buf, uint8_t read_len, uint16_t addr)
387 {
388  if (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK)
389  return -1;
390 
391  i2c_operation_setup(write_buf, write_len, read_buf, read_len, addr);
392 
393  /* Enable master TX and RX interrupts */
394  set_value(QUARKX1000_IC_INTR_MASK,
395  QUARKX1000_IC_INTR_STAT_TX_OVER_MASK, QUARKX1000_IC_INTR_STAT_TX_OVER_SHIFT, 1);
396  set_value(QUARKX1000_IC_INTR_MASK,
397  QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK, QUARKX1000_IC_INTR_STAT_TX_EMPTY_SHIFT, 1);
398  set_value(QUARKX1000_IC_INTR_MASK,
399  QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK, QUARKX1000_IC_INTR_STAT_TX_ABRT_SHIFT, 1);
400  set_value(QUARKX1000_IC_INTR_MASK,
401  QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK, QUARKX1000_IC_INTR_STAT_RX_UNDER_SHIFT, 1);
402  set_value(QUARKX1000_IC_INTR_MASK,
403  QUARKX1000_IC_INTR_STAT_RX_OVER_MASK, QUARKX1000_IC_INTR_STAT_RX_OVER_SHIFT, 1);
404  set_value(QUARKX1000_IC_INTR_MASK,
405  QUARKX1000_IC_INTR_STAT_RX_FULL_MASK, QUARKX1000_IC_INTR_STAT_RX_FULL_SHIFT, 1);
406  set_value(QUARKX1000_IC_INTR_MASK,
407  QUARKX1000_IC_INTR_STAT_STOP_DET_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT, 1);
408 
409  /* Enable controller */
410  set_value(QUARKX1000_IC_ENABLE,
411  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 1);
412 
413  return 0;
414 }
415 
416 /* This is an interrupt based write */
417 int
418 quarkX1000_i2c_write(uint8_t *buf, uint8_t len, uint16_t addr)
419 {
420  device.direction = I2C_DIRECTION_WRITE;
421  return i2c_operation(buf, len, 0, 0, addr);
422 }
423 
424 /* This is an interrupt based read */
425 int
426 quarkX1000_i2c_read(uint8_t *buf, uint8_t len, uint16_t addr)
427 {
428  device.direction = I2C_DIRECTION_READ;
429  return i2c_operation(0, 0, buf, len, addr);
430 }
431 
432 static int
433 i2c_polling_operation(uint8_t *write_buf, uint8_t write_len,
434  uint8_t *read_buf, uint8_t read_len, uint16_t addr)
435 {
436  uint32_t start_time, intr_mask_stat;
437 
438  if (!(read(QUARKX1000_IC_CON) & QUARKX1000_IC_CON_MASTER_MODE_MASK))
439  return -1;
440 
441  /* Wait i2c idle */
442  start_time = clock_seconds();
443  while (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK) {
444  if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
445  return -1;
446  }
447  }
448 
449  /* Get interrupt mask to restore in the end of polling operation */
450  intr_mask_stat = read(QUARKX1000_IC_INTR_MASK);
451 
452  i2c_operation_setup(write_buf, write_len, read_buf, read_len, addr);
453 
454  /* Enable controller */
455  set_value(QUARKX1000_IC_ENABLE,
456  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 1);
457 
458  /* Transmit */
459  if (device.tx_len != 0) {
460  while (device.tx_len > 0) {
461  start_time = clock_seconds();
462  while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_TFNF_MASK)) {
463  if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
464  set_value(QUARKX1000_IC_ENABLE,
465  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
466  return -1;
467  }
468  }
469  i2c_data_send();
470  }
471 
472  start_time = clock_seconds();
473  while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_TFE_MASK)) {
474  if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
475  set_value(QUARKX1000_IC_ENABLE,
476  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
477  return -1;
478  }
479  }
480  }
481 
482  i2c_data_send();
483 
484  /* Receive */
485  if (device.rx_len != 0) {
486  while (device.rx_len > 0) {
487  start_time = clock_seconds();
488  while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_RFNE_MASK)) {
489  if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
490  set_value(QUARKX1000_IC_ENABLE,
491  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
492  return -1;
493  }
494  }
495  i2c_data_read();
496  }
497  }
498 
499  /* Stop Det */
500  start_time = clock_seconds();
501  while (!(read(QUARKX1000_IC_RAW_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK)) {
502  if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
503  set_value(QUARKX1000_IC_ENABLE,
504  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
505  return -1;
506  }
507  }
508  read(QUARKX1000_IC_CLR_STOP_DET);
509 
510  /* Wait i2c idle */
511  start_time = clock_seconds();
512  while (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK) {
513  if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
514  set_value(QUARKX1000_IC_ENABLE,
515  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
516  return -1;
517  }
518  }
519 
520  /* Disable controller */
521  set_value(QUARKX1000_IC_ENABLE,
522  QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
523 
524  /* Restore interrupt mask */
525  write(QUARKX1000_IC_INTR_MASK, intr_mask_stat);
526 
527  return 0;
528 }
529 
530 int
531 quarkX1000_i2c_polling_write(uint8_t *buf, uint8_t len, uint16_t addr)
532 {
533  device.direction = I2C_DIRECTION_WRITE;
534  return i2c_polling_operation(buf, len, 0, 0, addr);
535 }
536 
537 int
538 quarkX1000_i2c_polling_read(uint8_t *buf, uint8_t len, uint16_t addr)
539 {
540  device.direction = I2C_DIRECTION_READ;
541  return i2c_polling_operation(0, 0, buf, len ,addr);
542 }
543 
544 int
545 quarkX1000_i2c_is_available(void)
546 {
547  return inited;
548 }
549 
550 DEFINE_SHARED_IRQ(I2C_IRQ, IRQAGENT3, INTC, PIRQC, i2c_isr);
551 
552 int
553 quarkX1000_i2c_init(void)
554 {
555  pci_config_addr_t pci_addr;
556 
557  pci_addr.raw = 0;
558  pci_addr.bus = 0;
559  pci_addr.dev = 21;
560  pci_addr.func = 2;
561  pci_addr.reg_off = PCI_CONFIG_REG_BAR0;
562 
563  pci_command_enable(pci_addr, PCI_CMD_1_MEM_SPACE_EN);
564 
565  PROT_DOMAINS_INIT_ID(drv);
566  pci_init(&drv, pci_addr, MMIO_SZ, 0, 0);
567  SYSCALLS_INIT(quarkX1000_i2c_mmin);
568  SYSCALLS_AUTHZ(quarkX1000_i2c_mmin, drv);
569  SYSCALLS_INIT(quarkX1000_i2c_mmout);
570  SYSCALLS_AUTHZ(quarkX1000_i2c_mmout, drv);
571 
572  inited = 1;
573 
574  return 0;
575 }
uint32_t func
Function number.
Definition: pci.h:89
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
PCI configuration address.
Definition: pci.h:85
uint32_t dev
Device number.
Definition: pci.h:90
uint32_t bus
Bus number.
Definition: pci.h:91
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:54
Data associated with each protection domain that is owned by clients of that domain and used to ident...
Definition: prot-domains.h:247
uint32_t reg_off
Register/offset number.
Definition: pci.h:88