diff options
Diffstat (limited to 'linux/drivers/soc/fsl/qbman/dpaa_sys.h')
-rw-r--r-- | linux/drivers/soc/fsl/qbman/dpaa_sys.h | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/linux/drivers/soc/fsl/qbman/dpaa_sys.h b/linux/drivers/soc/fsl/qbman/dpaa_sys.h new file mode 100644 index 00000000..85f87800 --- /dev/null +++ b/linux/drivers/soc/fsl/qbman/dpaa_sys.h @@ -0,0 +1,292 @@ +/* Copyright 2008 - 2015 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DPAA_SYS_H +#define __DPAA_SYS_H + +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_reserved_mem.h> +#include <linux/kthread.h> +#include <linux/uaccess.h> +#include <linux/debugfs.h> +#include <linux/vmalloc.h> +#include <linux/platform_device.h> +#include <linux/ctype.h> +#ifdef CONFIG_HOTPLUG_CPU +#include <linux/cpu.h> +#endif + +#include <asm/pgtable.h> +#ifdef __rtems__ +#include <asm/cache.h> +#include <asm/mpc85xx.h> +#include <linux/completion.h> +#include <linux/io.h> +#include <linux/rbtree.h> +#include <bsp/linker-symbols.h> +#define DPAA_NOCACHENOLOAD_ALIGNED_REGION(designator, size) \ + BSP_NOCACHENOLOAD_SUBSECTION(designator) __aligned(size) \ + uint8_t designator[size] +#endif /* __rtems__ */ + +struct dpaa_resource { + struct list_head free; + spinlock_t lock; + struct list_head used; +}; + +#define DECLARE_DPAA_RESOURCE(name) \ +struct dpaa_resource name = { \ + .free = { \ + .prev = &name.free, \ + .next = &name.free \ + }, \ + .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ + .used = { \ + .prev = &name.used, \ + .next = &name.used \ + } \ +} + +int dpaa_resource_new(struct dpaa_resource *alloc, u32 *result, + u32 count, u32 align, int partial); +u32 dpaa_resource_release(struct dpaa_resource *alloc, + u32 id, u32 count, int (*is_valid)(u32 id)); +void dpaa_resource_seed(struct dpaa_resource *alloc, u32 base_id, u32 count); +int dpaa_resource_reserve(struct dpaa_resource *alloc, u32 base, u32 num); + +/* When copying aligned words or shorts, try to avoid memcpy() */ +#define CONFIG_TRY_BETTER_MEMCPY + +/* For 2-element tables related to cache-inhibited and cache-enabled mappings */ +#define DPA_PORTAL_CE 0 +#define DPA_PORTAL_CI 1 + +/* Misc inline assists */ + +/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler + * barriers and that dcb*() won't fall victim to compiler or execution + * reordering with respect to other code/instructions that manipulate the same + * cacheline. */ +#define hwsync() __asm__ __volatile__ ("sync" : : : "memory") +#ifndef __rtems__ +#define lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory") +#else /* __rtems__ */ + #ifdef __PPC_CPU_E6500__ + #define lwsync() ppc_light_weight_synchronize() + #else + #define lwsync() ppc_synchronize_data() + #endif +#endif /* __rtems__ */ +#define dcbf(p) __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory") +#define dcbt_ro(p) __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p)) +#define dcbt_rw(p) __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p)) +#define dcbi(p) dcbf(p) +#ifdef CONFIG_PPC_E500MC +#define dcbzl(p) __asm__ __volatile__ ("dcbzl 0,%0" : : "r" (p)) +#define dcbz_64(p) dcbzl(p) +#define dcbf_64(p) dcbf(p) +/* Commonly used combo */ +#define dcbit_ro(p) \ + do { \ + dcbi(p); \ + dcbt_ro(p); \ + } while (0) +#else +#define dcbz(p) __asm__ __volatile__ ("dcbz 0,%0" : : "r" (p)) +#define dcbz_64(p) \ + do { \ + dcbz((u32)p + 32); \ + dcbz(p); \ + } while (0) +#define dcbf_64(p) \ + do { \ + dcbf((u32)p + 32); \ + dcbf(p); \ + } while (0) +/* Commonly used combo */ +#define dcbit_ro(p) \ + do { \ + dcbi(p); \ + dcbi((u32)p + 32); \ + dcbt_ro(p); \ + dcbt_ro((u32)p + 32); \ + } while (0) +#endif /* CONFIG_PPC_E500MC */ + +static inline u64 mfatb(void) +{ + u32 hi, lo, chk; + + do { + hi = mfspr(SPRN_ATBU); + lo = mfspr(SPRN_ATBL); + chk = mfspr(SPRN_ATBU); + } while (unlikely(hi != chk)); + return ((u64)hi << 32) | (u64)lo; +} + +#ifdef CONFIG_FSL_DPA_CHECKING +#define DPA_ASSERT(x) WARN_ON(!(x)) +#else +#define DPA_ASSERT(x) +#endif + +#ifdef CONFIG_TRY_BETTER_MEMCPY +static inline void copy_words(void *dest, const void *src, size_t sz) +{ + u32 *__dest = dest; + const u32 *__src = src; + size_t __sz = sz >> 2; + + BUG_ON((unsigned long)dest & 0x3); + BUG_ON((unsigned long)src & 0x3); + BUG_ON(sz & 0x3); + while (__sz--) + *(__dest++) = *(__src++); +} +#else +#define copy_words memcpy +#endif + +/* RB-trees */ + +/* We encapsulate RB-trees so that its easier to use non-linux forms in + * non-linux systems. This also encapsulates the extra plumbing that linux code + * usually provides when using RB-trees. This encapsulation assumes that the + * data type held by the tree is u32. */ + +struct dpa_rbtree { + struct rb_root root; +}; +#define DPA_RBTREE { .root = RB_ROOT } + +static inline void dpa_rbtree_init(struct dpa_rbtree *tree) +{ + tree->root = RB_ROOT; +} + +#define IMPLEMENT_DPA_RBTREE(name, type, node_field, val_field) \ +static inline int name##_push(struct dpa_rbtree *tree, type *obj) \ +{ \ + struct rb_node *parent = NULL, **p = &tree->root.rb_node; \ + while (*p) { \ + u32 item; \ + parent = *p; \ + item = rb_entry(parent, type, node_field)->val_field; \ + if (obj->val_field < item) \ + p = &parent->rb_left; \ + else if (obj->val_field > item) \ + p = &parent->rb_right; \ + else \ + return -EBUSY; \ + } \ + rb_link_node(&obj->node_field, parent, p); \ + rb_insert_color(&obj->node_field, &tree->root); \ + return 0; \ +} \ +static inline void name##_del(struct dpa_rbtree *tree, type *obj) \ +{ \ + rb_erase(&obj->node_field, &tree->root); \ +} \ +static inline type *name##_find(struct dpa_rbtree *tree, u32 val) \ +{ \ + type *ret; \ + struct rb_node *p = tree->root.rb_node; \ + while (p) { \ + ret = rb_entry(p, type, node_field); \ + if (val < ret->val_field) \ + p = p->rb_left; \ + else if (val > ret->val_field) \ + p = p->rb_right; \ + else \ + return ret; \ + } \ + return NULL; \ +} + +#ifndef __rtems__ +/* Bootargs */ + +/* QMan has "qportals=" and BMan has "bportals=", they use the same syntax + * though; a comma-separated list of items, each item being a cpu index and/or a + * range of cpu indices, and each item optionally be prefixed by "s" to indicate + * that the portal associated with that cpu should be shared. See bman_driver.c + * for more specifics. */ +static int __parse_portals_cpu(const char **s, unsigned int *cpu) +{ + *cpu = 0; + if (!isdigit(**s)) + return -EINVAL; + while (isdigit(**s)) + *cpu = *cpu * 10 + (*((*s)++) - '0'); + return 0; +} +static inline int parse_portals_bootarg(char *str, struct cpumask *want_shared, + struct cpumask *want_unshared, + const char *argname) +{ + const char *s = str; + unsigned int shared, cpu1, cpu2, loop; + +keep_going: + if (*s == 's') { + shared = 1; + s++; + } else + shared = 0; + if (__parse_portals_cpu(&s, &cpu1)) + goto err; + if (*s == '-') { + s++; + if (__parse_portals_cpu(&s, &cpu2)) + goto err; + if (cpu2 < cpu1) + goto err; + } else + cpu2 = cpu1; + for (loop = cpu1; loop <= cpu2; loop++) + cpumask_set_cpu(loop, shared ? want_shared : want_unshared); + if (*s == ',') { + s++; + goto keep_going; + } else if ((*s == '\0') || isspace(*s)) + return 0; +err: + pr_crit("Malformed %s argument: %s, offset: %lu\n", argname, str, + (unsigned long)s - (unsigned long)str); + return -EINVAL; +} +#endif /* __rtems__ */ +#endif /* __DPAA_SYS_H */ |