Commit d5acba26 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here is the bit set of char/misc drivers for 4.19-rc1

  There is a lot here, much more than normal, seems like everyone is
  writing new driver subsystems these days... Anyway, major things here
  are:

   - new FSI driver subsystem, yet-another-powerpc low-level hardware
     bus

   - gnss, finally an in-kernel GPS subsystem to try to tame all of the
     crazy out-of-tree drivers that have been floating around for years,
     combined with some really hacky userspace implementations. This is
     only for GNSS receivers, but you have to start somewhere, and this
     is great to see.

  Other than that, there are new slimbus drivers, new coresight drivers,
  new fpga drivers, and loads of DT bindings for all of these and
  existing drivers.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (255 commits)
  android: binder: Rate-limit debug and userspace triggered err msgs
  fsi: sbefifo: Bump max command length
  fsi: scom: Fix NULL dereference
  misc: mic: SCIF Fix scif_get_new_port() error handling
  misc: cxl: changed asterisk position
  genwqe: card_base: Use true and false for boolean values
  misc: eeprom: assignment outside the if statement
  uio: potential double frees if __uio_register_device() fails
  eeprom: idt_89hpesx: clean up an error pointer vs NULL inconsistency
  misc: ti-st: Fix memory leak in the error path of probe()
  android: binder: Show extra_buffers_size in trace
  firmware: vpd: Fix section enabled flag on vpd_section_destroy
  platform: goldfish: Retire pdev_bus
  goldfish: Use dedicated macros instead of manual bit shifting
  goldfish: Add missing includes to goldfish.h
  mux: adgs1408: new driver for Analog Devices ADGS1408/1409 mux
  dt-bindings: mux: add adi,adgs1408
  Drivers: hv: vmbus: Cleanup synic memory free path
  Drivers: hv: vmbus: Remove use of slow_virt_to_phys()
  Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind()
  ...
