linux/arch/powerpc/kernel/ibmebus.c
<<
>>
Prefs
   1/*
   2 * IBM PowerPC IBM eBus Infrastructure Support.
   3 *
   4 * Copyright (c) 2005 IBM Corporation
   5 *  Joachim Fenkes <fenkes@de.ibm.com>
   6 *  Heiko J Schick <schickhj@de.ibm.com>
   7 *
   8 * All rights reserved.
   9 *
  10 * This source code is distributed under a dual license of GPL v2.0 and OpenIB
  11 * BSD.
  12 *
  13 * OpenIB BSD License
  14 *
  15 * Redistribution and use in source and binary forms, with or without
  16 * modification, are permitted provided that the following conditions are met:
  17 *
  18 * Redistributions of source code must retain the above copyright notice, this
  19 * list of conditions and the following disclaimer.
  20 *
  21 * Redistributions in binary form must reproduce the above copyright notice,
  22 * this list of conditions and the following disclaimer in the documentation
  23 * and/or other materials
  24 * provided with the distribution.
  25 *
  26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  33 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  34 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36 * POSSIBILITY OF SUCH DAMAGE.
  37 */
  38
  39#include <linux/init.h>
  40#include <linux/console.h>
  41#include <linux/kobject.h>
  42#include <linux/dma-mapping.h>
  43#include <linux/interrupt.h>
  44#include <linux/of.h>
  45#include <linux/of_platform.h>
  46#include <asm/ibmebus.h>
  47#include <asm/abs_addr.h>
  48
  49static struct device ibmebus_bus_device = { /* fake "parent" device */
  50        .init_name = "ibmebus",
  51};
  52
  53struct bus_type ibmebus_bus_type;
  54
  55/* These devices will automatically be added to the bus during init */
  56static struct of_device_id __initdata ibmebus_matches[] = {
  57        { .compatible = "IBM,lhca" },
  58        { .compatible = "IBM,lhea" },
  59        {},
  60};
  61
  62static void *ibmebus_alloc_coherent(struct device *dev,
  63                                    size_t size,
  64                                    dma_addr_t *dma_handle,
  65                                    gfp_t flag)
  66{
  67        void *mem;
  68
  69        mem = kmalloc(size, flag);
  70        *dma_handle = (dma_addr_t)mem;
  71
  72        return mem;
  73}
  74
  75static void ibmebus_free_coherent(struct device *dev,
  76                                  size_t size, void *vaddr,
  77                                  dma_addr_t dma_handle)
  78{
  79        kfree(vaddr);
  80}
  81
  82static dma_addr_t ibmebus_map_page(struct device *dev,
  83                                   struct page *page,
  84                                   unsigned long offset,
  85                                   size_t size,
  86                                   enum dma_data_direction direction,
  87                                   struct dma_attrs *attrs)
  88{
  89        return (dma_addr_t)(page_address(page) + offset);
  90}
  91
  92static void ibmebus_unmap_page(struct device *dev,
  93                               dma_addr_t dma_addr,
  94                               size_t size,
  95                               enum dma_data_direction direction,
  96                               struct dma_attrs *attrs)
  97{
  98        return;
  99}
 100
 101static int ibmebus_map_sg(struct device *dev,
 102                          struct scatterlist *sgl,
 103                          int nents, enum dma_data_direction direction,
 104                          struct dma_attrs *attrs)
 105{
 106        struct scatterlist *sg;
 107        int i;
 108
 109        for_each_sg(sgl, sg, nents, i) {
 110                sg->dma_address = (dma_addr_t) sg_virt(sg);
 111                sg->dma_length = sg->length;
 112        }
 113
 114        return nents;
 115}
 116
 117static void ibmebus_unmap_sg(struct device *dev,
 118                             struct scatterlist *sg,
 119                             int nents, enum dma_data_direction direction,
 120                             struct dma_attrs *attrs)
 121{
 122        return;
 123}
 124
 125static int ibmebus_dma_supported(struct device *dev, u64 mask)
 126{
 127        return 1;
 128}
 129
 130static struct dma_map_ops ibmebus_dma_ops = {
 131        .alloc_coherent = ibmebus_alloc_coherent,
 132        .free_coherent  = ibmebus_free_coherent,
 133        .map_sg         = ibmebus_map_sg,
 134        .unmap_sg       = ibmebus_unmap_sg,
 135        .dma_supported  = ibmebus_dma_supported,
 136        .map_page       = ibmebus_map_page,
 137        .unmap_page     = ibmebus_unmap_page,
 138};
 139
 140static int ibmebus_match_path(struct device *dev, void *data)
 141{
 142        struct device_node *dn = to_of_device(dev)->node;
 143        return (dn->full_name &&
 144                (strcasecmp((char *)data, dn->full_name) == 0));
 145}
 146
 147static int ibmebus_match_node(struct device *dev, void *data)
 148{
 149        return to_of_device(dev)->node == data;
 150}
 151
 152static int ibmebus_create_device(struct device_node *dn)
 153{
 154        struct of_device *dev;
 155        int ret;
 156
 157        dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
 158        if (!dev)
 159                return -ENOMEM;
 160
 161        dev->dev.bus = &ibmebus_bus_type;
 162        dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
 163
 164        ret = of_device_register(dev);
 165        if (ret) {
 166                of_device_free(dev);
 167                return ret;
 168        }
 169
 170        return 0;
 171}
 172
 173static int ibmebus_create_devices(const struct of_device_id *matches)
 174{
 175        struct device_node *root, *child;
 176        int ret = 0;
 177
 178        root = of_find_node_by_path("/");
 179
 180        for_each_child_of_node(root, child) {
 181                if (!of_match_node(matches, child))
 182                        continue;
 183
 184                if (bus_find_device(&ibmebus_bus_type, NULL, child,
 185                                    ibmebus_match_node))
 186                        continue;
 187
 188                ret = ibmebus_create_device(child);
 189                if (ret) {
 190                        printk(KERN_ERR "%s: failed to create device (%i)",
 191                               __func__, ret);
 192                        of_node_put(child);
 193                        break;
 194                }
 195        }
 196
 197        of_node_put(root);
 198        return ret;
 199}
 200
 201int ibmebus_register_driver(struct of_platform_driver *drv)
 202{
 203        /* If the driver uses devices that ibmebus doesn't know, add them */
 204        ibmebus_create_devices(drv->match_table);
 205
 206        return of_register_driver(drv, &ibmebus_bus_type);
 207}
 208EXPORT_SYMBOL(ibmebus_register_driver);
 209
 210void ibmebus_unregister_driver(struct of_platform_driver *drv)
 211{
 212        of_unregister_driver(drv);
 213}
 214EXPORT_SYMBOL(ibmebus_unregister_driver);
 215
 216int ibmebus_request_irq(u32 ist, irq_handler_t handler,
 217                        unsigned long irq_flags, const char *devname,
 218                        void *dev_id)
 219{
 220        unsigned int irq = irq_create_mapping(NULL, ist);
 221
 222        if (irq == NO_IRQ)
 223                return -EINVAL;
 224
 225        return request_irq(irq, handler, irq_flags, devname, dev_id);
 226}
 227EXPORT_SYMBOL(ibmebus_request_irq);
 228
 229void ibmebus_free_irq(u32 ist, void *dev_id)
 230{
 231        unsigned int irq = irq_find_mapping(NULL, ist);
 232
 233        free_irq(irq, dev_id);
 234        irq_dispose_mapping(irq);
 235}
 236EXPORT_SYMBOL(ibmebus_free_irq);
 237
 238static char *ibmebus_chomp(const char *in, size_t count)
 239{
 240        char *out = kmalloc(count + 1, GFP_KERNEL);
 241
 242        if (!out)
 243                return NULL;
 244
 245        memcpy(out, in, count);
 246        out[count] = '\0';
 247        if (out[count - 1] == '\n')
 248                out[count - 1] = '\0';
 249
 250        return out;
 251}
 252
 253static ssize_t ibmebus_store_probe(struct bus_type *bus,
 254                                   const char *buf, size_t count)
 255{
 256        struct device_node *dn = NULL;
 257        char *path;
 258        ssize_t rc = 0;
 259
 260        path = ibmebus_chomp(buf, count);
 261        if (!path)
 262                return -ENOMEM;
 263
 264        if (bus_find_device(&ibmebus_bus_type, NULL, path,
 265                            ibmebus_match_path)) {
 266                printk(KERN_WARNING "%s: %s has already been probed\n",
 267                       __func__, path);
 268                rc = -EEXIST;
 269                goto out;
 270        }
 271
 272        if ((dn = of_find_node_by_path(path))) {
 273                rc = ibmebus_create_device(dn);
 274                of_node_put(dn);
 275        } else {
 276                printk(KERN_WARNING "%s: no such device node: %s\n",
 277                       __func__, path);
 278                rc = -ENODEV;
 279        }
 280
 281out:
 282        kfree(path);
 283        if (rc)
 284                return rc;
 285        return count;
 286}
 287
 288static ssize_t ibmebus_store_remove(struct bus_type *bus,
 289                                    const char *buf, size_t count)
 290{
 291        struct device *dev;
 292        char *path;
 293
 294        path = ibmebus_chomp(buf, count);
 295        if (!path)
 296                return -ENOMEM;
 297
 298        if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
 299                                   ibmebus_match_path))) {
 300                of_device_unregister(to_of_device(dev));
 301
 302                kfree(path);
 303                return count;
 304        } else {
 305                printk(KERN_WARNING "%s: %s not on the bus\n",
 306                       __func__, path);
 307
 308                kfree(path);
 309                return -ENODEV;
 310        }
 311}
 312
 313static struct bus_attribute ibmebus_bus_attrs[] = {
 314        __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
 315        __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
 316        __ATTR_NULL
 317};
 318
 319struct bus_type ibmebus_bus_type = {
 320        .uevent    = of_device_uevent,
 321        .bus_attrs = ibmebus_bus_attrs
 322};
 323EXPORT_SYMBOL(ibmebus_bus_type);
 324
 325static int __init ibmebus_bus_init(void)
 326{
 327        int err;
 328
 329        printk(KERN_INFO "IBM eBus Device Driver\n");
 330
 331        err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
 332        if (err) {
 333                printk(KERN_ERR "%s: failed to register IBM eBus.\n",
 334                       __func__);
 335                return err;
 336        }
 337
 338        err = device_register(&ibmebus_bus_device);
 339        if (err) {
 340                printk(KERN_WARNING "%s: device_register returned %i\n",
 341                       __func__, err);
 342                bus_unregister(&ibmebus_bus_type);
 343
 344                return err;
 345        }
 346
 347        err = ibmebus_create_devices(ibmebus_matches);
 348        if (err) {
 349                device_unregister(&ibmebus_bus_device);
 350                bus_unregister(&ibmebus_bus_type);
 351                return err;
 352        }
 353
 354        return 0;
 355}
 356postcore_initcall(ibmebus_bus_init);
 357