root/drivers/char/xilinx_hwicap/xilinx_hwicap.c

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

DEFINITIONS

This source file includes following definitions.
  1. hwicap_command_desync
  2. hwicap_get_configuration_register
  3. hwicap_initialize_hwicap
  4. hwicap_read
  5. hwicap_write
  6. hwicap_open
  7. hwicap_release
  8. hwicap_setup
  9. hwicap_remove
  10. hwicap_of_probe
  11. hwicap_of_probe
  12. hwicap_drv_probe
  13. hwicap_drv_remove
  14. hwicap_module_init
  15. hwicap_module_cleanup

   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 likelihood 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/sysctl.h>
  85 #include <linux/fs.h>
  86 #include <linux/cdev.h>
  87 #include <linux/platform_device.h>
  88 #include <linux/slab.h>
  89 #include <linux/io.h>
  90 #include <linux/uaccess.h>
  91 
  92 #ifdef CONFIG_OF
  93 /* For open firmware. */
  94 #include <linux/of_address.h>
  95 #include <linux/of_device.h>
  96 #include <linux/of_platform.h>
  97 #endif
  98 
  99 #include "xilinx_hwicap.h"
 100 #include "buffer_icap.h"
 101 #include "fifo_icap.h"
 102 
 103 #define DRIVER_NAME "icap"
 104 
 105 #define HWICAP_REGS   (0x10000)
 106 
 107 #define XHWICAP_MAJOR 259
 108 #define XHWICAP_MINOR 0
 109 #define HWICAP_DEVICES 1
 110 
 111 /* An array, which is set to true when the device is registered. */
 112 static DEFINE_MUTEX(hwicap_mutex);
 113 static bool probed_devices[HWICAP_DEVICES];
 114 static struct mutex icap_sem;
 115 
 116 static struct class *icap_class;
 117 
 118 #define UNIMPLEMENTED 0xFFFF
 119 
 120 static 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 
 145 static 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 };
 169 
 170 static const struct config_registers v5_config_registers = {
 171         .CRC = 0,
 172         .FAR = 1,
 173         .FDRI = 2,
 174         .FDRO = 3,
 175         .CMD = 4,
 176         .CTL = 5,
 177         .MASK = 6,
 178         .STAT = 7,
 179         .LOUT = 8,
 180         .COR = 9,
 181         .MFWR = 10,
 182         .FLR = UNIMPLEMENTED,
 183         .KEY = UNIMPLEMENTED,
 184         .CBC = 11,
 185         .IDCODE = 12,
 186         .AXSS = 13,
 187         .C0R_1 = 14,
 188         .CSOB = 15,
 189         .WBSTAR = 16,
 190         .TIMER = 17,
 191         .BOOTSTS = 18,
 192         .CTL_1 = 19,
 193 };
 194 
 195 static const struct config_registers v6_config_registers = {
 196         .CRC = 0,
 197         .FAR = 1,
 198         .FDRI = 2,
 199         .FDRO = 3,
 200         .CMD = 4,
 201         .CTL = 5,
 202         .MASK = 6,
 203         .STAT = 7,
 204         .LOUT = 8,
 205         .COR = 9,
 206         .MFWR = 10,
 207         .FLR = UNIMPLEMENTED,
 208         .KEY = UNIMPLEMENTED,
 209         .CBC = 11,
 210         .IDCODE = 12,
 211         .AXSS = 13,
 212         .C0R_1 = 14,
 213         .CSOB = 15,
 214         .WBSTAR = 16,
 215         .TIMER = 17,
 216         .BOOTSTS = 22,
 217         .CTL_1 = 24,
 218 };
 219 
 220 /**
 221  * hwicap_command_desync - Send a DESYNC command to the ICAP port.
 222  * @drvdata: a pointer to the drvdata.
 223  *
 224  * Returns: '0' on success and failure value on error
 225  *
 226  * This command desynchronizes the ICAP After this command, a
 227  * bitstream containing a NULL packet, followed by a SYNCH packet is
 228  * required before the ICAP will recognize commands.
 229  */
 230 static int hwicap_command_desync(struct hwicap_drvdata *drvdata)
 231 {
 232         u32 buffer[4];
 233         u32 index = 0;
 234 
 235         /*
 236          * Create the data to be written to the ICAP.
 237          */
 238         buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;
 239         buffer[index++] = XHI_CMD_DESYNCH;
 240         buffer[index++] = XHI_NOOP_PACKET;
 241         buffer[index++] = XHI_NOOP_PACKET;
 242 
 243         /*
 244          * Write the data to the FIFO and intiate the transfer of data present
 245          * in the FIFO to the ICAP device.
 246          */
 247         return drvdata->config->set_configuration(drvdata,
 248                         &buffer[0], index);
 249 }
 250 
 251 /**
 252  * hwicap_get_configuration_register - Query a configuration register.
 253  * @drvdata: a pointer to the drvdata.
 254  * @reg: a constant which represents the configuration
 255  * register value to be returned.
 256  * Examples: XHI_IDCODE, XHI_FLR.
 257  * @reg_data: returns the value of the register.
 258  *
 259  * Returns: '0' on success and failure value on error
 260  *
 261  * Sends a query packet to the ICAP and then receives the response.
 262  * The icap is left in Synched state.
 263  */
 264 static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
 265                 u32 reg, u32 *reg_data)
 266 {
 267         int status;
 268         u32 buffer[6];
 269         u32 index = 0;
 270 
 271         /*
 272          * Create the data to be written to the ICAP.
 273          */
 274         buffer[index++] = XHI_DUMMY_PACKET;
 275         buffer[index++] = XHI_NOOP_PACKET;
 276         buffer[index++] = XHI_SYNC_PACKET;
 277         buffer[index++] = XHI_NOOP_PACKET;
 278         buffer[index++] = XHI_NOOP_PACKET;
 279 
 280         /*
 281          * Write the data to the FIFO and initiate the transfer of data present
 282          * in the FIFO to the ICAP device.
 283          */
 284         status = drvdata->config->set_configuration(drvdata,
 285                                                     &buffer[0], index);
 286         if (status)
 287                 return status;
 288 
 289         /* If the syncword was not found, then we need to start over. */
 290         status = drvdata->config->get_status(drvdata);
 291         if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK)
 292                 return -EIO;
 293 
 294         index = 0;
 295         buffer[index++] = hwicap_type_1_read(reg) | 1;
 296         buffer[index++] = XHI_NOOP_PACKET;
 297         buffer[index++] = XHI_NOOP_PACKET;
 298 
 299         /*
 300          * Write the data to the FIFO and intiate the transfer of data present
 301          * in the FIFO to the ICAP device.
 302          */
 303         status = drvdata->config->set_configuration(drvdata,
 304                         &buffer[0], index);
 305         if (status)
 306                 return status;
 307 
 308         /*
 309          * Read the configuration register
 310          */
 311         status = drvdata->config->get_configuration(drvdata, reg_data, 1);
 312         if (status)
 313                 return status;
 314 
 315         return 0;
 316 }
 317 
 318 static int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)
 319 {
 320         int status;
 321         u32 idcode;
 322 
 323         dev_dbg(drvdata->dev, "initializing\n");
 324 
 325         /* Abort any current transaction, to make sure we have the
 326          * ICAP in a good state.
 327          */
 328         dev_dbg(drvdata->dev, "Reset...\n");
 329         drvdata->config->reset(drvdata);
 330 
 331         dev_dbg(drvdata->dev, "Desync...\n");
 332         status = hwicap_command_desync(drvdata);
 333         if (status)
 334                 return status;
 335 
 336         /* Attempt to read the IDCODE from ICAP.  This
 337          * may not be returned correctly, due to the design of the
 338          * hardware.
 339          */
 340         dev_dbg(drvdata->dev, "Reading IDCODE...\n");
 341         status = hwicap_get_configuration_register(
 342                         drvdata, drvdata->config_regs->IDCODE, &idcode);
 343         dev_dbg(drvdata->dev, "IDCODE = %x\n", idcode);
 344         if (status)
 345                 return status;
 346 
 347         dev_dbg(drvdata->dev, "Desync...\n");
 348         status = hwicap_command_desync(drvdata);
 349         if (status)
 350                 return status;
 351 
 352         return 0;
 353 }
 354 
 355 static ssize_t
 356 hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 357 {
 358         struct hwicap_drvdata *drvdata = file->private_data;
 359         ssize_t bytes_to_read = 0;
 360         u32 *kbuf;
 361         u32 words;
 362         u32 bytes_remaining;
 363         int status;
 364 
 365         status = mutex_lock_interruptible(&drvdata->sem);
 366         if (status)
 367                 return status;
 368 
 369         if (drvdata->read_buffer_in_use) {
 370                 /* If there are leftover bytes in the buffer, just */
 371                 /* return them and don't try to read more from the */
 372                 /* ICAP device. */
 373                 bytes_to_read =
 374                         (count < drvdata->read_buffer_in_use) ? count :
 375                         drvdata->read_buffer_in_use;
 376 
 377                 /* Return the data currently in the read buffer. */
 378                 if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) {
 379                         status = -EFAULT;
 380                         goto error;
 381                 }
 382                 drvdata->read_buffer_in_use -= bytes_to_read;
 383                 memmove(drvdata->read_buffer,
 384                        drvdata->read_buffer + bytes_to_read,
 385                        4 - bytes_to_read);
 386         } else {
 387                 /* Get new data from the ICAP, and return was was requested. */
 388                 kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);
 389                 if (!kbuf) {
 390                         status = -ENOMEM;
 391                         goto error;
 392                 }
 393 
 394                 /* The ICAP device is only able to read complete */
 395                 /* words.  If a number of bytes that do not correspond */
 396                 /* to complete words is requested, then we read enough */
 397                 /* words to get the required number of bytes, and then */
 398                 /* save the remaining bytes for the next read. */
 399 
 400                 /* Determine the number of words to read, rounding up */
 401                 /* if necessary. */
 402                 words = ((count + 3) >> 2);
 403                 bytes_to_read = words << 2;
 404 
 405                 if (bytes_to_read > PAGE_SIZE)
 406                         bytes_to_read = PAGE_SIZE;
 407 
 408                 /* Ensure we only read a complete number of words. */
 409                 bytes_remaining = bytes_to_read & 3;
 410                 bytes_to_read &= ~3;
 411                 words = bytes_to_read >> 2;
 412 
 413                 status = drvdata->config->get_configuration(drvdata,
 414                                 kbuf, words);
 415 
 416                 /* If we didn't read correctly, then bail out. */
 417                 if (status) {
 418                         free_page((unsigned long)kbuf);
 419                         goto error;
 420                 }
 421 
 422                 /* If we fail to return the data to the user, then bail out. */
 423                 if (copy_to_user(buf, kbuf, bytes_to_read)) {
 424                         free_page((unsigned long)kbuf);
 425                         status = -EFAULT;
 426                         goto error;
 427                 }
 428                 memcpy(drvdata->read_buffer,
 429                        kbuf,
 430                        bytes_remaining);
 431                 drvdata->read_buffer_in_use = bytes_remaining;
 432                 free_page((unsigned long)kbuf);
 433         }
 434         status = bytes_to_read;
 435  error:
 436         mutex_unlock(&drvdata->sem);
 437         return status;
 438 }
 439 
 440 static ssize_t
 441 hwicap_write(struct file *file, const char __user *buf,
 442                 size_t count, loff_t *ppos)
 443 {
 444         struct hwicap_drvdata *drvdata = file->private_data;
 445         ssize_t written = 0;
 446         ssize_t left = count;
 447         u32 *kbuf;
 448         ssize_t len;
 449         ssize_t status;
 450 
 451         status = mutex_lock_interruptible(&drvdata->sem);
 452         if (status)
 453                 return status;
 454 
 455         left += drvdata->write_buffer_in_use;
 456 
 457         /* Only write multiples of 4 bytes. */
 458         if (left < 4) {
 459                 status = 0;
 460                 goto error;
 461         }
 462 
 463         kbuf = (u32 *) __get_free_page(GFP_KERNEL);
 464         if (!kbuf) {
 465                 status = -ENOMEM;
 466                 goto error;
 467         }
 468 
 469         while (left > 3) {
 470                 /* only write multiples of 4 bytes, so there might */
 471                 /* be as many as 3 bytes left (at the end). */
 472                 len = left;
 473 
 474                 if (len > PAGE_SIZE)
 475                         len = PAGE_SIZE;
 476                 len &= ~3;
 477 
 478                 if (drvdata->write_buffer_in_use) {
 479                         memcpy(kbuf, drvdata->write_buffer,
 480                                         drvdata->write_buffer_in_use);
 481                         if (copy_from_user(
 482                             (((char *)kbuf) + drvdata->write_buffer_in_use),
 483                             buf + written,
 484                             len - (drvdata->write_buffer_in_use))) {
 485                                 free_page((unsigned long)kbuf);
 486                                 status = -EFAULT;
 487                                 goto error;
 488                         }
 489                 } else {
 490                         if (copy_from_user(kbuf, buf + written, len)) {
 491                                 free_page((unsigned long)kbuf);
 492                                 status = -EFAULT;
 493                                 goto error;
 494                         }
 495                 }
 496 
 497                 status = drvdata->config->set_configuration(drvdata,
 498                                 kbuf, len >> 2);
 499 
 500                 if (status) {
 501                         free_page((unsigned long)kbuf);
 502                         status = -EFAULT;
 503                         goto error;
 504                 }
 505                 if (drvdata->write_buffer_in_use) {
 506                         len -= drvdata->write_buffer_in_use;
 507                         left -= drvdata->write_buffer_in_use;
 508                         drvdata->write_buffer_in_use = 0;
 509                 }
 510                 written += len;
 511                 left -= len;
 512         }
 513         if ((left > 0) && (left < 4)) {
 514                 if (!copy_from_user(drvdata->write_buffer,
 515                                                 buf + written, left)) {
 516                         drvdata->write_buffer_in_use = left;
 517                         written += left;
 518                         left = 0;
 519                 }
 520         }
 521 
 522         free_page((unsigned long)kbuf);
 523         status = written;
 524  error:
 525         mutex_unlock(&drvdata->sem);
 526         return status;
 527 }
 528 
 529 static int hwicap_open(struct inode *inode, struct file *file)
 530 {
 531         struct hwicap_drvdata *drvdata;
 532         int status;
 533 
 534         mutex_lock(&hwicap_mutex);
 535         drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
 536 
 537         status = mutex_lock_interruptible(&drvdata->sem);
 538         if (status)
 539                 goto out;
 540 
 541         if (drvdata->is_open) {
 542                 status = -EBUSY;
 543                 goto error;
 544         }
 545 
 546         status = hwicap_initialize_hwicap(drvdata);
 547         if (status) {
 548                 dev_err(drvdata->dev, "Failed to open file");
 549                 goto error;
 550         }
 551 
 552         file->private_data = drvdata;
 553         drvdata->write_buffer_in_use = 0;
 554         drvdata->read_buffer_in_use = 0;
 555         drvdata->is_open = 1;
 556 
 557  error:
 558         mutex_unlock(&drvdata->sem);
 559  out:
 560         mutex_unlock(&hwicap_mutex);
 561         return status;
 562 }
 563 
 564 static int hwicap_release(struct inode *inode, struct file *file)
 565 {
 566         struct hwicap_drvdata *drvdata = file->private_data;
 567         int i;
 568         int status = 0;
 569 
 570         mutex_lock(&drvdata->sem);
 571 
 572         if (drvdata->write_buffer_in_use) {
 573                 /* Flush write buffer. */
 574                 for (i = drvdata->write_buffer_in_use; i < 4; i++)
 575                         drvdata->write_buffer[i] = 0;
 576 
 577                 status = drvdata->config->set_configuration(drvdata,
 578                                 (u32 *) drvdata->write_buffer, 1);
 579                 if (status)
 580                         goto error;
 581         }
 582 
 583         status = hwicap_command_desync(drvdata);
 584         if (status)
 585                 goto error;
 586 
 587  error:
 588         drvdata->is_open = 0;
 589         mutex_unlock(&drvdata->sem);
 590         return status;
 591 }
 592 
 593 static const struct file_operations hwicap_fops = {
 594         .owner = THIS_MODULE,
 595         .write = hwicap_write,
 596         .read = hwicap_read,
 597         .open = hwicap_open,
 598         .release = hwicap_release,
 599         .llseek = noop_llseek,
 600 };
 601 
 602 static int hwicap_setup(struct device *dev, int id,
 603                 const struct resource *regs_res,
 604                 const struct hwicap_driver_config *config,
 605                 const struct config_registers *config_regs)
 606 {
 607         dev_t devt;
 608         struct hwicap_drvdata *drvdata = NULL;
 609         int retval = 0;
 610 
 611         dev_info(dev, "Xilinx icap port driver\n");
 612 
 613         mutex_lock(&icap_sem);
 614 
 615         if (id < 0) {
 616                 for (id = 0; id < HWICAP_DEVICES; id++)
 617                         if (!probed_devices[id])
 618                                 break;
 619         }
 620         if (id < 0 || id >= HWICAP_DEVICES) {
 621                 mutex_unlock(&icap_sem);
 622                 dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);
 623                 return -EINVAL;
 624         }
 625         if (probed_devices[id]) {
 626                 mutex_unlock(&icap_sem);
 627                 dev_err(dev, "cannot assign to %s%i; it is already in use\n",
 628                         DRIVER_NAME, id);
 629                 return -EBUSY;
 630         }
 631 
 632         probed_devices[id] = 1;
 633         mutex_unlock(&icap_sem);
 634 
 635         devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
 636 
 637         drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
 638         if (!drvdata) {
 639                 retval = -ENOMEM;
 640                 goto failed0;
 641         }
 642         dev_set_drvdata(dev, (void *)drvdata);
 643 
 644         if (!regs_res) {
 645                 dev_err(dev, "Couldn't get registers resource\n");
 646                 retval = -EFAULT;
 647                 goto failed1;
 648         }
 649 
 650         drvdata->mem_start = regs_res->start;
 651         drvdata->mem_end = regs_res->end;
 652         drvdata->mem_size = resource_size(regs_res);
 653 
 654         if (!request_mem_region(drvdata->mem_start,
 655                                         drvdata->mem_size, DRIVER_NAME)) {
 656                 dev_err(dev, "Couldn't lock memory region at %Lx\n",
 657                         (unsigned long long) regs_res->start);
 658                 retval = -EBUSY;
 659                 goto failed1;
 660         }
 661 
 662         drvdata->devt = devt;
 663         drvdata->dev = dev;
 664         drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
 665         if (!drvdata->base_address) {
 666                 dev_err(dev, "ioremap() failed\n");
 667                 retval = -ENOMEM;
 668                 goto failed2;
 669         }
 670 
 671         drvdata->config = config;
 672         drvdata->config_regs = config_regs;
 673 
 674         mutex_init(&drvdata->sem);
 675         drvdata->is_open = 0;
 676 
 677         dev_info(dev, "ioremap %llx to %p with size %llx\n",
 678                  (unsigned long long) drvdata->mem_start,
 679                  drvdata->base_address,
 680                  (unsigned long long) drvdata->mem_size);
 681 
 682         cdev_init(&drvdata->cdev, &hwicap_fops);
 683         drvdata->cdev.owner = THIS_MODULE;
 684         retval = cdev_add(&drvdata->cdev, devt, 1);
 685         if (retval) {
 686                 dev_err(dev, "cdev_add() failed\n");
 687                 goto failed3;
 688         }
 689 
 690         device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
 691         return 0;               /* success */
 692 
 693  failed3:
 694         iounmap(drvdata->base_address);
 695 
 696  failed2:
 697         release_mem_region(regs_res->start, drvdata->mem_size);
 698 
 699  failed1:
 700         kfree(drvdata);
 701 
 702  failed0:
 703         mutex_lock(&icap_sem);
 704         probed_devices[id] = 0;
 705         mutex_unlock(&icap_sem);
 706 
 707         return retval;
 708 }
 709 
 710 static struct hwicap_driver_config buffer_icap_config = {
 711         .get_configuration = buffer_icap_get_configuration,
 712         .set_configuration = buffer_icap_set_configuration,
 713         .get_status = buffer_icap_get_status,
 714         .reset = buffer_icap_reset,
 715 };
 716 
 717 static struct hwicap_driver_config fifo_icap_config = {
 718         .get_configuration = fifo_icap_get_configuration,
 719         .set_configuration = fifo_icap_set_configuration,
 720         .get_status = fifo_icap_get_status,
 721         .reset = fifo_icap_reset,
 722 };
 723 
 724 static int hwicap_remove(struct device *dev)
 725 {
 726         struct hwicap_drvdata *drvdata;
 727 
 728         drvdata = dev_get_drvdata(dev);
 729 
 730         if (!drvdata)
 731                 return 0;
 732 
 733         device_destroy(icap_class, drvdata->devt);
 734         cdev_del(&drvdata->cdev);
 735         iounmap(drvdata->base_address);
 736         release_mem_region(drvdata->mem_start, drvdata->mem_size);
 737         kfree(drvdata);
 738 
 739         mutex_lock(&icap_sem);
 740         probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
 741         mutex_unlock(&icap_sem);
 742         return 0;               /* success */
 743 }
 744 
 745 #ifdef CONFIG_OF
 746 static int hwicap_of_probe(struct platform_device *op,
 747                                      const struct hwicap_driver_config *config)
 748 {
 749         struct resource res;
 750         const unsigned int *id;
 751         const char *family;
 752         int rc;
 753         const struct config_registers *regs;
 754 
 755 
 756         rc = of_address_to_resource(op->dev.of_node, 0, &res);
 757         if (rc) {
 758                 dev_err(&op->dev, "invalid address\n");
 759                 return rc;
 760         }
 761 
 762         id = of_get_property(op->dev.of_node, "port-number", NULL);
 763 
 764         /* It's most likely that we're using V4, if the family is not
 765          * specified
 766          */
 767         regs = &v4_config_registers;
 768         family = of_get_property(op->dev.of_node, "xlnx,family", NULL);
 769 
 770         if (family) {
 771                 if (!strcmp(family, "virtex2p"))
 772                         regs = &v2_config_registers;
 773                 else if (!strcmp(family, "virtex4"))
 774                         regs = &v4_config_registers;
 775                 else if (!strcmp(family, "virtex5"))
 776                         regs = &v5_config_registers;
 777                 else if (!strcmp(family, "virtex6"))
 778                         regs = &v6_config_registers;
 779         }
 780         return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
 781                         regs);
 782 }
 783 #else
 784 static inline int hwicap_of_probe(struct platform_device *op,
 785                                   const struct hwicap_driver_config *config)
 786 {
 787         return -EINVAL;
 788 }
 789 #endif /* CONFIG_OF */
 790 
 791 static const struct of_device_id hwicap_of_match[];
 792 static int hwicap_drv_probe(struct platform_device *pdev)
 793 {
 794         const struct of_device_id *match;
 795         struct resource *res;
 796         const struct config_registers *regs;
 797         const char *family;
 798 
 799         match = of_match_device(hwicap_of_match, &pdev->dev);
 800         if (match)
 801                 return hwicap_of_probe(pdev, match->data);
 802 
 803         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 804         if (!res)
 805                 return -ENODEV;
 806 
 807         /* It's most likely that we're using V4, if the family is not
 808          * specified
 809          */
 810         regs = &v4_config_registers;
 811         family = pdev->dev.platform_data;
 812 
 813         if (family) {
 814                 if (!strcmp(family, "virtex2p"))
 815                         regs = &v2_config_registers;
 816                 else if (!strcmp(family, "virtex4"))
 817                         regs = &v4_config_registers;
 818                 else if (!strcmp(family, "virtex5"))
 819                         regs = &v5_config_registers;
 820                 else if (!strcmp(family, "virtex6"))
 821                         regs = &v6_config_registers;
 822         }
 823 
 824         return hwicap_setup(&pdev->dev, pdev->id, res,
 825                         &buffer_icap_config, regs);
 826 }
 827 
 828 static int hwicap_drv_remove(struct platform_device *pdev)
 829 {
 830         return hwicap_remove(&pdev->dev);
 831 }
 832 
 833 #ifdef CONFIG_OF
 834 /* Match table for device tree binding */
 835 static const struct of_device_id hwicap_of_match[] = {
 836         { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
 837         { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
 838         {},
 839 };
 840 MODULE_DEVICE_TABLE(of, hwicap_of_match);
 841 #else
 842 #define hwicap_of_match NULL
 843 #endif
 844 
 845 static struct platform_driver hwicap_platform_driver = {
 846         .probe = hwicap_drv_probe,
 847         .remove = hwicap_drv_remove,
 848         .driver = {
 849                 .name = DRIVER_NAME,
 850                 .of_match_table = hwicap_of_match,
 851         },
 852 };
 853 
 854 static int __init hwicap_module_init(void)
 855 {
 856         dev_t devt;
 857         int retval;
 858 
 859         icap_class = class_create(THIS_MODULE, "xilinx_config");
 860         mutex_init(&icap_sem);
 861 
 862         devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
 863         retval = register_chrdev_region(devt,
 864                                         HWICAP_DEVICES,
 865                                         DRIVER_NAME);
 866         if (retval < 0)
 867                 return retval;
 868 
 869         retval = platform_driver_register(&hwicap_platform_driver);
 870         if (retval)
 871                 goto failed;
 872 
 873         return retval;
 874 
 875  failed:
 876         unregister_chrdev_region(devt, HWICAP_DEVICES);
 877 
 878         return retval;
 879 }
 880 
 881 static void __exit hwicap_module_cleanup(void)
 882 {
 883         dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
 884 
 885         class_destroy(icap_class);
 886 
 887         platform_driver_unregister(&hwicap_platform_driver);
 888 
 889         unregister_chrdev_region(devt, HWICAP_DEVICES);
 890 }
 891 
 892 module_init(hwicap_module_init);
 893 module_exit(hwicap_module_cleanup);
 894 
 895 MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group");
 896 MODULE_DESCRIPTION("Xilinx ICAP Port Driver");
 897 MODULE_LICENSE("GPL");

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