linux/drivers/char/xilinx_hwicap/xilinx_hwicap.c
<<
>>
Prefs
   1/*****************************************************************************
   2 *
   3 *     Author: Xilinx, Inc.
   4 *
   5 *     This program is free software; you can redistribute it and/or modify it
   6 *     under the terms of the GNU General Public License as published by the
   7 *     Free Software Foundation; either version 2 of the License, or (at your
   8 *     option) any later version.
   9 *
  10 *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
  11 *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
  12 *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,
  13 *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
  14 *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
  15 *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
  16 *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
  17 *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY
  18 *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
  19 *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
  20 *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
  21 *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22 *     FOR A PARTICULAR PURPOSE.
  23 *
  24 *     (c) Copyright 2002 Xilinx Inc., Systems Engineering Group
  25 *     (c) Copyright 2004 Xilinx Inc., Systems Engineering Group
  26 *     (c) Copyright 2007-2008 Xilinx Inc.
  27 *     All rights reserved.
  28 *
  29 *     You should have received a copy of the GNU General Public License along
  30 *     with this program; if not, write to the Free Software Foundation, Inc.,
  31 *     675 Mass Ave, Cambridge, MA 02139, USA.
  32 *
  33 *****************************************************************************/
  34
  35/*
  36 * This is the code behind /dev/icap* -- it allows a user-space
  37 * application to use the Xilinx ICAP subsystem.
  38 *
  39 * The following operations are possible:
  40 *
  41 * open         open the port and initialize for access.
  42 * release      release port
  43 * write        Write a bitstream to the configuration processor.
  44 * read         Read a data stream from the configuration processor.
  45 *
  46 * After being opened, the port is initialized and accessed to avoid a
  47 * corrupted first read which may occur with some hardware.  The port
  48 * is left in a desynched state, requiring that a synch sequence be
  49 * transmitted before any valid configuration data.  A user will have
  50 * exclusive access to the device while it remains open, and the state
  51 * of the ICAP cannot be guaranteed after the device is closed.  Note
  52 * that a complete reset of the core and the state of the ICAP cannot
  53 * be performed on many versions of the cores, hence users of this
  54 * device should avoid making inconsistent accesses to the device.  In
  55 * particular, accessing the read interface, without first generating
  56 * a write containing a readback packet can leave the ICAP in an
  57 * inaccessible state.
  58 *
  59 * Note that in order to use the read interface, it is first necessary
  60 * to write a request packet to the write interface.  i.e., it is not
  61 * possible to simply readback the bitstream (or any configuration
  62 * bits) from a device without specifically requesting them first.
  63 * The code to craft such packets is intended to be part of the
  64 * user-space application code that uses this device.  The simplest
  65 * way to use this interface is simply:
  66 *
  67 * cp foo.bit /dev/icap0
  68 *
  69 * Note that unless foo.bit is an appropriately constructed partial
  70 * bitstream, this has a high likelyhood of overwriting the design
  71 * currently programmed in the FPGA.
  72 */
  73
  74#include <linux/module.h>
  75#include <linux/kernel.h>
  76#include <linux/types.h>
  77#include <linux/ioport.h>
  78#include <linux/interrupt.h>
  79#include <linux/fcntl.h>
  80#include <linux/init.h>
  81#include <linux/poll.h>
  82#include <linux/proc_fs.h>
  83#include <linux/mutex.h>
  84#include <linux/smp_lock.h>
  85#include <linux/sysctl.h>
  86#include <linux/fs.h>
  87#include <linux/cdev.h>
  88#include <linux/platform_device.h>
  89
  90#include <asm/io.h>
  91#include <asm/uaccess.h>
  92#include <asm/system.h>
  93
  94#ifdef CONFIG_OF
  95/* For open firmware. */
  96#include <linux/of_device.h>
  97#include <linux/of_platform.h>
  98#endif
  99
 100#include "xilinx_hwicap.h"
 101#include "buffer_icap.h"
 102#include "fifo_icap.h"
 103
 104#define DRIVER_NAME "icap"
 105
 106#define HWICAP_REGS   (0x10000)
 107
 108#define XHWICAP_MAJOR 259
 109#define XHWICAP_MINOR 0
 110#define HWICAP_DEVICES 1
 111
 112/* An array, which is set to true when the device is registered. */
 113static bool probed_devices[HWICAP_DEVICES];
 114static struct mutex icap_sem;
 115
 116static struct class *icap_class;
 117
 118#define UNIMPLEMENTED 0xFFFF
 119
 120static const struct config_registers v2_config_registers = {
 121        .CRC = 0,
 122        .FAR = 1,
 123        .FDRI = 2,
 124        .FDRO = 3,
 125        .CMD = 4,
 126        .CTL = 5,
 127        .MASK = 6,
 128        .STAT = 7,
 129        .LOUT = 8,
 130        .COR = 9,
 131        .MFWR = 10,
 132        .FLR = 11,
 133        .KEY = 12,
 134        .CBC = 13,
 135        .IDCODE = 14,
 136        .AXSS = UNIMPLEMENTED,
 137        .C0R_1 = UNIMPLEMENTED,
 138        .CSOB = UNIMPLEMENTED,
 139        .WBSTAR = UNIMPLEMENTED,
 140        .TIMER = UNIMPLEMENTED,
 141        .BOOTSTS = UNIMPLEMENTED,
 142        .CTL_1 = UNIMPLEMENTED,
 143};
 144
 145static const struct config_registers v4_config_registers = {
 146        .CRC = 0,
 147        .FAR = 1,
 148        .FDRI = 2,
 149        .FDRO = 3,
 150        .CMD = 4,
 151        .CTL = 5,
 152        .MASK = 6,
 153        .STAT = 7,
 154        .LOUT = 8,
 155        .COR = 9,
 156        .MFWR = 10,
 157        .FLR = UNIMPLEMENTED,
 158        .KEY = UNIMPLEMENTED,
 159        .CBC = 11,
 160        .IDCODE = 12,
 161        .AXSS = 13,
 162        .C0R_1 = UNIMPLEMENTED,
 163        .CSOB = UNIMPLEMENTED,
 164        .WBSTAR = UNIMPLEMENTED,
 165        .TIMER = UNIMPLEMENTED,
 166        .BOOTSTS = UNIMPLEMENTED,
 167        .CTL_1 = UNIMPLEMENTED,
 168};
 169static const struct config_registers v5_config_registers = {
 170        .CRC = 0,
 171        .FAR = 1,
 172        .FDRI = 2,
 173        .FDRO = 3,
 174        .CMD = 4,
 175        .CTL = 5,
 176        .MASK = 6,
 177        .STAT = 7,
 178        .LOUT = 8,
 179        .COR = 9,
 180        .MFWR = 10,
 181        .FLR = UNIMPLEMENTED,
 182        .KEY = UNIMPLEMENTED,
 183        .CBC = 11,
 184        .IDCODE = 12,
 185        .AXSS = 13,
 186        .C0R_1 = 14,
 187        .CSOB = 15,
 188        .WBSTAR = 16,
 189        .TIMER = 17,
 190        .BOOTSTS = 18,
 191        .CTL_1 = 19,
 192};
 193
 194/**
 195 * hwicap_command_desync - Send a DESYNC command to the ICAP port.
 196 * @drvdata: a pointer to the drvdata.
 197 *
 198 * This command desynchronizes the ICAP After this command, a
 199 * bitstream containing a NULL packet, followed by a SYNCH packet is
 200 * required before the ICAP will recognize commands.
 201 */
 202static int hwicap_command_desync(struct hwicap_drvdata *drvdata)
 203{
 204        u32 buffer[4];
 205        u32 index = 0;
 206
 207        /*
 208         * Create the data to be written to the ICAP.
 209         */
 210        buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;
 211        buffer[index++] = XHI_CMD_DESYNCH;
 212        buffer[index++] = XHI_NOOP_PACKET;
 213        buffer[index++] = XHI_NOOP_PACKET;
 214
 215        /*
 216         * Write the data to the FIFO and intiate the transfer of data present
 217         * in the FIFO to the ICAP device.
 218         */
 219        return drvdata->config->set_configuration(drvdata,
 220                        &buffer[0], index);
 221}
 222
 223/**
 224 * hwicap_get_configuration_register - Query a configuration register.
 225 * @drvdata: a pointer to the drvdata.
 226 * @reg: a constant which represents the configuration
 227 *              register value to be returned.
 228 *              Examples:  XHI_IDCODE, XHI_FLR.
 229 * @reg_data: returns the value of the register.
 230 *
 231 * Sends a query packet to the ICAP and then receives the response.
 232 * The icap is left in Synched state.
 233 */
 234static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
 235                u32 reg, u32 *reg_data)
 236{
 237        int status;
 238        u32 buffer[6];
 239        u32 index = 0;
 240
 241        /*
 242         * Create the data to be written to the ICAP.
 243         */
 244        buffer[index++] = XHI_DUMMY_PACKET;
 245        buffer[index++] = XHI_NOOP_PACKET;
 246        buffer[index++] = XHI_SYNC_PACKET;
 247        buffer[index++] = XHI_NOOP_PACKET;
 248        buffer[index++] = XHI_NOOP_PACKET;
 249
 250        /*
 251         * Write the data to the FIFO and initiate the transfer of data present
 252         * in the FIFO to the ICAP device.
 253         */
 254        status = drvdata->config->set_configuration(drvdata,
 255                                                    &buffer[0], index);
 256        if (status)
 257                return status;
 258
 259        /* If the syncword was not found, then we need to start over. */
 260        status = drvdata->config->get_status(drvdata);
 261        if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK)
 262                return -EIO;
 263
 264        index = 0;
 265        buffer[index++] = hwicap_type_1_read(reg) | 1;
 266        buffer[index++] = XHI_NOOP_PACKET;
 267        buffer[index++] = XHI_NOOP_PACKET;
 268
 269        /*
 270         * Write the data to the FIFO and intiate the transfer of data present
 271         * in the FIFO to the ICAP device.
 272         */
 273        status = drvdata->config->set_configuration(drvdata,
 274                        &buffer[0], index);
 275        if (status)
 276                return status;
 277
 278        /*
 279         * Read the configuration register
 280         */
 281        status = drvdata->config->get_configuration(drvdata, reg_data, 1);
 282        if (status)
 283                return status;
 284
 285        return 0;
 286}
 287
 288static int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)
 289{
 290        int status;
 291        u32 idcode;
 292
 293        dev_dbg(drvdata->dev, "initializing\n");
 294
 295        /* Abort any current transaction, to make sure we have the
 296         * ICAP in a good state. */
 297        dev_dbg(drvdata->dev, "Reset...\n");
 298        drvdata->config->reset(drvdata);
 299
 300        dev_dbg(drvdata->dev, "Desync...\n");
 301        status = hwicap_command_desync(drvdata);
 302        if (status)
 303                return status;
 304
 305        /* Attempt to read the IDCODE from ICAP.  This
 306         * may not be returned correctly, due to the design of the
 307         * hardware.
 308         */
 309        dev_dbg(drvdata->dev, "Reading IDCODE...\n");
 310        status = hwicap_get_configuration_register(
 311                        drvdata, drvdata->config_regs->IDCODE, &idcode);
 312        dev_dbg(drvdata->dev, "IDCODE = %x\n", idcode);
 313        if (status)
 314                return status;
 315
 316        dev_dbg(drvdata->dev, "Desync...\n");
 317        status = hwicap_command_desync(drvdata);
 318        if (status)
 319                return status;
 320
 321        return 0;
 322}
 323
 324static ssize_t
 325hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 326{
 327        struct hwicap_drvdata *drvdata = file->private_data;
 328        ssize_t bytes_to_read = 0;
 329        u32 *kbuf;
 330        u32 words;
 331        u32 bytes_remaining;
 332        int status;
 333
 334        status = mutex_lock_interruptible(&drvdata->sem);
 335        if (status)
 336                return status;
 337
 338        if (drvdata->read_buffer_in_use) {
 339                /* If there are leftover bytes in the buffer, just */
 340                /* return them and don't try to read more from the */
 341                /* ICAP device. */
 342                bytes_to_read =
 343                        (count < drvdata->read_buffer_in_use) ? count :
 344                        drvdata->read_buffer_in_use;
 345
 346                /* Return the data currently in the read buffer. */
 347                if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) {
 348                        status = -EFAULT;
 349                        goto error;
 350                }
 351                drvdata->read_buffer_in_use -= bytes_to_read;
 352                memmove(drvdata->read_buffer,
 353                       drvdata->read_buffer + bytes_to_read,
 354                       4 - bytes_to_read);
 355        } else {
 356                /* Get new data from the ICAP, and return was was requested. */
 357                kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);
 358                if (!kbuf) {
 359                        status = -ENOMEM;
 360                        goto error;
 361                }
 362
 363                /* The ICAP device is only able to read complete */
 364                /* words.  If a number of bytes that do not correspond */
 365                /* to complete words is requested, then we read enough */
 366                /* words to get the required number of bytes, and then */
 367                /* save the remaining bytes for the next read. */
 368
 369                /* Determine the number of words to read, rounding up */
 370                /* if necessary. */
 371                words = ((count + 3) >> 2);
 372                bytes_to_read = words << 2;
 373
 374                if (bytes_to_read > PAGE_SIZE)
 375                        bytes_to_read = PAGE_SIZE;
 376
 377                /* Ensure we only read a complete number of words. */
 378                bytes_remaining = bytes_to_read & 3;
 379                bytes_to_read &= ~3;
 380                words = bytes_to_read >> 2;
 381
 382                status = drvdata->config->get_configuration(drvdata,
 383                                kbuf, words);
 384
 385                /* If we didn't read correctly, then bail out. */
 386                if (status) {
 387                        free_page((unsigned long)kbuf);
 388                        goto error;
 389                }
 390
 391                /* If we fail to return the data to the user, then bail out. */
 392                if (copy_to_user(buf, kbuf, bytes_to_read)) {
 393                        free_page((unsigned long)kbuf);
 394                        status = -EFAULT;
 395                        goto error;
 396                }
 397                memcpy(drvdata->read_buffer,
 398                       kbuf,
 399                       bytes_remaining);
 400                drvdata->read_buffer_in_use = bytes_remaining;
 401                free_page((unsigned long)kbuf);
 402        }
 403        status = bytes_to_read;
 404 error:
 405        mutex_unlock(&drvdata->sem);
 406        return status;
 407}
 408
 409static ssize_t
 410hwicap_write(struct file *file, const char __user *buf,
 411                size_t count, loff_t *ppos)
 412{
 413        struct hwicap_drvdata *drvdata = file->private_data;
 414        ssize_t written = 0;
 415        ssize_t left = count;
 416        u32 *kbuf;
 417        ssize_t len;
 418        ssize_t status;
 419
 420        status = mutex_lock_interruptible(&drvdata->sem);
 421        if (status)
 422                return status;
 423
 424        left += drvdata->write_buffer_in_use;
 425
 426        /* Only write multiples of 4 bytes. */
 427        if (left < 4) {
 428                status = 0;
 429                goto error;
 430        }
 431
 432        kbuf = (u32 *) __get_free_page(GFP_KERNEL);
 433        if (!kbuf) {
 434                status = -ENOMEM;
 435                goto error;
 436        }
 437
 438        while (left > 3) {
 439                /* only write multiples of 4 bytes, so there might */
 440                /* be as many as 3 bytes left (at the end). */
 441                len = left;
 442
 443                if (len > PAGE_SIZE)
 444                        len = PAGE_SIZE;
 445                len &= ~3;
 446
 447                if (drvdata->write_buffer_in_use) {
 448                        memcpy(kbuf, drvdata->write_buffer,
 449                                        drvdata->write_buffer_in_use);
 450                        if (copy_from_user(
 451                            (((char *)kbuf) + drvdata->write_buffer_in_use),
 452                            buf + written,
 453                            len - (drvdata->write_buffer_in_use))) {
 454                                free_page((unsigned long)kbuf);
 455                                status = -EFAULT;
 456                                goto error;
 457                        }
 458                } else {
 459                        if (copy_from_user(kbuf, buf + written, len)) {
 460                                free_page((unsigned long)kbuf);
 461                                status = -EFAULT;
 462                                goto error;
 463                        }
 464                }
 465
 466                status = drvdata->config->set_configuration(drvdata,
 467                                kbuf, len >> 2);
 468
 469                if (status) {
 470                        free_page((unsigned long)kbuf);
 471                        status = -EFAULT;
 472                        goto error;
 473                }
 474                if (drvdata->write_buffer_in_use) {
 475                        len -= drvdata->write_buffer_in_use;
 476                        left -= drvdata->write_buffer_in_use;
 477                        drvdata->write_buffer_in_use = 0;
 478                }
 479                written += len;
 480                left -= len;
 481        }
 482        if ((left > 0) && (left < 4)) {
 483                if (!copy_from_user(drvdata->write_buffer,
 484                                                buf + written, left)) {
 485                        drvdata->write_buffer_in_use = left;
 486                        written += left;
 487                        left = 0;
 488                }
 489        }
 490
 491        free_page((unsigned long)kbuf);
 492        status = written;
 493 error:
 494        mutex_unlock(&drvdata->sem);
 495        return status;
 496}
 497
 498static int hwicap_open(struct inode *inode, struct file *file)
 499{
 500        struct hwicap_drvdata *drvdata;
 501        int status;
 502
 503        lock_kernel();
 504        drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
 505
 506        status = mutex_lock_interruptible(&drvdata->sem);
 507        if (status)
 508                goto out;
 509
 510        if (drvdata->is_open) {
 511                status = -EBUSY;
 512                goto error;
 513        }
 514
 515        status = hwicap_initialize_hwicap(drvdata);
 516        if (status) {
 517                dev_err(drvdata->dev, "Failed to open file");
 518                goto error;
 519        }
 520
 521        file->private_data = drvdata;
 522        drvdata->write_buffer_in_use = 0;
 523        drvdata->read_buffer_in_use = 0;
 524        drvdata->is_open = 1;
 525
 526 error:
 527        mutex_unlock(&drvdata->sem);
 528 out:
 529        unlock_kernel();
 530        return status;
 531}
 532
 533static int hwicap_release(struct inode *inode, struct file *file)
 534{
 535        struct hwicap_drvdata *drvdata = file->private_data;
 536        int i;
 537        int status = 0;
 538
 539        mutex_lock(&drvdata->sem);
 540
 541        if (drvdata->write_buffer_in_use) {
 542                /* Flush write buffer. */
 543                for (i = drvdata->write_buffer_in_use; i < 4; i++)
 544                        drvdata->write_buffer[i] = 0;
 545
 546                status = drvdata->config->set_configuration(drvdata,
 547                                (u32 *) drvdata->write_buffer, 1);
 548                if (status)
 549                        goto error;
 550        }
 551
 552        status = hwicap_command_desync(drvdata);
 553        if (status)
 554                goto error;
 555
 556 error:
 557        drvdata->is_open = 0;
 558        mutex_unlock(&drvdata->sem);
 559        return status;
 560}
 561
 562static const struct file_operations hwicap_fops = {
 563        .owner = THIS_MODULE,
 564        .write = hwicap_write,
 565        .read = hwicap_read,
 566        .open = hwicap_open,
 567        .release = hwicap_release,
 568};
 569
 570static int __devinit hwicap_setup(struct device *dev, int id,
 571                const struct resource *regs_res,
 572                const struct hwicap_driver_config *config,
 573                const struct config_registers *config_regs)
 574{
 575        dev_t devt;
 576        struct hwicap_drvdata *drvdata = NULL;
 577        int retval = 0;
 578
 579        dev_info(dev, "Xilinx icap port driver\n");
 580
 581        mutex_lock(&icap_sem);
 582
 583        if (id < 0) {
 584                for (id = 0; id < HWICAP_DEVICES; id++)
 585                        if (!probed_devices[id])
 586                                break;
 587        }
 588        if (id < 0 || id >= HWICAP_DEVICES) {
 589                mutex_unlock(&icap_sem);
 590                dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);
 591                return -EINVAL;
 592        }
 593        if (probed_devices[id]) {
 594                mutex_unlock(&icap_sem);
 595                dev_err(dev, "cannot assign to %s%i; it is already in use\n",
 596                        DRIVER_NAME, id);
 597                return -EBUSY;
 598        }
 599
 600        probed_devices[id] = 1;
 601        mutex_unlock(&icap_sem);
 602
 603        devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
 604
 605        drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
 606        if (!drvdata) {
 607                dev_err(dev, "Couldn't allocate device private record\n");
 608                retval = -ENOMEM;
 609                goto failed0;
 610        }
 611        dev_set_drvdata(dev, (void *)drvdata);
 612
 613        if (!regs_res) {
 614                dev_err(dev, "Couldn't get registers resource\n");
 615                retval = -EFAULT;
 616                goto failed1;
 617        }
 618
 619        drvdata->mem_start = regs_res->start;
 620        drvdata->mem_end = regs_res->end;
 621        drvdata->mem_size = regs_res->end - regs_res->start + 1;
 622
 623        if (!request_mem_region(drvdata->mem_start,
 624                                        drvdata->mem_size, DRIVER_NAME)) {
 625                dev_err(dev, "Couldn't lock memory region at %Lx\n",
 626                        (unsigned long long) regs_res->start);
 627                retval = -EBUSY;
 628                goto failed1;
 629        }
 630
 631        drvdata->devt = devt;
 632        drvdata->dev = dev;
 633        drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
 634        if (!drvdata->base_address) {
 635                dev_err(dev, "ioremap() failed\n");
 636                goto failed2;
 637        }
 638
 639        drvdata->config = config;
 640        drvdata->config_regs = config_regs;
 641
 642        mutex_init(&drvdata->sem);
 643        drvdata->is_open = 0;
 644
 645        dev_info(dev, "ioremap %llx to %p with size %llx\n",
 646                 (unsigned long long) drvdata->mem_start,
 647                 drvdata->base_address,
 648                 (unsigned long long) drvdata->mem_size);
 649
 650        cdev_init(&drvdata->cdev, &hwicap_fops);
 651        drvdata->cdev.owner = THIS_MODULE;
 652        retval = cdev_add(&drvdata->cdev, devt, 1);
 653        if (retval) {
 654                dev_err(dev, "cdev_add() failed\n");
 655                goto failed3;
 656        }
 657
 658        device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
 659        return 0;               /* success */
 660
 661 failed3:
 662        iounmap(drvdata->base_address);
 663
 664 failed2:
 665        release_mem_region(regs_res->start, drvdata->mem_size);
 666
 667 failed1:
 668        kfree(drvdata);
 669
 670 failed0:
 671        mutex_lock(&icap_sem);
 672        probed_devices[id] = 0;
 673        mutex_unlock(&icap_sem);
 674
 675        return retval;
 676}
 677
 678static struct hwicap_driver_config buffer_icap_config = {
 679        .get_configuration = buffer_icap_get_configuration,
 680        .set_configuration = buffer_icap_set_configuration,
 681        .get_status = buffer_icap_get_status,
 682        .reset = buffer_icap_reset,
 683};
 684
 685static struct hwicap_driver_config fifo_icap_config = {
 686        .get_configuration = fifo_icap_get_configuration,
 687        .set_configuration = fifo_icap_set_configuration,
 688        .get_status = fifo_icap_get_status,
 689        .reset = fifo_icap_reset,
 690};
 691
 692static int __devexit hwicap_remove(struct device *dev)
 693{
 694        struct hwicap_drvdata *drvdata;
 695
 696        drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);
 697
 698        if (!drvdata)
 699                return 0;
 700
 701        device_destroy(icap_class, drvdata->devt);
 702        cdev_del(&drvdata->cdev);
 703        iounmap(drvdata->base_address);
 704        release_mem_region(drvdata->mem_start, drvdata->mem_size);
 705        kfree(drvdata);
 706        dev_set_drvdata(dev, NULL);
 707
 708        mutex_lock(&icap_sem);
 709        probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
 710        mutex_unlock(&icap_sem);
 711        return 0;               /* success */
 712}
 713
 714static int __devinit hwicap_drv_probe(struct platform_device *pdev)
 715{
 716        struct resource *res;
 717        const struct config_registers *regs;
 718        const char *family;
 719
 720        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 721        if (!res)
 722                return -ENODEV;
 723
 724        /* It's most likely that we're using V4, if the family is not
 725           specified */
 726        regs = &v4_config_registers;
 727        family = pdev->dev.platform_data;
 728
 729        if (family) {
 730                if (!strcmp(family, "virtex2p")) {
 731                        regs = &v2_config_registers;
 732                } else if (!strcmp(family, "virtex4")) {
 733                        regs = &v4_config_registers;
 734                } else if (!strcmp(family, "virtex5")) {
 735                        regs = &v5_config_registers;
 736                }
 737        }
 738
 739        return hwicap_setup(&pdev->dev, pdev->id, res,
 740                        &buffer_icap_config, regs);
 741}
 742
 743static int __devexit hwicap_drv_remove(struct platform_device *pdev)
 744{
 745        return hwicap_remove(&pdev->dev);
 746}
 747
 748static struct platform_driver hwicap_platform_driver = {
 749        .probe = hwicap_drv_probe,
 750        .remove = hwicap_drv_remove,
 751        .driver = {
 752                .owner = THIS_MODULE,
 753                .name = DRIVER_NAME,
 754        },
 755};
 756
 757/* ---------------------------------------------------------------------
 758 * OF bus binding
 759 */
 760
 761#if defined(CONFIG_OF)
 762static int __devinit
 763hwicap_of_probe(struct of_device *op, const struct of_device_id *match)
 764{
 765        struct resource res;
 766        const unsigned int *id;
 767        const char *family;
 768        int rc;
 769        const struct hwicap_driver_config *config = match->data;
 770        const struct config_registers *regs;
 771
 772        dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match);
 773
 774        rc = of_address_to_resource(op->node, 0, &res);
 775        if (rc) {
 776                dev_err(&op->dev, "invalid address\n");
 777                return rc;
 778        }
 779
 780        id = of_get_property(op->node, "port-number", NULL);
 781
 782        /* It's most likely that we're using V4, if the family is not
 783           specified */
 784        regs = &v4_config_registers;
 785        family = of_get_property(op->node, "xlnx,family", NULL);
 786
 787        if (family) {
 788                if (!strcmp(family, "virtex2p")) {
 789                        regs = &v2_config_registers;
 790                } else if (!strcmp(family, "virtex4")) {
 791                        regs = &v4_config_registers;
 792                } else if (!strcmp(family, "virtex5")) {
 793                        regs = &v5_config_registers;
 794                }
 795        }
 796        return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
 797                        regs);
 798}
 799
 800static int __devexit hwicap_of_remove(struct of_device *op)
 801{
 802        return hwicap_remove(&op->dev);
 803}
 804
 805/* Match table for of_platform binding */
 806static const struct of_device_id __devinitconst hwicap_of_match[] = {
 807        { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
 808        { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
 809        {},
 810};
 811MODULE_DEVICE_TABLE(of, hwicap_of_match);
 812
 813static struct of_platform_driver hwicap_of_driver = {
 814        .owner = THIS_MODULE,
 815        .name = DRIVER_NAME,
 816        .match_table = hwicap_of_match,
 817        .probe = hwicap_of_probe,
 818        .remove = __devexit_p(hwicap_of_remove),
 819        .driver = {
 820                .name = DRIVER_NAME,
 821        },
 822};
 823
 824/* Registration helpers to keep the number of #ifdefs to a minimum */
 825static inline int __init hwicap_of_register(void)
 826{
 827        pr_debug("hwicap: calling of_register_platform_driver()\n");
 828        return of_register_platform_driver(&hwicap_of_driver);
 829}
 830
 831static inline void __exit hwicap_of_unregister(void)
 832{
 833        of_unregister_platform_driver(&hwicap_of_driver);
 834}
 835#else /* CONFIG_OF */
 836/* CONFIG_OF not enabled; do nothing helpers */
 837static inline int __init hwicap_of_register(void) { return 0; }
 838static inline void __exit hwicap_of_unregister(void) { }
 839#endif /* CONFIG_OF */
 840
 841static int __init hwicap_module_init(void)
 842{
 843        dev_t devt;
 844        int retval;
 845
 846        icap_class = class_create(THIS_MODULE, "xilinx_config");
 847        mutex_init(&icap_sem);
 848
 849        devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
 850        retval = register_chrdev_region(devt,
 851                                        HWICAP_DEVICES,
 852                                        DRIVER_NAME);
 853        if (retval < 0)
 854                return retval;
 855
 856        retval = platform_driver_register(&hwicap_platform_driver);
 857
 858        if (retval)
 859                goto failed1;
 860
 861        retval = hwicap_of_register();
 862
 863        if (retval)
 864                goto failed2;
 865
 866        return retval;
 867
 868 failed2:
 869        platform_driver_unregister(&hwicap_platform_driver);
 870
 871 failed1:
 872        unregister_chrdev_region(devt, HWICAP_DEVICES);
 873
 874        return retval;
 875}
 876
 877static void __exit hwicap_module_cleanup(void)
 878{
 879        dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
 880
 881        class_destroy(icap_class);
 882
 883        platform_driver_unregister(&hwicap_platform_driver);
 884
 885        hwicap_of_unregister();
 886
 887        unregister_chrdev_region(devt, HWICAP_DEVICES);
 888}
 889
 890module_init(hwicap_module_init);
 891module_exit(hwicap_module_cleanup);
 892
 893MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group");
 894MODULE_DESCRIPTION("Xilinx ICAP Port Driver");
 895MODULE_LICENSE("GPL");
 896