root/arch/powerpc/sysdev/dcr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_dcr_parent
  2. dcr_map_ok_generic
  3. dcr_map_generic
  4. dcr_unmap_generic
  5. dcr_read_generic
  6. dcr_write_generic
  7. dcr_resource_start
  8. dcr_resource_len
  9. of_translate_dcr_address
  10. dcr_map_mmio
  11. dcr_unmap_mmio

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
   4  *                    <benh@kernel.crashing.org>
   5  */
   6 
   7 #undef DEBUG
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/export.h>
  11 #include <asm/prom.h>
  12 #include <asm/dcr.h>
  13 
  14 #ifdef CONFIG_PPC_DCR_MMIO
  15 static struct device_node *find_dcr_parent(struct device_node *node)
  16 {
  17         struct device_node *par, *tmp;
  18         const u32 *p;
  19 
  20         for (par = of_node_get(node); par;) {
  21                 if (of_get_property(par, "dcr-controller", NULL))
  22                         break;
  23                 p = of_get_property(par, "dcr-parent", NULL);
  24                 tmp = par;
  25                 if (p == NULL)
  26                         par = of_get_parent(par);
  27                 else
  28                         par = of_find_node_by_phandle(*p);
  29                 of_node_put(tmp);
  30         }
  31         return par;
  32 }
  33 #endif
  34 
  35 #if defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO)
  36 
  37 bool dcr_map_ok_generic(dcr_host_t host)
  38 {
  39         if (host.type == DCR_HOST_NATIVE)
  40                 return dcr_map_ok_native(host.host.native);
  41         else if (host.type == DCR_HOST_MMIO)
  42                 return dcr_map_ok_mmio(host.host.mmio);
  43         else
  44                 return false;
  45 }
  46 EXPORT_SYMBOL_GPL(dcr_map_ok_generic);
  47 
  48 dcr_host_t dcr_map_generic(struct device_node *dev,
  49                            unsigned int dcr_n,
  50                            unsigned int dcr_c)
  51 {
  52         dcr_host_t host;
  53         struct device_node *dp;
  54         const char *prop;
  55 
  56         host.type = DCR_HOST_INVALID;
  57 
  58         dp = find_dcr_parent(dev);
  59         if (dp == NULL)
  60                 return host;
  61 
  62         prop = of_get_property(dp, "dcr-access-method", NULL);
  63 
  64         pr_debug("dcr_map_generic(dcr-access-method = %s)\n", prop);
  65 
  66         if (!strcmp(prop, "native")) {
  67                 host.type = DCR_HOST_NATIVE;
  68                 host.host.native = dcr_map_native(dev, dcr_n, dcr_c);
  69         } else if (!strcmp(prop, "mmio")) {
  70                 host.type = DCR_HOST_MMIO;
  71                 host.host.mmio = dcr_map_mmio(dev, dcr_n, dcr_c);
  72         }
  73 
  74         of_node_put(dp);
  75         return host;
  76 }
  77 EXPORT_SYMBOL_GPL(dcr_map_generic);
  78 
  79 void dcr_unmap_generic(dcr_host_t host, unsigned int dcr_c)
  80 {
  81         if (host.type == DCR_HOST_NATIVE)
  82                 dcr_unmap_native(host.host.native, dcr_c);
  83         else if (host.type == DCR_HOST_MMIO)
  84                 dcr_unmap_mmio(host.host.mmio, dcr_c);
  85         else /* host.type == DCR_HOST_INVALID */
  86                 WARN_ON(true);
  87 }
  88 EXPORT_SYMBOL_GPL(dcr_unmap_generic);
  89 
  90 u32 dcr_read_generic(dcr_host_t host, unsigned int dcr_n)
  91 {
  92         if (host.type == DCR_HOST_NATIVE)
  93                 return dcr_read_native(host.host.native, dcr_n);
  94         else if (host.type == DCR_HOST_MMIO)
  95                 return dcr_read_mmio(host.host.mmio, dcr_n);
  96         else /* host.type == DCR_HOST_INVALID */
  97                 WARN_ON(true);
  98         return 0;
  99 }
 100 EXPORT_SYMBOL_GPL(dcr_read_generic);
 101 
 102 void dcr_write_generic(dcr_host_t host, unsigned int dcr_n, u32 value)
 103 {
 104         if (host.type == DCR_HOST_NATIVE)
 105                 dcr_write_native(host.host.native, dcr_n, value);
 106         else if (host.type == DCR_HOST_MMIO)
 107                 dcr_write_mmio(host.host.mmio, dcr_n, value);
 108         else /* host.type == DCR_HOST_INVALID */
 109                 WARN_ON(true);
 110 }
 111 EXPORT_SYMBOL_GPL(dcr_write_generic);
 112 
 113 #endif /* defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) */
 114 
 115 unsigned int dcr_resource_start(const struct device_node *np,
 116                                 unsigned int index)
 117 {
 118         unsigned int ds;
 119         const u32 *dr = of_get_property(np, "dcr-reg", &ds);
 120 
 121         if (dr == NULL || ds & 1 || index >= (ds / 8))
 122                 return 0;
 123 
 124         return dr[index * 2];
 125 }
 126 EXPORT_SYMBOL_GPL(dcr_resource_start);
 127 
 128 unsigned int dcr_resource_len(const struct device_node *np, unsigned int index)
 129 {
 130         unsigned int ds;
 131         const u32 *dr = of_get_property(np, "dcr-reg", &ds);
 132 
 133         if (dr == NULL || ds & 1 || index >= (ds / 8))
 134                 return 0;
 135 
 136         return dr[index * 2 + 1];
 137 }
 138 EXPORT_SYMBOL_GPL(dcr_resource_len);
 139 
 140 #ifdef CONFIG_PPC_DCR_MMIO
 141 
 142 static u64 of_translate_dcr_address(struct device_node *dev,
 143                                     unsigned int dcr_n,
 144                                     unsigned int *out_stride)
 145 {
 146         struct device_node *dp;
 147         const u32 *p;
 148         unsigned int stride;
 149         u64 ret = OF_BAD_ADDR;
 150 
 151         dp = find_dcr_parent(dev);
 152         if (dp == NULL)
 153                 return OF_BAD_ADDR;
 154 
 155         /* Stride is not properly defined yet, default to 0x10 for Axon */
 156         p = of_get_property(dp, "dcr-mmio-stride", NULL);
 157         stride = (p == NULL) ? 0x10 : *p;
 158 
 159         /* XXX FIXME: Which property name is to use of the 2 following ? */
 160         p = of_get_property(dp, "dcr-mmio-range", NULL);
 161         if (p == NULL)
 162                 p = of_get_property(dp, "dcr-mmio-space", NULL);
 163         if (p == NULL)
 164                 goto done;
 165 
 166         /* Maybe could do some better range checking here */
 167         ret = of_translate_address(dp, p);
 168         if (ret != OF_BAD_ADDR)
 169                 ret += (u64)(stride) * (u64)dcr_n;
 170         if (out_stride)
 171                 *out_stride = stride;
 172 
 173  done:
 174         of_node_put(dp);
 175         return ret;
 176 }
 177 
 178 dcr_host_mmio_t dcr_map_mmio(struct device_node *dev,
 179                              unsigned int dcr_n,
 180                              unsigned int dcr_c)
 181 {
 182         dcr_host_mmio_t ret = { .token = NULL, .stride = 0, .base = dcr_n };
 183         u64 addr;
 184 
 185         pr_debug("dcr_map(%pOF, 0x%x, 0x%x)\n",
 186                  dev, dcr_n, dcr_c);
 187 
 188         addr = of_translate_dcr_address(dev, dcr_n, &ret.stride);
 189         pr_debug("translates to addr: 0x%llx, stride: 0x%x\n",
 190                  (unsigned long long) addr, ret.stride);
 191         if (addr == OF_BAD_ADDR)
 192                 return ret;
 193         pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride);
 194         ret.token = ioremap(addr, dcr_c * ret.stride);
 195         if (ret.token == NULL)
 196                 return ret;
 197         pr_debug("mapped at 0x%p -> base is 0x%p\n",
 198                  ret.token, ret.token - dcr_n * ret.stride);
 199         ret.token -= dcr_n * ret.stride;
 200         return ret;
 201 }
 202 EXPORT_SYMBOL_GPL(dcr_map_mmio);
 203 
 204 void dcr_unmap_mmio(dcr_host_mmio_t host, unsigned int dcr_c)
 205 {
 206         dcr_host_mmio_t h = host;
 207 
 208         if (h.token == NULL)
 209                 return;
 210         h.token += host.base * h.stride;
 211         iounmap(h.token);
 212         h.token = NULL;
 213 }
 214 EXPORT_SYMBOL_GPL(dcr_unmap_mmio);
 215 
 216 #endif /* defined(CONFIG_PPC_DCR_MMIO) */
 217 
 218 #ifdef CONFIG_PPC_DCR_NATIVE
 219 DEFINE_SPINLOCK(dcr_ind_lock);
 220 EXPORT_SYMBOL_GPL(dcr_ind_lock);
 221 #endif  /* defined(CONFIG_PPC_DCR_NATIVE) */
 222 

/* [<][>][^][v][top][bottom][index][help] */