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/slab.h>
  46#include <linux/of_platform.h>
  47#include <asm/ibmebus.h>
  48#include <asm/abs_addr.h>
  49
  50static struct device ibmebus_bus_device = { /* fake "parent" device */
  51        .init_name = "ibmebus",
  52};
  53
  54struct bus_type ibmebus_bus_type;
  55
  56/* These devices will automatically be added to the bus during init */
  57static struct of_device_id __initdata ibmebus_matches[] = {
  58        { .compatible = "IBM,lhca" },
  59        { .compatible = "IBM,lhea" },
  60        {},
  61};
  62
  63static void *ibmebus_alloc_coherent(struct device *dev,
  64                                    size_t size,
  65                                    dma_addr_t *dma_handle,
  66                                    gfp_t flag)
  67{
  68        void *mem;
  69
  70        mem = kmalloc(size, flag);
  71        *dma_handle = (dma_addr_t)mem;
  72
  73        return mem;
  74}
  75
  76static void ibmebus_free_coherent(struct device *dev,
  77                                  size_t size, void *vaddr,
  78                                  dma_addr_t dma_handle)
  79{
  80        kfree(vaddr);
  81}
  82
  83static dma_addr_t ibmebus_map_page(struct device *dev,
  84                                   struct page *page,
  85                                   unsigned long offset,
  86                                   size_t size,
  87                                   enum dma_data_direction direction,
  88                                   struct dma_attrs *attrs)
  89{
  90        return (dma_addr_t)(page_address(page) + offset);
  91}
  92
  93static void ibmebus_unmap_page(struct device *dev,
  94                               dma_addr_t dma_addr,
  95                               size_t size,
  96                               enum dma_data_direction direction,
  97                               struct dma_attrs *attrs)
  98{
  99        return;
 100}
 101
 102static int ibmebus_map_sg(struct device *dev,
 103                          struct scatterlist *sgl,
 104                          int nents, enum dma_data_direction direction,
 105                          struct dma_attrs *attrs)
 106{
 107        struct scatterlist *sg;
 108        int i;
 109
 110        for_each_sg(sgl, sg, nents, i) {
 111                sg->dma_address = (dma_addr_t) sg_virt(sg);
 112                sg->dma_length = sg->length;
 113        }
 114
 115        return nents;
 116}
 117
 118static void ibmebus_unmap_sg(struct device *dev,
 119                             struct scatterlist *sg,
 120                             int nents, enum dma_data_direction direction,
 121                             struct dma_attrs *attrs)
 122{
 123        return;
 124}
 125
 126static int ibmebus_dma_supported(struct device *dev, u64 mask)
 127{
 128        return 1;
 129}
 130
 131static struct dma_map_ops ibmebus_dma_ops = {
 132        .alloc_coherent = ibmebus_alloc_coherent,
 133        .free_coherent  = ibmebus_free_coherent,
 134        .map_sg         = ibmebus_map_sg,
 135        .unmap_sg       = ibmebus_unmap_sg,
 136        .dma_supported  = ibmebus_dma_supported,
 137        .map_page       = ibmebus_map_page,
 138        .unmap_page     = ibmebus_unmap_page,
 139};
 140
 141static int ibmebus_match_path(struct device *dev, void *data)
 142{
 143        struct device_node *dn = to_platform_device(dev)->dev.of_node;
 144        return (dn->full_name &&
 145                (strcasecmp((char *)data, dn->full_name) == 0));
 146}
 147
 148static int ibmebus_match_node(struct device *dev, void *data)
 149{
 150        return to_platform_device(dev)->dev.of_node == data;
 151}
 152
 153static int ibmebus_create_device(struct device_node *dn)
 154{
 155        struct platform_device *dev;
 156        int ret;
 157
 158        dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
 159        if (!dev)
 160                return -ENOMEM;
 161
 162        dev->dev.bus = &ibmebus_bus_type;
 163        dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
 164
 165        ret = of_device_add(dev);
 166        if (ret)
 167                platform_device_put(dev);
 168        return ret;
 169}
 170
 171static int ibmebus_create_devices(const struct of_device_id *matches)
 172{
 173        struct device_node *root, *child;
 174        int ret = 0;
 175
 176        root = of_find_node_by_path("/");
 177
 178        for_each_child_of_node(root, child) {
 179                if (!of_match_node(matches, child))
 180                        continue;
 181
 182                if (bus_find_device(&ibmebus_bus_type, NULL, child,
 183                                    ibmebus_match_node))
 184                        continue;
 185
 186                ret = ibmebus_create_device(child);
 187                if (ret) {
 188                        printk(KERN_ERR "%s: failed to create device (%i)",
 189                               __func__, ret);
 190                        of_node_put(child);
 191                        break;
 192                }
 193        }
 194
 195        of_node_put(root);
 196        return ret;
 197}
 198
 199int ibmebus_register_driver(struct of_platform_driver *drv)
 200{
 201        /* If the driver uses devices that ibmebus doesn't know, add them */
 202        ibmebus_create_devices(drv->driver.of_match_table);
 203
 204        return of_register_driver(drv, &ibmebus_bus_type);
 205}
 206EXPORT_SYMBOL(ibmebus_register_driver);
 207
 208void ibmebus_unregister_driver(struct of_platform_driver *drv)
 209{
 210        of_unregister_driver(drv);
 211}
 212EXPORT_SYMBOL(ibmebus_unregister_driver);
 213
 214int ibmebus_request_irq(u32 ist, irq_handler_t handler,
 215                        unsigned long irq_flags, const char *devname,
 216                        void *dev_id)
 217{
 218        unsigned int irq = irq_create_mapping(NULL, ist);
 219
 220        if (irq == NO_IRQ)
 221                return -EINVAL;
 222
 223        return request_irq(irq, handler, irq_flags, devname, dev_id);
 224}
 225EXPORT_SYMBOL(ibmebus_request_irq);
 226
 227void ibmebus_free_irq(u32 ist, void *dev_id)
 228{
 229        unsigned int irq = irq_find_mapping(NULL, ist);
 230
 231        free_irq(irq, dev_id);
 232        irq_dispose_mapping(irq);
 233}
 234EXPORT_SYMBOL(ibmebus_free_irq);
 235
 236static char *ibmebus_chomp(const char *in, size_t count)
 237{
 238        char *out = kmalloc(count + 1, GFP_KERNEL);
 239
 240        if (!out)
 241                return NULL;
 242
 243        memcpy(out, in, count);
 244        out[count] = '\0';
 245        if (out[count - 1] == '\n')
 246                out[count - 1] = '\0';
 247
 248        return out;
 249}
 250
 251static ssize_t ibmebus_store_probe(struct bus_type *bus,
 252                                   const char *buf, size_t count)
 253{
 254        struct device_node *dn = NULL;
 255        char *path;
 256        ssize_t rc = 0;
 257
 258        path = ibmebus_chomp(buf, count);
 259        if (!path)
 260                return -ENOMEM;
 261
 262        if (bus_find_device(&ibmebus_bus_type, NULL, path,
 263                            ibmebus_match_path)) {
 264                printk(KERN_WARNING "%s: %s has already been probed\n",
 265                       __func__, path);
 266                rc = -EEXIST;
 267                goto out;
 268        }
 269
 270        if ((dn = of_find_node_by_path(path))) {
 271                rc = ibmebus_create_device(dn);
 272                of_node_put(dn);
 273        } else {
 274                printk(KERN_WARNING "%s: no such device node: %s\n",
 275                       __func__, path);
 276                rc = -ENODEV;
 277        }
 278
 279out:
 280        kfree(path);
 281        if (rc)
 282                return rc;
 283        return count;
 284}
 285
 286static ssize_t ibmebus_store_remove(struct bus_type *bus,
 287                                    const char *buf, size_t count)
 288{
 289        struct device *dev;
 290        char *path;
 291
 292        path = ibmebus_chomp(buf, count);
 293        if (!path)
 294                return -ENOMEM;
 295
 296        if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
 297                                   ibmebus_match_path))) {
 298                of_device_unregister(to_platform_device(dev));
 299
 300                kfree(path);
 301                return count;
 302        } else {
 303                printk(KERN_WARNING "%s: %s not on the bus\n",
 304                       __func__, path);
 305
 306                kfree(path);
 307                return -ENODEV;
 308        }
 309}
 310
 311static struct bus_attribute ibmebus_bus_attrs[] = {
 312        __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
 313        __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
 314        __ATTR_NULL
 315};
 316
 317struct bus_type ibmebus_bus_type = {
 318        .uevent    = of_device_uevent,
 319        .bus_attrs = ibmebus_bus_attrs
 320};
 321EXPORT_SYMBOL(ibmebus_bus_type);
 322
 323static int __init ibmebus_bus_init(void)
 324{
 325        int err;
 326
 327        printk(KERN_INFO "IBM eBus Device Driver\n");
 328
 329        err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
 330        if (err) {
 331                printk(KERN_ERR "%s: failed to register IBM eBus.\n",
 332                       __func__);
 333                return err;
 334        }
 335
 336        err = device_register(&ibmebus_bus_device);
 337        if (err) {
 338                printk(KERN_WARNING "%s: device_register returned %i\n",
 339                       __func__, err);
 340                bus_unregister(&ibmebus_bus_type);
 341
 342                return err;
 343        }
 344
 345        err = ibmebus_create_devices(ibmebus_matches);
 346        if (err) {
 347                device_unregister(&ibmebus_bus_device);
 348                bus_unregister(&ibmebus_bus_type);
 349                return err;
 350        }
 351
 352        return 0;
 353}
 354postcore_initcall(ibmebus_bus_init);
 355