···25782578 Requred properties:25792579 - current-speed : Baud rate of uartlite2580258025812581+ v) Xilinx hwicap25822582+25832583+ Xilinx hwicap devices provide access to the configuration logic25842584+ of the FPGA through the Internal Configuration Access Port25852585+ (ICAP). The ICAP enables partial reconfiguration of the FPGA,25862586+ readback of the configuration information, and some control over25872587+ 'warm boots' of the FPGA fabric.25882588+25892589+ Required properties:25902590+ - xlnx,family : The family of the FPGA, necessary since the25912591+ capabilities of the underlying ICAP hardware25922592+ differ between different families. May be25932593+ 'virtex2p', 'virtex4', or 'virtex5'.25942594+25812595 p) Freescale Synchronous Serial Interface2582259625832597 The SSI is a serial device that communicates with audio codecs. It can
+1-1
arch/powerpc/platforms/40x/virtex.c
···3737{3838 unsigned long root = of_get_flat_dt_root();39394040- if (!of_flat_dt_is_compatible(root, "xilinx,virtex"))4040+ if (!of_flat_dt_is_compatible(root, "xlnx,virtex"))4141 return 0;42424343 return 1;
···841841 To compile this driver as a module, choose M here: the842842 module will be called dtlk.843843844844+config XILINX_HWICAP845845+ tristate "Xilinx HWICAP Support"846846+ depends on XILINX_VIRTEX847847+ help848848+ This option enables support for Xilinx Internal Configuration849849+ Access Port (ICAP) driver. The ICAP is used on Xilinx Virtex850850+ FPGA platforms to partially reconfigure the FPGA at runtime.851851+852852+ If unsure, say N.853853+844854config R3964845855 tristate "Siemens R3964 line discipline"846856 ---help---
···11+#22+# Makefile for the Xilinx OPB hwicap driver33+#44+55+obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap_m.o 66+77+xilinx_hwicap_m-y := xilinx_hwicap.o fifo_icap.o buffer_icap.o
+380
drivers/char/xilinx_hwicap/buffer_icap.c
···11+/*****************************************************************************22+ *33+ * Author: Xilinx, Inc.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the77+ * Free Software Foundation; either version 2 of the License, or (at your88+ * option) any later version.99+ *1010+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"1111+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND1212+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,1313+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,1414+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION1515+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,1616+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE1717+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY1818+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE1919+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR2020+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF2121+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS2222+ * FOR A PARTICULAR PURPOSE.2323+ *2424+ * Xilinx products are not intended for use in life support appliances,2525+ * devices, or systems. Use in such applications is expressly prohibited.2626+ *2727+ * (c) Copyright 2003-2008 Xilinx Inc.2828+ * All rights reserved.2929+ *3030+ * You should have received a copy of the GNU General Public License along3131+ * with this program; if not, write to the Free Software Foundation, Inc.,3232+ * 675 Mass Ave, Cambridge, MA 02139, USA.3333+ *3434+ *****************************************************************************/3535+3636+#include "buffer_icap.h"3737+3838+/* Indicates how many bytes will fit in a buffer. (1 BRAM) */3939+#define XHI_MAX_BUFFER_BYTES 20484040+#define XHI_MAX_BUFFER_INTS (XHI_MAX_BUFFER_BYTES >> 2)4141+4242+/* File access and error constants */4343+#define XHI_DEVICE_READ_ERROR -14444+#define XHI_DEVICE_WRITE_ERROR -24545+#define XHI_BUFFER_OVERFLOW_ERROR -34646+4747+#define XHI_DEVICE_READ 0x14848+#define XHI_DEVICE_WRITE 0x04949+5050+/* Constants for checking transfer status */5151+#define XHI_CYCLE_DONE 05252+#define XHI_CYCLE_EXECUTING 15353+5454+/* buffer_icap register offsets */5555+5656+/* Size of transfer, read & write */5757+#define XHI_SIZE_REG_OFFSET 0x800L5858+/* offset into bram, read & write */5959+#define XHI_BRAM_OFFSET_REG_OFFSET 0x804L6060+/* Read not Configure, direction of transfer. Write only */6161+#define XHI_RNC_REG_OFFSET 0x808L6262+/* Indicates transfer complete. Read only */6363+#define XHI_STATUS_REG_OFFSET 0x80CL6464+6565+/* Constants for setting the RNC register */6666+#define XHI_CONFIGURE 0x0UL6767+#define XHI_READBACK 0x1UL6868+6969+/* Constants for the Done register */7070+#define XHI_NOT_FINISHED 0x0UL7171+#define XHI_FINISHED 0x1UL7272+7373+#define XHI_BUFFER_START 07474+7575+/**7676+ * buffer_icap_get_status: Get the contents of the status register.7777+ * @parameter base_address: is the base address of the device7878+ *7979+ * The status register contains the ICAP status and the done bit.8080+ *8181+ * D8 - cfgerr8282+ * D7 - dalign8383+ * D6 - rip8484+ * D5 - in_abort_l8585+ * D4 - Always 18686+ * D3 - Always 18787+ * D2 - Always 18888+ * D1 - Always 18989+ * D0 - Done bit9090+ **/9191+static inline u32 buffer_icap_get_status(void __iomem *base_address)9292+{9393+ return in_be32(base_address + XHI_STATUS_REG_OFFSET);9494+}9595+9696+/**9797+ * buffer_icap_get_bram: Reads data from the storage buffer bram.9898+ * @parameter base_address: contains the base address of the component.9999+ * @parameter offset: The word offset from which the data should be read.100100+ *101101+ * A bram is used as a configuration memory cache. One frame of data can102102+ * be stored in this "storage buffer".103103+ **/104104+static inline u32 buffer_icap_get_bram(void __iomem *base_address,105105+ u32 offset)106106+{107107+ return in_be32(base_address + (offset << 2));108108+}109109+110110+/**111111+ * buffer_icap_busy: Return true if the icap device is busy112112+ * @parameter base_address: is the base address of the device113113+ *114114+ * The queries the low order bit of the status register, which115115+ * indicates whether the current configuration or readback operation116116+ * has completed.117117+ **/118118+static inline bool buffer_icap_busy(void __iomem *base_address)119119+{120120+ return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;121121+}122122+123123+/**124124+ * buffer_icap_busy: Return true if the icap device is not busy125125+ * @parameter base_address: is the base address of the device126126+ *127127+ * The queries the low order bit of the status register, which128128+ * indicates whether the current configuration or readback operation129129+ * has completed.130130+ **/131131+static inline bool buffer_icap_done(void __iomem *base_address)132132+{133133+ return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;134134+}135135+136136+/**137137+ * buffer_icap_set_size: Set the size register.138138+ * @parameter base_address: is the base address of the device139139+ * @parameter data: The size in bytes.140140+ *141141+ * The size register holds the number of 8 bit bytes to transfer between142142+ * bram and the icap (or icap to bram).143143+ **/144144+static inline void buffer_icap_set_size(void __iomem *base_address,145145+ u32 data)146146+{147147+ out_be32(base_address + XHI_SIZE_REG_OFFSET, data);148148+}149149+150150+/**151151+ * buffer_icap_mSetoffsetReg: Set the bram offset register.152152+ * @parameter base_address: contains the base address of the device.153153+ * @parameter data: is the value to be written to the data register.154154+ *155155+ * The bram offset register holds the starting bram address to transfer156156+ * data from during configuration or write data to during readback.157157+ **/158158+static inline void buffer_icap_set_offset(void __iomem *base_address,159159+ u32 data)160160+{161161+ out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);162162+}163163+164164+/**165165+ * buffer_icap_set_rnc: Set the RNC (Readback not Configure) register.166166+ * @parameter base_address: contains the base address of the device.167167+ * @parameter data: is the value to be written to the data register.168168+ *169169+ * The RNC register determines the direction of the data transfer. It170170+ * controls whether a configuration or readback take place. Writing to171171+ * this register initiates the transfer. A value of 1 initiates a172172+ * readback while writing a value of 0 initiates a configuration.173173+ **/174174+static inline void buffer_icap_set_rnc(void __iomem *base_address,175175+ u32 data)176176+{177177+ out_be32(base_address + XHI_RNC_REG_OFFSET, data);178178+}179179+180180+/**181181+ * buffer_icap_set_bram: Write data to the storage buffer bram.182182+ * @parameter base_address: contains the base address of the component.183183+ * @parameter offset: The word offset at which the data should be written.184184+ * @parameter data: The value to be written to the bram offset.185185+ *186186+ * A bram is used as a configuration memory cache. One frame of data can187187+ * be stored in this "storage buffer".188188+ **/189189+static inline void buffer_icap_set_bram(void __iomem *base_address,190190+ u32 offset, u32 data)191191+{192192+ out_be32(base_address + (offset << 2), data);193193+}194194+195195+/**196196+ * buffer_icap_device_read: Transfer bytes from ICAP to the storage buffer.197197+ * @parameter drvdata: a pointer to the drvdata.198198+ * @parameter offset: The storage buffer start address.199199+ * @parameter count: The number of words (32 bit) to read from the200200+ * device (ICAP).201201+ **/202202+static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,203203+ u32 offset, u32 count)204204+{205205+206206+ s32 retries = 0;207207+ void __iomem *base_address = drvdata->base_address;208208+209209+ if (buffer_icap_busy(base_address))210210+ return -EBUSY;211211+212212+ if ((offset + count) > XHI_MAX_BUFFER_INTS)213213+ return -EINVAL;214214+215215+ /* setSize count*4 to get bytes. */216216+ buffer_icap_set_size(base_address, (count << 2));217217+ buffer_icap_set_offset(base_address, offset);218218+ buffer_icap_set_rnc(base_address, XHI_READBACK);219219+220220+ while (buffer_icap_busy(base_address)) {221221+ retries++;222222+ if (retries > XHI_MAX_RETRIES)223223+ return -EBUSY;224224+ }225225+ return 0;226226+227227+};228228+229229+/**230230+ * buffer_icap_device_write: Transfer bytes from ICAP to the storage buffer.231231+ * @parameter drvdata: a pointer to the drvdata.232232+ * @parameter offset: The storage buffer start address.233233+ * @parameter count: The number of words (32 bit) to read from the234234+ * device (ICAP).235235+ **/236236+static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,237237+ u32 offset, u32 count)238238+{239239+240240+ s32 retries = 0;241241+ void __iomem *base_address = drvdata->base_address;242242+243243+ if (buffer_icap_busy(base_address))244244+ return -EBUSY;245245+246246+ if ((offset + count) > XHI_MAX_BUFFER_INTS)247247+ return -EINVAL;248248+249249+ /* setSize count*4 to get bytes. */250250+ buffer_icap_set_size(base_address, count << 2);251251+ buffer_icap_set_offset(base_address, offset);252252+ buffer_icap_set_rnc(base_address, XHI_CONFIGURE);253253+254254+ while (buffer_icap_busy(base_address)) {255255+ retries++;256256+ if (retries > XHI_MAX_RETRIES)257257+ return -EBUSY;258258+ }259259+ return 0;260260+261261+};262262+263263+/**264264+ * buffer_icap_reset: Reset the logic of the icap device.265265+ * @parameter drvdata: a pointer to the drvdata.266266+ *267267+ * Writing to the status register resets the ICAP logic in an internal268268+ * version of the core. For the version of the core published in EDK,269269+ * this is a noop.270270+ **/271271+void buffer_icap_reset(struct hwicap_drvdata *drvdata)272272+{273273+ out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);274274+}275275+276276+/**277277+ * buffer_icap_set_configuration: Load a partial bitstream from system memory.278278+ * @parameter drvdata: a pointer to the drvdata.279279+ * @parameter data: Kernel address of the partial bitstream.280280+ * @parameter size: the size of the partial bitstream in 32 bit words.281281+ **/282282+int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,283283+ u32 size)284284+{285285+ int status;286286+ s32 buffer_count = 0;287287+ s32 num_writes = 0;288288+ bool dirty = 0;289289+ u32 i;290290+ void __iomem *base_address = drvdata->base_address;291291+292292+ /* Loop through all the data */293293+ for (i = 0, buffer_count = 0; i < size; i++) {294294+295295+ /* Copy data to bram */296296+ buffer_icap_set_bram(base_address, buffer_count, data[i]);297297+ dirty = 1;298298+299299+ if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {300300+ buffer_count++;301301+ continue;302302+ }303303+304304+ /* Write data to ICAP */305305+ status = buffer_icap_device_write(306306+ drvdata,307307+ XHI_BUFFER_START,308308+ XHI_MAX_BUFFER_INTS);309309+ if (status != 0) {310310+ /* abort. */311311+ buffer_icap_reset(drvdata);312312+ return status;313313+ }314314+315315+ buffer_count = 0;316316+ num_writes++;317317+ dirty = 0;318318+ }319319+320320+ /* Write unwritten data to ICAP */321321+ if (dirty) {322322+ /* Write data to ICAP */323323+ status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,324324+ buffer_count);325325+ if (status != 0) {326326+ /* abort. */327327+ buffer_icap_reset(drvdata);328328+ }329329+ return status;330330+ }331331+332332+ return 0;333333+};334334+335335+/**336336+ * buffer_icap_get_configuration: Read configuration data from the device.337337+ * @parameter drvdata: a pointer to the drvdata.338338+ * @parameter data: Address of the data representing the partial bitstream339339+ * @parameter size: the size of the partial bitstream in 32 bit words.340340+ **/341341+int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,342342+ u32 size)343343+{344344+ int status;345345+ s32 buffer_count = 0;346346+ s32 read_count = 0;347347+ u32 i;348348+ void __iomem *base_address = drvdata->base_address;349349+350350+ /* Loop through all the data */351351+ for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {352352+ if (buffer_count == XHI_MAX_BUFFER_INTS) {353353+ u32 words_remaining = size - i;354354+ u32 words_to_read =355355+ words_remaining <356356+ XHI_MAX_BUFFER_INTS ? words_remaining :357357+ XHI_MAX_BUFFER_INTS;358358+359359+ /* Read data from ICAP */360360+ status = buffer_icap_device_read(361361+ drvdata,362362+ XHI_BUFFER_START,363363+ words_to_read);364364+ if (status != 0) {365365+ /* abort. */366366+ buffer_icap_reset(drvdata);367367+ return status;368368+ }369369+370370+ buffer_count = 0;371371+ read_count++;372372+ }373373+374374+ /* Copy data from bram */375375+ data[i] = buffer_icap_get_bram(base_address, buffer_count);376376+ buffer_count++;377377+ }378378+379379+ return 0;380380+};
+57
drivers/char/xilinx_hwicap/buffer_icap.h
···11+/*****************************************************************************22+ *33+ * Author: Xilinx, Inc.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the77+ * Free Software Foundation; either version 2 of the License, or (at your88+ * option) any later version.99+ *1010+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"1111+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND1212+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,1313+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,1414+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION1515+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,1616+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE1717+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY1818+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE1919+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR2020+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF2121+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS2222+ * FOR A PARTICULAR PURPOSE.2323+ *2424+ * Xilinx products are not intended for use in life support appliances,2525+ * devices, or systems. Use in such applications is expressly prohibited.2626+ *2727+ * (c) Copyright 2003-2008 Xilinx Inc.2828+ * All rights reserved.2929+ *3030+ * You should have received a copy of the GNU General Public License along3131+ * with this program; if not, write to the Free Software Foundation, Inc.,3232+ * 675 Mass Ave, Cambridge, MA 02139, USA.3333+ *3434+ *****************************************************************************/3535+3636+#ifndef XILINX_BUFFER_ICAP_H_ /* prevent circular inclusions */3737+#define XILINX_BUFFER_ICAP_H_ /* by using protection macros */3838+3939+#include <linux/types.h>4040+#include <linux/cdev.h>4141+#include <linux/version.h>4242+#include <linux/platform_device.h>4343+4444+#include <asm/io.h>4545+#include "xilinx_hwicap.h"4646+4747+void buffer_icap_reset(struct hwicap_drvdata *drvdata);4848+4949+/* Loads a partial bitstream from system memory. */5050+int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,5151+ u32 Size);5252+5353+/* Loads a partial bitstream from system memory. */5454+int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,5555+ u32 Size);5656+5757+#endif
+381
drivers/char/xilinx_hwicap/fifo_icap.c
···11+/*****************************************************************************22+ *33+ * Author: Xilinx, Inc.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the77+ * Free Software Foundation; either version 2 of the License, or (at your88+ * option) any later version.99+ *1010+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"1111+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND1212+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,1313+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,1414+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION1515+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,1616+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE1717+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY1818+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE1919+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR2020+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF2121+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS2222+ * FOR A PARTICULAR PURPOSE.2323+ *2424+ * Xilinx products are not intended for use in life support appliances,2525+ * devices, or systems. Use in such applications is expressly prohibited.2626+ *2727+ * (c) Copyright 2007-2008 Xilinx Inc.2828+ * All rights reserved.2929+ *3030+ * You should have received a copy of the GNU General Public License along3131+ * with this program; if not, write to the Free Software Foundation, Inc.,3232+ * 675 Mass Ave, Cambridge, MA 02139, USA.3333+ *3434+ *****************************************************************************/3535+3636+#include "fifo_icap.h"3737+3838+/* Register offsets for the XHwIcap device. */3939+#define XHI_GIER_OFFSET 0x1C /* Device Global Interrupt Enable Reg */4040+#define XHI_IPISR_OFFSET 0x20 /* Interrupt Status Register */4141+#define XHI_IPIER_OFFSET 0x28 /* Interrupt Enable Register */4242+#define XHI_WF_OFFSET 0x100 /* Write FIFO */4343+#define XHI_RF_OFFSET 0x104 /* Read FIFO */4444+#define XHI_SZ_OFFSET 0x108 /* Size Register */4545+#define XHI_CR_OFFSET 0x10C /* Control Register */4646+#define XHI_SR_OFFSET 0x110 /* Status Register */4747+#define XHI_WFV_OFFSET 0x114 /* Write FIFO Vacancy Register */4848+#define XHI_RFO_OFFSET 0x118 /* Read FIFO Occupancy Register */4949+5050+/* Device Global Interrupt Enable Register (GIER) bit definitions */5151+5252+#define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */5353+5454+/**5555+ * HwIcap Device Interrupt Status/Enable Registers5656+ *5757+ * Interrupt Status Register (IPISR) : This register holds the5858+ * interrupt status flags for the device. These bits are toggle on5959+ * write.6060+ *6161+ * Interrupt Enable Register (IPIER) : This register is used to enable6262+ * interrupt sources for the device.6363+ * Writing a '1' to a bit enables the corresponding interrupt.6464+ * Writing a '0' to a bit disables the corresponding interrupt.6565+ *6666+ * IPISR/IPIER registers have the same bit definitions and are only defined6767+ * once.6868+ */6969+#define XHI_IPIXR_RFULL_MASK 0x00000008 /* Read FIFO Full */7070+#define XHI_IPIXR_WEMPTY_MASK 0x00000004 /* Write FIFO Empty */7171+#define XHI_IPIXR_RDP_MASK 0x00000002 /* Read FIFO half full */7272+#define XHI_IPIXR_WRP_MASK 0x00000001 /* Write FIFO half full */7373+#define XHI_IPIXR_ALL_MASK 0x0000000F /* Mask of all interrupts */7474+7575+/* Control Register (CR) */7676+#define XHI_CR_SW_RESET_MASK 0x00000008 /* SW Reset Mask */7777+#define XHI_CR_FIFO_CLR_MASK 0x00000004 /* FIFO Clear Mask */7878+#define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */7979+#define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */8080+8181+/* Status Register (SR) */8282+#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */8383+#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */8484+#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */8585+#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */8686+#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */8787+8888+8989+#define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */9090+#define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */9191+/* The maximum amount we can request from fifo_icap_get_configuration9292+ at once, in bytes. */9393+#define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF9494+9595+9696+/**9797+ * fifo_icap_fifo_write: Write data to the write FIFO.9898+ * @parameter drvdata: a pointer to the drvdata.9999+ * @parameter data: the 32-bit value to be written to the FIFO.100100+ *101101+ * This function will silently fail if the fifo is full.102102+ **/103103+static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,104104+ u32 data)105105+{106106+ dev_dbg(drvdata->dev, "fifo_write: %x\n", data);107107+ out_be32(drvdata->base_address + XHI_WF_OFFSET, data);108108+}109109+110110+/**111111+ * fifo_icap_fifo_read: Read data from the Read FIFO.112112+ * @parameter drvdata: a pointer to the drvdata.113113+ *114114+ * This function will silently fail if the fifo is empty.115115+ **/116116+static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)117117+{118118+ u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET);119119+ dev_dbg(drvdata->dev, "fifo_read: %x\n", data);120120+ return data;121121+}122122+123123+/**124124+ * fifo_icap_set_read_size: Set the the size register.125125+ * @parameter drvdata: a pointer to the drvdata.126126+ * @parameter data: the size of the following read transaction, in words.127127+ **/128128+static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,129129+ u32 data)130130+{131131+ out_be32(drvdata->base_address + XHI_SZ_OFFSET, data);132132+}133133+134134+/**135135+ * fifo_icap_start_config: Initiate a configuration (write) to the device.136136+ * @parameter drvdata: a pointer to the drvdata.137137+ **/138138+static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)139139+{140140+ out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK);141141+ dev_dbg(drvdata->dev, "configuration started\n");142142+}143143+144144+/**145145+ * fifo_icap_start_readback: Initiate a readback from the device.146146+ * @parameter drvdata: a pointer to the drvdata.147147+ **/148148+static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)149149+{150150+ out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK);151151+ dev_dbg(drvdata->dev, "readback started\n");152152+}153153+154154+/**155155+ * fifo_icap_busy: Return true if the ICAP is still processing a transaction.156156+ * @parameter drvdata: a pointer to the drvdata.157157+ **/158158+static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)159159+{160160+ u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);161161+ dev_dbg(drvdata->dev, "Getting status = %x\n", status);162162+ return (status & XHI_SR_DONE_MASK) ? 0 : 1;163163+}164164+165165+/**166166+ * fifo_icap_write_fifo_vacancy: Query the write fifo available space.167167+ * @parameter drvdata: a pointer to the drvdata.168168+ *169169+ * Return the number of words that can be safely pushed into the write fifo.170170+ **/171171+static inline u32 fifo_icap_write_fifo_vacancy(172172+ struct hwicap_drvdata *drvdata)173173+{174174+ return in_be32(drvdata->base_address + XHI_WFV_OFFSET);175175+}176176+177177+/**178178+ * fifo_icap_read_fifo_occupancy: Query the read fifo available data.179179+ * @parameter drvdata: a pointer to the drvdata.180180+ *181181+ * Return the number of words that can be safely read from the read fifo.182182+ **/183183+static inline u32 fifo_icap_read_fifo_occupancy(184184+ struct hwicap_drvdata *drvdata)185185+{186186+ return in_be32(drvdata->base_address + XHI_RFO_OFFSET);187187+}188188+189189+/**190190+ * fifo_icap_set_configuration: Send configuration data to the ICAP.191191+ * @parameter drvdata: a pointer to the drvdata.192192+ * @parameter frame_buffer: a pointer to the data to be written to the193193+ * ICAP device.194194+ * @parameter num_words: the number of words (32 bit) to write to the ICAP195195+ * device.196196+197197+ * This function writes the given user data to the Write FIFO in198198+ * polled mode and starts the transfer of the data to199199+ * the ICAP device.200200+ **/201201+int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,202202+ u32 *frame_buffer, u32 num_words)203203+{204204+205205+ u32 write_fifo_vacancy = 0;206206+ u32 retries = 0;207207+ u32 remaining_words;208208+209209+ dev_dbg(drvdata->dev, "fifo_set_configuration\n");210210+211211+ /*212212+ * Check if the ICAP device is Busy with the last Read/Write213213+ */214214+ if (fifo_icap_busy(drvdata))215215+ return -EBUSY;216216+217217+ /*218218+ * Set up the buffer pointer and the words to be transferred.219219+ */220220+ remaining_words = num_words;221221+222222+ while (remaining_words > 0) {223223+ /*224224+ * Wait until we have some data in the fifo.225225+ */226226+ while (write_fifo_vacancy == 0) {227227+ write_fifo_vacancy =228228+ fifo_icap_write_fifo_vacancy(drvdata);229229+ retries++;230230+ if (retries > XHI_MAX_RETRIES)231231+ return -EIO;232232+ }233233+234234+ /*235235+ * Write data into the Write FIFO.236236+ */237237+ while ((write_fifo_vacancy != 0) &&238238+ (remaining_words > 0)) {239239+ fifo_icap_fifo_write(drvdata, *frame_buffer);240240+241241+ remaining_words--;242242+ write_fifo_vacancy--;243243+ frame_buffer++;244244+ }245245+ /* Start pushing whatever is in the FIFO into the ICAP. */246246+ fifo_icap_start_config(drvdata);247247+ }248248+249249+ /* Wait until the write has finished. */250250+ while (fifo_icap_busy(drvdata)) {251251+ retries++;252252+ if (retries > XHI_MAX_RETRIES)253253+ break;254254+ }255255+256256+ dev_dbg(drvdata->dev, "done fifo_set_configuration\n");257257+258258+ /*259259+ * If the requested number of words have not been read from260260+ * the device then indicate failure.261261+ */262262+ if (remaining_words != 0)263263+ return -EIO;264264+265265+ return 0;266266+}267267+268268+/**269269+ * fifo_icap_get_configuration: Read configuration data from the device.270270+ * @parameter drvdata: a pointer to the drvdata.271271+ * @parameter data: Address of the data representing the partial bitstream272272+ * @parameter size: the size of the partial bitstream in 32 bit words.273273+ *274274+ * This function reads the specified number of words from the ICAP device in275275+ * the polled mode.276276+ */277277+int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,278278+ u32 *frame_buffer, u32 num_words)279279+{280280+281281+ u32 read_fifo_occupancy = 0;282282+ u32 retries = 0;283283+ u32 *data = frame_buffer;284284+ u32 remaining_words;285285+ u32 words_to_read;286286+287287+ dev_dbg(drvdata->dev, "fifo_get_configuration\n");288288+289289+ /*290290+ * Check if the ICAP device is Busy with the last Write/Read291291+ */292292+ if (fifo_icap_busy(drvdata))293293+ return -EBUSY;294294+295295+ remaining_words = num_words;296296+297297+ while (remaining_words > 0) {298298+ words_to_read = remaining_words;299299+ /* The hardware has a limit on the number of words300300+ that can be read at one time. */301301+ if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS)302302+ words_to_read = XHI_MAX_READ_TRANSACTION_WORDS;303303+304304+ remaining_words -= words_to_read;305305+306306+ fifo_icap_set_read_size(drvdata, words_to_read);307307+ fifo_icap_start_readback(drvdata);308308+309309+ while (words_to_read > 0) {310310+ /* Wait until we have some data in the fifo. */311311+ while (read_fifo_occupancy == 0) {312312+ read_fifo_occupancy =313313+ fifo_icap_read_fifo_occupancy(drvdata);314314+ retries++;315315+ if (retries > XHI_MAX_RETRIES)316316+ return -EIO;317317+ }318318+319319+ if (read_fifo_occupancy > words_to_read)320320+ read_fifo_occupancy = words_to_read;321321+322322+ words_to_read -= read_fifo_occupancy;323323+324324+ /* Read the data from the Read FIFO. */325325+ while (read_fifo_occupancy != 0) {326326+ *data++ = fifo_icap_fifo_read(drvdata);327327+ read_fifo_occupancy--;328328+ }329329+ }330330+ }331331+332332+ dev_dbg(drvdata->dev, "done fifo_get_configuration\n");333333+334334+ return 0;335335+}336336+337337+/**338338+ * buffer_icap_reset: Reset the logic of the icap device.339339+ * @parameter drvdata: a pointer to the drvdata.340340+ *341341+ * This function forces the software reset of the complete HWICAP device.342342+ * All the registers will return to the default value and the FIFO is also343343+ * flushed as a part of this software reset.344344+ */345345+void fifo_icap_reset(struct hwicap_drvdata *drvdata)346346+{347347+ u32 reg_data;348348+ /*349349+ * Reset the device by setting/clearing the RESET bit in the350350+ * Control Register.351351+ */352352+ reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);353353+354354+ out_be32(drvdata->base_address + XHI_CR_OFFSET,355355+ reg_data | XHI_CR_SW_RESET_MASK);356356+357357+ out_be32(drvdata->base_address + XHI_CR_OFFSET,358358+ reg_data & (~XHI_CR_SW_RESET_MASK));359359+360360+}361361+362362+/**363363+ * fifo_icap_flush_fifo: This function flushes the FIFOs in the device.364364+ * @parameter drvdata: a pointer to the drvdata.365365+ */366366+void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata)367367+{368368+ u32 reg_data;369369+ /*370370+ * Flush the FIFO by setting/clearing the FIFO Clear bit in the371371+ * Control Register.372372+ */373373+ reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);374374+375375+ out_be32(drvdata->base_address + XHI_CR_OFFSET,376376+ reg_data | XHI_CR_FIFO_CLR_MASK);377377+378378+ out_be32(drvdata->base_address + XHI_CR_OFFSET,379379+ reg_data & (~XHI_CR_FIFO_CLR_MASK));380380+}381381+
+62
drivers/char/xilinx_hwicap/fifo_icap.h
···11+/*****************************************************************************22+ *33+ * Author: Xilinx, Inc.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the77+ * Free Software Foundation; either version 2 of the License, or (at your88+ * option) any later version.99+ *1010+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"1111+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND1212+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,1313+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,1414+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION1515+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,1616+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE1717+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY1818+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE1919+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR2020+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF2121+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS2222+ * FOR A PARTICULAR PURPOSE.2323+ *2424+ * Xilinx products are not intended for use in life support appliances,2525+ * devices, or systems. Use in such applications is expressly prohibited.2626+ *2727+ * (c) Copyright 2007-2008 Xilinx Inc.2828+ * All rights reserved.2929+ *3030+ * You should have received a copy of the GNU General Public License along3131+ * with this program; if not, write to the Free Software Foundation, Inc.,3232+ * 675 Mass Ave, Cambridge, MA 02139, USA.3333+ *3434+ *****************************************************************************/3535+3636+#ifndef XILINX_FIFO_ICAP_H_ /* prevent circular inclusions */3737+#define XILINX_FIFO_ICAP_H_ /* by using protection macros */3838+3939+#include <linux/types.h>4040+#include <linux/cdev.h>4141+#include <linux/version.h>4242+#include <linux/platform_device.h>4343+4444+#include <asm/io.h>4545+#include "xilinx_hwicap.h"4646+4747+/* Reads integers from the device into the storage buffer. */4848+int fifo_icap_get_configuration(4949+ struct hwicap_drvdata *drvdata,5050+ u32 *FrameBuffer,5151+ u32 NumWords);5252+5353+/* Writes integers to the device from the storage buffer. */5454+int fifo_icap_set_configuration(5555+ struct hwicap_drvdata *drvdata,5656+ u32 *FrameBuffer,5757+ u32 NumWords);5858+5959+void fifo_icap_reset(struct hwicap_drvdata *drvdata);6060+void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata);6161+6262+#endif
+904
drivers/char/xilinx_hwicap/xilinx_hwicap.c
···11+/*****************************************************************************22+ *33+ * Author: Xilinx, Inc.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the77+ * Free Software Foundation; either version 2 of the License, or (at your88+ * option) any later version.99+ *1010+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"1111+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND1212+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,1313+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,1414+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION1515+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,1616+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE1717+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY1818+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE1919+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR2020+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF2121+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS2222+ * FOR A PARTICULAR PURPOSE.2323+ *2424+ * Xilinx products are not intended for use in life support appliances,2525+ * devices, or systems. Use in such applications is expressly prohibited.2626+ *2727+ * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group2828+ * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group2929+ * (c) Copyright 2007-2008 Xilinx Inc.3030+ * All rights reserved.3131+ *3232+ * You should have received a copy of the GNU General Public License along3333+ * with this program; if not, write to the Free Software Foundation, Inc.,3434+ * 675 Mass Ave, Cambridge, MA 02139, USA.3535+ *3636+ *****************************************************************************/3737+3838+/*3939+ * This is the code behind /dev/xilinx_icap -- it allows a user-space4040+ * application to use the Xilinx ICAP subsystem.4141+ *4242+ * The following operations are possible:4343+ *4444+ * open open the port and initialize for access.4545+ * release release port4646+ * write Write a bitstream to the configuration processor.4747+ * read Read a data stream from the configuration processor.4848+ *4949+ * After being opened, the port is initialized and accessed to avoid a5050+ * corrupted first read which may occur with some hardware. The port5151+ * is left in a desynched state, requiring that a synch sequence be5252+ * transmitted before any valid configuration data. A user will have5353+ * exclusive access to the device while it remains open, and the state5454+ * of the ICAP cannot be guaranteed after the device is closed. Note5555+ * that a complete reset of the core and the state of the ICAP cannot5656+ * be performed on many versions of the cores, hence users of this5757+ * device should avoid making inconsistent accesses to the device. In5858+ * particular, accessing the read interface, without first generating5959+ * a write containing a readback packet can leave the ICAP in an6060+ * inaccessible state.6161+ *6262+ * Note that in order to use the read interface, it is first necessary6363+ * to write a request packet to the write interface. i.e., it is not6464+ * possible to simply readback the bitstream (or any configuration6565+ * bits) from a device without specifically requesting them first.6666+ * The code to craft such packets is intended to be part of the6767+ * user-space application code that uses this device. The simplest6868+ * way to use this interface is simply:6969+ *7070+ * cp foo.bit /dev/xilinx_icap7171+ *7272+ * Note that unless foo.bit is an appropriately constructed partial7373+ * bitstream, this has a high likelyhood of overwriting the design7474+ * currently programmed in the FPGA.7575+ */7676+7777+#include <linux/version.h>7878+#include <linux/module.h>7979+#include <linux/kernel.h>8080+#include <linux/types.h>8181+#include <linux/ioport.h>8282+#include <linux/interrupt.h>8383+#include <linux/fcntl.h>8484+#include <linux/init.h>8585+#include <linux/poll.h>8686+#include <linux/proc_fs.h>8787+#include <asm/semaphore.h>8888+#include <linux/sysctl.h>8989+#include <linux/version.h>9090+#include <linux/fs.h>9191+#include <linux/cdev.h>9292+#include <linux/platform_device.h>9393+9494+#include <asm/io.h>9595+#include <asm/uaccess.h>9696+#include <asm/system.h>9797+9898+#ifdef CONFIG_OF9999+/* For open firmware. */100100+#include <linux/of_device.h>101101+#include <linux/of_platform.h>102102+#endif103103+104104+#include "xilinx_hwicap.h"105105+#include "buffer_icap.h"106106+#include "fifo_icap.h"107107+108108+#define DRIVER_NAME "xilinx_icap"109109+110110+#define HWICAP_REGS (0x10000)111111+112112+/* dynamically allocate device number */113113+static int xhwicap_major;114114+static int xhwicap_minor;115115+#define HWICAP_DEVICES 1116116+117117+module_param(xhwicap_major, int, S_IRUGO);118118+module_param(xhwicap_minor, int, S_IRUGO);119119+120120+/* An array, which is set to true when the device is registered. */121121+static bool probed_devices[HWICAP_DEVICES];122122+123123+static struct class *icap_class;124124+125125+#define UNIMPLEMENTED 0xFFFF126126+127127+static const struct config_registers v2_config_registers = {128128+ .CRC = 0,129129+ .FAR = 1,130130+ .FDRI = 2,131131+ .FDRO = 3,132132+ .CMD = 4,133133+ .CTL = 5,134134+ .MASK = 6,135135+ .STAT = 7,136136+ .LOUT = 8,137137+ .COR = 9,138138+ .MFWR = 10,139139+ .FLR = 11,140140+ .KEY = 12,141141+ .CBC = 13,142142+ .IDCODE = 14,143143+ .AXSS = UNIMPLEMENTED,144144+ .C0R_1 = UNIMPLEMENTED,145145+ .CSOB = UNIMPLEMENTED,146146+ .WBSTAR = UNIMPLEMENTED,147147+ .TIMER = UNIMPLEMENTED,148148+ .BOOTSTS = UNIMPLEMENTED,149149+ .CTL_1 = UNIMPLEMENTED,150150+};151151+152152+static const struct config_registers v4_config_registers = {153153+ .CRC = 0,154154+ .FAR = 1,155155+ .FDRI = 2,156156+ .FDRO = 3,157157+ .CMD = 4,158158+ .CTL = 5,159159+ .MASK = 6,160160+ .STAT = 7,161161+ .LOUT = 8,162162+ .COR = 9,163163+ .MFWR = 10,164164+ .FLR = UNIMPLEMENTED,165165+ .KEY = UNIMPLEMENTED,166166+ .CBC = 11,167167+ .IDCODE = 12,168168+ .AXSS = 13,169169+ .C0R_1 = UNIMPLEMENTED,170170+ .CSOB = UNIMPLEMENTED,171171+ .WBSTAR = UNIMPLEMENTED,172172+ .TIMER = UNIMPLEMENTED,173173+ .BOOTSTS = UNIMPLEMENTED,174174+ .CTL_1 = UNIMPLEMENTED,175175+};176176+static const struct config_registers v5_config_registers = {177177+ .CRC = 0,178178+ .FAR = 1,179179+ .FDRI = 2,180180+ .FDRO = 3,181181+ .CMD = 4,182182+ .CTL = 5,183183+ .MASK = 6,184184+ .STAT = 7,185185+ .LOUT = 8,186186+ .COR = 9,187187+ .MFWR = 10,188188+ .FLR = UNIMPLEMENTED,189189+ .KEY = UNIMPLEMENTED,190190+ .CBC = 11,191191+ .IDCODE = 12,192192+ .AXSS = 13,193193+ .C0R_1 = 14,194194+ .CSOB = 15,195195+ .WBSTAR = 16,196196+ .TIMER = 17,197197+ .BOOTSTS = 18,198198+ .CTL_1 = 19,199199+};200200+201201+/**202202+ * hwicap_command_desync: Send a DESYNC command to the ICAP port.203203+ * @parameter drvdata: a pointer to the drvdata.204204+ *205205+ * This command desynchronizes the ICAP After this command, a206206+ * bitstream containing a NULL packet, followed by a SYNCH packet is207207+ * required before the ICAP will recognize commands.208208+ */209209+int hwicap_command_desync(struct hwicap_drvdata *drvdata)210210+{211211+ u32 buffer[4];212212+ u32 index = 0;213213+214214+ /*215215+ * Create the data to be written to the ICAP.216216+ */217217+ buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;218218+ buffer[index++] = XHI_CMD_DESYNCH;219219+ buffer[index++] = XHI_NOOP_PACKET;220220+ buffer[index++] = XHI_NOOP_PACKET;221221+222222+ /*223223+ * Write the data to the FIFO and intiate the transfer of data present224224+ * in the FIFO to the ICAP device.225225+ */226226+ return drvdata->config->set_configuration(drvdata,227227+ &buffer[0], index);228228+}229229+230230+/**231231+ * hwicap_command_capture: Send a CAPTURE command to the ICAP port.232232+ * @parameter drvdata: a pointer to the drvdata.233233+ *234234+ * This command captures all of the flip flop states so they will be235235+ * available during readback. One can use this command instead of236236+ * enabling the CAPTURE block in the design.237237+ */238238+int hwicap_command_capture(struct hwicap_drvdata *drvdata)239239+{240240+ u32 buffer[7];241241+ u32 index = 0;242242+243243+ /*244244+ * Create the data to be written to the ICAP.245245+ */246246+ buffer[index++] = XHI_DUMMY_PACKET;247247+ buffer[index++] = XHI_SYNC_PACKET;248248+ buffer[index++] = XHI_NOOP_PACKET;249249+ buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;250250+ buffer[index++] = XHI_CMD_GCAPTURE;251251+ buffer[index++] = XHI_DUMMY_PACKET;252252+ buffer[index++] = XHI_DUMMY_PACKET;253253+254254+ /*255255+ * Write the data to the FIFO and intiate the transfer of data256256+ * present in the FIFO to the ICAP device.257257+ */258258+ return drvdata->config->set_configuration(drvdata,259259+ &buffer[0], index);260260+261261+}262262+263263+/**264264+ * hwicap_get_configuration_register: Query a configuration register.265265+ * @parameter drvdata: a pointer to the drvdata.266266+ * @parameter reg: a constant which represents the configuration267267+ * register value to be returned.268268+ * Examples: XHI_IDCODE, XHI_FLR.269269+ * @parameter RegData: returns the value of the register.270270+ *271271+ * Sends a query packet to the ICAP and then receives the response.272272+ * The icap is left in Synched state.273273+ */274274+int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,275275+ u32 reg, u32 *RegData)276276+{277277+ int status;278278+ u32 buffer[6];279279+ u32 index = 0;280280+281281+ /*282282+ * Create the data to be written to the ICAP.283283+ */284284+ buffer[index++] = XHI_DUMMY_PACKET;285285+ buffer[index++] = XHI_SYNC_PACKET;286286+ buffer[index++] = XHI_NOOP_PACKET;287287+ buffer[index++] = hwicap_type_1_read(reg) | 1;288288+ buffer[index++] = XHI_NOOP_PACKET;289289+ buffer[index++] = XHI_NOOP_PACKET;290290+291291+ /*292292+ * Write the data to the FIFO and intiate the transfer of data present293293+ * in the FIFO to the ICAP device.294294+ */295295+ status = drvdata->config->set_configuration(drvdata,296296+ &buffer[0], index);297297+ if (status)298298+ return status;299299+300300+ /*301301+ * Read the configuration register302302+ */303303+ status = drvdata->config->get_configuration(drvdata, RegData, 1);304304+ if (status)305305+ return status;306306+307307+ return 0;308308+}309309+310310+int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)311311+{312312+ int status;313313+ u32 idcode;314314+315315+ dev_dbg(drvdata->dev, "initializing\n");316316+317317+ /* Abort any current transaction, to make sure we have the318318+ * ICAP in a good state. */319319+ dev_dbg(drvdata->dev, "Reset...\n");320320+ drvdata->config->reset(drvdata);321321+322322+ dev_dbg(drvdata->dev, "Desync...\n");323323+ status = hwicap_command_desync(drvdata);324324+ if (status)325325+ return status;326326+327327+ /* Attempt to read the IDCODE from ICAP. This328328+ * may not be returned correctly, due to the design of the329329+ * hardware.330330+ */331331+ dev_dbg(drvdata->dev, "Reading IDCODE...\n");332332+ status = hwicap_get_configuration_register(333333+ drvdata, drvdata->config_regs->IDCODE, &idcode);334334+ dev_dbg(drvdata->dev, "IDCODE = %x\n", idcode);335335+ if (status)336336+ return status;337337+338338+ dev_dbg(drvdata->dev, "Desync...\n");339339+ status = hwicap_command_desync(drvdata);340340+ if (status)341341+ return status;342342+343343+ return 0;344344+}345345+346346+static ssize_t347347+hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)348348+{349349+ struct hwicap_drvdata *drvdata = file->private_data;350350+ ssize_t bytes_to_read = 0;351351+ u32 *kbuf;352352+ u32 words;353353+ u32 bytes_remaining;354354+ int status;355355+356356+ if (down_interruptible(&drvdata->sem))357357+ return -ERESTARTSYS;358358+359359+ if (drvdata->read_buffer_in_use) {360360+ /* If there are leftover bytes in the buffer, just */361361+ /* return them and don't try to read more from the */362362+ /* ICAP device. */363363+ bytes_to_read =364364+ (count < drvdata->read_buffer_in_use) ? count :365365+ drvdata->read_buffer_in_use;366366+367367+ /* Return the data currently in the read buffer. */368368+ if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) {369369+ status = -EFAULT;370370+ goto error;371371+ }372372+ drvdata->read_buffer_in_use -= bytes_to_read;373373+ memcpy(drvdata->read_buffer + bytes_to_read,374374+ drvdata->read_buffer, 4 - bytes_to_read);375375+ } else {376376+ /* Get new data from the ICAP, and return was was requested. */377377+ kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);378378+ if (!kbuf) {379379+ status = -ENOMEM;380380+ goto error;381381+ }382382+383383+ /* The ICAP device is only able to read complete */384384+ /* words. If a number of bytes that do not correspond */385385+ /* to complete words is requested, then we read enough */386386+ /* words to get the required number of bytes, and then */387387+ /* save the remaining bytes for the next read. */388388+389389+ /* Determine the number of words to read, rounding up */390390+ /* if necessary. */391391+ words = ((count + 3) >> 2);392392+ bytes_to_read = words << 2;393393+394394+ if (bytes_to_read > PAGE_SIZE)395395+ bytes_to_read = PAGE_SIZE;396396+397397+ /* Ensure we only read a complete number of words. */398398+ bytes_remaining = bytes_to_read & 3;399399+ bytes_to_read &= ~3;400400+ words = bytes_to_read >> 2;401401+402402+ status = drvdata->config->get_configuration(drvdata,403403+ kbuf, words);404404+405405+ /* If we didn't read correctly, then bail out. */406406+ if (status) {407407+ free_page((unsigned long)kbuf);408408+ goto error;409409+ }410410+411411+ /* If we fail to return the data to the user, then bail out. */412412+ if (copy_to_user(buf, kbuf, bytes_to_read)) {413413+ free_page((unsigned long)kbuf);414414+ status = -EFAULT;415415+ goto error;416416+ }417417+ memcpy(kbuf, drvdata->read_buffer, bytes_remaining);418418+ drvdata->read_buffer_in_use = bytes_remaining;419419+ free_page((unsigned long)kbuf);420420+ }421421+ status = bytes_to_read;422422+ error:423423+ up(&drvdata->sem);424424+ return status;425425+}426426+427427+static ssize_t428428+hwicap_write(struct file *file, const char *buf,429429+ size_t count, loff_t *ppos)430430+{431431+ struct hwicap_drvdata *drvdata = file->private_data;432432+ ssize_t written = 0;433433+ ssize_t left = count;434434+ u32 *kbuf;435435+ ssize_t len;436436+ ssize_t status;437437+438438+ if (down_interruptible(&drvdata->sem))439439+ return -ERESTARTSYS;440440+441441+ left += drvdata->write_buffer_in_use;442442+443443+ /* Only write multiples of 4 bytes. */444444+ if (left < 4) {445445+ status = 0;446446+ goto error;447447+ }448448+449449+ kbuf = (u32 *) __get_free_page(GFP_KERNEL);450450+ if (!kbuf) {451451+ status = -ENOMEM;452452+ goto error;453453+ }454454+455455+ while (left > 3) {456456+ /* only write multiples of 4 bytes, so there might */457457+ /* be as many as 3 bytes left (at the end). */458458+ len = left;459459+460460+ if (len > PAGE_SIZE)461461+ len = PAGE_SIZE;462462+ len &= ~3;463463+464464+ if (drvdata->write_buffer_in_use) {465465+ memcpy(kbuf, drvdata->write_buffer,466466+ drvdata->write_buffer_in_use);467467+ if (copy_from_user(468468+ (((char *)kbuf) + (drvdata->write_buffer_in_use)),469469+ buf + written,470470+ len - (drvdata->write_buffer_in_use))) {471471+ free_page((unsigned long)kbuf);472472+ status = -EFAULT;473473+ goto error;474474+ }475475+ } else {476476+ if (copy_from_user(kbuf, buf + written, len)) {477477+ free_page((unsigned long)kbuf);478478+ status = -EFAULT;479479+ goto error;480480+ }481481+ }482482+483483+ status = drvdata->config->set_configuration(drvdata,484484+ kbuf, len >> 2);485485+486486+ if (status) {487487+ free_page((unsigned long)kbuf);488488+ status = -EFAULT;489489+ goto error;490490+ }491491+ if (drvdata->write_buffer_in_use) {492492+ len -= drvdata->write_buffer_in_use;493493+ left -= drvdata->write_buffer_in_use;494494+ drvdata->write_buffer_in_use = 0;495495+ }496496+ written += len;497497+ left -= len;498498+ }499499+ if ((left > 0) && (left < 4)) {500500+ if (!copy_from_user(drvdata->write_buffer,501501+ buf + written, left)) {502502+ drvdata->write_buffer_in_use = left;503503+ written += left;504504+ left = 0;505505+ }506506+ }507507+508508+ free_page((unsigned long)kbuf);509509+ status = written;510510+ error:511511+ up(&drvdata->sem);512512+ return status;513513+}514514+515515+static int hwicap_open(struct inode *inode, struct file *file)516516+{517517+ struct hwicap_drvdata *drvdata;518518+ int status;519519+520520+ drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);521521+522522+ if (down_interruptible(&drvdata->sem))523523+ return -ERESTARTSYS;524524+525525+ if (drvdata->is_open) {526526+ status = -EBUSY;527527+ goto error;528528+ }529529+530530+ status = hwicap_initialize_hwicap(drvdata);531531+ if (status) {532532+ dev_err(drvdata->dev, "Failed to open file");533533+ goto error;534534+ }535535+536536+ file->private_data = drvdata;537537+ drvdata->write_buffer_in_use = 0;538538+ drvdata->read_buffer_in_use = 0;539539+ drvdata->is_open = 1;540540+541541+ error:542542+ up(&drvdata->sem);543543+ return status;544544+}545545+546546+static int hwicap_release(struct inode *inode, struct file *file)547547+{548548+ struct hwicap_drvdata *drvdata = file->private_data;549549+ int i;550550+ int status = 0;551551+552552+ if (down_interruptible(&drvdata->sem))553553+ return -ERESTARTSYS;554554+555555+ if (drvdata->write_buffer_in_use) {556556+ /* Flush write buffer. */557557+ for (i = drvdata->write_buffer_in_use; i < 4; i++)558558+ drvdata->write_buffer[i] = 0;559559+560560+ status = drvdata->config->set_configuration(drvdata,561561+ (u32 *) drvdata->write_buffer, 1);562562+ if (status)563563+ goto error;564564+ }565565+566566+ status = hwicap_command_desync(drvdata);567567+ if (status)568568+ goto error;569569+570570+ error:571571+ drvdata->is_open = 0;572572+ up(&drvdata->sem);573573+ return status;574574+}575575+576576+static struct file_operations hwicap_fops = {577577+ .owner = THIS_MODULE,578578+ .write = hwicap_write,579579+ .read = hwicap_read,580580+ .open = hwicap_open,581581+ .release = hwicap_release,582582+};583583+584584+static int __devinit hwicap_setup(struct device *dev, int id,585585+ const struct resource *regs_res,586586+ const struct hwicap_driver_config *config,587587+ const struct config_registers *config_regs)588588+{589589+ dev_t devt;590590+ struct hwicap_drvdata *drvdata = NULL;591591+ int retval = 0;592592+593593+ dev_info(dev, "Xilinx icap port driver\n");594594+595595+ if (id < 0) {596596+ for (id = 0; id < HWICAP_DEVICES; id++)597597+ if (!probed_devices[id])598598+ break;599599+ }600600+ if (id < 0 || id >= HWICAP_DEVICES) {601601+ dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);602602+ return -EINVAL;603603+ }604604+ if (probed_devices[id]) {605605+ dev_err(dev, "cannot assign to %s%i; it is already in use\n",606606+ DRIVER_NAME, id);607607+ return -EBUSY;608608+ }609609+610610+ probed_devices[id] = 1;611611+612612+ devt = MKDEV(xhwicap_major, xhwicap_minor + id);613613+614614+ drvdata = kmalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);615615+ if (!drvdata) {616616+ dev_err(dev, "Couldn't allocate device private record\n");617617+ return -ENOMEM;618618+ }619619+ memset((void *)drvdata, 0, sizeof(struct hwicap_drvdata));620620+ dev_set_drvdata(dev, (void *)drvdata);621621+622622+ if (!regs_res) {623623+ dev_err(dev, "Couldn't get registers resource\n");624624+ retval = -EFAULT;625625+ goto failed1;626626+ }627627+628628+ drvdata->mem_start = regs_res->start;629629+ drvdata->mem_end = regs_res->end;630630+ drvdata->mem_size = regs_res->end - regs_res->start + 1;631631+632632+ if (!request_mem_region(drvdata->mem_start,633633+ drvdata->mem_size, DRIVER_NAME)) {634634+ dev_err(dev, "Couldn't lock memory region at %p\n",635635+ (void *)regs_res->start);636636+ retval = -EBUSY;637637+ goto failed1;638638+ }639639+640640+ drvdata->devt = devt;641641+ drvdata->dev = dev;642642+ drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);643643+ if (!drvdata->base_address) {644644+ dev_err(dev, "ioremap() failed\n");645645+ goto failed2;646646+ }647647+648648+ drvdata->config = config;649649+ drvdata->config_regs = config_regs;650650+651651+ init_MUTEX(&drvdata->sem);652652+ drvdata->is_open = 0;653653+654654+ dev_info(dev, "ioremap %lx to %p with size %x\n",655655+ (unsigned long int)drvdata->mem_start,656656+ drvdata->base_address, drvdata->mem_size);657657+658658+ cdev_init(&drvdata->cdev, &hwicap_fops);659659+ drvdata->cdev.owner = THIS_MODULE;660660+ retval = cdev_add(&drvdata->cdev, devt, 1);661661+ if (retval) {662662+ dev_err(dev, "cdev_add() failed\n");663663+ goto failed3;664664+ }665665+ /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */666666+ class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME);667667+ return 0; /* success */668668+669669+ failed3:670670+ iounmap(drvdata->base_address);671671+672672+ failed2:673673+ release_mem_region(regs_res->start, drvdata->mem_size);674674+675675+ failed1:676676+ kfree(drvdata);677677+678678+ return retval;679679+}680680+681681+static struct hwicap_driver_config buffer_icap_config = {682682+ .get_configuration = buffer_icap_get_configuration,683683+ .set_configuration = buffer_icap_set_configuration,684684+ .reset = buffer_icap_reset,685685+};686686+687687+static struct hwicap_driver_config fifo_icap_config = {688688+ .get_configuration = fifo_icap_get_configuration,689689+ .set_configuration = fifo_icap_set_configuration,690690+ .reset = fifo_icap_reset,691691+};692692+693693+static int __devexit hwicap_remove(struct device *dev)694694+{695695+ struct hwicap_drvdata *drvdata;696696+697697+ drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);698698+699699+ if (!drvdata)700700+ return 0;701701+702702+ class_device_destroy(icap_class, drvdata->devt);703703+ cdev_del(&drvdata->cdev);704704+ iounmap(drvdata->base_address);705705+ release_mem_region(drvdata->mem_start, drvdata->mem_size);706706+ kfree(drvdata);707707+ dev_set_drvdata(dev, NULL);708708+ probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;709709+710710+ return 0; /* success */711711+}712712+713713+static int __devinit hwicap_drv_probe(struct platform_device *pdev)714714+{715715+ struct resource *res;716716+ const struct config_registers *regs;717717+ const char *family;718718+719719+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);720720+ if (!res)721721+ return -ENODEV;722722+723723+ /* It's most likely that we're using V4, if the family is not724724+ specified */725725+ regs = &v4_config_registers;726726+ family = pdev->dev.platform_data;727727+728728+ if (family) {729729+ if (!strcmp(family, "virtex2p")) {730730+ regs = &v2_config_registers;731731+ } else if (!strcmp(family, "virtex4")) {732732+ regs = &v4_config_registers;733733+ } else if (!strcmp(family, "virtex5")) {734734+ regs = &v5_config_registers;735735+ }736736+ }737737+738738+ return hwicap_setup(&pdev->dev, pdev->id, res,739739+ &buffer_icap_config, regs);740740+}741741+742742+static int __devexit hwicap_drv_remove(struct platform_device *pdev)743743+{744744+ return hwicap_remove(&pdev->dev);745745+}746746+747747+static struct platform_driver hwicap_platform_driver = {748748+ .probe = hwicap_drv_probe,749749+ .remove = hwicap_drv_remove,750750+ .driver = {751751+ .owner = THIS_MODULE,752752+ .name = DRIVER_NAME,753753+ },754754+};755755+756756+/* ---------------------------------------------------------------------757757+ * OF bus binding758758+ */759759+760760+#if defined(CONFIG_OF)761761+static int __devinit762762+hwicap_of_probe(struct of_device *op, const struct of_device_id *match)763763+{764764+ struct resource res;765765+ const unsigned int *id;766766+ const char *family;767767+ int rc;768768+ const struct hwicap_driver_config *config = match->data;769769+ const struct config_registers *regs;770770+771771+ dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match);772772+773773+ rc = of_address_to_resource(op->node, 0, &res);774774+ if (rc) {775775+ dev_err(&op->dev, "invalid address\n");776776+ return rc;777777+ }778778+779779+ id = of_get_property(op->node, "port-number", NULL);780780+781781+ /* It's most likely that we're using V4, if the family is not782782+ specified */783783+ regs = &v4_config_registers;784784+ family = of_get_property(op->node, "xlnx,family", NULL);785785+786786+ if (family) {787787+ if (!strcmp(family, "virtex2p")) {788788+ regs = &v2_config_registers;789789+ } else if (!strcmp(family, "virtex4")) {790790+ regs = &v4_config_registers;791791+ } else if (!strcmp(family, "virtex5")) {792792+ regs = &v5_config_registers;793793+ }794794+ }795795+ return hwicap_setup(&op->dev, id ? *id : -1, &res, config,796796+ regs);797797+}798798+799799+static int __devexit hwicap_of_remove(struct of_device *op)800800+{801801+ return hwicap_remove(&op->dev);802802+}803803+804804+/* Match table for of_platform binding */805805+static const struct of_device_id __devinit hwicap_of_match[] = {806806+ { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},807807+ { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},808808+ {},809809+};810810+MODULE_DEVICE_TABLE(of, hwicap_of_match);811811+812812+static struct of_platform_driver hwicap_of_driver = {813813+ .owner = THIS_MODULE,814814+ .name = DRIVER_NAME,815815+ .match_table = hwicap_of_match,816816+ .probe = hwicap_of_probe,817817+ .remove = __devexit_p(hwicap_of_remove),818818+ .driver = {819819+ .name = DRIVER_NAME,820820+ },821821+};822822+823823+/* Registration helpers to keep the number of #ifdefs to a minimum */824824+static inline int __devinit hwicap_of_register(void)825825+{826826+ pr_debug("hwicap: calling of_register_platform_driver()\n");827827+ return of_register_platform_driver(&hwicap_of_driver);828828+}829829+830830+static inline void __devexit hwicap_of_unregister(void)831831+{832832+ of_unregister_platform_driver(&hwicap_of_driver);833833+}834834+#else /* CONFIG_OF */835835+/* CONFIG_OF not enabled; do nothing helpers */836836+static inline int __devinit hwicap_of_register(void) { return 0; }837837+static inline void __devexit hwicap_of_unregister(void) { }838838+#endif /* CONFIG_OF */839839+840840+static int __devinit hwicap_module_init(void)841841+{842842+ dev_t devt;843843+ int retval;844844+845845+ icap_class = class_create(THIS_MODULE, "xilinx_config");846846+847847+ if (xhwicap_major) {848848+ devt = MKDEV(xhwicap_major, xhwicap_minor);849849+ retval = register_chrdev_region(850850+ devt,851851+ HWICAP_DEVICES,852852+ DRIVER_NAME);853853+ if (retval < 0)854854+ return retval;855855+ } else {856856+ retval = alloc_chrdev_region(&devt,857857+ xhwicap_minor,858858+ HWICAP_DEVICES,859859+ DRIVER_NAME);860860+ if (retval < 0)861861+ return retval;862862+ xhwicap_major = MAJOR(devt);863863+ }864864+865865+ retval = platform_driver_register(&hwicap_platform_driver);866866+867867+ if (retval)868868+ goto failed1;869869+870870+ retval = hwicap_of_register();871871+872872+ if (retval)873873+ goto failed2;874874+875875+ return retval;876876+877877+ failed2:878878+ platform_driver_unregister(&hwicap_platform_driver);879879+880880+ failed1:881881+ unregister_chrdev_region(devt, HWICAP_DEVICES);882882+883883+ return retval;884884+}885885+886886+static void __devexit hwicap_module_cleanup(void)887887+{888888+ dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);889889+890890+ class_destroy(icap_class);891891+892892+ platform_driver_unregister(&hwicap_platform_driver);893893+894894+ hwicap_of_unregister();895895+896896+ unregister_chrdev_region(devt, HWICAP_DEVICES);897897+}898898+899899+module_init(hwicap_module_init);900900+module_exit(hwicap_module_cleanup);901901+902902+MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group");903903+MODULE_DESCRIPTION("Xilinx ICAP Port Driver");904904+MODULE_LICENSE("GPL");
+193
drivers/char/xilinx_hwicap/xilinx_hwicap.h
···11+/*****************************************************************************22+ *33+ * Author: Xilinx, Inc.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the77+ * Free Software Foundation; either version 2 of the License, or (at your88+ * option) any later version.99+ *1010+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"1111+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND1212+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,1313+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,1414+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION1515+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,1616+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE1717+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY1818+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE1919+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR2020+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF2121+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS2222+ * FOR A PARTICULAR PURPOSE.2323+ *2424+ * Xilinx products are not intended for use in life support appliances,2525+ * devices, or systems. Use in such applications is expressly prohibited.2626+ *2727+ * (c) Copyright 2003-2007 Xilinx Inc.2828+ * All rights reserved.2929+ *3030+ * You should have received a copy of the GNU General Public License along3131+ * with this program; if not, write to the Free Software Foundation, Inc.,3232+ * 675 Mass Ave, Cambridge, MA 02139, USA.3333+ *3434+ *****************************************************************************/3535+3636+#ifndef XILINX_HWICAP_H_ /* prevent circular inclusions */3737+#define XILINX_HWICAP_H_ /* by using protection macros */3838+3939+#include <linux/types.h>4040+#include <linux/cdev.h>4141+#include <linux/version.h>4242+#include <linux/platform_device.h>4343+4444+#include <asm/io.h>4545+4646+struct hwicap_drvdata {4747+ u32 write_buffer_in_use; /* Always in [0,3] */4848+ u8 write_buffer[4];4949+ u32 read_buffer_in_use; /* Always in [0,3] */5050+ u8 read_buffer[4];5151+ u32 mem_start; /* phys. address of the control registers */5252+ u32 mem_end; /* phys. address of the control registers */5353+ u32 mem_size;5454+ void __iomem *base_address;/* virt. address of the control registers */5555+5656+ struct device *dev;5757+ struct cdev cdev; /* Char device structure */5858+ dev_t devt;5959+6060+ const struct hwicap_driver_config *config;6161+ const struct config_registers *config_regs;6262+ void *private_data;6363+ bool is_open;6464+ struct semaphore sem;6565+};6666+6767+struct hwicap_driver_config {6868+ int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data,6969+ u32 size);7070+ int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data,7171+ u32 size);7272+ void (*reset)(struct hwicap_drvdata *drvdata);7373+};7474+7575+/* Number of times to poll the done regsiter */7676+#define XHI_MAX_RETRIES 107777+7878+/************ Constant Definitions *************/7979+8080+#define XHI_PAD_FRAMES 0x18181+8282+/* Mask for calculating configuration packet headers */8383+#define XHI_WORD_COUNT_MASK_TYPE_1 0x7FFUL8484+#define XHI_WORD_COUNT_MASK_TYPE_2 0x1FFFFFUL8585+#define XHI_TYPE_MASK 0x78686+#define XHI_REGISTER_MASK 0xF8787+#define XHI_OP_MASK 0x38888+8989+#define XHI_TYPE_SHIFT 299090+#define XHI_REGISTER_SHIFT 139191+#define XHI_OP_SHIFT 279292+9393+#define XHI_TYPE_1 19494+#define XHI_TYPE_2 29595+#define XHI_OP_WRITE 29696+#define XHI_OP_READ 19797+9898+/* Address Block Types */9999+#define XHI_FAR_CLB_BLOCK 0100100+#define XHI_FAR_BRAM_BLOCK 1101101+#define XHI_FAR_BRAM_INT_BLOCK 2102102+103103+struct config_registers {104104+ u32 CRC;105105+ u32 FAR;106106+ u32 FDRI;107107+ u32 FDRO;108108+ u32 CMD;109109+ u32 CTL;110110+ u32 MASK;111111+ u32 STAT;112112+ u32 LOUT;113113+ u32 COR;114114+ u32 MFWR;115115+ u32 FLR;116116+ u32 KEY;117117+ u32 CBC;118118+ u32 IDCODE;119119+ u32 AXSS;120120+ u32 C0R_1;121121+ u32 CSOB;122122+ u32 WBSTAR;123123+ u32 TIMER;124124+ u32 BOOTSTS;125125+ u32 CTL_1;126126+};127127+128128+/* Configuration Commands */129129+#define XHI_CMD_NULL 0130130+#define XHI_CMD_WCFG 1131131+#define XHI_CMD_MFW 2132132+#define XHI_CMD_DGHIGH 3133133+#define XHI_CMD_RCFG 4134134+#define XHI_CMD_START 5135135+#define XHI_CMD_RCAP 6136136+#define XHI_CMD_RCRC 7137137+#define XHI_CMD_AGHIGH 8138138+#define XHI_CMD_SWITCH 9139139+#define XHI_CMD_GRESTORE 10140140+#define XHI_CMD_SHUTDOWN 11141141+#define XHI_CMD_GCAPTURE 12142142+#define XHI_CMD_DESYNCH 13143143+#define XHI_CMD_IPROG 15 /* Only in Virtex5 */144144+#define XHI_CMD_CRCC 16 /* Only in Virtex5 */145145+#define XHI_CMD_LTIMER 17 /* Only in Virtex5 */146146+147147+/* Packet constants */148148+#define XHI_SYNC_PACKET 0xAA995566UL149149+#define XHI_DUMMY_PACKET 0xFFFFFFFFUL150150+#define XHI_NOOP_PACKET (XHI_TYPE_1 << XHI_TYPE_SHIFT)151151+#define XHI_TYPE_2_READ ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \152152+ (XHI_OP_READ << XHI_OP_SHIFT))153153+154154+#define XHI_TYPE_2_WRITE ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \155155+ (XHI_OP_WRITE << XHI_OP_SHIFT))156156+157157+#define XHI_TYPE2_CNT_MASK 0x07FFFFFF158158+159159+#define XHI_TYPE_1_PACKET_MAX_WORDS 2047UL160160+#define XHI_TYPE_1_HEADER_BYTES 4161161+#define XHI_TYPE_2_HEADER_BYTES 8162162+163163+/* Constant to use for CRC check when CRC has been disabled */164164+#define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL165165+166166+/**167167+ * hwicap_type_1_read: Generates a Type 1 read packet header.168168+ * @parameter: Register is the address of the register to be read back.169169+ *170170+ * Generates a Type 1 read packet header, which is used to indirectly171171+ * read registers in the configuration logic. This packet must then172172+ * be sent through the icap device, and a return packet received with173173+ * the information.174174+ **/175175+static inline u32 hwicap_type_1_read(u32 Register)176176+{177177+ return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |178178+ (Register << XHI_REGISTER_SHIFT) |179179+ (XHI_OP_READ << XHI_OP_SHIFT);180180+}181181+182182+/**183183+ * hwicap_type_1_write: Generates a Type 1 write packet header184184+ * @parameter: Register is the address of the register to be read back.185185+ **/186186+static inline u32 hwicap_type_1_write(u32 Register)187187+{188188+ return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |189189+ (Register << XHI_REGISTER_SHIFT) |190190+ (XHI_OP_WRITE << XHI_OP_SHIFT);191191+}192192+193193+#endif
+15-38
drivers/serial/uartlite.c
···1717#include <linux/tty.h>1818#include <linux/delay.h>1919#include <linux/interrupt.h>2020+#include <linux/init.h>2021#include <asm/io.h>2122#if defined(CONFIG_OF)2323+#include <linux/of.h>2224#include <linux/of_device.h>2325#include <linux/of_platform.h>2626+2727+/* Match table for of_platform binding */2828+static struct of_device_id ulite_of_match[] __devinitdata = {2929+ { .compatible = "xlnx,opb-uartlite-1.00.b", },3030+ { .compatible = "xlnx,xps-uartlite-1.00.a", },3131+ {}3232+};3333+MODULE_DEVICE_TABLE(of, ulite_of_match);3434+2435#endif25362637#define ULITE_NAME "ttyUL"···286275287276static int ulite_request_port(struct uart_port *port)288277{278278+ pr_debug("ulite console: port=%p; port->mapbase=%x\n",279279+ port, port->mapbase);280280+289281 if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {290282 dev_err(port->dev, "Memory region busy\n");291283 return -EBUSY;···389375 spin_unlock_irqrestore(&port->lock, flags);390376}391377392392-#if defined(CONFIG_OF)393393-static inline void __init ulite_console_of_find_device(int id)394394-{395395- struct device_node *np;396396- struct resource res;397397- const unsigned int *of_id;398398- int rc;399399-400400- for_each_compatible_node(np, NULL, "xilinx,uartlite") {401401- of_id = of_get_property(np, "port-number", NULL);402402- if ((!of_id) || (*of_id != id))403403- continue;404404-405405- rc = of_address_to_resource(np, 0, &res);406406- if (rc)407407- continue;408408-409409- ulite_ports[id].mapbase = res.start;410410- of_node_put(np);411411- return;412412- }413413-}414414-#else /* CONFIG_OF */415415-static inline void __init ulite_console_of_find_device(int id) { /* do nothing */ }416416-#endif /* CONFIG_OF */417417-418378static int __init ulite_console_setup(struct console *co, char *options)419379{420380 struct uart_port *port;···402414403415 port = &ulite_ports[co->index];404416405405- /* Check if it is an OF device */406406- if (!port->mapbase)407407- ulite_console_of_find_device(co->index);408408-409409- /* Do we have a device now? */417417+ /* Has the device been initialized yet? */410418 if (!port->mapbase) {411419 pr_debug("console on ttyUL%i not present\n", co->index);412420 return -ENODEV;···600616{601617 return ulite_release(&op->dev);602618}603603-604604-/* Match table for of_platform binding */605605-static struct of_device_id __devinit ulite_of_match[] = {606606- { .type = "serial", .compatible = "xilinx,uartlite", },607607- {},608608-};609609-MODULE_DEVICE_TABLE(of, ulite_of_match);610619611620static struct of_platform_driver ulite_of_driver = {612621 .owner = THIS_MODULE,