blob: d6f36feb0854967714b13d1d2a082c16c076b9d0 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30/*
31 * bcmos_system.h
32 * Maple System Services
33 * posix port: simulation
34 */
35
36#ifndef BCMOS_SYSTEM_H_
37#define BCMOS_SYSTEM_H_
38#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/types.h>
41#include <linux/string.h>
42#include <linux/stddef.h>
43#include <linux/skbuff.h>
44#include <linux/mutex.h>
45#include <linux/spinlock.h>
46#include <linux/semaphore.h>
47#include <linux/interrupt.h>
48#include <linux/kthread.h>
49#include <linux/compiler.h>
50#include <linux/random.h>
51#include <linux/ctype.h>
52#include <linux/time.h>
53#include <asm/io.h>
54
55#define BCMOS_IRQ_SINGLE 0
56#define BCMOS_IRQ_SHARED IRQF_SHARED
57
58/* Re-define GNU typeof as ISO __typeof__ */
59#define typeof __typeof__
60
61#define strtol(s,p,b) simple_strtol(s,p,b)
62
63/* Specify here which system functions are inlined */
64
65#define BCMOS_FASTLOCK_INLINE
66#define BCMOS_SEM_INLINE
67#define BCMOS_MUTEX_INLINE
68
69#ifdef ENABLE_LOG
70#define BCMOS_TRACE_IN_DEV_LOG
71#endif
72
73#if !defined(BCMOS_TRACE_IN_DEV_LOG) && !defined(BCMOS_TRACE_PRINTF)
74#define BCMOS_TRACE_PRINTF
75#endif
76
77/* #define BCMOS_BYTE_POOL_ALLOC_FREE_INLINE */
78#define BCMOS_MALLOC_FREE_INLINE
79/* #define BCMOS_CALLOC_INLINE */
80#define BCMOS_BUF_OS_SPECIFIC
81#define BCMOS_BUF_INLINE
82#define BCMOS_INTERRUPT_INLINE
83#define BCMOS_TIMESTAMP_INLINE
84/* #define BCMOS_DMA_ALLOC_FREE_INLINE */
85#define BCMOS_VIRT_TO_PHYS_INLINE
86#define BCMOS_CACHE_INLINE
87/* Uncommentthe following line if h/w supports DMA cache coherency */
88/* #define BCMOS_DMA_CACHE_COHERENCY */
89
90/* getchar, putchar are not support. define as inline and proviude dummy targets */
91#define BCMOS_GETCHAR_INLINE
92#define BCMOS_PUTCHAR_INLINE
93
94#include "bcmos_common.h"
95
96static inline void bcm_pci_write32(volatile uint32_t *address, uint32_t value)
97{
98 writel(value, address);
99}
100
101static inline uint32_t bcm_pci_read32(const volatile uint32_t *address)
102{
103 return readl(address);
104}
105
106
107void _bcmos_backtrace(void);
108int bcmos_sys_vprintf(const char *format, va_list args);
109
110/*
111 * Memory allocation
112 */
113
114/* Allocate DMAable memory from the main heap */
115static inline void *bcmos_alloc(uint32_t size)
116{
117 return kmalloc(size, GFP_DMA);
118}
119
120/* Release memory to the main pool */
121static inline void bcmos_free(void *ptr)
122{
123 return kfree(ptr);
124}
125
126static inline void *bcmos_alloc_not_cache(int32_t size)
127{
128 return kmalloc(size, GFP_KERNEL);
129}
130static inline void bcmos_free_not_cache(void *dest)
131{
132 kfree(dest);
133}
134/*
135 * Synchronization
136 */
137
138/* Mutex control block */
139struct bcmos_mutex
140{
141 struct mutex m; /**< linux kernel mutex */
142};
143
144/* Create recursive mutex */
145static inline bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name)
146{
147 mutex_init(&mutex->m);
148 return BCM_ERR_OK;
149}
150
151/* Destroy mutex */
152static inline void bcmos_mutex_destroy(bcmos_mutex *mutex)
153{
154 mutex_destroy(&mutex->m);
155}
156
157/* Lock mutex */
158static inline void bcmos_mutex_lock(bcmos_mutex *mutex)
159{
160 mutex_lock(&mutex->m);
161}
162
163/* Release mutex */
164static inline void bcmos_mutex_unlock(bcmos_mutex *mutex)
165{
166 mutex_unlock(&mutex->m);
167}
168
169/** Fast lock control block */
170struct bcmos_fastlock
171{
172 spinlock_t m;
173};
174
175/** Fastlock initializer. Can be used instead of calling bcmos_fastlock_init() */
176#define BCMOS_FASTLOCK_INITIALIZER { SPINLOCK_UNLOCKED }
177
178/* Init fastlock */
179static inline void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags)
180{
181 spin_lock_init(&lock->m);
182}
183
184/* Take fast lock */
185static inline long bcmos_fastlock_lock(bcmos_fastlock *lock)
186{
187 unsigned long flags;
188 spin_lock_irqsave(&lock->m, flags);
189 return (long)flags;
190}
191
192/* Release fast lock */
193static inline void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags)
194{
195 spin_unlock_irqrestore(&lock->m, (unsigned long)flags);
196}
197
198/** Semaphore control block */
199struct bcmos_sem
200{
201 struct semaphore s; /**< linux kernel semaphore */
202};
203
204/* Create semaphore */
205static inline bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name)
206{
207 sema_init(&sem->s, count);
208 return BCM_ERR_OK;
209}
210
211/* Destroy semaphore */
212static inline void bcmos_sem_destroy(bcmos_sem *sem)
213{
214}
215
216/* Wait for semaphore */
217bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout);
218
219/* Increment semaphore counter */
220static inline void bcmos_sem_post(bcmos_sem *sem)
221{
222 up(&sem->s);
223}
224
225/*
226 * Timers
227 */
228
229/** System timer */
230struct bcmos_sys_timer
231{
232 struct timer_list t; /**< linux timer */
233 bcmos_sys_timer_handler handler; /**< Timer handler */
234 void *data; /**< Parameter to be passed to the handler */
235};
236
237/* Get current timestamp (us) */
238static inline uint32_t bcmos_timestamp(void)
239{
240 struct timespec uptime;
241 do_posix_clock_monotonic_gettime(&uptime);
242 monotonic_to_bootbased(&uptime);
243 return uptime.tv_sec * USEC_PER_SEC + uptime.tv_nsec / NSEC_PER_USEC;
244}
245
246/* Get current timestamp (us) */
247static inline uint64_t bcmos_timestamp64(void)
248{
249 struct timespec uptime;
250 do_posix_clock_monotonic_gettime(&uptime);
251 monotonic_to_bootbased(&uptime);
252 return (uint64_t)uptime.tv_sec * USEC_PER_SEC + (uint64_t)uptime.tv_nsec / NSEC_PER_USEC;
253}
254
255/*
256 * Task control
257 */
258
259/** OS-specific task control block extension */
260typedef struct bcmos_sys_task
261{
262 struct task_struct *t;
263} bcmos_sys_task;
264
265/** Memory pool control block */
266struct bcmos_byte_pool
267{
268 bcmos_byte_pool_parm parm; /**< Pool parameters */
269 uint32_t allocated; /**< Number of bytes allocated */
270#ifdef BCMOS_MEM_DEBUG
271 uint32_t magic; /**< magic number */
272#define BCMOS_BYTE_POOL_VALID (('b'<<24) | ('y' << 16) | ('p' << 8) | 'o')
273#define BCMOS_BYTE_POOL_DELETED (('b'<<24) | ('y' << 16) | ('p' << 8) | '~')
274#endif
275};
276
277/* Transport / network buffer service */
278extern uint32_t bcmos_buf_default_headroom;
279
280/*
281 * Network / transport buffer
282 */
283
284/* Data alignment. Should be a max lf L1, L2 cache line size */
285#define BCMOS_BUF_DATA_ALIGNMENT 128
286
287/* Encapsulated skb */
288struct bcmos_buf
289{
290 struct sk_buff skb;
291};
292
293/* Buffer list */
294typedef struct sk_buff_head bcmos_buf_queue;
295
296/* Allocate buffer */
297static inline bcmos_buf *bcmos_buf_alloc(uint32_t size)
298{
299 /* Allocate extra 2 * BCMOS_BUF_DATA_ALIGNMENT to make sure that neither data start nor end
300 * end up in the middle of cache line
301 */
302 struct sk_buff *skb = dev_alloc_skb(size + BCMTR_BUF_EXTRA_HEADROOM + 2 * BCMOS_BUF_DATA_ALIGNMENT - 1);
303 if (!skb)
304 return NULL;
305#if BCMTR_BUF_EXTRA_HEADROOM
306 skb_reserve(skb, BCMTR_BUF_EXTRA_HEADROOM);
307#endif
308 if ((long)skb->data & (BCMOS_BUF_DATA_ALIGNMENT - 1))
309 {
310 skb_reserve(skb, BCMOS_BUF_DATA_ALIGNMENT - ((long)skb->data & (BCMOS_BUF_DATA_ALIGNMENT - 1)));
311 }
312 return (bcmos_buf *)skb;
313}
314
315/* Release buffer */
316static inline void bcmos_buf_free(bcmos_buf *buf)
317{
318 consume_skb(&buf->skb);
319}
320
321/* Get data length */
322static inline uint32_t bcmos_buf_length(bcmos_buf *buf)
323{
324 return buf->skb.len;
325}
326
327/* Set data length */
328static inline bcmos_errno bcmos_buf_length_set(bcmos_buf *buf, uint32_t length)
329{
330 if (unlikely(length > skb_tailroom(&buf->skb)))
331 {
332 BCMOS_TRACE_ERR("!!!%s: length=%u tailroom=%d\n",
333 __FUNCTION__, length, skb_tailroom(&buf->skb));
334 return BCM_ERR_OVERFLOW;
335 }
336 buf->skb.len = length;
337 return BCM_ERR_OK;
338}
339
340/* Get buffer data pointer. */
341static inline uint8_t *bcmos_buf_data(bcmos_buf *buf)
342{
343 return buf->skb.data;
344}
345
346/* Get buffer channel. */
347static inline uint8_t bcmos_buf_channel(bcmos_buf *buf)
348{
349 return buf->skb.cb[0];
350}
351
352/* Set buffer channel. */
353static inline void bcmos_buf_channel_set(bcmos_buf *buf, uint8_t channel)
354{
355 buf->skb.cb[0] = channel;
356}
357
358/** Initialize buffer queue
359 * \param[in] q Buffer queue
360 */
361static inline void bcmos_buf_queue_init(bcmos_buf_queue *q)
362{
363 skb_queue_head_init(q);
364}
365
366/** Enqueue buffer
367 *
368 * Must be called under lock, e.g., q->lock
369 *
370 * \param[in] q Buffer queue
371 * \param[in] buf Buffer
372 */
373static inline void bcmos_buf_queue_put(bcmos_buf_queue *q, bcmos_buf *buf)
374{
375 __skb_queue_tail(q, &buf->skb);
376}
377
378/* Check if buffer queue is empty
379 * \param[in] q Buffer queue
380 * \returns TRUE if the queue is empty
381 */
382static inline bcmos_bool bcmos_buf_queue_is_empty(bcmos_buf_queue *q)
383{
384 return (bcmos_bool)skb_queue_empty(q);
385}
386
387/* Dequeue buffer
388 *
389 * Must be called under lock, e.g., q->lock
390 *
391 * Remove and return the 1st queued buffer.
392 * \param[in] q Buffer queue
393 * \returns the buffer pointer
394 */
395static inline bcmos_buf *bcmos_buf_queue_get(bcmos_buf_queue *q)
396{
397 struct sk_buff *skb = __skb_dequeue(q);
398 return skb ? container_of(skb, bcmos_buf, skb) : NULL;
399}
400
401/* Peek into queue and return the 1st buffer without dequeing it
402 *
403 * Must be called under lock, e.g., q->lock
404 * \param[in] q Buffer queue
405 * \returns the buffer pointer
406 */
407static inline bcmos_buf *bcmos_buf_queue_peek(bcmos_buf_queue *q)
408{
409 struct sk_buff *skb = skb_peek(q);
410 return skb ? container_of(skb, bcmos_buf, skb) : NULL;
411}
412
413/*
414 * dcache utilities
415 */
416/* Invalidate address area in data cache. Dirty cache lines content is discarded */
417static inline void bcmos_dcache_inv(void *start, uint32_t size)
418{
419#if defined(CONFIG_MIPS)
420 dma_cache_inv((unsigned long)start, size);
421#elif defined(CONFIG_PPC)
422 if (((unsigned long)start & (L1_CACHE_BYTES - 1)) || (size & (L1_CACHE_BYTES - 1)))
423 flush_dcache_range((unsigned long)start, (unsigned long)start + size);
424 else
425 invalidate_dcache_range((unsigned long)start, (unsigned long)start + size);
426#elif defined(CONFIG_UML)
427 /* Nothing to do */
428#else
429#error Please implement bcmos_dcache_inv()
430#endif
431}
432
433/* Flush address area in data cache. Dirty cache lines are committed to memory */
434static inline void bcmos_dcache_flush(void *start, uint32_t size)
435{
436#if defined(CONFIG_MIPS)
437 dma_cache_wback((unsigned long)start, size);
438#elif defined(CONFIG_PPC)
439 clean_dcache_range((unsigned long)start, (unsigned long)start + size);
440#elif defined(CONFIG_UML)
441 /* Nothing to do */
442#else
443#error Please implement bcmos_dcache_flush()
444#endif
445}
446
447/*
448 * Interrupt service
449 */
450
451/* Connect system interrupt */
452static inline int bcmos_int_connect(int irq, int cpu, int flags,
453 int (*isr)(int irq, void *priv), const char *name, void *priv)
454{
455 return request_irq(irq, (irq_handler_t)isr, flags, name, priv);
456}
457
458/* Disconnect system interrupt */
459static inline void bcmos_int_disconnect(int irq, void *priv)
460{
461 free_irq(irq, priv);
462}
463
464/* Unmask IRQ */
465static inline void bcmos_int_enable(int irq)
466{
467 enable_irq(irq);
468}
469
470/* Mask IRQ */
471static inline void bcmos_int_disable(int irq)
472{
473 disable_irq(irq);
474}
475
476/* Check in-irq status */
477static inline int is_irq_mode(void)
478{
479 return in_interrupt();
480}
481
482/* Check if interrupts are disabled */
483static inline int is_irq_disabled(void)
484{
485 return irqs_disabled();
486}
487
488/* Convert virtual address to physical address */
489static inline unsigned long bcmos_virt_to_phys(void *va)
490{
491 return virt_to_phys(va);
492}
493
494/* write barrier */
495static inline void bcmos_barrier(void)
496{
497 smp_wmb();
498}
499static inline int bcmos_getchar(void)
500{
501 return -1;
502}
503
504static inline void bcmos_putchar(int c)
505{
506}
507
508#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
509#undef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
510#endif
511
512#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
513#undef BCMOS_MSG_QUEUE_UDP_SOCKET
514#endif
515
516/* 2nd part of OS-independent declarations */
517#include "bcmos_common2.h"
518
519#endif /* BCMOS_SYSTEM_H_ */