parents 2475c515 128f3804
......@@ -42,6 +42,13 @@ Contact: K. Y. Srinivasan <kys@microsoft.com>
Description: The 16 bit vendor ID of the device
Users: tools/hv/lsvmbus and user level RDMA libraries
What: /sys/bus/vmbus/devices/<UUID>/numa_node
Date: Jul 2018
KernelVersion: 4.19
Contact: Stephen Hemminger <sthemmin@microsoft.com>
Description: This NUMA node to which the VMBUS device is
attached, or -1 if the node is unknown.
What: /sys/bus/vmbus/devices/<UUID>/channels/<N>
Date: September. 2017
KernelVersion: 4.14
......
......@@ -83,3 +83,11 @@ KernelVersion: 4.7
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) Indicates the capabilities of the Coresight TMC.
The value is read directly from the DEVID register, 0xFC8,
What: /sys/bus/coresight/devices/<memory_map>.tmc/buffer_size
Date: December 2018
KernelVersion: 4.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Size of the trace buffer for TMC-ETR when used in SYSFS
mode. Writable only for TMC-ETR configurations. The value
should be aligned to the kernel pagesize.
......@@ -35,3 +35,27 @@ Description: Read fpga manager state as a string.
* write complete = Doing post programming steps
* write complete error = Error while doing post programming
* operating = FPGA is programmed and operating
What: /sys/class/fpga_manager/<fpga>/status
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: Read fpga manager status as a string.
If FPGA programming operation fails, it could be caused by crc
error or incompatible bitstream image. The intent of this
interface is to provide more detailed information for FPGA
programming errors to userspace. This is a list of strings for
the supported status.
* reconfig operation error - invalid operations detected by
reconfiguration hardware.
e.g. start reconfiguration
with errors not cleared
* reconfig CRC error - CRC error detected by
reconfiguration hardware.
* reconfig incompatible image - reconfiguration image is
incompatible with hardware
* reconfig IP protocol error - protocol errors detected by
reconfiguration hardware
* reconfig fifo overflow error - FIFO overflow detected by
reconfiguration hardware
What: /sys/class/fpga_region/<region>/compat_id
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: FPGA region id for compatibility check, e.g. compatibility
of the FPGA reconfiguration hardware and image. This value
is defined or calculated by the layer that is creating the
FPGA region. This interface returns the compat_id value or
just error code -ENOENT in case compat_id is not used.
What: /sys/class/gnss/gnssN/type
Date: May 2018
KernelVersion: 4.18
Contact: Johan Hovold <johan@kernel.org>
Description:
The GNSS receiver type. The currently identified types reflect
the protocol(s) supported by the receiver:
"NMEA" NMEA 0183
"SiRF" SiRF Binary
"UBX" UBX
Note that also non-"NMEA" type receivers typically support a
subset of NMEA 0183 with vendor extensions (e.g. to allow
switching to a vendor protocol).
......@@ -54,3 +54,14 @@ Description: Configure tx queue limit
Set maximal number of pending writes
per opened session.
What: /sys/class/mei/meiN/fw_ver
Date: May 2018
KernelVersion: 4.18
Contact: Tomas Winkler <tomas.winkler@intel.com>
Description: Display the ME firmware version.
The version of the platform ME firmware is in format:
<platform>:<major>.<minor>.<milestone>.<build_no>.
There can be up to three such blocks for different
FW components.
What: /sys/bus/platform/devices/dfl-fme.0/ports_num
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. One DFL FPGA device may have more than 1
port/Accelerator Function Unit (AFU). It returns the
number of ports on the FPGA device when read it.
What: /sys/bus/platform/devices/dfl-fme.0/bitstream_id
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns Bitstream (static FPGA region)
identifier number, which includes the detailed version
and other information of this static FPGA region.
What: /sys/bus/platform/devices/dfl-fme.0/bitstream_metadata
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns Bitstream (static FPGA region) meta
data, which includes the synthesis date, seed and other
information of this static FPGA region.
What: /sys/bus/platform/devices/dfl-port.0/id
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. It returns id of this port. One DFL FPGA device
may have more than one port. Userspace could use this id to
distinguish different ports under same FPGA device.
What: /sys/bus/platform/devices/dfl-port.0/afu_id
Date: June 2018
KernelVersion: 4.19
Contact: Wu Hao <hao.wu@intel.com>
Description: Read-only. User can program different PR bitstreams to FPGA
Accelerator Function Unit (AFU) for different functions. It
returns uuid which could be used to identify which PR bitstream
is programmed in this AFU.
......@@ -39,6 +39,8 @@ its hardware characteristcs.
- System Trace Macrocell:
"arm,coresight-stm", "arm,primecell"; [1]
- Coresight Address Translation Unit (CATU)
"arm,coresight-catu", "arm,primecell";
* reg: physical base address and length of the register
set(s) of the component.
......@@ -84,8 +86,15 @@ its hardware characteristcs.
* Optional property for TMC:
* arm,buffer-size: size of contiguous buffer space for TMC ETR
(embedded trace router)
(embedded trace router). This property is obsolete. The buffer size
can be configured dynamically via buffer_size property in sysfs.
* arm,scatter-gather: boolean. Indicates that the TMC-ETR can safely
use the SG mode on this system.
* Optional property for CATU :
* interrupts : Exactly one SPI may be listed for reporting the address
error
Example:
......@@ -118,6 +127,35 @@ Example:
};
};
etr@20070000 {
compatible = "arm,coresight-tmc", "arm,primecell";
reg = <0 0x20070000 0 0x1000>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* input port */
port@0 {
reg = <0>;
etr_in_port: endpoint {
slave-mode;
remote-endpoint = <&replicator2_out_port0>;
};
};
/* CATU link represented by output port */
port@1 {
reg = <1>;
etr_out_port: endpoint {
remote-endpoint = <&catu_in_port>;
};
};
};
};
2. Links
replicator {
/* non-configurable replicators don't show up on the
......@@ -247,5 +285,23 @@ Example:
};
};
5. CATU
catu@207e0000 {
compatible = "arm,coresight-catu", "arm,primecell";
reg = <0 0x207e0000 0 0x1000>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
port {
catu_in_port: endpoint {
slave-mode;
remote-endpoint = <&etr_out_port>;
};
};
};
[1]. There is currently two version of STM: STM32 and STM500. Both
have the same HW interface and as such don't need an explicit binding name.
Device-tree bindings for ColdFire offloaded gpio-based FSI master driver
------------------------------------------------------------------------
Required properties:
- compatible =
"aspeed,ast2400-cf-fsi-master" for an AST2400 based system
or
"aspeed,ast2500-cf-fsi-master" for an AST2500 based system
- clock-gpios = <gpio-descriptor>; : GPIO for FSI clock
- data-gpios = <gpio-descriptor>; : GPIO for FSI data signal
- enable-gpios = <gpio-descriptor>; : GPIO for enable signal
- trans-gpios = <gpio-descriptor>; : GPIO for voltage translator enable
- mux-gpios = <gpio-descriptor>; : GPIO for pin multiplexing with other
functions (eg, external FSI masters)
- memory-region = <phandle>; : Reference to the reserved memory for
the ColdFire. Must be 2M aligned on
AST2400 and 1M aligned on AST2500
- aspeed,sram = <phandle>; : Reference to the SRAM node.
- aspeed,cvic = <phandle>; : Reference to the CVIC node.
Examples:
fsi-master {
compatible = "aspeed,ast2500-cf-fsi-master", "fsi-master";
clock-gpios = <&gpio 0>;
data-gpios = <&gpio 1>;
enable-gpios = <&gpio 2>;
trans-gpios = <&gpio 3>;
mux-gpios = <&gpio 4>;
memory-region = <&coldfire_memory>;
aspeed,sram = <&sram>;
aspeed,cvic = <&cvic>;
}
......@@ -83,6 +83,10 @@ addresses and sizes in the slave address space:
#address-cells = <1>;
#size-cells = <1>;
Optionally, a slave can provide a global unique chip ID which is used to
identify the physical location of the chip in a system specific way
chip-id = <0>;
FSI engines (devices)
---------------------
......@@ -125,6 +129,7 @@ device tree if no extra platform information is required.
reg = <0 0>;
#address-cells = <1>;
#size-cells = <1>;
chip-id = <0>;
/* FSI engine at 0xc00, using a single page. In this example,
* it's an I2C master controller, so subnodes describe the
......
GNSS Receiver DT binding
This documents the binding structure and common properties for GNSS receiver
devices.
A GNSS receiver node is a node named "gnss" and typically resides on a serial
bus (e.g. UART, I2C or SPI).
Please refer to the following documents for generic properties:
Documentation/devicetree/bindings/serial/slave-device.txt
Documentation/devicetree/bindings/spi/spi-bus.txt
Required properties:
- compatible : A string reflecting the vendor and specific device the node
represents
Optional properties:
- enable-gpios : GPIO used to enable the device
- timepulse-gpios : Time pulse GPIO
Example:
serial@1234 {
compatible = "ns16550a";
gnss {
compatible = "u-blox,neo-8";
vcc-supply = <&gnss_reg>;
timepulse-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
current-speed = <4800>;
};
};
SiRFstar-based GNSS Receiver DT binding
SiRFstar chipsets are used in GNSS-receiver modules produced by several
vendors and can use UART, SPI or I2C interfaces.
Please see Documentation/devicetree/bindings/gnss/gnss.txt for generic
properties.
Required properties:
- compatible : Must be one of
"fastrax,uc430"
"linx,r4"
"wi2wi,w2sg0008i"
"wi2wi,w2sg0084i"
- vcc-supply : Main voltage regulator (pin name: 3V3_IN, VCC, VDD)
Required properties (I2C):
- reg : I2C slave address
Required properties (SPI):
- reg : SPI chip select address
Optional properties:
- sirf,onoff-gpios : GPIO used to power on and off device (pin name: ON_OFF)
- sirf,wakeup-gpios : GPIO used to determine device power state
(pin name: RFPWRUP, WAKEUP)
- timepulse-gpios : Time pulse GPIO (pin name: 1PPS, TM)
Example:
serial@1234 {
compatible = "ns16550a";
gnss {
compatible = "wi2wi,w2sg0084i";
vcc-supply = <&gnss_reg>;
sirf,onoff-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
sirf,wakeup-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
};
};
u-blox GNSS Receiver DT binding
The u-blox GNSS receivers can use UART, DDC (I2C), SPI and USB interfaces.
Please see Documentation/devicetree/bindings/gnss/gnss.txt for generic
properties.
Required properties:
- compatible : Must be one of
"u-blox,neo-8"
"u-blox,neo-m8"
- vcc-supply : Main voltage regulator
Required properties (DDC):
- reg : DDC (I2C) slave address
Required properties (SPI):
- reg : SPI chip select address
Required properties (USB):
- reg : Number of the USB hub port or the USB host-controller port
to which this device is attached
Optional properties:
- timepulse-gpios : Time pulse GPIO
- u-blox,extint-gpios : GPIO connected to the "external interrupt" input pin
- v-bckp-supply : Backup voltage regulator
Example:
serial@1234 {
compatible = "ns16550a";
gnss {
compatible = "u-blox,neo-8";
v-bckp-supply = <&gnss_v_bckp_reg>;
vcc-supply = <&gnss_vcc_reg>;
};
};
Bindings for Analog Devices ADGS1408/1409 8:1/Dual 4:1 Mux
Required properties:
- compatible : Should be one of
* "adi,adgs1408"
* "adi,adgs1409"
* Standard mux-controller bindings as described in mux-controller.txt
Optional properties for ADGS1408/1409:
- gpio-controller : if present, #gpio-cells is required.
- #gpio-cells : should be <2>
- First cell is the GPO line number, i.e. 0 to 3
for ADGS1408 and 0 to 4 for ADGS1409
- Second cell is used to specify active high (0)
or active low (1)
Optional properties:
- idle-state : if present, the state that the mux controller will have
when idle. The special state MUX_IDLE_AS_IS is the default and
MUX_IDLE_DISCONNECT is also supported.
States 0 through 7 correspond to signals S1 through S8 in the datasheet.
For ADGS1409 only states 0 to 3 are available.
Example:
/*
* One mux controller.
* Mux state set to idle as is (no idle-state declared)
*/
&spi0 {
mux: mux-controller@0 {
compatible = "adi,adgs1408";
reg = <0>;
spi-max-frequency = <1000000>;
#mux-control-cells = <0>;
};
}
adc-mux {
compatible = "io-channel-mux";
io-channels = <&adc 1>;
io-channel-names = "parent";
mux-controls = <&mux>;
channels = "out_a0", "out_a1", "test0", "test1",
"out_b0", "out_b1", "testb0", "testb1";
};
Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
This binding represents the on-chip eFuse OTP controller found on
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX and i.MX6UL SoCs.
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL and i.MX6SLL SoCs.
Required properties:
- compatible: should be one of
......@@ -10,6 +10,7 @@ Required properties:
"fsl,imx6sx-ocotp" (i.MX6SX),
"fsl,imx6ul-ocotp" (i.MX6UL),
"fsl,imx7d-ocotp" (i.MX7D/S),
"fsl,imx6sll-ocotp" (i.MX6SLL),
followed by "syscon".
- #address-cells : Should be 1
- #size-cells : Should be 1
......
= Spreadtrum SC27XX PMIC eFuse device tree bindings =
Required properties:
- compatible: Should be one of the following.
"sprd,sc2720-efuse"
"sprd,sc2721-efuse"
"sprd,sc2723-efuse"
"sprd,sc2730-efuse"
"sprd,sc2731-efuse"
- reg: Specify the address offset of efuse controller.
- hwlocks: Reference to a phandle of a hwlock provider node.
= Data cells =
Are child nodes of eFuse, bindings of which as described in
bindings/nvmem/nvmem.txt
Example:
sc2731_pmic: pmic@0 {
compatible = "sprd,sc2731";
reg = <0>;
spi-max-frequency = <26000000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
efuse@380 {
compatible = "sprd,sc2731-efuse";
reg = <0x380>;
#address-cells = <1>;
#size-cells = <1>;
hwlocks = <&hwlock 12>;
/* Data cells */
thermal_calib: calib@10 {
reg = <0x10 0x2>;
};
};
};
= Data consumers =
Are device nodes which consume nvmem data cells.
Example:
thermal {
...
nvmem-cells = <&thermal_calib>;
nvmem-cell-names = "calibration";
};
Qualcomm SLIMBus Non Generic Device (NGD) Controller binding
SLIMBus NGD controller is a light-weight driver responsible for communicating
with SLIMBus slaves directly over the bus using messaging interface and
communicating with master component residing on ADSP for bandwidth and
data-channel management
Please refer to slimbus/bus.txt for details of the common SLIMBus bindings.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,slim-ngd-v<MAJOR>.<MINOR>.<STEP>"
must be one of the following.
"qcom,slim-ngd-v1.5.0" for MSM8996
"qcom,slim-ngd-v2.1.0" for SDM845
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: must specify the base address and size of the controller
register space.
- dmas
Usage: required
Value type: <array of phandles>
Definition: List of rx and tx dma channels
- dma-names
Usage: required
Value type: <stringlist>
Definition: must be "rx" and "tx".
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: must list controller IRQ.
#address-cells
Usage: required
Value type: <u32>
Definition: Should be 1, reflecting the instance id of ngd.
#size-cells
Usage: required
Value type: <u32>
Definition: Should be 0
= NGD Devices
Each subnode represents an instance of NGD, must contain the following
properties:
- reg:
Usage: required
Value type: <u32>
Definition: Should be instance id of ngd.
#address-cells
Usage: required
Refer to slimbus/bus.txt for details of the common SLIMBus bindings.
#size-cells
Usage: required
Refer to slimbus/bus.txt for details of the common SLIMBus bindings.
= EXAMPLE
slim@91c0000 {
compatible = "qcom,slim-ngd-v1.5.0";
reg = <0x91c0000 0x2c000>;
interrupts = <0 163 0>;
dmas = <&slimbam 3>, <&slimbam 4>;
dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <0>;
ngd@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <1>;
codec@1 {
compatible = "slim217,1a0";
reg = <1 0>;
};
};
};
......@@ -129,6 +129,7 @@ excito Excito
ezchip EZchip Semiconductor
fairphone Fairphone B.V.
faraday Faraday Technology Corporation
fastrax Fastrax Oy
fcs Fairchild Semiconductor
firefly Firefly
focaltech FocalTech Systems Co.,Ltd
......@@ -209,6 +210,7 @@ licheepi Lichee Pi
linaro Linaro Limited
linksys Belkin International, Inc. (Linksys)
linux Linux-specific binding
linx Linx Technologies
lltc Linear Technology Corporation
logicpd Logic PD, Inc.
lsi LSI Corp. (LSI Logic)
......@@ -390,6 +392,7 @@ tronsmart Tronsmart
truly Truly Semiconductors Limited
tsd Theobroma Systems Design und Consulting GmbH
tyan Tyan Computer Corporation
u-blox u-blox
ucrobotics uCRobotics
ubnt Ubiquiti Networks
udoo Udoo
......
......@@ -83,7 +83,7 @@ The programming sequence is::
3. .write_complete
The .write_init function will prepare the FPGA to receive the image data. The
buffer passed into .write_init will be atmost .initial_header_size bytes long,
buffer passed into .write_init will be at most .initial_header_size bytes long;
if the whole bitstream is not immediately available then the core code will
buffer up at least this much before starting.
......@@ -98,9 +98,9 @@ scatter list. This interface is suitable for drivers which use DMA.
The .write_complete function is called after all the image has been written
to put the FPGA into operating mode.
The ops include a .state function which will read the hardware FPGA manager and
return a code of type enum fpga_mgr_states. It doesn't result in a change in
hardware state.
The ops include a .state function which will determine the state the FPGA is in
and return a code of type enum fpga_mgr_states. It doesn't result in a change
in state.
How to write an image buffer to a supported FPGA
------------------------------------------------
......@@ -181,8 +181,8 @@ API for implementing a new FPGA Manager driver
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_unregister
API for programming a FPGA
--------------------------
API for programming an FPGA
---------------------------
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_image_info
......
......@@ -4,7 +4,7 @@ FPGA Region
Overview
--------
This document is meant to be an brief overview of the FPGA region API usage. A
This document is meant to be a brief overview of the FPGA region API usage. A
more conceptual look at regions can be found in the Device Tree binding
document [#f1]_.
......@@ -31,11 +31,11 @@ fpga_image_info including:
* pointers to the image as either a scatter-gather buffer, a contiguous
buffer, or the name of firmware file
* flags indicating specifics such as whether the image if for partial
* flags indicating specifics such as whether the image is for partial
reconfiguration.
How to program a FPGA using a region
------------------------------------
How to program an FPGA using a region
-------------------------------------
First, allocate the info struct::
......@@ -77,8 +77,8 @@ An example of usage can be seen in the probe function of [#f2]_.
.. [#f1] ../devicetree/bindings/fpga/fpga-region.txt
.. [#f2] ../../drivers/fpga/of-fpga-region.c
API to program a FGPA
---------------------
API to program an FPGA
----------------------
.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: fpga_region_program_fpga
......
......@@ -12,18 +12,18 @@ Linux. Some of the core intentions of the FPGA subsystems are:
* Code should not be shared between upper and lower layers. This
should go without saying. If that seems necessary, there's probably
framework functionality that that can be added that will benefit
framework functionality that can be added that will benefit
other users. Write the linux-fpga mailing list and maintainers and
seek out a solution that expands the framework for broad reuse.
* Generally, when adding code, think of the future. Plan for re-use.
* Generally, when adding code, think of the future. Plan for reuse.
The framework in the kernel is divided into:
FPGA Manager
------------
If you are adding a new FPGA or a new method of programming a FPGA,
If you are adding a new FPGA or a new method of programming an FPGA,
this is the subsystem for you. Low level FPGA manager drivers contain
the knowledge of how to program a specific device. This subsystem
includes the framework in fpga-mgr.c and the low level drivers that
......@@ -32,10 +32,10 @@ are registered with it.
FPGA Bridge
-----------
FPGA Bridges prevent spurious signals from going out of a FPGA or a
region of a FPGA during programming. They are disabled before
FPGA Bridges prevent spurious signals from going out of an FPGA or a
region of an FPGA during programming. They are disabled before
programming begins and re-enabled afterwards. An FPGA bridge may be
actual hard hardware that gates a bus to a cpu or a soft ("freeze")
actual hard hardware that gates a bus to a CPU or a soft ("freeze")
bridge in FPGA fabric that surrounds a partial reconfiguration region
of an FPGA. This subsystem includes fpga-bridge.c and the low level
drivers that are registered with it.
......@@ -44,7 +44,7 @@ FPGA Region
-----------
If you are adding a new interface to the FPGA framework, add it on top
of a FPGA region to allow the most reuse of your interface.
of an FPGA region to allow the most reuse of your interface.
The FPGA Region framework (fpga-region.c) associates managers and
bridges as reconfigurable regions. A region may refer to the whole
......
......@@ -125,3 +125,8 @@ Messaging APIs:
~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/slimbus/messaging.c
:export:
Streaming APIs:
~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/slimbus/stream.c
:export:
This diff is collapsed.
......@@ -324,6 +324,7 @@ Code Seq#(hex) Include File Comments
0xB3 00 linux/mmc/ioctl.h
0xB4 00-0F linux/gpio.h <mailto:linux-gpio@vger.kernel.org>
0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
0xB6 all linux/fpga-dfl.h
0xC0 00-0F linux/usb/iowarrior.h
0xCA 00-0F uapi/misc/cxl.h
0xCA 10-2F uapi/misc/ocxl.h
......
......@@ -39,6 +39,7 @@ show up in /proc/sys/kernel:
- hung_task_check_count
- hung_task_timeout_secs
- hung_task_warnings
- hyperv_record_panic_msg
- kexec_load_disabled
- kptr_restrict
- l2cr [ PPC only ]
......@@ -374,6 +375,16 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
==============================================================
hyperv_record_panic_msg:
Controls whether the panic kmsg data should be reported to Hyper-V.
0: do not report panic kmsg data.
1: report the panic kmsg data. This is the default behavior.
==============================================================
kexec_load_disabled:
A toggle indicating if the kexec_load syscall has been disabled. This
......
......@@ -60,4 +60,4 @@ vad: general purpose A/D input (VAD)
vdd: battery input (VDD)
After the voltage conversion the value is returned as decimal ASCII.
Note: The value is in mV, so to get a volts the value has to be divided by 10.
Note: To get a volts the value has to be divided by 100.
......@@ -836,6 +836,12 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/ad9389b*
ANALOG DEVICES INC ADGS1408 DRIVER
M: Mircea Caprioru <mircea.caprioru@analog.com>
S: Supported
F: drivers/mux/adgs1408.c
F: Documentation/devicetree/bindings/mux/adgs1408.txt
ANALOG DEVICES INC ADV7180 DRIVER
M: Lars-Peter Clausen <lars@metafoo.de>
L: linux-media@vger.kernel.org
......@@ -5714,6 +5720,14 @@ F: drivers/fpga/
F: include/linux/fpga/
W: http://www.rocketboards.org
FPGA DFL DRIVERS
M: Wu Hao <hao.wu@intel.com>
L: linux-fpga@vger.kernel.org
S: Maintained
F: Documentation/fpga/dfl.txt
F: include/uapi/linux/fpga-dfl.h
F: drivers/fpga/dfl*
FPU EMULATOR
M: Bill Metzenthen <billm@melbpc.org.au>
W: http://floatingpoint.sourceforge.net/emulator/index.html
......@@ -6130,6 +6144,14 @@ F: Documentation/isdn/README.gigaset
F: drivers/isdn/gigaset/
F: include/uapi/linux/gigaset_dev.h
GNSS SUBSYSTEM
M: Johan Hovold <johan@kernel.org>
S: Maintained
F: Documentation/ABI/testing/sysfs-class-gnss
F: Documentation/devicetree/bindings/gnss/
F: drivers/gnss/
F: include/linux/gnss.h
GO7007 MPEG CODEC
M: Hans Verkuil <hans.verkuil@cisco.com>
L: linux-media@vger.kernel.org
......@@ -15523,7 +15545,7 @@ F: include/linux/vme*
VMWARE BALLOON DRIVER
M: Xavier Deguillard <xdeguillard@vmware.com>
M: Philip Moltmann <moltmann@vmware.com>
M: Nadav Amit <namit@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
L: linux-kernel@vger.kernel.org
S: Maintained
......@@ -15615,6 +15637,7 @@ F: drivers/mmc/host/vub300.c
W1 DALLAS'S 1-WIRE BUS
M: Evgeniy Polyakov <zbr@ioremap.net>
S: Maintained
F: Documentation/devicetree/bindings/w1/
F: Documentation/w1/
F: drivers/w1/
F: include/linux/w1.h
......
......@@ -52,6 +52,7 @@ fsi: gpio-fsi {
compatible = "fsi-master-gpio", "fsi-master";
#address-cells = <2>;
#size-cells = <0>;
no-gpio-delays;
clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
data-gpios = <&gpio ASPEED_GPIO(AA, 2) GPIO_ACTIVE_HIGH>;
......
......@@ -153,6 +153,7 @@ fsi: gpio-fsi {
compatible = "fsi-master-gpio", "fsi-master";
#address-cells = <2>;
#size-cells = <0>;
no-gpio-delays;
clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
data-gpios = <&gpio ASPEED_GPIO(E, 0) GPIO_ACTIVE_HIGH>;
......
......@@ -91,6 +91,7 @@ fsi: gpio-fsi {
compatible = "fsi-master-gpio", "fsi-master";
#address-cells = <2>;
#size-cells = <0>;
no-gpio-delays;
trans-gpios = <&gpio ASPEED_GPIO(O, 6) GPIO_ACTIVE_HIGH>;
enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
......
......@@ -15,6 +15,7 @@
*/
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
......
......@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/list.h>
......
......@@ -333,7 +333,7 @@ void __init hyperv_init(void)
* Register Hyper-V specific clocksource.
*/
#ifdef CONFIG_HYPERV_TSCPAGE
if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
if (ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE) {
union hv_x64_msr_hypercall_contents tsc_msr;
tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
......@@ -362,7 +362,7 @@ void __init hyperv_init(void)
*/
hyperv_cs = &hyperv_cs_msr;
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
if (ms_hyperv.features & HV_MSR_TIME_REF_COUNT_AVAILABLE)
clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
return;
......@@ -426,6 +426,33 @@ void hyperv_report_panic(struct pt_regs *regs, long err)
}
EXPORT_SYMBOL_GPL(hyperv_report_panic);
/**
* hyperv_report_panic_msg - report panic message to Hyper-V
* @pa: physical address of the panic page containing the message
* @size: size of the message in the page
*/
void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
{
/*
* P3 to contain the physical address of the panic page & P4 to
* contain the size of the panic data in that page. Rest of the
* registers are no-op when the NOTIFY_MSG flag is set.
*/
wrmsrl(HV_X64_MSR_CRASH_P0, 0);
wrmsrl(HV_X64_MSR_CRASH_P1, 0);
wrmsrl(HV_X64_MSR_CRASH_P2, 0);
wrmsrl(HV_X64_MSR_CRASH_P3, pa);
wrmsrl(HV_X64_MSR_CRASH_P4, size);
/*
* Let Hyper-V know there is crash data available along with
* the panic message.
*/
wrmsrl(HV_X64_MSR_CRASH_CTL,
(HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
}
EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
bool hv_is_hyperv_initialized(void)
{
union hv_x64_msr_hypercall_contents hypercall_msr;
......
......@@ -35,9 +35,9 @@
/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
#define HV_X64_MSR_VP_RUNTIME_AVAILABLE (1 << 0)
/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
#define HV_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
/* Partition reference TSC MSR is available */
#define HV_X64_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
#define HV_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
/* A partition's reference time stamp counter (TSC) page */
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
......@@ -60,7 +60,7 @@
* Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
* HV_X64_MSR_STIMER3_COUNT) available
*/
#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3)
#define HV_MSR_SYNTIMER_AVAILABLE (1 << 3)
/*
* APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
* are available
......@@ -86,7 +86,7 @@
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
/* stimer Direct Mode is available */
#define HV_X64_STIMER_DIRECT_MODE_AVAILABLE (1 << 19)
#define HV_STIMER_DIRECT_MODE_AVAILABLE (1 << 19)
/*
* Feature identification: EBX indicates which flags were specified at
......@@ -160,9 +160,9 @@
#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
/*
* Virtual APIC support
* Recommend not using Auto End-Of-Interrupt feature
*/
#define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9)
#define HV_DEPRECATING_AEOI_RECOMMENDED (1 << 9)
/*
* Recommend using cluster IPI hypercalls.
......@@ -176,9 +176,10 @@
#define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED (1 << 14)
/*
* Crash notification flag.
* Crash notification flags.
*/
#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
#define HV_CRASH_CTL_CRASH_NOTIFY_MSG BIT_ULL(62)
#define HV_CRASH_CTL_CRASH_NOTIFY BIT_ULL(63)
/* MSR used to identify the guest OS. */
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
......
......@@ -76,8 +76,10 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
}
}
#define hv_init_timer(timer, tick) wrmsrl(timer, tick)
#define hv_init_timer_config(config, val) wrmsrl(config, val)
#define hv_init_timer(timer, tick) \
wrmsrl(HV_X64_MSR_STIMER0_COUNT + (2*timer), tick)
#define hv_init_timer_config(timer, val) \
wrmsrl(HV_X64_MSR_STIMER0_CONFIG + (2*timer), val)
#define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val)
#define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val)
......@@ -90,8 +92,13 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
#define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
#define hv_get_synint_state(int_num, val) rdmsrl(int_num, val)
#define hv_set_synint_state(int_num, val) wrmsrl(int_num, val)
#define hv_get_synint_state(int_num, val) \
rdmsrl(HV_X64_MSR_SINT0 + int_num, val)
#define hv_set_synint_state(int_num, val) \
wrmsrl(HV_X64_MSR_SINT0 + int_num, val)
#define hv_get_crash_ctl(val) \
rdmsrl(HV_X64_MSR_CRASH_CTL, val)
void hyperv_callback_vector(void);
void hyperv_reenlightenment_vector(void);
......@@ -332,6 +339,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
void __init hyperv_init(void);
void hyperv_setup_mmu_ops(void);
void hyperv_report_panic(struct pt_regs *regs, long err);
void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
bool hv_is_hyperv_initialized(void);
void hyperv_cleanup(void);
......
......@@ -41,7 +41,7 @@ static void (*hv_stimer0_handler)(void);
static void (*hv_kexec_handler)(void);
static void (*hv_crash_handler)(struct pt_regs *regs);
void hyperv_vector_handler(struct pt_regs *regs)
__visible void __irq_entry hyperv_vector_handler(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
......@@ -50,7 +50,7 @@ void hyperv_vector_handler(struct pt_regs *regs)
if (vmbus_handler)
vmbus_handler();
if (ms_hyperv.hints & HV_X64_DEPRECATING_AEOI_RECOMMENDED)
if (ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED)
ack_APIC_irq();
exiting_irq();
......@@ -300,7 +300,7 @@ static void __init ms_hyperv_init_platform(void)
hyperv_reenlightenment_vector);
/* Setup the IDT for stimer0 */
if (ms_hyperv.misc_features & HV_X64_STIMER_DIRECT_MODE_AVAILABLE)
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
alloc_intr_gate(HYPERV_STIMER0_VECTOR,
hv_stimer0_callback_vector);
#endif
......
......@@ -9,6 +9,8 @@ source "drivers/bus/Kconfig"
source "drivers/connector/Kconfig"
source "drivers/gnss/Kconfig"
source "drivers/mtd/Kconfig"
source "drivers/of/Kconfig"
......
......@@ -185,3 +185,4 @@ obj-$(CONFIG_TEE) += tee/
obj-$(CONFIG_MULTIPLEXER) += mux/
obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/
obj-$(CONFIG_SIOX) += siox/
obj-$(CONFIG_GNSS) += gnss/
......@@ -10,7 +10,7 @@ if ANDROID
config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
depends on MMU && !M68K
depends on MMU
default n
---help---
Binder is used in Android for both communication between processes,
......
......@@ -51,7 +51,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <asm/cacheflush.h>
#include <linux/fdtable.h>
#include <linux/file.h>
#include <linux/freezer.h>
......@@ -71,8 +70,12 @@
#include <linux/pid_namespace.h>
#include <linux/security.h>
#include <linux/spinlock.h>
#include <linux/ratelimit.h>
#include <uapi/linux/android/binder.h>
#include <asm/cacheflush.h>
#include "binder_alloc.h"
#include "binder_trace.h"
......@@ -161,13 +164,13 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error,
#define binder_debug(mask, x...) \
do { \
if (binder_debug_mask & mask) \
pr_info(x); \
pr_info_ratelimited(x); \
} while (0)
#define binder_user_error(x...) \
do { \
if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \
pr_info(x); \
pr_info_ratelimited(x); \
if (binder_stop_on_user_error) \
binder_stop_on_user_error = 2; \
} while (0)
......
......@@ -17,7 +17,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <asm/cacheflush.h>
#include <linux/list.h>
#include <linux/sched/mm.h>
#include <linux/module.h>
......@@ -28,6 +27,8 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/list_lru.h>
#include <linux/ratelimit.h>
#include <asm/cacheflush.h>
#include "binder_alloc.h"
#include "binder_trace.h"
......@@ -36,11 +37,12 @@ struct list_lru binder_alloc_lru;
static DEFINE_MUTEX(binder_alloc_mmap_lock);
enum {
BINDER_DEBUG_USER_ERROR = 1U << 0,
BINDER_DEBUG_OPEN_CLOSE = 1U << 1,
BINDER_DEBUG_BUFFER_ALLOC = 1U << 2,
BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3,
};
static uint32_t binder_alloc_debug_mask;
static uint32_t binder_alloc_debug_mask = BINDER_DEBUG_USER_ERROR;
module_param_named(debug_mask, binder_alloc_debug_mask,
uint, 0644);
......@@ -48,7 +50,7 @@ module_param_named(debug_mask, binder_alloc_debug_mask,
#define binder_alloc_debug(mask, x...) \
do { \
if (binder_alloc_debug_mask & mask) \
pr_info(x); \
pr_info_ratelimited(x); \
} while (0)
static struct binder_buffer *binder_buffer_next(struct binder_buffer *buffer)
......@@ -152,8 +154,10 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked(
* free the buffer twice
*/
if (buffer->free_in_progress) {
pr_err("%d:%d FREE_BUFFER u%016llx user freed buffer twice\n",
alloc->pid, current->pid, (u64)user_ptr);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
"%d:%d FREE_BUFFER u%016llx user freed buffer twice\n",
alloc->pid, current->pid,
(u64)user_ptr);
return NULL;
}
buffer->free_in_progress = 1;
......@@ -224,8 +228,9 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
}
if (!vma && need_mm) {
pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n",
alloc->pid);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
"%d: binder_alloc_buf failed to map pages in userspace, no vma\n",
alloc->pid);
goto err_no_vma;
}
......@@ -344,8 +349,9 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
int ret;
if (alloc->vma == NULL) {
pr_err("%d: binder_alloc_buf, no vma\n",
alloc->pid);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
"%d: binder_alloc_buf, no vma\n",
alloc->pid);
return ERR_PTR(-ESRCH);
}
......@@ -417,11 +423,14 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
if (buffer_size > largest_free_size)
largest_free_size = buffer_size;
}
pr_err("%d: binder_alloc_buf size %zd failed, no address space\n",
alloc->pid, size);
pr_err("allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n",
total_alloc_size, allocated_buffers, largest_alloc_size,
total_free_size, free_buffers, largest_free_size);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
"%d: binder_alloc_buf size %zd failed, no address space\n",
alloc->pid, size);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
"allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n",
total_alloc_size, allocated_buffers,
largest_alloc_size, total_free_size,
free_buffers, largest_free_size);
return ERR_PTR(-ENOSPC);
}
if (n == NULL) {
......@@ -731,8 +740,10 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
err_get_vm_area_failed:
err_already_mapped:
mutex_unlock(&binder_alloc_mmap_lock);
pr_err("%s: %d %lx-%lx %s failed %d\n", __func__,
alloc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
"%s: %d %lx-%lx %s failed %d\n", __func__,
alloc->pid, vma->vm_start, vma->vm_end,
failure_string, ret);
return ret;
}
......
......@@ -248,14 +248,17 @@ DECLARE_EVENT_CLASS(binder_buffer_class,
__field(int, debug_id)
__field(size_t, data_size)
__field(size_t, offsets_size)
__field(size_t, extra_buffers_size)
),
TP_fast_assign(
__entry->debug_id = buf->debug_id;
__entry->data_size = buf->data_size;
__entry->offsets_size = buf->offsets_size;
__entry->extra_buffers_size = buf->extra_buffers_size;
),
TP_printk("transaction=%d data_size=%zd offsets_size=%zd",
__entry->debug_id, __entry->data_size, __entry->offsets_size)
TP_printk("transaction=%d data_size=%zd offsets_size=%zd extra_buffers_size=%zd",
__entry->debug_id, __entry->data_size, __entry->offsets_size,
__entry->extra_buffers_size)
);
DEFINE_EVENT(binder_buffer_class, binder_transaction_alloc_buf,
......
......@@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <linux/libata.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#define DRV_NAME "pata_imx"
......
......@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/libata.h>
......
......@@ -9,6 +9,7 @@
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
......
......@@ -579,7 +579,6 @@ hpet_ioctl_common(struct hpet_dev *devp, unsigned int cmd, unsigned long arg,
struct hpet_info *info)
{
struct hpet_timer __iomem *timer;
struct hpet __iomem *hpet;
struct hpets *hpetp;
int err;
unsigned long v;
......@@ -591,7 +590,6 @@ hpet_ioctl_common(struct hpet_dev *devp, unsigned int cmd, unsigned long arg,
case HPET_DPI:
case HPET_IRQFREQ:
timer = devp->hd_timer;
hpet = devp->hd_hpet;
hpetp = devp->hd_hpets;
break;
case HPET_IE_ON:
......
......@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
......
......@@ -19,6 +19,7 @@
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
......
......@@ -13,6 +13,7 @@
*/
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/clk.h>
......
......@@ -10,6 +10,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/random.h>
......
......@@ -766,6 +766,7 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
switch (orig) {
case SEEK_CUR:
offset += file->f_pos;
/* fall through */
case SEEK_SET:
/* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */
if ((unsigned long long)offset >= -MAX_ERRNO) {
......
......@@ -1748,8 +1748,6 @@ static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
static int cm4000_config(struct pcmcia_device * link, int devno)
{
struct cm4000_dev *dev;
link->config_flags |= CONF_AUTO_SET_IO;
/* read the config-tuples */
......@@ -1759,8 +1757,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
if (pcmcia_enable_device(link))
goto cs_release;
dev = link->priv;
return 0;
cs_release:
......
......@@ -1309,51 +1309,35 @@ static const struct attribute_group port_attribute_group = {
.attrs = port_sysfs_entries,
};
static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
size_t count, loff_t *offp)
static int debugfs_show(struct seq_file *s, void *data)
{
struct port *port;
char *buf;
ssize_t ret, out_offset, out_count;
struct port *port = s->private;
seq_printf(s, "name: %s\n", port->name ? port->name : "");
seq_printf(s, "guest_connected: %d\n", port->guest_connected);
seq_printf(s, "host_connected: %d\n", port->host_connected);
seq_printf(s, "outvq_full: %d\n", port->outvq_full);
seq_printf(s, "bytes_sent: %lu\n", port->stats.bytes_sent);
seq_printf(s, "bytes_received: %lu\n", port->stats.bytes_received);
seq_printf(s, "bytes_discarded: %lu\n", port->stats.bytes_discarded);
seq_printf(s, "is_console: %s\n",
is_console_port(port) ? "yes" : "no");
seq_printf(s, "console_vtermno: %u\n", port->cons.vtermno);
out_count = 1024;
buf = kmalloc(out_count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
return 0;
}
port = filp->private_data;
out_offset = 0;
out_offset += snprintf(buf + out_offset, out_count,
"name: %s\n", port->name ? port->name : "");
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"guest_connected: %d\n", port->guest_connected);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"host_connected: %d\n", port->host_connected);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"outvq_full: %d\n", port->outvq_full);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"bytes_sent: %lu\n", port->stats.bytes_sent);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"bytes_received: %lu\n",
port->stats.bytes_received);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"bytes_discarded: %lu\n",
port->stats.bytes_discarded);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"is_console: %s\n",
is_console_port(port) ? "yes" : "no");
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"console_vtermno: %u\n", port->cons.vtermno);
ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset);
kfree(buf);
return ret;
static int debugfs_open(struct inode *inode, struct file *file)
{
return single_open(file, debugfs_show, inode->i_private);
}
static const struct file_operations port_debugfs_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = debugfs_read,
.open = debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void set_console_size(struct port *port, u16 rows, u16 cols)
......
......@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include "mtk-platform.h"
......
......@@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/types.h>
......
......@@ -8,6 +8,7 @@
#include <linux/clk.h>
#include <linux/crc32poly.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
......
......@@ -20,6 +20,7 @@
#include <linux/irqreturn.h>
#include <linux/klist.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/semaphore.h>
......
......@@ -21,6 +21,7 @@
#include <linux/klist.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/crypto.h>
......
......@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/reset.h>
......
......@@ -23,6 +23,7 @@
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
......
......@@ -35,6 +35,7 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/platform_data/dma-s3c24xx.h>
......
......@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
......
......@@ -20,7 +20,7 @@
#include <linux/acpi.h>
#include <linux/extcon-provider.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
......
......@@ -14,6 +14,7 @@
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
struct max3355_data {
......
......@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
......
/**
* drivers/extcon/extcon-usbc-cros-ec - ChromeOS Embedded Controller extcon
*
* Copyright (C) 2017 Google, Inc
* Author: Benson Leung <bleung@chromium.org>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
// SPDX-License-Identifier: GPL-2.0
// ChromeOS Embedded Controller extcon
//
// Copyright (C) 2017 Google, Inc.
// Author: Benson Leung <bleung@chromium.org>
#include <linux/extcon-provider.h>
#include <linux/kernel.h>
......@@ -548,4 +538,4 @@ module_platform_driver(extcon_cros_ec_driver);
MODULE_DESCRIPTION("ChromeOS Embedded Controller extcon driver");
MODULE_AUTHOR("Benson Leung <bleung@chromium.org>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
......@@ -433,8 +433,8 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
return index;
spin_lock_irqsave(&edev->lock, flags);
state = !!(edev->state & BIT(index));
spin_unlock_irqrestore(&edev->lock, flags);
/*
* Call functions in a raw notifier chain for the specific one
......@@ -448,6 +448,7 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
*/
raw_notifier_call_chain(&edev->nh_all, state, edev);
spin_lock_irqsave(&edev->lock, flags);
/* This could be in interrupt handler */
prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
if (!prop_buf) {
......
......@@ -246,6 +246,7 @@ static int vpd_section_destroy(struct vpd_section *sec)
sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr);
kfree(sec->raw_name);
memunmap(sec->baseaddr);
sec->enabled = false;
}
return 0;
......@@ -279,8 +280,10 @@ static int vpd_sections_init(phys_addr_t physaddr)
ret = vpd_section_init("rw", &rw_vpd,
physaddr + sizeof(struct vpd_cbmem) +
header.ro_size, header.rw_size);
if (ret)
if (ret) {
vpd_section_destroy(&ro_vpd);
return ret;
}
}
return 0;
......
......@@ -130,4 +130,72 @@ config OF_FPGA_REGION
Support for loading FPGA images by applying a Device Tree
overlay.
config FPGA_DFL
tristate "FPGA Device Feature List (DFL) support"
select FPGA_BRIDGE
select FPGA_REGION
help
Device Feature List (DFL) defines a feature list structure that
creates a linked list of feature headers within the MMIO space
to provide an extensible way of adding features for FPGA.
Driver can walk through the feature headers to enumerate feature
devices (e.g. FPGA Management Engine, Port and Accelerator
Function Unit) and their private features for target FPGA devices.
Select this option to enable common support for Field-Programmable
Gate Array (FPGA) solutions which implement Device Feature List.
It provides enumeration APIs and feature device infrastructure.
config FPGA_DFL_FME
tristate "FPGA DFL FME Driver"
depends on FPGA_DFL
help
The FPGA Management Engine (FME) is a feature device implemented
under Device Feature List (DFL) framework. Select this option to
enable the platform device driver for FME which implements all
FPGA platform level management features. There shall be one FME
per DFL based FPGA device.
config FPGA_DFL_FME_MGR
tristate "FPGA DFL FME Manager Driver"
depends on FPGA_DFL_FME && HAS_IOMEM
help
Say Y to enable FPGA Manager driver for FPGA Management Engine.
config FPGA_DFL_FME_BRIDGE
tristate "FPGA DFL FME Bridge Driver"
depends on FPGA_DFL_FME && HAS_IOMEM
help
Say Y to enable FPGA Bridge driver for FPGA Management Engine.
config FPGA_DFL_FME_REGION
tristate "FPGA DFL FME Region Driver"
depends on FPGA_DFL_FME && HAS_IOMEM
help
Say Y to enable FPGA Region driver for FPGA Management Engine.
config FPGA_DFL_AFU
tristate "FPGA DFL AFU Driver"
depends on FPGA_DFL
help
This is the driver for FPGA Accelerated Function Unit (AFU) which
implements AFU and Port management features. A User AFU connects
to the FPGA infrastructure via a Port. There may be more than one
Port/AFU per DFL based FPGA device.
config FPGA_DFL_PCI
tristate "FPGA DFL PCIe Device Driver"
depends on PCI && FPGA_DFL
help
Select this option to enable PCIe driver for PCIe-based
Field-Programmable Gate Array (FPGA) solutions which implement
the Device Feature List (DFL). This driver provides interfaces
for userspace applications to configure, enumerate, open and access
FPGA accelerators on the FPGA DFL devices, enables system level
management functions such as FPGA partial reconfiguration, power
management and virtualization with DFL framework and DFL feature
device drivers.
To compile this as a module, choose M here.
endif # FPGA
......@@ -28,3 +28,17 @@ obj-$(CONFIG_XILINX_PR_DECOUPLER) += xilinx-pr-decoupler.o
# High Level Interfaces
obj-$(CONFIG_FPGA_REGION) += fpga-region.o
obj-$(CONFIG_OF_FPGA_REGION) += of-fpga-region.o
# FPGA Device Feature List Support
obj-$(CONFIG_FPGA_DFL) += dfl.o
obj-$(CONFIG_FPGA_DFL_FME) += dfl-fme.o
obj-$(CONFIG_FPGA_DFL_FME_MGR) += dfl-fme-mgr.o
obj-$(CONFIG_FPGA_DFL_FME_BRIDGE) += dfl-fme-br.o
obj-$(CONFIG_FPGA_DFL_FME_REGION) += dfl-fme-region.o
obj-$(CONFIG_FPGA_DFL_AFU) += dfl-afu.o
dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o
dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o
# Drivers for FPGAs which implement DFL
obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for FPGA Accelerated Function Unit (AFU) MMIO Region Management
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Wu Hao <hao.wu@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
*/
#include "dfl-afu.h"
/**
* afu_mmio_region_init - init function for afu mmio region support
* @pdata: afu platform device's pdata.
*/
void afu_mmio_region_init(struct dfl_feature_platform_data *pdata)
{
struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
INIT_LIST_HEAD(&afu->regions);
}
#define for_each_region(region, afu) \
list_for_each_entry((region), &(afu)->regions, node)
static struct dfl_afu_mmio_region *get_region_by_index(struct dfl_afu *afu,
u32 region_index)
{
struct dfl_afu_mmio_region *region;
for_each_region(region, afu)
if (region->index == region_index)
return region;
return NULL;
}
/**
* afu_mmio_region_add - add a mmio region to given feature dev.
*
* @region_index: region index.
* @region_size: region size.
* @phys: region's physical address of this region.
* @flags: region flags (access permission).
*
* Return: 0 on success, negative error code otherwise.
*/
int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
u32 region_index, u64 region_size, u64 phys, u32 flags)
{
struct dfl_afu_mmio_region *region;
struct dfl_afu *afu;
int ret = 0;
region = devm_kzalloc(&pdata->dev->dev, sizeof(*region), GFP_KERNEL);
if (!region)
return -ENOMEM;
region->index = region_index;
region->size = region_size;
region->phys = phys;
region->flags = flags;
mutex_lock(&pdata->lock);
afu = dfl_fpga_pdata_get_private(pdata);
/* check if @index already exists */
if (get_region_by_index(afu, region_index)) {
mutex_unlock(&pdata->lock);
ret = -EEXIST;
goto exit;
}
region_size = PAGE_ALIGN(region_size);
region->offset = afu->region_cur_offset;
list_add(&region->node, &afu->regions);
afu->region_cur_offset += region_size;
afu->num_regions++;
mutex_unlock(&pdata->lock);
return 0;
exit:
devm_kfree(&pdata->dev->dev, region);
return ret;
}
/**
* afu_mmio_region_destroy - destroy all mmio regions under given feature dev.
* @pdata: afu platform device's pdata.
*/
void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata)
{
struct dfl_afu *afu = dfl_fpga_pdata_get_private(pdata);
struct dfl_afu_mmio_region *tmp, *region;
list_for_each_entry_safe(region, tmp, &afu->regions, node)
devm_kfree(&pdata->dev->dev, region);
}
/**
* afu_mmio_region_get_by_index - find an afu region by index.
* @pdata: afu platform device's pdata.
* @region_index: region index.
* @pregion: ptr to region for result.
*
* Return: 0 on success, negative error code otherwise.
*/
int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
u32 region_index,
struct dfl_afu_mmio_region *pregion)
{
struct dfl_afu_mmio_region *region;
struct dfl_afu *afu;
int ret = 0;
mutex_lock(&pdata->lock);
afu = dfl_fpga_pdata_get_private(pdata);
region = get_region_by_index(afu, region_index);
if (!region) {
ret = -EINVAL;
goto exit;
}
*pregion = *region;
exit:
mutex_unlock(&pdata->lock);
return ret;
}
/**
* afu_mmio_region_get_by_offset - find an afu mmio region by offset and size
*
* @pdata: afu platform device's pdata.
* @offset: region offset from start of the device fd.
* @size: region size.
* @pregion: ptr to region for result.
*
* Find the region which fully contains the region described by input
* parameters (offset and size) from the feature dev's region linked list.
*
* Return: 0 on success, negative error code otherwise.
*/
int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
u64 offset, u64 size,
struct dfl_afu_mmio_region *pregion)
{
struct dfl_afu_mmio_region *region;
struct dfl_afu *afu;
int ret = 0;
mutex_lock(&pdata->lock);
afu = dfl_fpga_pdata_get_private(pdata);
for_each_region(region, afu)
if (region->offset <= offset &&
region->offset + region->size >= offset + size) {
*pregion = *region;
goto exit;
}
ret = -EINVAL;
exit:
mutex_unlock(&pdata->lock);
return ret;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Header file for FPGA Accelerated Function Unit (AFU) Driver
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Wu Hao <hao.wu@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#ifndef __DFL_AFU_H
#define __DFL_AFU_H
#include <linux/mm.h>
#include "dfl.h"
/**
* struct dfl_afu_mmio_region - afu mmio region data structure
*
* @index: region index.
* @flags: region flags (access permission).
* @size: region size.
* @offset: region offset from start of the device fd.
* @phys: region's physical address.
* @node: node to add to afu feature dev's region list.
*/
struct dfl_afu_mmio_region {
u32 index;
u32 flags;
u64 size;
u64 offset;
u64 phys;
struct list_head node;
};
/**
* struct fpga_afu_dma_region - afu DMA region data structure
*
* @user_addr: region userspace virtual address.
* @length: region length.
* @iova: region IO virtual address.
* @pages: ptr to pages of this region.
* @node: rb tree node.
* @in_use: flag to indicate if this region is in_use.
*/
struct dfl_afu_dma_region {
u64 user_addr;
u64 length;
u64 iova;
struct page **pages;
struct rb_node node;
bool in_use;
};
/**
* struct dfl_afu - afu device data structure
*
* @region_cur_offset: current region offset from start to the device fd.
* @num_regions: num of mmio regions.
* @regions: the mmio region linked list of this afu feature device.
* @dma_regions: root of dma regions rb tree.
* @num_umsgs: num of umsgs.
* @pdata: afu platform device's pdata.
*/
struct dfl_afu {
u64 region_cur_offset;
int num_regions;
u8 num_umsgs;
struct list_head regions;
struct rb_root dma_regions;
struct dfl_feature_platform_data *pdata;
};
void afu_mmio_region_init(struct dfl_feature_platform_data *pdata);
int afu_mmio_region_add(struct dfl_feature_platform_data *pdata,
u32 region_index, u64 region_size, u64 phys, u32 flags);
void afu_mmio_region_destroy(struct dfl_feature_platform_data *pdata);
int afu_mmio_region_get_by_index(struct dfl_feature_platform_data *pdata,
u32 region_index,
struct dfl_afu_mmio_region *pregion);
int afu_mmio_region_get_by_offset(struct dfl_feature_platform_data *pdata,
u64 offset, u64 size,
struct dfl_afu_mmio_region *pregion);
void afu_dma_region_init(struct dfl_feature_platform_data *pdata);
void afu_dma_region_destroy(struct dfl_feature_platform_data *pdata);
int afu_dma_map_region(struct dfl_feature_platform_data *pdata,
u64 user_addr, u64 length, u64 *iova);
int afu_dma_unmap_region(struct dfl_feature_platform_data *pdata, u64 iova);
struct dfl_afu_dma_region *
afu_dma_region_find(struct dfl_feature_platform_data *pdata,
u64 iova, u64 size);
#endif /* __DFL_AFU_H */
// SPDX-License-Identifier: GPL-2.0
/*
* FPGA Bridge Driver for FPGA Management Engine (FME)
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Wu Hao <hao.wu@intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#include <linux/module.h>
#include <linux/fpga/fpga-bridge.h>
#include "dfl.h"
#include "dfl-fme-pr.h"
struct fme_br_priv {
struct dfl_fme_br_pdata *pdata;
struct dfl_fpga_port_ops *port_ops;
struct platform_device *port_pdev;
};
static int fme_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
{
struct fme_br_priv *priv = bridge->priv;
struct platform_device *port_pdev;
struct dfl_fpga_port_ops *ops;
if (!priv->port_pdev) {
port_pdev = dfl_fpga_cdev_find_port(priv->pdata->cdev,
&priv->pdata->port_id,
dfl_fpga_check_port_id);
if (!port_pdev)
return -ENODEV;
priv->port_pdev = port_pdev;
}
if (priv->port_pdev && !priv->port_ops) {
ops = dfl_fpga_port_ops_get(priv->port_pdev);
if (!ops || !ops->enable_set)
return -ENOENT;
priv->port_ops = ops;
}
return priv->port_ops->enable_set(priv->port_pdev, enable);
}
static const struct fpga_bridge_ops fme_bridge_ops = {
.enable_set = fme_bridge_enable_set,
};
static int fme_br_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fme_br_priv *priv;
struct fpga_bridge *br;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->pdata = dev_get_platdata(dev);
br = fpga_bridge_create(dev, "DFL FPGA FME Bridge",
&fme_bridge_ops, priv);
if (!br)
return -ENOMEM;
platform_set_drvdata(pdev, br);
ret = fpga_bridge_register(br);
if (ret)
fpga_bridge_free(br);
return ret;
}
static int fme_br_remove(struct platform_device *pdev)
{
struct fpga_bridge *br = platform_get_drvdata(pdev);
struct fme_br_priv *priv = br->priv;
fpga_bridge_unregister(br);
if (priv->port_pdev)
put_device(&priv->port_pdev->dev);
if (priv->port_ops)
dfl_fpga_port_ops_put(priv->port_ops);
return 0;
}
static struct platform_driver fme_br_driver = {
.driver = {
.name = DFL_FPGA_FME_BRIDGE,
},
.probe = fme_br_probe,
.remove = fme_br_remove,
};
module_platform_driver(fme_br_driver);
MODULE_DESCRIPTION("FPGA Bridge for DFL FPGA Management Engine");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:dfl-fme-bridge");
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for FPGA Management Engine (FME)
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Kang Luwei <luwei.kang@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fpga-dfl.h>
#include "dfl.h"
#include "dfl-fme.h"
static ssize_t ports_num_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
}
static DEVICE_ATTR_RO(ports_num);
/*
* Bitstream (static FPGA region) identifier number. It contains the
* detailed version and other information of this static FPGA region.
*/
static ssize_t bitstream_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_BITSTREAM_ID);
return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
}
static DEVICE_ATTR_RO(bitstream_id);
/*
* Bitstream (static FPGA region) meta data. It contains the synthesis
* date, seed and other information of this static FPGA region.
*/
static ssize_t bitstream_metadata_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_BITSTREAM_MD);
return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
}
static DEVICE_ATTR_RO(bitstream_metadata);
static const struct attribute *fme_hdr_attrs[] = {
&dev_attr_ports_num.attr,
&dev_attr_bitstream_id.attr,
&dev_attr_bitstream_metadata.attr,
NULL,
};
static int fme_hdr_init(struct platform_device *pdev,
struct dfl_feature *feature)
{
void __iomem *base = feature->ioaddr;
int ret;
dev_dbg(&pdev->dev, "FME HDR Init.\n");
dev_dbg(&pdev->dev, "FME cap %llx.\n",
(unsigned long long)readq(base + FME_HDR_CAP));
ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs);
if (ret)
return ret;
return 0;
}
static void fme_hdr_uinit(struct platform_device *pdev,
struct dfl_feature *feature)
{
dev_dbg(&pdev->dev, "FME HDR UInit.\n");
sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs);
}
static const struct dfl_feature_ops fme_hdr_ops = {
.init = fme_hdr_init,
.uinit = fme_hdr_uinit,
};
static struct dfl_feature_driver fme_feature_drvs[] = {
{
.id = FME_FEATURE_ID_HEADER,
.ops = &fme_hdr_ops,
},
{
.id = FME_FEATURE_ID_PR_MGMT,
.ops = &pr_mgmt_ops,
},
{
.ops = NULL,
},
};
static long fme_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
unsigned long arg)
{
/* No extension support for now */
return 0;
}
static int fme_open(struct inode *inode, struct file *filp)
{
struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);
int ret;
if (WARN_ON(!pdata))
return -ENODEV;
ret = dfl_feature_dev_use_begin(pdata);
if (ret)
return ret;
dev_dbg(&fdev->dev, "Device File Open\n");
filp->private_data = pdata;
return 0;
}
static int fme_release(struct inode *inode, struct file *filp)
{
struct dfl_feature_platform_data *pdata = filp->private_data;
struct platform_device *pdev = pdata->dev;
dev_dbg(&pdev->dev, "Device File Release\n");
dfl_feature_dev_use_end(pdata);
return 0;
}
static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct dfl_feature_platform_data *pdata = filp->private_data;
struct platform_device *pdev = pdata->dev;
struct dfl_feature *f;
long ret;
dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);
switch (cmd) {
case DFL_FPGA_GET_API_VERSION:
return DFL_FPGA_API_VERSION;
case DFL_FPGA_CHECK_EXTENSION:
return fme_ioctl_check_extension(pdata, arg);
default:
/*
* Let sub-feature's ioctl function to handle the cmd.
* Sub-feature's ioctl returns -ENODEV when cmd is not
* handled in this sub feature, and returns 0 or other
* error code if cmd is handled.
*/
dfl_fpga_dev_for_each_feature(pdata, f) {
if (f->ops && f->ops->ioctl) {
ret = f->ops->ioctl(pdev, f, cmd, arg);
if (ret != -ENODEV)
return ret;
}
}
}
return -EINVAL;
}
static int fme_dev_init(struct platform_device *pdev)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fme *fme;
fme = devm_kzalloc(&pdev->dev, sizeof(*fme), GFP_KERNEL);
if (!fme)
return -ENOMEM;
fme->pdata = pdata;
mutex_lock(&pdata->lock);
dfl_fpga_pdata_set_private(pdata, fme);
mutex_unlock(&pdata->lock);
return 0;
}
static void fme_dev_destroy(struct platform_device *pdev)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fme *fme;
mutex_lock(&pdata->lock);
fme = dfl_fpga_pdata_get_private(pdata);
dfl_fpga_pdata_set_private(pdata, NULL);
mutex_unlock(&pdata->lock);
}
static const struct file_operations fme_fops = {
.owner = THIS_MODULE,
.open = fme_open,
.release = fme_release,
.unlocked_ioctl = fme_ioctl,
};
static int fme_probe(struct platform_device *pdev)
{
int ret;
ret = fme_dev_init(pdev);
if (ret)
goto exit;
ret = dfl_fpga_dev_feature_init(pdev, fme_feature_drvs);
if (ret)
goto dev_destroy;
ret = dfl_fpga_dev_ops_register(pdev, &fme_fops, THIS_MODULE);
if (ret)
goto feature_uinit;
return 0;
feature_uinit:
dfl_fpga_dev_feature_uinit(pdev);
dev_destroy:
fme_dev_destroy(pdev);
exit:
return ret;
}
static int fme_remove(struct platform_device *pdev)
{
dfl_fpga_dev_ops_unregister(pdev);
dfl_fpga_dev_feature_uinit(pdev);
fme_dev_destroy(pdev);
return 0;
}
static struct platform_driver fme_driver = {
.driver = {
.name = DFL_FPGA_FEATURE_DEV_FME,
},
.probe = fme_probe,
.remove = fme_remove,
};
module_platform_driver(fme_driver);
MODULE_DESCRIPTION("FPGA Management Engine driver");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:dfl-fme");
// SPDX-License-Identifier: GPL-2.0
/*
* FPGA Manager Driver for FPGA Management Engine (FME)
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Kang Luwei <luwei.kang@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Wu Hao <hao.wu@intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Christopher Rauer <christopher.rauer@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/iopoll.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/fpga/fpga-mgr.h>
#include "dfl-fme-pr.h"
/* FME Partial Reconfiguration Sub Feature Register Set */
#define FME_PR_DFH 0x0
#define FME_PR_CTRL 0x8
#define FME_PR_STS 0x10
#define FME_PR_DATA 0x18
#define FME_PR_ERR 0x20
#define FME_PR_INTFC_ID_H 0xA8
#define FME_PR_INTFC_ID_L 0xB0
/* FME PR Control Register Bitfield */
#define FME_PR_CTRL_PR_RST BIT_ULL(0) /* Reset PR engine */
#define FME_PR_CTRL_PR_RSTACK BIT_ULL(4) /* Ack for PR engine reset */
#define FME_PR_CTRL_PR_RGN_ID GENMASK_ULL(9, 7) /* PR Region ID */
#define FME_PR_CTRL_PR_START BIT_ULL(12) /* Start to request PR service */
#define FME_PR_CTRL_PR_COMPLETE BIT_ULL(13) /* PR data push completion */
/* FME PR Status Register Bitfield */
/* Number of available entries in HW queue inside the PR engine. */
#define FME_PR_STS_PR_CREDIT GENMASK_ULL(8, 0)
#define FME_PR_STS_PR_STS BIT_ULL(16) /* PR operation status */
#define FME_PR_STS_PR_STS_IDLE 0
#define FME_PR_STS_PR_CTRLR_STS GENMASK_ULL(22, 20) /* Controller status */
#define FME_PR_STS_PR_HOST_STS GENMASK_ULL(27, 24) /* PR host status */
/* FME PR Data Register Bitfield */
/* PR data from the raw-binary file. */
#define FME_PR_DATA_PR_DATA_RAW GENMASK_ULL(32, 0)
/* FME PR Error Register */
/* PR Operation errors detected. */
#define FME_PR_ERR_OPERATION_ERR BIT_ULL(0)
/* CRC error detected. */
#define FME_PR_ERR_CRC_ERR BIT_ULL(1)
/* Incompatible PR bitstream detected. */
#define FME_PR_ERR_INCOMPATIBLE_BS BIT_ULL(2)
/* PR data push protocol violated. */
#define FME_PR_ERR_PROTOCOL_ERR BIT_ULL(3)
/* PR data fifo overflow error detected */
#define FME_PR_ERR_FIFO_OVERFLOW BIT_ULL(4)
#define PR_WAIT_TIMEOUT 8000000
#define PR_HOST_STATUS_IDLE 0
struct fme_mgr_priv {
void __iomem *ioaddr;
u64 pr_error;
};
static u64 pr_error_to_mgr_status(u64 err)
{
u64 status = 0;
if (err & FME_PR_ERR_OPERATION_ERR)
status |= FPGA_MGR_STATUS_OPERATION_ERR;
if (err & FME_PR_ERR_CRC_ERR)
status |= FPGA_MGR_STATUS_CRC_ERR;
if (err & FME_PR_ERR_INCOMPATIBLE_BS)
status |= FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR;
if (err & FME_PR_ERR_PROTOCOL_ERR)
status |= FPGA_MGR_STATUS_IP_PROTOCOL_ERR;
if (err & FME_PR_ERR_FIFO_OVERFLOW)
status |= FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR;
return status;
}
static u64 fme_mgr_pr_error_handle(void __iomem *fme_pr)
{
u64 pr_status, pr_error;
pr_status = readq(fme_pr + FME_PR_STS);
if (!(pr_status & FME_PR_STS_PR_STS))
return 0;
pr_error = readq(fme_pr + FME_PR_ERR);
writeq(pr_error, fme_pr + FME_PR_ERR);
return pr_error;
}
static int fme_mgr_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
{
struct device *dev = &mgr->dev;
struct fme_mgr_priv *priv = mgr->priv;
void __iomem *fme_pr = priv->ioaddr;
u64 pr_ctrl, pr_status;
if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
dev_err(dev, "only supports partial reconfiguration.\n");
return -EINVAL;
}
dev_dbg(dev, "resetting PR before initiated PR\n");
pr_ctrl = readq(fme_pr + FME_PR_CTRL);
pr_ctrl |= FME_PR_CTRL_PR_RST;
writeq(pr_ctrl, fme_pr + FME_PR_CTRL);
if (readq_poll_timeout(fme_pr + FME_PR_CTRL, pr_ctrl,
pr_ctrl & FME_PR_CTRL_PR_RSTACK, 1,
PR_WAIT_TIMEOUT)) {
dev_err(dev, "PR Reset ACK timeout\n");
return -ETIMEDOUT;
}
pr_ctrl = readq(fme_pr + FME_PR_CTRL);
pr_ctrl &= ~FME_PR_CTRL_PR_RST;
writeq(pr_ctrl, fme_pr + FME_PR_CTRL);
dev_dbg(dev,
"waiting for PR resource in HW to be initialized and ready\n");
if (readq_poll_timeout(fme_pr + FME_PR_STS, pr_status,
(pr_status & FME_PR_STS_PR_STS) ==
FME_PR_STS_PR_STS_IDLE, 1, PR_WAIT_TIMEOUT)) {
dev_err(dev, "PR Status timeout\n");
priv->pr_error = fme_mgr_pr_error_handle(fme_pr);
return -ETIMEDOUT;
}
dev_dbg(dev, "check and clear previous PR error\n");
priv->pr_error = fme_mgr_pr_error_handle(fme_pr);
if (priv->pr_error)
dev_dbg(dev, "previous PR error detected %llx\n",
(unsigned long long)priv->pr_error);
dev_dbg(dev, "set PR port ID\n");
pr_ctrl = readq(fme_pr + FME_PR_CTRL);
pr_ctrl &= ~FME_PR_CTRL_PR_RGN_ID;
pr_ctrl |= FIELD_PREP(FME_PR_CTRL_PR_RGN_ID, info->region_id);
writeq(pr_ctrl, fme_pr + FME_PR_CTRL);
return 0;
}
static int fme_mgr_write(struct fpga_manager *mgr,
const char *buf, size_t count)
{
struct device *dev = &mgr->dev;
struct fme_mgr_priv *priv = mgr->priv;
void __iomem *fme_pr = priv->ioaddr;
u64 pr_ctrl, pr_status, pr_data;
int delay = 0, pr_credit, i = 0;
dev_dbg(dev, "start request\n");
pr_ctrl = readq(fme_pr + FME_PR_CTRL);
pr_ctrl |= FME_PR_CTRL_PR_START;
writeq(pr_ctrl, fme_pr + FME_PR_CTRL);
dev_dbg(dev, "pushing data from bitstream to HW\n");
/*
* driver can push data to PR hardware using PR_DATA register once HW
* has enough pr_credit (> 1), pr_credit reduces one for every 32bit
* pr data write to PR_DATA register. If pr_credit <= 1, driver needs
* to wait for enough pr_credit from hardware by polling.
*/
pr_status = readq(fme_pr + FME_PR_STS);
pr_credit = FIELD_GET(FME_PR_STS_PR_CREDIT, pr_status);
while (count > 0) {
while (pr_credit <= 1) {
if (delay++ > PR_WAIT_TIMEOUT) {
dev_err(dev, "PR_CREDIT timeout\n");
return -ETIMEDOUT;
}
udelay(1);
pr_status = readq(fme_pr + FME_PR_STS);
pr_credit = FIELD_GET(FME_PR_STS_PR_CREDIT, pr_status);
}
if (count < 4) {
dev_err(dev, "Invaild PR bitstream size\n");
return -EINVAL;
}
pr_data = 0;
pr_data |= FIELD_PREP(FME_PR_DATA_PR_DATA_RAW,
*(((u32 *)buf) + i));
writeq(pr_data, fme_pr + FME_PR_DATA);
count -= 4;
pr_credit--;
i++;
}
return 0;
}
static int fme_mgr_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info)
{
struct device *dev = &mgr->dev;
struct fme_mgr_priv *priv = mgr->priv;
void __iomem *fme_pr = priv->ioaddr;
u64 pr_ctrl;
pr_ctrl = readq(fme_pr + FME_PR_CTRL);
pr_ctrl |= FME_PR_CTRL_PR_COMPLETE;
writeq(pr_ctrl, fme_pr + FME_PR_CTRL);
dev_dbg(dev, "green bitstream push complete\n");
dev_dbg(dev, "waiting for HW to release PR resource\n");
if (readq_poll_timeout(fme_pr + FME_PR_CTRL, pr_ctrl,
!(pr_ctrl & FME_PR_CTRL_PR_START), 1,
PR_WAIT_TIMEOUT)) {
dev_err(dev, "PR Completion ACK timeout.\n");
return -ETIMEDOUT;
}
dev_dbg(dev, "PR operation complete, checking status\n");
priv->pr_error = fme_mgr_pr_error_handle(fme_pr);
if (priv->pr_error) {
dev_dbg(dev, "PR error detected %llx\n",
(unsigned long long)priv->pr_error);
return -EIO;
}
dev_dbg(dev, "PR done successfully\n");
return 0;
}
static enum fpga_mgr_states fme_mgr_state(struct fpga_manager *mgr)
{
return FPGA_MGR_STATE_UNKNOWN;
}
static u64 fme_mgr_status(struct fpga_manager *mgr)
{
struct fme_mgr_priv *priv = mgr->priv;
return pr_error_to_mgr_status(priv->pr_error);
}
static const struct fpga_manager_ops fme_mgr_ops = {
.write_init = fme_mgr_write_init,
.write = fme_mgr_write,
.write_complete = fme_mgr_write_complete,
.state = fme_mgr_state,
.status = fme_mgr_status,
};
static void fme_mgr_get_compat_id(void __iomem *fme_pr,
struct fpga_compat_id *id)
{
id->id_l = readq(fme_pr + FME_PR_INTFC_ID_L);
id->id_h = readq(fme_pr + FME_PR_INTFC_ID_H);
}
static int fme_mgr_probe(struct platform_device *pdev)
{
struct dfl_fme_mgr_pdata *pdata = dev_get_platdata(&pdev->dev);
struct fpga_compat_id *compat_id;
struct device *dev = &pdev->dev;
struct fme_mgr_priv *priv;
struct fpga_manager *mgr;
struct resource *res;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
if (pdata->ioaddr)
priv->ioaddr = pdata->ioaddr;
if (!priv->ioaddr) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->ioaddr = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->ioaddr))
return PTR_ERR(priv->ioaddr);
}
compat_id = devm_kzalloc(dev, sizeof(*compat_id), GFP_KERNEL);
if (!compat_id)
return -ENOMEM;
fme_mgr_get_compat_id(priv->ioaddr, compat_id);
mgr = fpga_mgr_create(dev, "DFL FME FPGA Manager",
&fme_mgr_ops, priv);
if (!mgr)
return -ENOMEM;
mgr->compat_id = compat_id;
platform_set_drvdata(pdev, mgr);
ret = fpga_mgr_register(mgr);
if (ret)
fpga_mgr_free(mgr);
return ret;
}
static int fme_mgr_remove(struct platform_device *pdev)
{
struct fpga_manager *mgr = platform_get_drvdata(pdev);
fpga_mgr_unregister(mgr);
return 0;
}
static struct platform_driver fme_mgr_driver = {
.driver = {
.name = DFL_FPGA_FME_MGR,
},
.probe = fme_mgr_probe,
.remove = fme_mgr_remove,
};
module_platform_driver(fme_mgr_driver);
MODULE_DESCRIPTION("FPGA Manager for DFL FPGA Management Engine");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:dfl-fme-mgr");
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Header file for FPGA Management Engine (FME) Partial Reconfiguration Driver
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Kang Luwei <luwei.kang@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Wu Hao <hao.wu@intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#ifndef __DFL_FME_PR_H
#define __DFL_FME_PR_H
#include <linux/platform_device.h>
/**
* struct dfl_fme_region - FME fpga region data structure
*
* @region: platform device of the FPGA region.
* @node: used to link fme_region to a list.
* @port_id: indicate which port this region connected to.
*/
struct dfl_fme_region {
struct platform_device *region;
struct list_head node;
int port_id;
};
/**
* struct dfl_fme_region_pdata - platform data for FME region platform device.
*
* @mgr: platform device of the FPGA manager.
* @br: platform device of the FPGA bridge.
* @region_id: region id (same as port_id).
*/
struct dfl_fme_region_pdata {
struct platform_device *mgr;
struct platform_device *br;
int region_id;
};
/**
* struct dfl_fme_bridge - FME fpga bridge data structure
*
* @br: platform device of the FPGA bridge.
* @node: used to link fme_bridge to a list.
*/
struct dfl_fme_bridge {
struct platform_device *br;
struct list_head node;
};
/**
* struct dfl_fme_bridge_pdata - platform data for FME bridge platform device.
*
* @cdev: container device.
* @port_id: port id.
*/
struct dfl_fme_br_pdata {
struct dfl_fpga_cdev *cdev;
int port_id;
};
/**
* struct dfl_fme_mgr_pdata - platform data for FME manager platform device.
*
* @ioaddr: mapped io address for FME manager platform device.
*/
struct dfl_fme_mgr_pdata {
void __iomem *ioaddr;
};
#define DFL_FPGA_FME_MGR "dfl-fme-mgr"
#define DFL_FPGA_FME_BRIDGE "dfl-fme-bridge"
#define DFL_FPGA_FME_REGION "dfl-fme-region"
#endif /* __DFL_FME_PR_H */
// SPDX-License-Identifier: GPL-2.0
/*
* FPGA Region Driver for FPGA Management Engine (FME)
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Wu Hao <hao.wu@intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#include <linux/module.h>
#include <linux/fpga/fpga-region.h>
#include "dfl-fme-pr.h"
static int fme_region_get_bridges(struct fpga_region *region)
{
struct dfl_fme_region_pdata *pdata = region->priv;
struct device *dev = &pdata->br->dev;
return fpga_bridge_get_to_list(dev, region->info, &region->bridge_list);
}
static int fme_region_probe(struct platform_device *pdev)
{
struct dfl_fme_region_pdata *pdata = dev_get_platdata(&pdev->dev);
struct device *dev = &pdev->dev;
struct fpga_region *region;
struct fpga_manager *mgr;
int ret;
mgr = fpga_mgr_get(&pdata->mgr->dev);
if (IS_ERR(mgr))
return -EPROBE_DEFER;
region = fpga_region_create(dev, mgr, fme_region_get_bridges);
if (!region) {
ret = -ENOMEM;
goto eprobe_mgr_put;
}
region->priv = pdata;
region->compat_id = mgr->compat_id;
platform_set_drvdata(pdev, region);
ret = fpga_region_register(region);
if (ret)
goto region_free;
dev_dbg(dev, "DFL FME FPGA Region probed\n");
return 0;
region_free:
fpga_region_free(region);
eprobe_mgr_put:
fpga_mgr_put(mgr);
return ret;
}
static int fme_region_remove(struct platform_device *pdev)
{
struct fpga_region *region = dev_get_drvdata(&pdev->dev);
fpga_region_unregister(region);
fpga_mgr_put(region->mgr);
return 0;
}
static struct platform_driver fme_region_driver = {
.driver = {
.name = DFL_FPGA_FME_REGION,
},
.probe = fme_region_probe,
.remove = fme_region_remove,
};
module_platform_driver(fme_region_driver);
MODULE_DESCRIPTION("FPGA Region for DFL FPGA Management Engine");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:dfl-fme-region");
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Header file for FPGA Management Engine (FME) Driver
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Kang Luwei <luwei.kang@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Wu Hao <hao.wu@intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#ifndef __DFL_FME_H
#define __DFL_FME_H
/**
* struct dfl_fme - dfl fme private data
*
* @mgr: FME's FPGA manager platform device.
* @region_list: linked list of FME's FPGA regions.
* @bridge_list: linked list of FME's FPGA bridges.
* @pdata: fme platform device's pdata.
*/
struct dfl_fme {
struct platform_device *mgr;
struct list_head region_list;
struct list_head bridge_list;
struct dfl_feature_platform_data *pdata;
};
extern const struct dfl_feature_ops pr_mgmt_ops;
#endif /* __DFL_FME_H */
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for FPGA Device Feature List (DFL) PCIe device
*
* Copyright (C) 2017-2018 Intel Corporation, Inc.
*
* Authors:
* Zhang Yi <Yi.Z.Zhang@intel.com>
* Xiao Guangrong <guangrong.xiao@linux.intel.com>
* Joseph Grecco <joe.grecco@intel.com>
* Enno Luebbers <enno.luebbers@intel.com>
* Tim Whisonant <tim.whisonant@intel.com>
* Ananda Ravuri <ananda.ravuri@intel.com>
* Henry Mitchel <henry.mitchel@intel.com>
*/
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/errno.h>
#include <linux/aer.h>
#include "dfl.h"
#define DRV_VERSION "0.8"
#define DRV_NAME "dfl-pci"
struct cci_drvdata {
struct dfl_fpga_cdev *cdev; /* container device */
};
static void __iomem *cci_pci_ioremap_bar(struct pci_dev *pcidev, int bar)
{
if (pcim_iomap_regions(pcidev, BIT(bar), DRV_NAME))
return NULL;
return pcim_iomap_table(pcidev)[bar];
}
/* PCI Device ID */
#define PCIE_DEVICE_ID_PF_INT_5_X 0xBCBD
#define PCIE_DEVICE_ID_PF_INT_6_X 0xBCC0
#define PCIE_DEVICE_ID_PF_DSC_1_X 0x09C4
/* VF Device */
#define PCIE_DEVICE_ID_VF_INT_5_X 0xBCBF
#define PCIE_DEVICE_ID_VF_INT_6_X 0xBCC1
#define PCIE_DEVICE_ID_VF_DSC_1_X 0x09C5
static struct pci_device_id cci_pcie_id_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_5_X),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_5_X),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_INT_6_X),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_INT_6_X),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_PF_DSC_1_X),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_VF_DSC_1_X),},
{0,}
};
MODULE_DEVICE_TABLE(pci, cci_pcie_id_tbl);
static int cci_init_drvdata(struct pci_dev *pcidev)
{
struct cci_drvdata *drvdata;
drvdata = devm_kzalloc(&pcidev->dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
pci_set_drvdata(pcidev, drvdata);
return 0;
}
static void cci_remove_feature_devs(struct pci_dev *pcidev)
{
struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
/* remove all children feature devices */
dfl_fpga_feature_devs_remove(drvdata->cdev);
}
/* enumerate feature devices under pci device */
static int cci_enumerate_feature_devs(struct pci_dev *pcidev)
{
struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
struct dfl_fpga_enum_info *info;
struct dfl_fpga_cdev *cdev;
resource_size_t start, len;
int port_num, bar, i, ret = 0;
void __iomem *base;
u32 offset;
u64 v;
/* allocate enumeration info via pci_dev */
info = dfl_fpga_enum_info_alloc(&pcidev->dev);
if (!info)
return -ENOMEM;
/* start to find Device Feature List from Bar 0 */
base = cci_pci_ioremap_bar(pcidev, 0);
if (!base) {
ret = -ENOMEM;
goto enum_info_free_exit;
}
/*
* PF device has FME and Ports/AFUs, and VF device only has one
* Port/AFU. Check them and add related "Device Feature List" info
* for the next step enumeration.
*/
if (dfl_feature_is_fme(base)) {
start = pci_resource_start(pcidev, 0);
len = pci_resource_len(pcidev, 0);
dfl_fpga_enum_info_add_dfl(info, start, len, base);
/*
* find more Device Feature Lists (e.g. Ports) per information
* indicated by FME module.
*/
v = readq(base + FME_HDR_CAP);
port_num = FIELD_GET(FME_CAP_NUM_PORTS, v);
WARN_ON(port_num > MAX_DFL_FPGA_PORT_NUM);
for (i = 0; i < port_num; i++) {
v = readq(base + FME_HDR_PORT_OFST(i));
/* skip ports which are not implemented. */
if (!(v & FME_PORT_OFST_IMP))
continue;
/*
* add Port's Device Feature List information for next
* step enumeration.
*/
bar = FIELD_GET(FME_PORT_OFST_BAR_ID, v);
offset = FIELD_GET(FME_PORT_OFST_DFH_OFST, v);
base = cci_pci_ioremap_bar(pcidev, bar);
if (!base)
continue;
start = pci_resource_start(pcidev, bar) + offset;
len = pci_resource_len(pcidev, bar) - offset;
dfl_fpga_enum_info_add_dfl(info, start, len,
base + offset);
}
} else if (dfl_feature_is_port(base)) {
start = pci_resource_start(pcidev, 0);
len = pci_resource_len(pcidev, 0);
dfl_fpga_enum_info_add_dfl(info, start, len, base);
} else {
ret = -ENODEV;
goto enum_info_free_exit;
}
/* start enumeration with prepared enumeration information */
cdev = dfl_fpga_feature_devs_enumerate(info);
if (IS_ERR(cdev)) {
dev_err(&pcidev->dev, "Enumeration failure\n");
ret = PTR_ERR(cdev);
goto enum_info_free_exit;
}
drvdata->cdev = cdev;
enum_info_free_exit:
dfl_fpga_enum_info_free(info);
return ret;
}
static
int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
{
int ret;
ret = pcim_enable_device(pcidev);
if (ret < 0) {
dev_err(&pcidev->dev, "Failed to enable device %d.\n", ret);
return ret;
}
ret = pci_enable_pcie_error_reporting(pcidev);
if (ret && ret != -EINVAL)
dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
pci_set_master(pcidev);
if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
if (ret)
goto disable_error_report_exit;
} else if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
if (ret)
goto disable_error_report_exit;
} else {
ret = -EIO;
dev_err(&pcidev->dev, "No suitable DMA support available.\n");
goto disable_error_report_exit;
}
ret = cci_init_drvdata(pcidev);
if (ret) {
dev_err(&pcidev->dev, "Fail to init drvdata %d.\n", ret);
goto disable_error_report_exit;
}
ret = cci_enumerate_feature_devs(pcidev);
if (ret) {
dev_err(&pcidev->dev, "enumeration failure %d.\n", ret);
goto disable_error_report_exit;
}
return ret;
disable_error_report_exit:
pci_disable_pcie_error_reporting(pcidev);
return ret;
}
static void cci_pci_remove(struct pci_dev *pcidev)
{
cci_remove_feature_devs(pcidev);
pci_disable_pcie_error_reporting(pcidev);
}
static struct pci_driver cci_pci_driver = {
.name = DRV_NAME,
.id_table = cci_pcie_id_tbl,
.probe = cci_pci_probe,
.remove = cci_pci_remove,
};
module_pci_driver(cci_pci_driver);
MODULE_DESCRIPTION("FPGA DFL PCIe Device Driver");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
This diff is collapsed.
......@@ -406,12 +406,40 @@ static ssize_t state_show(struct device *dev,
return sprintf(buf, "%s\n", state_str[mgr->state]);
}
static ssize_t status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fpga_manager *mgr = to_fpga_manager(dev);
u64 status;
int len = 0;
if (!mgr->mops->status)
return -ENOENT;
status = mgr->mops->status(mgr);
if (status & FPGA_MGR_STATUS_OPERATION_ERR)
len += sprintf(buf + len, "reconfig operation error\n");
if (status & FPGA_MGR_STATUS_CRC_ERR)
len += sprintf(buf + len, "reconfig CRC error\n");
if (status & FPGA_MGR_STATUS_INCOMPATIBLE_IMAGE_ERR)
len += sprintf(buf + len, "reconfig incompatible image\n");
if (status & FPGA_MGR_STATUS_IP_PROTOCOL_ERR)
len += sprintf(buf + len, "reconfig IP protocol error\n");
if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR)
len += sprintf(buf + len, "reconfig fifo overflow error\n");
return len;
}
static DEVICE_ATTR_RO(name);
static DEVICE_ATTR_RO(state);
static DEVICE_ATTR_RO(status);
static struct attribute *fpga_mgr_attrs[] = {
&dev_attr_name.attr,
&dev_attr_state.attr,
&dev_attr_status.attr,
NULL,
};
ATTRIBUTE_GROUPS(fpga_mgr);
......
......@@ -158,6 +158,27 @@ int fpga_region_program_fpga(struct fpga_region *region)
}
EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
static ssize_t compat_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fpga_region *region = to_fpga_region(dev);
if (!region->compat_id)
return -ENOENT;
return sprintf(buf, "%016llx%016llx\n",
(unsigned long long)region->compat_id->id_h,
(unsigned long long)region->compat_id->id_l);
}
static DEVICE_ATTR_RO(compat_id);
static struct attribute *fpga_region_attrs[] = {
&dev_attr_compat_id.attr,
NULL,
};
ATTRIBUTE_GROUPS(fpga_region);
/**
* fpga_region_create - alloc and init a struct fpga_region
* @dev: device parent
......@@ -258,6 +279,7 @@ static int __init fpga_region_init(void)
if (IS_ERR(fpga_region_class))
return PTR_ERR(fpga_region_class);
fpga_region_class->dev_groups = fpga_region_groups;
fpga_region_class->dev_release = fpga_region_dev_release;
return 0;
......
This diff is collapsed.
......@@ -2,4 +2,6 @@
obj-$(CONFIG_FSI) += fsi-core.o
obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o
obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
obj-$(CONFIG_FSI_MASTER_AST_CF) += fsi-master-ast-cf.o
obj-$(CONFIG_FSI_SCOM) += fsi-scom.o
obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -122,7 +122,8 @@ static int hub_master_write(struct fsi_master *master, int link,
static int hub_master_break(struct fsi_master *master, int link)
{
uint32_t addr, cmd;
uint32_t addr;
__be32 cmd;
addr = 0x4;
cmd = cpu_to_be32(0xc0de0000);
......@@ -205,7 +206,7 @@ static int hub_master_init(struct fsi_master_hub *hub)
if (rc)
return rc;
reg = ~0;
reg = cpu_to_be32(~0);
rc = fsi_device_write(dev, FSI_MSENP0, &reg, sizeof(reg));
if (rc)
return rc;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment