forked from Minki/linux
drm/tegra: Changes for v3.14-rc1
This series of changes brings DRM panel support as well as initial code to register DSI hosts and peripherals and bind them to DSI drivers. The panel and DSI code are both used by the simple panel driver. The Tegra-specific changes build on top of this work to add support for various panels found on Tegra boards. New drivers enable the DSI host found on Tegra114 and a special hardware block that calibrates the pads used for DSI and CSI. The host1x and the display controller drivers gain basic Tegra124 support. To round of the new features, the DRM driver now sports a very simple PRIME implementation. In addition there are various improvements such as the host1x API being exported so that client drivers (like the Tegra DRM driver) can be built as modules. HDMI now does better power management and legacy FBDEV can now be disabled via Kconfig (though it's still enabled by default). A few sparse warnings have been squashed and various parts of the code have become more robust. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJStLL5AAoJEN0jrNd/PrOhtD0QAJwhRTuEh8xCJ7pu1eK3TMh2 BYCD5UOiqnPAcDjJlTsiX0NaNQQ15+9uIjSIbbk36tfZ5cWbiP5yURYyMZp1HjvP woGqsdI4eHVXswXNPMMIeTRrQKNMoQV82uvFAnE3QsfFwdkB+9p5tSUxnqXSuJ5U ZKv1AL4FC0FdAnvugEz1lBzxqthoLm0mQ9xwkoYN2hT9ak1bnZUljfGYp2G/0xqM RqhKgboZapL4Aul8lLIqqTCgo9XS3xN8Zo8F3WwyuOYJTgGZ6EK25H2bMvPBx0NO fBNeacVd2jaCrELL6ZdsodKuu+TbHM82Sc6mZTA3YxN/E4tFUTfT++LQF7w505mA PGHiZylwfDUPhGRRA8tYEz+OVQvT1FMhKEswlhDki0RJF5OHReQdrmBl0HfiUfmn cQC9/WzGIqIP68tuuxOf8tdKHbAP1sOf7WgjFrBVX86hktN2Aq2f4dYtB7tf1c5O 1wTY+NPho8avscCycWdcqAtrgz2/KHBo4KvO7f9dqiTFa+A6KXdqe1dZaFrsPBjL N4SizpY9VW7zJnmW9dIhb7qopVNw4g9OzCfH9dmpqrCnHpNFfmXYqDuppcSz7X5h fWpXtA6iAEVIa5CE44liZWv/5SU8Mowrb8YbBgC/EoMWphDfnzporvcHe94GLNiy O1iUYmI3mv48JKs30bYD =lQsh -----END PGP SIGNATURE----- Merge tag 'drm/for-3.14-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next drm/tegra: Changes for v3.14-rc1 This series of changes brings DRM panel support as well as initial code to register DSI hosts and peripherals and bind them to DSI drivers. The panel and DSI code are both used by the simple panel driver. The Tegra-specific changes build on top of this work to add support for various panels found on Tegra boards. New drivers enable the DSI host found on Tegra114 and a special hardware block that calibrates the pads used for DSI and CSI. The host1x and the display controller drivers gain basic Tegra124 support. To round of the new features, the DRM driver now sports a very simple PRIME implementation. In addition there are various improvements such as the host1x API being exported so that client drivers (like the Tegra DRM driver) can be built as modules. HDMI now does better power management and legacy FBDEV can now be disabled via Kconfig (though it's still enabled by default). A few sparse warnings have been squashed and various parts of the code have become more robust. * tag 'drm/for-3.14-rc1' of git://anongit.freedesktop.org/tegra/linux: (121 commits) drm/tegra: fix compile w/ CONFIG_DYNAMIC_DEBUG drm/tegra: Add PRIME support drm/tegra: Relocate some output-specific code drm/tegra: Add Tegra124 DC support drm/tegra: Fix small leak on error in tegra_fb_alloc() drm/tegra: Make legacy fbdev support optional drm/tegra: Sort reverse-dependencies alphabetically drm/tegra: Fix return value check drm/tegra: Add DSI support drm/tegra: Disable outputs for power-saving drm/tegra: Track HDMI enable state drm/tegra: Fix HDMI audio frequency typo drm/tegra: Do not export tegra_bo_ops drm/tegra: Remove spurious blank line drm/tegra: Increase compile test coverage drm/tegra: Allow the driver to be built as a module gpu: host1x: Add Tegra124 support gpu: host1x: clk_round_rate() can return a zero upon error gpu: host1x: Fix build warnings gpu: host1x: Increase compile test coverage ...
This commit is contained in:
commit
785e15ecef
@ -9,6 +9,7 @@ Required properties:
|
|||||||
- compatible : Should contain "nvidia,tegra<chip>-pmc".
|
- compatible : Should contain "nvidia,tegra<chip>-pmc".
|
||||||
- reg : Offset and length of the register set for the device
|
- reg : Offset and length of the register set for the device
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
"pclk" (The Tegra clock of that name),
|
"pclk" (The Tegra clock of that name),
|
||||||
"clk32k_in" (The 32KHz clock input to Tegra).
|
"clk32k_in" (The 32KHz clock input to Tegra).
|
||||||
|
@ -15,6 +15,9 @@ Required properties :
|
|||||||
In clock consumers, this cell represents the clock ID exposed by the
|
In clock consumers, this cell represents the clock ID exposed by the
|
||||||
CAR. The assignments may be found in header file
|
CAR. The assignments may be found in header file
|
||||||
<dt-bindings/clock/tegra114-car.h>.
|
<dt-bindings/clock/tegra114-car.h>.
|
||||||
|
- #reset-cells : Should be 1.
|
||||||
|
In clock consumers, this cell represents the bit number in the CAR's
|
||||||
|
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
|
||||||
|
|
||||||
Example SoC include file:
|
Example SoC include file:
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ Example SoC include file:
|
|||||||
compatible = "nvidia,tegra114-car";
|
compatible = "nvidia,tegra114-car";
|
||||||
reg = <0x60006000 0x1000>;
|
reg = <0x60006000 0x1000>;
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
usb@c5004000 {
|
usb@c5004000 {
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
NVIDIA Tegra124 Clock And Reset Controller
|
||||||
|
|
||||||
|
This binding uses the common clock binding:
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
|
||||||
|
The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
|
||||||
|
for muxing and gating Tegra's clocks, and setting their rates.
|
||||||
|
|
||||||
|
Required properties :
|
||||||
|
- compatible : Should be "nvidia,tegra124-car"
|
||||||
|
- reg : Should contain CAR registers location and length
|
||||||
|
- clocks : Should contain phandle and clock specifiers for two clocks:
|
||||||
|
the 32 KHz "32k_in", and the board-specific oscillator "osc".
|
||||||
|
- #clock-cells : Should be 1.
|
||||||
|
In clock consumers, this cell represents the clock ID exposed by the
|
||||||
|
CAR. The assignments may be found in header file
|
||||||
|
<dt-bindings/clock/tegra124-car.h>.
|
||||||
|
- #reset-cells : Should be 1.
|
||||||
|
In clock consumers, this cell represents the bit number in the CAR's
|
||||||
|
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
|
||||||
|
|
||||||
|
Example SoC include file:
|
||||||
|
|
||||||
|
/ {
|
||||||
|
tegra_car: clock {
|
||||||
|
compatible = "nvidia,tegra124-car";
|
||||||
|
reg = <0x60006000 0x1000>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
usb@c5004000 {
|
||||||
|
clocks = <&tegra_car TEGRA124_CLK_USB2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Example board file:
|
||||||
|
|
||||||
|
/ {
|
||||||
|
clocks {
|
||||||
|
compatible = "simple-bus";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
osc: clock@0 {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg = <0>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <112400000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
clk_32k: clock@1 {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg = <1>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <32768>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&tegra_car {
|
||||||
|
clocks = <&clk_32k> <&osc>;
|
||||||
|
};
|
||||||
|
};
|
@ -15,6 +15,9 @@ Required properties :
|
|||||||
In clock consumers, this cell represents the clock ID exposed by the
|
In clock consumers, this cell represents the clock ID exposed by the
|
||||||
CAR. The assignments may be found in header file
|
CAR. The assignments may be found in header file
|
||||||
<dt-bindings/clock/tegra20-car.h>.
|
<dt-bindings/clock/tegra20-car.h>.
|
||||||
|
- #reset-cells : Should be 1.
|
||||||
|
In clock consumers, this cell represents the bit number in the CAR's
|
||||||
|
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
|
||||||
|
|
||||||
Example SoC include file:
|
Example SoC include file:
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ Example SoC include file:
|
|||||||
compatible = "nvidia,tegra20-car";
|
compatible = "nvidia,tegra20-car";
|
||||||
reg = <0x60006000 0x1000>;
|
reg = <0x60006000 0x1000>;
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
usb@c5004000 {
|
usb@c5004000 {
|
||||||
|
@ -15,6 +15,9 @@ Required properties :
|
|||||||
In clock consumers, this cell represents the clock ID exposed by the
|
In clock consumers, this cell represents the clock ID exposed by the
|
||||||
CAR. The assignments may be found in header file
|
CAR. The assignments may be found in header file
|
||||||
<dt-bindings/clock/tegra30-car.h>.
|
<dt-bindings/clock/tegra30-car.h>.
|
||||||
|
- #reset-cells : Should be 1.
|
||||||
|
In clock consumers, this cell represents the bit number in the CAR's
|
||||||
|
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
|
||||||
|
|
||||||
Example SoC include file:
|
Example SoC include file:
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ Example SoC include file:
|
|||||||
compatible = "nvidia,tegra30-car";
|
compatible = "nvidia,tegra30-car";
|
||||||
reg = <0x60006000 0x1000>;
|
reg = <0x60006000 0x1000>;
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
usb@c5004000 {
|
usb@c5004000 {
|
||||||
|
@ -5,6 +5,16 @@ Required properties:
|
|||||||
- reg: Should contain DMA registers location and length. This shuld include
|
- reg: Should contain DMA registers location and length. This shuld include
|
||||||
all of the per-channel registers.
|
all of the per-channel registers.
|
||||||
- interrupts: Should contain all of the per-channel DMA interrupts.
|
- interrupts: Should contain all of the per-channel DMA interrupts.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- dma
|
||||||
|
- #dma-cells : Must be <1>. This dictates the length of DMA specifiers in
|
||||||
|
client nodes' dmas properties. The specifier represents the DMA request
|
||||||
|
select value for the peripheral. For more details, consult the Tegra TRM's
|
||||||
|
documentation of the APB DMA channel control register REQ_SEL field.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@ -27,4 +37,8 @@ apbdma: dma@6000a000 {
|
|||||||
0 149 0x04
|
0 149 0x04
|
||||||
0 150 0x04
|
0 150 0x04
|
||||||
0 151 0x04 >;
|
0 151 0x04 >;
|
||||||
|
clocks = <&tegra_car 34>;
|
||||||
|
resets = <&tegra_car 34>;
|
||||||
|
reset-names = "dma";
|
||||||
|
#dma-cells = <1>;
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,12 @@ Required properties:
|
|||||||
- #size-cells: The number of cells used to represent the size of an address
|
- #size-cells: The number of cells used to represent the size of an address
|
||||||
range in the host1x address space. Should be 1.
|
range in the host1x address space. Should be 1.
|
||||||
- ranges: The mapping of the host1x address space to the CPU address space.
|
- ranges: The mapping of the host1x address space to the CPU address space.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- host1x
|
||||||
|
|
||||||
The host1x top-level node defines a number of children, each representing one
|
The host1x top-level node defines a number of children, each representing one
|
||||||
of the following host1x client modules:
|
of the following host1x client modules:
|
||||||
@ -19,6 +25,12 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-mpe"
|
- compatible: "nvidia,tegra<chip>-mpe"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- mpe
|
||||||
|
|
||||||
- vi: video input
|
- vi: video input
|
||||||
|
|
||||||
@ -26,6 +38,12 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-vi"
|
- compatible: "nvidia,tegra<chip>-vi"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- vi
|
||||||
|
|
||||||
- epp: encoder pre-processor
|
- epp: encoder pre-processor
|
||||||
|
|
||||||
@ -33,6 +51,12 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-epp"
|
- compatible: "nvidia,tegra<chip>-epp"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- epp
|
||||||
|
|
||||||
- isp: image signal processor
|
- isp: image signal processor
|
||||||
|
|
||||||
@ -40,6 +64,12 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-isp"
|
- compatible: "nvidia,tegra<chip>-isp"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- isp
|
||||||
|
|
||||||
- gr2d: 2D graphics engine
|
- gr2d: 2D graphics engine
|
||||||
|
|
||||||
@ -47,12 +77,30 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-gr2d"
|
- compatible: "nvidia,tegra<chip>-gr2d"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- 2d
|
||||||
|
|
||||||
- gr3d: 3D graphics engine
|
- gr3d: 3D graphics engine
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: "nvidia,tegra<chip>-gr3d"
|
- compatible: "nvidia,tegra<chip>-gr3d"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- clock-names: Must include the following entries:
|
||||||
|
(This property may be omitted if the only clock in the list is "3d")
|
||||||
|
- 3d
|
||||||
|
This MUST be the first entry.
|
||||||
|
- 3d2 (Only required on SoCs with two 3D clocks)
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- 3d
|
||||||
|
- 3d2 (Only required on SoCs with two 3D clocks)
|
||||||
|
|
||||||
- dc: display controller
|
- dc: display controller
|
||||||
|
|
||||||
@ -60,6 +108,16 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-dc"
|
- compatible: "nvidia,tegra<chip>-dc"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- clock-names: Must include the following entries:
|
||||||
|
- dc
|
||||||
|
This MUST be the first entry.
|
||||||
|
- parent
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- dc
|
||||||
|
|
||||||
Each display controller node has a child node, named "rgb", that represents
|
Each display controller node has a child node, named "rgb", that represents
|
||||||
the RGB output associated with the controller. It can take the following
|
the RGB output associated with the controller. It can take the following
|
||||||
@ -67,6 +125,7 @@ of the following host1x client modules:
|
|||||||
- nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
- nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
||||||
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
|
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
|
||||||
- nvidia,edid: supplies a binary EDID blob
|
- nvidia,edid: supplies a binary EDID blob
|
||||||
|
- nvidia,panel: phandle of a display panel
|
||||||
|
|
||||||
- hdmi: High Definition Multimedia Interface
|
- hdmi: High Definition Multimedia Interface
|
||||||
|
|
||||||
@ -76,11 +135,22 @@ of the following host1x client modules:
|
|||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
- vdd-supply: regulator for supply voltage
|
- vdd-supply: regulator for supply voltage
|
||||||
- pll-supply: regulator for PLL
|
- pll-supply: regulator for PLL
|
||||||
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- clock-names: Must include the following entries:
|
||||||
|
- hdmi
|
||||||
|
This MUST be the first entry.
|
||||||
|
- parent
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- hdmi
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
- nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
||||||
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
|
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
|
||||||
- nvidia,edid: supplies a binary EDID blob
|
- nvidia,edid: supplies a binary EDID blob
|
||||||
|
- nvidia,panel: phandle of a display panel
|
||||||
|
|
||||||
- tvo: TV encoder output
|
- tvo: TV encoder output
|
||||||
|
|
||||||
@ -88,12 +158,34 @@ of the following host1x client modules:
|
|||||||
- compatible: "nvidia,tegra<chip>-tvo"
|
- compatible: "nvidia,tegra<chip>-tvo"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
- interrupts: The interrupt outputs from the controller.
|
- interrupts: The interrupt outputs from the controller.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
|
||||||
- dsi: display serial interface
|
- dsi: display serial interface
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: "nvidia,tegra<chip>-dsi"
|
- compatible: "nvidia,tegra<chip>-dsi"
|
||||||
- reg: Physical base address and length of the controller's registers.
|
- reg: Physical base address and length of the controller's registers.
|
||||||
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- clock-names: Must include the following entries:
|
||||||
|
- dsi
|
||||||
|
This MUST be the first entry.
|
||||||
|
- lp
|
||||||
|
- parent
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- dsi
|
||||||
|
- nvidia,mipi-calibrate: Should contain a phandle and a specifier specifying
|
||||||
|
which pads are used by this DSI output and need to be calibrated. See also
|
||||||
|
../mipi/nvidia,tegra114-mipi.txt.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
||||||
|
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
|
||||||
|
- nvidia,edid: supplies a binary EDID blob
|
||||||
|
- nvidia,panel: phandle of a display panel
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -105,6 +197,9 @@ Example:
|
|||||||
reg = <0x50000000 0x00024000>;
|
reg = <0x50000000 0x00024000>;
|
||||||
interrupts = <0 65 0x04 /* mpcore syncpt */
|
interrupts = <0 65 0x04 /* mpcore syncpt */
|
||||||
0 67 0x04>; /* mpcore general */
|
0 67 0x04>; /* mpcore general */
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_HOST1X>;
|
||||||
|
resets = <&tegra_car 28>;
|
||||||
|
reset-names = "host1x";
|
||||||
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
@ -115,41 +210,64 @@ Example:
|
|||||||
compatible = "nvidia,tegra20-mpe";
|
compatible = "nvidia,tegra20-mpe";
|
||||||
reg = <0x54040000 0x00040000>;
|
reg = <0x54040000 0x00040000>;
|
||||||
interrupts = <0 68 0x04>;
|
interrupts = <0 68 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_MPE>;
|
||||||
|
resets = <&tegra_car 60>;
|
||||||
|
reset-names = "mpe";
|
||||||
};
|
};
|
||||||
|
|
||||||
vi {
|
vi {
|
||||||
compatible = "nvidia,tegra20-vi";
|
compatible = "nvidia,tegra20-vi";
|
||||||
reg = <0x54080000 0x00040000>;
|
reg = <0x54080000 0x00040000>;
|
||||||
interrupts = <0 69 0x04>;
|
interrupts = <0 69 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_VI>;
|
||||||
|
resets = <&tegra_car 100>;
|
||||||
|
reset-names = "vi";
|
||||||
};
|
};
|
||||||
|
|
||||||
epp {
|
epp {
|
||||||
compatible = "nvidia,tegra20-epp";
|
compatible = "nvidia,tegra20-epp";
|
||||||
reg = <0x540c0000 0x00040000>;
|
reg = <0x540c0000 0x00040000>;
|
||||||
interrupts = <0 70 0x04>;
|
interrupts = <0 70 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_EPP>;
|
||||||
|
resets = <&tegra_car 19>;
|
||||||
|
reset-names = "epp";
|
||||||
};
|
};
|
||||||
|
|
||||||
isp {
|
isp {
|
||||||
compatible = "nvidia,tegra20-isp";
|
compatible = "nvidia,tegra20-isp";
|
||||||
reg = <0x54100000 0x00040000>;
|
reg = <0x54100000 0x00040000>;
|
||||||
interrupts = <0 71 0x04>;
|
interrupts = <0 71 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_ISP>;
|
||||||
|
resets = <&tegra_car 23>;
|
||||||
|
reset-names = "isp";
|
||||||
};
|
};
|
||||||
|
|
||||||
gr2d {
|
gr2d {
|
||||||
compatible = "nvidia,tegra20-gr2d";
|
compatible = "nvidia,tegra20-gr2d";
|
||||||
reg = <0x54140000 0x00040000>;
|
reg = <0x54140000 0x00040000>;
|
||||||
interrupts = <0 72 0x04>;
|
interrupts = <0 72 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_GR2D>;
|
||||||
|
resets = <&tegra_car 21>;
|
||||||
|
reset-names = "2d";
|
||||||
};
|
};
|
||||||
|
|
||||||
gr3d {
|
gr3d {
|
||||||
compatible = "nvidia,tegra20-gr3d";
|
compatible = "nvidia,tegra20-gr3d";
|
||||||
reg = <0x54180000 0x00040000>;
|
reg = <0x54180000 0x00040000>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_GR3D>;
|
||||||
|
resets = <&tegra_car 24>;
|
||||||
|
reset-names = "3d";
|
||||||
};
|
};
|
||||||
|
|
||||||
dc@54200000 {
|
dc@54200000 {
|
||||||
compatible = "nvidia,tegra20-dc";
|
compatible = "nvidia,tegra20-dc";
|
||||||
reg = <0x54200000 0x00040000>;
|
reg = <0x54200000 0x00040000>;
|
||||||
interrupts = <0 73 0x04>;
|
interrupts = <0 73 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_DISP1>,
|
||||||
|
<&tegra_car TEGRA20_CLK_PLL_P>;
|
||||||
|
clock-names = "dc", "parent";
|
||||||
|
resets = <&tegra_car 27>;
|
||||||
|
reset-names = "dc";
|
||||||
|
|
||||||
rgb {
|
rgb {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -160,6 +278,11 @@ Example:
|
|||||||
compatible = "nvidia,tegra20-dc";
|
compatible = "nvidia,tegra20-dc";
|
||||||
reg = <0x54240000 0x00040000>;
|
reg = <0x54240000 0x00040000>;
|
||||||
interrupts = <0 74 0x04>;
|
interrupts = <0 74 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_DISP2>,
|
||||||
|
<&tegra_car TEGRA20_CLK_PLL_P>;
|
||||||
|
clock-names = "dc", "parent";
|
||||||
|
resets = <&tegra_car 26>;
|
||||||
|
reset-names = "dc";
|
||||||
|
|
||||||
rgb {
|
rgb {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -170,6 +293,11 @@ Example:
|
|||||||
compatible = "nvidia,tegra20-hdmi";
|
compatible = "nvidia,tegra20-hdmi";
|
||||||
reg = <0x54280000 0x00040000>;
|
reg = <0x54280000 0x00040000>;
|
||||||
interrupts = <0 75 0x04>;
|
interrupts = <0 75 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_HDMI>,
|
||||||
|
<&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
|
||||||
|
clock-names = "hdmi", "parent";
|
||||||
|
resets = <&tegra_car 51>;
|
||||||
|
reset-names = "hdmi";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -177,12 +305,18 @@ Example:
|
|||||||
compatible = "nvidia,tegra20-tvo";
|
compatible = "nvidia,tegra20-tvo";
|
||||||
reg = <0x542c0000 0x00040000>;
|
reg = <0x542c0000 0x00040000>;
|
||||||
interrupts = <0 76 0x04>;
|
interrupts = <0 76 0x04>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_TVO>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
dsi {
|
dsi {
|
||||||
compatible = "nvidia,tegra20-dsi";
|
compatible = "nvidia,tegra20-dsi";
|
||||||
reg = <0x54300000 0x00040000>;
|
reg = <0x54300000 0x00040000>;
|
||||||
|
clocks = <&tegra_car TEGRA20_CLK_DSI>,
|
||||||
|
<&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
|
||||||
|
clock-names = "dsi", "parent";
|
||||||
|
resets = <&tegra_car 48>;
|
||||||
|
reset-names = "dsi";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -39,12 +39,23 @@ Required properties:
|
|||||||
- interrupts: Should contain I2C controller interrupts.
|
- interrupts: Should contain I2C controller interrupts.
|
||||||
- address-cells: Address cells for I2C device address.
|
- address-cells: Address cells for I2C device address.
|
||||||
- size-cells: Size of the I2C device address.
|
- size-cells: Size of the I2C device address.
|
||||||
- clocks: Clock ID as per
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
Documentation/devicetree/bindings/clock/tegra<chip-id>.txt
|
See ../clocks/clock-bindings.txt for details.
|
||||||
for I2C controller.
|
- clock-names: Must include the following entries:
|
||||||
- clock-names: Name of the clock:
|
Tegra20/Tegra30:
|
||||||
Tegra20/Tegra30 I2C controller: "div-clk and "fast-clk".
|
- div-clk
|
||||||
Tegra114 I2C controller: "div-clk".
|
- fast-clk
|
||||||
|
Tegra114:
|
||||||
|
- div-clk
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- i2c
|
||||||
|
- dmas: Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names: Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -56,5 +67,9 @@ Example:
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car 12>, <&tegra_car 124>;
|
clocks = <&tegra_car 12>, <&tegra_car 124>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 12>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,12 @@ Required properties:
|
|||||||
array of pin numbers which is used as column.
|
array of pin numbers which is used as column.
|
||||||
- linux,keymap: The keymap for keys as described in the binding document
|
- linux,keymap: The keymap for keys as described in the binding document
|
||||||
devicetree/bindings/input/matrix-keymap.txt.
|
devicetree/bindings/input/matrix-keymap.txt.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- kbc
|
||||||
|
|
||||||
Optional properties, in addition to those specified by the shared
|
Optional properties, in addition to those specified by the shared
|
||||||
matrix-keyboard bindings:
|
matrix-keyboard bindings:
|
||||||
@ -31,6 +37,9 @@ keyboard: keyboard {
|
|||||||
compatible = "nvidia,tegra20-kbc";
|
compatible = "nvidia,tegra20-kbc";
|
||||||
reg = <0x7000e200 0x100>;
|
reg = <0x7000e200 0x100>;
|
||||||
interrupts = <0 85 0x04>;
|
interrupts = <0 85 0x04>;
|
||||||
|
clocks = <&tegra_car 36>;
|
||||||
|
resets = <&tegra_car 36>;
|
||||||
|
reset-names = "kbc";
|
||||||
nvidia,ghost-filter;
|
nvidia,ghost-filter;
|
||||||
nvidia,debounce-delay-ms = <640>;
|
nvidia,debounce-delay-ms = <640>;
|
||||||
nvidia,kbc-row-pins = <0 1 2>; /* pin 0, 1, 2 as rows */
|
nvidia,kbc-row-pins = <0 1 2>; /* pin 0, 1, 2 as rows */
|
||||||
|
98
Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt
Normal file
98
Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
MIPI DSI (Display Serial Interface) busses
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
The MIPI Display Serial Interface specifies a serial bus and a protocol for
|
||||||
|
communication between a host and up to four peripherals. This document will
|
||||||
|
define the syntax used to represent a DSI bus in a device tree.
|
||||||
|
|
||||||
|
This document describes DSI bus-specific properties only or defines existing
|
||||||
|
standard properties in the context of the DSI bus.
|
||||||
|
|
||||||
|
Each DSI host provides a DSI bus. The DSI host controller's node contains a
|
||||||
|
set of properties that characterize the bus. Child nodes describe individual
|
||||||
|
peripherals on that bus.
|
||||||
|
|
||||||
|
The following assumes that only a single peripheral is connected to a DSI
|
||||||
|
host. Experience shows that this is true for the large majority of setups.
|
||||||
|
|
||||||
|
DSI host
|
||||||
|
--------
|
||||||
|
|
||||||
|
In addition to the standard properties and those defined by the parent bus of
|
||||||
|
a DSI host, the following properties apply to a node representing a DSI host.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- #address-cells: The number of cells required to represent an address on the
|
||||||
|
bus. DSI peripherals are addressed using a 2-bit virtual channel number, so
|
||||||
|
a maximum of 4 devices can be addressed on a single bus. Hence the value of
|
||||||
|
this property should be 1.
|
||||||
|
- #size-cells: Should be 0. There are cases where it makes sense to use a
|
||||||
|
different value here. See below.
|
||||||
|
|
||||||
|
DSI peripheral
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Peripherals are represented as child nodes of the DSI host's node. Properties
|
||||||
|
described here apply to all DSI peripherals, but individual bindings may want
|
||||||
|
to define additional, device-specific properties.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- reg: The virtual channel number of a DSI peripheral. Must be in the range
|
||||||
|
from 0 to 3.
|
||||||
|
|
||||||
|
Some DSI peripherals respond to more than a single virtual channel. In that
|
||||||
|
case two alternative representations can be chosen:
|
||||||
|
- The reg property can take multiple entries, one for each virtual channel
|
||||||
|
that the peripheral responds to.
|
||||||
|
- If the virtual channels that a peripheral responds to are consecutive, the
|
||||||
|
#size-cells can be set to 1. The first cell of each entry in the reg
|
||||||
|
property is the number of the first virtual channel and the second cell is
|
||||||
|
the number of consecutive virtual channels.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
dsi-host {
|
||||||
|
...
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
/* peripheral responds to virtual channel 0 */
|
||||||
|
peripheral@0 {
|
||||||
|
compatible = "...";
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi-host {
|
||||||
|
...
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
/* peripheral responds to virtual channels 0 and 2 */
|
||||||
|
peripheral@0 {
|
||||||
|
compatible = "...";
|
||||||
|
reg = <0, 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi-host {
|
||||||
|
...
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* peripheral responds to virtual channels 1, 2 and 3 */
|
||||||
|
peripheral@1 {
|
||||||
|
compatible = "...";
|
||||||
|
reg = <1 3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
};
|
@ -0,0 +1,41 @@
|
|||||||
|
NVIDIA Tegra MIPI pad calibration controller
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: "nvidia,tegra<chip>-mipi"
|
||||||
|
- reg: Physical base address and length of the controller's registers.
|
||||||
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- clock-names: Must include the following entries:
|
||||||
|
- mipi-cal
|
||||||
|
- #nvidia,mipi-calibrate-cells: Should be 1. The cell is a bitmask of the pads
|
||||||
|
that need to be calibrated for a given device.
|
||||||
|
|
||||||
|
User nodes need to contain an nvidia,mipi-calibrate property that has a
|
||||||
|
phandle to refer to the calibration controller node and a bitmask of the pads
|
||||||
|
that need to be calibrated.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
mipi: mipi@700e3000 {
|
||||||
|
compatible = "nvidia,tegra114-mipi";
|
||||||
|
reg = <0x700e3000 0x100>;
|
||||||
|
clocks = <&tegra_car TEGRA114_CLK_MIPI_CAL>;
|
||||||
|
clock-names = "mipi-cal";
|
||||||
|
#nvidia,mipi-calibrate-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
host1x@50000000 {
|
||||||
|
...
|
||||||
|
|
||||||
|
dsi@54300000 {
|
||||||
|
...
|
||||||
|
|
||||||
|
nvidia,mipi-calibrate = <&mipi 0x060>;
|
||||||
|
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
};
|
@ -8,6 +8,12 @@ by mmc.txt and the properties used by the sdhci-tegra driver.
|
|||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : Should be "nvidia,<chip>-sdhci"
|
- compatible : Should be "nvidia,<chip>-sdhci"
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- sdhci
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- power-gpios : Specify GPIOs for power control
|
- power-gpios : Specify GPIOs for power control
|
||||||
@ -18,6 +24,9 @@ sdhci@c8000200 {
|
|||||||
compatible = "nvidia,tegra20-sdhci";
|
compatible = "nvidia,tegra20-sdhci";
|
||||||
reg = <0xc8000200 0x200>;
|
reg = <0xc8000200 0x200>;
|
||||||
interrupts = <47>;
|
interrupts = <47>;
|
||||||
|
clocks = <&tegra_car 14>;
|
||||||
|
resets = <&tegra_car 14>;
|
||||||
|
reset-names = "sdhci";
|
||||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
||||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||||
power-gpios = <&gpio 155 0>; /* gpio PT3 */
|
power-gpios = <&gpio 155 0>; /* gpio PT3 */
|
||||||
|
@ -7,3 +7,15 @@ Required properties:
|
|||||||
- clock-frequency : the frequency of the i2c bus
|
- clock-frequency : the frequency of the i2c bus
|
||||||
- gpios : the gpio used for ec request
|
- gpios : the gpio used for ec request
|
||||||
- slave-addr: the i2c address of the slave controller
|
- slave-addr: the i2c address of the slave controller
|
||||||
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- clock-names : Must include the following entries:
|
||||||
|
Tegra20/Tegra30:
|
||||||
|
- div-clk
|
||||||
|
- fast-clk
|
||||||
|
Tegra114:
|
||||||
|
- div-clk
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- i2c
|
||||||
|
7
Documentation/devicetree/bindings/panel/auo,b101aw03.txt
Normal file
7
Documentation/devicetree/bindings/panel/auo,b101aw03.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
AU Optronics Corporation 10.1" WSVGA TFT LCD panel
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: should be "auo,b101aw03"
|
||||||
|
|
||||||
|
This binding is compatible with the simple-panel binding, which is specified
|
||||||
|
in simple-panel.txt in this directory.
|
@ -0,0 +1,7 @@
|
|||||||
|
Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: should be "chunghwa,claa101wb03"
|
||||||
|
|
||||||
|
This binding is compatible with the simple-panel binding, which is specified
|
||||||
|
in simple-panel.txt in this directory.
|
@ -0,0 +1,7 @@
|
|||||||
|
Panasonic Corporation 10.1" WUXGA TFT LCD panel
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: should be "panasonic,vvx10f004b00"
|
||||||
|
|
||||||
|
This binding is compatible with the simple-panel binding, which is specified
|
||||||
|
in simple-panel.txt in this directory.
|
21
Documentation/devicetree/bindings/panel/simple-panel.txt
Normal file
21
Documentation/devicetree/bindings/panel/simple-panel.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
Simple display panel
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- power-supply: regulator to provide the supply voltage
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
||||||
|
- enable-gpios: GPIO pin to enable or disable the panel
|
||||||
|
- backlight: phandle of the backlight device attached to the panel
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
panel: panel {
|
||||||
|
compatible = "cptt,claa101wb01";
|
||||||
|
ddc-i2c-bus = <&panelddc>;
|
||||||
|
|
||||||
|
power-supply = <&vdd_pnl_reg>;
|
||||||
|
enable-gpios = <&gpio 90 0>;
|
||||||
|
|
||||||
|
backlight = <&backlight>;
|
||||||
|
};
|
@ -42,14 +42,19 @@ Required properties:
|
|||||||
- 0xc2000000: prefetchable memory region
|
- 0xc2000000: prefetchable memory region
|
||||||
Please refer to the standard PCI bus binding document for a more detailed
|
Please refer to the standard PCI bus binding document for a more detailed
|
||||||
explanation.
|
explanation.
|
||||||
- clocks: List of clock inputs of the controller. Must contain an entry for
|
- clocks: Must contain an entry for each entry in clock-names.
|
||||||
each entry in the clock-names property.
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names: Must include the following entries:
|
- clock-names: Must include the following entries:
|
||||||
"pex": The Tegra clock of that name
|
- pex
|
||||||
"afi": The Tegra clock of that name
|
- afi
|
||||||
"pcie_xclk": The Tegra clock of that name
|
- pll_e
|
||||||
"pll_e": The Tegra clock of that name
|
- cml (not required for Tegra20)
|
||||||
"cml": The Tegra clock of that name (not required for Tegra20)
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- pex
|
||||||
|
- afi
|
||||||
|
- pcie_x
|
||||||
|
|
||||||
Root ports are defined as subnodes of the PCIe controller node.
|
Root ports are defined as subnodes of the PCIe controller node.
|
||||||
|
|
||||||
@ -91,9 +96,10 @@ SoC DTSI:
|
|||||||
0x82000000 0 0xa0000000 0xa0000000 0 0x10000000 /* non-prefetchable memory */
|
0x82000000 0 0xa0000000 0xa0000000 0 0x10000000 /* non-prefetchable memory */
|
||||||
0xc2000000 0 0xb0000000 0xb0000000 0 0x10000000>; /* prefetchable memory */
|
0xc2000000 0 0xb0000000 0xb0000000 0 0x10000000>; /* prefetchable memory */
|
||||||
|
|
||||||
clocks = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 74>,
|
clocks = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 118>;
|
||||||
<&tegra_car 118>;
|
clock-names = "pex", "afi", "pll_e";
|
||||||
clock-names = "pex", "afi", "pcie_xclk", "pll_e";
|
resets = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 74>;
|
||||||
|
reset-names = "pex", "afi", "pcie_x";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
pci@1,0 {
|
pci@1,0 {
|
||||||
|
@ -7,6 +7,12 @@ Required properties:
|
|||||||
- reg: physical base address and length of the controller's registers
|
- reg: physical base address and length of the controller's registers
|
||||||
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
|
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
|
||||||
the cells format.
|
the cells format.
|
||||||
|
- clocks: Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets: Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names: Must include the following entries:
|
||||||
|
- pwm
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -14,4 +20,7 @@ Example:
|
|||||||
compatible = "nvidia,tegra20-pwm";
|
compatible = "nvidia,tegra20-pwm";
|
||||||
reg = <0x7000a000 0x100>;
|
reg = <0x7000a000 0x100>;
|
||||||
#pwm-cells = <2>;
|
#pwm-cells = <2>;
|
||||||
|
clocks = <&tegra_car 17>;
|
||||||
|
resets = <&tegra_car 17>;
|
||||||
|
reset-names = "pwm";
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,8 @@ Required properties:
|
|||||||
- compatible : should be "nvidia,tegra20-rtc".
|
- compatible : should be "nvidia,tegra20-rtc".
|
||||||
- reg : Specifies base physical address and size of the registers.
|
- reg : Specifies base physical address and size of the registers.
|
||||||
- interrupts : A single interrupt specifier.
|
- interrupts : A single interrupt specifier.
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -16,4 +18,5 @@ timer {
|
|||||||
compatible = "nvidia,tegra20-rtc";
|
compatible = "nvidia,tegra20-rtc";
|
||||||
reg = <0x7000e000 0x100>;
|
reg = <0x7000e000 0x100>;
|
||||||
interrupts = <0 2 0x04>;
|
interrupts = <0 2 0x04>;
|
||||||
|
clocks = <&tegra_car 4>;
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,17 @@ Required properties:
|
|||||||
- compatible : should be "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart".
|
- compatible : should be "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart".
|
||||||
- reg: Should contain UART controller registers location and length.
|
- reg: Should contain UART controller registers location and length.
|
||||||
- interrupts: Should contain UART controller interrupts.
|
- interrupts: Should contain UART controller interrupts.
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- clocks: Must contain one entry, for the module clock.
|
||||||
request selector for this UART controller.
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- serial
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- nvidia,enable-modem-interrupt: Enable modem interrupts. Should be enable
|
- nvidia,enable-modem-interrupt: Enable modem interrupts. Should be enable
|
||||||
@ -18,7 +27,11 @@ serial@70006000 {
|
|||||||
reg = <0x70006000 0x40>;
|
reg = <0x70006000 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <0 36 0x04>;
|
interrupts = <0 36 0x04>;
|
||||||
nvidia,dma-request-selector = <&apbdma 8>;
|
|
||||||
nvidia,enable-modem-interrupt;
|
nvidia,enable-modem-interrupt;
|
||||||
|
clocks = <&tegra_car 6>;
|
||||||
|
resets = <&tegra_car 6>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 8>, <&apbdma 8>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra-audio-alc5632"
|
- compatible : "nvidia,tegra-audio-alc5632"
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
"pll_a" (The Tegra clock of that name),
|
- pll_a
|
||||||
"pll_a_out0" (The Tegra clock of that name),
|
- pll_a_out0
|
||||||
"mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
||||||
- nvidia,model : The user-visible name of this sound complex.
|
- nvidia,model : The user-visible name of this sound complex.
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- nvidia,audio-routing : A list of the connections between audio components.
|
||||||
Each entry is a pair of strings, the first being the connection's sink,
|
Each entry is a pair of strings, the first being the connection's sink,
|
||||||
|
@ -3,10 +3,11 @@ NVIDIA Tegra audio complex, with RT5640 CODEC
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra-audio-rt5640"
|
- compatible : "nvidia,tegra-audio-rt5640"
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
"pll_a" (The Tegra clock of that name),
|
- pll_a
|
||||||
"pll_a_out0" (The Tegra clock of that name),
|
- pll_a_out0
|
||||||
"mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
||||||
- nvidia,model : The user-visible name of this sound complex.
|
- nvidia,model : The user-visible name of this sound complex.
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- nvidia,audio-routing : A list of the connections between audio components.
|
||||||
Each entry is a pair of strings, the first being the connection's sink,
|
Each entry is a pair of strings, the first being the connection's sink,
|
||||||
|
@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra-audio-wm8753"
|
- compatible : "nvidia,tegra-audio-wm8753"
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
"pll_a" (The Tegra clock of that name),
|
- pll_a
|
||||||
"pll_a_out0" (The Tegra clock of that name),
|
- pll_a_out0
|
||||||
"mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
||||||
- nvidia,model : The user-visible name of this sound complex.
|
- nvidia,model : The user-visible name of this sound complex.
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- nvidia,audio-routing : A list of the connections between audio components.
|
||||||
Each entry is a pair of strings, the first being the connection's sink,
|
Each entry is a pair of strings, the first being the connection's sink,
|
||||||
|
@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra-audio-wm8903"
|
- compatible : "nvidia,tegra-audio-wm8903"
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
"pll_a" (The Tegra clock of that name),
|
- pll_a
|
||||||
"pll_a_out0" (The Tegra clock of that name),
|
- pll_a_out0
|
||||||
"mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
||||||
- nvidia,model : The user-visible name of this sound complex.
|
- nvidia,model : The user-visible name of this sound complex.
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- nvidia,audio-routing : A list of the connections between audio components.
|
||||||
Each entry is a pair of strings, the first being the connection's sink,
|
Each entry is a pair of strings, the first being the connection's sink,
|
||||||
|
@ -3,10 +3,11 @@ NVIDIA Tegra audio complex
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra-audio-wm9712"
|
- compatible : "nvidia,tegra-audio-wm9712"
|
||||||
- clocks : Must contain an entry for each entry in clock-names.
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
"pll_a" (The Tegra clock of that name),
|
- pll_a
|
||||||
"pll_a_out0" (The Tegra clock of that name),
|
- pll_a_out0
|
||||||
"mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
- mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
|
||||||
- nvidia,model : The user-visible name of this sound complex.
|
- nvidia,model : The user-visible name of this sound complex.
|
||||||
- nvidia,audio-routing : A list of the connections between audio components.
|
- nvidia,audio-routing : A list of the connections between audio components.
|
||||||
Each entry is a pair of strings, the first being the connection's sink,
|
Each entry is a pair of strings, the first being the connection's sink,
|
||||||
|
@ -4,19 +4,33 @@ Required properties:
|
|||||||
- compatible : "nvidia,tegra20-ac97"
|
- compatible : "nvidia,tegra20-ac97"
|
||||||
- reg : Should contain AC97 controller registers location and length
|
- reg : Should contain AC97 controller registers location and length
|
||||||
- interrupts : Should contain AC97 interrupt
|
- interrupts : Should contain AC97 interrupt
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
request selector for the AC97 controller
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- ac97
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
- nvidia,codec-reset-gpio : The Tegra GPIO controller's phandle and the number
|
- nvidia,codec-reset-gpio : The Tegra GPIO controller's phandle and the number
|
||||||
of the GPIO used to reset the external AC97 codec
|
of the GPIO used to reset the external AC97 codec
|
||||||
- nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number
|
- nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number
|
||||||
of the GPIO corresponding with the AC97 DAP _FS line
|
of the GPIO corresponding with the AC97 DAP _FS line
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
ac97@70002000 {
|
ac97@70002000 {
|
||||||
compatible = "nvidia,tegra20-ac97";
|
compatible = "nvidia,tegra20-ac97";
|
||||||
reg = <0x70002000 0x200>;
|
reg = <0x70002000 0x200>;
|
||||||
interrupts = <0 81 0x04>;
|
interrupts = <0 81 0x04>;
|
||||||
nvidia,dma-request-selector = <&apbdma 12>;
|
|
||||||
nvidia,codec-reset-gpio = <&gpio 170 0>;
|
nvidia,codec-reset-gpio = <&gpio 170 0>;
|
||||||
nvidia,codec-sync-gpio = <&gpio 120 0>;
|
nvidia,codec-sync-gpio = <&gpio 120 0>;
|
||||||
|
clocks = <&tegra_car 3>;
|
||||||
|
resets = <&tegra_car 3>;
|
||||||
|
reset-names = "ac97";
|
||||||
|
dmas = <&apbdma 12>, <&apbdma 12>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,17 @@ Required properties:
|
|||||||
- compatible : "nvidia,tegra20-i2s"
|
- compatible : "nvidia,tegra20-i2s"
|
||||||
- reg : Should contain I2S registers location and length
|
- reg : Should contain I2S registers location and length
|
||||||
- interrupts : Should contain I2S interrupt
|
- interrupts : Should contain I2S interrupt
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
request selector for this I2S controller
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- i2s
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -13,5 +22,9 @@ i2s@70002800 {
|
|||||||
compatible = "nvidia,tegra20-i2s";
|
compatible = "nvidia,tegra20-i2s";
|
||||||
reg = <0x70002800 0x200>;
|
reg = <0x70002800 0x200>;
|
||||||
interrupts = < 45 >;
|
interrupts = < 45 >;
|
||||||
nvidia,dma-request-selector = < &apbdma 2 >;
|
clocks = <&tegra_car 11>;
|
||||||
|
resets = <&tegra_car 11>;
|
||||||
|
reset-names = "i2s";
|
||||||
|
dmas = <&apbdma 21>, <&apbdma 21>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
};
|
};
|
||||||
|
@ -7,18 +7,48 @@ Required properties:
|
|||||||
- Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
|
- Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
|
||||||
- Tegra114 requires an additional entry, for the APBIF2 register block.
|
- Tegra114 requires an additional entry, for the APBIF2 register block.
|
||||||
- interrupts : Should contain AHUB interrupt
|
- interrupts : Should contain AHUB interrupt
|
||||||
- nvidia,dma-request-selector : A list of the DMA channel specifiers. Each
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
entry contains the Tegra DMA controller's phandle and request selector.
|
See ../clocks/clock-bindings.txt for details.
|
||||||
If a single entry is present, the request selectors for the channels are
|
|
||||||
assumed to be contiguous, and increment from this value.
|
|
||||||
If multiple values are given, one value must be given per channel.
|
|
||||||
- clocks : Must contain an entry for each required entry in clock-names.
|
|
||||||
- clock-names : Must include the following entries:
|
- clock-names : Must include the following entries:
|
||||||
- Tegra30: Requires d_audio, apbif, i2s0, i2s1, i2s2, i2s3, i2s4, dam0,
|
- d_audio
|
||||||
dam1, dam2, spdif_in.
|
- apbif
|
||||||
- Tegra114: Additionally requires amx, adx.
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
Tegra30 and later:
|
||||||
|
- d_audio
|
||||||
|
- apbif
|
||||||
|
- i2s0
|
||||||
|
- i2s1
|
||||||
|
- i2s2
|
||||||
|
- i2s3
|
||||||
|
- i2s4
|
||||||
|
- dam0
|
||||||
|
- dam1
|
||||||
|
- dam2
|
||||||
|
- spdif
|
||||||
|
Tegra114 and later additionally require:
|
||||||
|
- amx
|
||||||
|
- adx
|
||||||
|
Tegra124 and later additionally require:
|
||||||
|
- amx1
|
||||||
|
- adx1
|
||||||
|
- afc0
|
||||||
|
- afc1
|
||||||
|
- afc2
|
||||||
|
- afc3
|
||||||
|
- afc4
|
||||||
|
- afc5
|
||||||
- ranges : The bus address mapping for the configlink register bus.
|
- ranges : The bus address mapping for the configlink register bus.
|
||||||
Can be empty since the mapping is 1:1.
|
Can be empty since the mapping is 1:1.
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx0 .. rx<n>
|
||||||
|
- tx0 .. tx<n>
|
||||||
|
... where n is:
|
||||||
|
Tegra30: 3
|
||||||
|
Tegra114, Tegra124: 9
|
||||||
- #address-cells : For the configlink bus. Should be <1>;
|
- #address-cells : For the configlink bus. Should be <1>;
|
||||||
- #size-cells : For the configlink bus. Should be <1>.
|
- #size-cells : For the configlink bus. Should be <1>.
|
||||||
|
|
||||||
@ -35,13 +65,20 @@ ahub@70080000 {
|
|||||||
reg = <0x70080000 0x200 0x70080200 0x100>;
|
reg = <0x70080000 0x200 0x70080200 0x100>;
|
||||||
interrupts = < 0 103 0x04 >;
|
interrupts = < 0 103 0x04 >;
|
||||||
nvidia,dma-request-selector = <&apbdma 1>;
|
nvidia,dma-request-selector = <&apbdma 1>;
|
||||||
clocks = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
|
clocks = <&tegra_car 106>, <&tegra_car 107>;
|
||||||
|
clock-names = "d_audio", "apbif";
|
||||||
|
resets = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
|
||||||
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
|
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
|
||||||
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
|
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
|
||||||
<&tegra_car 110>, <&tegra_car 162>;
|
<&tegra_car 110>, <&tegra_car 10>;
|
||||||
clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
||||||
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
||||||
"spdif_in";
|
"spdif";
|
||||||
|
dmas = <&apbdma 1>, <&apbdma 1>;
|
||||||
|
<&apbdma 2>, <&apbdma 2>;
|
||||||
|
<&apbdma 3>, <&apbdma 3>;
|
||||||
|
<&apbdma 4>, <&apbdma 4>;
|
||||||
|
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3";
|
||||||
ranges;
|
ranges;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
@ -3,13 +3,22 @@ NVIDIA Tegra30 I2S controller
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible : "nvidia,tegra30-i2s"
|
- compatible : "nvidia,tegra30-i2s"
|
||||||
- reg : Should contain I2S registers location and length
|
- reg : Should contain I2S registers location and length
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- i2s
|
||||||
- nvidia,ahub-cif-ids : The list of AHUB CIF IDs for this port, rx (playback)
|
- nvidia,ahub-cif-ids : The list of AHUB CIF IDs for this port, rx (playback)
|
||||||
first, tx (capture) second. See nvidia,tegra30-ahub.txt for values.
|
first, tx (capture) second. See nvidia,tegra30-ahub.txt for values.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
i2s@70002800 {
|
i2s@70080300 {
|
||||||
compatible = "nvidia,tegra30-i2s";
|
compatible = "nvidia,tegra30-i2s";
|
||||||
reg = <0x70080300 0x100>;
|
reg = <0x70080300 0x100>;
|
||||||
nvidia,ahub-cif-ids = <4 4>;
|
nvidia,ahub-cif-ids = <4 4>;
|
||||||
|
clocks = <&tegra_car 11>;
|
||||||
|
resets = <&tegra_car 11>;
|
||||||
|
reset-names = "i2s";
|
||||||
};
|
};
|
||||||
|
@ -4,10 +4,19 @@ Required properties:
|
|||||||
- compatible : should be "nvidia,tegra114-spi".
|
- compatible : should be "nvidia,tegra114-spi".
|
||||||
- reg: Should contain SPI registers location and length.
|
- reg: Should contain SPI registers location and length.
|
||||||
- interrupts: Should contain SPI interrupts.
|
- interrupts: Should contain SPI interrupts.
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- clock-names : Must include the following entries:
|
||||||
request selector for this SPI controller.
|
- spi
|
||||||
- This is also require clock named "spi" as per binding document
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- spi
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
- clocks : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
|
||||||
Recommended properties:
|
Recommended properties:
|
||||||
- spi-max-frequency: Definition as per
|
- spi-max-frequency: Definition as per
|
||||||
@ -18,9 +27,14 @@ spi@7000d600 {
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000d600 0x200>;
|
reg = <0x7000d600 0x200>;
|
||||||
interrupts = <0 82 0x04>;
|
interrupts = <0 82 0x04>;
|
||||||
nvidia,dma-request-selector = <&apbdma 16>;
|
|
||||||
spi-max-frequency = <25000000>;
|
spi-max-frequency = <25000000>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
clocks = <&tegra_car 44>;
|
||||||
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 44>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,17 @@ Required properties:
|
|||||||
- compatible : should be "nvidia,tegra20-sflash".
|
- compatible : should be "nvidia,tegra20-sflash".
|
||||||
- reg: Should contain SFLASH registers location and length.
|
- reg: Should contain SFLASH registers location and length.
|
||||||
- interrupts: Should contain SFLASH interrupts.
|
- interrupts: Should contain SFLASH interrupts.
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- clocks : Must contain one entry, for the module clock.
|
||||||
request selector for this SFLASH controller.
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- spi
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
|
||||||
Recommended properties:
|
Recommended properties:
|
||||||
- spi-max-frequency: Definition as per
|
- spi-max-frequency: Definition as per
|
||||||
@ -17,10 +26,13 @@ spi@7000c380 {
|
|||||||
compatible = "nvidia,tegra20-sflash";
|
compatible = "nvidia,tegra20-sflash";
|
||||||
reg = <0x7000c380 0x80>;
|
reg = <0x7000c380 0x80>;
|
||||||
interrupts = <0 39 0x04>;
|
interrupts = <0 39 0x04>;
|
||||||
nvidia,dma-request-selector = <&apbdma 16>;
|
|
||||||
spi-max-frequency = <25000000>;
|
spi-max-frequency = <25000000>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
clocks = <&tegra_car 43>;
|
||||||
|
resets = <&tegra_car 43>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 11>, <&apbdma 11>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,8 +4,17 @@ Required properties:
|
|||||||
- compatible : should be "nvidia,tegra20-slink", "nvidia,tegra30-slink".
|
- compatible : should be "nvidia,tegra20-slink", "nvidia,tegra30-slink".
|
||||||
- reg: Should contain SLINK registers location and length.
|
- reg: Should contain SLINK registers location and length.
|
||||||
- interrupts: Should contain SLINK interrupts.
|
- interrupts: Should contain SLINK interrupts.
|
||||||
- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
|
- clocks : Must contain one entry, for the module clock.
|
||||||
request selector for this SLINK controller.
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- spi
|
||||||
|
- dmas : Must contain an entry for each entry in clock-names.
|
||||||
|
See ../dma/dma.txt for details.
|
||||||
|
- dma-names : Must include the following entries:
|
||||||
|
- rx
|
||||||
|
- tx
|
||||||
|
|
||||||
Recommended properties:
|
Recommended properties:
|
||||||
- spi-max-frequency: Definition as per
|
- spi-max-frequency: Definition as per
|
||||||
@ -17,10 +26,13 @@ spi@7000d600 {
|
|||||||
compatible = "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d600 0x200>;
|
reg = <0x7000d600 0x200>;
|
||||||
interrupts = <0 82 0x04>;
|
interrupts = <0 82 0x04>;
|
||||||
nvidia,dma-request-selector = <&apbdma 16>;
|
|
||||||
spi-max-frequency = <25000000>;
|
spi-max-frequency = <25000000>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
clocks = <&tegra_car 44>;
|
||||||
|
resets = <&tegra_car 44>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ Required properties:
|
|||||||
- compatible : should be "nvidia,tegra20-timer".
|
- compatible : should be "nvidia,tegra20-timer".
|
||||||
- reg : Specifies base physical address and size of the registers.
|
- reg : Specifies base physical address and size of the registers.
|
||||||
- interrupts : A list of 4 interrupts; one per timer channel.
|
- interrupts : A list of 4 interrupts; one per timer channel.
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -18,4 +20,5 @@ timer {
|
|||||||
0 1 0x04
|
0 1 0x04
|
||||||
0 41 0x04
|
0 41 0x04
|
||||||
0 42 0x04>;
|
0 42 0x04>;
|
||||||
|
clocks = <&tegra_car 132>;
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,8 @@ Required properties:
|
|||||||
- reg : Specifies base physical address and size of the registers.
|
- reg : Specifies base physical address and size of the registers.
|
||||||
- interrupts : A list of 6 interrupts; one per each of timer channels 1
|
- interrupts : A list of 6 interrupts; one per each of timer channels 1
|
||||||
through 5, and one for the shared interrupt for the remaining channels.
|
through 5, and one for the shared interrupt for the remaining channels.
|
||||||
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
|
||||||
timer {
|
timer {
|
||||||
compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
|
compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
|
||||||
@ -20,4 +22,5 @@ timer {
|
|||||||
0 42 0x04
|
0 42 0x04
|
||||||
0 121 0x04
|
0 121 0x04
|
||||||
0 122 0x04>;
|
0 122 0x04>;
|
||||||
|
clocks = <&tegra_car 214>;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,12 @@ and additions :
|
|||||||
Required properties :
|
Required properties :
|
||||||
- compatible : Should be "nvidia,tegra20-ehci".
|
- compatible : Should be "nvidia,tegra20-ehci".
|
||||||
- nvidia,phy : phandle of the PHY that the controller is connected to.
|
- nvidia,phy : phandle of the PHY that the controller is connected to.
|
||||||
- clocks : Contains a single entry which defines the USB controller's clock.
|
- clocks : Must contain one entry, for the module clock.
|
||||||
|
See ../clocks/clock-bindings.txt for details.
|
||||||
|
- resets : Must contain an entry for each entry in reset-names.
|
||||||
|
See ../reset/reset.txt for details.
|
||||||
|
- reset-names : Must include the following entries:
|
||||||
|
- usb
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- nvidia,needs-double-reset : boolean is to be set for some of the Tegra20
|
- nvidia,needs-double-reset : boolean is to be set for some of the Tegra20
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
compatible = "nvidia,tegra114-car";
|
compatible = "nvidia,tegra114-car";
|
||||||
reg = <0x60006000 0x1000>;
|
reg = <0x60006000 0x1000>;
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
apbdma: dma {
|
apbdma: dma {
|
||||||
@ -81,6 +82,9 @@
|
|||||||
<GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
<GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_APBDMA>;
|
clocks = <&tegra_car TEGRA114_CLK_APBDMA>;
|
||||||
|
resets = <&tegra_car 34>;
|
||||||
|
reset-names = "dma";
|
||||||
|
#dma-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
ahb: ahb {
|
ahb: ahb {
|
||||||
@ -124,9 +128,12 @@
|
|||||||
reg = <0x70006000 0x40>;
|
reg = <0x70006000 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 8>;
|
|
||||||
status = "disabled";
|
|
||||||
clocks = <&tegra_car TEGRA114_CLK_UARTA>;
|
clocks = <&tegra_car TEGRA114_CLK_UARTA>;
|
||||||
|
resets = <&tegra_car 6>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 8>, <&apbdma 8>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
uartb: serial@70006040 {
|
uartb: serial@70006040 {
|
||||||
@ -134,9 +141,12 @@
|
|||||||
reg = <0x70006040 0x40>;
|
reg = <0x70006040 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 9>;
|
|
||||||
status = "disabled";
|
|
||||||
clocks = <&tegra_car TEGRA114_CLK_UARTB>;
|
clocks = <&tegra_car TEGRA114_CLK_UARTB>;
|
||||||
|
resets = <&tegra_car 7>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 9>, <&apbdma 9>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
uartc: serial@70006200 {
|
uartc: serial@70006200 {
|
||||||
@ -144,9 +154,12 @@
|
|||||||
reg = <0x70006200 0x100>;
|
reg = <0x70006200 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 10>;
|
|
||||||
status = "disabled";
|
|
||||||
clocks = <&tegra_car TEGRA114_CLK_UARTC>;
|
clocks = <&tegra_car TEGRA114_CLK_UARTC>;
|
||||||
|
resets = <&tegra_car 55>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 10>, <&apbdma 10>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
uartd: serial@70006300 {
|
uartd: serial@70006300 {
|
||||||
@ -154,9 +167,12 @@
|
|||||||
reg = <0x70006300 0x100>;
|
reg = <0x70006300 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 19>;
|
|
||||||
status = "disabled";
|
|
||||||
clocks = <&tegra_car TEGRA114_CLK_UARTD>;
|
clocks = <&tegra_car TEGRA114_CLK_UARTD>;
|
||||||
|
resets = <&tegra_car 65>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 19>, <&apbdma 19>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
pwm: pwm {
|
pwm: pwm {
|
||||||
@ -164,6 +180,8 @@
|
|||||||
reg = <0x7000a000 0x100>;
|
reg = <0x7000a000 0x100>;
|
||||||
#pwm-cells = <2>;
|
#pwm-cells = <2>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_PWM>;
|
clocks = <&tegra_car TEGRA114_CLK_PWM>;
|
||||||
|
resets = <&tegra_car 17>;
|
||||||
|
reset-names = "pwm";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -175,6 +193,10 @@
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2C1>;
|
clocks = <&tegra_car TEGRA114_CLK_I2C1>;
|
||||||
clock-names = "div-clk";
|
clock-names = "div-clk";
|
||||||
|
resets = <&tegra_car 12>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 21>, <&apbdma 21>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -186,6 +208,10 @@
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2C2>;
|
clocks = <&tegra_car TEGRA114_CLK_I2C2>;
|
||||||
clock-names = "div-clk";
|
clock-names = "div-clk";
|
||||||
|
resets = <&tegra_car 54>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 22>, <&apbdma 22>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -197,6 +223,10 @@
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2C3>;
|
clocks = <&tegra_car TEGRA114_CLK_I2C3>;
|
||||||
clock-names = "div-clk";
|
clock-names = "div-clk";
|
||||||
|
resets = <&tegra_car 67>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 23>, <&apbdma 23>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -208,6 +238,10 @@
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2C4>;
|
clocks = <&tegra_car TEGRA114_CLK_I2C4>;
|
||||||
clock-names = "div-clk";
|
clock-names = "div-clk";
|
||||||
|
resets = <&tegra_car 103>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 26>, <&apbdma 26>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -219,6 +253,10 @@
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2C5>;
|
clocks = <&tegra_car TEGRA114_CLK_I2C5>;
|
||||||
clock-names = "div-clk";
|
clock-names = "div-clk";
|
||||||
|
resets = <&tegra_car 47>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 24>, <&apbdma 24>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -226,11 +264,14 @@
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000d400 0x200>;
|
reg = <0x7000d400 0x200>;
|
||||||
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 15>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SBC1>;
|
clocks = <&tegra_car TEGRA114_CLK_SBC1>;
|
||||||
clock-names = "spi";
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 41>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 15>, <&apbdma 15>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -238,11 +279,14 @@
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000d600 0x200>;
|
reg = <0x7000d600 0x200>;
|
||||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 16>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SBC2>;
|
clocks = <&tegra_car TEGRA114_CLK_SBC2>;
|
||||||
clock-names = "spi";
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 44>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,11 +294,14 @@
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000d800 0x200>;
|
reg = <0x7000d800 0x200>;
|
||||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 17>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SBC3>;
|
clocks = <&tegra_car TEGRA114_CLK_SBC3>;
|
||||||
clock-names = "spi";
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 46>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 17>, <&apbdma 17>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -262,11 +309,14 @@
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000da00 0x200>;
|
reg = <0x7000da00 0x200>;
|
||||||
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 18>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SBC4>;
|
clocks = <&tegra_car TEGRA114_CLK_SBC4>;
|
||||||
clock-names = "spi";
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 68>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 18>, <&apbdma 18>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -274,11 +324,14 @@
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000dc00 0x200>;
|
reg = <0x7000dc00 0x200>;
|
||||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 27>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SBC5>;
|
clocks = <&tegra_car TEGRA114_CLK_SBC5>;
|
||||||
clock-names = "spi";
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 104>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 27>, <&apbdma 27>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -286,11 +339,14 @@
|
|||||||
compatible = "nvidia,tegra114-spi";
|
compatible = "nvidia,tegra114-spi";
|
||||||
reg = <0x7000de00 0x200>;
|
reg = <0x7000de00 0x200>;
|
||||||
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 28>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SBC6>;
|
clocks = <&tegra_car TEGRA114_CLK_SBC6>;
|
||||||
clock-names = "spi";
|
clock-names = "spi";
|
||||||
|
resets = <&tegra_car 105>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 28>, <&apbdma 28>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -306,6 +362,8 @@
|
|||||||
reg = <0x7000e200 0x100>;
|
reg = <0x7000e200 0x100>;
|
||||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_KBC>;
|
clocks = <&tegra_car TEGRA114_CLK_KBC>;
|
||||||
|
resets = <&tegra_car 36>;
|
||||||
|
reset-names = "kbc";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -333,26 +391,39 @@
|
|||||||
<0x70080200 0x100>,
|
<0x70080200 0x100>,
|
||||||
<0x70081000 0x200>;
|
<0x70081000 0x200>;
|
||||||
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 1>, <&apbdma 2>,
|
|
||||||
<&apbdma 3>, <&apbdma 4>, <&apbdma 6>, <&apbdma 7>,
|
|
||||||
<&apbdma 12>, <&apbdma 13>, <&apbdma 14>,
|
|
||||||
<&apbdma 29>;
|
|
||||||
clocks = <&tegra_car TEGRA114_CLK_D_AUDIO>,
|
clocks = <&tegra_car TEGRA114_CLK_D_AUDIO>,
|
||||||
<&tegra_car TEGRA114_CLK_APBIF>,
|
<&tegra_car TEGRA114_CLK_APBIF>;
|
||||||
<&tegra_car TEGRA114_CLK_I2S0>,
|
clock-names = "d_audio", "apbif";
|
||||||
<&tegra_car TEGRA114_CLK_I2S1>,
|
resets = <&tegra_car 106>, /* d_audio */
|
||||||
<&tegra_car TEGRA114_CLK_I2S2>,
|
<&tegra_car 107>, /* apbif */
|
||||||
<&tegra_car TEGRA114_CLK_I2S3>,
|
<&tegra_car 30>, /* i2s0 */
|
||||||
<&tegra_car TEGRA114_CLK_I2S4>,
|
<&tegra_car 11>, /* i2s1 */
|
||||||
<&tegra_car TEGRA114_CLK_DAM0>,
|
<&tegra_car 18>, /* i2s2 */
|
||||||
<&tegra_car TEGRA114_CLK_DAM1>,
|
<&tegra_car 101>, /* i2s3 */
|
||||||
<&tegra_car TEGRA114_CLK_DAM2>,
|
<&tegra_car 102>, /* i2s4 */
|
||||||
<&tegra_car TEGRA114_CLK_SPDIF_IN>,
|
<&tegra_car 108>, /* dam0 */
|
||||||
<&tegra_car TEGRA114_CLK_AMX>,
|
<&tegra_car 109>, /* dam1 */
|
||||||
<&tegra_car TEGRA114_CLK_ADX>;
|
<&tegra_car 110>, /* dam2 */
|
||||||
clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
<&tegra_car 10>, /* spdif */
|
||||||
|
<&tegra_car 153>, /* amx */
|
||||||
|
<&tegra_car 154>; /* adx */
|
||||||
|
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
||||||
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
||||||
"spdif_in", "amx", "adx";
|
"spdif", "amx", "adx";
|
||||||
|
dmas = <&apbdma 1>, <&apbdma 1>,
|
||||||
|
<&apbdma 2>, <&apbdma 2>,
|
||||||
|
<&apbdma 3>, <&apbdma 3>,
|
||||||
|
<&apbdma 4>, <&apbdma 4>,
|
||||||
|
<&apbdma 6>, <&apbdma 6>,
|
||||||
|
<&apbdma 7>, <&apbdma 7>,
|
||||||
|
<&apbdma 12>, <&apbdma 12>,
|
||||||
|
<&apbdma 13>, <&apbdma 13>,
|
||||||
|
<&apbdma 14>, <&apbdma 14>,
|
||||||
|
<&apbdma 29>, <&apbdma 29>;
|
||||||
|
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2",
|
||||||
|
"rx3", "tx3", "rx4", "tx4", "rx5", "tx5",
|
||||||
|
"rx6", "tx6", "rx7", "tx7", "rx8", "tx8",
|
||||||
|
"rx9", "tx9";
|
||||||
ranges;
|
ranges;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
@ -362,6 +433,8 @@
|
|||||||
reg = <0x70080300 0x100>;
|
reg = <0x70080300 0x100>;
|
||||||
nvidia,ahub-cif-ids = <4 4>;
|
nvidia,ahub-cif-ids = <4 4>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2S0>;
|
clocks = <&tegra_car TEGRA114_CLK_I2S0>;
|
||||||
|
resets = <&tegra_car 30>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,6 +443,8 @@
|
|||||||
reg = <0x70080400 0x100>;
|
reg = <0x70080400 0x100>;
|
||||||
nvidia,ahub-cif-ids = <5 5>;
|
nvidia,ahub-cif-ids = <5 5>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2S1>;
|
clocks = <&tegra_car TEGRA114_CLK_I2S1>;
|
||||||
|
resets = <&tegra_car 11>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -378,6 +453,8 @@
|
|||||||
reg = <0x70080500 0x100>;
|
reg = <0x70080500 0x100>;
|
||||||
nvidia,ahub-cif-ids = <6 6>;
|
nvidia,ahub-cif-ids = <6 6>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2S2>;
|
clocks = <&tegra_car TEGRA114_CLK_I2S2>;
|
||||||
|
resets = <&tegra_car 18>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -386,6 +463,8 @@
|
|||||||
reg = <0x70080600 0x100>;
|
reg = <0x70080600 0x100>;
|
||||||
nvidia,ahub-cif-ids = <7 7>;
|
nvidia,ahub-cif-ids = <7 7>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2S3>;
|
clocks = <&tegra_car TEGRA114_CLK_I2S3>;
|
||||||
|
resets = <&tegra_car 101>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -394,6 +473,8 @@
|
|||||||
reg = <0x70080700 0x100>;
|
reg = <0x70080700 0x100>;
|
||||||
nvidia,ahub-cif-ids = <8 8>;
|
nvidia,ahub-cif-ids = <8 8>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_I2S4>;
|
clocks = <&tegra_car TEGRA114_CLK_I2S4>;
|
||||||
|
resets = <&tegra_car 102>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -403,6 +484,8 @@
|
|||||||
reg = <0x78000000 0x200>;
|
reg = <0x78000000 0x200>;
|
||||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SDMMC1>;
|
clocks = <&tegra_car TEGRA114_CLK_SDMMC1>;
|
||||||
|
resets = <&tegra_car 14>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disable";
|
status = "disable";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -411,6 +494,8 @@
|
|||||||
reg = <0x78000200 0x200>;
|
reg = <0x78000200 0x200>;
|
||||||
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SDMMC2>;
|
clocks = <&tegra_car TEGRA114_CLK_SDMMC2>;
|
||||||
|
resets = <&tegra_car 9>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disable";
|
status = "disable";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -419,6 +504,8 @@
|
|||||||
reg = <0x78000400 0x200>;
|
reg = <0x78000400 0x200>;
|
||||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SDMMC3>;
|
clocks = <&tegra_car TEGRA114_CLK_SDMMC3>;
|
||||||
|
resets = <&tegra_car 69>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disable";
|
status = "disable";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -427,6 +514,8 @@
|
|||||||
reg = <0x78000600 0x200>;
|
reg = <0x78000600 0x200>;
|
||||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA114_CLK_SDMMC4>;
|
clocks = <&tegra_car TEGRA114_CLK_SDMMC4>;
|
||||||
|
resets = <&tegra_car 15>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disable";
|
status = "disable";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -436,6 +525,8 @@
|
|||||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "utmi";
|
phy_type = "utmi";
|
||||||
clocks = <&tegra_car TEGRA114_CLK_USBD>;
|
clocks = <&tegra_car TEGRA114_CLK_USBD>;
|
||||||
|
resets = <&tegra_car 22>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,phy = <&phy1>;
|
nvidia,phy = <&phy1>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@ -467,6 +558,8 @@
|
|||||||
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "utmi";
|
phy_type = "utmi";
|
||||||
clocks = <&tegra_car TEGRA114_CLK_USB3>;
|
clocks = <&tegra_car TEGRA114_CLK_USB3>;
|
||||||
|
resets = <&tegra_car 59>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,phy = <&phy3>;
|
nvidia,phy = <&phy3>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -280,6 +280,8 @@
|
|||||||
clocks = <&tegra_car TEGRA20_CLK_I2C3>,
|
clocks = <&tegra_car TEGRA20_CLK_I2C3>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 67>;
|
||||||
|
reset-names = "i2c";
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c@7000d000 {
|
i2c@7000d000 {
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
|
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
|
||||||
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
|
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
|
||||||
clocks = <&tegra_car TEGRA20_CLK_HOST1X>;
|
clocks = <&tegra_car TEGRA20_CLK_HOST1X>;
|
||||||
|
resets = <&tegra_car 28>;
|
||||||
|
reset-names = "host1x";
|
||||||
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
@ -33,6 +35,8 @@
|
|||||||
reg = <0x54040000 0x00040000>;
|
reg = <0x54040000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_MPE>;
|
clocks = <&tegra_car TEGRA20_CLK_MPE>;
|
||||||
|
resets = <&tegra_car 60>;
|
||||||
|
reset-names = "mpe";
|
||||||
};
|
};
|
||||||
|
|
||||||
vi {
|
vi {
|
||||||
@ -40,6 +44,8 @@
|
|||||||
reg = <0x54080000 0x00040000>;
|
reg = <0x54080000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_VI>;
|
clocks = <&tegra_car TEGRA20_CLK_VI>;
|
||||||
|
resets = <&tegra_car 20>;
|
||||||
|
reset-names = "vi";
|
||||||
};
|
};
|
||||||
|
|
||||||
epp {
|
epp {
|
||||||
@ -47,6 +53,8 @@
|
|||||||
reg = <0x540c0000 0x00040000>;
|
reg = <0x540c0000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_EPP>;
|
clocks = <&tegra_car TEGRA20_CLK_EPP>;
|
||||||
|
resets = <&tegra_car 19>;
|
||||||
|
reset-names = "epp";
|
||||||
};
|
};
|
||||||
|
|
||||||
isp {
|
isp {
|
||||||
@ -54,6 +62,8 @@
|
|||||||
reg = <0x54100000 0x00040000>;
|
reg = <0x54100000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_ISP>;
|
clocks = <&tegra_car TEGRA20_CLK_ISP>;
|
||||||
|
resets = <&tegra_car 23>;
|
||||||
|
reset-names = "isp";
|
||||||
};
|
};
|
||||||
|
|
||||||
gr2d {
|
gr2d {
|
||||||
@ -61,12 +71,16 @@
|
|||||||
reg = <0x54140000 0x00040000>;
|
reg = <0x54140000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_GR2D>;
|
clocks = <&tegra_car TEGRA20_CLK_GR2D>;
|
||||||
|
resets = <&tegra_car 21>;
|
||||||
|
reset-names = "2d";
|
||||||
};
|
};
|
||||||
|
|
||||||
gr3d {
|
gr3d {
|
||||||
compatible = "nvidia,tegra20-gr3d";
|
compatible = "nvidia,tegra20-gr3d";
|
||||||
reg = <0x54180000 0x00040000>;
|
reg = <0x54180000 0x00040000>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_GR3D>;
|
clocks = <&tegra_car TEGRA20_CLK_GR3D>;
|
||||||
|
resets = <&tegra_car 24>;
|
||||||
|
reset-names = "3d";
|
||||||
};
|
};
|
||||||
|
|
||||||
dc@54200000 {
|
dc@54200000 {
|
||||||
@ -75,7 +89,9 @@
|
|||||||
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_DISP1>,
|
clocks = <&tegra_car TEGRA20_CLK_DISP1>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P>;
|
<&tegra_car TEGRA20_CLK_PLL_P>;
|
||||||
clock-names = "disp1", "parent";
|
clock-names = "dc", "parent";
|
||||||
|
resets = <&tegra_car 27>;
|
||||||
|
reset-names = "dc";
|
||||||
|
|
||||||
rgb {
|
rgb {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -88,7 +104,9 @@
|
|||||||
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_DISP2>,
|
clocks = <&tegra_car TEGRA20_CLK_DISP2>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P>;
|
<&tegra_car TEGRA20_CLK_PLL_P>;
|
||||||
clock-names = "disp2", "parent";
|
clock-names = "dc", "parent";
|
||||||
|
resets = <&tegra_car 26>;
|
||||||
|
reset-names = "dc";
|
||||||
|
|
||||||
rgb {
|
rgb {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -102,6 +120,8 @@
|
|||||||
clocks = <&tegra_car TEGRA20_CLK_HDMI>,
|
clocks = <&tegra_car TEGRA20_CLK_HDMI>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
|
<&tegra_car TEGRA20_CLK_PLL_D_OUT0>;
|
||||||
clock-names = "hdmi", "parent";
|
clock-names = "hdmi", "parent";
|
||||||
|
resets = <&tegra_car 51>;
|
||||||
|
reset-names = "hdmi";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,6 +137,8 @@
|
|||||||
compatible = "nvidia,tegra20-dsi";
|
compatible = "nvidia,tegra20-dsi";
|
||||||
reg = <0x54300000 0x00040000>;
|
reg = <0x54300000 0x00040000>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_DSI>;
|
clocks = <&tegra_car TEGRA20_CLK_DSI>;
|
||||||
|
resets = <&tegra_car 48>;
|
||||||
|
reset-names = "dsi";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -160,6 +182,7 @@
|
|||||||
compatible = "nvidia,tegra20-car";
|
compatible = "nvidia,tegra20-car";
|
||||||
reg = <0x60006000 0x1000>;
|
reg = <0x60006000 0x1000>;
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
apbdma: dma {
|
apbdma: dma {
|
||||||
@ -182,6 +205,9 @@
|
|||||||
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
|
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
|
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_APBDMA>;
|
clocks = <&tegra_car TEGRA20_CLK_APBDMA>;
|
||||||
|
resets = <&tegra_car 34>;
|
||||||
|
reset-names = "dma";
|
||||||
|
#dma-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
ahb {
|
ahb {
|
||||||
@ -222,8 +248,11 @@
|
|||||||
compatible = "nvidia,tegra20-ac97";
|
compatible = "nvidia,tegra20-ac97";
|
||||||
reg = <0x70002000 0x200>;
|
reg = <0x70002000 0x200>;
|
||||||
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 12>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_AC97>;
|
clocks = <&tegra_car TEGRA20_CLK_AC97>;
|
||||||
|
resets = <&tegra_car 3>;
|
||||||
|
reset-names = "ac97";
|
||||||
|
dmas = <&apbdma 12>, <&apbdma 12>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -231,8 +260,11 @@
|
|||||||
compatible = "nvidia,tegra20-i2s";
|
compatible = "nvidia,tegra20-i2s";
|
||||||
reg = <0x70002800 0x200>;
|
reg = <0x70002800 0x200>;
|
||||||
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 2>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_I2S1>;
|
clocks = <&tegra_car TEGRA20_CLK_I2S1>;
|
||||||
|
resets = <&tegra_car 11>;
|
||||||
|
reset-names = "i2s";
|
||||||
|
dmas = <&apbdma 2>, <&apbdma 2>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -240,8 +272,11 @@
|
|||||||
compatible = "nvidia,tegra20-i2s";
|
compatible = "nvidia,tegra20-i2s";
|
||||||
reg = <0x70002a00 0x200>;
|
reg = <0x70002a00 0x200>;
|
||||||
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 1>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_I2S2>;
|
clocks = <&tegra_car TEGRA20_CLK_I2S2>;
|
||||||
|
resets = <&tegra_car 18>;
|
||||||
|
reset-names = "i2s";
|
||||||
|
dmas = <&apbdma 1>, <&apbdma 1>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -257,8 +292,11 @@
|
|||||||
reg = <0x70006000 0x40>;
|
reg = <0x70006000 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 8>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_UARTA>;
|
clocks = <&tegra_car TEGRA20_CLK_UARTA>;
|
||||||
|
resets = <&tegra_car 6>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 8>, <&apbdma 8>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -267,8 +305,11 @@
|
|||||||
reg = <0x70006040 0x40>;
|
reg = <0x70006040 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 9>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_UARTB>;
|
clocks = <&tegra_car TEGRA20_CLK_UARTB>;
|
||||||
|
resets = <&tegra_car 7>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 9>, <&apbdma 9>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -277,8 +318,11 @@
|
|||||||
reg = <0x70006200 0x100>;
|
reg = <0x70006200 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 10>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_UARTC>;
|
clocks = <&tegra_car TEGRA20_CLK_UARTC>;
|
||||||
|
resets = <&tegra_car 55>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 10>, <&apbdma 10>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -287,8 +331,11 @@
|
|||||||
reg = <0x70006300 0x100>;
|
reg = <0x70006300 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 19>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_UARTD>;
|
clocks = <&tegra_car TEGRA20_CLK_UARTD>;
|
||||||
|
resets = <&tegra_car 65>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 19>, <&apbdma 19>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -297,8 +344,11 @@
|
|||||||
reg = <0x70006400 0x100>;
|
reg = <0x70006400 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 20>;
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_UARTE>;
|
clocks = <&tegra_car TEGRA20_CLK_UARTE>;
|
||||||
|
resets = <&tegra_car 66>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 20>, <&apbdma 20>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -307,6 +357,8 @@
|
|||||||
reg = <0x7000a000 0x100>;
|
reg = <0x7000a000 0x100>;
|
||||||
#pwm-cells = <2>;
|
#pwm-cells = <2>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_PWM>;
|
clocks = <&tegra_car TEGRA20_CLK_PWM>;
|
||||||
|
resets = <&tegra_car 17>;
|
||||||
|
reset-names = "pwm";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -326,6 +378,10 @@
|
|||||||
clocks = <&tegra_car TEGRA20_CLK_I2C1>,
|
clocks = <&tegra_car TEGRA20_CLK_I2C1>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 12>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 21>, <&apbdma 21>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -333,10 +389,13 @@
|
|||||||
compatible = "nvidia,tegra20-sflash";
|
compatible = "nvidia,tegra20-sflash";
|
||||||
reg = <0x7000c380 0x80>;
|
reg = <0x7000c380 0x80>;
|
||||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 11>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SPI>;
|
clocks = <&tegra_car TEGRA20_CLK_SPI>;
|
||||||
|
resets = <&tegra_car 43>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 11>, <&apbdma 11>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -349,6 +408,10 @@
|
|||||||
clocks = <&tegra_car TEGRA20_CLK_I2C2>,
|
clocks = <&tegra_car TEGRA20_CLK_I2C2>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 54>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 22>, <&apbdma 22>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -361,6 +424,10 @@
|
|||||||
clocks = <&tegra_car TEGRA20_CLK_I2C3>,
|
clocks = <&tegra_car TEGRA20_CLK_I2C3>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 67>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 23>, <&apbdma 23>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -373,6 +440,10 @@
|
|||||||
clocks = <&tegra_car TEGRA20_CLK_DVC>,
|
clocks = <&tegra_car TEGRA20_CLK_DVC>,
|
||||||
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 47>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 24>, <&apbdma 24>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -380,10 +451,13 @@
|
|||||||
compatible = "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d400 0x200>;
|
reg = <0x7000d400 0x200>;
|
||||||
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 15>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SBC1>;
|
clocks = <&tegra_car TEGRA20_CLK_SBC1>;
|
||||||
|
resets = <&tegra_car 41>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 15>, <&apbdma 15>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -391,10 +465,13 @@
|
|||||||
compatible = "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d600 0x200>;
|
reg = <0x7000d600 0x200>;
|
||||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 16>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SBC2>;
|
clocks = <&tegra_car TEGRA20_CLK_SBC2>;
|
||||||
|
resets = <&tegra_car 44>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -402,10 +479,13 @@
|
|||||||
compatible = "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d800 0x200>;
|
reg = <0x7000d800 0x200>;
|
||||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 17>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SBC3>;
|
clocks = <&tegra_car TEGRA20_CLK_SBC3>;
|
||||||
|
resets = <&tegra_car 46>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 17>, <&apbdma 17>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -413,10 +493,13 @@
|
|||||||
compatible = "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra20-slink";
|
||||||
reg = <0x7000da00 0x200>;
|
reg = <0x7000da00 0x200>;
|
||||||
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 18>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SBC4>;
|
clocks = <&tegra_car TEGRA20_CLK_SBC4>;
|
||||||
|
resets = <&tegra_car 68>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 18>, <&apbdma 18>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -425,6 +508,8 @@
|
|||||||
reg = <0x7000e200 0x100>;
|
reg = <0x7000e200 0x100>;
|
||||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_KBC>;
|
clocks = <&tegra_car TEGRA20_CLK_KBC>;
|
||||||
|
resets = <&tegra_car 36>;
|
||||||
|
reset-names = "kbc";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -478,9 +563,12 @@
|
|||||||
|
|
||||||
clocks = <&tegra_car TEGRA20_CLK_PEX>,
|
clocks = <&tegra_car TEGRA20_CLK_PEX>,
|
||||||
<&tegra_car TEGRA20_CLK_AFI>,
|
<&tegra_car TEGRA20_CLK_AFI>,
|
||||||
<&tegra_car TEGRA20_CLK_PCIE_XCLK>,
|
|
||||||
<&tegra_car TEGRA20_CLK_PLL_E>;
|
<&tegra_car TEGRA20_CLK_PLL_E>;
|
||||||
clock-names = "pex", "afi", "pcie_xclk", "pll_e";
|
clock-names = "pex", "afi", "pll_e";
|
||||||
|
resets = <&tegra_car 70>,
|
||||||
|
<&tegra_car 72>,
|
||||||
|
<&tegra_car 74>;
|
||||||
|
reset-names = "pex", "afi", "pcie_x";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
pci@1,0 {
|
pci@1,0 {
|
||||||
@ -517,6 +605,8 @@
|
|||||||
phy_type = "utmi";
|
phy_type = "utmi";
|
||||||
nvidia,has-legacy-mode;
|
nvidia,has-legacy-mode;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_USBD>;
|
clocks = <&tegra_car TEGRA20_CLK_USBD>;
|
||||||
|
resets = <&tegra_car 22>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,needs-double-reset;
|
nvidia,needs-double-reset;
|
||||||
nvidia,phy = <&phy1>;
|
nvidia,phy = <&phy1>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -548,6 +638,8 @@
|
|||||||
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "ulpi";
|
phy_type = "ulpi";
|
||||||
clocks = <&tegra_car TEGRA20_CLK_USB2>;
|
clocks = <&tegra_car TEGRA20_CLK_USB2>;
|
||||||
|
resets = <&tegra_car 58>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,phy = <&phy2>;
|
nvidia,phy = <&phy2>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@ -569,6 +661,8 @@
|
|||||||
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "utmi";
|
phy_type = "utmi";
|
||||||
clocks = <&tegra_car TEGRA20_CLK_USB3>;
|
clocks = <&tegra_car TEGRA20_CLK_USB3>;
|
||||||
|
resets = <&tegra_car 59>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,phy = <&phy3>;
|
nvidia,phy = <&phy3>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@ -597,6 +691,8 @@
|
|||||||
reg = <0xc8000000 0x200>;
|
reg = <0xc8000000 0x200>;
|
||||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SDMMC1>;
|
clocks = <&tegra_car TEGRA20_CLK_SDMMC1>;
|
||||||
|
resets = <&tegra_car 14>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -605,6 +701,8 @@
|
|||||||
reg = <0xc8000200 0x200>;
|
reg = <0xc8000200 0x200>;
|
||||||
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SDMMC2>;
|
clocks = <&tegra_car TEGRA20_CLK_SDMMC2>;
|
||||||
|
resets = <&tegra_car 9>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -613,6 +711,8 @@
|
|||||||
reg = <0xc8000400 0x200>;
|
reg = <0xc8000400 0x200>;
|
||||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SDMMC3>;
|
clocks = <&tegra_car TEGRA20_CLK_SDMMC3>;
|
||||||
|
resets = <&tegra_car 69>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -621,6 +721,8 @@
|
|||||||
reg = <0xc8000600 0x200>;
|
reg = <0xc8000600 0x200>;
|
||||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA20_CLK_SDMMC4>;
|
clocks = <&tegra_car TEGRA20_CLK_SDMMC4>;
|
||||||
|
resets = <&tegra_car 15>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,10 +40,13 @@
|
|||||||
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_PCIE>,
|
clocks = <&tegra_car TEGRA30_CLK_PCIE>,
|
||||||
<&tegra_car TEGRA30_CLK_AFI>,
|
<&tegra_car TEGRA30_CLK_AFI>,
|
||||||
<&tegra_car TEGRA30_CLK_PCIEX>,
|
|
||||||
<&tegra_car TEGRA30_CLK_PLL_E>,
|
<&tegra_car TEGRA30_CLK_PLL_E>,
|
||||||
<&tegra_car TEGRA30_CLK_CML0>;
|
<&tegra_car TEGRA30_CLK_CML0>;
|
||||||
clock-names = "pex", "afi", "pcie_xclk", "pll_e", "cml";
|
clock-names = "pex", "afi", "pll_e", "cml";
|
||||||
|
resets = <&tegra_car 70>,
|
||||||
|
<&tegra_car 72>,
|
||||||
|
<&tegra_car 74>;
|
||||||
|
reset-names = "pex", "afi", "pcie_x";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
pci@1,0 {
|
pci@1,0 {
|
||||||
@ -92,6 +95,8 @@
|
|||||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
|
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
|
||||||
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
|
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
|
||||||
clocks = <&tegra_car TEGRA30_CLK_HOST1X>;
|
clocks = <&tegra_car TEGRA30_CLK_HOST1X>;
|
||||||
|
resets = <&tegra_car 28>;
|
||||||
|
reset-names = "host1x";
|
||||||
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
@ -103,6 +108,8 @@
|
|||||||
reg = <0x54040000 0x00040000>;
|
reg = <0x54040000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_MPE>;
|
clocks = <&tegra_car TEGRA30_CLK_MPE>;
|
||||||
|
resets = <&tegra_car 60>;
|
||||||
|
reset-names = "mpe";
|
||||||
};
|
};
|
||||||
|
|
||||||
vi {
|
vi {
|
||||||
@ -110,6 +117,8 @@
|
|||||||
reg = <0x54080000 0x00040000>;
|
reg = <0x54080000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_VI>;
|
clocks = <&tegra_car TEGRA30_CLK_VI>;
|
||||||
|
resets = <&tegra_car 20>;
|
||||||
|
reset-names = "vi";
|
||||||
};
|
};
|
||||||
|
|
||||||
epp {
|
epp {
|
||||||
@ -117,6 +126,8 @@
|
|||||||
reg = <0x540c0000 0x00040000>;
|
reg = <0x540c0000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_EPP>;
|
clocks = <&tegra_car TEGRA30_CLK_EPP>;
|
||||||
|
resets = <&tegra_car 19>;
|
||||||
|
reset-names = "epp";
|
||||||
};
|
};
|
||||||
|
|
||||||
isp {
|
isp {
|
||||||
@ -124,12 +135,16 @@
|
|||||||
reg = <0x54100000 0x00040000>;
|
reg = <0x54100000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_ISP>;
|
clocks = <&tegra_car TEGRA30_CLK_ISP>;
|
||||||
|
resets = <&tegra_car 23>;
|
||||||
|
reset-names = "isp";
|
||||||
};
|
};
|
||||||
|
|
||||||
gr2d {
|
gr2d {
|
||||||
compatible = "nvidia,tegra30-gr2d";
|
compatible = "nvidia,tegra30-gr2d";
|
||||||
reg = <0x54140000 0x00040000>;
|
reg = <0x54140000 0x00040000>;
|
||||||
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
resets = <&tegra_car 21>;
|
||||||
|
reset-names = "2d";
|
||||||
clocks = <&tegra_car TEGRA30_CLK_GR2D>;
|
clocks = <&tegra_car TEGRA30_CLK_GR2D>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,6 +154,9 @@
|
|||||||
clocks = <&tegra_car TEGRA30_CLK_GR3D
|
clocks = <&tegra_car TEGRA30_CLK_GR3D
|
||||||
&tegra_car TEGRA30_CLK_GR3D2>;
|
&tegra_car TEGRA30_CLK_GR3D2>;
|
||||||
clock-names = "3d", "3d2";
|
clock-names = "3d", "3d2";
|
||||||
|
resets = <&tegra_car 24>,
|
||||||
|
<&tegra_car 98>;
|
||||||
|
reset-names = "3d", "3d2";
|
||||||
};
|
};
|
||||||
|
|
||||||
dc@54200000 {
|
dc@54200000 {
|
||||||
@ -147,7 +165,9 @@
|
|||||||
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_DISP1>,
|
clocks = <&tegra_car TEGRA30_CLK_DISP1>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P>;
|
<&tegra_car TEGRA30_CLK_PLL_P>;
|
||||||
clock-names = "disp1", "parent";
|
clock-names = "dc", "parent";
|
||||||
|
resets = <&tegra_car 27>;
|
||||||
|
reset-names = "dc";
|
||||||
|
|
||||||
rgb {
|
rgb {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -160,7 +180,9 @@
|
|||||||
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_DISP2>,
|
clocks = <&tegra_car TEGRA30_CLK_DISP2>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P>;
|
<&tegra_car TEGRA30_CLK_PLL_P>;
|
||||||
clock-names = "disp2", "parent";
|
clock-names = "dc", "parent";
|
||||||
|
resets = <&tegra_car 26>;
|
||||||
|
reset-names = "dc";
|
||||||
|
|
||||||
rgb {
|
rgb {
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -174,6 +196,8 @@
|
|||||||
clocks = <&tegra_car TEGRA30_CLK_HDMI>,
|
clocks = <&tegra_car TEGRA30_CLK_HDMI>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_D2_OUT0>;
|
<&tegra_car TEGRA30_CLK_PLL_D2_OUT0>;
|
||||||
clock-names = "hdmi", "parent";
|
clock-names = "hdmi", "parent";
|
||||||
|
resets = <&tegra_car 51>;
|
||||||
|
reset-names = "hdmi";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -189,6 +213,8 @@
|
|||||||
compatible = "nvidia,tegra30-dsi";
|
compatible = "nvidia,tegra30-dsi";
|
||||||
reg = <0x54300000 0x00040000>;
|
reg = <0x54300000 0x00040000>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_DSIA>;
|
clocks = <&tegra_car TEGRA30_CLK_DSIA>;
|
||||||
|
resets = <&tegra_car 48>;
|
||||||
|
reset-names = "dsi";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -234,6 +260,7 @@
|
|||||||
compatible = "nvidia,tegra30-car";
|
compatible = "nvidia,tegra30-car";
|
||||||
reg = <0x60006000 0x1000>;
|
reg = <0x60006000 0x1000>;
|
||||||
#clock-cells = <1>;
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
apbdma: dma {
|
apbdma: dma {
|
||||||
@ -272,6 +299,9 @@
|
|||||||
<GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
<GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_APBDMA>;
|
clocks = <&tegra_car TEGRA30_CLK_APBDMA>;
|
||||||
|
resets = <&tegra_car 34>;
|
||||||
|
reset-names = "dma";
|
||||||
|
#dma-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
ahb: ahb {
|
ahb: ahb {
|
||||||
@ -315,8 +345,11 @@
|
|||||||
reg = <0x70006000 0x40>;
|
reg = <0x70006000 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 8>;
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_UARTA>;
|
clocks = <&tegra_car TEGRA30_CLK_UARTA>;
|
||||||
|
resets = <&tegra_car 6>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 8>, <&apbdma 8>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -325,8 +358,11 @@
|
|||||||
reg = <0x70006040 0x40>;
|
reg = <0x70006040 0x40>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 9>;
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_UARTB>;
|
clocks = <&tegra_car TEGRA30_CLK_UARTB>;
|
||||||
|
resets = <&tegra_car 7>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 9>, <&apbdma 9>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -335,8 +371,11 @@
|
|||||||
reg = <0x70006200 0x100>;
|
reg = <0x70006200 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 10>;
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_UARTC>;
|
clocks = <&tegra_car TEGRA30_CLK_UARTC>;
|
||||||
|
resets = <&tegra_car 55>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 10>, <&apbdma 10>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -345,8 +384,11 @@
|
|||||||
reg = <0x70006300 0x100>;
|
reg = <0x70006300 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 19>;
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_UARTD>;
|
clocks = <&tegra_car TEGRA30_CLK_UARTD>;
|
||||||
|
resets = <&tegra_car 65>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 19>, <&apbdma 19>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -355,8 +397,11 @@
|
|||||||
reg = <0x70006400 0x100>;
|
reg = <0x70006400 0x100>;
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 20>;
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_UARTE>;
|
clocks = <&tegra_car TEGRA30_CLK_UARTE>;
|
||||||
|
resets = <&tegra_car 66>;
|
||||||
|
reset-names = "serial";
|
||||||
|
dmas = <&apbdma 20>, <&apbdma 20>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -365,6 +410,8 @@
|
|||||||
reg = <0x7000a000 0x100>;
|
reg = <0x7000a000 0x100>;
|
||||||
#pwm-cells = <2>;
|
#pwm-cells = <2>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_PWM>;
|
clocks = <&tegra_car TEGRA30_CLK_PWM>;
|
||||||
|
resets = <&tegra_car 17>;
|
||||||
|
reset-names = "pwm";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -384,6 +431,10 @@
|
|||||||
clocks = <&tegra_car TEGRA30_CLK_I2C1>,
|
clocks = <&tegra_car TEGRA30_CLK_I2C1>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 12>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 21>, <&apbdma 21>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -396,6 +447,10 @@
|
|||||||
clocks = <&tegra_car TEGRA30_CLK_I2C2>,
|
clocks = <&tegra_car TEGRA30_CLK_I2C2>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 54>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 22>, <&apbdma 22>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -408,6 +463,10 @@
|
|||||||
clocks = <&tegra_car TEGRA30_CLK_I2C3>,
|
clocks = <&tegra_car TEGRA30_CLK_I2C3>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 67>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 23>, <&apbdma 23>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -419,7 +478,11 @@
|
|||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_I2C4>,
|
clocks = <&tegra_car TEGRA30_CLK_I2C4>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||||
|
resets = <&tegra_car 103>;
|
||||||
|
reset-names = "i2c";
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
dmas = <&apbdma 26>, <&apbdma 26>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -432,6 +495,10 @@
|
|||||||
clocks = <&tegra_car TEGRA30_CLK_I2C5>,
|
clocks = <&tegra_car TEGRA30_CLK_I2C5>,
|
||||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||||
clock-names = "div-clk", "fast-clk";
|
clock-names = "div-clk", "fast-clk";
|
||||||
|
resets = <&tegra_car 47>;
|
||||||
|
reset-names = "i2c";
|
||||||
|
dmas = <&apbdma 24>, <&apbdma 24>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -439,10 +506,13 @@
|
|||||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d400 0x200>;
|
reg = <0x7000d400 0x200>;
|
||||||
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 15>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SBC1>;
|
clocks = <&tegra_car TEGRA30_CLK_SBC1>;
|
||||||
|
resets = <&tegra_car 41>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 15>, <&apbdma 15>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -450,10 +520,13 @@
|
|||||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d600 0x200>;
|
reg = <0x7000d600 0x200>;
|
||||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 16>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SBC2>;
|
clocks = <&tegra_car TEGRA30_CLK_SBC2>;
|
||||||
|
resets = <&tegra_car 44>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -461,10 +534,13 @@
|
|||||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||||
reg = <0x7000d800 0x200>;
|
reg = <0x7000d800 0x200>;
|
||||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 17>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SBC3>;
|
clocks = <&tegra_car TEGRA30_CLK_SBC3>;
|
||||||
|
resets = <&tegra_car 46>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 17>, <&apbdma 17>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -472,10 +548,13 @@
|
|||||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||||
reg = <0x7000da00 0x200>;
|
reg = <0x7000da00 0x200>;
|
||||||
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 18>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SBC4>;
|
clocks = <&tegra_car TEGRA30_CLK_SBC4>;
|
||||||
|
resets = <&tegra_car 68>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 18>, <&apbdma 18>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -483,10 +562,13 @@
|
|||||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||||
reg = <0x7000dc00 0x200>;
|
reg = <0x7000dc00 0x200>;
|
||||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 27>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SBC5>;
|
clocks = <&tegra_car TEGRA30_CLK_SBC5>;
|
||||||
|
resets = <&tegra_car 104>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 27>, <&apbdma 27>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -494,10 +576,13 @@
|
|||||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||||
reg = <0x7000de00 0x200>;
|
reg = <0x7000de00 0x200>;
|
||||||
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 28>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SBC6>;
|
clocks = <&tegra_car TEGRA30_CLK_SBC6>;
|
||||||
|
resets = <&tegra_car 106>;
|
||||||
|
reset-names = "spi";
|
||||||
|
dmas = <&apbdma 28>, <&apbdma 28>;
|
||||||
|
dma-names = "rx", "tx";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -506,6 +591,8 @@
|
|||||||
reg = <0x7000e200 0x100>;
|
reg = <0x7000e200 0x100>;
|
||||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_KBC>;
|
clocks = <&tegra_car TEGRA30_CLK_KBC>;
|
||||||
|
resets = <&tegra_car 36>;
|
||||||
|
reset-names = "kbc";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -540,21 +627,29 @@
|
|||||||
reg = <0x70080000 0x200
|
reg = <0x70080000 0x200
|
||||||
0x70080200 0x100>;
|
0x70080200 0x100>;
|
||||||
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
nvidia,dma-request-selector = <&apbdma 1>;
|
|
||||||
clocks = <&tegra_car TEGRA30_CLK_D_AUDIO>,
|
clocks = <&tegra_car TEGRA30_CLK_D_AUDIO>,
|
||||||
<&tegra_car TEGRA30_CLK_APBIF>,
|
<&tegra_car TEGRA30_CLK_APBIF>;
|
||||||
<&tegra_car TEGRA30_CLK_I2S0>,
|
clock-names = "d_audio", "apbif";
|
||||||
<&tegra_car TEGRA30_CLK_I2S1>,
|
resets = <&tegra_car 106>, /* d_audio */
|
||||||
<&tegra_car TEGRA30_CLK_I2S2>,
|
<&tegra_car 107>, /* apbif */
|
||||||
<&tegra_car TEGRA30_CLK_I2S3>,
|
<&tegra_car 30>, /* i2s0 */
|
||||||
<&tegra_car TEGRA30_CLK_I2S4>,
|
<&tegra_car 11>, /* i2s1 */
|
||||||
<&tegra_car TEGRA30_CLK_DAM0>,
|
<&tegra_car 18>, /* i2s2 */
|
||||||
<&tegra_car TEGRA30_CLK_DAM1>,
|
<&tegra_car 101>, /* i2s3 */
|
||||||
<&tegra_car TEGRA30_CLK_DAM2>,
|
<&tegra_car 102>, /* i2s4 */
|
||||||
<&tegra_car TEGRA30_CLK_SPDIF_IN>;
|
<&tegra_car 108>, /* dam0 */
|
||||||
clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
<&tegra_car 109>, /* dam1 */
|
||||||
|
<&tegra_car 110>, /* dam2 */
|
||||||
|
<&tegra_car 10>; /* spdif */
|
||||||
|
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
||||||
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
||||||
"spdif_in";
|
"spdif";
|
||||||
|
dmas = <&apbdma 1>, <&apbdma 1>,
|
||||||
|
<&apbdma 2>, <&apbdma 2>,
|
||||||
|
<&apbdma 3>, <&apbdma 3>,
|
||||||
|
<&apbdma 4>, <&apbdma 4>;
|
||||||
|
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2",
|
||||||
|
"rx3", "tx3";
|
||||||
ranges;
|
ranges;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
@ -564,6 +659,8 @@
|
|||||||
reg = <0x70080300 0x100>;
|
reg = <0x70080300 0x100>;
|
||||||
nvidia,ahub-cif-ids = <4 4>;
|
nvidia,ahub-cif-ids = <4 4>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_I2S0>;
|
clocks = <&tegra_car TEGRA30_CLK_I2S0>;
|
||||||
|
resets = <&tegra_car 30>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -572,6 +669,8 @@
|
|||||||
reg = <0x70080400 0x100>;
|
reg = <0x70080400 0x100>;
|
||||||
nvidia,ahub-cif-ids = <5 5>;
|
nvidia,ahub-cif-ids = <5 5>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_I2S1>;
|
clocks = <&tegra_car TEGRA30_CLK_I2S1>;
|
||||||
|
resets = <&tegra_car 11>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -580,6 +679,8 @@
|
|||||||
reg = <0x70080500 0x100>;
|
reg = <0x70080500 0x100>;
|
||||||
nvidia,ahub-cif-ids = <6 6>;
|
nvidia,ahub-cif-ids = <6 6>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_I2S2>;
|
clocks = <&tegra_car TEGRA30_CLK_I2S2>;
|
||||||
|
resets = <&tegra_car 18>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -588,6 +689,8 @@
|
|||||||
reg = <0x70080600 0x100>;
|
reg = <0x70080600 0x100>;
|
||||||
nvidia,ahub-cif-ids = <7 7>;
|
nvidia,ahub-cif-ids = <7 7>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_I2S3>;
|
clocks = <&tegra_car TEGRA30_CLK_I2S3>;
|
||||||
|
resets = <&tegra_car 101>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -596,6 +699,8 @@
|
|||||||
reg = <0x70080700 0x100>;
|
reg = <0x70080700 0x100>;
|
||||||
nvidia,ahub-cif-ids = <8 8>;
|
nvidia,ahub-cif-ids = <8 8>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_I2S4>;
|
clocks = <&tegra_car TEGRA30_CLK_I2S4>;
|
||||||
|
resets = <&tegra_car 102>;
|
||||||
|
reset-names = "i2s";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -605,6 +710,8 @@
|
|||||||
reg = <0x78000000 0x200>;
|
reg = <0x78000000 0x200>;
|
||||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC1>;
|
clocks = <&tegra_car TEGRA30_CLK_SDMMC1>;
|
||||||
|
resets = <&tegra_car 14>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -613,6 +720,8 @@
|
|||||||
reg = <0x78000200 0x200>;
|
reg = <0x78000200 0x200>;
|
||||||
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC2>;
|
clocks = <&tegra_car TEGRA30_CLK_SDMMC2>;
|
||||||
|
resets = <&tegra_car 9>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -621,6 +730,8 @@
|
|||||||
reg = <0x78000400 0x200>;
|
reg = <0x78000400 0x200>;
|
||||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC3>;
|
clocks = <&tegra_car TEGRA30_CLK_SDMMC3>;
|
||||||
|
resets = <&tegra_car 69>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -629,6 +740,8 @@
|
|||||||
reg = <0x78000600 0x200>;
|
reg = <0x78000600 0x200>;
|
||||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC4>;
|
clocks = <&tegra_car TEGRA30_CLK_SDMMC4>;
|
||||||
|
resets = <&tegra_car 15>;
|
||||||
|
reset-names = "sdhci";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -638,6 +751,8 @@
|
|||||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "utmi";
|
phy_type = "utmi";
|
||||||
clocks = <&tegra_car TEGRA30_CLK_USBD>;
|
clocks = <&tegra_car TEGRA30_CLK_USBD>;
|
||||||
|
resets = <&tegra_car 22>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,needs-double-reset;
|
nvidia,needs-double-reset;
|
||||||
nvidia,phy = <&phy1>;
|
nvidia,phy = <&phy1>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@ -671,6 +786,8 @@
|
|||||||
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "ulpi";
|
phy_type = "ulpi";
|
||||||
clocks = <&tegra_car TEGRA30_CLK_USB2>;
|
clocks = <&tegra_car TEGRA30_CLK_USB2>;
|
||||||
|
resets = <&tegra_car 58>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,phy = <&phy2>;
|
nvidia,phy = <&phy2>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@ -692,6 +809,8 @@
|
|||||||
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
phy_type = "utmi";
|
phy_type = "utmi";
|
||||||
clocks = <&tegra_car TEGRA30_CLK_USB3>;
|
clocks = <&tegra_car TEGRA30_CLK_USB3>;
|
||||||
|
resets = <&tegra_car 59>;
|
||||||
|
reset-names = "usb";
|
||||||
nvidia,phy = <&phy3>;
|
nvidia,phy = <&phy3>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,8 @@ config ARCH_TEGRA
|
|||||||
select MIGHT_HAVE_CACHE_L2X0
|
select MIGHT_HAVE_CACHE_L2X0
|
||||||
select MIGHT_HAVE_PCI
|
select MIGHT_HAVE_PCI
|
||||||
select PINCTRL
|
select PINCTRL
|
||||||
|
select ARCH_HAS_RESET_CONTROLLER
|
||||||
|
select RESET_CONTROLLER
|
||||||
select SOC_BUS
|
select SOC_BUS
|
||||||
select SPARSE_IRQ
|
select SPARSE_IRQ
|
||||||
select USB_ARCH_HAS_EHCI if USB_SUPPORT
|
select USB_ARCH_HAS_EHCI if USB_SUPPORT
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/clk/tegra.h>
|
#include <linux/clk/tegra.h>
|
||||||
@ -33,6 +34,10 @@
|
|||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
|
|
||||||
|
#define DPD_SAMPLE 0x020
|
||||||
|
#define DPD_SAMPLE_ENABLE (1 << 0)
|
||||||
|
#define DPD_SAMPLE_DISABLE (0 << 0)
|
||||||
|
|
||||||
#define PWRGATE_TOGGLE 0x30
|
#define PWRGATE_TOGGLE 0x30
|
||||||
#define PWRGATE_TOGGLE_START (1 << 8)
|
#define PWRGATE_TOGGLE_START (1 << 8)
|
||||||
|
|
||||||
@ -40,6 +45,19 @@
|
|||||||
|
|
||||||
#define PWRGATE_STATUS 0x38
|
#define PWRGATE_STATUS 0x38
|
||||||
|
|
||||||
|
#define IO_DPD_REQ 0x1b8
|
||||||
|
#define IO_DPD_REQ_CODE_IDLE (0 << 30)
|
||||||
|
#define IO_DPD_REQ_CODE_OFF (1 << 30)
|
||||||
|
#define IO_DPD_REQ_CODE_ON (2 << 30)
|
||||||
|
#define IO_DPD_REQ_CODE_MASK (3 << 30)
|
||||||
|
|
||||||
|
#define IO_DPD_STATUS 0x1bc
|
||||||
|
#define IO_DPD2_REQ 0x1c0
|
||||||
|
#define IO_DPD2_STATUS 0x1c4
|
||||||
|
#define SEL_DPD_TIM 0x1c8
|
||||||
|
|
||||||
|
#define GPU_RG_CNTRL 0x2d4
|
||||||
|
|
||||||
static int tegra_num_powerdomains;
|
static int tegra_num_powerdomains;
|
||||||
static int tegra_num_cpu_domains;
|
static int tegra_num_cpu_domains;
|
||||||
static const u8 *tegra_cpu_domains;
|
static const u8 *tegra_cpu_domains;
|
||||||
@ -58,6 +76,13 @@ static const u8 tegra114_cpu_domains[] = {
|
|||||||
TEGRA_POWERGATE_CPU3,
|
TEGRA_POWERGATE_CPU3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const u8 tegra124_cpu_domains[] = {
|
||||||
|
TEGRA_POWERGATE_CPU0,
|
||||||
|
TEGRA_POWERGATE_CPU1,
|
||||||
|
TEGRA_POWERGATE_CPU2,
|
||||||
|
TEGRA_POWERGATE_CPU3,
|
||||||
|
};
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(tegra_powergate_lock);
|
static DEFINE_SPINLOCK(tegra_powergate_lock);
|
||||||
|
|
||||||
static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
|
static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
|
||||||
@ -108,6 +133,7 @@ int tegra_powergate_power_off(int id)
|
|||||||
|
|
||||||
return tegra_powergate_set(id, false);
|
return tegra_powergate_set(id, false);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(tegra_powergate_power_off);
|
||||||
|
|
||||||
int tegra_powergate_is_powered(int id)
|
int tegra_powergate_is_powered(int id)
|
||||||
{
|
{
|
||||||
@ -127,13 +153,24 @@ int tegra_powergate_remove_clamping(int id)
|
|||||||
if (id < 0 || id >= tegra_num_powerdomains)
|
if (id < 0 || id >= tegra_num_powerdomains)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Tegra124 GPU has a separate register (with different semantics)
|
||||||
|
* to remove clamps.
|
||||||
|
*/
|
||||||
|
if (tegra_chip_id == TEGRA124) {
|
||||||
|
if (id == TEGRA_POWERGATE_3D) {
|
||||||
|
pmc_write(0, GPU_RG_CNTRL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tegra 2 has a bug where PCIE and VDE clamping masks are
|
* Tegra 2 has a bug where PCIE and VDE clamping masks are
|
||||||
* swapped relatively to the partition ids
|
* swapped relatively to the partition ids
|
||||||
*/
|
*/
|
||||||
if (id == TEGRA_POWERGATE_VDEC)
|
if (id == TEGRA_POWERGATE_VDEC)
|
||||||
mask = (1 << TEGRA_POWERGATE_PCIE);
|
mask = (1 << TEGRA_POWERGATE_PCIE);
|
||||||
else if (id == TEGRA_POWERGATE_PCIE)
|
else if (id == TEGRA_POWERGATE_PCIE)
|
||||||
mask = (1 << TEGRA_POWERGATE_VDEC);
|
mask = (1 << TEGRA_POWERGATE_VDEC);
|
||||||
else
|
else
|
||||||
mask = (1 << id);
|
mask = (1 << id);
|
||||||
@ -142,13 +179,15 @@ int tegra_powergate_remove_clamping(int id)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
|
||||||
|
|
||||||
/* Must be called with clk disabled, and returns with clk enabled */
|
/* Must be called with clk disabled, and returns with clk enabled */
|
||||||
int tegra_powergate_sequence_power_up(int id, struct clk *clk)
|
int tegra_powergate_sequence_power_up(int id, struct clk *clk,
|
||||||
|
struct reset_control *rst)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
tegra_periph_reset_assert(clk);
|
reset_control_assert(rst);
|
||||||
|
|
||||||
ret = tegra_powergate_power_on(id);
|
ret = tegra_powergate_power_on(id);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -165,7 +204,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk)
|
|||||||
goto err_clamp;
|
goto err_clamp;
|
||||||
|
|
||||||
udelay(10);
|
udelay(10);
|
||||||
tegra_periph_reset_deassert(clk);
|
reset_control_deassert(rst);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -202,6 +241,11 @@ int __init tegra_powergate_init(void)
|
|||||||
tegra_num_cpu_domains = 4;
|
tegra_num_cpu_domains = 4;
|
||||||
tegra_cpu_domains = tegra114_cpu_domains;
|
tegra_cpu_domains = tegra114_cpu_domains;
|
||||||
break;
|
break;
|
||||||
|
case TEGRA124:
|
||||||
|
tegra_num_powerdomains = 25;
|
||||||
|
tegra_num_cpu_domains = 4;
|
||||||
|
tegra_cpu_domains = tegra124_cpu_domains;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown Tegra variant. Disable powergating */
|
/* Unknown Tegra variant. Disable powergating */
|
||||||
tegra_num_powerdomains = 0;
|
tegra_num_powerdomains = 0;
|
||||||
@ -243,7 +287,7 @@ static const char * const powergate_name_t30[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char * const powergate_name_t114[] = {
|
static const char * const powergate_name_t114[] = {
|
||||||
[TEGRA_POWERGATE_CPU] = "cpu0",
|
[TEGRA_POWERGATE_CPU] = "crail",
|
||||||
[TEGRA_POWERGATE_3D] = "3d",
|
[TEGRA_POWERGATE_3D] = "3d",
|
||||||
[TEGRA_POWERGATE_VENC] = "venc",
|
[TEGRA_POWERGATE_VENC] = "venc",
|
||||||
[TEGRA_POWERGATE_VDEC] = "vdec",
|
[TEGRA_POWERGATE_VDEC] = "vdec",
|
||||||
@ -263,6 +307,33 @@ static const char * const powergate_name_t114[] = {
|
|||||||
[TEGRA_POWERGATE_XUSBC] = "xusbc",
|
[TEGRA_POWERGATE_XUSBC] = "xusbc",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const powergate_name_t124[] = {
|
||||||
|
[TEGRA_POWERGATE_CPU] = "crail",
|
||||||
|
[TEGRA_POWERGATE_3D] = "3d",
|
||||||
|
[TEGRA_POWERGATE_VENC] = "venc",
|
||||||
|
[TEGRA_POWERGATE_PCIE] = "pcie",
|
||||||
|
[TEGRA_POWERGATE_VDEC] = "vdec",
|
||||||
|
[TEGRA_POWERGATE_L2] = "l2",
|
||||||
|
[TEGRA_POWERGATE_MPE] = "mpe",
|
||||||
|
[TEGRA_POWERGATE_HEG] = "heg",
|
||||||
|
[TEGRA_POWERGATE_SATA] = "sata",
|
||||||
|
[TEGRA_POWERGATE_CPU1] = "cpu1",
|
||||||
|
[TEGRA_POWERGATE_CPU2] = "cpu2",
|
||||||
|
[TEGRA_POWERGATE_CPU3] = "cpu3",
|
||||||
|
[TEGRA_POWERGATE_CELP] = "celp",
|
||||||
|
[TEGRA_POWERGATE_CPU0] = "cpu0",
|
||||||
|
[TEGRA_POWERGATE_C0NC] = "c0nc",
|
||||||
|
[TEGRA_POWERGATE_C1NC] = "c1nc",
|
||||||
|
[TEGRA_POWERGATE_SOR] = "sor",
|
||||||
|
[TEGRA_POWERGATE_DIS] = "dis",
|
||||||
|
[TEGRA_POWERGATE_DISB] = "disb",
|
||||||
|
[TEGRA_POWERGATE_XUSBA] = "xusba",
|
||||||
|
[TEGRA_POWERGATE_XUSBB] = "xusbb",
|
||||||
|
[TEGRA_POWERGATE_XUSBC] = "xusbc",
|
||||||
|
[TEGRA_POWERGATE_VIC] = "vic",
|
||||||
|
[TEGRA_POWERGATE_IRAM] = "iram",
|
||||||
|
};
|
||||||
|
|
||||||
static int powergate_show(struct seq_file *s, void *data)
|
static int powergate_show(struct seq_file *s, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -307,6 +378,9 @@ int __init tegra_powergate_debugfs_init(void)
|
|||||||
case TEGRA114:
|
case TEGRA114:
|
||||||
powergate_name = powergate_name_t114;
|
powergate_name = powergate_name_t114;
|
||||||
break;
|
break;
|
||||||
|
case TEGRA124:
|
||||||
|
powergate_name = powergate_name_t124;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (powergate_name) {
|
if (powergate_name) {
|
||||||
@ -320,3 +394,120 @@ int __init tegra_powergate_debugfs_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int tegra_io_rail_prepare(int id, unsigned long *request,
|
||||||
|
unsigned long *status, unsigned int *bit)
|
||||||
|
{
|
||||||
|
unsigned long rate, value;
|
||||||
|
struct clk *clk;
|
||||||
|
|
||||||
|
*bit = id % 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are two sets of 30 bits to select IO rails, but bits 30 and
|
||||||
|
* 31 are control bits rather than IO rail selection bits.
|
||||||
|
*/
|
||||||
|
if (id > 63 || *bit == 30 || *bit == 31)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (id < 32) {
|
||||||
|
*status = IO_DPD_STATUS;
|
||||||
|
*request = IO_DPD_REQ;
|
||||||
|
} else {
|
||||||
|
*status = IO_DPD2_STATUS;
|
||||||
|
*request = IO_DPD2_REQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk = clk_get_sys(NULL, "pclk");
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
return PTR_ERR(clk);
|
||||||
|
|
||||||
|
rate = clk_get_rate(clk);
|
||||||
|
clk_put(clk);
|
||||||
|
|
||||||
|
pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
|
||||||
|
|
||||||
|
/* must be at least 200 ns, in APB (PCLK) clock cycles */
|
||||||
|
value = DIV_ROUND_UP(1000000000, rate);
|
||||||
|
value = DIV_ROUND_UP(200, value);
|
||||||
|
pmc_write(value, SEL_DPD_TIM);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
|
||||||
|
unsigned long val, unsigned long timeout)
|
||||||
|
{
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
timeout = jiffies + msecs_to_jiffies(timeout);
|
||||||
|
|
||||||
|
while (time_after(timeout, jiffies)) {
|
||||||
|
value = pmc_read(offset);
|
||||||
|
if ((value & mask) == val)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usleep_range(250, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_io_rail_unprepare(void)
|
||||||
|
{
|
||||||
|
pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_io_rail_power_on(int id)
|
||||||
|
{
|
||||||
|
unsigned long request, status, value;
|
||||||
|
unsigned int bit, mask;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = tegra_io_rail_prepare(id, &request, &status, &bit);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
mask = 1 << bit;
|
||||||
|
|
||||||
|
value = pmc_read(request);
|
||||||
|
value |= mask;
|
||||||
|
value &= ~IO_DPD_REQ_CODE_MASK;
|
||||||
|
value |= IO_DPD_REQ_CODE_OFF;
|
||||||
|
pmc_write(value, request);
|
||||||
|
|
||||||
|
err = tegra_io_rail_poll(status, mask, 0, 250);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tegra_io_rail_unprepare();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_io_rail_power_off(int id)
|
||||||
|
{
|
||||||
|
unsigned long request, status, value;
|
||||||
|
unsigned int bit, mask;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = tegra_io_rail_prepare(id, &request, &status, &bit);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
mask = 1 << bit;
|
||||||
|
|
||||||
|
value = pmc_read(request);
|
||||||
|
value |= mask;
|
||||||
|
value &= ~IO_DPD_REQ_CODE_MASK;
|
||||||
|
value |= IO_DPD_REQ_CODE_ON;
|
||||||
|
pmc_write(value, request);
|
||||||
|
|
||||||
|
err = tegra_io_rail_poll(status, mask, mask, 250);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tegra_io_rail_unprepare();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,7 +6,12 @@ obj-y += clk-periph-gate.o
|
|||||||
obj-y += clk-pll.o
|
obj-y += clk-pll.o
|
||||||
obj-y += clk-pll-out.o
|
obj-y += clk-pll-out.o
|
||||||
obj-y += clk-super.o
|
obj-y += clk-super.o
|
||||||
|
obj-y += clk-tegra-audio.o
|
||||||
|
obj-y += clk-tegra-periph.o
|
||||||
|
obj-y += clk-tegra-pmc.o
|
||||||
|
obj-y += clk-tegra-fixed.o
|
||||||
|
obj-y += clk-tegra-super-gen4.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
|
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
|
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
|
||||||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
|
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
|
||||||
|
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
|
||||||
|
235
drivers/clk/tegra/clk-id.h
Normal file
235
drivers/clk/tegra/clk-id.h
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* This header provides IDs for clocks common between several Tegra SoCs
|
||||||
|
*/
|
||||||
|
#ifndef _TEGRA_CLK_ID_H
|
||||||
|
#define _TEGRA_CLK_ID_H
|
||||||
|
|
||||||
|
enum clk_id {
|
||||||
|
tegra_clk_actmon,
|
||||||
|
tegra_clk_adx,
|
||||||
|
tegra_clk_adx1,
|
||||||
|
tegra_clk_afi,
|
||||||
|
tegra_clk_amx,
|
||||||
|
tegra_clk_amx1,
|
||||||
|
tegra_clk_apbdma,
|
||||||
|
tegra_clk_apbif,
|
||||||
|
tegra_clk_audio0,
|
||||||
|
tegra_clk_audio0_2x,
|
||||||
|
tegra_clk_audio0_mux,
|
||||||
|
tegra_clk_audio1,
|
||||||
|
tegra_clk_audio1_2x,
|
||||||
|
tegra_clk_audio1_mux,
|
||||||
|
tegra_clk_audio2,
|
||||||
|
tegra_clk_audio2_2x,
|
||||||
|
tegra_clk_audio2_mux,
|
||||||
|
tegra_clk_audio3,
|
||||||
|
tegra_clk_audio3_2x,
|
||||||
|
tegra_clk_audio3_mux,
|
||||||
|
tegra_clk_audio4,
|
||||||
|
tegra_clk_audio4_2x,
|
||||||
|
tegra_clk_audio4_mux,
|
||||||
|
tegra_clk_blink,
|
||||||
|
tegra_clk_bsea,
|
||||||
|
tegra_clk_bsev,
|
||||||
|
tegra_clk_cclk_g,
|
||||||
|
tegra_clk_cclk_lp,
|
||||||
|
tegra_clk_cilab,
|
||||||
|
tegra_clk_cilcd,
|
||||||
|
tegra_clk_cile,
|
||||||
|
tegra_clk_clk_32k,
|
||||||
|
tegra_clk_clk72Mhz,
|
||||||
|
tegra_clk_clk_m,
|
||||||
|
tegra_clk_clk_m_div2,
|
||||||
|
tegra_clk_clk_m_div4,
|
||||||
|
tegra_clk_clk_out_1,
|
||||||
|
tegra_clk_clk_out_1_mux,
|
||||||
|
tegra_clk_clk_out_2,
|
||||||
|
tegra_clk_clk_out_2_mux,
|
||||||
|
tegra_clk_clk_out_3,
|
||||||
|
tegra_clk_clk_out_3_mux,
|
||||||
|
tegra_clk_cml0,
|
||||||
|
tegra_clk_cml1,
|
||||||
|
tegra_clk_csi,
|
||||||
|
tegra_clk_csite,
|
||||||
|
tegra_clk_csus,
|
||||||
|
tegra_clk_cve,
|
||||||
|
tegra_clk_dam0,
|
||||||
|
tegra_clk_dam1,
|
||||||
|
tegra_clk_dam2,
|
||||||
|
tegra_clk_d_audio,
|
||||||
|
tegra_clk_dds,
|
||||||
|
tegra_clk_dfll_ref,
|
||||||
|
tegra_clk_dfll_soc,
|
||||||
|
tegra_clk_disp1,
|
||||||
|
tegra_clk_disp2,
|
||||||
|
tegra_clk_dp2,
|
||||||
|
tegra_clk_dpaux,
|
||||||
|
tegra_clk_dsia,
|
||||||
|
tegra_clk_dsialp,
|
||||||
|
tegra_clk_dsia_mux,
|
||||||
|
tegra_clk_dsib,
|
||||||
|
tegra_clk_dsiblp,
|
||||||
|
tegra_clk_dsib_mux,
|
||||||
|
tegra_clk_dtv,
|
||||||
|
tegra_clk_emc,
|
||||||
|
tegra_clk_entropy,
|
||||||
|
tegra_clk_epp,
|
||||||
|
tegra_clk_epp_8,
|
||||||
|
tegra_clk_extern1,
|
||||||
|
tegra_clk_extern2,
|
||||||
|
tegra_clk_extern3,
|
||||||
|
tegra_clk_fuse,
|
||||||
|
tegra_clk_fuse_burn,
|
||||||
|
tegra_clk_gpu,
|
||||||
|
tegra_clk_gr2d,
|
||||||
|
tegra_clk_gr2d_8,
|
||||||
|
tegra_clk_gr3d,
|
||||||
|
tegra_clk_gr3d_8,
|
||||||
|
tegra_clk_hclk,
|
||||||
|
tegra_clk_hda,
|
||||||
|
tegra_clk_hda2codec_2x,
|
||||||
|
tegra_clk_hda2hdmi,
|
||||||
|
tegra_clk_hdmi,
|
||||||
|
tegra_clk_hdmi_audio,
|
||||||
|
tegra_clk_host1x,
|
||||||
|
tegra_clk_host1x_8,
|
||||||
|
tegra_clk_i2c1,
|
||||||
|
tegra_clk_i2c2,
|
||||||
|
tegra_clk_i2c3,
|
||||||
|
tegra_clk_i2c4,
|
||||||
|
tegra_clk_i2c5,
|
||||||
|
tegra_clk_i2c6,
|
||||||
|
tegra_clk_i2cslow,
|
||||||
|
tegra_clk_i2s0,
|
||||||
|
tegra_clk_i2s0_sync,
|
||||||
|
tegra_clk_i2s1,
|
||||||
|
tegra_clk_i2s1_sync,
|
||||||
|
tegra_clk_i2s2,
|
||||||
|
tegra_clk_i2s2_sync,
|
||||||
|
tegra_clk_i2s3,
|
||||||
|
tegra_clk_i2s3_sync,
|
||||||
|
tegra_clk_i2s4,
|
||||||
|
tegra_clk_i2s4_sync,
|
||||||
|
tegra_clk_isp,
|
||||||
|
tegra_clk_isp_8,
|
||||||
|
tegra_clk_ispb,
|
||||||
|
tegra_clk_kbc,
|
||||||
|
tegra_clk_kfuse,
|
||||||
|
tegra_clk_la,
|
||||||
|
tegra_clk_mipi,
|
||||||
|
tegra_clk_mipi_cal,
|
||||||
|
tegra_clk_mpe,
|
||||||
|
tegra_clk_mselect,
|
||||||
|
tegra_clk_msenc,
|
||||||
|
tegra_clk_ndflash,
|
||||||
|
tegra_clk_ndflash_8,
|
||||||
|
tegra_clk_ndspeed,
|
||||||
|
tegra_clk_ndspeed_8,
|
||||||
|
tegra_clk_nor,
|
||||||
|
tegra_clk_owr,
|
||||||
|
tegra_clk_pcie,
|
||||||
|
tegra_clk_pclk,
|
||||||
|
tegra_clk_pll_a,
|
||||||
|
tegra_clk_pll_a_out0,
|
||||||
|
tegra_clk_pll_c,
|
||||||
|
tegra_clk_pll_c2,
|
||||||
|
tegra_clk_pll_c3,
|
||||||
|
tegra_clk_pll_c4,
|
||||||
|
tegra_clk_pll_c_out1,
|
||||||
|
tegra_clk_pll_d,
|
||||||
|
tegra_clk_pll_d2,
|
||||||
|
tegra_clk_pll_d2_out0,
|
||||||
|
tegra_clk_pll_d_out0,
|
||||||
|
tegra_clk_pll_dp,
|
||||||
|
tegra_clk_pll_e_out0,
|
||||||
|
tegra_clk_pll_m,
|
||||||
|
tegra_clk_pll_m_out1,
|
||||||
|
tegra_clk_pll_p,
|
||||||
|
tegra_clk_pll_p_out1,
|
||||||
|
tegra_clk_pll_p_out2,
|
||||||
|
tegra_clk_pll_p_out2_int,
|
||||||
|
tegra_clk_pll_p_out3,
|
||||||
|
tegra_clk_pll_p_out4,
|
||||||
|
tegra_clk_pll_p_out5,
|
||||||
|
tegra_clk_pll_ref,
|
||||||
|
tegra_clk_pll_re_out,
|
||||||
|
tegra_clk_pll_re_vco,
|
||||||
|
tegra_clk_pll_u,
|
||||||
|
tegra_clk_pll_u_12m,
|
||||||
|
tegra_clk_pll_u_480m,
|
||||||
|
tegra_clk_pll_u_48m,
|
||||||
|
tegra_clk_pll_u_60m,
|
||||||
|
tegra_clk_pll_x,
|
||||||
|
tegra_clk_pll_x_out0,
|
||||||
|
tegra_clk_pwm,
|
||||||
|
tegra_clk_rtc,
|
||||||
|
tegra_clk_sata,
|
||||||
|
tegra_clk_sata_cold,
|
||||||
|
tegra_clk_sata_oob,
|
||||||
|
tegra_clk_sbc1,
|
||||||
|
tegra_clk_sbc1_8,
|
||||||
|
tegra_clk_sbc2,
|
||||||
|
tegra_clk_sbc2_8,
|
||||||
|
tegra_clk_sbc3,
|
||||||
|
tegra_clk_sbc3_8,
|
||||||
|
tegra_clk_sbc4,
|
||||||
|
tegra_clk_sbc4_8,
|
||||||
|
tegra_clk_sbc5,
|
||||||
|
tegra_clk_sbc5_8,
|
||||||
|
tegra_clk_sbc6,
|
||||||
|
tegra_clk_sbc6_8,
|
||||||
|
tegra_clk_sclk,
|
||||||
|
tegra_clk_sdmmc1,
|
||||||
|
tegra_clk_sdmmc2,
|
||||||
|
tegra_clk_sdmmc3,
|
||||||
|
tegra_clk_sdmmc4,
|
||||||
|
tegra_clk_se,
|
||||||
|
tegra_clk_soc_therm,
|
||||||
|
tegra_clk_sor0,
|
||||||
|
tegra_clk_sor0_lvds,
|
||||||
|
tegra_clk_spdif,
|
||||||
|
tegra_clk_spdif_2x,
|
||||||
|
tegra_clk_spdif_in,
|
||||||
|
tegra_clk_spdif_in_sync,
|
||||||
|
tegra_clk_spdif_mux,
|
||||||
|
tegra_clk_spdif_out,
|
||||||
|
tegra_clk_timer,
|
||||||
|
tegra_clk_trace,
|
||||||
|
tegra_clk_tsec,
|
||||||
|
tegra_clk_tsensor,
|
||||||
|
tegra_clk_tvdac,
|
||||||
|
tegra_clk_tvo,
|
||||||
|
tegra_clk_uarta,
|
||||||
|
tegra_clk_uartb,
|
||||||
|
tegra_clk_uartc,
|
||||||
|
tegra_clk_uartd,
|
||||||
|
tegra_clk_uarte,
|
||||||
|
tegra_clk_usb2,
|
||||||
|
tegra_clk_usb3,
|
||||||
|
tegra_clk_usbd,
|
||||||
|
tegra_clk_vcp,
|
||||||
|
tegra_clk_vde,
|
||||||
|
tegra_clk_vde_8,
|
||||||
|
tegra_clk_vfir,
|
||||||
|
tegra_clk_vi,
|
||||||
|
tegra_clk_vi_8,
|
||||||
|
tegra_clk_vi_9,
|
||||||
|
tegra_clk_vic03,
|
||||||
|
tegra_clk_vim2_clk,
|
||||||
|
tegra_clk_vimclk_sync,
|
||||||
|
tegra_clk_vi_sensor,
|
||||||
|
tegra_clk_vi_sensor2,
|
||||||
|
tegra_clk_vi_sensor_8,
|
||||||
|
tegra_clk_xusb_dev,
|
||||||
|
tegra_clk_xusb_dev_src,
|
||||||
|
tegra_clk_xusb_falcon_src,
|
||||||
|
tegra_clk_xusb_fs_src,
|
||||||
|
tegra_clk_xusb_host,
|
||||||
|
tegra_clk_xusb_host_src,
|
||||||
|
tegra_clk_xusb_hs_src,
|
||||||
|
tegra_clk_xusb_ss,
|
||||||
|
tegra_clk_xusb_ss_src,
|
||||||
|
tegra_clk_max,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _TEGRA_CLK_ID_H */
|
@ -36,8 +36,6 @@ static DEFINE_SPINLOCK(periph_ref_lock);
|
|||||||
|
|
||||||
#define read_rst(gate) \
|
#define read_rst(gate) \
|
||||||
readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
|
readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
|
||||||
#define write_rst_set(val, gate) \
|
|
||||||
writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg))
|
|
||||||
#define write_rst_clr(val, gate) \
|
#define write_rst_clr(val, gate) \
|
||||||
writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
|
writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
|
||||||
|
|
||||||
@ -123,26 +121,6 @@ static void clk_periph_disable(struct clk_hw *hw)
|
|||||||
spin_unlock_irqrestore(&periph_ref_lock, flags);
|
spin_unlock_irqrestore(&periph_ref_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert)
|
|
||||||
{
|
|
||||||
if (gate->flags & TEGRA_PERIPH_NO_RESET)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (assert) {
|
|
||||||
/*
|
|
||||||
* If peripheral is in the APB bus then read the APB bus to
|
|
||||||
* flush the write operation in apb bus. This will avoid the
|
|
||||||
* peripheral access after disabling clock
|
|
||||||
*/
|
|
||||||
if (gate->flags & TEGRA_PERIPH_ON_APB)
|
|
||||||
tegra_read_chipid();
|
|
||||||
|
|
||||||
write_rst_set(periph_clk_to_bit(gate), gate);
|
|
||||||
} else {
|
|
||||||
write_rst_clr(periph_clk_to_bit(gate), gate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct clk_ops tegra_clk_periph_gate_ops = {
|
const struct clk_ops tegra_clk_periph_gate_ops = {
|
||||||
.is_enabled = clk_periph_is_enabled,
|
.is_enabled = clk_periph_is_enabled,
|
||||||
.enable = clk_periph_enable,
|
.enable = clk_periph_enable,
|
||||||
@ -151,12 +129,16 @@ const struct clk_ops tegra_clk_periph_gate_ops = {
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_periph_gate(const char *name,
|
struct clk *tegra_clk_register_periph_gate(const char *name,
|
||||||
const char *parent_name, u8 gate_flags, void __iomem *clk_base,
|
const char *parent_name, u8 gate_flags, void __iomem *clk_base,
|
||||||
unsigned long flags, int clk_num,
|
unsigned long flags, int clk_num, int *enable_refcnt)
|
||||||
struct tegra_clk_periph_regs *pregs, int *enable_refcnt)
|
|
||||||
{
|
{
|
||||||
struct tegra_clk_periph_gate *gate;
|
struct tegra_clk_periph_gate *gate;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
struct tegra_clk_periph_regs *pregs;
|
||||||
|
|
||||||
|
pregs = get_reg_bank(clk_num);
|
||||||
|
if (!pregs)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||||
if (!gate) {
|
if (!gate) {
|
||||||
|
@ -111,46 +111,6 @@ static void clk_periph_disable(struct clk_hw *hw)
|
|||||||
gate_ops->disable(gate_hw);
|
gate_ops->disable(gate_hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tegra_periph_reset_deassert(struct clk *c)
|
|
||||||
{
|
|
||||||
struct clk_hw *hw = __clk_get_hw(c);
|
|
||||||
struct tegra_clk_periph *periph = to_clk_periph(hw);
|
|
||||||
struct tegra_clk_periph_gate *gate;
|
|
||||||
|
|
||||||
if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
|
|
||||||
gate = to_clk_periph_gate(hw);
|
|
||||||
if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
|
|
||||||
WARN_ON(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gate = &periph->gate;
|
|
||||||
}
|
|
||||||
|
|
||||||
tegra_periph_reset(gate, 0);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(tegra_periph_reset_deassert);
|
|
||||||
|
|
||||||
void tegra_periph_reset_assert(struct clk *c)
|
|
||||||
{
|
|
||||||
struct clk_hw *hw = __clk_get_hw(c);
|
|
||||||
struct tegra_clk_periph *periph = to_clk_periph(hw);
|
|
||||||
struct tegra_clk_periph_gate *gate;
|
|
||||||
|
|
||||||
if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
|
|
||||||
gate = to_clk_periph_gate(hw);
|
|
||||||
if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
|
|
||||||
WARN_ON(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gate = &periph->gate;
|
|
||||||
}
|
|
||||||
|
|
||||||
tegra_periph_reset(gate, 1);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(tegra_periph_reset_assert);
|
|
||||||
|
|
||||||
const struct clk_ops tegra_clk_periph_ops = {
|
const struct clk_ops tegra_clk_periph_ops = {
|
||||||
.get_parent = clk_periph_get_parent,
|
.get_parent = clk_periph_get_parent,
|
||||||
.set_parent = clk_periph_set_parent,
|
.set_parent = clk_periph_set_parent,
|
||||||
@ -170,27 +130,50 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
|
|||||||
.disable = clk_periph_disable,
|
.disable = clk_periph_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct clk_ops tegra_clk_periph_no_gate_ops = {
|
||||||
|
.get_parent = clk_periph_get_parent,
|
||||||
|
.set_parent = clk_periph_set_parent,
|
||||||
|
.recalc_rate = clk_periph_recalc_rate,
|
||||||
|
.round_rate = clk_periph_round_rate,
|
||||||
|
.set_rate = clk_periph_set_rate,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk *_tegra_clk_register_periph(const char *name,
|
static struct clk *_tegra_clk_register_periph(const char *name,
|
||||||
const char **parent_names, int num_parents,
|
const char **parent_names, int num_parents,
|
||||||
struct tegra_clk_periph *periph,
|
struct tegra_clk_periph *periph,
|
||||||
void __iomem *clk_base, u32 offset, bool div,
|
void __iomem *clk_base, u32 offset,
|
||||||
unsigned long flags)
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
struct tegra_clk_periph_regs *bank;
|
||||||
|
bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
|
||||||
|
|
||||||
|
if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
|
||||||
|
flags |= CLK_SET_RATE_PARENT;
|
||||||
|
init.ops = &tegra_clk_periph_nodiv_ops;
|
||||||
|
} else if (periph->gate.flags & TEGRA_PERIPH_NO_GATE)
|
||||||
|
init.ops = &tegra_clk_periph_no_gate_ops;
|
||||||
|
else
|
||||||
|
init.ops = &tegra_clk_periph_ops;
|
||||||
|
|
||||||
init.name = name;
|
init.name = name;
|
||||||
init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
|
|
||||||
init.flags = flags;
|
init.flags = flags;
|
||||||
init.parent_names = parent_names;
|
init.parent_names = parent_names;
|
||||||
init.num_parents = num_parents;
|
init.num_parents = num_parents;
|
||||||
|
|
||||||
|
bank = get_reg_bank(periph->gate.clk_num);
|
||||||
|
if (!bank)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
/* Data in .init is copied by clk_register(), so stack variable OK */
|
/* Data in .init is copied by clk_register(), so stack variable OK */
|
||||||
periph->hw.init = &init;
|
periph->hw.init = &init;
|
||||||
periph->magic = TEGRA_CLK_PERIPH_MAGIC;
|
periph->magic = TEGRA_CLK_PERIPH_MAGIC;
|
||||||
periph->mux.reg = clk_base + offset;
|
periph->mux.reg = clk_base + offset;
|
||||||
periph->divider.reg = div ? (clk_base + offset) : NULL;
|
periph->divider.reg = div ? (clk_base + offset) : NULL;
|
||||||
periph->gate.clk_base = clk_base;
|
periph->gate.clk_base = clk_base;
|
||||||
|
periph->gate.regs = bank;
|
||||||
|
periph->gate.enable_refcnt = periph_clk_enb_refcnt;
|
||||||
|
|
||||||
clk = clk_register(NULL, &periph->hw);
|
clk = clk_register(NULL, &periph->hw);
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
@ -209,7 +192,7 @@ struct clk *tegra_clk_register_periph(const char *name,
|
|||||||
u32 offset, unsigned long flags)
|
u32 offset, unsigned long flags)
|
||||||
{
|
{
|
||||||
return _tegra_clk_register_periph(name, parent_names, num_parents,
|
return _tegra_clk_register_periph(name, parent_names, num_parents,
|
||||||
periph, clk_base, offset, true, flags);
|
periph, clk_base, offset, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct clk *tegra_clk_register_periph_nodiv(const char *name,
|
struct clk *tegra_clk_register_periph_nodiv(const char *name,
|
||||||
@ -217,6 +200,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
|
|||||||
struct tegra_clk_periph *periph, void __iomem *clk_base,
|
struct tegra_clk_periph *periph, void __iomem *clk_base,
|
||||||
u32 offset)
|
u32 offset)
|
||||||
{
|
{
|
||||||
|
periph->gate.flags |= TEGRA_PERIPH_NO_DIV;
|
||||||
return _tegra_clk_register_periph(name, parent_names, num_parents,
|
return _tegra_clk_register_periph(name, parent_names, num_parents,
|
||||||
periph, clk_base, offset, false, CLK_SET_RATE_PARENT);
|
periph, clk_base, offset, CLK_SET_RATE_PARENT);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,23 @@
|
|||||||
#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
|
#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
|
||||||
|
|
||||||
#define PLLE_SS_CTRL 0x68
|
#define PLLE_SS_CTRL 0x68
|
||||||
#define PLLE_SS_DISABLE (7 << 10)
|
#define PLLE_SS_CNTL_BYPASS_SS BIT(10)
|
||||||
|
#define PLLE_SS_CNTL_INTERP_RESET BIT(11)
|
||||||
|
#define PLLE_SS_CNTL_SSC_BYP BIT(12)
|
||||||
|
#define PLLE_SS_CNTL_CENTER BIT(14)
|
||||||
|
#define PLLE_SS_CNTL_INVERT BIT(15)
|
||||||
|
#define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\
|
||||||
|
PLLE_SS_CNTL_SSC_BYP)
|
||||||
|
#define PLLE_SS_MAX_MASK 0x1ff
|
||||||
|
#define PLLE_SS_MAX_VAL 0x25
|
||||||
|
#define PLLE_SS_INC_MASK (0xff << 16)
|
||||||
|
#define PLLE_SS_INC_VAL (0x1 << 16)
|
||||||
|
#define PLLE_SS_INCINTRV_MASK (0x3f << 24)
|
||||||
|
#define PLLE_SS_INCINTRV_VAL (0x20 << 24)
|
||||||
|
#define PLLE_SS_COEFFICIENTS_MASK \
|
||||||
|
(PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK)
|
||||||
|
#define PLLE_SS_COEFFICIENTS_VAL \
|
||||||
|
(PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
|
||||||
|
|
||||||
#define PLLE_AUX_PLLP_SEL BIT(2)
|
#define PLLE_AUX_PLLP_SEL BIT(2)
|
||||||
#define PLLE_AUX_ENABLE_SWCTL BIT(4)
|
#define PLLE_AUX_ENABLE_SWCTL BIT(4)
|
||||||
@ -121,6 +137,36 @@
|
|||||||
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
|
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
|
||||||
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
|
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
|
||||||
|
|
||||||
|
#define PLLSS_MISC_KCP 0
|
||||||
|
#define PLLSS_MISC_KVCO 0
|
||||||
|
#define PLLSS_MISC_SETUP 0
|
||||||
|
#define PLLSS_EN_SDM 0
|
||||||
|
#define PLLSS_EN_SSC 0
|
||||||
|
#define PLLSS_EN_DITHER2 0
|
||||||
|
#define PLLSS_EN_DITHER 1
|
||||||
|
#define PLLSS_SDM_RESET 0
|
||||||
|
#define PLLSS_CLAMP 0
|
||||||
|
#define PLLSS_SDM_SSC_MAX 0
|
||||||
|
#define PLLSS_SDM_SSC_MIN 0
|
||||||
|
#define PLLSS_SDM_SSC_STEP 0
|
||||||
|
#define PLLSS_SDM_DIN 0
|
||||||
|
#define PLLSS_MISC_DEFAULT ((PLLSS_MISC_KCP << 25) | \
|
||||||
|
(PLLSS_MISC_KVCO << 24) | \
|
||||||
|
PLLSS_MISC_SETUP)
|
||||||
|
#define PLLSS_CFG_DEFAULT ((PLLSS_EN_SDM << 31) | \
|
||||||
|
(PLLSS_EN_SSC << 30) | \
|
||||||
|
(PLLSS_EN_DITHER2 << 29) | \
|
||||||
|
(PLLSS_EN_DITHER << 28) | \
|
||||||
|
(PLLSS_SDM_RESET) << 27 | \
|
||||||
|
(PLLSS_CLAMP << 22))
|
||||||
|
#define PLLSS_CTRL1_DEFAULT \
|
||||||
|
((PLLSS_SDM_SSC_MAX << 16) | PLLSS_SDM_SSC_MIN)
|
||||||
|
#define PLLSS_CTRL2_DEFAULT \
|
||||||
|
((PLLSS_SDM_SSC_STEP << 16) | PLLSS_SDM_DIN)
|
||||||
|
#define PLLSS_LOCK_OVERRIDE BIT(24)
|
||||||
|
#define PLLSS_REF_SRC_SEL_SHIFT 25
|
||||||
|
#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)
|
||||||
|
|
||||||
#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
|
#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
|
||||||
#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
|
#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
|
||||||
#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
|
#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
|
||||||
@ -134,7 +180,7 @@
|
|||||||
#define mask(w) ((1 << (w)) - 1)
|
#define mask(w) ((1 << (w)) - 1)
|
||||||
#define divm_mask(p) mask(p->params->div_nmp->divm_width)
|
#define divm_mask(p) mask(p->params->div_nmp->divm_width)
|
||||||
#define divn_mask(p) mask(p->params->div_nmp->divn_width)
|
#define divn_mask(p) mask(p->params->div_nmp->divn_width)
|
||||||
#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
|
#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
|
||||||
mask(p->params->div_nmp->divp_width))
|
mask(p->params->div_nmp->divp_width))
|
||||||
|
|
||||||
#define divm_max(p) (divm_mask(p))
|
#define divm_max(p) (divm_mask(p))
|
||||||
@ -154,10 +200,10 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
|
|||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
if (!(pll->flags & TEGRA_PLL_USE_LOCK))
|
if (!(pll->params->flags & TEGRA_PLL_USE_LOCK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
|
if (!(pll->params->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
val = pll_readl_misc(pll);
|
val = pll_readl_misc(pll);
|
||||||
@ -171,13 +217,13 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
|
|||||||
u32 val, lock_mask;
|
u32 val, lock_mask;
|
||||||
void __iomem *lock_addr;
|
void __iomem *lock_addr;
|
||||||
|
|
||||||
if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
|
if (!(pll->params->flags & TEGRA_PLL_USE_LOCK)) {
|
||||||
udelay(pll->params->lock_delay);
|
udelay(pll->params->lock_delay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_addr = pll->clk_base;
|
lock_addr = pll->clk_base;
|
||||||
if (pll->flags & TEGRA_PLL_LOCK_MISC)
|
if (pll->params->flags & TEGRA_PLL_LOCK_MISC)
|
||||||
lock_addr += pll->params->misc_reg;
|
lock_addr += pll->params->misc_reg;
|
||||||
else
|
else
|
||||||
lock_addr += pll->params->base_reg;
|
lock_addr += pll->params->base_reg;
|
||||||
@ -204,7 +250,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
|
|||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLLM) {
|
if (pll->params->flags & TEGRA_PLLM) {
|
||||||
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
||||||
if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
|
if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
|
||||||
return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
|
return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
|
||||||
@ -223,12 +269,12 @@ static void _clk_pll_enable(struct clk_hw *hw)
|
|||||||
clk_pll_enable_lock(pll);
|
clk_pll_enable_lock(pll);
|
||||||
|
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
if (pll->flags & TEGRA_PLL_BYPASS)
|
if (pll->params->flags & TEGRA_PLL_BYPASS)
|
||||||
val &= ~PLL_BASE_BYPASS;
|
val &= ~PLL_BASE_BYPASS;
|
||||||
val |= PLL_BASE_ENABLE;
|
val |= PLL_BASE_ENABLE;
|
||||||
pll_writel_base(val, pll);
|
pll_writel_base(val, pll);
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLLM) {
|
if (pll->params->flags & TEGRA_PLLM) {
|
||||||
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
||||||
val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
|
val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
|
||||||
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
||||||
@ -241,12 +287,12 @@ static void _clk_pll_disable(struct clk_hw *hw)
|
|||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
if (pll->flags & TEGRA_PLL_BYPASS)
|
if (pll->params->flags & TEGRA_PLL_BYPASS)
|
||||||
val &= ~PLL_BASE_BYPASS;
|
val &= ~PLL_BASE_BYPASS;
|
||||||
val &= ~PLL_BASE_ENABLE;
|
val &= ~PLL_BASE_ENABLE;
|
||||||
pll_writel_base(val, pll);
|
pll_writel_base(val, pll);
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLLM) {
|
if (pll->params->flags & TEGRA_PLLM) {
|
||||||
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
||||||
val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
|
val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
|
||||||
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
|
||||||
@ -326,7 +372,7 @@ static int _get_table_rate(struct clk_hw *hw,
|
|||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
struct tegra_clk_pll_freq_table *sel;
|
struct tegra_clk_pll_freq_table *sel;
|
||||||
|
|
||||||
for (sel = pll->freq_table; sel->input_rate != 0; sel++)
|
for (sel = pll->params->freq_table; sel->input_rate != 0; sel++)
|
||||||
if (sel->input_rate == parent_rate &&
|
if (sel->input_rate == parent_rate &&
|
||||||
sel->output_rate == rate)
|
sel->output_rate == rate)
|
||||||
break;
|
break;
|
||||||
@ -389,12 +435,11 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
|
|||||||
if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
|
if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
|
||||||
(1 << p_div) > divp_max(pll)
|
(1 << p_div) > divp_max(pll)
|
||||||
|| cfg->output_rate > pll->params->vco_max) {
|
|| cfg->output_rate > pll->params->vco_max) {
|
||||||
pr_err("%s: Failed to set %s rate %lu\n",
|
|
||||||
__func__, __clk_get_name(hw->clk), rate);
|
|
||||||
WARN_ON(1);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg->output_rate >>= p_div;
|
||||||
|
|
||||||
if (pll->params->pdiv_tohw) {
|
if (pll->params->pdiv_tohw) {
|
||||||
ret = _p_div_to_hw(hw, 1 << p_div);
|
ret = _p_div_to_hw(hw, 1 << p_div);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -414,7 +459,7 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
|
|||||||
struct tegra_clk_pll_params *params = pll->params;
|
struct tegra_clk_pll_params *params = pll->params;
|
||||||
struct div_nmp *div_nmp = params->div_nmp;
|
struct div_nmp *div_nmp = params->div_nmp;
|
||||||
|
|
||||||
if ((pll->flags & TEGRA_PLLM) &&
|
if ((params->flags & TEGRA_PLLM) &&
|
||||||
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
|
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
|
||||||
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
|
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
|
||||||
val = pll_override_readl(params->pmc_divp_reg, pll);
|
val = pll_override_readl(params->pmc_divp_reg, pll);
|
||||||
@ -450,7 +495,7 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
|
|||||||
struct tegra_clk_pll_params *params = pll->params;
|
struct tegra_clk_pll_params *params = pll->params;
|
||||||
struct div_nmp *div_nmp = params->div_nmp;
|
struct div_nmp *div_nmp = params->div_nmp;
|
||||||
|
|
||||||
if ((pll->flags & TEGRA_PLLM) &&
|
if ((params->flags & TEGRA_PLLM) &&
|
||||||
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
|
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
|
||||||
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
|
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
|
||||||
val = pll_override_readl(params->pmc_divp_reg, pll);
|
val = pll_override_readl(params->pmc_divp_reg, pll);
|
||||||
@ -479,11 +524,11 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll,
|
|||||||
val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
|
val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
|
||||||
val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
|
val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLL_SET_LFCON) {
|
if (pll->params->flags & TEGRA_PLL_SET_LFCON) {
|
||||||
val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
|
val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
|
||||||
if (cfg->n >= PLLDU_LFCON_SET_DIVN)
|
if (cfg->n >= PLLDU_LFCON_SET_DIVN)
|
||||||
val |= 1 << PLL_MISC_LFCON_SHIFT;
|
val |= 1 << PLL_MISC_LFCON_SHIFT;
|
||||||
} else if (pll->flags & TEGRA_PLL_SET_DCCON) {
|
} else if (pll->params->flags & TEGRA_PLL_SET_DCCON) {
|
||||||
val &= ~(1 << PLL_MISC_DCCON_SHIFT);
|
val &= ~(1 << PLL_MISC_DCCON_SHIFT);
|
||||||
if (rate >= (pll->params->vco_max >> 1))
|
if (rate >= (pll->params->vco_max >> 1))
|
||||||
val |= 1 << PLL_MISC_DCCON_SHIFT;
|
val |= 1 << PLL_MISC_DCCON_SHIFT;
|
||||||
@ -505,7 +550,7 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
|
|||||||
|
|
||||||
_update_pll_mnp(pll, cfg);
|
_update_pll_mnp(pll, cfg);
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLL_HAS_CPCON)
|
if (pll->params->flags & TEGRA_PLL_HAS_CPCON)
|
||||||
_update_pll_cpcon(pll, cfg, rate);
|
_update_pll_cpcon(pll, cfg, rate);
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
@ -524,11 +569,11 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLL_FIXED) {
|
if (pll->params->flags & TEGRA_PLL_FIXED) {
|
||||||
if (rate != pll->fixed_rate) {
|
if (rate != pll->params->fixed_rate) {
|
||||||
pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
|
pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
|
||||||
__func__, __clk_get_name(hw->clk),
|
__func__, __clk_get_name(hw->clk),
|
||||||
pll->fixed_rate, rate);
|
pll->params->fixed_rate, rate);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -536,6 +581,8 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
|
|
||||||
if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
|
if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
|
||||||
_calc_rate(hw, &cfg, rate, parent_rate)) {
|
_calc_rate(hw, &cfg, rate, parent_rate)) {
|
||||||
|
pr_err("%s: Failed to set %s rate %lu\n", __func__,
|
||||||
|
__clk_get_name(hw->clk), rate);
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -559,18 +606,16 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
struct tegra_clk_pll_freq_table cfg;
|
struct tegra_clk_pll_freq_table cfg;
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLL_FIXED)
|
if (pll->params->flags & TEGRA_PLL_FIXED)
|
||||||
return pll->fixed_rate;
|
return pll->params->fixed_rate;
|
||||||
|
|
||||||
/* PLLM is used for memory; we do not change rate */
|
/* PLLM is used for memory; we do not change rate */
|
||||||
if (pll->flags & TEGRA_PLLM)
|
if (pll->params->flags & TEGRA_PLLM)
|
||||||
return __clk_get_rate(hw->clk);
|
return __clk_get_rate(hw->clk);
|
||||||
|
|
||||||
if (_get_table_rate(hw, &cfg, rate, *prate) &&
|
if (_get_table_rate(hw, &cfg, rate, *prate) &&
|
||||||
_calc_rate(hw, &cfg, rate, *prate)) {
|
_calc_rate(hw, &cfg, rate, *prate))
|
||||||
WARN_ON(1);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
return cfg.output_rate;
|
return cfg.output_rate;
|
||||||
}
|
}
|
||||||
@ -586,17 +631,19 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
|||||||
|
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
|
|
||||||
if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
|
if ((pll->params->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
|
||||||
return parent_rate;
|
return parent_rate;
|
||||||
|
|
||||||
if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
|
if ((pll->params->flags & TEGRA_PLL_FIXED) &&
|
||||||
|
!(val & PLL_BASE_OVERRIDE)) {
|
||||||
struct tegra_clk_pll_freq_table sel;
|
struct tegra_clk_pll_freq_table sel;
|
||||||
if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {
|
if (_get_table_rate(hw, &sel, pll->params->fixed_rate,
|
||||||
|
parent_rate)) {
|
||||||
pr_err("Clock %s has unknown fixed frequency\n",
|
pr_err("Clock %s has unknown fixed frequency\n",
|
||||||
__clk_get_name(hw->clk));
|
__clk_get_name(hw->clk));
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
return pll->fixed_rate;
|
return pll->params->fixed_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
_get_pll_mnp(pll, &cfg);
|
_get_pll_mnp(pll, &cfg);
|
||||||
@ -664,7 +711,7 @@ static int clk_plle_enable(struct clk_hw *hw)
|
|||||||
u32 val;
|
u32 val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
|
if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
clk_pll_disable(hw);
|
clk_pll_disable(hw);
|
||||||
@ -680,7 +727,7 @@ static int clk_plle_enable(struct clk_hw *hw)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLLE_CONFIGURE) {
|
if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {
|
||||||
/* configure dividers */
|
/* configure dividers */
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
||||||
@ -744,7 +791,7 @@ const struct clk_ops tegra_clk_plle_ops = {
|
|||||||
.enable = clk_plle_enable,
|
.enable = clk_plle_enable,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
|
||||||
|
|
||||||
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
|
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
|
||||||
unsigned long parent_rate)
|
unsigned long parent_rate)
|
||||||
@ -755,6 +802,48 @@ static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long _clip_vco_min(unsigned long vco_min,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
return DIV_ROUND_UP(vco_min, parent_rate) * parent_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
|
||||||
|
void __iomem *clk_base,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
u32 step_a, step_b;
|
||||||
|
|
||||||
|
switch (parent_rate) {
|
||||||
|
case 12000000:
|
||||||
|
case 13000000:
|
||||||
|
case 26000000:
|
||||||
|
step_a = 0x2B;
|
||||||
|
step_b = 0x0B;
|
||||||
|
break;
|
||||||
|
case 16800000:
|
||||||
|
step_a = 0x1A;
|
||||||
|
step_b = 0x09;
|
||||||
|
break;
|
||||||
|
case 19200000:
|
||||||
|
step_a = 0x12;
|
||||||
|
step_b = 0x08;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("%s: Unexpected reference rate %lu\n",
|
||||||
|
__func__, parent_rate);
|
||||||
|
WARN_ON(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = step_a << pll_params->stepa_shift;
|
||||||
|
val |= step_b << pll_params->stepb_shift;
|
||||||
|
writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int clk_pll_iddq_enable(struct clk_hw *hw)
|
static int clk_pll_iddq_enable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
@ -1173,7 +1262,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
|
|||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
|
unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
|
||||||
|
|
||||||
if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
|
if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (pll->lock)
|
if (pll->lock)
|
||||||
@ -1217,6 +1306,18 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
val = pll_readl(PLLE_SS_CTRL, pll);
|
||||||
|
val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);
|
||||||
|
val &= ~PLLE_SS_COEFFICIENTS_MASK;
|
||||||
|
val |= PLLE_SS_COEFFICIENTS_VAL;
|
||||||
|
pll_writel(val, PLLE_SS_CTRL, pll);
|
||||||
|
val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);
|
||||||
|
pll_writel(val, PLLE_SS_CTRL, pll);
|
||||||
|
udelay(1);
|
||||||
|
val &= ~PLLE_SS_CNTL_INTERP_RESET;
|
||||||
|
pll_writel(val, PLLE_SS_CTRL, pll);
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
/* TODO: enable hw control of xusb brick pll */
|
/* TODO: enable hw control of xusb brick pll */
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -1248,9 +1349,8 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
|
static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
|
||||||
void __iomem *pmc, unsigned long fixed_rate,
|
void __iomem *pmc, struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
|
spinlock_t *lock)
|
||||||
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
|
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
|
|
||||||
@ -1261,10 +1361,7 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
|
|||||||
pll->clk_base = clk_base;
|
pll->clk_base = clk_base;
|
||||||
pll->pmc = pmc;
|
pll->pmc = pmc;
|
||||||
|
|
||||||
pll->freq_table = freq_table;
|
|
||||||
pll->params = pll_params;
|
pll->params = pll_params;
|
||||||
pll->fixed_rate = fixed_rate;
|
|
||||||
pll->flags = pll_flags;
|
|
||||||
pll->lock = lock;
|
pll->lock = lock;
|
||||||
|
|
||||||
if (!pll_params->div_nmp)
|
if (!pll_params->div_nmp)
|
||||||
@ -1293,17 +1390,15 @@ static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags, struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
|
spinlock_t *lock)
|
||||||
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
|
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_BYPASS;
|
pll_params->flags |= TEGRA_PLL_BYPASS;
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
|
||||||
freq_table, lock);
|
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
@ -1317,17 +1412,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags, struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
|
spinlock_t *lock)
|
||||||
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
|
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
|
pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
|
||||||
freq_table, lock);
|
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
@ -1339,7 +1432,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
|||||||
return clk;
|
return clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
|
||||||
const struct clk_ops tegra_clk_pllxc_ops = {
|
const struct clk_ops tegra_clk_pllxc_ops = {
|
||||||
.is_enabled = clk_pll_is_enabled,
|
.is_enabled = clk_pll_is_enabled,
|
||||||
.enable = clk_pll_iddq_enable,
|
.enable = clk_pll_iddq_enable,
|
||||||
@ -1386,21 +1479,46 @@ const struct clk_ops tegra_clk_plle_tegra114_ops = {
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock)
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk, *parent;
|
||||||
|
unsigned long parent_rate;
|
||||||
|
int err;
|
||||||
|
u32 val, val_iddq;
|
||||||
|
|
||||||
|
parent = __clk_lookup(parent_name);
|
||||||
|
if (!parent) {
|
||||||
|
WARN(1, "parent clk %s of %s must be registered first\n",
|
||||||
|
name, parent_name);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!pll_params->pdiv_tohw)
|
if (!pll_params->pdiv_tohw)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
parent_rate = __clk_get_rate(parent);
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
|
||||||
freq_table, lock);
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
|
err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
val = readl_relaxed(clk_base + pll_params->base_reg);
|
||||||
|
val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
|
||||||
|
|
||||||
|
if (val & PLL_BASE_ENABLE)
|
||||||
|
WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
|
||||||
|
else {
|
||||||
|
val_iddq |= BIT(pll_params->iddq_bit_idx);
|
||||||
|
writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
|
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
@ -1414,19 +1532,19 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock, unsigned long parent_rate)
|
spinlock_t *lock, unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
|
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
|
||||||
freq_table, lock);
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
|
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
@ -1461,23 +1579,32 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock)
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk, *parent;
|
||||||
|
unsigned long parent_rate;
|
||||||
|
|
||||||
if (!pll_params->pdiv_tohw)
|
if (!pll_params->pdiv_tohw)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_BYPASS;
|
parent = __clk_lookup(parent_name);
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
if (!parent) {
|
||||||
pll_flags |= TEGRA_PLLM;
|
WARN(1, "parent clk %s of %s must be registered first\n",
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
name, parent_name);
|
||||||
freq_table, lock);
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
|
pll_params->flags |= TEGRA_PLL_BYPASS;
|
||||||
|
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
|
pll_params->flags |= TEGRA_PLLM;
|
||||||
|
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
@ -1491,10 +1618,8 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
|||||||
|
|
||||||
struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock)
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct clk *parent, *clk;
|
struct clk *parent, *clk;
|
||||||
@ -1507,20 +1632,21 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
|||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
parent = __clk_lookup(parent_name);
|
parent = __clk_lookup(parent_name);
|
||||||
if (IS_ERR(parent)) {
|
if (!parent) {
|
||||||
WARN(1, "parent clk %s of %s must be registered first\n",
|
WARN(1, "parent clk %s of %s must be registered first\n",
|
||||||
name, parent_name);
|
name, parent_name);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_BYPASS;
|
parent_rate = __clk_get_rate(parent);
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
|
||||||
freq_table, lock);
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
|
pll_params->flags |= TEGRA_PLL_BYPASS;
|
||||||
|
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
parent_rate = __clk_get_rate(parent);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Most of PLLC register fields are shadowed, and can not be read
|
* Most of PLLC register fields are shadowed, and can not be read
|
||||||
* directly from PLL h/w. Hence, actual PLLC boot state is unknown.
|
* directly from PLL h/w. Hence, actual PLLC boot state is unknown.
|
||||||
@ -1567,17 +1693,15 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
|||||||
struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
||||||
const char *parent_name,
|
const char *parent_name,
|
||||||
void __iomem *clk_base, unsigned long flags,
|
void __iomem *clk_base, unsigned long flags,
|
||||||
unsigned long fixed_rate,
|
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock)
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
u32 val, val_aux;
|
u32 val, val_aux;
|
||||||
|
|
||||||
pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params,
|
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock);
|
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
@ -1587,11 +1711,13 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
|||||||
val_aux = pll_readl(pll_params->aux_reg, pll);
|
val_aux = pll_readl(pll_params->aux_reg, pll);
|
||||||
|
|
||||||
if (val & PLL_BASE_ENABLE) {
|
if (val & PLL_BASE_ENABLE) {
|
||||||
if (!(val_aux & PLLE_AUX_PLLRE_SEL))
|
if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
|
||||||
|
(val_aux & PLLE_AUX_PLLP_SEL))
|
||||||
WARN(1, "pll_e enabled with unsupported parent %s\n",
|
WARN(1, "pll_e enabled with unsupported parent %s\n",
|
||||||
(val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");
|
(val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
|
||||||
|
"pll_re_vco");
|
||||||
} else {
|
} else {
|
||||||
val_aux |= PLLE_AUX_PLLRE_SEL;
|
val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
|
||||||
pll_writel(val, pll_params->aux_reg, pll);
|
pll_writel(val, pll_params->aux_reg, pll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1603,3 +1729,92 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
|||||||
return clk;
|
return clk;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA_124_SOC
|
||||||
|
const struct clk_ops tegra_clk_pllss_ops = {
|
||||||
|
.is_enabled = clk_pll_is_enabled,
|
||||||
|
.enable = clk_pll_iddq_enable,
|
||||||
|
.disable = clk_pll_iddq_disable,
|
||||||
|
.recalc_rate = clk_pll_recalc_rate,
|
||||||
|
.round_rate = clk_pll_ramp_round_rate,
|
||||||
|
.set_rate = clk_pllxc_set_rate,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
|
||||||
|
void __iomem *clk_base, unsigned long flags,
|
||||||
|
struct tegra_clk_pll_params *pll_params,
|
||||||
|
spinlock_t *lock)
|
||||||
|
{
|
||||||
|
struct tegra_clk_pll *pll;
|
||||||
|
struct clk *clk, *parent;
|
||||||
|
struct tegra_clk_pll_freq_table cfg;
|
||||||
|
unsigned long parent_rate;
|
||||||
|
u32 val;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!pll_params->div_nmp)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
parent = __clk_lookup(parent_name);
|
||||||
|
if (!parent) {
|
||||||
|
WARN(1, "parent clk %s of %s must be registered first\n",
|
||||||
|
name, parent_name);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK;
|
||||||
|
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
|
||||||
|
if (IS_ERR(pll))
|
||||||
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
|
val = pll_readl_base(pll);
|
||||||
|
val &= ~PLLSS_REF_SRC_SEL_MASK;
|
||||||
|
pll_writel_base(val, pll);
|
||||||
|
|
||||||
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
|
/* initialize PLL to minimum rate */
|
||||||
|
|
||||||
|
cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
|
||||||
|
cfg.n = cfg.m * pll_params->vco_min / parent_rate;
|
||||||
|
|
||||||
|
for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++)
|
||||||
|
;
|
||||||
|
if (!i) {
|
||||||
|
kfree(pll);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.p = pll_params->pdiv_tohw[i-1].hw_val;
|
||||||
|
|
||||||
|
_update_pll_mnp(pll, &cfg);
|
||||||
|
|
||||||
|
pll_writel_misc(PLLSS_MISC_DEFAULT, pll);
|
||||||
|
pll_writel(PLLSS_CFG_DEFAULT, pll_params->ext_misc_reg[0], pll);
|
||||||
|
pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[1], pll);
|
||||||
|
pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll);
|
||||||
|
|
||||||
|
val = pll_readl_base(pll);
|
||||||
|
if (val & PLL_BASE_ENABLE) {
|
||||||
|
if (val & BIT(pll_params->iddq_bit_idx)) {
|
||||||
|
WARN(1, "%s is on but IDDQ set\n", name);
|
||||||
|
kfree(pll);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
val |= BIT(pll_params->iddq_bit_idx);
|
||||||
|
|
||||||
|
val &= ~PLLSS_LOCK_OVERRIDE;
|
||||||
|
pll_writel_base(val, pll);
|
||||||
|
|
||||||
|
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
|
||||||
|
&tegra_clk_pllss_ops);
|
||||||
|
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
kfree(pll);
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
215
drivers/clk/tegra/clk-tegra-audio.c
Normal file
215
drivers/clk/tegra/clk-tegra-audio.c
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
|
#include "clk.h"
|
||||||
|
#include "clk-id.h"
|
||||||
|
|
||||||
|
#define AUDIO_SYNC_CLK_I2S0 0x4a0
|
||||||
|
#define AUDIO_SYNC_CLK_I2S1 0x4a4
|
||||||
|
#define AUDIO_SYNC_CLK_I2S2 0x4a8
|
||||||
|
#define AUDIO_SYNC_CLK_I2S3 0x4ac
|
||||||
|
#define AUDIO_SYNC_CLK_I2S4 0x4b0
|
||||||
|
#define AUDIO_SYNC_CLK_SPDIF 0x4b4
|
||||||
|
|
||||||
|
#define AUDIO_SYNC_DOUBLER 0x49c
|
||||||
|
|
||||||
|
#define PLLA_OUT 0xb4
|
||||||
|
|
||||||
|
struct tegra_sync_source_initdata {
|
||||||
|
char *name;
|
||||||
|
unsigned long rate;
|
||||||
|
unsigned long max_rate;
|
||||||
|
int clk_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SYNC(_name) \
|
||||||
|
{\
|
||||||
|
.name = #_name,\
|
||||||
|
.rate = 24000000,\
|
||||||
|
.max_rate = 24000000,\
|
||||||
|
.clk_id = tegra_clk_ ## _name,\
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tegra_audio_clk_initdata {
|
||||||
|
char *gate_name;
|
||||||
|
char *mux_name;
|
||||||
|
u32 offset;
|
||||||
|
int gate_clk_id;
|
||||||
|
int mux_clk_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AUDIO(_name, _offset) \
|
||||||
|
{\
|
||||||
|
.gate_name = #_name,\
|
||||||
|
.mux_name = #_name"_mux",\
|
||||||
|
.offset = _offset,\
|
||||||
|
.gate_clk_id = tegra_clk_ ## _name,\
|
||||||
|
.mux_clk_id = tegra_clk_ ## _name ## _mux,\
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tegra_audio2x_clk_initdata {
|
||||||
|
char *parent;
|
||||||
|
char *gate_name;
|
||||||
|
char *name_2x;
|
||||||
|
char *div_name;
|
||||||
|
int clk_id;
|
||||||
|
int clk_num;
|
||||||
|
u8 div_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AUDIO2X(_name, _num, _offset) \
|
||||||
|
{\
|
||||||
|
.parent = #_name,\
|
||||||
|
.gate_name = #_name"_2x",\
|
||||||
|
.name_2x = #_name"_doubler",\
|
||||||
|
.div_name = #_name"_div",\
|
||||||
|
.clk_id = tegra_clk_ ## _name ## _2x,\
|
||||||
|
.clk_num = _num,\
|
||||||
|
.div_offset = _offset,\
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(clk_doubler_lock);
|
||||||
|
|
||||||
|
static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
|
||||||
|
"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {
|
||||||
|
SYNC(spdif_in_sync),
|
||||||
|
SYNC(i2s0_sync),
|
||||||
|
SYNC(i2s1_sync),
|
||||||
|
SYNC(i2s2_sync),
|
||||||
|
SYNC(i2s3_sync),
|
||||||
|
SYNC(i2s4_sync),
|
||||||
|
SYNC(vimclk_sync),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct tegra_audio_clk_initdata audio_clks[] = {
|
||||||
|
AUDIO(audio0, AUDIO_SYNC_CLK_I2S0),
|
||||||
|
AUDIO(audio1, AUDIO_SYNC_CLK_I2S1),
|
||||||
|
AUDIO(audio2, AUDIO_SYNC_CLK_I2S2),
|
||||||
|
AUDIO(audio3, AUDIO_SYNC_CLK_I2S3),
|
||||||
|
AUDIO(audio4, AUDIO_SYNC_CLK_I2S4),
|
||||||
|
AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
|
||||||
|
AUDIO2X(audio0, 113, 24),
|
||||||
|
AUDIO2X(audio1, 114, 25),
|
||||||
|
AUDIO2X(audio2, 115, 26),
|
||||||
|
AUDIO2X(audio3, 116, 27),
|
||||||
|
AUDIO2X(audio4, 117, 28),
|
||||||
|
AUDIO2X(spdif, 118, 29),
|
||||||
|
};
|
||||||
|
|
||||||
|
void __init tegra_audio_clk_init(void __iomem *clk_base,
|
||||||
|
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *pll_a_params)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* PLLA */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base,
|
||||||
|
pmc_base, 0, pll_a_params, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PLLA_OUT0 */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
|
||||||
|
clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
|
||||||
|
8, 8, 1, NULL);
|
||||||
|
clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
|
||||||
|
clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
|
||||||
|
CLK_SET_RATE_PARENT, 0, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(sync_source_clks); i++) {
|
||||||
|
struct tegra_sync_source_initdata *data;
|
||||||
|
|
||||||
|
data = &sync_source_clks[i];
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = tegra_clk_register_sync_source(data->name,
|
||||||
|
data->rate, data->max_rate);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(audio_clks); i++) {
|
||||||
|
struct tegra_audio_clk_initdata *data;
|
||||||
|
|
||||||
|
data = &audio_clks[i];
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
|
||||||
|
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk,
|
||||||
|
ARRAY_SIZE(mux_audio_sync_clk),
|
||||||
|
CLK_SET_RATE_NO_REPARENT,
|
||||||
|
clk_base + data->offset, 0, 3, 0,
|
||||||
|
NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
|
||||||
|
0, clk_base + data->offset, 4,
|
||||||
|
CLK_GATE_SET_TO_DISABLE, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) {
|
||||||
|
struct tegra_audio2x_clk_initdata *data;
|
||||||
|
|
||||||
|
data = &audio2x_clks[i];
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = clk_register_fixed_factor(NULL, data->name_2x,
|
||||||
|
data->parent, CLK_SET_RATE_PARENT, 2, 1);
|
||||||
|
clk = tegra_clk_register_divider(data->div_name,
|
||||||
|
data->name_2x, clk_base + AUDIO_SYNC_DOUBLER,
|
||||||
|
0, 0, data->div_offset, 1, 0,
|
||||||
|
&clk_doubler_lock);
|
||||||
|
clk = tegra_clk_register_periph_gate(data->gate_name,
|
||||||
|
data->div_name, TEGRA_PERIPH_NO_RESET,
|
||||||
|
clk_base, CLK_SET_RATE_PARENT, data->clk_num,
|
||||||
|
periph_clk_enb_refcnt);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
111
drivers/clk/tegra/clk-tegra-fixed.c
Normal file
111
drivers/clk/tegra/clk-tegra-fixed.c
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
|
#include "clk.h"
|
||||||
|
#include "clk-id.h"
|
||||||
|
|
||||||
|
#define OSC_CTRL 0x50
|
||||||
|
#define OSC_CTRL_OSC_FREQ_SHIFT 28
|
||||||
|
#define OSC_CTRL_PLL_REF_DIV_SHIFT 26
|
||||||
|
|
||||||
|
int __init tegra_osc_clk_init(void __iomem *clk_base,
|
||||||
|
struct tegra_clk *tegra_clks,
|
||||||
|
unsigned long *input_freqs, int num,
|
||||||
|
unsigned long *osc_freq,
|
||||||
|
unsigned long *pll_ref_freq)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
u32 val, pll_ref_div;
|
||||||
|
unsigned osc_idx;
|
||||||
|
|
||||||
|
val = readl_relaxed(clk_base + OSC_CTRL);
|
||||||
|
osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
|
||||||
|
|
||||||
|
if (osc_idx < num)
|
||||||
|
*osc_freq = input_freqs[osc_idx];
|
||||||
|
else
|
||||||
|
*osc_freq = 0;
|
||||||
|
|
||||||
|
if (!*osc_freq) {
|
||||||
|
WARN_ON(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
|
||||||
|
*osc_freq);
|
||||||
|
*dt_clk = clk;
|
||||||
|
|
||||||
|
/* pll_ref */
|
||||||
|
val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
|
||||||
|
pll_ref_div = 1 << val;
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
|
||||||
|
0, 1, pll_ref_div);
|
||||||
|
*dt_clk = clk;
|
||||||
|
|
||||||
|
if (pll_ref_freq)
|
||||||
|
*pll_ref_freq = *osc_freq / pll_ref_div;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
|
||||||
|
/* clk_32k */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = clk_register_fixed_rate(NULL, "clk_32k", NULL,
|
||||||
|
CLK_IS_ROOT, 32768);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clk_m_div2 */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
|
||||||
|
CLK_SET_RATE_PARENT, 1, 2);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clk_m_div4 */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
|
||||||
|
CLK_SET_RATE_PARENT, 1, 4);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
674
drivers/clk/tegra/clk-tegra-periph.c
Normal file
674
drivers/clk/tegra/clk-tegra-periph.c
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/clkdev.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
|
#include "clk.h"
|
||||||
|
#include "clk-id.h"
|
||||||
|
|
||||||
|
#define CLK_SOURCE_I2S0 0x1d8
|
||||||
|
#define CLK_SOURCE_I2S1 0x100
|
||||||
|
#define CLK_SOURCE_I2S2 0x104
|
||||||
|
#define CLK_SOURCE_NDFLASH 0x160
|
||||||
|
#define CLK_SOURCE_I2S3 0x3bc
|
||||||
|
#define CLK_SOURCE_I2S4 0x3c0
|
||||||
|
#define CLK_SOURCE_SPDIF_OUT 0x108
|
||||||
|
#define CLK_SOURCE_SPDIF_IN 0x10c
|
||||||
|
#define CLK_SOURCE_PWM 0x110
|
||||||
|
#define CLK_SOURCE_ADX 0x638
|
||||||
|
#define CLK_SOURCE_ADX1 0x670
|
||||||
|
#define CLK_SOURCE_AMX 0x63c
|
||||||
|
#define CLK_SOURCE_AMX1 0x674
|
||||||
|
#define CLK_SOURCE_HDA 0x428
|
||||||
|
#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
|
||||||
|
#define CLK_SOURCE_SBC1 0x134
|
||||||
|
#define CLK_SOURCE_SBC2 0x118
|
||||||
|
#define CLK_SOURCE_SBC3 0x11c
|
||||||
|
#define CLK_SOURCE_SBC4 0x1b4
|
||||||
|
#define CLK_SOURCE_SBC5 0x3c8
|
||||||
|
#define CLK_SOURCE_SBC6 0x3cc
|
||||||
|
#define CLK_SOURCE_SATA_OOB 0x420
|
||||||
|
#define CLK_SOURCE_SATA 0x424
|
||||||
|
#define CLK_SOURCE_NDSPEED 0x3f8
|
||||||
|
#define CLK_SOURCE_VFIR 0x168
|
||||||
|
#define CLK_SOURCE_SDMMC1 0x150
|
||||||
|
#define CLK_SOURCE_SDMMC2 0x154
|
||||||
|
#define CLK_SOURCE_SDMMC3 0x1bc
|
||||||
|
#define CLK_SOURCE_SDMMC4 0x164
|
||||||
|
#define CLK_SOURCE_CVE 0x140
|
||||||
|
#define CLK_SOURCE_TVO 0x188
|
||||||
|
#define CLK_SOURCE_TVDAC 0x194
|
||||||
|
#define CLK_SOURCE_VDE 0x1c8
|
||||||
|
#define CLK_SOURCE_CSITE 0x1d4
|
||||||
|
#define CLK_SOURCE_LA 0x1f8
|
||||||
|
#define CLK_SOURCE_TRACE 0x634
|
||||||
|
#define CLK_SOURCE_OWR 0x1cc
|
||||||
|
#define CLK_SOURCE_NOR 0x1d0
|
||||||
|
#define CLK_SOURCE_MIPI 0x174
|
||||||
|
#define CLK_SOURCE_I2C1 0x124
|
||||||
|
#define CLK_SOURCE_I2C2 0x198
|
||||||
|
#define CLK_SOURCE_I2C3 0x1b8
|
||||||
|
#define CLK_SOURCE_I2C4 0x3c4
|
||||||
|
#define CLK_SOURCE_I2C5 0x128
|
||||||
|
#define CLK_SOURCE_I2C6 0x65c
|
||||||
|
#define CLK_SOURCE_UARTA 0x178
|
||||||
|
#define CLK_SOURCE_UARTB 0x17c
|
||||||
|
#define CLK_SOURCE_UARTC 0x1a0
|
||||||
|
#define CLK_SOURCE_UARTD 0x1c0
|
||||||
|
#define CLK_SOURCE_UARTE 0x1c4
|
||||||
|
#define CLK_SOURCE_3D 0x158
|
||||||
|
#define CLK_SOURCE_2D 0x15c
|
||||||
|
#define CLK_SOURCE_MPE 0x170
|
||||||
|
#define CLK_SOURCE_UARTE 0x1c4
|
||||||
|
#define CLK_SOURCE_VI_SENSOR 0x1a8
|
||||||
|
#define CLK_SOURCE_VI 0x148
|
||||||
|
#define CLK_SOURCE_EPP 0x16c
|
||||||
|
#define CLK_SOURCE_MSENC 0x1f0
|
||||||
|
#define CLK_SOURCE_TSEC 0x1f4
|
||||||
|
#define CLK_SOURCE_HOST1X 0x180
|
||||||
|
#define CLK_SOURCE_HDMI 0x18c
|
||||||
|
#define CLK_SOURCE_DISP1 0x138
|
||||||
|
#define CLK_SOURCE_DISP2 0x13c
|
||||||
|
#define CLK_SOURCE_CILAB 0x614
|
||||||
|
#define CLK_SOURCE_CILCD 0x618
|
||||||
|
#define CLK_SOURCE_CILE 0x61c
|
||||||
|
#define CLK_SOURCE_DSIALP 0x620
|
||||||
|
#define CLK_SOURCE_DSIBLP 0x624
|
||||||
|
#define CLK_SOURCE_TSENSOR 0x3b8
|
||||||
|
#define CLK_SOURCE_D_AUDIO 0x3d0
|
||||||
|
#define CLK_SOURCE_DAM0 0x3d8
|
||||||
|
#define CLK_SOURCE_DAM1 0x3dc
|
||||||
|
#define CLK_SOURCE_DAM2 0x3e0
|
||||||
|
#define CLK_SOURCE_ACTMON 0x3e8
|
||||||
|
#define CLK_SOURCE_EXTERN1 0x3ec
|
||||||
|
#define CLK_SOURCE_EXTERN2 0x3f0
|
||||||
|
#define CLK_SOURCE_EXTERN3 0x3f4
|
||||||
|
#define CLK_SOURCE_I2CSLOW 0x3fc
|
||||||
|
#define CLK_SOURCE_SE 0x42c
|
||||||
|
#define CLK_SOURCE_MSELECT 0x3b4
|
||||||
|
#define CLK_SOURCE_DFLL_REF 0x62c
|
||||||
|
#define CLK_SOURCE_DFLL_SOC 0x630
|
||||||
|
#define CLK_SOURCE_SOC_THERM 0x644
|
||||||
|
#define CLK_SOURCE_XUSB_HOST_SRC 0x600
|
||||||
|
#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
|
||||||
|
#define CLK_SOURCE_XUSB_FS_SRC 0x608
|
||||||
|
#define CLK_SOURCE_XUSB_SS_SRC 0x610
|
||||||
|
#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
|
||||||
|
#define CLK_SOURCE_ISP 0x144
|
||||||
|
#define CLK_SOURCE_SOR0 0x414
|
||||||
|
#define CLK_SOURCE_DPAUX 0x418
|
||||||
|
#define CLK_SOURCE_SATA_OOB 0x420
|
||||||
|
#define CLK_SOURCE_SATA 0x424
|
||||||
|
#define CLK_SOURCE_ENTROPY 0x628
|
||||||
|
#define CLK_SOURCE_VI_SENSOR2 0x658
|
||||||
|
#define CLK_SOURCE_HDMI_AUDIO 0x668
|
||||||
|
#define CLK_SOURCE_VIC03 0x678
|
||||||
|
#define CLK_SOURCE_CLK72MHZ 0x66c
|
||||||
|
|
||||||
|
#define MASK(x) (BIT(x) - 1)
|
||||||
|
|
||||||
|
#define MUX(_name, _parents, _offset, \
|
||||||
|
_clk_num, _gate_flags, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \
|
||||||
|
_clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
|
||||||
|
NULL)
|
||||||
|
|
||||||
|
#define MUX_FLAGS(_name, _parents, _offset,\
|
||||||
|
_clk_num, _gate_flags, _clk_id, flags)\
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
|
||||||
|
_clk_num, _gate_flags, _clk_id, _parents##_idx, flags,\
|
||||||
|
NULL)
|
||||||
|
|
||||||
|
#define MUX8(_name, _parents, _offset, \
|
||||||
|
_clk_num, _gate_flags, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
|
||||||
|
_clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
|
||||||
|
NULL)
|
||||||
|
|
||||||
|
#define MUX8_NOGATE_LOCK(_name, _parents, _offset, _clk_id, _lock) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
|
||||||
|
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
|
||||||
|
0, TEGRA_PERIPH_NO_GATE, _clk_id,\
|
||||||
|
_parents##_idx, 0, _lock)
|
||||||
|
|
||||||
|
#define INT(_name, _parents, _offset, \
|
||||||
|
_clk_num, _gate_flags, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
|
||||||
|
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
|
||||||
|
_clk_id, _parents##_idx, 0, NULL)
|
||||||
|
|
||||||
|
#define INT_FLAGS(_name, _parents, _offset,\
|
||||||
|
_clk_num, _gate_flags, _clk_id, flags)\
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
|
||||||
|
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
|
||||||
|
_clk_id, _parents##_idx, flags, NULL)
|
||||||
|
|
||||||
|
#define INT8(_name, _parents, _offset,\
|
||||||
|
_clk_num, _gate_flags, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
|
||||||
|
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
|
||||||
|
_clk_id, _parents##_idx, 0, NULL)
|
||||||
|
|
||||||
|
#define UART(_name, _parents, _offset,\
|
||||||
|
_clk_num, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \
|
||||||
|
TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
|
||||||
|
_parents##_idx, 0, NULL)
|
||||||
|
|
||||||
|
#define I2C(_name, _parents, _offset,\
|
||||||
|
_clk_num, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\
|
||||||
|
_clk_num, 0, _clk_id, _parents##_idx, 0, NULL)
|
||||||
|
|
||||||
|
#define XUSB(_name, _parents, _offset, \
|
||||||
|
_clk_num, _gate_flags, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
|
||||||
|
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
|
||||||
|
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
|
||||||
|
_clk_id, _parents##_idx, 0, NULL)
|
||||||
|
|
||||||
|
#define AUDIO(_name, _offset, _clk_num,\
|
||||||
|
_gate_flags, _clk_id) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk, \
|
||||||
|
_offset, 16, 0xE01F, 0, 0, 8, 1, \
|
||||||
|
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags, \
|
||||||
|
_clk_id, mux_d_audio_clk_idx, 0, NULL)
|
||||||
|
|
||||||
|
#define NODIV(_name, _parents, _offset, \
|
||||||
|
_mux_shift, _mux_mask, _clk_num, \
|
||||||
|
_gate_flags, _clk_id, _lock) \
|
||||||
|
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||||
|
_mux_shift, _mux_mask, 0, 0, 0, 0, 0,\
|
||||||
|
_clk_num, (_gate_flags) | TEGRA_PERIPH_NO_DIV,\
|
||||||
|
_clk_id, _parents##_idx, 0, _lock)
|
||||||
|
|
||||||
|
#define GATE(_name, _parent_name, \
|
||||||
|
_clk_num, _gate_flags, _clk_id, _flags) \
|
||||||
|
{ \
|
||||||
|
.name = _name, \
|
||||||
|
.clk_id = _clk_id, \
|
||||||
|
.p.parent_name = _parent_name, \
|
||||||
|
.periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 0, 0, 0, \
|
||||||
|
_clk_num, _gate_flags, 0, NULL), \
|
||||||
|
.flags = _flags \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PLLP_BASE 0xa0
|
||||||
|
#define PLLP_MISC 0xac
|
||||||
|
#define PLLP_OUTA 0xa4
|
||||||
|
#define PLLP_OUTB 0xa8
|
||||||
|
#define PLLP_OUTC 0x67c
|
||||||
|
|
||||||
|
#define PLL_BASE_LOCK BIT(27)
|
||||||
|
#define PLL_MISC_LOCK_ENABLE 18
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(PLLP_OUTA_lock);
|
||||||
|
static DEFINE_SPINLOCK(PLLP_OUTB_lock);
|
||||||
|
static DEFINE_SPINLOCK(PLLP_OUTC_lock);
|
||||||
|
static DEFINE_SPINLOCK(sor0_lock);
|
||||||
|
|
||||||
|
#define MUX_I2S_SPDIF(_id) \
|
||||||
|
static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
|
||||||
|
#_id, "pll_p",\
|
||||||
|
"clk_m"};
|
||||||
|
MUX_I2S_SPDIF(audio0)
|
||||||
|
MUX_I2S_SPDIF(audio1)
|
||||||
|
MUX_I2S_SPDIF(audio2)
|
||||||
|
MUX_I2S_SPDIF(audio3)
|
||||||
|
MUX_I2S_SPDIF(audio4)
|
||||||
|
MUX_I2S_SPDIF(audio)
|
||||||
|
|
||||||
|
#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
|
||||||
|
#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
|
||||||
|
#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
|
||||||
|
#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
|
||||||
|
#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
|
||||||
|
#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllc_pllm_clkm[] = {
|
||||||
|
"pll_p", "pll_c", "pll_m", "clk_m"
|
||||||
|
};
|
||||||
|
#define mux_pllp_pllc_pllm_clkm_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
|
||||||
|
#define mux_pllp_pllc_pllm_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllc_clk32_clkm[] = {
|
||||||
|
"pll_p", "pll_c", "clk_32k", "clk_m"
|
||||||
|
};
|
||||||
|
#define mux_pllp_pllc_clk32_clkm_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_plla_pllc_pllp_clkm[] = {
|
||||||
|
"pll_a_out0", "pll_c", "pll_p", "clk_m"
|
||||||
|
};
|
||||||
|
#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
|
||||||
|
"pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
|
||||||
|
};
|
||||||
|
static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_pllp_clkm[] = {
|
||||||
|
"pll_p", "clk_m"
|
||||||
|
};
|
||||||
|
static u32 mux_pllp_clkm_idx[] = {
|
||||||
|
[0] = 0, [1] = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
|
||||||
|
"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
|
||||||
|
};
|
||||||
|
#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
|
||||||
|
"pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
|
||||||
|
"pll_d2_out0", "clk_m"
|
||||||
|
};
|
||||||
|
#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_pllm_pllc_pllp_plla[] = {
|
||||||
|
"pll_m", "pll_c", "pll_p", "pll_a_out0"
|
||||||
|
};
|
||||||
|
#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllc_clkm[] = {
|
||||||
|
"pll_p", "pll_c", "pll_m"
|
||||||
|
};
|
||||||
|
static u32 mux_pllp_pllc_clkm_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_pllp_pllc_clkm_clk32[] = {
|
||||||
|
"pll_p", "pll_c", "clk_m", "clk_32k"
|
||||||
|
};
|
||||||
|
#define mux_pllp_pllc_clkm_clk32_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_plla_clk32_pllp_clkm_plle[] = {
|
||||||
|
"pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
|
||||||
|
};
|
||||||
|
#define mux_plla_clk32_pllp_clkm_plle_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_clkm_pllp_pllc_pllre[] = {
|
||||||
|
"clk_m", "pll_p", "pll_c", "pll_re_out"
|
||||||
|
};
|
||||||
|
static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 3, [3] = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_clkm_48M_pllp_480M[] = {
|
||||||
|
"clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
|
||||||
|
};
|
||||||
|
#define mux_clkm_48M_pllp_480M_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
|
||||||
|
"clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
|
||||||
|
};
|
||||||
|
static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_d_audio_clk[] = {
|
||||||
|
"pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
|
||||||
|
"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
|
||||||
|
};
|
||||||
|
static u32 mux_d_audio_clk_idx[] = {
|
||||||
|
[0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
|
||||||
|
[5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_pllp_plld_pllc_clkm[] = {
|
||||||
|
"pll_p", "pll_d_out0", "pll_c", "clk_m"
|
||||||
|
};
|
||||||
|
#define mux_pllp_plld_pllc_clkm_idx NULL
|
||||||
|
static const char *mux_pllm_pllc_pllp_plla_clkm_pllc4[] = {
|
||||||
|
"pll_m", "pll_c", "pll_p", "pll_a_out0", "clk_m", "pll_c4",
|
||||||
|
};
|
||||||
|
static u32 mux_pllm_pllc_pllp_plla_clkm_pllc4_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 6, [5] = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_pllp_clkm1[] = {
|
||||||
|
"pll_p", "clk_m",
|
||||||
|
};
|
||||||
|
#define mux_pllp_clkm1_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_pllp3_pllc_clkm[] = {
|
||||||
|
"pll_p_out3", "pll_c", "pll_c2", "clk_m",
|
||||||
|
};
|
||||||
|
#define mux_pllp3_pllc_clkm_idx NULL
|
||||||
|
|
||||||
|
static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = {
|
||||||
|
"pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m"
|
||||||
|
};
|
||||||
|
static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = {
|
||||||
|
"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4",
|
||||||
|
};
|
||||||
|
static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = {
|
||||||
|
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *mux_clkm_plldp_sor0lvds[] = {
|
||||||
|
"clk_m", "pll_dp", "sor0_lvds",
|
||||||
|
};
|
||||||
|
#define mux_clkm_plldp_sor0lvds_idx NULL
|
||||||
|
|
||||||
|
static struct tegra_periph_init_data periph_clks[] = {
|
||||||
|
AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio),
|
||||||
|
AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0),
|
||||||
|
AUDIO("dam1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, tegra_clk_dam1),
|
||||||
|
AUDIO("dam2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, tegra_clk_dam2),
|
||||||
|
I2C("i2c1", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, tegra_clk_i2c1),
|
||||||
|
I2C("i2c2", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, tegra_clk_i2c2),
|
||||||
|
I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3),
|
||||||
|
I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4),
|
||||||
|
I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5),
|
||||||
|
INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde),
|
||||||
|
INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi),
|
||||||
|
INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp),
|
||||||
|
INT("host1x", mux_pllm_pllc_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x),
|
||||||
|
INT("mpe", mux_pllm_pllc_pllp_plla, CLK_SOURCE_MPE, 60, 0, tegra_clk_mpe),
|
||||||
|
INT("2d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d),
|
||||||
|
INT("3d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d),
|
||||||
|
INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8),
|
||||||
|
INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8),
|
||||||
|
INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9),
|
||||||
|
INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8),
|
||||||
|
INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc),
|
||||||
|
INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec),
|
||||||
|
INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
|
||||||
|
INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
|
||||||
|
INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
|
||||||
|
INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
|
||||||
|
INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
|
||||||
|
INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED),
|
||||||
|
MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0),
|
||||||
|
MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1),
|
||||||
|
MUX("i2s2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, tegra_clk_i2s2),
|
||||||
|
MUX("i2s3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, tegra_clk_i2s3),
|
||||||
|
MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4),
|
||||||
|
MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out),
|
||||||
|
MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in),
|
||||||
|
MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm),
|
||||||
|
MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx),
|
||||||
|
MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx),
|
||||||
|
MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda),
|
||||||
|
MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
|
||||||
|
MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
|
||||||
|
MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1),
|
||||||
|
MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2),
|
||||||
|
MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3),
|
||||||
|
MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4),
|
||||||
|
MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la),
|
||||||
|
MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace),
|
||||||
|
MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr),
|
||||||
|
MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor),
|
||||||
|
MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi),
|
||||||
|
MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor),
|
||||||
|
MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab),
|
||||||
|
MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd),
|
||||||
|
MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile),
|
||||||
|
MUX("dsialp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, tegra_clk_dsialp),
|
||||||
|
MUX("dsiblp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, tegra_clk_dsiblp),
|
||||||
|
MUX("tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, tegra_clk_tsensor),
|
||||||
|
MUX("actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, tegra_clk_actmon),
|
||||||
|
MUX("dfll_ref", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_ref),
|
||||||
|
MUX("dfll_soc", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_soc),
|
||||||
|
MUX("i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, tegra_clk_i2cslow),
|
||||||
|
MUX("sbc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1),
|
||||||
|
MUX("sbc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2),
|
||||||
|
MUX("sbc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3),
|
||||||
|
MUX("sbc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4),
|
||||||
|
MUX("sbc5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5),
|
||||||
|
MUX("sbc6", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6),
|
||||||
|
MUX("cve", mux_pllp_plld_pllc_clkm, CLK_SOURCE_CVE, 49, 0, tegra_clk_cve),
|
||||||
|
MUX("tvo", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVO, 49, 0, tegra_clk_tvo),
|
||||||
|
MUX("tvdac", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVDAC, 53, 0, tegra_clk_tvdac),
|
||||||
|
MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash),
|
||||||
|
MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed),
|
||||||
|
MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob),
|
||||||
|
MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
|
||||||
|
MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
|
||||||
|
MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
|
||||||
|
MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
|
||||||
|
MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8),
|
||||||
|
MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8),
|
||||||
|
MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8),
|
||||||
|
MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8),
|
||||||
|
MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8),
|
||||||
|
MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8),
|
||||||
|
MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
|
||||||
|
MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
|
||||||
|
MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
|
||||||
|
MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1),
|
||||||
|
MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
|
||||||
|
MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
|
||||||
|
MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
|
||||||
|
MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
|
||||||
|
MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
|
||||||
|
MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy),
|
||||||
|
MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
|
||||||
|
MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz),
|
||||||
|
MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock),
|
||||||
|
MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED),
|
||||||
|
NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL),
|
||||||
|
NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL),
|
||||||
|
NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock),
|
||||||
|
UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta),
|
||||||
|
UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
|
||||||
|
UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
|
||||||
|
UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
|
||||||
|
UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte),
|
||||||
|
XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
|
||||||
|
XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
|
||||||
|
XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
|
||||||
|
XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src),
|
||||||
|
XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct tegra_periph_init_data gate_clks[] = {
|
||||||
|
GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0),
|
||||||
|
GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0),
|
||||||
|
GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0),
|
||||||
|
GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
|
||||||
|
GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
|
||||||
|
GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
|
||||||
|
GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
|
||||||
|
GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
|
||||||
|
GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
|
||||||
|
GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
|
||||||
|
GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0),
|
||||||
|
GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0),
|
||||||
|
GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0),
|
||||||
|
GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0),
|
||||||
|
GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0),
|
||||||
|
GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
|
||||||
|
GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
|
||||||
|
GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0),
|
||||||
|
GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0),
|
||||||
|
GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0),
|
||||||
|
GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0),
|
||||||
|
GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0),
|
||||||
|
GATE("dtv", "clk_m", 79, TEGRA_PERIPH_ON_APB, tegra_clk_dtv, 0),
|
||||||
|
GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0),
|
||||||
|
GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0),
|
||||||
|
GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
|
||||||
|
GATE("dsia", "dsia_mux", 48, 0, tegra_clk_dsia, 0),
|
||||||
|
GATE("dsib", "dsib_mux", 82, 0, tegra_clk_dsib, 0),
|
||||||
|
GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
|
||||||
|
GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
|
||||||
|
GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
|
||||||
|
GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
|
||||||
|
GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
|
||||||
|
GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
|
||||||
|
GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pll_out_data {
|
||||||
|
char *div_name;
|
||||||
|
char *pll_out_name;
|
||||||
|
u32 offset;
|
||||||
|
int clk_id;
|
||||||
|
u8 div_shift;
|
||||||
|
u8 div_flags;
|
||||||
|
u8 rst_shift;
|
||||||
|
spinlock_t *lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PLL_OUT(_num, _offset, _div_shift, _div_flags, _rst_shift, _id) \
|
||||||
|
{\
|
||||||
|
.div_name = "pll_p_out" #_num "_div",\
|
||||||
|
.pll_out_name = "pll_p_out" #_num,\
|
||||||
|
.offset = _offset,\
|
||||||
|
.div_shift = _div_shift,\
|
||||||
|
.div_flags = _div_flags | TEGRA_DIVIDER_FIXED |\
|
||||||
|
TEGRA_DIVIDER_ROUND_UP,\
|
||||||
|
.rst_shift = _rst_shift,\
|
||||||
|
.clk_id = tegra_clk_ ## _id,\
|
||||||
|
.lock = &_offset ##_lock,\
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pll_out_data pllp_out_clks[] = {
|
||||||
|
PLL_OUT(1, PLLP_OUTA, 8, 0, 0, pll_p_out1),
|
||||||
|
PLL_OUT(2, PLLP_OUTA, 24, 0, 16, pll_p_out2),
|
||||||
|
PLL_OUT(2, PLLP_OUTA, 24, TEGRA_DIVIDER_INT, 16, pll_p_out2_int),
|
||||||
|
PLL_OUT(3, PLLP_OUTB, 8, 0, 0, pll_p_out3),
|
||||||
|
PLL_OUT(4, PLLP_OUTB, 24, 0, 16, pll_p_out4),
|
||||||
|
PLL_OUT(5, PLLP_OUTC, 24, 0, 16, pll_p_out5),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init periph_clk_init(void __iomem *clk_base,
|
||||||
|
struct tegra_clk *tegra_clks)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(periph_clks); i++) {
|
||||||
|
struct tegra_clk_periph_regs *bank;
|
||||||
|
struct tegra_periph_init_data *data;
|
||||||
|
|
||||||
|
data = periph_clks + i;
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bank = get_reg_bank(data->periph.gate.clk_num);
|
||||||
|
if (!bank)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
data->periph.gate.regs = bank;
|
||||||
|
clk = tegra_clk_register_periph(data->name,
|
||||||
|
data->p.parent_names, data->num_parents,
|
||||||
|
&data->periph, clk_base, data->offset,
|
||||||
|
data->flags);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init gate_clk_init(void __iomem *clk_base,
|
||||||
|
struct tegra_clk *tegra_clks)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(gate_clks); i++) {
|
||||||
|
struct tegra_periph_init_data *data;
|
||||||
|
|
||||||
|
data = gate_clks + i;
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = tegra_clk_register_periph_gate(data->name,
|
||||||
|
data->p.parent_name, data->periph.gate.flags,
|
||||||
|
clk_base, data->flags,
|
||||||
|
data->periph.gate.clk_num,
|
||||||
|
periph_clk_enb_refcnt);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
|
||||||
|
struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *pll_params)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
/* PLLP */
|
||||||
|
clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base,
|
||||||
|
pmc_base, 0, pll_params, NULL);
|
||||||
|
clk_register_clkdev(clk, "pll_p", NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(pllp_out_clks); i++) {
|
||||||
|
struct pll_out_data *data;
|
||||||
|
|
||||||
|
data = pllp_out_clks + i;
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = tegra_clk_register_divider(data->div_name, "pll_p",
|
||||||
|
clk_base + data->offset, 0, data->div_flags,
|
||||||
|
data->div_shift, 8, 1, data->lock);
|
||||||
|
clk = tegra_clk_register_pll_out(data->pll_out_name,
|
||||||
|
data->div_name, clk_base + data->offset,
|
||||||
|
data->rst_shift + 1, data->rst_shift,
|
||||||
|
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
|
||||||
|
data->lock);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init tegra_periph_clk_init(void __iomem *clk_base,
|
||||||
|
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *pll_params)
|
||||||
|
{
|
||||||
|
init_pllp(clk_base, pmc_base, tegra_clks, pll_params);
|
||||||
|
periph_clk_init(clk_base, tegra_clks);
|
||||||
|
gate_clk_init(clk_base, tegra_clks);
|
||||||
|
}
|
132
drivers/clk/tegra/clk-tegra-pmc.c
Normal file
132
drivers/clk/tegra/clk-tegra-pmc.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/clkdev.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
|
#include "clk.h"
|
||||||
|
#include "clk-id.h"
|
||||||
|
|
||||||
|
#define PMC_CLK_OUT_CNTRL 0x1a8
|
||||||
|
#define PMC_DPD_PADS_ORIDE 0x1c
|
||||||
|
#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
|
||||||
|
#define PMC_CTRL 0
|
||||||
|
#define PMC_CTRL_BLINK_ENB 7
|
||||||
|
#define PMC_BLINK_TIMER 0x40
|
||||||
|
|
||||||
|
struct pmc_clk_init_data {
|
||||||
|
char *mux_name;
|
||||||
|
char *gate_name;
|
||||||
|
const char **parents;
|
||||||
|
int num_parents;
|
||||||
|
int mux_id;
|
||||||
|
int gate_id;
|
||||||
|
char *dev_name;
|
||||||
|
u8 mux_shift;
|
||||||
|
u8 gate_shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PMC_CLK(_num, _mux_shift, _gate_shift)\
|
||||||
|
{\
|
||||||
|
.mux_name = "clk_out_" #_num "_mux",\
|
||||||
|
.gate_name = "clk_out_" #_num,\
|
||||||
|
.parents = clk_out ##_num ##_parents,\
|
||||||
|
.num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\
|
||||||
|
.mux_id = tegra_clk_clk_out_ ##_num ##_mux,\
|
||||||
|
.gate_id = tegra_clk_clk_out_ ##_num,\
|
||||||
|
.dev_name = "extern" #_num,\
|
||||||
|
.mux_shift = _mux_shift,\
|
||||||
|
.gate_shift = _gate_shift,\
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(clk_out_lock);
|
||||||
|
|
||||||
|
static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
|
||||||
|
"clk_m_div4", "extern1",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
|
||||||
|
"clk_m_div4", "extern2",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
|
||||||
|
"clk_m_div4", "extern3",
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pmc_clk_init_data pmc_clks[] = {
|
||||||
|
PMC_CLK(1, 6, 2),
|
||||||
|
PMC_CLK(2, 14, 10),
|
||||||
|
PMC_CLK(3, 22, 18),
|
||||||
|
};
|
||||||
|
|
||||||
|
void __init tegra_pmc_clk_init(void __iomem *pmc_base,
|
||||||
|
struct tegra_clk *tegra_clks)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) {
|
||||||
|
struct pmc_clk_init_data *data;
|
||||||
|
|
||||||
|
data = pmc_clks + i;
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = clk_register_mux(NULL, data->mux_name, data->parents,
|
||||||
|
data->num_parents, CLK_SET_RATE_NO_REPARENT,
|
||||||
|
pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
|
||||||
|
3, 0, &clk_out_lock);
|
||||||
|
*dt_clk = clk;
|
||||||
|
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
|
||||||
|
0, pmc_base + PMC_CLK_OUT_CNTRL,
|
||||||
|
data->gate_shift, 0, &clk_out_lock);
|
||||||
|
*dt_clk = clk;
|
||||||
|
clk_register_clkdev(clk, data->dev_name, data->gate_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* blink */
|
||||||
|
writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
|
||||||
|
clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
|
||||||
|
pmc_base + PMC_DPD_PADS_ORIDE,
|
||||||
|
PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clk = clk_register_gate(NULL, "blink", "blink_override", 0,
|
||||||
|
pmc_base + PMC_CTRL,
|
||||||
|
PMC_CTRL_BLINK_ENB, 0, NULL);
|
||||||
|
clk_register_clkdev(clk, "blink", NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
149
drivers/clk/tegra/clk-tegra-super-gen4.c
Normal file
149
drivers/clk/tegra/clk-tegra-super-gen4.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
|
#include "clk.h"
|
||||||
|
#include "clk-id.h"
|
||||||
|
|
||||||
|
#define PLLX_BASE 0xe0
|
||||||
|
#define PLLX_MISC 0xe4
|
||||||
|
#define PLLX_MISC2 0x514
|
||||||
|
#define PLLX_MISC3 0x518
|
||||||
|
|
||||||
|
#define CCLKG_BURST_POLICY 0x368
|
||||||
|
#define CCLKLP_BURST_POLICY 0x370
|
||||||
|
#define SCLK_BURST_POLICY 0x028
|
||||||
|
#define SYSTEM_CLK_RATE 0x030
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(sysrate_lock);
|
||||||
|
|
||||||
|
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
|
||||||
|
"pll_p", "pll_p_out2", "unused",
|
||||||
|
"clk_32k", "pll_m_out1" };
|
||||||
|
|
||||||
|
static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
||||||
|
"pll_p", "pll_p_out4", "unused",
|
||||||
|
"unused", "pll_x" };
|
||||||
|
|
||||||
|
static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
||||||
|
"pll_p", "pll_p_out4", "unused",
|
||||||
|
"unused", "pll_x", "pll_x_out0" };
|
||||||
|
|
||||||
|
static void __init tegra_sclk_init(void __iomem *clk_base,
|
||||||
|
struct tegra_clk *tegra_clks)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
|
||||||
|
/* SCLK */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = tegra_clk_register_super_mux("sclk", sclk_parents,
|
||||||
|
ARRAY_SIZE(sclk_parents),
|
||||||
|
CLK_SET_RATE_PARENT,
|
||||||
|
clk_base + SCLK_BURST_POLICY,
|
||||||
|
0, 4, 0, 0, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HCLK */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_hclk, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
|
||||||
|
clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
|
||||||
|
&sysrate_lock);
|
||||||
|
clk = clk_register_gate(NULL, "hclk", "hclk_div",
|
||||||
|
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||||
|
clk_base + SYSTEM_CLK_RATE,
|
||||||
|
7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PCLK */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pclk, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
|
||||||
|
clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
|
||||||
|
&sysrate_lock);
|
||||||
|
clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
|
||||||
|
CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
|
||||||
|
3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
|
||||||
|
void __iomem *pmc_base,
|
||||||
|
struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *params)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk **dt_clk;
|
||||||
|
|
||||||
|
/* CCLKG */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
|
||||||
|
ARRAY_SIZE(cclk_g_parents),
|
||||||
|
CLK_SET_RATE_PARENT,
|
||||||
|
clk_base + CCLKG_BURST_POLICY,
|
||||||
|
0, 4, 0, 0, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CCLKLP */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
|
||||||
|
if (dt_clk) {
|
||||||
|
clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
|
||||||
|
ARRAY_SIZE(cclk_lp_parents),
|
||||||
|
CLK_SET_RATE_PARENT,
|
||||||
|
clk_base + CCLKLP_BURST_POLICY,
|
||||||
|
0, 4, 8, 9, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
tegra_sclk_init(clk_base, tegra_clks);
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
|
||||||
|
/* PLLX */
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
|
||||||
|
pmc_base, CLK_IGNORE_UNUSED, params, NULL);
|
||||||
|
*dt_clk = clk;
|
||||||
|
|
||||||
|
/* PLLX_OUT0 */
|
||||||
|
|
||||||
|
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
|
||||||
|
if (!dt_clk)
|
||||||
|
return;
|
||||||
|
clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
|
||||||
|
CLK_SET_RATE_PARENT, 1, 2);
|
||||||
|
*dt_clk = clk;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
1424
drivers/clk/tegra/clk-tegra124.c
Normal file
1424
drivers/clk/tegra/clk-tegra124.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -18,13 +18,175 @@
|
|||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/clk/tegra.h>
|
#include <linux/clk/tegra.h>
|
||||||
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/tegra-soc.h>
|
||||||
|
|
||||||
#include "clk.h"
|
#include "clk.h"
|
||||||
|
|
||||||
|
#define CLK_OUT_ENB_L 0x010
|
||||||
|
#define CLK_OUT_ENB_H 0x014
|
||||||
|
#define CLK_OUT_ENB_U 0x018
|
||||||
|
#define CLK_OUT_ENB_V 0x360
|
||||||
|
#define CLK_OUT_ENB_W 0x364
|
||||||
|
#define CLK_OUT_ENB_X 0x280
|
||||||
|
#define CLK_OUT_ENB_SET_L 0x320
|
||||||
|
#define CLK_OUT_ENB_CLR_L 0x324
|
||||||
|
#define CLK_OUT_ENB_SET_H 0x328
|
||||||
|
#define CLK_OUT_ENB_CLR_H 0x32c
|
||||||
|
#define CLK_OUT_ENB_SET_U 0x330
|
||||||
|
#define CLK_OUT_ENB_CLR_U 0x334
|
||||||
|
#define CLK_OUT_ENB_SET_V 0x440
|
||||||
|
#define CLK_OUT_ENB_CLR_V 0x444
|
||||||
|
#define CLK_OUT_ENB_SET_W 0x448
|
||||||
|
#define CLK_OUT_ENB_CLR_W 0x44c
|
||||||
|
#define CLK_OUT_ENB_SET_X 0x284
|
||||||
|
#define CLK_OUT_ENB_CLR_X 0x288
|
||||||
|
|
||||||
|
#define RST_DEVICES_L 0x004
|
||||||
|
#define RST_DEVICES_H 0x008
|
||||||
|
#define RST_DEVICES_U 0x00C
|
||||||
|
#define RST_DFLL_DVCO 0x2F4
|
||||||
|
#define RST_DEVICES_V 0x358
|
||||||
|
#define RST_DEVICES_W 0x35C
|
||||||
|
#define RST_DEVICES_X 0x28C
|
||||||
|
#define RST_DEVICES_SET_L 0x300
|
||||||
|
#define RST_DEVICES_CLR_L 0x304
|
||||||
|
#define RST_DEVICES_SET_H 0x308
|
||||||
|
#define RST_DEVICES_CLR_H 0x30c
|
||||||
|
#define RST_DEVICES_SET_U 0x310
|
||||||
|
#define RST_DEVICES_CLR_U 0x314
|
||||||
|
#define RST_DEVICES_SET_V 0x430
|
||||||
|
#define RST_DEVICES_CLR_V 0x434
|
||||||
|
#define RST_DEVICES_SET_W 0x438
|
||||||
|
#define RST_DEVICES_CLR_W 0x43c
|
||||||
|
#define RST_DEVICES_SET_X 0x290
|
||||||
|
#define RST_DEVICES_CLR_X 0x294
|
||||||
|
|
||||||
/* Global data of Tegra CPU CAR ops */
|
/* Global data of Tegra CPU CAR ops */
|
||||||
static struct tegra_cpu_car_ops dummy_car_ops;
|
static struct tegra_cpu_car_ops dummy_car_ops;
|
||||||
struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
|
struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
|
||||||
|
|
||||||
|
int *periph_clk_enb_refcnt;
|
||||||
|
static int periph_banks;
|
||||||
|
static struct clk **clks;
|
||||||
|
static int clk_num;
|
||||||
|
static struct clk_onecell_data clk_data;
|
||||||
|
|
||||||
|
static struct tegra_clk_periph_regs periph_regs[] = {
|
||||||
|
[0] = {
|
||||||
|
.enb_reg = CLK_OUT_ENB_L,
|
||||||
|
.enb_set_reg = CLK_OUT_ENB_SET_L,
|
||||||
|
.enb_clr_reg = CLK_OUT_ENB_CLR_L,
|
||||||
|
.rst_reg = RST_DEVICES_L,
|
||||||
|
.rst_set_reg = RST_DEVICES_SET_L,
|
||||||
|
.rst_clr_reg = RST_DEVICES_CLR_L,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.enb_reg = CLK_OUT_ENB_H,
|
||||||
|
.enb_set_reg = CLK_OUT_ENB_SET_H,
|
||||||
|
.enb_clr_reg = CLK_OUT_ENB_CLR_H,
|
||||||
|
.rst_reg = RST_DEVICES_H,
|
||||||
|
.rst_set_reg = RST_DEVICES_SET_H,
|
||||||
|
.rst_clr_reg = RST_DEVICES_CLR_H,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.enb_reg = CLK_OUT_ENB_U,
|
||||||
|
.enb_set_reg = CLK_OUT_ENB_SET_U,
|
||||||
|
.enb_clr_reg = CLK_OUT_ENB_CLR_U,
|
||||||
|
.rst_reg = RST_DEVICES_U,
|
||||||
|
.rst_set_reg = RST_DEVICES_SET_U,
|
||||||
|
.rst_clr_reg = RST_DEVICES_CLR_U,
|
||||||
|
},
|
||||||
|
[3] = {
|
||||||
|
.enb_reg = CLK_OUT_ENB_V,
|
||||||
|
.enb_set_reg = CLK_OUT_ENB_SET_V,
|
||||||
|
.enb_clr_reg = CLK_OUT_ENB_CLR_V,
|
||||||
|
.rst_reg = RST_DEVICES_V,
|
||||||
|
.rst_set_reg = RST_DEVICES_SET_V,
|
||||||
|
.rst_clr_reg = RST_DEVICES_CLR_V,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
.enb_reg = CLK_OUT_ENB_W,
|
||||||
|
.enb_set_reg = CLK_OUT_ENB_SET_W,
|
||||||
|
.enb_clr_reg = CLK_OUT_ENB_CLR_W,
|
||||||
|
.rst_reg = RST_DEVICES_W,
|
||||||
|
.rst_set_reg = RST_DEVICES_SET_W,
|
||||||
|
.rst_clr_reg = RST_DEVICES_CLR_W,
|
||||||
|
},
|
||||||
|
[5] = {
|
||||||
|
.enb_reg = CLK_OUT_ENB_X,
|
||||||
|
.enb_set_reg = CLK_OUT_ENB_SET_X,
|
||||||
|
.enb_clr_reg = CLK_OUT_ENB_CLR_X,
|
||||||
|
.rst_reg = RST_DEVICES_X,
|
||||||
|
.rst_set_reg = RST_DEVICES_SET_X,
|
||||||
|
.rst_clr_reg = RST_DEVICES_CLR_X,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __iomem *clk_base;
|
||||||
|
|
||||||
|
static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If peripheral is on the APB bus then we must read the APB bus to
|
||||||
|
* flush the write operation in apb bus. This will avoid peripheral
|
||||||
|
* access after disabling clock. Since the reset driver has no
|
||||||
|
* knowledge of which reset IDs represent which devices, simply do
|
||||||
|
* this all the time.
|
||||||
|
*/
|
||||||
|
tegra_read_chipid();
|
||||||
|
|
||||||
|
writel_relaxed(BIT(id % 32),
|
||||||
|
clk_base + periph_regs[id / 32].rst_set_reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
writel_relaxed(BIT(id % 32),
|
||||||
|
clk_base + periph_regs[id / 32].rst_clr_reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tegra_clk_periph_regs *get_reg_bank(int clkid)
|
||||||
|
{
|
||||||
|
int reg_bank = clkid / 32;
|
||||||
|
|
||||||
|
if (reg_bank < periph_banks)
|
||||||
|
return &periph_regs[reg_bank];
|
||||||
|
else {
|
||||||
|
WARN_ON(1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
|
||||||
|
{
|
||||||
|
clk_base = regs;
|
||||||
|
|
||||||
|
if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
periph_clk_enb_refcnt = kzalloc(32 * banks *
|
||||||
|
sizeof(*periph_clk_enb_refcnt), GFP_KERNEL);
|
||||||
|
if (!periph_clk_enb_refcnt)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
periph_banks = banks;
|
||||||
|
|
||||||
|
clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL);
|
||||||
|
if (!clks)
|
||||||
|
kfree(periph_clk_enb_refcnt);
|
||||||
|
|
||||||
|
clk_num = num;
|
||||||
|
|
||||||
|
return clks;
|
||||||
|
}
|
||||||
|
|
||||||
void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
|
void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
|
||||||
struct clk *clks[], int clk_max)
|
struct clk *clks[], int clk_max)
|
||||||
{
|
{
|
||||||
@ -74,6 +236,58 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct reset_control_ops rst_ops = {
|
||||||
|
.assert = tegra_clk_rst_assert,
|
||||||
|
.deassert = tegra_clk_rst_deassert,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct reset_controller_dev rst_ctlr = {
|
||||||
|
.ops = &rst_ops,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_reset_n_cells = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
void __init tegra_add_of_provider(struct device_node *np)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < clk_num; i++) {
|
||||||
|
if (IS_ERR(clks[i])) {
|
||||||
|
pr_err
|
||||||
|
("Tegra clk %d: register failed with %ld\n",
|
||||||
|
i, PTR_ERR(clks[i]));
|
||||||
|
}
|
||||||
|
if (!clks[i])
|
||||||
|
clks[i] = ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_data.clks = clks;
|
||||||
|
clk_data.clk_num = clk_num;
|
||||||
|
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||||
|
|
||||||
|
rst_ctlr.of_node = np;
|
||||||
|
rst_ctlr.nr_resets = clk_num * 32;
|
||||||
|
reset_controller_register(&rst_ctlr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++, dev_clks++)
|
||||||
|
clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
|
||||||
|
dev_clks->dev_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct clk ** __init tegra_lookup_dt_id(int clk_id,
|
||||||
|
struct tegra_clk *tegra_clk)
|
||||||
|
{
|
||||||
|
if (tegra_clk[clk_id].present)
|
||||||
|
return &clks[tegra_clk[clk_id].dt_id];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
|
tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
|
||||||
|
|
||||||
void __init tegra_clocks_apply_init_table(void)
|
void __init tegra_clocks_apply_init_table(void)
|
||||||
|
@ -37,6 +37,8 @@ struct tegra_clk_sync_source {
|
|||||||
container_of(_hw, struct tegra_clk_sync_source, hw)
|
container_of(_hw, struct tegra_clk_sync_source, hw)
|
||||||
|
|
||||||
extern const struct clk_ops tegra_clk_sync_source_ops;
|
extern const struct clk_ops tegra_clk_sync_source_ops;
|
||||||
|
extern int *periph_clk_enb_refcnt;
|
||||||
|
|
||||||
struct clk *tegra_clk_register_sync_source(const char *name,
|
struct clk *tegra_clk_register_sync_source(const char *name,
|
||||||
unsigned long fixed_rate, unsigned long max_rate);
|
unsigned long fixed_rate, unsigned long max_rate);
|
||||||
|
|
||||||
@ -188,12 +190,15 @@ struct tegra_clk_pll_params {
|
|||||||
u32 ext_misc_reg[3];
|
u32 ext_misc_reg[3];
|
||||||
u32 pmc_divnm_reg;
|
u32 pmc_divnm_reg;
|
||||||
u32 pmc_divp_reg;
|
u32 pmc_divp_reg;
|
||||||
|
u32 flags;
|
||||||
int stepa_shift;
|
int stepa_shift;
|
||||||
int stepb_shift;
|
int stepb_shift;
|
||||||
int lock_delay;
|
int lock_delay;
|
||||||
int max_p;
|
int max_p;
|
||||||
struct pdiv_map *pdiv_tohw;
|
struct pdiv_map *pdiv_tohw;
|
||||||
struct div_nmp *div_nmp;
|
struct div_nmp *div_nmp;
|
||||||
|
struct tegra_clk_pll_freq_table *freq_table;
|
||||||
|
unsigned long fixed_rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,10 +238,7 @@ struct tegra_clk_pll {
|
|||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
void __iomem *clk_base;
|
void __iomem *clk_base;
|
||||||
void __iomem *pmc;
|
void __iomem *pmc;
|
||||||
u32 flags;
|
|
||||||
unsigned long fixed_rate;
|
|
||||||
spinlock_t *lock;
|
spinlock_t *lock;
|
||||||
struct tegra_clk_pll_freq_table *freq_table;
|
|
||||||
struct tegra_clk_pll_params *params;
|
struct tegra_clk_pll_params *params;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -258,56 +260,49 @@ extern const struct clk_ops tegra_clk_pll_ops;
|
|||||||
extern const struct clk_ops tegra_clk_plle_ops;
|
extern const struct clk_ops tegra_clk_plle_ops;
|
||||||
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags, struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
|
spinlock_t *lock);
|
||||||
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
|
|
||||||
|
|
||||||
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags, struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
|
spinlock_t *lock);
|
||||||
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
|
|
||||||
|
|
||||||
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock);
|
spinlock_t *lock);
|
||||||
|
|
||||||
struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock);
|
spinlock_t *lock);
|
||||||
|
|
||||||
struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock);
|
spinlock_t *lock);
|
||||||
|
|
||||||
struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
||||||
void __iomem *clk_base, void __iomem *pmc,
|
void __iomem *clk_base, void __iomem *pmc,
|
||||||
unsigned long flags, unsigned long fixed_rate,
|
unsigned long flags,
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
u32 pll_flags,
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock, unsigned long parent_rate);
|
spinlock_t *lock, unsigned long parent_rate);
|
||||||
|
|
||||||
struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
||||||
const char *parent_name,
|
const char *parent_name,
|
||||||
void __iomem *clk_base, unsigned long flags,
|
void __iomem *clk_base, unsigned long flags,
|
||||||
unsigned long fixed_rate,
|
|
||||||
struct tegra_clk_pll_params *pll_params,
|
struct tegra_clk_pll_params *pll_params,
|
||||||
struct tegra_clk_pll_freq_table *freq_table,
|
|
||||||
spinlock_t *lock);
|
spinlock_t *lock);
|
||||||
|
|
||||||
|
struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
|
||||||
|
void __iomem *clk_base, unsigned long flags,
|
||||||
|
struct tegra_clk_pll_params *pll_params,
|
||||||
|
spinlock_t *lock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct tegra_clk_pll_out - PLL divider down clock
|
* struct tegra_clk_pll_out - PLL divider down clock
|
||||||
*
|
*
|
||||||
@ -395,13 +390,13 @@ struct tegra_clk_periph_gate {
|
|||||||
#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
|
#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
|
||||||
#define TEGRA_PERIPH_ON_APB BIT(2)
|
#define TEGRA_PERIPH_ON_APB BIT(2)
|
||||||
#define TEGRA_PERIPH_WAR_1005168 BIT(3)
|
#define TEGRA_PERIPH_WAR_1005168 BIT(3)
|
||||||
|
#define TEGRA_PERIPH_NO_DIV BIT(4)
|
||||||
|
#define TEGRA_PERIPH_NO_GATE BIT(5)
|
||||||
|
|
||||||
void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
|
|
||||||
extern const struct clk_ops tegra_clk_periph_gate_ops;
|
extern const struct clk_ops tegra_clk_periph_gate_ops;
|
||||||
struct clk *tegra_clk_register_periph_gate(const char *name,
|
struct clk *tegra_clk_register_periph_gate(const char *name,
|
||||||
const char *parent_name, u8 gate_flags, void __iomem *clk_base,
|
const char *parent_name, u8 gate_flags, void __iomem *clk_base,
|
||||||
unsigned long flags, int clk_num,
|
unsigned long flags, int clk_num, int *enable_refcnt);
|
||||||
struct tegra_clk_periph_regs *pregs, int *enable_refcnt);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct clk-periph - peripheral clock
|
* struct clk-periph - peripheral clock
|
||||||
@ -443,26 +438,26 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
|
|||||||
|
|
||||||
#define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \
|
#define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \
|
||||||
_div_shift, _div_width, _div_frac_width, \
|
_div_shift, _div_width, _div_frac_width, \
|
||||||
_div_flags, _clk_num, _enb_refcnt, _regs, \
|
_div_flags, _clk_num,\
|
||||||
_gate_flags, _table) \
|
_gate_flags, _table, _lock) \
|
||||||
{ \
|
{ \
|
||||||
.mux = { \
|
.mux = { \
|
||||||
.flags = _mux_flags, \
|
.flags = _mux_flags, \
|
||||||
.shift = _mux_shift, \
|
.shift = _mux_shift, \
|
||||||
.mask = _mux_mask, \
|
.mask = _mux_mask, \
|
||||||
.table = _table, \
|
.table = _table, \
|
||||||
|
.lock = _lock, \
|
||||||
}, \
|
}, \
|
||||||
.divider = { \
|
.divider = { \
|
||||||
.flags = _div_flags, \
|
.flags = _div_flags, \
|
||||||
.shift = _div_shift, \
|
.shift = _div_shift, \
|
||||||
.width = _div_width, \
|
.width = _div_width, \
|
||||||
.frac_width = _div_frac_width, \
|
.frac_width = _div_frac_width, \
|
||||||
|
.lock = _lock, \
|
||||||
}, \
|
}, \
|
||||||
.gate = { \
|
.gate = { \
|
||||||
.flags = _gate_flags, \
|
.flags = _gate_flags, \
|
||||||
.clk_num = _clk_num, \
|
.clk_num = _clk_num, \
|
||||||
.enable_refcnt = _enb_refcnt, \
|
|
||||||
.regs = _regs, \
|
|
||||||
}, \
|
}, \
|
||||||
.mux_ops = &clk_mux_ops, \
|
.mux_ops = &clk_mux_ops, \
|
||||||
.div_ops = &tegra_clk_frac_div_ops, \
|
.div_ops = &tegra_clk_frac_div_ops, \
|
||||||
@ -472,7 +467,10 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
|
|||||||
struct tegra_periph_init_data {
|
struct tegra_periph_init_data {
|
||||||
const char *name;
|
const char *name;
|
||||||
int clk_id;
|
int clk_id;
|
||||||
const char **parent_names;
|
union {
|
||||||
|
const char **parent_names;
|
||||||
|
const char *parent_name;
|
||||||
|
} p;
|
||||||
int num_parents;
|
int num_parents;
|
||||||
struct tegra_clk_periph periph;
|
struct tegra_clk_periph periph;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
@ -483,20 +481,19 @@ struct tegra_periph_init_data {
|
|||||||
|
|
||||||
#define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
|
#define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
|
||||||
_mux_shift, _mux_mask, _mux_flags, _div_shift, \
|
_mux_shift, _mux_mask, _mux_flags, _div_shift, \
|
||||||
_div_width, _div_frac_width, _div_flags, _regs, \
|
_div_width, _div_frac_width, _div_flags, \
|
||||||
_clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
|
_clk_num, _gate_flags, _clk_id, _table, \
|
||||||
_flags) \
|
_flags, _lock) \
|
||||||
{ \
|
{ \
|
||||||
.name = _name, \
|
.name = _name, \
|
||||||
.clk_id = _clk_id, \
|
.clk_id = _clk_id, \
|
||||||
.parent_names = _parent_names, \
|
.p.parent_names = _parent_names, \
|
||||||
.num_parents = ARRAY_SIZE(_parent_names), \
|
.num_parents = ARRAY_SIZE(_parent_names), \
|
||||||
.periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \
|
.periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \
|
||||||
_mux_flags, _div_shift, \
|
_mux_flags, _div_shift, \
|
||||||
_div_width, _div_frac_width, \
|
_div_width, _div_frac_width, \
|
||||||
_div_flags, _clk_num, \
|
_div_flags, _clk_num, \
|
||||||
_enb_refcnt, _regs, \
|
_gate_flags, _table, _lock), \
|
||||||
_gate_flags, _table), \
|
|
||||||
.offset = _offset, \
|
.offset = _offset, \
|
||||||
.con_id = _con_id, \
|
.con_id = _con_id, \
|
||||||
.dev_id = _dev_id, \
|
.dev_id = _dev_id, \
|
||||||
@ -505,13 +502,13 @@ struct tegra_periph_init_data {
|
|||||||
|
|
||||||
#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
|
#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
|
||||||
_mux_shift, _mux_width, _mux_flags, _div_shift, \
|
_mux_shift, _mux_width, _mux_flags, _div_shift, \
|
||||||
_div_width, _div_frac_width, _div_flags, _regs, \
|
_div_width, _div_frac_width, _div_flags, \
|
||||||
_clk_num, _enb_refcnt, _gate_flags, _clk_id) \
|
_clk_num, _gate_flags, _clk_id) \
|
||||||
TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
|
TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
|
||||||
_mux_shift, BIT(_mux_width) - 1, _mux_flags, \
|
_mux_shift, BIT(_mux_width) - 1, _mux_flags, \
|
||||||
_div_shift, _div_width, _div_frac_width, _div_flags, \
|
_div_shift, _div_width, _div_frac_width, _div_flags, \
|
||||||
_regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
|
_clk_num, _gate_flags, _clk_id,\
|
||||||
NULL, 0)
|
NULL, 0, NULL)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct clk_super_mux - super clock
|
* struct clk_super_mux - super clock
|
||||||
@ -581,12 +578,49 @@ struct tegra_clk_duplicate {
|
|||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tegra_clk {
|
||||||
|
int dt_id;
|
||||||
|
bool present;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tegra_devclk {
|
||||||
|
int dt_id;
|
||||||
|
char *dev_id;
|
||||||
|
char *con_id;
|
||||||
|
};
|
||||||
|
|
||||||
void tegra_init_from_table(struct tegra_clk_init_table *tbl,
|
void tegra_init_from_table(struct tegra_clk_init_table *tbl,
|
||||||
struct clk *clks[], int clk_max);
|
struct clk *clks[], int clk_max);
|
||||||
|
|
||||||
void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
|
void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
|
||||||
struct clk *clks[], int clk_max);
|
struct clk *clks[], int clk_max);
|
||||||
|
|
||||||
|
struct tegra_clk_periph_regs *get_reg_bank(int clkid);
|
||||||
|
struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
|
||||||
|
|
||||||
|
struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
|
||||||
|
|
||||||
|
void tegra_add_of_provider(struct device_node *np);
|
||||||
|
void tegra_register_devclks(struct tegra_devclk *dev_clks, int num);
|
||||||
|
|
||||||
|
void tegra_audio_clk_init(void __iomem *clk_base,
|
||||||
|
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *pll_params);
|
||||||
|
|
||||||
|
void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
|
||||||
|
struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *pll_params);
|
||||||
|
|
||||||
|
void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks);
|
||||||
|
void tegra_fixed_clk_init(struct tegra_clk *tegra_clks);
|
||||||
|
int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks,
|
||||||
|
unsigned long *input_freqs, int num,
|
||||||
|
unsigned long *osc_freq,
|
||||||
|
unsigned long *pll_ref_freq);
|
||||||
|
void tegra_super_clk_gen4_init(void __iomem *clk_base,
|
||||||
|
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||||
|
struct tegra_clk_pll_params *pll_params);
|
||||||
|
|
||||||
void tegra114_clock_tune_cpu_trimmers_high(void);
|
void tegra114_clock_tune_cpu_trimmers_high(void);
|
||||||
void tegra114_clock_tune_cpu_trimmers_low(void);
|
void tegra114_clock_tune_cpu_trimmers_low(void);
|
||||||
void tegra114_clock_tune_cpu_trimmers_init(void);
|
void tegra114_clock_tune_cpu_trimmers_init(void);
|
||||||
|
@ -535,11 +535,41 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dma_get_slave_channel);
|
EXPORT_SYMBOL_GPL(dma_get_slave_channel);
|
||||||
|
|
||||||
|
struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
|
||||||
|
{
|
||||||
|
dma_cap_mask_t mask;
|
||||||
|
struct dma_chan *chan;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
dma_cap_zero(mask);
|
||||||
|
dma_cap_set(DMA_SLAVE, mask);
|
||||||
|
|
||||||
|
/* lock against __dma_request_channel */
|
||||||
|
mutex_lock(&dma_list_mutex);
|
||||||
|
|
||||||
|
chan = private_candidate(&mask, device, NULL, NULL);
|
||||||
|
if (chan) {
|
||||||
|
err = dma_chan_get(chan);
|
||||||
|
if (err) {
|
||||||
|
pr_debug("%s: failed to get %s: (%d)\n",
|
||||||
|
__func__, dma_chan_name(chan), err);
|
||||||
|
chan = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&dma_list_mutex);
|
||||||
|
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __dma_request_channel - try to allocate an exclusive channel
|
* __dma_request_channel - try to allocate an exclusive channel
|
||||||
* @mask: capabilities that the channel must satisfy
|
* @mask: capabilities that the channel must satisfy
|
||||||
* @fn: optional callback to disposition available channels
|
* @fn: optional callback to disposition available channels
|
||||||
* @fn_param: opaque parameter to pass to dma_filter_fn
|
* @fn_param: opaque parameter to pass to dma_filter_fn
|
||||||
|
*
|
||||||
|
* Returns pointer to appropriate DMA channel on success or NULL.
|
||||||
*/
|
*/
|
||||||
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
|
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
|
||||||
dma_filter_fn fn, void *fn_param)
|
dma_filter_fn fn, void *fn_param)
|
||||||
@ -591,18 +621,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
|
|||||||
* dma_request_slave_channel - try to allocate an exclusive slave channel
|
* dma_request_slave_channel - try to allocate an exclusive slave channel
|
||||||
* @dev: pointer to client device structure
|
* @dev: pointer to client device structure
|
||||||
* @name: slave channel name
|
* @name: slave channel name
|
||||||
|
*
|
||||||
|
* Returns pointer to appropriate DMA channel on success or an error pointer.
|
||||||
*/
|
*/
|
||||||
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
|
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
|
||||||
|
const char *name)
|
||||||
{
|
{
|
||||||
|
struct dma_chan *chan;
|
||||||
|
|
||||||
/* If device-tree is present get slave info from here */
|
/* If device-tree is present get slave info from here */
|
||||||
if (dev->of_node)
|
if (dev->of_node)
|
||||||
return of_dma_request_slave_channel(dev->of_node, name);
|
return of_dma_request_slave_channel(dev->of_node, name);
|
||||||
|
|
||||||
/* If device was enumerated by ACPI get slave info from here */
|
/* If device was enumerated by ACPI get slave info from here */
|
||||||
if (ACPI_HANDLE(dev))
|
if (ACPI_HANDLE(dev)) {
|
||||||
return acpi_dma_request_slave_chan_by_name(dev, name);
|
chan = acpi_dma_request_slave_chan_by_name(dev, name);
|
||||||
|
if (chan)
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dma_request_slave_channel - try to allocate an exclusive slave channel
|
||||||
|
* @dev: pointer to client device structure
|
||||||
|
* @name: slave channel name
|
||||||
|
*
|
||||||
|
* Returns pointer to appropriate DMA channel on success or NULL.
|
||||||
|
*/
|
||||||
|
struct dma_chan *dma_request_slave_channel(struct device *dev,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
|
||||||
|
if (IS_ERR(ch))
|
||||||
|
return NULL;
|
||||||
|
return ch;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
|
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
|
||||||
|
|
||||||
|
@ -893,33 +893,17 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
|
|||||||
struct of_dma *ofdma)
|
struct of_dma *ofdma)
|
||||||
{
|
{
|
||||||
struct mmp_pdma_device *d = ofdma->of_dma_data;
|
struct mmp_pdma_device *d = ofdma->of_dma_data;
|
||||||
struct dma_chan *chan, *candidate;
|
struct dma_chan *chan;
|
||||||
|
struct mmp_pdma_chan *c;
|
||||||
|
|
||||||
retry:
|
chan = dma_get_any_slave_channel(&d->device);
|
||||||
candidate = NULL;
|
if (!chan)
|
||||||
|
|
||||||
/* walk the list of channels registered with the current instance and
|
|
||||||
* find one that is currently unused */
|
|
||||||
list_for_each_entry(chan, &d->device.channels, device_node)
|
|
||||||
if (chan->client_count == 0) {
|
|
||||||
candidate = chan;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!candidate)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* dma_get_slave_channel will return NULL if we lost a race between
|
c = to_mmp_pdma_chan(chan);
|
||||||
* the lookup and the reservation */
|
c->drcmr = dma_spec->args[0];
|
||||||
chan = dma_get_slave_channel(candidate);
|
|
||||||
|
|
||||||
if (chan) {
|
return chan;
|
||||||
struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan);
|
|
||||||
c->drcmr = dma_spec->args[0];
|
|
||||||
return chan;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto retry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmp_pdma_probe(struct platform_device *op)
|
static int mmp_pdma_probe(struct platform_device *op)
|
||||||
|
@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
|
|||||||
* @np: device node to get DMA request from
|
* @np: device node to get DMA request from
|
||||||
* @name: name of desired channel
|
* @name: name of desired channel
|
||||||
*
|
*
|
||||||
* Returns pointer to appropriate dma channel on success or NULL on error.
|
* Returns pointer to appropriate DMA channel on success or an error pointer.
|
||||||
*/
|
*/
|
||||||
struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
||||||
const char *name)
|
const char *name)
|
||||||
@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
|||||||
struct of_dma *ofdma;
|
struct of_dma *ofdma;
|
||||||
struct dma_chan *chan;
|
struct dma_chan *chan;
|
||||||
int count, i;
|
int count, i;
|
||||||
|
int ret_no_channel = -ENODEV;
|
||||||
|
|
||||||
if (!np || !name) {
|
if (!np || !name) {
|
||||||
pr_err("%s: not enough information provided\n", __func__);
|
pr_err("%s: not enough information provided\n", __func__);
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
count = of_property_count_strings(np, "dma-names");
|
count = of_property_count_strings(np, "dma-names");
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
pr_err("%s: dma-names property of node '%s' missing or empty\n",
|
pr_err("%s: dma-names property of node '%s' missing or empty\n",
|
||||||
__func__, np->full_name);
|
__func__, np->full_name);
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
|||||||
mutex_lock(&of_dma_lock);
|
mutex_lock(&of_dma_lock);
|
||||||
ofdma = of_dma_find_controller(&dma_spec);
|
ofdma = of_dma_find_controller(&dma_spec);
|
||||||
|
|
||||||
if (ofdma)
|
if (ofdma) {
|
||||||
chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
|
chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
|
||||||
else
|
} else {
|
||||||
|
ret_no_channel = -EPROBE_DEFER;
|
||||||
chan = NULL;
|
chan = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&of_dma_lock);
|
mutex_unlock(&of_dma_lock);
|
||||||
|
|
||||||
@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
|
|||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return ERR_PTR(ret_no_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* DMA driver for Nvidia's Tegra20 APB DMA controller.
|
* DMA driver for Nvidia's Tegra20 APB DMA controller.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@ -29,11 +29,12 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/of_dma.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/clk/tegra.h>
|
|
||||||
|
|
||||||
#include "dmaengine.h"
|
#include "dmaengine.h"
|
||||||
|
|
||||||
@ -199,6 +200,7 @@ struct tegra_dma_channel {
|
|||||||
void *callback_param;
|
void *callback_param;
|
||||||
|
|
||||||
/* Channel-slave specific configuration */
|
/* Channel-slave specific configuration */
|
||||||
|
unsigned int slave_id;
|
||||||
struct dma_slave_config dma_sconfig;
|
struct dma_slave_config dma_sconfig;
|
||||||
struct tegra_dma_channel_regs channel_reg;
|
struct tegra_dma_channel_regs channel_reg;
|
||||||
};
|
};
|
||||||
@ -208,6 +210,7 @@ struct tegra_dma {
|
|||||||
struct dma_device dma_dev;
|
struct dma_device dma_dev;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *dma_clk;
|
struct clk *dma_clk;
|
||||||
|
struct reset_control *rst;
|
||||||
spinlock_t global_lock;
|
spinlock_t global_lock;
|
||||||
void __iomem *base_addr;
|
void __iomem *base_addr;
|
||||||
const struct tegra_dma_chip_data *chip_data;
|
const struct tegra_dma_chip_data *chip_data;
|
||||||
@ -339,6 +342,8 @@ static int tegra_dma_slave_config(struct dma_chan *dc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
|
memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
|
||||||
|
if (!tdc->slave_id)
|
||||||
|
tdc->slave_id = sconfig->slave_id;
|
||||||
tdc->config_init = true;
|
tdc->config_init = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -941,7 +946,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
|
|||||||
ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
|
ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
|
||||||
|
|
||||||
csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW;
|
csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW;
|
||||||
csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
||||||
if (flags & DMA_PREP_INTERRUPT)
|
if (flags & DMA_PREP_INTERRUPT)
|
||||||
csr |= TEGRA_APBDMA_CSR_IE_EOC;
|
csr |= TEGRA_APBDMA_CSR_IE_EOC;
|
||||||
|
|
||||||
@ -1085,7 +1090,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
|
|||||||
csr |= TEGRA_APBDMA_CSR_FLOW;
|
csr |= TEGRA_APBDMA_CSR_FLOW;
|
||||||
if (flags & DMA_PREP_INTERRUPT)
|
if (flags & DMA_PREP_INTERRUPT)
|
||||||
csr |= TEGRA_APBDMA_CSR_IE_EOC;
|
csr |= TEGRA_APBDMA_CSR_IE_EOC;
|
||||||
csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
|
||||||
|
|
||||||
apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
|
apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
|
||||||
|
|
||||||
@ -1205,6 +1210,25 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
|
|||||||
kfree(sg_req);
|
kfree(sg_req);
|
||||||
}
|
}
|
||||||
clk_disable_unprepare(tdma->dma_clk);
|
clk_disable_unprepare(tdma->dma_clk);
|
||||||
|
|
||||||
|
tdc->slave_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||||
|
struct of_dma *ofdma)
|
||||||
|
{
|
||||||
|
struct tegra_dma *tdma = ofdma->of_dma_data;
|
||||||
|
struct dma_chan *chan;
|
||||||
|
struct tegra_dma_channel *tdc;
|
||||||
|
|
||||||
|
chan = dma_get_any_slave_channel(&tdma->dma_dev);
|
||||||
|
if (!chan)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
tdc = to_tegra_dma_chan(chan);
|
||||||
|
tdc->slave_id = dma_spec->args[0];
|
||||||
|
|
||||||
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tegra20 specific DMA controller information */
|
/* Tegra20 specific DMA controller information */
|
||||||
@ -1282,6 +1306,12 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(tdma->dma_clk);
|
return PTR_ERR(tdma->dma_clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tdma->rst = devm_reset_control_get(&pdev->dev, "dma");
|
||||||
|
if (IS_ERR(tdma->rst)) {
|
||||||
|
dev_err(&pdev->dev, "Error: Missing reset\n");
|
||||||
|
return PTR_ERR(tdma->rst);
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_init(&tdma->global_lock);
|
spin_lock_init(&tdma->global_lock);
|
||||||
|
|
||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
@ -1302,9 +1332,9 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reset DMA controller */
|
/* Reset DMA controller */
|
||||||
tegra_periph_reset_assert(tdma->dma_clk);
|
reset_control_assert(tdma->rst);
|
||||||
udelay(2);
|
udelay(2);
|
||||||
tegra_periph_reset_deassert(tdma->dma_clk);
|
reset_control_deassert(tdma->rst);
|
||||||
|
|
||||||
/* Enable global DMA registers */
|
/* Enable global DMA registers */
|
||||||
tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE);
|
tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE);
|
||||||
@ -1376,10 +1406,20 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||||||
goto err_irq;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = of_dma_controller_register(pdev->dev.of_node,
|
||||||
|
tegra_dma_of_xlate, tdma);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"Tegra20 APB DMA OF registration failed %d\n", ret);
|
||||||
|
goto err_unregister_dma_dev;
|
||||||
|
}
|
||||||
|
|
||||||
dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n",
|
dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n",
|
||||||
cdata->nr_channels);
|
cdata->nr_channels);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_unregister_dma_dev:
|
||||||
|
dma_async_device_unregister(&tdma->dma_dev);
|
||||||
err_irq:
|
err_irq:
|
||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
struct tegra_dma_channel *tdc = &tdma->channels[i];
|
struct tegra_dma_channel *tdc = &tdma->channels[i];
|
||||||
|
@ -20,6 +20,10 @@ menuconfig DRM
|
|||||||
details. You should also select and configure AGP
|
details. You should also select and configure AGP
|
||||||
(/dev/agpgart) support if it is available for your platform.
|
(/dev/agpgart) support if it is available for your platform.
|
||||||
|
|
||||||
|
config DRM_MIPI_DSI
|
||||||
|
bool
|
||||||
|
depends on DRM
|
||||||
|
|
||||||
config DRM_USB
|
config DRM_USB
|
||||||
tristate
|
tristate
|
||||||
depends on DRM
|
depends on DRM
|
||||||
@ -191,3 +195,5 @@ source "drivers/gpu/drm/qxl/Kconfig"
|
|||||||
source "drivers/gpu/drm/msm/Kconfig"
|
source "drivers/gpu/drm/msm/Kconfig"
|
||||||
|
|
||||||
source "drivers/gpu/drm/tegra/Kconfig"
|
source "drivers/gpu/drm/tegra/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/gpu/drm/panel/Kconfig"
|
||||||
|
@ -18,6 +18,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
|
|||||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||||
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
||||||
drm-$(CONFIG_PCI) += ati_pcigart.o
|
drm-$(CONFIG_PCI) += ati_pcigart.o
|
||||||
|
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
|
||||||
|
|
||||||
drm-usb-y := drm_usb.o
|
drm-usb-y := drm_usb.o
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
|||||||
CFLAGS_drm_trace_points.o := -I$(src)
|
CFLAGS_drm_trace_points.o := -I$(src)
|
||||||
|
|
||||||
obj-$(CONFIG_DRM) += drm.o
|
obj-$(CONFIG_DRM) += drm.o
|
||||||
|
obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
|
||||||
obj-$(CONFIG_DRM_USB) += drm_usb.o
|
obj-$(CONFIG_DRM_USB) += drm_usb.o
|
||||||
obj-$(CONFIG_DRM_TTM) += ttm/
|
obj-$(CONFIG_DRM_TTM) += ttm/
|
||||||
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
||||||
@ -59,3 +61,4 @@ obj-$(CONFIG_DRM_QXL) += qxl/
|
|||||||
obj-$(CONFIG_DRM_MSM) += msm/
|
obj-$(CONFIG_DRM_MSM) += msm/
|
||||||
obj-$(CONFIG_DRM_TEGRA) += tegra/
|
obj-$(CONFIG_DRM_TEGRA) += tegra/
|
||||||
obj-y += i2c/
|
obj-y += i2c/
|
||||||
|
obj-y += panel/
|
||||||
|
315
drivers/gpu/drm/drm_mipi_dsi.c
Normal file
315
drivers/gpu/drm/drm_mipi_dsi.c
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* MIPI DSI Bus
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
|
||||||
|
* Andrzej Hajda <a.hajda@samsung.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <drm/drm_mipi_dsi.h>
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <video/mipi_display.h>
|
||||||
|
|
||||||
|
static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
|
||||||
|
{
|
||||||
|
return of_driver_match_device(dev, drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
|
||||||
|
.runtime_suspend = pm_generic_runtime_suspend,
|
||||||
|
.runtime_resume = pm_generic_runtime_resume,
|
||||||
|
.suspend = pm_generic_suspend,
|
||||||
|
.resume = pm_generic_resume,
|
||||||
|
.freeze = pm_generic_freeze,
|
||||||
|
.thaw = pm_generic_thaw,
|
||||||
|
.poweroff = pm_generic_poweroff,
|
||||||
|
.restore = pm_generic_restore,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct bus_type mipi_dsi_bus_type = {
|
||||||
|
.name = "mipi-dsi",
|
||||||
|
.match = mipi_dsi_device_match,
|
||||||
|
.pm = &mipi_dsi_device_pm_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mipi_dsi_dev_release(struct device *dev)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||||
|
|
||||||
|
of_node_put(dev->of_node);
|
||||||
|
kfree(dsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct device_type mipi_dsi_device_type = {
|
||||||
|
.release = mipi_dsi_dev_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_device *dsi;
|
||||||
|
|
||||||
|
dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
|
||||||
|
if (!dsi)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
dsi->host = host;
|
||||||
|
dsi->dev.bus = &mipi_dsi_bus_type;
|
||||||
|
dsi->dev.parent = host->dev;
|
||||||
|
dsi->dev.type = &mipi_dsi_device_type;
|
||||||
|
|
||||||
|
device_initialize(&dsi->dev);
|
||||||
|
|
||||||
|
return dsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_host *host = dsi->host;
|
||||||
|
|
||||||
|
dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel);
|
||||||
|
|
||||||
|
return device_add(&dsi->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mipi_dsi_device *
|
||||||
|
of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_device *dsi;
|
||||||
|
struct device *dev = host->dev;
|
||||||
|
int ret;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
ret = of_property_read_u32(node, "reg", ®);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "device node %s has no valid reg property: %d\n",
|
||||||
|
node->full_name, ret);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg > 3) {
|
||||||
|
dev_err(dev, "device node %s has invalid reg property: %u\n",
|
||||||
|
node->full_name, reg);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
dsi = mipi_dsi_device_alloc(host);
|
||||||
|
if (IS_ERR(dsi)) {
|
||||||
|
dev_err(dev, "failed to allocate DSI device %s: %ld\n",
|
||||||
|
node->full_name, PTR_ERR(dsi));
|
||||||
|
return dsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsi->dev.of_node = of_node_get(node);
|
||||||
|
dsi->channel = reg;
|
||||||
|
|
||||||
|
ret = mipi_dsi_device_add(dsi);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to add DSI device %s: %d\n",
|
||||||
|
node->full_name, ret);
|
||||||
|
kfree(dsi);
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mipi_dsi_host_register(struct mipi_dsi_host *host)
|
||||||
|
{
|
||||||
|
struct device_node *node;
|
||||||
|
|
||||||
|
for_each_available_child_of_node(host->dev->of_node, node)
|
||||||
|
of_mipi_dsi_device_add(host, node);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_host_register);
|
||||||
|
|
||||||
|
static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||||
|
|
||||||
|
device_unregister(&dsi->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
|
||||||
|
{
|
||||||
|
device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_host_unregister);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mipi_dsi_attach - attach a DSI device to its DSI host
|
||||||
|
* @dsi: DSI peripheral
|
||||||
|
*/
|
||||||
|
int mipi_dsi_attach(struct mipi_dsi_device *dsi)
|
||||||
|
{
|
||||||
|
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
||||||
|
|
||||||
|
if (!ops || !ops->attach)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
return ops->attach(dsi->host, dsi);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_attach);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mipi_dsi_detach - detach a DSI device from its DSI host
|
||||||
|
* @dsi: DSI peripheral
|
||||||
|
*/
|
||||||
|
int mipi_dsi_detach(struct mipi_dsi_device *dsi)
|
||||||
|
{
|
||||||
|
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
||||||
|
|
||||||
|
if (!ops || !ops->detach)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
return ops->detach(dsi->host, dsi);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_detach);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mipi_dsi_dcs_write - send DCS write command
|
||||||
|
* @dsi: DSI device
|
||||||
|
* @channel: virtual channel
|
||||||
|
* @data: pointer to the command followed by parameters
|
||||||
|
* @len: length of @data
|
||||||
|
*/
|
||||||
|
int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel,
|
||||||
|
const void *data, size_t len)
|
||||||
|
{
|
||||||
|
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
||||||
|
struct mipi_dsi_msg msg = {
|
||||||
|
.channel = channel,
|
||||||
|
.tx_buf = data,
|
||||||
|
.tx_len = len
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!ops || !ops->transfer)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
switch (len) {
|
||||||
|
case 0:
|
||||||
|
return -EINVAL;
|
||||||
|
case 1:
|
||||||
|
msg.type = MIPI_DSI_DCS_SHORT_WRITE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg.type = MIPI_DSI_DCS_LONG_WRITE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ops->transfer(dsi->host, &msg);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_dcs_write);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mipi_dsi_dcs_read - send DCS read request command
|
||||||
|
* @dsi: DSI device
|
||||||
|
* @channel: virtual channel
|
||||||
|
* @cmd: DCS read command
|
||||||
|
* @data: pointer to read buffer
|
||||||
|
* @len: length of @data
|
||||||
|
*
|
||||||
|
* Function returns number of read bytes or error code.
|
||||||
|
*/
|
||||||
|
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel,
|
||||||
|
u8 cmd, void *data, size_t len)
|
||||||
|
{
|
||||||
|
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
||||||
|
struct mipi_dsi_msg msg = {
|
||||||
|
.channel = channel,
|
||||||
|
.type = MIPI_DSI_DCS_READ,
|
||||||
|
.tx_buf = &cmd,
|
||||||
|
.tx_len = 1,
|
||||||
|
.rx_buf = data,
|
||||||
|
.rx_len = len
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!ops || !ops->transfer)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
return ops->transfer(dsi->host, &msg);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_dcs_read);
|
||||||
|
|
||||||
|
static int mipi_dsi_drv_probe(struct device *dev)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
|
||||||
|
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||||
|
|
||||||
|
return drv->probe(dsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mipi_dsi_drv_remove(struct device *dev)
|
||||||
|
{
|
||||||
|
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
|
||||||
|
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||||
|
|
||||||
|
return drv->remove(dsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mipi_dsi_driver_register - register a driver for DSI devices
|
||||||
|
* @drv: DSI driver structure
|
||||||
|
*/
|
||||||
|
int mipi_dsi_driver_register(struct mipi_dsi_driver *drv)
|
||||||
|
{
|
||||||
|
drv->driver.bus = &mipi_dsi_bus_type;
|
||||||
|
if (drv->probe)
|
||||||
|
drv->driver.probe = mipi_dsi_drv_probe;
|
||||||
|
if (drv->remove)
|
||||||
|
drv->driver.remove = mipi_dsi_drv_remove;
|
||||||
|
|
||||||
|
return driver_register(&drv->driver);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_driver_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mipi_dsi_driver_unregister - unregister a driver for DSI devices
|
||||||
|
* @drv: DSI driver structure
|
||||||
|
*/
|
||||||
|
void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
|
||||||
|
{
|
||||||
|
driver_unregister(&drv->driver);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mipi_dsi_driver_unregister);
|
||||||
|
|
||||||
|
static int __init mipi_dsi_bus_init(void)
|
||||||
|
{
|
||||||
|
return bus_register(&mipi_dsi_bus_type);
|
||||||
|
}
|
||||||
|
postcore_initcall(mipi_dsi_bus_init);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
|
||||||
|
MODULE_DESCRIPTION("MIPI DSI Bus");
|
||||||
|
MODULE_LICENSE("GPL and additional rights");
|
100
drivers/gpu/drm/drm_panel.c
Normal file
100
drivers/gpu/drm/drm_panel.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include <drm/drm_crtc.h>
|
||||||
|
#include <drm/drm_panel.h>
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(panel_lock);
|
||||||
|
static LIST_HEAD(panel_list);
|
||||||
|
|
||||||
|
void drm_panel_init(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
INIT_LIST_HEAD(&panel->list);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_panel_init);
|
||||||
|
|
||||||
|
int drm_panel_add(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
mutex_lock(&panel_lock);
|
||||||
|
list_add_tail(&panel->list, &panel_list);
|
||||||
|
mutex_unlock(&panel_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_panel_add);
|
||||||
|
|
||||||
|
void drm_panel_remove(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
mutex_lock(&panel_lock);
|
||||||
|
list_del_init(&panel->list);
|
||||||
|
mutex_unlock(&panel_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_panel_remove);
|
||||||
|
|
||||||
|
int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
if (panel->connector)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
panel->connector = connector;
|
||||||
|
panel->drm = connector->dev;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_panel_attach);
|
||||||
|
|
||||||
|
int drm_panel_detach(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
panel->connector = NULL;
|
||||||
|
panel->drm = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_panel_detach);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
struct drm_panel *of_drm_find_panel(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct drm_panel *panel;
|
||||||
|
|
||||||
|
mutex_lock(&panel_lock);
|
||||||
|
|
||||||
|
list_for_each_entry(panel, &panel_list, list) {
|
||||||
|
if (panel->dev->of_node == np) {
|
||||||
|
mutex_unlock(&panel_lock);
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&panel_lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(of_drm_find_panel);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
|
||||||
|
MODULE_DESCRIPTION("DRM panel infrastructure");
|
||||||
|
MODULE_LICENSE("GPL and additional rights");
|
19
drivers/gpu/drm/panel/Kconfig
Normal file
19
drivers/gpu/drm/panel/Kconfig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
config DRM_PANEL
|
||||||
|
bool
|
||||||
|
depends on DRM
|
||||||
|
help
|
||||||
|
Panel registration and lookup framework.
|
||||||
|
|
||||||
|
menu "Display Panels"
|
||||||
|
depends on DRM_PANEL
|
||||||
|
|
||||||
|
config DRM_PANEL_SIMPLE
|
||||||
|
tristate "support for simple panels"
|
||||||
|
depends on OF
|
||||||
|
help
|
||||||
|
DRM panel driver for dumb panels that need at most a regulator and
|
||||||
|
a GPIO to be powered up. Optionally a backlight can be attached so
|
||||||
|
that it can be automatically turned off when the panel goes into a
|
||||||
|
low power state.
|
||||||
|
|
||||||
|
endmenu
|
1
drivers/gpu/drm/panel/Makefile
Normal file
1
drivers/gpu/drm/panel/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
|
497
drivers/gpu/drm/panel/panel-simple.c
Normal file
497
drivers/gpu/drm/panel/panel-simple.c
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial portions
|
||||||
|
* of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/backlight.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
|
#include <drm/drmP.h>
|
||||||
|
#include <drm/drm_crtc.h>
|
||||||
|
#include <drm/drm_mipi_dsi.h>
|
||||||
|
#include <drm/drm_panel.h>
|
||||||
|
|
||||||
|
struct panel_desc {
|
||||||
|
const struct drm_display_mode *modes;
|
||||||
|
unsigned int num_modes;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
} size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO: convert to gpiod_*() API once it's been merged */
|
||||||
|
#define GPIO_ACTIVE_LOW (1 << 0)
|
||||||
|
|
||||||
|
struct panel_simple {
|
||||||
|
struct drm_panel base;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
const struct panel_desc *desc;
|
||||||
|
|
||||||
|
struct backlight_device *backlight;
|
||||||
|
struct regulator *supply;
|
||||||
|
struct i2c_adapter *ddc;
|
||||||
|
|
||||||
|
unsigned long enable_gpio_flags;
|
||||||
|
int enable_gpio;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
return container_of(panel, struct panel_simple, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_get_fixed_modes(struct panel_simple *panel)
|
||||||
|
{
|
||||||
|
struct drm_connector *connector = panel->base.connector;
|
||||||
|
struct drm_device *drm = panel->base.drm;
|
||||||
|
struct drm_display_mode *mode;
|
||||||
|
unsigned int i, num = 0;
|
||||||
|
|
||||||
|
if (!panel->desc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < panel->desc->num_modes; i++) {
|
||||||
|
const struct drm_display_mode *m = &panel->desc->modes[i];
|
||||||
|
|
||||||
|
mode = drm_mode_duplicate(drm, m);
|
||||||
|
if (!mode) {
|
||||||
|
dev_err(drm->dev, "failed to add mode %ux%u@%u\n",
|
||||||
|
m->hdisplay, m->vdisplay, m->vrefresh);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_mode_set_name(mode);
|
||||||
|
|
||||||
|
drm_mode_probed_add(connector, mode);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
connector->display_info.width_mm = panel->desc->size.width;
|
||||||
|
connector->display_info.height_mm = panel->desc->size.height;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_disable(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
struct panel_simple *p = to_panel_simple(panel);
|
||||||
|
|
||||||
|
if (!p->enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (p->backlight) {
|
||||||
|
p->backlight->props.power = FB_BLANK_POWERDOWN;
|
||||||
|
backlight_update_status(p->backlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpio_is_valid(p->enable_gpio)) {
|
||||||
|
if (p->enable_gpio_flags & GPIO_ACTIVE_LOW)
|
||||||
|
gpio_set_value(p->enable_gpio, 1);
|
||||||
|
else
|
||||||
|
gpio_set_value(p->enable_gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
regulator_disable(p->supply);
|
||||||
|
p->enabled = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_enable(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
struct panel_simple *p = to_panel_simple(panel);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (p->enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = regulator_enable(p->supply);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(panel->dev, "failed to enable supply: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpio_is_valid(p->enable_gpio)) {
|
||||||
|
if (p->enable_gpio_flags & GPIO_ACTIVE_LOW)
|
||||||
|
gpio_set_value(p->enable_gpio, 0);
|
||||||
|
else
|
||||||
|
gpio_set_value(p->enable_gpio, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->backlight) {
|
||||||
|
p->backlight->props.power = FB_BLANK_UNBLANK;
|
||||||
|
backlight_update_status(p->backlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->enabled = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_get_modes(struct drm_panel *panel)
|
||||||
|
{
|
||||||
|
struct panel_simple *p = to_panel_simple(panel);
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
/* probe EDID if a DDC bus is available */
|
||||||
|
if (p->ddc) {
|
||||||
|
struct edid *edid = drm_get_edid(panel->connector, p->ddc);
|
||||||
|
if (edid) {
|
||||||
|
num += drm_add_edid_modes(panel->connector, edid);
|
||||||
|
kfree(edid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add hard-coded panel modes */
|
||||||
|
num += panel_simple_get_fixed_modes(p);
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct drm_panel_funcs panel_simple_funcs = {
|
||||||
|
.disable = panel_simple_disable,
|
||||||
|
.enable = panel_simple_enable,
|
||||||
|
.get_modes = panel_simple_get_modes,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
|
||||||
|
{
|
||||||
|
struct device_node *backlight, *ddc;
|
||||||
|
struct panel_simple *panel;
|
||||||
|
enum of_gpio_flags flags;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
|
||||||
|
if (!panel)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
panel->enabled = false;
|
||||||
|
panel->desc = desc;
|
||||||
|
|
||||||
|
panel->supply = devm_regulator_get(dev, "power");
|
||||||
|
if (IS_ERR(panel->supply))
|
||||||
|
return PTR_ERR(panel->supply);
|
||||||
|
|
||||||
|
panel->enable_gpio = of_get_named_gpio_flags(dev->of_node,
|
||||||
|
"enable-gpios", 0,
|
||||||
|
&flags);
|
||||||
|
if (gpio_is_valid(panel->enable_gpio)) {
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
if (flags & OF_GPIO_ACTIVE_LOW)
|
||||||
|
panel->enable_gpio_flags |= GPIO_ACTIVE_LOW;
|
||||||
|
|
||||||
|
err = gpio_request(panel->enable_gpio, "enable");
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "failed to request GPIO#%u: %d\n",
|
||||||
|
panel->enable_gpio, err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (panel->enable_gpio_flags & GPIO_ACTIVE_LOW) != 0;
|
||||||
|
|
||||||
|
err = gpio_direction_output(panel->enable_gpio, value);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "failed to setup GPIO%u: %d\n",
|
||||||
|
panel->enable_gpio, err);
|
||||||
|
goto free_gpio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
backlight = of_parse_phandle(dev->of_node, "backlight", 0);
|
||||||
|
if (backlight) {
|
||||||
|
panel->backlight = of_find_backlight_by_node(backlight);
|
||||||
|
of_node_put(backlight);
|
||||||
|
|
||||||
|
if (!panel->backlight) {
|
||||||
|
err = -EPROBE_DEFER;
|
||||||
|
goto free_gpio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
|
||||||
|
if (ddc) {
|
||||||
|
panel->ddc = of_find_i2c_adapter_by_node(ddc);
|
||||||
|
of_node_put(ddc);
|
||||||
|
|
||||||
|
if (!panel->ddc) {
|
||||||
|
err = -EPROBE_DEFER;
|
||||||
|
goto free_backlight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_panel_init(&panel->base);
|
||||||
|
panel->base.dev = dev;
|
||||||
|
panel->base.funcs = &panel_simple_funcs;
|
||||||
|
|
||||||
|
err = drm_panel_add(&panel->base);
|
||||||
|
if (err < 0)
|
||||||
|
goto free_ddc;
|
||||||
|
|
||||||
|
dev_set_drvdata(dev, panel);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free_ddc:
|
||||||
|
if (panel->ddc)
|
||||||
|
put_device(&panel->ddc->dev);
|
||||||
|
free_backlight:
|
||||||
|
if (panel->backlight)
|
||||||
|
put_device(&panel->backlight->dev);
|
||||||
|
free_gpio:
|
||||||
|
if (gpio_is_valid(panel->enable_gpio))
|
||||||
|
gpio_free(panel->enable_gpio);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_remove(struct device *dev)
|
||||||
|
{
|
||||||
|
struct panel_simple *panel = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
drm_panel_detach(&panel->base);
|
||||||
|
drm_panel_remove(&panel->base);
|
||||||
|
|
||||||
|
panel_simple_disable(&panel->base);
|
||||||
|
|
||||||
|
if (panel->ddc)
|
||||||
|
put_device(&panel->ddc->dev);
|
||||||
|
|
||||||
|
if (panel->backlight)
|
||||||
|
put_device(&panel->backlight->dev);
|
||||||
|
|
||||||
|
if (gpio_is_valid(panel->enable_gpio))
|
||||||
|
gpio_free(panel->enable_gpio);
|
||||||
|
|
||||||
|
regulator_disable(panel->supply);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct drm_display_mode auo_b101aw03_mode = {
|
||||||
|
.clock = 51450,
|
||||||
|
.hdisplay = 1024,
|
||||||
|
.hsync_start = 1024 + 156,
|
||||||
|
.hsync_end = 1024 + 156 + 8,
|
||||||
|
.htotal = 1024 + 156 + 8 + 156,
|
||||||
|
.vdisplay = 600,
|
||||||
|
.vsync_start = 600 + 16,
|
||||||
|
.vsync_end = 600 + 16 + 6,
|
||||||
|
.vtotal = 600 + 16 + 6 + 16,
|
||||||
|
.vrefresh = 60,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct panel_desc auo_b101aw03 = {
|
||||||
|
.modes = &auo_b101aw03_mode,
|
||||||
|
.num_modes = 1,
|
||||||
|
.size = {
|
||||||
|
.width = 223,
|
||||||
|
.height = 125,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct drm_display_mode chunghwa_claa101wb01_mode = {
|
||||||
|
.clock = 69300,
|
||||||
|
.hdisplay = 1366,
|
||||||
|
.hsync_start = 1366 + 48,
|
||||||
|
.hsync_end = 1366 + 48 + 32,
|
||||||
|
.htotal = 1366 + 48 + 32 + 20,
|
||||||
|
.vdisplay = 768,
|
||||||
|
.vsync_start = 768 + 16,
|
||||||
|
.vsync_end = 768 + 16 + 8,
|
||||||
|
.vtotal = 768 + 16 + 8 + 16,
|
||||||
|
.vrefresh = 60,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct panel_desc chunghwa_claa101wb01 = {
|
||||||
|
.modes = &chunghwa_claa101wb01_mode,
|
||||||
|
.num_modes = 1,
|
||||||
|
.size = {
|
||||||
|
.width = 223,
|
||||||
|
.height = 125,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id platform_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "auo,b101aw03",
|
||||||
|
.data = &auo_b101aw03,
|
||||||
|
}, {
|
||||||
|
.compatible = "chunghwa,claa101wb01",
|
||||||
|
.data = &chunghwa_claa101wb01
|
||||||
|
}, {
|
||||||
|
.compatible = "simple-panel",
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, platform_of_match);
|
||||||
|
|
||||||
|
static int panel_simple_platform_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
const struct of_device_id *id;
|
||||||
|
|
||||||
|
id = of_match_node(platform_of_match, pdev->dev.of_node);
|
||||||
|
if (!id)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return panel_simple_probe(&pdev->dev, id->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_platform_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
return panel_simple_remove(&pdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver panel_simple_platform_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "panel-simple",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = platform_of_match,
|
||||||
|
},
|
||||||
|
.probe = panel_simple_platform_probe,
|
||||||
|
.remove = panel_simple_platform_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct panel_desc_dsi {
|
||||||
|
struct panel_desc desc;
|
||||||
|
|
||||||
|
enum mipi_dsi_pixel_format format;
|
||||||
|
unsigned int lanes;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct drm_display_mode panasonic_vvx10f004b00_mode = {
|
||||||
|
.clock = 157200,
|
||||||
|
.hdisplay = 1920,
|
||||||
|
.hsync_start = 1920 + 154,
|
||||||
|
.hsync_end = 1920 + 154 + 16,
|
||||||
|
.htotal = 1920 + 154 + 16 + 32,
|
||||||
|
.vdisplay = 1200,
|
||||||
|
.vsync_start = 1200 + 17,
|
||||||
|
.vsync_end = 1200 + 17 + 2,
|
||||||
|
.vtotal = 1200 + 17 + 2 + 16,
|
||||||
|
.vrefresh = 60,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
|
||||||
|
.desc = {
|
||||||
|
.modes = &panasonic_vvx10f004b00_mode,
|
||||||
|
.num_modes = 1,
|
||||||
|
.size = {
|
||||||
|
.width = 217,
|
||||||
|
.height = 136,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.format = MIPI_DSI_FMT_RGB888,
|
||||||
|
.lanes = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id dsi_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "panasonic,vvx10f004b00",
|
||||||
|
.data = &panasonic_vvx10f004b00
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, dsi_of_match);
|
||||||
|
|
||||||
|
static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
|
||||||
|
{
|
||||||
|
const struct panel_desc_dsi *desc;
|
||||||
|
const struct of_device_id *id;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
id = of_match_node(dsi_of_match, dsi->dev.of_node);
|
||||||
|
if (!id)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
desc = id->data;
|
||||||
|
|
||||||
|
err = panel_simple_probe(&dsi->dev, &desc->desc);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
dsi->format = desc->format;
|
||||||
|
dsi->lanes = desc->lanes;
|
||||||
|
|
||||||
|
return mipi_dsi_attach(dsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = mipi_dsi_detach(dsi);
|
||||||
|
if (err < 0)
|
||||||
|
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
|
||||||
|
|
||||||
|
return panel_simple_remove(&dsi->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mipi_dsi_driver panel_simple_dsi_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "panel-simple-dsi",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = dsi_of_match,
|
||||||
|
},
|
||||||
|
.probe = panel_simple_dsi_probe,
|
||||||
|
.remove = panel_simple_dsi_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init panel_simple_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = platform_driver_register(&panel_simple_platform_driver);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
|
||||||
|
err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
module_init(panel_simple_init);
|
||||||
|
|
||||||
|
static void __exit panel_simple_exit(void)
|
||||||
|
{
|
||||||
|
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
|
||||||
|
mipi_dsi_driver_unregister(&panel_simple_dsi_driver);
|
||||||
|
|
||||||
|
platform_driver_unregister(&panel_simple_platform_driver);
|
||||||
|
}
|
||||||
|
module_exit(panel_simple_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
|
||||||
|
MODULE_DESCRIPTION("DRM Driver for Simple Panels");
|
||||||
|
MODULE_LICENSE("GPL and additional rights");
|
@ -1,13 +1,12 @@
|
|||||||
config DRM_TEGRA
|
config DRM_TEGRA
|
||||||
bool "NVIDIA Tegra DRM"
|
tristate "NVIDIA Tegra DRM"
|
||||||
depends on ARCH_TEGRA || ARCH_MULTIPLATFORM
|
depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
|
||||||
depends on DRM
|
depends on DRM
|
||||||
select TEGRA_HOST1X
|
depends on RESET_CONTROLLER
|
||||||
select DRM_KMS_HELPER
|
select DRM_KMS_HELPER
|
||||||
select DRM_KMS_FB_HELPER
|
select DRM_MIPI_DSI
|
||||||
select FB_SYS_FILLRECT
|
select DRM_PANEL
|
||||||
select FB_SYS_COPYAREA
|
select TEGRA_HOST1X
|
||||||
select FB_SYS_IMAGEBLIT
|
|
||||||
help
|
help
|
||||||
Choose this option if you have an NVIDIA Tegra SoC.
|
Choose this option if you have an NVIDIA Tegra SoC.
|
||||||
|
|
||||||
@ -16,6 +15,18 @@ config DRM_TEGRA
|
|||||||
|
|
||||||
if DRM_TEGRA
|
if DRM_TEGRA
|
||||||
|
|
||||||
|
config DRM_TEGRA_FBDEV
|
||||||
|
bool "Enable legacy fbdev support"
|
||||||
|
select DRM_KMS_FB_HELPER
|
||||||
|
select FB_SYS_FILLRECT
|
||||||
|
select FB_SYS_COPYAREA
|
||||||
|
select FB_SYS_IMAGEBLIT
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Choose this option if you have a need for the legacy fbdev support.
|
||||||
|
Note that this support also provides the Linux console on top of
|
||||||
|
the Tegra modesetting driver.
|
||||||
|
|
||||||
config DRM_TEGRA_DEBUG
|
config DRM_TEGRA_DEBUG
|
||||||
bool "NVIDIA Tegra DRM debug support"
|
bool "NVIDIA Tegra DRM debug support"
|
||||||
help
|
help
|
||||||
|
@ -9,6 +9,8 @@ tegra-drm-y := \
|
|||||||
output.o \
|
output.o \
|
||||||
rgb.o \
|
rgb.o \
|
||||||
hdmi.o \
|
hdmi.o \
|
||||||
|
mipi-phy.o \
|
||||||
|
dsi.o \
|
||||||
gr2d.o \
|
gr2d.o \
|
||||||
gr3d.o
|
gr3d.o
|
||||||
|
|
||||||
|
@ -8,13 +8,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/clk/tegra.h>
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
#include "dc.h"
|
#include "dc.h"
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
#include "gem.h"
|
#include "gem.h"
|
||||||
|
|
||||||
|
struct tegra_dc_soc_info {
|
||||||
|
bool supports_interlacing;
|
||||||
|
};
|
||||||
|
|
||||||
struct tegra_plane {
|
struct tegra_plane {
|
||||||
struct drm_plane base;
|
struct drm_plane base;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
@ -658,19 +662,12 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
|
|||||||
/* program display mode */
|
/* program display mode */
|
||||||
tegra_dc_set_timings(dc, mode);
|
tegra_dc_set_timings(dc, mode);
|
||||||
|
|
||||||
value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
|
/* interlacing isn't supported yet, so disable it */
|
||||||
tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
|
if (dc->soc->supports_interlacing) {
|
||||||
|
value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
|
||||||
value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
|
value &= ~INTERLACE_ENABLE;
|
||||||
value &= ~LVS_OUTPUT_POLARITY_LOW;
|
tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
|
||||||
value &= ~LHS_OUTPUT_POLARITY_LOW;
|
}
|
||||||
tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
|
|
||||||
|
|
||||||
value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
|
|
||||||
DISP_ORDER_RED_BLUE;
|
|
||||||
tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
|
|
||||||
|
|
||||||
tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
|
|
||||||
|
|
||||||
value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
|
value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
|
||||||
tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
|
tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
|
||||||
@ -712,7 +709,7 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
|
|||||||
unsigned long value;
|
unsigned long value;
|
||||||
|
|
||||||
/* hardware initialization */
|
/* hardware initialization */
|
||||||
tegra_periph_reset_deassert(dc->clk);
|
reset_control_deassert(dc->rst);
|
||||||
usleep_range(10000, 20000);
|
usleep_range(10000, 20000);
|
||||||
|
|
||||||
if (dc->pipe)
|
if (dc->pipe)
|
||||||
@ -735,10 +732,6 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
|
|||||||
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
|
||||||
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
|
|
||||||
value |= DISP_CTRL_MODE_C_DISPLAY;
|
|
||||||
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
|
|
||||||
|
|
||||||
/* initialize timer */
|
/* initialize timer */
|
||||||
value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
|
value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
|
||||||
WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
|
WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
|
||||||
@ -1167,8 +1160,36 @@ static const struct host1x_client_ops dc_client_ops = {
|
|||||||
.exit = tegra_dc_exit,
|
.exit = tegra_dc_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
|
||||||
|
.supports_interlacing = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
|
||||||
|
.supports_interlacing = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
|
||||||
|
.supports_interlacing = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id tegra_dc_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "nvidia,tegra124-dc",
|
||||||
|
.data = &tegra124_dc_soc_info,
|
||||||
|
}, {
|
||||||
|
.compatible = "nvidia,tegra30-dc",
|
||||||
|
.data = &tegra30_dc_soc_info,
|
||||||
|
}, {
|
||||||
|
.compatible = "nvidia,tegra20-dc",
|
||||||
|
.data = &tegra20_dc_soc_info,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static int tegra_dc_probe(struct platform_device *pdev)
|
static int tegra_dc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
const struct of_device_id *id;
|
||||||
struct resource *regs;
|
struct resource *regs;
|
||||||
struct tegra_dc *dc;
|
struct tegra_dc *dc;
|
||||||
int err;
|
int err;
|
||||||
@ -1177,9 +1198,14 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
|||||||
if (!dc)
|
if (!dc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
id = of_match_node(tegra_dc_of_match, pdev->dev.of_node);
|
||||||
|
if (!id)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
spin_lock_init(&dc->lock);
|
spin_lock_init(&dc->lock);
|
||||||
INIT_LIST_HEAD(&dc->list);
|
INIT_LIST_HEAD(&dc->list);
|
||||||
dc->dev = &pdev->dev;
|
dc->dev = &pdev->dev;
|
||||||
|
dc->soc = id->data;
|
||||||
|
|
||||||
dc->clk = devm_clk_get(&pdev->dev, NULL);
|
dc->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
if (IS_ERR(dc->clk)) {
|
if (IS_ERR(dc->clk)) {
|
||||||
@ -1187,6 +1213,12 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(dc->clk);
|
return PTR_ERR(dc->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc->rst = devm_reset_control_get(&pdev->dev, "dc");
|
||||||
|
if (IS_ERR(dc->rst)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get reset\n");
|
||||||
|
return PTR_ERR(dc->rst);
|
||||||
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(dc->clk);
|
err = clk_prepare_enable(dc->clk);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -1247,12 +1279,6 @@ static int tegra_dc_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct of_device_id tegra_dc_of_match[] = {
|
|
||||||
{ .compatible = "nvidia,tegra30-dc", },
|
|
||||||
{ .compatible = "nvidia,tegra20-dc", },
|
|
||||||
{ },
|
|
||||||
};
|
|
||||||
|
|
||||||
struct platform_driver tegra_dc_driver = {
|
struct platform_driver tegra_dc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tegra-dc",
|
.name = "tegra-dc",
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#define DISP_CTRL_MODE_STOP (0 << 5)
|
#define DISP_CTRL_MODE_STOP (0 << 5)
|
||||||
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
|
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
|
||||||
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
|
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
|
||||||
|
#define DISP_CTRL_MODE_MASK (3 << 5)
|
||||||
#define DC_CMD_SIGNAL_RAISE 0x033
|
#define DC_CMD_SIGNAL_RAISE 0x033
|
||||||
#define DC_CMD_DISPLAY_POWER_CONTROL 0x036
|
#define DC_CMD_DISPLAY_POWER_CONTROL 0x036
|
||||||
#define PW0_ENABLE (1 << 0)
|
#define PW0_ENABLE (1 << 0)
|
||||||
@ -116,6 +117,7 @@
|
|||||||
|
|
||||||
#define DC_DISP_DISP_WIN_OPTIONS 0x402
|
#define DC_DISP_DISP_WIN_OPTIONS 0x402
|
||||||
#define HDMI_ENABLE (1 << 30)
|
#define HDMI_ENABLE (1 << 30)
|
||||||
|
#define DSI_ENABLE (1 << 29)
|
||||||
|
|
||||||
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
|
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
|
||||||
#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
|
#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
|
||||||
@ -238,6 +240,8 @@
|
|||||||
#define DITHER_CONTROL_ERRDIFF (3 << 8)
|
#define DITHER_CONTROL_ERRDIFF (3 << 8)
|
||||||
|
|
||||||
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
|
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
|
||||||
|
#define SC1_H_QUALIFIER_NONE (1 << 16)
|
||||||
|
#define SC0_H_QUALIFIER_NONE (1 << 0)
|
||||||
|
|
||||||
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
|
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
|
||||||
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
|
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
|
||||||
@ -292,6 +296,11 @@
|
|||||||
#define DC_DISP_SD_HW_K_VALUES 0x4dd
|
#define DC_DISP_SD_HW_K_VALUES 0x4dd
|
||||||
#define DC_DISP_SD_MAN_K_VALUES 0x4de
|
#define DC_DISP_SD_MAN_K_VALUES 0x4de
|
||||||
|
|
||||||
|
#define DC_DISP_INTERLACE_CONTROL 0x4e5
|
||||||
|
#define INTERLACE_STATUS (1 << 2)
|
||||||
|
#define INTERLACE_START (1 << 1)
|
||||||
|
#define INTERLACE_ENABLE (1 << 0)
|
||||||
|
|
||||||
#define DC_WIN_CSC_YOF 0x611
|
#define DC_WIN_CSC_YOF 0x611
|
||||||
#define DC_WIN_CSC_KYRGB 0x612
|
#define DC_WIN_CSC_KYRGB 0x612
|
||||||
#define DC_WIN_CSC_KUR 0x613
|
#define DC_WIN_CSC_KUR 0x613
|
||||||
|
@ -104,9 +104,11 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
|
|||||||
|
|
||||||
static void tegra_drm_lastclose(struct drm_device *drm)
|
static void tegra_drm_lastclose(struct drm_device *drm)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_TEGRA_DRM_FBDEV
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
|
|
||||||
tegra_fbdev_restore_mode(tegra->fbdev);
|
tegra_fbdev_restore_mode(tegra->fbdev);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct host1x_bo *
|
static struct host1x_bo *
|
||||||
@ -578,7 +580,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct drm_driver tegra_drm_driver = {
|
static struct drm_driver tegra_drm_driver = {
|
||||||
.driver_features = DRIVER_MODESET | DRIVER_GEM,
|
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
|
||||||
.load = tegra_drm_load,
|
.load = tegra_drm_load,
|
||||||
.unload = tegra_drm_unload,
|
.unload = tegra_drm_unload,
|
||||||
.open = tegra_drm_open,
|
.open = tegra_drm_open,
|
||||||
@ -596,6 +598,12 @@ static struct drm_driver tegra_drm_driver = {
|
|||||||
|
|
||||||
.gem_free_object = tegra_bo_free_object,
|
.gem_free_object = tegra_bo_free_object,
|
||||||
.gem_vm_ops = &tegra_bo_vm_ops,
|
.gem_vm_ops = &tegra_bo_vm_ops,
|
||||||
|
|
||||||
|
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||||
|
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||||
|
.gem_prime_export = tegra_gem_prime_export,
|
||||||
|
.gem_prime_import = tegra_gem_prime_import,
|
||||||
|
|
||||||
.dumb_create = tegra_bo_dumb_create,
|
.dumb_create = tegra_bo_dumb_create,
|
||||||
.dumb_map_offset = tegra_bo_dumb_map_offset,
|
.dumb_map_offset = tegra_bo_dumb_map_offset,
|
||||||
.dumb_destroy = drm_gem_dumb_destroy,
|
.dumb_destroy = drm_gem_dumb_destroy,
|
||||||
@ -653,8 +661,10 @@ static const struct of_device_id host1x_drm_subdevs[] = {
|
|||||||
{ .compatible = "nvidia,tegra30-hdmi", },
|
{ .compatible = "nvidia,tegra30-hdmi", },
|
||||||
{ .compatible = "nvidia,tegra30-gr2d", },
|
{ .compatible = "nvidia,tegra30-gr2d", },
|
||||||
{ .compatible = "nvidia,tegra30-gr3d", },
|
{ .compatible = "nvidia,tegra30-gr3d", },
|
||||||
|
{ .compatible = "nvidia,tegra114-dsi", },
|
||||||
{ .compatible = "nvidia,tegra114-hdmi", },
|
{ .compatible = "nvidia,tegra114-hdmi", },
|
||||||
{ .compatible = "nvidia,tegra114-gr3d", },
|
{ .compatible = "nvidia,tegra114-gr3d", },
|
||||||
|
{ .compatible = "nvidia,tegra124-dc", },
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -677,10 +687,14 @@ static int __init host1x_drm_init(void)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto unregister_host1x;
|
goto unregister_host1x;
|
||||||
|
|
||||||
err = platform_driver_register(&tegra_hdmi_driver);
|
err = platform_driver_register(&tegra_dsi_driver);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto unregister_dc;
|
goto unregister_dc;
|
||||||
|
|
||||||
|
err = platform_driver_register(&tegra_hdmi_driver);
|
||||||
|
if (err < 0)
|
||||||
|
goto unregister_dsi;
|
||||||
|
|
||||||
err = platform_driver_register(&tegra_gr2d_driver);
|
err = platform_driver_register(&tegra_gr2d_driver);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto unregister_hdmi;
|
goto unregister_hdmi;
|
||||||
@ -695,6 +709,8 @@ unregister_gr2d:
|
|||||||
platform_driver_unregister(&tegra_gr2d_driver);
|
platform_driver_unregister(&tegra_gr2d_driver);
|
||||||
unregister_hdmi:
|
unregister_hdmi:
|
||||||
platform_driver_unregister(&tegra_hdmi_driver);
|
platform_driver_unregister(&tegra_hdmi_driver);
|
||||||
|
unregister_dsi:
|
||||||
|
platform_driver_unregister(&tegra_dsi_driver);
|
||||||
unregister_dc:
|
unregister_dc:
|
||||||
platform_driver_unregister(&tegra_dc_driver);
|
platform_driver_unregister(&tegra_dc_driver);
|
||||||
unregister_host1x:
|
unregister_host1x:
|
||||||
@ -708,6 +724,7 @@ static void __exit host1x_drm_exit(void)
|
|||||||
platform_driver_unregister(&tegra_gr3d_driver);
|
platform_driver_unregister(&tegra_gr3d_driver);
|
||||||
platform_driver_unregister(&tegra_gr2d_driver);
|
platform_driver_unregister(&tegra_gr2d_driver);
|
||||||
platform_driver_unregister(&tegra_hdmi_driver);
|
platform_driver_unregister(&tegra_hdmi_driver);
|
||||||
|
platform_driver_unregister(&tegra_dsi_driver);
|
||||||
platform_driver_unregister(&tegra_dc_driver);
|
platform_driver_unregister(&tegra_dc_driver);
|
||||||
host1x_driver_unregister(&host1x_drm_driver);
|
host1x_driver_unregister(&host1x_drm_driver);
|
||||||
}
|
}
|
||||||
|
@ -19,16 +19,20 @@
|
|||||||
#include <drm/drm_fb_helper.h>
|
#include <drm/drm_fb_helper.h>
|
||||||
#include <drm/drm_fixed.h>
|
#include <drm/drm_fixed.h>
|
||||||
|
|
||||||
|
struct reset_control;
|
||||||
|
|
||||||
struct tegra_fb {
|
struct tegra_fb {
|
||||||
struct drm_framebuffer base;
|
struct drm_framebuffer base;
|
||||||
struct tegra_bo **planes;
|
struct tegra_bo **planes;
|
||||||
unsigned int num_planes;
|
unsigned int num_planes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
struct tegra_fbdev {
|
struct tegra_fbdev {
|
||||||
struct drm_fb_helper base;
|
struct drm_fb_helper base;
|
||||||
struct tegra_fb *fb;
|
struct tegra_fb *fb;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct tegra_drm {
|
struct tegra_drm {
|
||||||
struct drm_device *drm;
|
struct drm_device *drm;
|
||||||
@ -36,7 +40,9 @@ struct tegra_drm {
|
|||||||
struct mutex clients_lock;
|
struct mutex clients_lock;
|
||||||
struct list_head clients;
|
struct list_head clients;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
struct tegra_fbdev *fbdev;
|
struct tegra_fbdev *fbdev;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_drm_client;
|
struct tegra_drm_client;
|
||||||
@ -82,6 +88,7 @@ extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
|
|||||||
extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
|
extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
|
||||||
extern int tegra_drm_exit(struct tegra_drm *tegra);
|
extern int tegra_drm_exit(struct tegra_drm *tegra);
|
||||||
|
|
||||||
|
struct tegra_dc_soc_info;
|
||||||
struct tegra_output;
|
struct tegra_output;
|
||||||
|
|
||||||
struct tegra_dc {
|
struct tegra_dc {
|
||||||
@ -93,6 +100,7 @@ struct tegra_dc {
|
|||||||
int pipe;
|
int pipe;
|
||||||
|
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct reset_control *rst;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
@ -106,6 +114,8 @@ struct tegra_dc {
|
|||||||
|
|
||||||
/* page-flip handling */
|
/* page-flip handling */
|
||||||
struct drm_pending_vblank_event *event;
|
struct drm_pending_vblank_event *event;
|
||||||
|
|
||||||
|
const struct tegra_dc_soc_info *soc;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct tegra_dc *
|
static inline struct tegra_dc *
|
||||||
@ -174,6 +184,7 @@ struct tegra_output_ops {
|
|||||||
enum tegra_output_type {
|
enum tegra_output_type {
|
||||||
TEGRA_OUTPUT_RGB,
|
TEGRA_OUTPUT_RGB,
|
||||||
TEGRA_OUTPUT_HDMI,
|
TEGRA_OUTPUT_HDMI,
|
||||||
|
TEGRA_OUTPUT_DSI,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tegra_output {
|
struct tegra_output {
|
||||||
@ -183,6 +194,7 @@ struct tegra_output {
|
|||||||
const struct tegra_output_ops *ops;
|
const struct tegra_output_ops *ops;
|
||||||
enum tegra_output_type type;
|
enum tegra_output_type type;
|
||||||
|
|
||||||
|
struct drm_panel *panel;
|
||||||
struct i2c_adapter *ddc;
|
struct i2c_adapter *ddc;
|
||||||
const struct edid *edid;
|
const struct edid *edid;
|
||||||
unsigned int hpd_irq;
|
unsigned int hpd_irq;
|
||||||
@ -260,9 +272,12 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
|
|||||||
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
|
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
|
||||||
extern int tegra_drm_fb_init(struct drm_device *drm);
|
extern int tegra_drm_fb_init(struct drm_device *drm);
|
||||||
extern void tegra_drm_fb_exit(struct drm_device *drm);
|
extern void tegra_drm_fb_exit(struct drm_device *drm);
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
|
extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
|
||||||
|
#endif
|
||||||
|
|
||||||
extern struct platform_driver tegra_dc_driver;
|
extern struct platform_driver tegra_dc_driver;
|
||||||
|
extern struct platform_driver tegra_dsi_driver;
|
||||||
extern struct platform_driver tegra_hdmi_driver;
|
extern struct platform_driver tegra_hdmi_driver;
|
||||||
extern struct platform_driver tegra_gr2d_driver;
|
extern struct platform_driver tegra_gr2d_driver;
|
||||||
extern struct platform_driver tegra_gr3d_driver;
|
extern struct platform_driver tegra_gr3d_driver;
|
||||||
|
971
drivers/gpu/drm/tegra/dsi.c
Normal file
971
drivers/gpu/drm/tegra/dsi.c
Normal file
@ -0,0 +1,971 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 NVIDIA Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/host1x.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
|
#include <drm/drm_mipi_dsi.h>
|
||||||
|
#include <drm/drm_panel.h>
|
||||||
|
|
||||||
|
#include <video/mipi_display.h>
|
||||||
|
|
||||||
|
#include "dc.h"
|
||||||
|
#include "drm.h"
|
||||||
|
#include "dsi.h"
|
||||||
|
#include "mipi-phy.h"
|
||||||
|
|
||||||
|
#define DSI_VIDEO_FIFO_DEPTH (1920 / 4)
|
||||||
|
#define DSI_HOST_FIFO_DEPTH 64
|
||||||
|
|
||||||
|
struct tegra_dsi {
|
||||||
|
struct host1x_client client;
|
||||||
|
struct tegra_output output;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
void __iomem *regs;
|
||||||
|
|
||||||
|
struct reset_control *rst;
|
||||||
|
struct clk *clk_parent;
|
||||||
|
struct clk *clk_lp;
|
||||||
|
struct clk *clk;
|
||||||
|
|
||||||
|
struct drm_info_list *debugfs_files;
|
||||||
|
struct drm_minor *minor;
|
||||||
|
struct dentry *debugfs;
|
||||||
|
|
||||||
|
enum mipi_dsi_pixel_format format;
|
||||||
|
unsigned int lanes;
|
||||||
|
|
||||||
|
struct tegra_mipi_device *mipi;
|
||||||
|
struct mipi_dsi_host host;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct tegra_dsi *
|
||||||
|
host1x_client_to_dsi(struct host1x_client *client)
|
||||||
|
{
|
||||||
|
return container_of(client, struct tegra_dsi, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host)
|
||||||
|
{
|
||||||
|
return container_of(host, struct tegra_dsi, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct tegra_dsi *to_dsi(struct tegra_output *output)
|
||||||
|
{
|
||||||
|
return container_of(output, struct tegra_dsi, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long tegra_dsi_readl(struct tegra_dsi *dsi,
|
||||||
|
unsigned long reg)
|
||||||
|
{
|
||||||
|
return readl(dsi->regs + (reg << 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tegra_dsi_writel(struct tegra_dsi *dsi, unsigned long value,
|
||||||
|
unsigned long reg)
|
||||||
|
{
|
||||||
|
writel(value, dsi->regs + (reg << 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_show_regs(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct drm_info_node *node = s->private;
|
||||||
|
struct tegra_dsi *dsi = node->info_ent->data;
|
||||||
|
|
||||||
|
#define DUMP_REG(name) \
|
||||||
|
seq_printf(s, "%-32s %#05x %08lx\n", #name, name, \
|
||||||
|
tegra_dsi_readl(dsi, name))
|
||||||
|
|
||||||
|
DUMP_REG(DSI_INCR_SYNCPT);
|
||||||
|
DUMP_REG(DSI_INCR_SYNCPT_CONTROL);
|
||||||
|
DUMP_REG(DSI_INCR_SYNCPT_ERROR);
|
||||||
|
DUMP_REG(DSI_CTXSW);
|
||||||
|
DUMP_REG(DSI_RD_DATA);
|
||||||
|
DUMP_REG(DSI_WR_DATA);
|
||||||
|
DUMP_REG(DSI_POWER_CONTROL);
|
||||||
|
DUMP_REG(DSI_INT_ENABLE);
|
||||||
|
DUMP_REG(DSI_INT_STATUS);
|
||||||
|
DUMP_REG(DSI_INT_MASK);
|
||||||
|
DUMP_REG(DSI_HOST_CONTROL);
|
||||||
|
DUMP_REG(DSI_CONTROL);
|
||||||
|
DUMP_REG(DSI_SOL_DELAY);
|
||||||
|
DUMP_REG(DSI_MAX_THRESHOLD);
|
||||||
|
DUMP_REG(DSI_TRIGGER);
|
||||||
|
DUMP_REG(DSI_TX_CRC);
|
||||||
|
DUMP_REG(DSI_STATUS);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_CONTROL);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_0);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_1);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_2);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_3);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_4);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_5);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_6);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_7);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_0_LO);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_0_HI);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_1_LO);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_1_HI);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_2_LO);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_2_HI);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_3_LO);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_3_HI);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_4_LO);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_4_HI);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_5_LO);
|
||||||
|
DUMP_REG(DSI_PKT_SEQ_5_HI);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_DCS_CMDS);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_PKT_LEN_0_1);
|
||||||
|
DUMP_REG(DSI_PKT_LEN_2_3);
|
||||||
|
DUMP_REG(DSI_PKT_LEN_4_5);
|
||||||
|
DUMP_REG(DSI_PKT_LEN_6_7);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_PHY_TIMING_0);
|
||||||
|
DUMP_REG(DSI_PHY_TIMING_1);
|
||||||
|
DUMP_REG(DSI_PHY_TIMING_2);
|
||||||
|
DUMP_REG(DSI_BTA_TIMING);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_TIMEOUT_0);
|
||||||
|
DUMP_REG(DSI_TIMEOUT_1);
|
||||||
|
DUMP_REG(DSI_TO_TALLY);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_PAD_CONTROL_0);
|
||||||
|
DUMP_REG(DSI_PAD_CONTROL_CD);
|
||||||
|
DUMP_REG(DSI_PAD_CD_STATUS);
|
||||||
|
DUMP_REG(DSI_VIDEO_MODE_CONTROL);
|
||||||
|
DUMP_REG(DSI_PAD_CONTROL_1);
|
||||||
|
DUMP_REG(DSI_PAD_CONTROL_2);
|
||||||
|
DUMP_REG(DSI_PAD_CONTROL_3);
|
||||||
|
DUMP_REG(DSI_PAD_CONTROL_4);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_GANGED_MODE_CONTROL);
|
||||||
|
DUMP_REG(DSI_GANGED_MODE_START);
|
||||||
|
DUMP_REG(DSI_GANGED_MODE_SIZE);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_RAW_DATA_BYTE_COUNT);
|
||||||
|
DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL);
|
||||||
|
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_8);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_9);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_10);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_11);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_12);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_13);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_14);
|
||||||
|
DUMP_REG(DSI_INIT_SEQ_DATA_15);
|
||||||
|
|
||||||
|
#undef DUMP_REG
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_info_list debugfs_files[] = {
|
||||||
|
{ "regs", tegra_dsi_show_regs, 0, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi,
|
||||||
|
struct drm_minor *minor)
|
||||||
|
{
|
||||||
|
const char *name = dev_name(dsi->dev);
|
||||||
|
unsigned int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root);
|
||||||
|
if (!dsi->debugfs)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!dsi->debugfs_files) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
|
||||||
|
dsi->debugfs_files[i].data = dsi;
|
||||||
|
|
||||||
|
err = drm_debugfs_create_files(dsi->debugfs_files,
|
||||||
|
ARRAY_SIZE(debugfs_files),
|
||||||
|
dsi->debugfs, minor);
|
||||||
|
if (err < 0)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
dsi->minor = minor;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free:
|
||||||
|
kfree(dsi->debugfs_files);
|
||||||
|
dsi->debugfs_files = NULL;
|
||||||
|
remove:
|
||||||
|
debugfs_remove(dsi->debugfs);
|
||||||
|
dsi->debugfs = NULL;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_debugfs_exit(struct tegra_dsi *dsi)
|
||||||
|
{
|
||||||
|
drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files),
|
||||||
|
dsi->minor);
|
||||||
|
dsi->minor = NULL;
|
||||||
|
|
||||||
|
kfree(dsi->debugfs_files);
|
||||||
|
dsi->debugfs_files = NULL;
|
||||||
|
|
||||||
|
debugfs_remove(dsi->debugfs);
|
||||||
|
dsi->debugfs = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PKT_ID0(id) ((((id) & 0x3f) << 3) | (1 << 9))
|
||||||
|
#define PKT_LEN0(len) (((len) & 0x07) << 0)
|
||||||
|
#define PKT_ID1(id) ((((id) & 0x3f) << 13) | (1 << 19))
|
||||||
|
#define PKT_LEN1(len) (((len) & 0x07) << 10)
|
||||||
|
#define PKT_ID2(id) ((((id) & 0x3f) << 23) | (1 << 29))
|
||||||
|
#define PKT_LEN2(len) (((len) & 0x07) << 20)
|
||||||
|
|
||||||
|
#define PKT_LP (1 << 30)
|
||||||
|
#define NUM_PKT_SEQ 12
|
||||||
|
|
||||||
|
/* non-burst mode with sync-end */
|
||||||
|
static const u32 pkt_seq_vnb_syne[NUM_PKT_SEQ] = {
|
||||||
|
[ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
|
||||||
|
PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
|
||||||
|
PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
|
||||||
|
PKT_LP,
|
||||||
|
[ 1] = 0,
|
||||||
|
[ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) |
|
||||||
|
PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
|
||||||
|
PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
|
||||||
|
PKT_LP,
|
||||||
|
[ 3] = 0,
|
||||||
|
[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
|
||||||
|
PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
|
||||||
|
PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
|
||||||
|
PKT_LP,
|
||||||
|
[ 5] = 0,
|
||||||
|
[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
|
||||||
|
PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
|
||||||
|
PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
|
||||||
|
[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
|
||||||
|
PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
|
||||||
|
PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
|
||||||
|
[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
|
||||||
|
PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
|
||||||
|
PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
|
||||||
|
PKT_LP,
|
||||||
|
[ 9] = 0,
|
||||||
|
[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
|
||||||
|
PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
|
||||||
|
PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
|
||||||
|
[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
|
||||||
|
PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
|
||||||
|
PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi)
|
||||||
|
{
|
||||||
|
struct mipi_dphy_timing timing;
|
||||||
|
unsigned long value, period;
|
||||||
|
long rate;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
rate = clk_get_rate(dsi->clk);
|
||||||
|
if (rate < 0)
|
||||||
|
return rate;
|
||||||
|
|
||||||
|
period = DIV_ROUND_CLOSEST(1000000000UL, rate * 2);
|
||||||
|
|
||||||
|
err = mipi_dphy_timing_get_default(&timing, period);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = mipi_dphy_timing_validate(&timing, period);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The D-PHY timing fields below are expressed in byte-clock cycles,
|
||||||
|
* so multiply the period by 8.
|
||||||
|
*/
|
||||||
|
period *= 8;
|
||||||
|
|
||||||
|
value = DSI_TIMING_FIELD(timing.hsexit, period, 1) << 24 |
|
||||||
|
DSI_TIMING_FIELD(timing.hstrail, period, 0) << 16 |
|
||||||
|
DSI_TIMING_FIELD(timing.hszero, period, 3) << 8 |
|
||||||
|
DSI_TIMING_FIELD(timing.hsprepare, period, 1);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0);
|
||||||
|
|
||||||
|
value = DSI_TIMING_FIELD(timing.clktrail, period, 1) << 24 |
|
||||||
|
DSI_TIMING_FIELD(timing.clkpost, period, 1) << 16 |
|
||||||
|
DSI_TIMING_FIELD(timing.clkzero, period, 1) << 8 |
|
||||||
|
DSI_TIMING_FIELD(timing.lpx, period, 1);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1);
|
||||||
|
|
||||||
|
value = DSI_TIMING_FIELD(timing.clkprepare, period, 1) << 16 |
|
||||||
|
DSI_TIMING_FIELD(timing.clkpre, period, 1) << 8 |
|
||||||
|
DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2);
|
||||||
|
|
||||||
|
value = DSI_TIMING_FIELD(timing.taget, period, 1) << 16 |
|
||||||
|
DSI_TIMING_FIELD(timing.tasure, period, 1) << 8 |
|
||||||
|
DSI_TIMING_FIELD(timing.tago, period, 1);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format,
|
||||||
|
unsigned int *mulp, unsigned int *divp)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case MIPI_DSI_FMT_RGB666_PACKED:
|
||||||
|
case MIPI_DSI_FMT_RGB888:
|
||||||
|
*mulp = 3;
|
||||||
|
*divp = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIPI_DSI_FMT_RGB565:
|
||||||
|
*mulp = 2;
|
||||||
|
*divp = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIPI_DSI_FMT_RGB666:
|
||||||
|
*mulp = 9;
|
||||||
|
*divp = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_output_dsi_enable(struct tegra_output *output)
|
||||||
|
{
|
||||||
|
struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
|
||||||
|
struct drm_display_mode *mode = &dc->base.mode;
|
||||||
|
unsigned int hact, hsw, hbp, hfp, i, mul, div;
|
||||||
|
struct tegra_dsi *dsi = to_dsi(output);
|
||||||
|
/* FIXME: don't hardcode this */
|
||||||
|
const u32 *pkt_seq = pkt_seq_vnb_syne;
|
||||||
|
unsigned long value;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = clk_enable(dsi->clk);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
reset_control_deassert(dsi->rst);
|
||||||
|
|
||||||
|
value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(dsi->format) |
|
||||||
|
DSI_CONTROL_LANES(dsi->lanes - 1) |
|
||||||
|
DSI_CONTROL_SOURCE(dc->pipe);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_CONTROL);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, DSI_VIDEO_FIFO_DEPTH, DSI_MAX_THRESHOLD);
|
||||||
|
|
||||||
|
value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS |
|
||||||
|
DSI_HOST_CONTROL_ECC;
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
|
||||||
|
|
||||||
|
value = tegra_dsi_readl(dsi, DSI_CONTROL);
|
||||||
|
value |= DSI_CONTROL_HS_CLK_CTRL;
|
||||||
|
value &= ~DSI_CONTROL_TX_TRIG(3);
|
||||||
|
value &= ~DSI_CONTROL_DCS_ENABLE;
|
||||||
|
value |= DSI_CONTROL_VIDEO_ENABLE;
|
||||||
|
value &= ~DSI_CONTROL_HOST_ENABLE;
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_CONTROL);
|
||||||
|
|
||||||
|
err = tegra_dsi_set_phy_timing(dsi);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_PKT_SEQ; i++)
|
||||||
|
tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);
|
||||||
|
|
||||||
|
/* horizontal active pixels */
|
||||||
|
hact = mode->hdisplay * mul / div;
|
||||||
|
|
||||||
|
/* horizontal sync width */
|
||||||
|
hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
|
||||||
|
hsw -= 10;
|
||||||
|
|
||||||
|
/* horizontal back porch */
|
||||||
|
hbp = (mode->htotal - mode->hsync_end) * mul / div;
|
||||||
|
hbp -= 14;
|
||||||
|
|
||||||
|
/* horizontal front porch */
|
||||||
|
hfp = (mode->hsync_start - mode->hdisplay) * mul / div;
|
||||||
|
hfp -= 8;
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
|
||||||
|
tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3);
|
||||||
|
tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
|
||||||
|
tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
|
||||||
|
|
||||||
|
/* set SOL delay */
|
||||||
|
tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
|
||||||
|
|
||||||
|
/* enable display controller */
|
||||||
|
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
value |= DSI_ENABLE;
|
||||||
|
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
value &= ~DISP_CTRL_MODE_MASK;
|
||||||
|
value |= DISP_CTRL_MODE_C_DISPLAY;
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
||||||
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
|
tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
||||||
|
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
||||||
|
|
||||||
|
/* enable DSI controller */
|
||||||
|
value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
|
||||||
|
value |= DSI_POWER_CONTROL_ENABLE;
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_output_dsi_disable(struct tegra_output *output)
|
||||||
|
{
|
||||||
|
struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
|
||||||
|
struct tegra_dsi *dsi = to_dsi(output);
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
/* disable DSI controller */
|
||||||
|
value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
|
||||||
|
value &= DSI_POWER_CONTROL_ENABLE;
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following accesses registers of the display controller, so make
|
||||||
|
* sure it's only executed when the output is attached to one.
|
||||||
|
*/
|
||||||
|
if (dc) {
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
||||||
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
value &= ~DISP_CTRL_MODE_MASK;
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
value &= ~DSI_ENABLE;
|
||||||
|
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
|
||||||
|
tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
||||||
|
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_disable(dsi->clk);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_output_dsi_setup_clock(struct tegra_output *output,
|
||||||
|
struct clk *clk, unsigned long pclk)
|
||||||
|
{
|
||||||
|
struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
|
||||||
|
struct drm_display_mode *mode = &dc->base.mode;
|
||||||
|
unsigned int timeout, mul, div, vrefresh;
|
||||||
|
struct tegra_dsi *dsi = to_dsi(output);
|
||||||
|
unsigned long bclk, plld, value;
|
||||||
|
struct clk *base;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = tegra_dsi_get_muldiv(dsi->format, &mul, &div);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
vrefresh = drm_mode_vrefresh(mode);
|
||||||
|
|
||||||
|
pclk = mode->htotal * mode->vtotal * vrefresh;
|
||||||
|
bclk = (pclk * mul) / (div * dsi->lanes);
|
||||||
|
plld = DIV_ROUND_UP(bclk * 8, 1000000);
|
||||||
|
pclk = (plld * 1000000) / 2;
|
||||||
|
|
||||||
|
err = clk_set_parent(clk, dsi->clk_parent);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dsi->dev, "failed to set parent clock: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = clk_get_parent(dsi->clk_parent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This assumes that the parent clock is pll_d_out0 or pll_d2_out
|
||||||
|
* respectively, each of which divides the base pll_d by 2.
|
||||||
|
*/
|
||||||
|
err = clk_set_rate(base, pclk * 2);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dsi->dev, "failed to set base clock rate to %lu Hz\n",
|
||||||
|
pclk * 2);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: Move the below somewhere else so that we don't need to have
|
||||||
|
* access to the vrefresh in this function?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* one frame high-speed transmission timeout */
|
||||||
|
timeout = (bclk / vrefresh) / 512;
|
||||||
|
value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
|
||||||
|
|
||||||
|
/* 2 ms peripheral timeout for panel */
|
||||||
|
timeout = 2 * bclk / 512 * 1000;
|
||||||
|
value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
|
||||||
|
|
||||||
|
value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_output_dsi_check_mode(struct tegra_output *output,
|
||||||
|
struct drm_display_mode *mode,
|
||||||
|
enum drm_mode_status *status)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* FIXME: For now, always assume that the mode is okay.
|
||||||
|
*/
|
||||||
|
|
||||||
|
*status = MODE_OK;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct tegra_output_ops dsi_ops = {
|
||||||
|
.enable = tegra_output_dsi_enable,
|
||||||
|
.disable = tegra_output_dsi_disable,
|
||||||
|
.setup_clock = tegra_output_dsi_setup_clock,
|
||||||
|
.check_mode = tegra_output_dsi_check_mode,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
|
||||||
|
{
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
||||||
|
{
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
|
||||||
|
|
||||||
|
/* start calibration */
|
||||||
|
tegra_dsi_pad_enable(dsi);
|
||||||
|
|
||||||
|
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
|
||||||
|
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
|
||||||
|
DSI_PAD_OUT_CLK(0x0);
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
|
||||||
|
|
||||||
|
return tegra_mipi_calibrate(dsi->mipi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_init(struct host1x_client *client)
|
||||||
|
{
|
||||||
|
struct tegra_drm *tegra = dev_get_drvdata(client->parent);
|
||||||
|
struct tegra_dsi *dsi = host1x_client_to_dsi(client);
|
||||||
|
unsigned long value, i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
dsi->output.type = TEGRA_OUTPUT_DSI;
|
||||||
|
dsi->output.dev = client->dev;
|
||||||
|
dsi->output.ops = &dsi_ops;
|
||||||
|
|
||||||
|
err = tegra_output_init(tegra->drm, &dsi->output);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(client->dev, "output setup failed: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
|
||||||
|
err = tegra_dsi_debugfs_init(dsi, tegra->drm->primary);
|
||||||
|
if (err < 0)
|
||||||
|
dev_err(dsi->dev, "debugfs setup failed: %d\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* enable high-speed mode, checksum generation, ECC generation and
|
||||||
|
* disable raw mode
|
||||||
|
*/
|
||||||
|
value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
|
||||||
|
value |= DSI_HOST_CONTROL_ECC | DSI_HOST_CONTROL_CS |
|
||||||
|
DSI_HOST_CONTROL_HS;
|
||||||
|
value &= ~DSI_HOST_CONTROL_RAW;
|
||||||
|
tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 12; i++)
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS);
|
||||||
|
|
||||||
|
err = tegra_dsi_pad_calibrate(dsi);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, DSI_POWER_CONTROL_ENABLE, DSI_POWER_CONTROL);
|
||||||
|
usleep_range(300, 1000);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_exit(struct host1x_client *client)
|
||||||
|
{
|
||||||
|
struct tegra_dsi *dsi = host1x_client_to_dsi(client);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
|
||||||
|
err = tegra_dsi_debugfs_exit(dsi);
|
||||||
|
if (err < 0)
|
||||||
|
dev_err(dsi->dev, "debugfs cleanup failed: %d\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tegra_output_disable(&dsi->output);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(client->dev, "output failed to disable: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tegra_output_exit(&dsi->output);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(client->dev, "output cleanup failed: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct host1x_client_ops dsi_client_ops = {
|
||||||
|
.init = tegra_dsi_init,
|
||||||
|
.exit = tegra_dsi_exit,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
|
||||||
|
{
|
||||||
|
struct clk *parent;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
parent = clk_get_parent(dsi->clk);
|
||||||
|
if (!parent)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = clk_set_parent(parent, dsi->clk_parent);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_dsi_initialize(struct tegra_dsi *dsi)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_POWER_CONTROL);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INT_ENABLE);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INT_STATUS);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INT_MASK);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_HOST_CONTROL);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_CONTROL);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_SOL_DELAY);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_MAX_THRESHOLD);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_CONTROL);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + i);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_8 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 12; i++)
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PKT_SEQ_0_LO + i);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_DCS_CMDS);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1 + i);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0x00000000, DSI_PHY_TIMING_0);
|
||||||
|
tegra_dsi_writel(dsi, 0x00000000, DSI_PHY_TIMING_1);
|
||||||
|
tegra_dsi_writel(dsi, 0x000000ff, DSI_PHY_TIMING_2);
|
||||||
|
tegra_dsi_writel(dsi, 0x00000000, DSI_BTA_TIMING);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_TIMEOUT_0);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_TIMEOUT_1);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_TO_TALLY);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_CD);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CD_STATUS);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_VIDEO_MODE_CONTROL);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
|
||||||
|
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
|
||||||
|
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_host_attach(struct mipi_dsi_host *host,
|
||||||
|
struct mipi_dsi_device *device)
|
||||||
|
{
|
||||||
|
struct tegra_dsi *dsi = host_to_tegra(host);
|
||||||
|
struct tegra_output *output = &dsi->output;
|
||||||
|
|
||||||
|
dsi->format = device->format;
|
||||||
|
dsi->lanes = device->lanes;
|
||||||
|
|
||||||
|
output->panel = of_drm_find_panel(device->dev.of_node);
|
||||||
|
if (output->panel) {
|
||||||
|
if (output->connector.dev)
|
||||||
|
drm_helper_hpd_irq_event(output->connector.dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_host_detach(struct mipi_dsi_host *host,
|
||||||
|
struct mipi_dsi_device *device)
|
||||||
|
{
|
||||||
|
struct tegra_dsi *dsi = host_to_tegra(host);
|
||||||
|
struct tegra_output *output = &dsi->output;
|
||||||
|
|
||||||
|
if (output->panel && &device->dev == output->panel->dev) {
|
||||||
|
if (output->connector.dev)
|
||||||
|
drm_helper_hpd_irq_event(output->connector.dev);
|
||||||
|
|
||||||
|
output->panel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mipi_dsi_host_ops tegra_dsi_host_ops = {
|
||||||
|
.attach = tegra_dsi_host_attach,
|
||||||
|
.detach = tegra_dsi_host_detach,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_dsi_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct tegra_dsi *dsi;
|
||||||
|
struct resource *regs;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
|
||||||
|
if (!dsi)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dsi->output.dev = dsi->dev = &pdev->dev;
|
||||||
|
|
||||||
|
err = tegra_output_probe(&dsi->output);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume these values by default. When a DSI peripheral driver
|
||||||
|
* attaches to the DSI host, the parameters will be taken from
|
||||||
|
* the attached device.
|
||||||
|
*/
|
||||||
|
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||||
|
dsi->lanes = 4;
|
||||||
|
|
||||||
|
dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
|
||||||
|
if (IS_ERR(dsi->rst))
|
||||||
|
return PTR_ERR(dsi->rst);
|
||||||
|
|
||||||
|
dsi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(dsi->clk)) {
|
||||||
|
dev_err(&pdev->dev, "cannot get DSI clock\n");
|
||||||
|
return PTR_ERR(dsi->clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clk_prepare_enable(dsi->clk);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "cannot enable DSI clock\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
|
||||||
|
if (IS_ERR(dsi->clk_lp)) {
|
||||||
|
dev_err(&pdev->dev, "cannot get low-power clock\n");
|
||||||
|
return PTR_ERR(dsi->clk_lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clk_prepare_enable(dsi->clk_lp);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "cannot enable low-power clock\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
|
||||||
|
if (IS_ERR(dsi->clk_parent)) {
|
||||||
|
dev_err(&pdev->dev, "cannot get parent clock\n");
|
||||||
|
return PTR_ERR(dsi->clk_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clk_prepare_enable(dsi->clk_parent);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "cannot enable parent clock\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tegra_dsi_setup_clocks(dsi);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "cannot setup clocks\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
|
||||||
|
if (IS_ERR(dsi->regs))
|
||||||
|
return PTR_ERR(dsi->regs);
|
||||||
|
|
||||||
|
tegra_dsi_initialize(dsi);
|
||||||
|
|
||||||
|
dsi->mipi = tegra_mipi_request(&pdev->dev);
|
||||||
|
if (IS_ERR(dsi->mipi))
|
||||||
|
return PTR_ERR(dsi->mipi);
|
||||||
|
|
||||||
|
dsi->host.ops = &tegra_dsi_host_ops;
|
||||||
|
dsi->host.dev = &pdev->dev;
|
||||||
|
|
||||||
|
err = mipi_dsi_host_register(&dsi->host);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to register DSI host: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&dsi->client.list);
|
||||||
|
dsi->client.ops = &dsi_client_ops;
|
||||||
|
dsi->client.dev = &pdev->dev;
|
||||||
|
|
||||||
|
err = host1x_client_register(&dsi->client);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
|
||||||
|
err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, dsi);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_dsi_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct tegra_dsi *dsi = platform_get_drvdata(pdev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = host1x_client_unregister(&dsi->client);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
|
||||||
|
err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mipi_dsi_host_unregister(&dsi->host);
|
||||||
|
tegra_mipi_free(dsi->mipi);
|
||||||
|
|
||||||
|
clk_disable_unprepare(dsi->clk_parent);
|
||||||
|
clk_disable_unprepare(dsi->clk_lp);
|
||||||
|
clk_disable_unprepare(dsi->clk);
|
||||||
|
|
||||||
|
err = tegra_output_remove(&dsi->output);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to remove output: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id tegra_dsi_of_match[] = {
|
||||||
|
{ .compatible = "nvidia,tegra114-dsi", },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct platform_driver tegra_dsi_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "tegra-dsi",
|
||||||
|
.of_match_table = tegra_dsi_of_match,
|
||||||
|
},
|
||||||
|
.probe = tegra_dsi_probe,
|
||||||
|
.remove = tegra_dsi_remove,
|
||||||
|
};
|
134
drivers/gpu/drm/tegra/dsi.h
Normal file
134
drivers/gpu/drm/tegra/dsi.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 NVIDIA Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRM_TEGRA_DSI_H
|
||||||
|
#define DRM_TEGRA_DSI_H
|
||||||
|
|
||||||
|
#define DSI_INCR_SYNCPT 0x00
|
||||||
|
#define DSI_INCR_SYNCPT_CONTROL 0x01
|
||||||
|
#define DSI_INCR_SYNCPT_ERROR 0x02
|
||||||
|
#define DSI_CTXSW 0x08
|
||||||
|
#define DSI_RD_DATA 0x09
|
||||||
|
#define DSI_WR_DATA 0x0a
|
||||||
|
#define DSI_POWER_CONTROL 0x0b
|
||||||
|
#define DSI_POWER_CONTROL_ENABLE (1 << 0)
|
||||||
|
#define DSI_INT_ENABLE 0x0c
|
||||||
|
#define DSI_INT_STATUS 0x0d
|
||||||
|
#define DSI_INT_MASK 0x0e
|
||||||
|
#define DSI_HOST_CONTROL 0x0f
|
||||||
|
#define DSI_HOST_CONTROL_RAW (1 << 6)
|
||||||
|
#define DSI_HOST_CONTROL_HS (1 << 5)
|
||||||
|
#define DSI_HOST_CONTROL_BTA (1 << 2)
|
||||||
|
#define DSI_HOST_CONTROL_CS (1 << 1)
|
||||||
|
#define DSI_HOST_CONTROL_ECC (1 << 0)
|
||||||
|
#define DSI_CONTROL 0x10
|
||||||
|
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
|
||||||
|
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
|
||||||
|
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
|
||||||
|
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
|
||||||
|
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
|
||||||
|
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
|
||||||
|
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
|
||||||
|
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
|
||||||
|
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
|
||||||
|
#define DSI_SOL_DELAY 0x11
|
||||||
|
#define DSI_MAX_THRESHOLD 0x12
|
||||||
|
#define DSI_TRIGGER 0x13
|
||||||
|
#define DSI_TX_CRC 0x14
|
||||||
|
#define DSI_STATUS 0x15
|
||||||
|
#define DSI_STATUS_IDLE (1 << 10)
|
||||||
|
#define DSI_INIT_SEQ_CONTROL 0x1a
|
||||||
|
#define DSI_INIT_SEQ_DATA_0 0x1b
|
||||||
|
#define DSI_INIT_SEQ_DATA_1 0x1c
|
||||||
|
#define DSI_INIT_SEQ_DATA_2 0x1d
|
||||||
|
#define DSI_INIT_SEQ_DATA_3 0x1e
|
||||||
|
#define DSI_INIT_SEQ_DATA_4 0x1f
|
||||||
|
#define DSI_INIT_SEQ_DATA_5 0x20
|
||||||
|
#define DSI_INIT_SEQ_DATA_6 0x21
|
||||||
|
#define DSI_INIT_SEQ_DATA_7 0x22
|
||||||
|
#define DSI_PKT_SEQ_0_LO 0x23
|
||||||
|
#define DSI_PKT_SEQ_0_HI 0x24
|
||||||
|
#define DSI_PKT_SEQ_1_LO 0x25
|
||||||
|
#define DSI_PKT_SEQ_1_HI 0x26
|
||||||
|
#define DSI_PKT_SEQ_2_LO 0x27
|
||||||
|
#define DSI_PKT_SEQ_2_HI 0x28
|
||||||
|
#define DSI_PKT_SEQ_3_LO 0x29
|
||||||
|
#define DSI_PKT_SEQ_3_HI 0x2a
|
||||||
|
#define DSI_PKT_SEQ_4_LO 0x2b
|
||||||
|
#define DSI_PKT_SEQ_4_HI 0x2c
|
||||||
|
#define DSI_PKT_SEQ_5_LO 0x2d
|
||||||
|
#define DSI_PKT_SEQ_5_HI 0x2e
|
||||||
|
#define DSI_DCS_CMDS 0x33
|
||||||
|
#define DSI_PKT_LEN_0_1 0x34
|
||||||
|
#define DSI_PKT_LEN_2_3 0x35
|
||||||
|
#define DSI_PKT_LEN_4_5 0x36
|
||||||
|
#define DSI_PKT_LEN_6_7 0x37
|
||||||
|
#define DSI_PHY_TIMING_0 0x3c
|
||||||
|
#define DSI_PHY_TIMING_1 0x3d
|
||||||
|
#define DSI_PHY_TIMING_2 0x3e
|
||||||
|
#define DSI_BTA_TIMING 0x3f
|
||||||
|
|
||||||
|
#define DSI_TIMING_FIELD(value, period, hwinc) \
|
||||||
|
((DIV_ROUND_CLOSEST(value, period) - (hwinc)) & 0xff)
|
||||||
|
|
||||||
|
#define DSI_TIMEOUT_0 0x44
|
||||||
|
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
|
||||||
|
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
|
||||||
|
#define DSI_TIMEOUT_1 0x45
|
||||||
|
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
|
||||||
|
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
|
||||||
|
#define DSI_TO_TALLY 0x46
|
||||||
|
#define DSI_TALLY_TA(x) (((x) & 0xff) << 16)
|
||||||
|
#define DSI_TALLY_LRX(x) (((x) & 0xff) << 8)
|
||||||
|
#define DSI_TALLY_HTX(x) (((x) & 0xff) << 0)
|
||||||
|
#define DSI_PAD_CONTROL_0 0x4b
|
||||||
|
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
|
||||||
|
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
|
||||||
|
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
|
||||||
|
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
|
||||||
|
#define DSI_PAD_CONTROL_CD 0x4c
|
||||||
|
#define DSI_PAD_CD_STATUS 0x4d
|
||||||
|
#define DSI_VIDEO_MODE_CONTROL 0x4e
|
||||||
|
#define DSI_PAD_CONTROL_1 0x4f
|
||||||
|
#define DSI_PAD_CONTROL_2 0x50
|
||||||
|
#define DSI_PAD_OUT_CLK(x) (((x) & 0x7) << 0)
|
||||||
|
#define DSI_PAD_LP_DN(x) (((x) & 0x7) << 4)
|
||||||
|
#define DSI_PAD_LP_UP(x) (((x) & 0x7) << 8)
|
||||||
|
#define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12)
|
||||||
|
#define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16)
|
||||||
|
#define DSI_PAD_CONTROL_3 0x51
|
||||||
|
#define DSI_PAD_CONTROL_4 0x52
|
||||||
|
#define DSI_GANGED_MODE_CONTROL 0x53
|
||||||
|
#define DSI_GANGED_MODE_START 0x54
|
||||||
|
#define DSI_GANGED_MODE_SIZE 0x55
|
||||||
|
#define DSI_RAW_DATA_BYTE_COUNT 0x56
|
||||||
|
#define DSI_ULTRA_LOW_POWER_CONTROL 0x57
|
||||||
|
#define DSI_INIT_SEQ_DATA_8 0x58
|
||||||
|
#define DSI_INIT_SEQ_DATA_9 0x59
|
||||||
|
#define DSI_INIT_SEQ_DATA_10 0x5a
|
||||||
|
#define DSI_INIT_SEQ_DATA_11 0x5b
|
||||||
|
#define DSI_INIT_SEQ_DATA_12 0x5c
|
||||||
|
#define DSI_INIT_SEQ_DATA_13 0x5d
|
||||||
|
#define DSI_INIT_SEQ_DATA_14 0x5e
|
||||||
|
#define DSI_INIT_SEQ_DATA_15 0x5f
|
||||||
|
|
||||||
|
#endif
|
@ -18,10 +18,12 @@ static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
|
|||||||
return container_of(fb, struct tegra_fb, base);
|
return container_of(fb, struct tegra_fb, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
|
static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
|
||||||
{
|
{
|
||||||
return container_of(helper, struct tegra_fbdev, base);
|
return container_of(helper, struct tegra_fbdev, base);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
|
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
|
||||||
unsigned int index)
|
unsigned int index)
|
||||||
@ -98,8 +100,10 @@ static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
|
|||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
|
fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
|
||||||
if (!fb->planes)
|
if (!fb->planes) {
|
||||||
|
kfree(fb);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
fb->num_planes = num_planes;
|
fb->num_planes = num_planes;
|
||||||
|
|
||||||
@ -172,6 +176,7 @@ unreference:
|
|||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
static struct fb_ops tegra_fb_ops = {
|
static struct fb_ops tegra_fb_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.fb_fillrect = sys_fillrect,
|
.fb_fillrect = sys_fillrect,
|
||||||
@ -339,6 +344,15 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
|
|||||||
kfree(fbdev);
|
kfree(fbdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
|
||||||
|
{
|
||||||
|
if (fbdev) {
|
||||||
|
drm_modeset_lock_all(fbdev->base.dev);
|
||||||
|
drm_fb_helper_restore_fbdev_mode(&fbdev->base);
|
||||||
|
drm_modeset_unlock_all(fbdev->base.dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void tegra_fb_output_poll_changed(struct drm_device *drm)
|
static void tegra_fb_output_poll_changed(struct drm_device *drm)
|
||||||
{
|
{
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
@ -346,16 +360,20 @@ static void tegra_fb_output_poll_changed(struct drm_device *drm)
|
|||||||
if (tegra->fbdev)
|
if (tegra->fbdev)
|
||||||
drm_fb_helper_hotplug_event(&tegra->fbdev->base);
|
drm_fb_helper_hotplug_event(&tegra->fbdev->base);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
|
static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
|
||||||
.fb_create = tegra_fb_create,
|
.fb_create = tegra_fb_create,
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
.output_poll_changed = tegra_fb_output_poll_changed,
|
.output_poll_changed = tegra_fb_output_poll_changed,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int tegra_drm_fb_init(struct drm_device *drm)
|
int tegra_drm_fb_init(struct drm_device *drm)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
struct tegra_fbdev *fbdev;
|
#endif
|
||||||
|
|
||||||
drm->mode_config.min_width = 0;
|
drm->mode_config.min_width = 0;
|
||||||
drm->mode_config.min_height = 0;
|
drm->mode_config.min_height = 0;
|
||||||
@ -365,28 +383,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
|
|||||||
|
|
||||||
drm->mode_config.funcs = &tegra_drm_mode_funcs;
|
drm->mode_config.funcs = &tegra_drm_mode_funcs;
|
||||||
|
|
||||||
fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
drm->mode_config.num_connector);
|
tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
|
||||||
if (IS_ERR(fbdev))
|
drm->mode_config.num_connector);
|
||||||
return PTR_ERR(fbdev);
|
if (IS_ERR(tegra->fbdev))
|
||||||
|
return PTR_ERR(tegra->fbdev);
|
||||||
tegra->fbdev = fbdev;
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tegra_drm_fb_exit(struct drm_device *drm)
|
void tegra_drm_fb_exit(struct drm_device *drm)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
|
|
||||||
tegra_fbdev_free(tegra->fbdev);
|
tegra_fbdev_free(tegra->fbdev);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
|
|
||||||
{
|
|
||||||
if (fbdev) {
|
|
||||||
drm_modeset_lock_all(fbdev->base.dev);
|
|
||||||
drm_fb_helper_restore_fbdev_mode(&fbdev->base);
|
|
||||||
drm_modeset_unlock_all(fbdev->base.dev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/dma-buf.h>
|
||||||
#include <drm/tegra_drm.h>
|
#include <drm/tegra_drm.h>
|
||||||
|
|
||||||
#include "gem.h"
|
#include "gem.h"
|
||||||
@ -83,7 +84,7 @@ static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
|
|||||||
return bo;
|
return bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct host1x_bo_ops tegra_bo_ops = {
|
static const struct host1x_bo_ops tegra_bo_ops = {
|
||||||
.get = tegra_bo_get,
|
.get = tegra_bo_get,
|
||||||
.put = tegra_bo_put,
|
.put = tegra_bo_put,
|
||||||
.pin = tegra_bo_pin,
|
.pin = tegra_bo_pin,
|
||||||
@ -145,7 +146,6 @@ err_dma:
|
|||||||
kfree(bo);
|
kfree(bo);
|
||||||
|
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
|
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
|
||||||
@ -174,13 +174,87 @@ err:
|
|||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tegra_bo *tegra_bo_import(struct drm_device *drm, struct dma_buf *buf)
|
||||||
|
{
|
||||||
|
struct dma_buf_attachment *attach;
|
||||||
|
struct tegra_bo *bo;
|
||||||
|
ssize_t size;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
bo = kzalloc(sizeof(*bo), GFP_KERNEL);
|
||||||
|
if (!bo)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
host1x_bo_init(&bo->base, &tegra_bo_ops);
|
||||||
|
size = round_up(buf->size, PAGE_SIZE);
|
||||||
|
|
||||||
|
err = drm_gem_object_init(drm, &bo->gem, size);
|
||||||
|
if (err < 0)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
err = drm_gem_create_mmap_offset(&bo->gem);
|
||||||
|
if (err < 0)
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
attach = dma_buf_attach(buf, drm->dev);
|
||||||
|
if (IS_ERR(attach)) {
|
||||||
|
err = PTR_ERR(attach);
|
||||||
|
goto free_mmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_dma_buf(buf);
|
||||||
|
|
||||||
|
bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
|
||||||
|
if (!bo->sgt) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto detach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ERR(bo->sgt)) {
|
||||||
|
err = PTR_ERR(bo->sgt);
|
||||||
|
goto detach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bo->sgt->nents > 1) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto detach;
|
||||||
|
}
|
||||||
|
|
||||||
|
bo->paddr = sg_dma_address(bo->sgt->sgl);
|
||||||
|
bo->gem.import_attach = attach;
|
||||||
|
|
||||||
|
return bo;
|
||||||
|
|
||||||
|
detach:
|
||||||
|
if (!IS_ERR_OR_NULL(bo->sgt))
|
||||||
|
dma_buf_unmap_attachment(attach, bo->sgt, DMA_TO_DEVICE);
|
||||||
|
|
||||||
|
dma_buf_detach(buf, attach);
|
||||||
|
dma_buf_put(buf);
|
||||||
|
free_mmap:
|
||||||
|
drm_gem_free_mmap_offset(&bo->gem);
|
||||||
|
release:
|
||||||
|
drm_gem_object_release(&bo->gem);
|
||||||
|
free:
|
||||||
|
kfree(bo);
|
||||||
|
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
void tegra_bo_free_object(struct drm_gem_object *gem)
|
void tegra_bo_free_object(struct drm_gem_object *gem)
|
||||||
{
|
{
|
||||||
struct tegra_bo *bo = to_tegra_bo(gem);
|
struct tegra_bo *bo = to_tegra_bo(gem);
|
||||||
|
|
||||||
|
if (gem->import_attach) {
|
||||||
|
dma_buf_unmap_attachment(gem->import_attach, bo->sgt,
|
||||||
|
DMA_TO_DEVICE);
|
||||||
|
drm_prime_gem_destroy(gem, NULL);
|
||||||
|
} else {
|
||||||
|
tegra_bo_destroy(gem->dev, bo);
|
||||||
|
}
|
||||||
|
|
||||||
drm_gem_free_mmap_offset(gem);
|
drm_gem_free_mmap_offset(gem);
|
||||||
drm_gem_object_release(gem);
|
drm_gem_object_release(gem);
|
||||||
tegra_bo_destroy(gem->dev, bo);
|
|
||||||
|
|
||||||
kfree(bo);
|
kfree(bo);
|
||||||
}
|
}
|
||||||
@ -256,3 +330,106 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sg_table *
|
||||||
|
tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
|
||||||
|
enum dma_data_direction dir)
|
||||||
|
{
|
||||||
|
struct drm_gem_object *gem = attach->dmabuf->priv;
|
||||||
|
struct tegra_bo *bo = to_tegra_bo(gem);
|
||||||
|
struct sg_table *sgt;
|
||||||
|
|
||||||
|
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
|
||||||
|
if (!sgt)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (sg_alloc_table(sgt, 1, GFP_KERNEL)) {
|
||||||
|
kfree(sgt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_dma_address(sgt->sgl) = bo->paddr;
|
||||||
|
sg_dma_len(sgt->sgl) = gem->size;
|
||||||
|
|
||||||
|
return sgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
|
||||||
|
struct sg_table *sgt,
|
||||||
|
enum dma_data_direction dir)
|
||||||
|
{
|
||||||
|
sg_free_table(sgt);
|
||||||
|
kfree(sgt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_gem_prime_release(struct dma_buf *buf)
|
||||||
|
{
|
||||||
|
drm_gem_dmabuf_release(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *tegra_gem_prime_kmap_atomic(struct dma_buf *buf,
|
||||||
|
unsigned long page)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_gem_prime_kunmap_atomic(struct dma_buf *buf,
|
||||||
|
unsigned long page,
|
||||||
|
void *addr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *tegra_gem_prime_kmap(struct dma_buf *buf, unsigned long page)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page,
|
||||||
|
void *addr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
|
||||||
|
.map_dma_buf = tegra_gem_prime_map_dma_buf,
|
||||||
|
.unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
|
||||||
|
.release = tegra_gem_prime_release,
|
||||||
|
.kmap_atomic = tegra_gem_prime_kmap_atomic,
|
||||||
|
.kunmap_atomic = tegra_gem_prime_kunmap_atomic,
|
||||||
|
.kmap = tegra_gem_prime_kmap,
|
||||||
|
.kunmap = tegra_gem_prime_kunmap,
|
||||||
|
.mmap = tegra_gem_prime_mmap,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
|
||||||
|
struct drm_gem_object *gem,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
return dma_buf_export(gem, &tegra_gem_prime_dmabuf_ops, gem->size,
|
||||||
|
flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
|
||||||
|
struct dma_buf *buf)
|
||||||
|
{
|
||||||
|
struct tegra_bo *bo;
|
||||||
|
|
||||||
|
if (buf->ops == &tegra_gem_prime_dmabuf_ops) {
|
||||||
|
struct drm_gem_object *gem = buf->priv;
|
||||||
|
|
||||||
|
if (gem->dev == drm) {
|
||||||
|
drm_gem_object_reference(gem);
|
||||||
|
return gem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bo = tegra_bo_import(drm, buf);
|
||||||
|
if (IS_ERR(bo))
|
||||||
|
return ERR_CAST(bo);
|
||||||
|
|
||||||
|
return &bo->gem;
|
||||||
|
}
|
||||||
|
@ -31,6 +31,7 @@ struct tegra_bo {
|
|||||||
struct drm_gem_object gem;
|
struct drm_gem_object gem;
|
||||||
struct host1x_bo base;
|
struct host1x_bo base;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct sg_table *sgt;
|
||||||
dma_addr_t paddr;
|
dma_addr_t paddr;
|
||||||
void *vaddr;
|
void *vaddr;
|
||||||
};
|
};
|
||||||
@ -40,8 +41,6 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
|
|||||||
return container_of(gem, struct tegra_bo, gem);
|
return container_of(gem, struct tegra_bo, gem);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const struct host1x_bo_ops tegra_bo_ops;
|
|
||||||
|
|
||||||
struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
|
struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
|
||||||
unsigned long flags);
|
unsigned long flags);
|
||||||
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
|
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
|
||||||
@ -59,4 +58,10 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
|
|||||||
|
|
||||||
extern const struct vm_operations_struct tegra_bo_vm_ops;
|
extern const struct vm_operations_struct tegra_bo_vm_ops;
|
||||||
|
|
||||||
|
struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
|
||||||
|
struct drm_gem_object *gem,
|
||||||
|
int flags);
|
||||||
|
struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
|
||||||
|
struct dma_buf *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <linux/host1x.h>
|
#include <linux/host1x.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
#include <linux/tegra-powergate.h>
|
#include <linux/tegra-powergate.h>
|
||||||
|
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
@ -22,6 +23,8 @@ struct gr3d {
|
|||||||
struct host1x_channel *channel;
|
struct host1x_channel *channel;
|
||||||
struct clk *clk_secondary;
|
struct clk *clk_secondary;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct reset_control *rst_secondary;
|
||||||
|
struct reset_control *rst;
|
||||||
|
|
||||||
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
|
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
|
||||||
};
|
};
|
||||||
@ -255,15 +258,29 @@ static int gr3d_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(gr3d->clk);
|
return PTR_ERR(gr3d->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gr3d->rst = devm_reset_control_get(&pdev->dev, "3d");
|
||||||
|
if (IS_ERR(gr3d->rst)) {
|
||||||
|
dev_err(&pdev->dev, "cannot get reset\n");
|
||||||
|
return PTR_ERR(gr3d->rst);
|
||||||
|
}
|
||||||
|
|
||||||
if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) {
|
if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) {
|
||||||
gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2");
|
gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2");
|
||||||
if (IS_ERR(gr3d->clk)) {
|
if (IS_ERR(gr3d->clk)) {
|
||||||
dev_err(&pdev->dev, "cannot get secondary clock\n");
|
dev_err(&pdev->dev, "cannot get secondary clock\n");
|
||||||
return PTR_ERR(gr3d->clk);
|
return PTR_ERR(gr3d->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gr3d->rst_secondary = devm_reset_control_get(&pdev->dev,
|
||||||
|
"3d2");
|
||||||
|
if (IS_ERR(gr3d->rst_secondary)) {
|
||||||
|
dev_err(&pdev->dev, "cannot get secondary reset\n");
|
||||||
|
return PTR_ERR(gr3d->rst_secondary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk);
|
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk,
|
||||||
|
gr3d->rst);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev, "failed to power up 3D unit\n");
|
dev_err(&pdev->dev, "failed to power up 3D unit\n");
|
||||||
return err;
|
return err;
|
||||||
@ -271,7 +288,8 @@ static int gr3d_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (gr3d->clk_secondary) {
|
if (gr3d->clk_secondary) {
|
||||||
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D1,
|
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D1,
|
||||||
gr3d->clk_secondary);
|
gr3d->clk_secondary,
|
||||||
|
gr3d->rst_secondary);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"failed to power up secondary 3D unit\n");
|
"failed to power up secondary 3D unit\n");
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/clk/tegra.h>
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/hdmi.h>
|
#include <linux/hdmi.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
#include "hdmi.h"
|
#include "hdmi.h"
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
@ -40,6 +40,7 @@ struct tegra_hdmi {
|
|||||||
struct host1x_client client;
|
struct host1x_client client;
|
||||||
struct tegra_output output;
|
struct tegra_output output;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
struct regulator *vdd;
|
struct regulator *vdd;
|
||||||
struct regulator *pll;
|
struct regulator *pll;
|
||||||
@ -49,6 +50,7 @@ struct tegra_hdmi {
|
|||||||
|
|
||||||
struct clk *clk_parent;
|
struct clk *clk_parent;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct reset_control *rst;
|
||||||
|
|
||||||
const struct tegra_hdmi_config *config;
|
const struct tegra_hdmi_config *config;
|
||||||
|
|
||||||
@ -378,7 +380,7 @@ static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
|
|||||||
|
|
||||||
if (f > 96000)
|
if (f > 96000)
|
||||||
delta = 2;
|
delta = 2;
|
||||||
else if (f > 480000)
|
else if (f > 48000)
|
||||||
delta = 6;
|
delta = 6;
|
||||||
else
|
else
|
||||||
delta = 9;
|
delta = 9;
|
||||||
@ -698,6 +700,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
|
|||||||
int retries = 1000;
|
int retries = 1000;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (hdmi->enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
hdmi->dvi = !tegra_output_is_hdmi(output);
|
hdmi->dvi = !tegra_output_is_hdmi(output);
|
||||||
|
|
||||||
pclk = mode->clock * 1000;
|
pclk = mode->clock * 1000;
|
||||||
@ -731,9 +736,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_periph_reset_assert(hdmi->clk);
|
reset_control_assert(hdmi->rst);
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
tegra_periph_reset_deassert(hdmi->clk);
|
reset_control_deassert(hdmi->rst);
|
||||||
|
|
||||||
tegra_dc_writel(dc, VSYNC_H_POSITION(1),
|
tegra_dc_writel(dc, VSYNC_H_POSITION(1),
|
||||||
DC_DISP_DISP_TIMING_OPTIONS);
|
DC_DISP_DISP_TIMING_OPTIONS);
|
||||||
@ -838,10 +843,6 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
|
|||||||
value |= SOR_CSTM_ROTCLK(2);
|
value |= SOR_CSTM_ROTCLK(2);
|
||||||
tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
|
tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
|
||||||
|
|
||||||
tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
|
|
||||||
tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
|
||||||
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
|
||||||
|
|
||||||
/* start SOR */
|
/* start SOR */
|
||||||
tegra_hdmi_writel(hdmi,
|
tegra_hdmi_writel(hdmi,
|
||||||
SOR_PWR_NORMAL_STATE_PU |
|
SOR_PWR_NORMAL_STATE_PU |
|
||||||
@ -891,31 +892,67 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
|
|||||||
HDMI_NV_PDISP_SOR_STATE1);
|
HDMI_NV_PDISP_SOR_STATE1);
|
||||||
tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
|
tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
|
||||||
|
|
||||||
tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
|
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
value |= HDMI_ENABLE;
|
||||||
|
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
|
||||||
value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
|
||||||
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
|
value &= ~DISP_CTRL_MODE_MASK;
|
||||||
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
value |= DISP_CTRL_MODE_C_DISPLAY;
|
||||||
|
|
||||||
value = DISP_CTRL_MODE_C_DISPLAY;
|
|
||||||
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
||||||
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
||||||
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
||||||
|
|
||||||
/* TODO: add HDCP support */
|
/* TODO: add HDCP support */
|
||||||
|
|
||||||
|
hdmi->enabled = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_output_hdmi_disable(struct tegra_output *output)
|
static int tegra_output_hdmi_disable(struct tegra_output *output)
|
||||||
{
|
{
|
||||||
|
struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
|
||||||
struct tegra_hdmi *hdmi = to_hdmi(output);
|
struct tegra_hdmi *hdmi = to_hdmi(output);
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
tegra_periph_reset_assert(hdmi->clk);
|
if (!hdmi->enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following accesses registers of the display controller, so make
|
||||||
|
* sure it's only executed when the output is attached to one.
|
||||||
|
*/
|
||||||
|
if (dc) {
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
||||||
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
value &= ~DISP_CTRL_MODE_MASK;
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
value &= ~HDMI_ENABLE;
|
||||||
|
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||||
|
|
||||||
|
tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
||||||
|
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_control_assert(hdmi->rst);
|
||||||
clk_disable(hdmi->clk);
|
clk_disable(hdmi->clk);
|
||||||
regulator_disable(hdmi->pll);
|
regulator_disable(hdmi->pll);
|
||||||
|
|
||||||
|
hdmi->enabled = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,7 +996,7 @@ static int tegra_output_hdmi_check_mode(struct tegra_output *output,
|
|||||||
parent = clk_get_parent(hdmi->clk_parent);
|
parent = clk_get_parent(hdmi->clk_parent);
|
||||||
|
|
||||||
err = clk_round_rate(parent, pclk * 4);
|
err = clk_round_rate(parent, pclk * 4);
|
||||||
if (err < 0)
|
if (err <= 0)
|
||||||
*status = MODE_NOCLOCK;
|
*status = MODE_NOCLOCK;
|
||||||
else
|
else
|
||||||
*status = MODE_OK;
|
*status = MODE_OK;
|
||||||
@ -1338,6 +1375,12 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(hdmi->clk);
|
return PTR_ERR(hdmi->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hdmi->rst = devm_reset_control_get(&pdev->dev, "hdmi");
|
||||||
|
if (IS_ERR(hdmi->rst)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get reset\n");
|
||||||
|
return PTR_ERR(hdmi->rst);
|
||||||
|
}
|
||||||
|
|
||||||
err = clk_prepare(hdmi->clk);
|
err = clk_prepare(hdmi->clk);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
138
drivers/gpu/drm/tegra/mipi-phy.c
Normal file
138
drivers/gpu/drm/tegra/mipi-phy.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 NVIDIA Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
|
#include "mipi-phy.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default D-PHY timings based on MIPI D-PHY specification. Derived from
|
||||||
|
* the valid ranges specified in Section 5.9 of the D-PHY specification
|
||||||
|
* with minor adjustments.
|
||||||
|
*/
|
||||||
|
int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
|
||||||
|
unsigned long period)
|
||||||
|
{
|
||||||
|
timing->clkmiss = 0;
|
||||||
|
timing->clkpost = 70 + 52 * period;
|
||||||
|
timing->clkpre = 8;
|
||||||
|
timing->clkprepare = 65;
|
||||||
|
timing->clksettle = 95;
|
||||||
|
timing->clktermen = 0;
|
||||||
|
timing->clktrail = 80;
|
||||||
|
timing->clkzero = 260;
|
||||||
|
timing->dtermen = 0;
|
||||||
|
timing->eot = 0;
|
||||||
|
timing->hsexit = 120;
|
||||||
|
timing->hsprepare = 65 + 5 * period;
|
||||||
|
timing->hszero = 145 + 5 * period;
|
||||||
|
timing->hssettle = 85 + 6 * period;
|
||||||
|
timing->hsskip = 40;
|
||||||
|
timing->hstrail = max(8 * period, 60 + 4 * period);
|
||||||
|
timing->init = 100000;
|
||||||
|
timing->lpx = 60;
|
||||||
|
timing->taget = 5 * timing->lpx;
|
||||||
|
timing->tago = 4 * timing->lpx;
|
||||||
|
timing->tasure = 2 * timing->lpx;
|
||||||
|
timing->wakeup = 1000000;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate D-PHY timing according to MIPI Alliance Specification for D-PHY,
|
||||||
|
* Section 5.9 "Global Operation Timing Parameters".
|
||||||
|
*/
|
||||||
|
int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
|
||||||
|
unsigned long period)
|
||||||
|
{
|
||||||
|
if (timing->clkmiss > 60)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clkpost < (60 + 52 * period))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clkpre < 8)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clkprepare < 38 || timing->clkprepare > 95)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clksettle < 95 || timing->clksettle > 300)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clktermen > 38)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clktrail < 60)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->clkprepare + timing->clkzero < 300)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->dtermen > 35 + 4 * period)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->eot > 105 + 12 * period)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->hsexit < 100)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->hsprepare < 40 + 4 * period ||
|
||||||
|
timing->hsprepare > 85 + 6 * period)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->hsprepare + timing->hszero < 145 + 10 * period)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((timing->hssettle < 85 + 6 * period) ||
|
||||||
|
(timing->hssettle > 145 + 10 * period))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->hsskip < 40 || timing->hsskip > 55 + 4 * period)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->hstrail < max(8 * period, 60 + 4 * period))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->init < 100000)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->lpx < 50)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->taget != 5 * timing->lpx)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->tago != 4 * timing->lpx)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->tasure < timing->lpx || timing->tasure > 2 * timing->lpx)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing->wakeup < 1000000)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
65
drivers/gpu/drm/tegra/mipi-phy.h
Normal file
65
drivers/gpu/drm/tegra/mipi-phy.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 NVIDIA Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRM_TEGRA_MIPI_PHY_H
|
||||||
|
#define DRM_TEGRA_MIPI_PHY_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* D-PHY timing parameters
|
||||||
|
*
|
||||||
|
* A detailed description of these parameters can be found in the MIPI
|
||||||
|
* Alliance Specification for D-PHY, Section 5.9 "Global Operation Timing
|
||||||
|
* Parameters".
|
||||||
|
*
|
||||||
|
* All parameters are specified in nanoseconds.
|
||||||
|
*/
|
||||||
|
struct mipi_dphy_timing {
|
||||||
|
unsigned int clkmiss;
|
||||||
|
unsigned int clkpost;
|
||||||
|
unsigned int clkpre;
|
||||||
|
unsigned int clkprepare;
|
||||||
|
unsigned int clksettle;
|
||||||
|
unsigned int clktermen;
|
||||||
|
unsigned int clktrail;
|
||||||
|
unsigned int clkzero;
|
||||||
|
unsigned int dtermen;
|
||||||
|
unsigned int eot;
|
||||||
|
unsigned int hsexit;
|
||||||
|
unsigned int hsprepare;
|
||||||
|
unsigned int hszero;
|
||||||
|
unsigned int hssettle;
|
||||||
|
unsigned int hsskip;
|
||||||
|
unsigned int hstrail;
|
||||||
|
unsigned int init;
|
||||||
|
unsigned int lpx;
|
||||||
|
unsigned int taget;
|
||||||
|
unsigned int tago;
|
||||||
|
unsigned int tasure;
|
||||||
|
unsigned int wakeup;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
|
||||||
|
unsigned long period);
|
||||||
|
int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
|
||||||
|
unsigned long period);
|
||||||
|
|
||||||
|
#endif
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
|
||||||
|
#include <drm/drm_panel.h>
|
||||||
#include "drm.h"
|
#include "drm.h"
|
||||||
|
|
||||||
static int tegra_connector_get_modes(struct drm_connector *connector)
|
static int tegra_connector_get_modes(struct drm_connector *connector)
|
||||||
@ -17,6 +18,12 @@ static int tegra_connector_get_modes(struct drm_connector *connector)
|
|||||||
struct edid *edid = NULL;
|
struct edid *edid = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
if (output->panel) {
|
||||||
|
err = output->panel->funcs->get_modes(output->panel);
|
||||||
|
if (err > 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (output->edid)
|
if (output->edid)
|
||||||
edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
|
edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
|
||||||
else if (output->ddc)
|
else if (output->ddc)
|
||||||
@ -72,6 +79,11 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
|
|||||||
else
|
else
|
||||||
status = connector_status_connected;
|
status = connector_status_connected;
|
||||||
} else {
|
} else {
|
||||||
|
if (!output->panel)
|
||||||
|
status = connector_status_disconnected;
|
||||||
|
else
|
||||||
|
status = connector_status_connected;
|
||||||
|
|
||||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
|
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
|
||||||
status = connector_status_connected;
|
status = connector_status_connected;
|
||||||
}
|
}
|
||||||
@ -115,6 +127,16 @@ static const struct drm_encoder_funcs encoder_funcs = {
|
|||||||
|
|
||||||
static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
|
static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||||
{
|
{
|
||||||
|
struct tegra_output *output = encoder_to_output(encoder);
|
||||||
|
struct drm_panel *panel = output->panel;
|
||||||
|
|
||||||
|
if (mode != DRM_MODE_DPMS_ON) {
|
||||||
|
drm_panel_disable(panel);
|
||||||
|
tegra_output_disable(output);
|
||||||
|
} else {
|
||||||
|
tegra_output_enable(output);
|
||||||
|
drm_panel_enable(panel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
|
static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
|
||||||
@ -163,14 +185,23 @@ static irqreturn_t hpd_irq(int irq, void *data)
|
|||||||
|
|
||||||
int tegra_output_probe(struct tegra_output *output)
|
int tegra_output_probe(struct tegra_output *output)
|
||||||
{
|
{
|
||||||
|
struct device_node *ddc, *panel;
|
||||||
enum of_gpio_flags flags;
|
enum of_gpio_flags flags;
|
||||||
struct device_node *ddc;
|
|
||||||
size_t size;
|
size_t size;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!output->of_node)
|
if (!output->of_node)
|
||||||
output->of_node = output->dev->of_node;
|
output->of_node = output->dev->of_node;
|
||||||
|
|
||||||
|
panel = of_parse_phandle(output->of_node, "nvidia,panel", 0);
|
||||||
|
if (panel) {
|
||||||
|
output->panel = of_drm_find_panel(panel);
|
||||||
|
if (!output->panel)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
|
of_node_put(panel);
|
||||||
|
}
|
||||||
|
|
||||||
output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
|
output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
|
||||||
|
|
||||||
ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
|
ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
|
||||||
@ -185,9 +216,6 @@ int tegra_output_probe(struct tegra_output *output)
|
|||||||
of_node_put(ddc);
|
of_node_put(ddc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!output->edid && !output->ddc)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
|
output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
|
||||||
"nvidia,hpd-gpio", 0,
|
"nvidia,hpd-gpio", 0,
|
||||||
&flags);
|
&flags);
|
||||||
@ -256,6 +284,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
|
|||||||
encoder = DRM_MODE_ENCODER_TMDS;
|
encoder = DRM_MODE_ENCODER_TMDS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TEGRA_OUTPUT_DSI:
|
||||||
|
connector = DRM_MODE_CONNECTOR_DSI;
|
||||||
|
encoder = DRM_MODE_ENCODER_DSI;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
connector = DRM_MODE_CONNECTOR_Unknown;
|
connector = DRM_MODE_CONNECTOR_Unknown;
|
||||||
encoder = DRM_MODE_ENCODER_NONE;
|
encoder = DRM_MODE_ENCODER_NONE;
|
||||||
@ -267,6 +300,9 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
|
|||||||
drm_connector_helper_add(&output->connector, &connector_helper_funcs);
|
drm_connector_helper_add(&output->connector, &connector_helper_funcs);
|
||||||
output->connector.dpms = DRM_MODE_DPMS_OFF;
|
output->connector.dpms = DRM_MODE_DPMS_OFF;
|
||||||
|
|
||||||
|
if (output->panel)
|
||||||
|
drm_panel_attach(output->panel, &output->connector);
|
||||||
|
|
||||||
drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
|
drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
|
||||||
drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
|
drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
|
||||||
|
|
||||||
|
@ -87,15 +87,60 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
|
|||||||
static int tegra_output_rgb_enable(struct tegra_output *output)
|
static int tegra_output_rgb_enable(struct tegra_output *output)
|
||||||
{
|
{
|
||||||
struct tegra_rgb *rgb = to_rgb(output);
|
struct tegra_rgb *rgb = to_rgb(output);
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
|
tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
|
||||||
|
|
||||||
|
value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
|
||||||
|
|
||||||
|
/* XXX: parameterize? */
|
||||||
|
value = tegra_dc_readl(rgb->dc, DC_COM_PIN_OUTPUT_POLARITY(1));
|
||||||
|
value &= ~LVS_OUTPUT_POLARITY_LOW;
|
||||||
|
value &= ~LHS_OUTPUT_POLARITY_LOW;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
|
||||||
|
|
||||||
|
/* XXX: parameterize? */
|
||||||
|
value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
|
||||||
|
DISP_ORDER_RED_BLUE;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
|
||||||
|
|
||||||
|
/* XXX: parameterize? */
|
||||||
|
value = SC0_H_QUALIFIER_NONE | SC1_H_QUALIFIER_NONE;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
value &= ~DISP_CTRL_MODE_MASK;
|
||||||
|
value |= DISP_CTRL_MODE_C_DISPLAY;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
||||||
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
|
tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
||||||
|
tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_output_rgb_disable(struct tegra_output *output)
|
static int tegra_output_rgb_disable(struct tegra_output *output)
|
||||||
{
|
{
|
||||||
struct tegra_rgb *rgb = to_rgb(output);
|
struct tegra_rgb *rgb = to_rgb(output);
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
|
||||||
|
PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
|
||||||
|
|
||||||
|
value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
value &= ~DISP_CTRL_MODE_MASK;
|
||||||
|
tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_COMMAND);
|
||||||
|
|
||||||
|
tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
|
||||||
|
tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
|
||||||
|
|
||||||
tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
|
tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
config TEGRA_HOST1X
|
config TEGRA_HOST1X
|
||||||
tristate "NVIDIA Tegra host1x driver"
|
tristate "NVIDIA Tegra host1x driver"
|
||||||
depends on ARCH_TEGRA || ARCH_MULTIPLATFORM
|
depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
|
||||||
help
|
help
|
||||||
Driver for the NVIDIA Tegra host1x hardware.
|
Driver for the NVIDIA Tegra host1x hardware.
|
||||||
|
|
||||||
|
@ -7,7 +7,9 @@ host1x-y = \
|
|||||||
channel.o \
|
channel.o \
|
||||||
job.o \
|
job.o \
|
||||||
debug.o \
|
debug.o \
|
||||||
|
mipi.o \
|
||||||
hw/host1x01.o \
|
hw/host1x01.o \
|
||||||
hw/host1x02.o
|
hw/host1x02.o \
|
||||||
|
hw/host1x04.o
|
||||||
|
|
||||||
obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
|
obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
|
||||||
|
@ -188,6 +188,7 @@ int host1x_device_init(struct host1x_device *device)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_device_init);
|
||||||
|
|
||||||
int host1x_device_exit(struct host1x_device *device)
|
int host1x_device_exit(struct host1x_device *device)
|
||||||
{
|
{
|
||||||
@ -213,6 +214,7 @@ int host1x_device_exit(struct host1x_device *device)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_device_exit);
|
||||||
|
|
||||||
static int host1x_register_client(struct host1x *host1x,
|
static int host1x_register_client(struct host1x *host1x,
|
||||||
struct host1x_client *client)
|
struct host1x_client *client)
|
||||||
|
@ -43,6 +43,7 @@ int host1x_job_submit(struct host1x_job *job)
|
|||||||
|
|
||||||
return host1x_hw_channel_submit(host, job);
|
return host1x_hw_channel_submit(host, job);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_job_submit);
|
||||||
|
|
||||||
struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
|
struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
|
||||||
{
|
{
|
||||||
@ -60,6 +61,7 @@ struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
|
|||||||
|
|
||||||
return err ? NULL : channel;
|
return err ? NULL : channel;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_channel_get);
|
||||||
|
|
||||||
void host1x_channel_put(struct host1x_channel *channel)
|
void host1x_channel_put(struct host1x_channel *channel)
|
||||||
{
|
{
|
||||||
@ -76,6 +78,7 @@ void host1x_channel_put(struct host1x_channel *channel)
|
|||||||
|
|
||||||
mutex_unlock(&channel->reflock);
|
mutex_unlock(&channel->reflock);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_channel_put);
|
||||||
|
|
||||||
struct host1x_channel *host1x_channel_request(struct device *dev)
|
struct host1x_channel *host1x_channel_request(struct device *dev)
|
||||||
{
|
{
|
||||||
@ -115,6 +118,7 @@ fail:
|
|||||||
mutex_unlock(&host->chlist_mutex);
|
mutex_unlock(&host->chlist_mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_channel_request);
|
||||||
|
|
||||||
void host1x_channel_free(struct host1x_channel *channel)
|
void host1x_channel_free(struct host1x_channel *channel)
|
||||||
{
|
{
|
||||||
@ -124,3 +128,4 @@ void host1x_channel_free(struct host1x_channel *channel)
|
|||||||
list_del(&channel->list);
|
list_del(&channel->list);
|
||||||
kfree(channel);
|
kfree(channel);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_channel_free);
|
||||||
|
@ -96,7 +96,6 @@ static void show_all(struct host1x *m, struct output *o)
|
|||||||
show_channels(ch, o, true);
|
show_channels(ch, o, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
|
||||||
static void show_all_no_fifo(struct host1x *host1x, struct output *o)
|
static void show_all_no_fifo(struct host1x *host1x, struct output *o)
|
||||||
{
|
{
|
||||||
struct host1x_channel *ch;
|
struct host1x_channel *ch;
|
||||||
@ -153,7 +152,7 @@ static const struct file_operations host1x_debug_fops = {
|
|||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
void host1x_debug_init(struct host1x *host1x)
|
static void host1x_debugfs_init(struct host1x *host1x)
|
||||||
{
|
{
|
||||||
struct dentry *de = debugfs_create_dir("tegra-host1x", NULL);
|
struct dentry *de = debugfs_create_dir("tegra-host1x", NULL);
|
||||||
|
|
||||||
@ -180,18 +179,22 @@ void host1x_debug_init(struct host1x *host1x)
|
|||||||
&host1x_debug_force_timeout_channel);
|
&host1x_debug_force_timeout_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void host1x_debug_deinit(struct host1x *host1x)
|
static void host1x_debugfs_exit(struct host1x *host1x)
|
||||||
{
|
{
|
||||||
debugfs_remove_recursive(host1x->debugfs);
|
debugfs_remove_recursive(host1x->debugfs);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void host1x_debug_init(struct host1x *host1x)
|
void host1x_debug_init(struct host1x *host1x)
|
||||||
{
|
{
|
||||||
|
if (IS_ENABLED(CONFIG_DEBUG_FS))
|
||||||
|
host1x_debugfs_init(host1x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void host1x_debug_deinit(struct host1x *host1x)
|
void host1x_debug_deinit(struct host1x *host1x)
|
||||||
{
|
{
|
||||||
|
if (IS_ENABLED(CONFIG_DEBUG_FS))
|
||||||
|
host1x_debugfs_exit(host1x);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void host1x_debug_dump(struct host1x *host1x)
|
void host1x_debug_dump(struct host1x *host1x)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "hw/host1x01.h"
|
#include "hw/host1x01.h"
|
||||||
#include "hw/host1x02.h"
|
#include "hw/host1x02.h"
|
||||||
|
#include "hw/host1x04.h"
|
||||||
|
|
||||||
void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
|
void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
|
||||||
{
|
{
|
||||||
@ -77,7 +78,17 @@ static const struct host1x_info host1x02_info = {
|
|||||||
.sync_offset = 0x3000,
|
.sync_offset = 0x3000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct host1x_info host1x04_info = {
|
||||||
|
.nb_channels = 12,
|
||||||
|
.nb_pts = 192,
|
||||||
|
.nb_mlocks = 16,
|
||||||
|
.nb_bases = 64,
|
||||||
|
.init = host1x04_init,
|
||||||
|
.sync_offset = 0x2100,
|
||||||
|
};
|
||||||
|
|
||||||
static struct of_device_id host1x_of_match[] = {
|
static struct of_device_id host1x_of_match[] = {
|
||||||
|
{ .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, },
|
||||||
{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
|
{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
|
||||||
{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
|
{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
|
||||||
{ .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
|
{ .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
|
||||||
@ -210,17 +221,26 @@ static int __init tegra_host1x_init(void)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = platform_driver_register(&tegra_host1x_driver);
|
err = platform_driver_register(&tegra_host1x_driver);
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
host1x_bus_exit();
|
goto unregister_bus;
|
||||||
return err;
|
|
||||||
}
|
err = platform_driver_register(&tegra_mipi_driver);
|
||||||
|
if (err < 0)
|
||||||
|
goto unregister_host1x;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
unregister_host1x:
|
||||||
|
platform_driver_unregister(&tegra_host1x_driver);
|
||||||
|
unregister_bus:
|
||||||
|
host1x_bus_exit();
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
module_init(tegra_host1x_init);
|
module_init(tegra_host1x_init);
|
||||||
|
|
||||||
static void __exit tegra_host1x_exit(void)
|
static void __exit tegra_host1x_exit(void)
|
||||||
{
|
{
|
||||||
|
platform_driver_unregister(&tegra_mipi_driver);
|
||||||
platform_driver_unregister(&tegra_host1x_driver);
|
platform_driver_unregister(&tegra_host1x_driver);
|
||||||
host1x_bus_exit();
|
host1x_bus_exit();
|
||||||
}
|
}
|
||||||
|
@ -306,4 +306,6 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o)
|
|||||||
host->debug_op->show_mlocks(host, o);
|
host->debug_op->show_mlocks(host, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern struct platform_driver tegra_mipi_driver;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* include hw specification */
|
/* include hw specification */
|
||||||
#include "host1x01.h"
|
#include "host1x02.h"
|
||||||
#include "host1x01_hardware.h"
|
#include "host1x02_hardware.h"
|
||||||
|
|
||||||
/* include code */
|
/* include code */
|
||||||
#include "cdma_hw.c"
|
#include "cdma_hw.c"
|
||||||
|
142
drivers/gpu/host1x/hw/host1x02_hardware.h
Normal file
142
drivers/gpu/host1x/hw/host1x02_hardware.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Tegra host1x Register Offsets for Tegra114
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 NVIDIA Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HOST1X_HOST1X02_HARDWARE_H
|
||||||
|
#define __HOST1X_HOST1X02_HARDWARE_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
|
#include "hw_host1x02_channel.h"
|
||||||
|
#include "hw_host1x02_sync.h"
|
||||||
|
#include "hw_host1x02_uclass.h"
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_wait_syncpt(
|
||||||
|
unsigned indx, unsigned threshold)
|
||||||
|
{
|
||||||
|
return host1x_uclass_wait_syncpt_indx_f(indx)
|
||||||
|
| host1x_uclass_wait_syncpt_thresh_f(threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_load_syncpt_base(
|
||||||
|
unsigned indx, unsigned threshold)
|
||||||
|
{
|
||||||
|
return host1x_uclass_load_syncpt_base_base_indx_f(indx)
|
||||||
|
| host1x_uclass_load_syncpt_base_value_f(threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_wait_syncpt_base(
|
||||||
|
unsigned indx, unsigned base_indx, unsigned offset)
|
||||||
|
{
|
||||||
|
return host1x_uclass_wait_syncpt_base_indx_f(indx)
|
||||||
|
| host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
|
||||||
|
| host1x_uclass_wait_syncpt_base_offset_f(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_incr_syncpt_base(
|
||||||
|
unsigned base_indx, unsigned offset)
|
||||||
|
{
|
||||||
|
return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
|
||||||
|
| host1x_uclass_incr_syncpt_base_offset_f(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_incr_syncpt(
|
||||||
|
unsigned cond, unsigned indx)
|
||||||
|
{
|
||||||
|
return host1x_uclass_incr_syncpt_cond_f(cond)
|
||||||
|
| host1x_uclass_incr_syncpt_indx_f(indx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_indoff_reg_write(
|
||||||
|
unsigned mod_id, unsigned offset, bool auto_inc)
|
||||||
|
{
|
||||||
|
u32 v = host1x_uclass_indoff_indbe_f(0xf)
|
||||||
|
| host1x_uclass_indoff_indmodid_f(mod_id)
|
||||||
|
| host1x_uclass_indoff_indroffset_f(offset);
|
||||||
|
if (auto_inc)
|
||||||
|
v |= host1x_uclass_indoff_autoinc_f(1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_indoff_reg_read(
|
||||||
|
unsigned mod_id, unsigned offset, bool auto_inc)
|
||||||
|
{
|
||||||
|
u32 v = host1x_uclass_indoff_indmodid_f(mod_id)
|
||||||
|
| host1x_uclass_indoff_indroffset_f(offset)
|
||||||
|
| host1x_uclass_indoff_rwn_read_v();
|
||||||
|
if (auto_inc)
|
||||||
|
v |= host1x_uclass_indoff_autoinc_f(1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cdma opcodes */
|
||||||
|
static inline u32 host1x_opcode_setclass(
|
||||||
|
unsigned class_id, unsigned offset, unsigned mask)
|
||||||
|
{
|
||||||
|
return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (1 << 28) | (offset << 16) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (2 << 28) | (offset << 16) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
|
||||||
|
{
|
||||||
|
return (3 << 28) | (offset << 16) | mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
|
||||||
|
{
|
||||||
|
return (4 << 28) | (offset << 16) | value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
|
||||||
|
{
|
||||||
|
return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
|
||||||
|
host1x_class_host_incr_syncpt(cond, indx));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_restart(unsigned address)
|
||||||
|
{
|
||||||
|
return (5 << 28) | (address >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_gather(unsigned count)
|
||||||
|
{
|
||||||
|
return (6 << 28) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_gather_nonincr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (6 << 28) | (offset << 16) | BIT(15) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
|
||||||
|
|
||||||
|
#endif
|
42
drivers/gpu/host1x/hw/host1x04.c
Normal file
42
drivers/gpu/host1x/hw/host1x04.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Host1x init for Tegra124 SoCs
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 NVIDIA Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* include hw specification */
|
||||||
|
#include "host1x04.h"
|
||||||
|
#include "host1x04_hardware.h"
|
||||||
|
|
||||||
|
/* include code */
|
||||||
|
#include "cdma_hw.c"
|
||||||
|
#include "channel_hw.c"
|
||||||
|
#include "debug_hw.c"
|
||||||
|
#include "intr_hw.c"
|
||||||
|
#include "syncpt_hw.c"
|
||||||
|
|
||||||
|
#include "../dev.h"
|
||||||
|
|
||||||
|
int host1x04_init(struct host1x *host)
|
||||||
|
{
|
||||||
|
host->channel_op = &host1x_channel_ops;
|
||||||
|
host->cdma_op = &host1x_cdma_ops;
|
||||||
|
host->cdma_pb_op = &host1x_pushbuffer_ops;
|
||||||
|
host->syncpt_op = &host1x_syncpt_ops;
|
||||||
|
host->intr_op = &host1x_intr_ops;
|
||||||
|
host->debug_op = &host1x_debug_ops;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
26
drivers/gpu/host1x/hw/host1x04.h
Normal file
26
drivers/gpu/host1x/hw/host1x04.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Host1x init for Tegra124 SoCs
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 NVIDIA Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HOST1X_HOST1X04_H
|
||||||
|
#define HOST1X_HOST1X04_H
|
||||||
|
|
||||||
|
struct host1x;
|
||||||
|
|
||||||
|
int host1x04_init(struct host1x *host);
|
||||||
|
|
||||||
|
#endif
|
142
drivers/gpu/host1x/hw/host1x04_hardware.h
Normal file
142
drivers/gpu/host1x/hw/host1x04_hardware.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Tegra host1x Register Offsets for Tegra124
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 NVIDIA Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HOST1X_HOST1X04_HARDWARE_H
|
||||||
|
#define __HOST1X_HOST1X04_HARDWARE_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
|
#include "hw_host1x04_channel.h"
|
||||||
|
#include "hw_host1x04_sync.h"
|
||||||
|
#include "hw_host1x04_uclass.h"
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_wait_syncpt(
|
||||||
|
unsigned indx, unsigned threshold)
|
||||||
|
{
|
||||||
|
return host1x_uclass_wait_syncpt_indx_f(indx)
|
||||||
|
| host1x_uclass_wait_syncpt_thresh_f(threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_load_syncpt_base(
|
||||||
|
unsigned indx, unsigned threshold)
|
||||||
|
{
|
||||||
|
return host1x_uclass_load_syncpt_base_base_indx_f(indx)
|
||||||
|
| host1x_uclass_load_syncpt_base_value_f(threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_wait_syncpt_base(
|
||||||
|
unsigned indx, unsigned base_indx, unsigned offset)
|
||||||
|
{
|
||||||
|
return host1x_uclass_wait_syncpt_base_indx_f(indx)
|
||||||
|
| host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
|
||||||
|
| host1x_uclass_wait_syncpt_base_offset_f(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_incr_syncpt_base(
|
||||||
|
unsigned base_indx, unsigned offset)
|
||||||
|
{
|
||||||
|
return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
|
||||||
|
| host1x_uclass_incr_syncpt_base_offset_f(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_incr_syncpt(
|
||||||
|
unsigned cond, unsigned indx)
|
||||||
|
{
|
||||||
|
return host1x_uclass_incr_syncpt_cond_f(cond)
|
||||||
|
| host1x_uclass_incr_syncpt_indx_f(indx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_indoff_reg_write(
|
||||||
|
unsigned mod_id, unsigned offset, bool auto_inc)
|
||||||
|
{
|
||||||
|
u32 v = host1x_uclass_indoff_indbe_f(0xf)
|
||||||
|
| host1x_uclass_indoff_indmodid_f(mod_id)
|
||||||
|
| host1x_uclass_indoff_indroffset_f(offset);
|
||||||
|
if (auto_inc)
|
||||||
|
v |= host1x_uclass_indoff_autoinc_f(1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_class_host_indoff_reg_read(
|
||||||
|
unsigned mod_id, unsigned offset, bool auto_inc)
|
||||||
|
{
|
||||||
|
u32 v = host1x_uclass_indoff_indmodid_f(mod_id)
|
||||||
|
| host1x_uclass_indoff_indroffset_f(offset)
|
||||||
|
| host1x_uclass_indoff_rwn_read_v();
|
||||||
|
if (auto_inc)
|
||||||
|
v |= host1x_uclass_indoff_autoinc_f(1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cdma opcodes */
|
||||||
|
static inline u32 host1x_opcode_setclass(
|
||||||
|
unsigned class_id, unsigned offset, unsigned mask)
|
||||||
|
{
|
||||||
|
return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (1 << 28) | (offset << 16) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (2 << 28) | (offset << 16) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
|
||||||
|
{
|
||||||
|
return (3 << 28) | (offset << 16) | mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
|
||||||
|
{
|
||||||
|
return (4 << 28) | (offset << 16) | value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
|
||||||
|
{
|
||||||
|
return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
|
||||||
|
host1x_class_host_incr_syncpt(cond, indx));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_restart(unsigned address)
|
||||||
|
{
|
||||||
|
return (5 << 28) | (address >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_gather(unsigned count)
|
||||||
|
{
|
||||||
|
return (6 << 28) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_gather_nonincr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (6 << 28) | (offset << 16) | BIT(15) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
|
||||||
|
{
|
||||||
|
return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
|
||||||
|
|
||||||
|
#endif
|
@ -111,6 +111,12 @@ static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
|
|||||||
}
|
}
|
||||||
#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
|
#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
|
||||||
host1x_uclass_wait_syncpt_base_offset_f(v)
|
host1x_uclass_wait_syncpt_base_offset_f(v)
|
||||||
|
static inline u32 host1x_uclass_load_syncpt_base_r(void)
|
||||||
|
{
|
||||||
|
return 0xb;
|
||||||
|
}
|
||||||
|
#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
|
||||||
|
host1x_uclass_load_syncpt_base_r()
|
||||||
static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
|
static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
|
||||||
{
|
{
|
||||||
return (v & 0xff) << 24;
|
return (v & 0xff) << 24;
|
||||||
|
121
drivers/gpu/host1x/hw/hw_host1x04_channel.h
Normal file
121
drivers/gpu/host1x/hw/hw_host1x04_channel.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 NVIDIA Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function naming determines intended use:
|
||||||
|
*
|
||||||
|
* <x>_r(void) : Returns the offset for register <x>.
|
||||||
|
*
|
||||||
|
* <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
|
||||||
|
*
|
||||||
|
* <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
|
||||||
|
*
|
||||||
|
* <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
|
||||||
|
* and masked to place it at field <y> of register <x>. This value
|
||||||
|
* can be |'d with others to produce a full register value for
|
||||||
|
* register <x>.
|
||||||
|
*
|
||||||
|
* <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
|
||||||
|
* value can be ~'d and then &'d to clear the value of field <y> for
|
||||||
|
* register <x>.
|
||||||
|
*
|
||||||
|
* <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
|
||||||
|
* to place it at field <y> of register <x>. This value can be |'d
|
||||||
|
* with others to produce a full register value for <x>.
|
||||||
|
*
|
||||||
|
* <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
|
||||||
|
* <x> value 'r' after being shifted to place its LSB at bit 0.
|
||||||
|
* This value is suitable for direct comparison with other unshifted
|
||||||
|
* values appropriate for use in field <y> of register <x>.
|
||||||
|
*
|
||||||
|
* <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
|
||||||
|
* field <y> of register <x>. This value is suitable for direct
|
||||||
|
* comparison with unshifted values appropriate for use in field <y>
|
||||||
|
* of register <x>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HOST1X_HW_HOST1X04_CHANNEL_H
|
||||||
|
#define HOST1X_HW_HOST1X04_CHANNEL_H
|
||||||
|
|
||||||
|
static inline u32 host1x_channel_fifostat_r(void)
|
||||||
|
{
|
||||||
|
return 0x0;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_FIFOSTAT \
|
||||||
|
host1x_channel_fifostat_r()
|
||||||
|
static inline u32 host1x_channel_fifostat_cfempty_v(u32 r)
|
||||||
|
{
|
||||||
|
return (r >> 11) & 0x1;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(r) \
|
||||||
|
host1x_channel_fifostat_cfempty_v(r)
|
||||||
|
static inline u32 host1x_channel_dmastart_r(void)
|
||||||
|
{
|
||||||
|
return 0x14;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMASTART \
|
||||||
|
host1x_channel_dmastart_r()
|
||||||
|
static inline u32 host1x_channel_dmaput_r(void)
|
||||||
|
{
|
||||||
|
return 0x18;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMAPUT \
|
||||||
|
host1x_channel_dmaput_r()
|
||||||
|
static inline u32 host1x_channel_dmaget_r(void)
|
||||||
|
{
|
||||||
|
return 0x1c;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMAGET \
|
||||||
|
host1x_channel_dmaget_r()
|
||||||
|
static inline u32 host1x_channel_dmaend_r(void)
|
||||||
|
{
|
||||||
|
return 0x20;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMAEND \
|
||||||
|
host1x_channel_dmaend_r()
|
||||||
|
static inline u32 host1x_channel_dmactrl_r(void)
|
||||||
|
{
|
||||||
|
return 0x24;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMACTRL \
|
||||||
|
host1x_channel_dmactrl_r()
|
||||||
|
static inline u32 host1x_channel_dmactrl_dmastop(void)
|
||||||
|
{
|
||||||
|
return 1 << 0;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMACTRL_DMASTOP \
|
||||||
|
host1x_channel_dmactrl_dmastop()
|
||||||
|
static inline u32 host1x_channel_dmactrl_dmastop_v(u32 r)
|
||||||
|
{
|
||||||
|
return (r >> 0) & 0x1;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMACTRL_DMASTOP_V(r) \
|
||||||
|
host1x_channel_dmactrl_dmastop_v(r)
|
||||||
|
static inline u32 host1x_channel_dmactrl_dmagetrst(void)
|
||||||
|
{
|
||||||
|
return 1 << 1;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMACTRL_DMAGETRST \
|
||||||
|
host1x_channel_dmactrl_dmagetrst()
|
||||||
|
static inline u32 host1x_channel_dmactrl_dmainitget(void)
|
||||||
|
{
|
||||||
|
return 1 << 2;
|
||||||
|
}
|
||||||
|
#define HOST1X_CHANNEL_DMACTRL_DMAINITGET \
|
||||||
|
host1x_channel_dmactrl_dmainitget()
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user