Merge branch 'for-next/tegra'
This commit is contained in:
commit
7b4cc54579
|
@ -198,6 +198,7 @@ config ARCH_TEGRA
|
|||
bool "NVIDIA Tegra"
|
||||
select CPU_V7
|
||||
select HAS_DEBUG_LL
|
||||
select HW_HAS_PCI
|
||||
select COMMON_CLK
|
||||
select COMMON_CLK_OF_PROVIDER
|
||||
select CLKDEV_LOOKUP
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <gpio.h>
|
||||
#include <i2c/i2c.h>
|
||||
#include <init.h>
|
||||
|
||||
static int nvidia_beaver_devices_init(void)
|
||||
static int nvidia_beaver_fs_init(void)
|
||||
{
|
||||
struct i2c_client client;
|
||||
u8 data;
|
||||
|
@ -33,6 +35,24 @@ static int nvidia_beaver_devices_init(void)
|
|||
data = 0x65;
|
||||
i2c_write_reg(&client, 0x32, &data, 1);
|
||||
|
||||
/* TPS659110: LDO1_REG = 1.05v, ACTIVE to PEX */
|
||||
data = 0x15;
|
||||
i2c_write_reg(&client, 0x30, &data, 1);
|
||||
|
||||
/* enable SYS_3V3_PEXS */
|
||||
gpio_direction_output(TEGRA_GPIO(L, 7), 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(nvidia_beaver_devices_init);
|
||||
fs_initcall(nvidia_beaver_fs_init);
|
||||
|
||||
static int nvidia_beaver_device_init(void)
|
||||
{
|
||||
if (!of_machine_is_compatible("nvidia,beaver"))
|
||||
return 0;
|
||||
|
||||
barebox_set_hostname("beaver");
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(nvidia_beaver_device_init);
|
||||
|
|
|
@ -3,5 +3,5 @@ CFLAGS_pbl-entry.o := \
|
|||
-fno-tree-switch-conversion -fno-jump-tables
|
||||
soc := tegra124
|
||||
lwl-y += entry.o
|
||||
#obj-y += board.o
|
||||
obj-y += board.o
|
||||
extra-y += jetson-tk1-2gb-emmc.bct
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Lucas Stach <l.stach@pengutronix.de>
|
||||
*
|
||||
* 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 <common.h>
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <gpio.h>
|
||||
#include <i2c/i2c.h>
|
||||
#include <init.h>
|
||||
|
||||
#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
|
||||
#define AS3722_GPIO_CONTROL(n) (0x08 + (n))
|
||||
#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0)
|
||||
#define AS3722_GPIO_SIGNAL_OUT 0x20
|
||||
#define AS3722_SD_CONTROL 0x4d
|
||||
|
||||
static int nvidia_jetson_tk1_fs_init(void)
|
||||
{
|
||||
struct i2c_client client;
|
||||
u8 data;
|
||||
|
||||
if (!of_machine_is_compatible("nvidia,jetson-tk1"))
|
||||
return 0;
|
||||
|
||||
client.adapter = i2c_get_adapter(4);
|
||||
client.addr = 0x40;
|
||||
|
||||
/* AS3722: enable SD4 and set voltage to 1.05v */
|
||||
i2c_read_reg(&client, AS3722_SD_CONTROL, &data, 1);
|
||||
data |= 1 << 4;
|
||||
i2c_write_reg(&client, AS3722_SD_CONTROL, &data, 1);
|
||||
|
||||
data = 0x24;
|
||||
i2c_write_reg(&client, AS3722_SD_VOLTAGE(4), &data, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
fs_initcall(nvidia_jetson_tk1_fs_init);
|
||||
|
||||
static int nvidia_jetson_tk1_device_init(void)
|
||||
{
|
||||
if (!of_machine_is_compatible("nvidia,jetson-tk1"))
|
||||
return 0;
|
||||
|
||||
barebox_set_hostname("jetson-tk1");
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(nvidia_jetson_tk1_device_init);
|
|
@ -3,6 +3,7 @@ CFLAGS_pbl-entry.o := \
|
|||
-fno-tree-switch-conversion -fno-jump-tables
|
||||
soc := tegra20
|
||||
lwl-y += entry.o
|
||||
obj-y += board.o
|
||||
extra-y += colibri-t20_256_hsmmc.bct colibri-t20_256_v11_nand.bct \
|
||||
colibri-t20_256_v12_nand.bct colibri-t20_512_hsmmc.bct \
|
||||
colibri-t20_512_v11_nand.bct colibri-t20_512_v12_nand.bct
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Lucas Stach <l.stach@pengutronix.de>
|
||||
*
|
||||
* 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 <common.h>
|
||||
#include <init.h>
|
||||
|
||||
static int toradex_colibri_t20_device_init(void)
|
||||
{
|
||||
if (!of_machine_is_compatible("toradex,colibri_t20-512"))
|
||||
return 0;
|
||||
|
||||
barebox_set_hostname("colibri-t20");
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(toradex_colibri_t20_device_init);
|
|
@ -16,6 +16,7 @@ CONFIG_AUTO_COMPLETE=y
|
|||
CONFIG_MENU=y
|
||||
CONFIG_BLSPEC=y
|
||||
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
|
||||
CONFIG_RESET_SOURCE=y
|
||||
CONFIG_LONGHELP=y
|
||||
CONFIG_CMD_IOMEM=y
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
|
@ -27,16 +28,25 @@ CONFIG_CMD_RESET=y
|
|||
CONFIG_CMD_EXPORT=y
|
||||
CONFIG_CMD_LOADENV=y
|
||||
CONFIG_CMD_SAVEENV=y
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_MIITOOL=y
|
||||
CONFIG_CMD_PING=y
|
||||
CONFIG_CMD_EDIT=y
|
||||
CONFIG_CMD_TIMEOUT=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DETECT=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_OFTREE=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_OF_BAREBOX_DRIVERS=y
|
||||
CONFIG_DRIVER_SERIAL_NS16550=y
|
||||
CONFIG_DRIVER_NET_RTL8169=y
|
||||
CONFIG_MCI=y
|
||||
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
|
||||
CONFIG_MCI_TEGRA=y
|
||||
CONFIG_PCI_TEGRA=y
|
||||
CONFIG_FS_EXT4=y
|
||||
CONFIG_FS_TFTP=y
|
||||
CONFIG_FS_NFS=y
|
||||
CONFIG_FS_FAT=y
|
||||
CONFIG_FS_FAT_LFN=y
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1 +1,8 @@
|
|||
#include <arm/tegra124.dtsi>
|
||||
/ {
|
||||
aliases {
|
||||
serial0 = "/serial@0,70006000/";
|
||||
serial1 = "/serial@0,70006040/";
|
||||
serial2 = "/serial@0,70006200/";
|
||||
serial3 = "/serial@0,70006300/";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
model = "Toradex Colibri T20 on Iris";
|
||||
compatible = "toradex,iris", "toradex,colibri_t20", "nvidia,tegra20";
|
||||
|
||||
chosen {
|
||||
stdout-path = &uarta;
|
||||
};
|
||||
|
||||
host1x@50000000 {
|
||||
hdmi@54280000 {
|
||||
status = "okay";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "tegra30.dtsi"
|
||||
#include <arm/tegra30.dtsi>
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Tegra30 Beaver evaluation board";
|
||||
|
@ -11,6 +11,15 @@
|
|||
rtc1 = "/rtc@7000e000";
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = &uarta;
|
||||
|
||||
environment@0 {
|
||||
compatible = "barebox,environment";
|
||||
device-path = &emmc, "partname:boot1";
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
reg = <0x80000000 0x7ff00000>;
|
||||
};
|
||||
|
@ -750,7 +759,7 @@
|
|||
bus-width = <4>;
|
||||
};
|
||||
|
||||
sdhci@78000600 {
|
||||
emmc: sdhci@78000600 {
|
||||
status = "okay";
|
||||
bus-width = <8>;
|
||||
non-removable;
|
||||
|
|
|
@ -1,892 +0,0 @@
|
|||
#include <dt-bindings/clock/tegra30-car.h>
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra30";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
serial0 = &uarta;
|
||||
serial1 = &uartb;
|
||||
serial2 = &uartc;
|
||||
serial3 = &uartd;
|
||||
serial4 = &uarte;
|
||||
};
|
||||
|
||||
pcie-controller@00003000 {
|
||||
compatible = "nvidia,tegra30-pcie";
|
||||
device_type = "pci";
|
||||
reg = <0x00003000 0x00000800 /* PADS registers */
|
||||
0x00003800 0x00000200 /* AFI registers */
|
||||
0x10000000 0x10000000>; /* configuration space */
|
||||
reg-names = "pads", "afi", "cs";
|
||||
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH /* controller interrupt */
|
||||
GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
|
||||
interrupt-names = "intr", "msi";
|
||||
|
||||
bus-range = <0x00 0xff>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
ranges = <0x82000000 0 0x00000000 0x00000000 0 0x00001000 /* port 0 configuration space */
|
||||
0x82000000 0 0x00001000 0x00001000 0 0x00001000 /* port 1 configuration space */
|
||||
0x82000000 0 0x00004000 0x00004000 0 0x00001000 /* port 2 configuration space */
|
||||
0x81000000 0 0 0x02000000 0 0x00010000 /* downstream I/O */
|
||||
0x82000000 0 0x20000000 0x20000000 0 0x08000000 /* non-prefetchable memory */
|
||||
0xc2000000 0 0x28000000 0x28000000 0 0x18000000>; /* prefetchable memory */
|
||||
|
||||
clocks = <&tegra_car TEGRA30_CLK_PCIE>,
|
||||
<&tegra_car TEGRA30_CLK_AFI>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_E>,
|
||||
<&tegra_car TEGRA30_CLK_CML0>;
|
||||
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";
|
||||
|
||||
pci@1,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82000800 0 0x00000000 0 0x1000>;
|
||||
reg = <0x000800 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
|
||||
pci@2,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82001000 0 0x00001000 0 0x1000>;
|
||||
reg = <0x001000 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
|
||||
pci@3,0 {
|
||||
device_type = "pci";
|
||||
assigned-addresses = <0x82001800 0 0x00004000 0 0x1000>;
|
||||
reg = <0x001800 0 0 0 0>;
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
nvidia,num-lanes = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
host1x@50000000 {
|
||||
compatible = "nvidia,tegra30-host1x", "simple-bus";
|
||||
reg = <0x50000000 0x00024000>;
|
||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
|
||||
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; /* general */
|
||||
clocks = <&tegra_car TEGRA30_CLK_HOST1X>;
|
||||
resets = <&tegra_car 28>;
|
||||
reset-names = "host1x";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
ranges = <0x54000000 0x54000000 0x04000000>;
|
||||
|
||||
mpe@54040000 {
|
||||
compatible = "nvidia,tegra30-mpe";
|
||||
reg = <0x54040000 0x00040000>;
|
||||
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_MPE>;
|
||||
resets = <&tegra_car 60>;
|
||||
reset-names = "mpe";
|
||||
};
|
||||
|
||||
vi@54080000 {
|
||||
compatible = "nvidia,tegra30-vi";
|
||||
reg = <0x54080000 0x00040000>;
|
||||
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_VI>;
|
||||
resets = <&tegra_car 20>;
|
||||
reset-names = "vi";
|
||||
};
|
||||
|
||||
epp@540c0000 {
|
||||
compatible = "nvidia,tegra30-epp";
|
||||
reg = <0x540c0000 0x00040000>;
|
||||
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_EPP>;
|
||||
resets = <&tegra_car 19>;
|
||||
reset-names = "epp";
|
||||
};
|
||||
|
||||
isp@54100000 {
|
||||
compatible = "nvidia,tegra30-isp";
|
||||
reg = <0x54100000 0x00040000>;
|
||||
interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_ISP>;
|
||||
resets = <&tegra_car 23>;
|
||||
reset-names = "isp";
|
||||
};
|
||||
|
||||
gr2d@54140000 {
|
||||
compatible = "nvidia,tegra30-gr2d";
|
||||
reg = <0x54140000 0x00040000>;
|
||||
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
||||
resets = <&tegra_car 21>;
|
||||
reset-names = "2d";
|
||||
clocks = <&tegra_car TEGRA30_CLK_GR2D>;
|
||||
};
|
||||
|
||||
gr3d@54180000 {
|
||||
compatible = "nvidia,tegra30-gr3d";
|
||||
reg = <0x54180000 0x00040000>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_GR3D
|
||||
&tegra_car TEGRA30_CLK_GR3D2>;
|
||||
clock-names = "3d", "3d2";
|
||||
resets = <&tegra_car 24>,
|
||||
<&tegra_car 98>;
|
||||
reset-names = "3d", "3d2";
|
||||
};
|
||||
|
||||
dc@54200000 {
|
||||
compatible = "nvidia,tegra30-dc", "nvidia,tegra20-dc";
|
||||
reg = <0x54200000 0x00040000>;
|
||||
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_DISP1>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P>;
|
||||
clock-names = "dc", "parent";
|
||||
resets = <&tegra_car 27>;
|
||||
reset-names = "dc";
|
||||
|
||||
nvidia,head = <0>;
|
||||
|
||||
rgb {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
dc@54240000 {
|
||||
compatible = "nvidia,tegra30-dc";
|
||||
reg = <0x54240000 0x00040000>;
|
||||
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_DISP2>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P>;
|
||||
clock-names = "dc", "parent";
|
||||
resets = <&tegra_car 26>;
|
||||
reset-names = "dc";
|
||||
|
||||
nvidia,head = <1>;
|
||||
|
||||
rgb {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
hdmi@54280000 {
|
||||
compatible = "nvidia,tegra30-hdmi";
|
||||
reg = <0x54280000 0x00040000>;
|
||||
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_HDMI>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_D2_OUT0>;
|
||||
clock-names = "hdmi", "parent";
|
||||
resets = <&tegra_car 51>;
|
||||
reset-names = "hdmi";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tvo@542c0000 {
|
||||
compatible = "nvidia,tegra30-tvo";
|
||||
reg = <0x542c0000 0x00040000>;
|
||||
interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_TVO>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dsi@54300000 {
|
||||
compatible = "nvidia,tegra30-dsi";
|
||||
reg = <0x54300000 0x00040000>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_DSIA>;
|
||||
resets = <&tegra_car 48>;
|
||||
reset-names = "dsi";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
timer@50004600 {
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0x50040600 0x20>;
|
||||
interrupts = <GIC_PPI 13
|
||||
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_TWD>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@50041000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
reg = <0x50041000 0x1000
|
||||
0x50040100 0x0100>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
};
|
||||
|
||||
cache-controller@50043000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0x50043000 0x1000>;
|
||||
arm,data-latency = <6 6 2>;
|
||||
arm,tag-latency = <5 5 2>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
};
|
||||
|
||||
timer@60005000 {
|
||||
compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
|
||||
reg = <0x60005000 0x400>;
|
||||
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_TIMER>;
|
||||
};
|
||||
|
||||
tegra_car: clock@60006000 {
|
||||
compatible = "nvidia,tegra30-car";
|
||||
reg = <0x60006000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
apbdma: dma@6000a000 {
|
||||
compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
|
||||
reg = <0x6000a000 0x1400>;
|
||||
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_APBDMA>;
|
||||
resets = <&tegra_car 34>;
|
||||
reset-names = "dma";
|
||||
#dma-cells = <1>;
|
||||
};
|
||||
|
||||
ahb: ahb@6000c004 {
|
||||
compatible = "nvidia,tegra30-ahb";
|
||||
reg = <0x6000c004 0x14c>; /* AHB Arbitration + Gizmo Controller */
|
||||
};
|
||||
|
||||
gpio: gpio@6000d000 {
|
||||
compatible = "nvidia,tegra30-gpio";
|
||||
reg = <0x6000d000 0x1000>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
pinmux: pinmux@70000868 {
|
||||
compatible = "nvidia,tegra30-pinmux";
|
||||
reg = <0x70000868 0xd4 /* Pad control registers */
|
||||
0x70003000 0x3e4>; /* Mux registers */
|
||||
};
|
||||
|
||||
/*
|
||||
* There are two serial driver i.e. 8250 based simple serial
|
||||
* driver and APB DMA based serial driver for higher baudrate
|
||||
* and performace. To enable the 8250 based driver, the compatible
|
||||
* is "nvidia,tegra30-uart", "nvidia,tegra20-uart" and to enable
|
||||
* the APB DMA based serial driver, the comptible is
|
||||
* "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart".
|
||||
*/
|
||||
uarta: serial@70006000 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006000 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_UARTA>;
|
||||
resets = <&tegra_car 6>;
|
||||
reset-names = "serial";
|
||||
dmas = <&apbdma 8>, <&apbdma 8>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uartb: serial@70006040 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006040 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_UARTB>;
|
||||
resets = <&tegra_car 7>;
|
||||
reset-names = "serial";
|
||||
dmas = <&apbdma 9>, <&apbdma 9>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uartc: serial@70006200 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006200 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_UARTC>;
|
||||
resets = <&tegra_car 55>;
|
||||
reset-names = "serial";
|
||||
dmas = <&apbdma 10>, <&apbdma 10>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uartd: serial@70006300 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006300 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_UARTD>;
|
||||
resets = <&tegra_car 65>;
|
||||
reset-names = "serial";
|
||||
dmas = <&apbdma 19>, <&apbdma 19>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uarte: serial@70006400 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006400 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_UARTE>;
|
||||
resets = <&tegra_car 66>;
|
||||
reset-names = "serial";
|
||||
dmas = <&apbdma 20>, <&apbdma 20>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pwm: pwm@7000a000 {
|
||||
compatible = "nvidia,tegra30-pwm", "nvidia,tegra20-pwm";
|
||||
reg = <0x7000a000 0x100>;
|
||||
#pwm-cells = <2>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_PWM>;
|
||||
resets = <&tegra_car 17>;
|
||||
reset-names = "pwm";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
rtc@7000e000 {
|
||||
compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
|
||||
reg = <0x7000e000 0x100>;
|
||||
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_RTC>;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000c000 0x100>;
|
||||
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2C1>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||
clock-names = "div-clk", "fast-clk";
|
||||
resets = <&tegra_car 12>;
|
||||
reset-names = "i2c";
|
||||
dmas = <&apbdma 21>, <&apbdma 21>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000c400 0x100>;
|
||||
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2C2>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||
clock-names = "div-clk", "fast-clk";
|
||||
resets = <&tegra_car 54>;
|
||||
reset-names = "i2c";
|
||||
dmas = <&apbdma 22>, <&apbdma 22>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000c500 0x100>;
|
||||
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2C3>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||
clock-names = "div-clk", "fast-clk";
|
||||
resets = <&tegra_car 67>;
|
||||
reset-names = "i2c";
|
||||
dmas = <&apbdma 23>, <&apbdma 23>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@7000c700 {
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000c700 0x100>;
|
||||
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2C4>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||
resets = <&tegra_car 103>;
|
||||
reset-names = "i2c";
|
||||
clock-names = "div-clk", "fast-clk";
|
||||
dmas = <&apbdma 26>, <&apbdma 26>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000d000 0x100>;
|
||||
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2C5>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_P_OUT3>;
|
||||
clock-names = "div-clk", "fast-clk";
|
||||
resets = <&tegra_car 47>;
|
||||
reset-names = "i2c";
|
||||
dmas = <&apbdma 24>, <&apbdma 24>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@7000d400 {
|
||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||
reg = <0x7000d400 0x200>;
|
||||
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SBC1>;
|
||||
resets = <&tegra_car 41>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 15>, <&apbdma 15>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@7000d600 {
|
||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||
reg = <0x7000d600 0x200>;
|
||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SBC2>;
|
||||
resets = <&tegra_car 44>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 16>, <&apbdma 16>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@7000d800 {
|
||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||
reg = <0x7000d800 0x200>;
|
||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SBC3>;
|
||||
resets = <&tegra_car 46>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 17>, <&apbdma 17>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@7000da00 {
|
||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||
reg = <0x7000da00 0x200>;
|
||||
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SBC4>;
|
||||
resets = <&tegra_car 68>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 18>, <&apbdma 18>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@7000dc00 {
|
||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||
reg = <0x7000dc00 0x200>;
|
||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SBC5>;
|
||||
resets = <&tegra_car 104>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 27>, <&apbdma 27>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi@7000de00 {
|
||||
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
|
||||
reg = <0x7000de00 0x200>;
|
||||
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SBC6>;
|
||||
resets = <&tegra_car 106>;
|
||||
reset-names = "spi";
|
||||
dmas = <&apbdma 28>, <&apbdma 28>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
kbc@7000e200 {
|
||||
compatible = "nvidia,tegra30-kbc", "nvidia,tegra20-kbc";
|
||||
reg = <0x7000e200 0x100>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_KBC>;
|
||||
resets = <&tegra_car 36>;
|
||||
reset-names = "kbc";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pmc@7000e400 {
|
||||
compatible = "nvidia,tegra30-pmc";
|
||||
reg = <0x7000e400 0x400>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_PCLK>, <&clk32k_in>;
|
||||
clock-names = "pclk", "clk32k_in";
|
||||
};
|
||||
|
||||
memory-controller@7000f000 {
|
||||
compatible = "nvidia,tegra30-mc";
|
||||
reg = <0x7000f000 0x010
|
||||
0x7000f03c 0x1b4
|
||||
0x7000f200 0x028
|
||||
0x7000f284 0x17c>;
|
||||
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
iommu@7000f010 {
|
||||
compatible = "nvidia,tegra30-smmu";
|
||||
reg = <0x7000f010 0x02c
|
||||
0x7000f1f0 0x010
|
||||
0x7000f228 0x05c>;
|
||||
nvidia,#asids = <4>; /* # of ASIDs */
|
||||
dma-window = <0 0x40000000>; /* IOVA start & length */
|
||||
nvidia,ahb = <&ahb>;
|
||||
};
|
||||
|
||||
ahub@70080000 {
|
||||
compatible = "nvidia,tegra30-ahub";
|
||||
reg = <0x70080000 0x200
|
||||
0x70080200 0x100>;
|
||||
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_D_AUDIO>,
|
||||
<&tegra_car TEGRA30_CLK_APBIF>;
|
||||
clock-names = "d_audio", "apbif";
|
||||
resets = <&tegra_car 106>, /* d_audio */
|
||||
<&tegra_car 107>, /* apbif */
|
||||
<&tegra_car 30>, /* i2s0 */
|
||||
<&tegra_car 11>, /* i2s1 */
|
||||
<&tegra_car 18>, /* i2s2 */
|
||||
<&tegra_car 101>, /* i2s3 */
|
||||
<&tegra_car 102>, /* i2s4 */
|
||||
<&tegra_car 108>, /* dam0 */
|
||||
<&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",
|
||||
"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;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
tegra_i2s0: i2s@70080300 {
|
||||
compatible = "nvidia,tegra30-i2s";
|
||||
reg = <0x70080300 0x100>;
|
||||
nvidia,ahub-cif-ids = <4 4>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2S0>;
|
||||
resets = <&tegra_car 30>;
|
||||
reset-names = "i2s";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tegra_i2s1: i2s@70080400 {
|
||||
compatible = "nvidia,tegra30-i2s";
|
||||
reg = <0x70080400 0x100>;
|
||||
nvidia,ahub-cif-ids = <5 5>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2S1>;
|
||||
resets = <&tegra_car 11>;
|
||||
reset-names = "i2s";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tegra_i2s2: i2s@70080500 {
|
||||
compatible = "nvidia,tegra30-i2s";
|
||||
reg = <0x70080500 0x100>;
|
||||
nvidia,ahub-cif-ids = <6 6>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2S2>;
|
||||
resets = <&tegra_car 18>;
|
||||
reset-names = "i2s";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tegra_i2s3: i2s@70080600 {
|
||||
compatible = "nvidia,tegra30-i2s";
|
||||
reg = <0x70080600 0x100>;
|
||||
nvidia,ahub-cif-ids = <7 7>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2S3>;
|
||||
resets = <&tegra_car 101>;
|
||||
reset-names = "i2s";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tegra_i2s4: i2s@70080700 {
|
||||
compatible = "nvidia,tegra30-i2s";
|
||||
reg = <0x70080700 0x100>;
|
||||
nvidia,ahub-cif-ids = <8 8>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_I2S4>;
|
||||
resets = <&tegra_car 102>;
|
||||
reset-names = "i2s";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
sdhci@78000000 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000000 0x200>;
|
||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC1>;
|
||||
resets = <&tegra_car 14>;
|
||||
reset-names = "sdhci";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sdhci@78000200 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000200 0x200>;
|
||||
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC2>;
|
||||
resets = <&tegra_car 9>;
|
||||
reset-names = "sdhci";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sdhci@78000400 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000400 0x200>;
|
||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC3>;
|
||||
resets = <&tegra_car 69>;
|
||||
reset-names = "sdhci";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sdhci@78000600 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000600 0x200>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_SDMMC4>;
|
||||
resets = <&tegra_car 15>;
|
||||
reset-names = "sdhci";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb@7d000000 {
|
||||
compatible = "nvidia,tegra30-ehci", "usb-ehci";
|
||||
reg = <0x7d000000 0x4000>;
|
||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy_type = "utmi";
|
||||
clocks = <&tegra_car TEGRA30_CLK_USBD>;
|
||||
resets = <&tegra_car 22>;
|
||||
reset-names = "usb";
|
||||
nvidia,needs-double-reset;
|
||||
nvidia,phy = <&phy1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
phy1: usb-phy@7d000000 {
|
||||
compatible = "nvidia,tegra30-usb-phy";
|
||||
reg = <0x7d000000 0x4000 0x7d000000 0x4000>;
|
||||
phy_type = "utmi";
|
||||
clocks = <&tegra_car TEGRA30_CLK_USBD>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_U>,
|
||||
<&tegra_car TEGRA30_CLK_USBD>;
|
||||
clock-names = "reg", "pll_u", "utmi-pads";
|
||||
nvidia,hssync-start-delay = <9>;
|
||||
nvidia,idle-wait-delay = <17>;
|
||||
nvidia,elastic-limit = <16>;
|
||||
nvidia,term-range-adj = <6>;
|
||||
nvidia,xcvr-setup = <51>;
|
||||
nvidia.xcvr-setup-use-fuses;
|
||||
nvidia,xcvr-lsfslew = <1>;
|
||||
nvidia,xcvr-lsrslew = <1>;
|
||||
nvidia,xcvr-hsslew = <32>;
|
||||
nvidia,hssquelch-level = <2>;
|
||||
nvidia,hsdiscon-level = <5>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb@7d004000 {
|
||||
compatible = "nvidia,tegra30-ehci", "usb-ehci";
|
||||
reg = <0x7d004000 0x4000>;
|
||||
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy_type = "utmi";
|
||||
clocks = <&tegra_car TEGRA30_CLK_USB2>;
|
||||
resets = <&tegra_car 58>;
|
||||
reset-names = "usb";
|
||||
nvidia,phy = <&phy2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
phy2: usb-phy@7d004000 {
|
||||
compatible = "nvidia,tegra30-usb-phy";
|
||||
reg = <0x7d004000 0x4000 0x7d000000 0x4000>;
|
||||
phy_type = "utmi";
|
||||
clocks = <&tegra_car TEGRA30_CLK_USB2>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_U>,
|
||||
<&tegra_car TEGRA30_CLK_USBD>;
|
||||
clock-names = "reg", "pll_u", "utmi-pads";
|
||||
nvidia,hssync-start-delay = <9>;
|
||||
nvidia,idle-wait-delay = <17>;
|
||||
nvidia,elastic-limit = <16>;
|
||||
nvidia,term-range-adj = <6>;
|
||||
nvidia,xcvr-setup = <51>;
|
||||
nvidia.xcvr-setup-use-fuses;
|
||||
nvidia,xcvr-lsfslew = <2>;
|
||||
nvidia,xcvr-lsrslew = <2>;
|
||||
nvidia,xcvr-hsslew = <32>;
|
||||
nvidia,hssquelch-level = <2>;
|
||||
nvidia,hsdiscon-level = <5>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
usb@7d008000 {
|
||||
compatible = "nvidia,tegra30-ehci", "usb-ehci";
|
||||
reg = <0x7d008000 0x4000>;
|
||||
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy_type = "utmi";
|
||||
clocks = <&tegra_car TEGRA30_CLK_USB3>;
|
||||
resets = <&tegra_car 59>;
|
||||
reset-names = "usb";
|
||||
nvidia,phy = <&phy3>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
phy3: usb-phy@7d008000 {
|
||||
compatible = "nvidia,tegra30-usb-phy";
|
||||
reg = <0x7d008000 0x4000 0x7d000000 0x4000>;
|
||||
phy_type = "utmi";
|
||||
clocks = <&tegra_car TEGRA30_CLK_USB3>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_U>,
|
||||
<&tegra_car TEGRA30_CLK_USBD>;
|
||||
clock-names = "reg", "pll_u", "utmi-pads";
|
||||
nvidia,hssync-start-delay = <0>;
|
||||
nvidia,idle-wait-delay = <17>;
|
||||
nvidia,elastic-limit = <16>;
|
||||
nvidia,term-range-adj = <6>;
|
||||
nvidia,xcvr-setup = <51>;
|
||||
nvidia.xcvr-setup-use-fuses;
|
||||
nvidia,xcvr-lsfslew = <2>;
|
||||
nvidia,xcvr-lsrslew = <2>;
|
||||
nvidia,xcvr-hsslew = <32>;
|
||||
nvidia,hssquelch-level = <2>;
|
||||
nvidia,hsdiscon-level = <5>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
cpu@2 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
cpu@3 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
pmu {
|
||||
compatible = "arm,cortex-a9-pmu";
|
||||
interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
|
@ -7,39 +7,6 @@ config ARCH_TEXT_BASE
|
|||
config BOARDINFO
|
||||
default ""
|
||||
|
||||
choice
|
||||
prompt "Tegra debug UART"
|
||||
help
|
||||
This is the first serial console that gets activated by barebox.
|
||||
Normally each board vendor should program a valid debug UART into
|
||||
the ODMdata section of the boot configuration table, so it's a
|
||||
reasonably good bet to use that.
|
||||
If you know your ODMdata is broken, or you don't wish to activate
|
||||
any serial console at all you can override the default here.
|
||||
|
||||
config TEGRA_UART_ODMDATA
|
||||
bool "ODMdata defined UART"
|
||||
|
||||
config TEGRA_UART_A
|
||||
bool "UART A"
|
||||
|
||||
config TEGRA_UART_B
|
||||
bool "UART B"
|
||||
|
||||
config TEGRA_UART_C
|
||||
bool "UART C"
|
||||
|
||||
config TEGRA_UART_D
|
||||
bool "UART D"
|
||||
|
||||
config TEGRA_UART_E
|
||||
bool "UART E"
|
||||
|
||||
config TEGRA_UART_NONE
|
||||
bool "None"
|
||||
|
||||
endchoice
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
config ARCH_TEGRA_2x_SOC
|
||||
|
@ -70,6 +37,8 @@ config MACH_NVIDIA_BEAVER
|
|||
config MACH_NVIDIA_JETSON
|
||||
bool "NVIDIA Jetson TK1"
|
||||
select ARCH_TEGRA_124_SOC
|
||||
select I2C
|
||||
select I2C_TEGRA
|
||||
|
||||
endmenu
|
||||
|
||||
|
|
|
@ -176,37 +176,6 @@ uint32_t tegra30_get_ramsize(void)
|
|||
}
|
||||
}
|
||||
|
||||
static long uart_id_to_base[] = {
|
||||
TEGRA_UARTA_BASE,
|
||||
TEGRA_UARTB_BASE,
|
||||
TEGRA_UARTC_BASE,
|
||||
TEGRA_UARTD_BASE,
|
||||
TEGRA_UARTE_BASE,
|
||||
};
|
||||
|
||||
static __always_inline
|
||||
long tegra20_get_debuguart_base(void)
|
||||
{
|
||||
u32 odmdata;
|
||||
int id;
|
||||
|
||||
odmdata = tegra_get_odmdata();
|
||||
|
||||
/*
|
||||
* Get type, we accept both "2" and "3", as they both demark a UART,
|
||||
* depending on the board type.
|
||||
*/
|
||||
if (!(((odmdata & T20_ODMDATA_UARTTYPE_MASK) >>
|
||||
T20_ODMDATA_UARTTYPE_SHIFT) & 0x2))
|
||||
return 0;
|
||||
|
||||
id = (odmdata & T20_ODMDATA_UARTID_MASK) >> T20_ODMDATA_UARTID_SHIFT;
|
||||
if (id > ARRAY_SIZE(uart_id_to_base))
|
||||
return 0;
|
||||
|
||||
return uart_id_to_base[id];
|
||||
}
|
||||
|
||||
#define CRC_OSC_CTRL 0x050
|
||||
#define CRC_OSC_CTRL_OSC_FREQ_SHIFT 30
|
||||
#define CRC_OSC_CTRL_OSC_FREQ_MASK (0x3 << CRC_OSC_CTRL_OSC_FREQ_SHIFT)
|
||||
|
@ -231,20 +200,6 @@ int tegra_get_osc_clock(void)
|
|||
}
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
int tegra_get_pllp_rate(void)
|
||||
{
|
||||
switch (tegra_get_chiptype()) {
|
||||
case TEGRA20:
|
||||
return 216000000;
|
||||
case TEGRA30:
|
||||
case TEGRA124:
|
||||
return 408000000;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define TIMER_CNTR_1US 0x00
|
||||
#define TIMER_USEC_CFG 0x04
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Google, Inc
|
||||
*
|
||||
* Author:
|
||||
* Colin Cross <ccross@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MACH_TEGRA_POWERGATE_H_
|
||||
#define _MACH_TEGRA_POWERGATE_H_
|
||||
|
||||
struct clk;
|
||||
struct reset_control;
|
||||
|
||||
#define TEGRA_POWERGATE_CPU 0
|
||||
#define TEGRA_POWERGATE_3D 1
|
||||
#define TEGRA_POWERGATE_VENC 2
|
||||
#define TEGRA_POWERGATE_PCIE 3
|
||||
#define TEGRA_POWERGATE_VDEC 4
|
||||
#define TEGRA_POWERGATE_L2 5
|
||||
#define TEGRA_POWERGATE_MPE 6
|
||||
#define TEGRA_POWERGATE_HEG 7
|
||||
#define TEGRA_POWERGATE_SATA 8
|
||||
#define TEGRA_POWERGATE_CPU1 9
|
||||
#define TEGRA_POWERGATE_CPU2 10
|
||||
#define TEGRA_POWERGATE_CPU3 11
|
||||
#define TEGRA_POWERGATE_CELP 12
|
||||
#define TEGRA_POWERGATE_3D1 13
|
||||
#define TEGRA_POWERGATE_CPU0 14
|
||||
#define TEGRA_POWERGATE_C0NC 15
|
||||
#define TEGRA_POWERGATE_C1NC 16
|
||||
#define TEGRA_POWERGATE_SOR 17
|
||||
#define TEGRA_POWERGATE_DIS 18
|
||||
#define TEGRA_POWERGATE_DISB 19
|
||||
#define TEGRA_POWERGATE_XUSBA 20
|
||||
#define TEGRA_POWERGATE_XUSBB 21
|
||||
#define TEGRA_POWERGATE_XUSBC 22
|
||||
#define TEGRA_POWERGATE_VIC 23
|
||||
#define TEGRA_POWERGATE_IRAM 24
|
||||
|
||||
#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D
|
||||
|
||||
#define TEGRA_IO_RAIL_CSIA 0
|
||||
#define TEGRA_IO_RAIL_CSIB 1
|
||||
#define TEGRA_IO_RAIL_DSI 2
|
||||
#define TEGRA_IO_RAIL_MIPI_BIAS 3
|
||||
#define TEGRA_IO_RAIL_PEX_BIAS 4
|
||||
#define TEGRA_IO_RAIL_PEX_CLK1 5
|
||||
#define TEGRA_IO_RAIL_PEX_CLK2 6
|
||||
#define TEGRA_IO_RAIL_USB0 9
|
||||
#define TEGRA_IO_RAIL_USB1 10
|
||||
#define TEGRA_IO_RAIL_USB2 11
|
||||
#define TEGRA_IO_RAIL_USB_BIAS 12
|
||||
#define TEGRA_IO_RAIL_NAND 13
|
||||
#define TEGRA_IO_RAIL_UART 14
|
||||
#define TEGRA_IO_RAIL_BB 15
|
||||
#define TEGRA_IO_RAIL_AUDIO 17
|
||||
#define TEGRA_IO_RAIL_HSIC 19
|
||||
#define TEGRA_IO_RAIL_COMP 22
|
||||
#define TEGRA_IO_RAIL_HDMI 28
|
||||
#define TEGRA_IO_RAIL_PEX_CNTRL 32
|
||||
#define TEGRA_IO_RAIL_SDMMC1 33
|
||||
#define TEGRA_IO_RAIL_SDMMC3 34
|
||||
#define TEGRA_IO_RAIL_SDMMC4 35
|
||||
#define TEGRA_IO_RAIL_CAM 36
|
||||
#define TEGRA_IO_RAIL_RES 37
|
||||
#define TEGRA_IO_RAIL_HV 38
|
||||
#define TEGRA_IO_RAIL_DSIB 39
|
||||
#define TEGRA_IO_RAIL_DSIC 40
|
||||
#define TEGRA_IO_RAIL_DSID 41
|
||||
#define TEGRA_IO_RAIL_CSIE 44
|
||||
#define TEGRA_IO_RAIL_LVDS 57
|
||||
#define TEGRA_IO_RAIL_SYS_DDC 58
|
||||
|
||||
int tegra_powergate_is_powered(int id);
|
||||
int tegra_powergate_power_on(int id);
|
||||
int tegra_powergate_power_off(int id);
|
||||
int tegra_powergate_remove_clamping(int id);
|
||||
|
||||
/* Must be called with clk disabled, and returns with clk enabled */
|
||||
int tegra_powergate_sequence_power_up(int id, struct clk *clk,
|
||||
struct reset_control *rst);
|
||||
|
||||
#endif /* _MACH_TEGRA_POWERGATE_H_ */
|
|
@ -49,6 +49,8 @@
|
|||
#define CRC_CLK_OUT_ENB_H 0x014
|
||||
#define CRC_CLK_OUT_ENB_H_DVC (1 << 15)
|
||||
|
||||
#define CRC_CLK_OUT_ENB_U 0x018
|
||||
|
||||
#define CRC_CCLK_BURST_POLICY 0x020
|
||||
#define CRC_CCLK_BURST_POLICY_SYS_STATE_SHIFT 28
|
||||
#define CRC_CCLK_BURST_POLICY_SYS_STATE_FIQ 8
|
||||
|
|
|
@ -71,3 +71,12 @@
|
|||
#define PMC_PARTID_C0NC 15
|
||||
|
||||
#define PMC_SCRATCH(i) (0x050 + 0x4*i)
|
||||
|
||||
#define PMC_RST_STATUS 0x1b4
|
||||
#define PMC_RST_STATUS_RST_SRC_SHIFT 0
|
||||
#define PMC_RST_STATUS_RST_SRC_MASK (0x7 << PMC_RST_STATUS_RST_SRC_SHIFT)
|
||||
#define PMC_RST_STATUS_RST_SRC_POR 0
|
||||
#define PMC_RST_STATUS_RST_SRC_WATCHDOG 1
|
||||
#define PMC_RST_STATUS_RST_SRC_SENSOR 2
|
||||
#define PMC_RST_STATUS_RST_SRC_SW_MAIN 3
|
||||
#define PMC_RST_STATUS_RST_SRC_LP0 4
|
||||
|
|
|
@ -33,3 +33,5 @@
|
|||
#define CRC_RST_DEV_V_CLR 0x434
|
||||
|
||||
#define CRC_CLK_OUT_ENB_V_SET 0x440
|
||||
|
||||
#define CRC_PLLE_AUX 0x48c
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
|
||||
* Copyright (C) 2013-2014 Lucas Stach <l.stach@pengutronix.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -19,15 +19,21 @@
|
|||
* @brief Device driver for the Tegra 20 power management controller.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/reset.h>
|
||||
#include <mach/lowlevel.h>
|
||||
#include <mach/tegra-powergate.h>
|
||||
#include <reset_source.h>
|
||||
|
||||
#include <mach/tegra20-pmc.h>
|
||||
|
||||
static void __iomem *pmc_base;
|
||||
static int tegra_num_powerdomains;
|
||||
|
||||
/* main SoC reset trigger */
|
||||
void __noreturn reset_cpu(ulong addr)
|
||||
|
@ -38,6 +44,162 @@ void __noreturn reset_cpu(ulong addr)
|
|||
}
|
||||
EXPORT_SYMBOL(reset_cpu);
|
||||
|
||||
static int tegra_powergate_set(int id, bool new_state)
|
||||
{
|
||||
bool status;
|
||||
|
||||
status = readl(pmc_base + PMC_PWRGATE_STATUS) & (1 << id);
|
||||
|
||||
if (status == new_state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
writel(PMC_PWRGATE_TOGGLE_START | id, pmc_base + PMC_PWRGATE_TOGGLE);
|
||||
/* I don't know exactly why this is needed, seems to flush the write */
|
||||
readl(pmc_base + PMC_PWRGATE_TOGGLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_powergate_power_on(int id)
|
||||
{
|
||||
if (id < 0 || id >= tegra_num_powerdomains)
|
||||
return -EINVAL;
|
||||
|
||||
return tegra_powergate_set(id, true);
|
||||
}
|
||||
|
||||
int tegra_powergate_power_off(int id)
|
||||
{
|
||||
if (id < 0 || id >= tegra_num_powerdomains)
|
||||
return -EINVAL;
|
||||
|
||||
return tegra_powergate_set(id, false);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_power_off);
|
||||
|
||||
int tegra_powergate_is_powered(int id)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
if (id < 0 || id >= tegra_num_powerdomains)
|
||||
return -EINVAL;
|
||||
|
||||
status = readl(pmc_base + PMC_PWRGATE_STATUS) & (1 << id);
|
||||
return !!status;
|
||||
}
|
||||
|
||||
int tegra_powergate_remove_clamping(int id)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (id < 0 || id >= tegra_num_powerdomains)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Tegra 2 has a bug where PCIE and VDE clamping masks are
|
||||
* swapped relatively to the partition ids
|
||||
*/
|
||||
if (id == TEGRA_POWERGATE_VDEC)
|
||||
mask = (1 << TEGRA_POWERGATE_PCIE);
|
||||
else if (id == TEGRA_POWERGATE_PCIE)
|
||||
mask = (1 << TEGRA_POWERGATE_VDEC);
|
||||
else
|
||||
mask = (1 << id);
|
||||
|
||||
writel(mask, pmc_base + PMC_REMOVE_CLAMPING_CMD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
|
||||
|
||||
/* Must be called with clk disabled, and returns with clk enabled */
|
||||
int tegra_powergate_sequence_power_up(int id, struct clk *clk,
|
||||
struct reset_control *rst)
|
||||
{
|
||||
int ret;
|
||||
|
||||
reset_control_assert(rst);
|
||||
|
||||
ret = tegra_powergate_power_on(id);
|
||||
if (ret)
|
||||
goto err_power;
|
||||
|
||||
ret = clk_enable(clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
udelay(10);
|
||||
|
||||
ret = tegra_powergate_remove_clamping(id);
|
||||
if (ret)
|
||||
goto err_clamp;
|
||||
|
||||
udelay(10);
|
||||
reset_control_deassert(rst);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clamp:
|
||||
clk_disable(clk);
|
||||
err_clk:
|
||||
tegra_powergate_power_off(id);
|
||||
err_power:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
|
||||
|
||||
static int tegra_powergate_init(void)
|
||||
{
|
||||
switch (tegra_get_chiptype()) {
|
||||
case TEGRA20:
|
||||
tegra_num_powerdomains = 7;
|
||||
break;
|
||||
case TEGRA30:
|
||||
tegra_num_powerdomains = 14;
|
||||
break;
|
||||
case TEGRA114:
|
||||
tegra_num_powerdomains = 23;
|
||||
break;
|
||||
case TEGRA124:
|
||||
tegra_num_powerdomains = 25;
|
||||
break;
|
||||
default:
|
||||
/* Unknown Tegra variant. Disable powergating */
|
||||
tegra_num_powerdomains = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra20_pmc_detect_reset_cause(void)
|
||||
{
|
||||
u32 reg = readl(pmc_base + PMC_RST_STATUS);
|
||||
|
||||
switch ((reg & PMC_RST_STATUS_RST_SRC_MASK) >>
|
||||
PMC_RST_STATUS_RST_SRC_SHIFT) {
|
||||
case PMC_RST_STATUS_RST_SRC_POR:
|
||||
reset_source_set(RESET_POR);
|
||||
break;
|
||||
case PMC_RST_STATUS_RST_SRC_WATCHDOG:
|
||||
reset_source_set(RESET_WDG);
|
||||
break;
|
||||
case PMC_RST_STATUS_RST_SRC_LP0:
|
||||
reset_source_set(RESET_WKE);
|
||||
break;
|
||||
case PMC_RST_STATUS_RST_SRC_SW_MAIN:
|
||||
reset_source_set(RESET_RST);
|
||||
break;
|
||||
case PMC_RST_STATUS_RST_SRC_SENSOR:
|
||||
reset_source_set(RESET_THERM);
|
||||
break;
|
||||
default:
|
||||
reset_source_set(RESET_UKWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra20_pmc_probe(struct device_d *dev)
|
||||
{
|
||||
pmc_base = dev_request_mem_region(dev, 0);
|
||||
|
@ -46,6 +208,11 @@ static int tegra20_pmc_probe(struct device_d *dev)
|
|||
return PTR_ERR(pmc_base);
|
||||
}
|
||||
|
||||
tegra_powergate_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_RESET_SOURCE))
|
||||
tegra20_pmc_detect_reset_cause();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,47 +22,6 @@
|
|||
#include <mach/lowlevel.h>
|
||||
#include <mach/tegra114-sysctr.h>
|
||||
|
||||
static struct NS16550_plat debug_uart = {
|
||||
.shift = 2,
|
||||
};
|
||||
|
||||
static int tegra_add_debug_console(void)
|
||||
{
|
||||
unsigned long base = 0;
|
||||
|
||||
if (!of_machine_is_compatible("nvidia,tegra20") &&
|
||||
!of_machine_is_compatible("nvidia,tegra30") &&
|
||||
!of_machine_is_compatible("nvidia,tegra124"))
|
||||
return 0;
|
||||
|
||||
/* figure out which UART to use */
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_NONE))
|
||||
return 0;
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_ODMDATA))
|
||||
base = tegra20_get_debuguart_base();
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_A))
|
||||
base = TEGRA_UARTA_BASE;
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_B))
|
||||
base = TEGRA_UARTB_BASE;
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_C))
|
||||
base = TEGRA_UARTC_BASE;
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_D))
|
||||
base = TEGRA_UARTD_BASE;
|
||||
if (IS_ENABLED(CONFIG_TEGRA_UART_E))
|
||||
base = TEGRA_UARTE_BASE;
|
||||
|
||||
if (!base)
|
||||
return -ENODEV;
|
||||
|
||||
debug_uart.clock = tegra_get_pllp_rate();
|
||||
|
||||
add_ns16550_device(DEVICE_ID_DYNAMIC, base, 8 << debug_uart.shift,
|
||||
IORESOURCE_MEM | IORESOURCE_MEM_8BIT, &debug_uart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
console_initcall(tegra_add_debug_console);
|
||||
|
||||
static int tegra20_mem_init(void)
|
||||
{
|
||||
if (!of_machine_is_compatible("nvidia,tegra20"))
|
||||
|
|
|
@ -151,7 +151,7 @@ static struct pci_controller gt64120_controller = {
|
|||
|
||||
static int pcibios_init(void)
|
||||
{
|
||||
resource_size_t start, end, map, start1, end1, map1, mask, res_end;
|
||||
resource_size_t start, end, map, start1, end1, map1, mask;
|
||||
|
||||
/*
|
||||
* Due to a bug in the Galileo system controller, we need
|
||||
|
@ -207,7 +207,7 @@ static int pcibios_init(void)
|
|||
BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
|
||||
mask != ~((mask & -mask) - 1));
|
||||
gt64120_io_resource.start = map & mask;
|
||||
res_end = (map & mask) | ~mask;
|
||||
gt64120_io_resource.end = (map & mask) | ~mask;
|
||||
gt64120_controller.io_offset = 0;
|
||||
/* Addresses are 36-bit, so do shifts in the destinations. */
|
||||
gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
|
||||
|
|
|
@ -20,10 +20,24 @@
|
|||
#include <complete.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
static void traverse_bus(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
printf("%02x:%02x.%1x %04x: %04x:%04x (rev %02x)\n",
|
||||
dev->bus->number, PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn), (dev->class >> 8) & 0xffff,
|
||||
dev->vendor, dev->device, dev->revision);
|
||||
|
||||
if (dev->subordinate)
|
||||
traverse_bus(dev->subordinate);
|
||||
}
|
||||
}
|
||||
|
||||
static int do_lspci(int argc, char *argv[])
|
||||
{
|
||||
struct pci_bus *root_bus;
|
||||
struct pci_dev *dev;
|
||||
|
||||
if (list_empty(&pci_root_buses)) {
|
||||
printf("No PCI bus detected\n");
|
||||
|
@ -31,14 +45,7 @@ static int do_lspci(int argc, char *argv[])
|
|||
}
|
||||
|
||||
list_for_each_entry(root_bus, &pci_root_buses, node) {
|
||||
list_for_each_entry(dev, &root_bus->devices, bus_list) {
|
||||
printf("%02x: %04x: %04x:%04x (rev %02x)\n",
|
||||
dev->devfn,
|
||||
(dev->class >> 8) & 0xffff,
|
||||
dev->vendor,
|
||||
dev->device,
|
||||
dev->revision);
|
||||
}
|
||||
traverse_bus(root_bus);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -25,6 +25,7 @@ static const char * const reset_src_names[] = {
|
|||
[RESET_WDG] = "WDG",
|
||||
[RESET_WKE] = "WKE",
|
||||
[RESET_JTAG] = "JTAG",
|
||||
[RESET_THERM] = "THERM",
|
||||
};
|
||||
|
||||
static enum reset_src_type reset_source;
|
||||
|
|
|
@ -30,5 +30,6 @@ source "drivers/reset/Kconfig"
|
|||
source "drivers/pci/Kconfig"
|
||||
source "drivers/rtc/Kconfig"
|
||||
source "drivers/firmware/Kconfig"
|
||||
source "drivers/phy/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -29,3 +29,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/
|
|||
obj-$(CONFIG_PCI) += pci/
|
||||
obj-y += rtc/
|
||||
obj-$(CONFIG_FIRMWARE) += firmware/
|
||||
obj-$(CONFIG_GENERIC_PHY) += phy/
|
||||
|
|
|
@ -17,12 +17,15 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clock.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
#include <asm-generic/div64.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
#define PLL_BASE_BYPASS BIT(31)
|
||||
|
@ -60,6 +63,7 @@
|
|||
#define PLLDU_LFCON_SET_DIVN 600
|
||||
|
||||
#define PLLE_BASE_DIVCML_SHIFT 24
|
||||
#define PLLE_BASE_DIVCML_MASK 0xf
|
||||
#define PLLE_BASE_DIVCML_WIDTH 4
|
||||
#define PLLE_BASE_DIVP_SHIFT 16
|
||||
#define PLLE_BASE_DIVP_WIDTH 7
|
||||
|
@ -78,8 +82,45 @@
|
|||
PLLE_MISC_SETUP_EX_MASK)
|
||||
#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
|
||||
|
||||
#define PLLE_SS_CTRL 0x68
|
||||
#define PLLE_SS_DISABLE (7 << 10)
|
||||
#define XUSBIO_PLL_CFG0 0x51c
|
||||
#define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL (1 << 0)
|
||||
#define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL (1 << 2)
|
||||
#define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET (1 << 6)
|
||||
#define XUSBIO_PLL_CFG0_SEQ_ENABLE (1 << 24)
|
||||
#define XUSBIO_PLL_CFG0_SEQ_START_STATE (1 << 25)
|
||||
|
||||
#define PLLE_SS_CTRL 0x68
|
||||
#define PLLE_SS_CNTL_BYPASS_SS (7 << 10)
|
||||
#define PLLE_SS_CNTL_INTERP_RESET (1 << 11)
|
||||
#define PLLE_SS_CNTL_SSC_BYP (1 << 12)
|
||||
#define PLLE_SS_CNTL_CENTER (1 << 14)
|
||||
#define PLLE_SS_CNTL_INVERT (1 << 15)
|
||||
#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_MISC_VREG_CTRL_SHIFT 2
|
||||
#define PLLE_MISC_VREG_CTRL_MASK (2 << PLLE_MISC_VREG_CTRL_SHIFT)
|
||||
#define PLLE_MISC_VREG_BG_CTRL_SHIFT 4
|
||||
#define PLLE_MISC_VREG_BG_CTRL_MASK (3 << PLLE_MISC_VREG_BG_CTRL_SHIFT)
|
||||
#define PLLE_MISC_PLLE_PTS (1 << 8)
|
||||
#define PLLE_MISC_IDDQ_SW_VALUE (1 << 13)
|
||||
#define PLLE_MISC_IDDQ_SW_CTRL (1 << 14)
|
||||
|
||||
#define PLLE_AUX_PLLP_SEL (1 << 2)
|
||||
#define PLLE_AUX_USE_LOCKDET (1 << 3)
|
||||
#define PLLE_AUX_ENABLE_SWCTL (1 << 4)
|
||||
#define PLLE_AUX_SS_SWCTL (1 << 6)
|
||||
#define PLLE_AUX_SEQ_ENABLE (1 << 24)
|
||||
#define PLLE_AUX_SEQ_START_STATE (1 << 25)
|
||||
#define PLLE_AUX_PLLRE_SEL (1 << 28)
|
||||
|
||||
#define PMC_SATA_PWRGT 0x1ac
|
||||
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
|
||||
|
@ -99,10 +140,19 @@
|
|||
#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
|
||||
mask(p->divp_width))
|
||||
|
||||
#define divm_shift(p) (p)->divm_shift
|
||||
#define divn_shift(p) (p)->divn_shift
|
||||
#define divp_shift(p) (p)->divp_shift
|
||||
|
||||
#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p))
|
||||
#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p))
|
||||
#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p))
|
||||
|
||||
#define divm_max(p) (divm_mask(p))
|
||||
#define divn_max(p) (divn_mask(p))
|
||||
#define divp_max(p) (1 << (divp_mask(p)))
|
||||
|
||||
|
||||
#define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw)
|
||||
|
||||
static int clk_pll_is_enabled(struct clk *hw)
|
||||
|
@ -393,6 +443,217 @@ const struct clk_ops tegra_clk_pll_ops = {
|
|||
.set_rate = clk_pll_set_rate,
|
||||
};
|
||||
|
||||
static unsigned long clk_plle_recalc_rate(struct clk *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 val = pll_readl_base(pll);
|
||||
u32 divn = 0, divm = 0, divp = 0;
|
||||
u64 rate = parent_rate;
|
||||
|
||||
divp = (val >> 16) & 0x3f;
|
||||
divn = (val >> 8) & (0xff);
|
||||
divm = (val >> 0) & (0xff);
|
||||
divm *= divp;
|
||||
|
||||
rate *= divn;
|
||||
do_div(rate, divm);
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int clk_plle_training(struct tegra_clk_pll *pll)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* PLLE is already disabled, and setup cleared;
|
||||
* create falling edge on PLLE IDDQ input.
|
||||
*/
|
||||
val = readl(TEGRA_PMC_BASE + PMC_SATA_PWRGT);
|
||||
val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
|
||||
writel(val, TEGRA_PMC_BASE + PMC_SATA_PWRGT);
|
||||
|
||||
val = readl(TEGRA_PMC_BASE + PMC_SATA_PWRGT);
|
||||
val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
|
||||
writel(val, TEGRA_PMC_BASE + PMC_SATA_PWRGT);
|
||||
|
||||
val = readl(TEGRA_PMC_BASE + PMC_SATA_PWRGT);
|
||||
val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
|
||||
writel(val, TEGRA_PMC_BASE + PMC_SATA_PWRGT);
|
||||
|
||||
return wait_on_timeout(100 * MSECOND,
|
||||
(pll_readl_misc(pll) & PLLE_MISC_READY));
|
||||
}
|
||||
|
||||
static int clk_plle_enable(struct clk *hw)
|
||||
{
|
||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||
unsigned long input_rate = clk_get_rate(clk_get_parent(hw));
|
||||
struct tegra_clk_pll_freq_table sel;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
|
||||
return -EINVAL;
|
||||
|
||||
clk_pll_disable(hw);
|
||||
|
||||
val = pll_readl_misc(pll);
|
||||
val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
|
||||
pll_writel_misc(val, pll);
|
||||
|
||||
val = pll_readl_misc(pll);
|
||||
if (!(val & PLLE_MISC_READY)) {
|
||||
err = clk_plle_training(pll);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* configure dividers */
|
||||
val = pll_readl_base(pll);
|
||||
val &= ~(0x3fffff);
|
||||
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
||||
val |= sel.m << 0;
|
||||
val |= sel.n << 8;
|
||||
val |= sel.p << 16;
|
||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||
pll_writel_base(val, pll);
|
||||
|
||||
val = pll_readl_misc(pll);
|
||||
val |= PLLE_MISC_SETUP_VALUE;
|
||||
val |= PLLE_MISC_LOCK_ENABLE;
|
||||
pll_writel_misc(val, pll);
|
||||
|
||||
val = readl(pll->clk_base + PLLE_SS_CTRL);
|
||||
val |= PLLE_SS_CNTL_BYPASS_SS;
|
||||
writel(val, pll->clk_base + PLLE_SS_CTRL);
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
|
||||
pll_writel_base(val, pll);
|
||||
|
||||
clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg,
|
||||
pll->params->lock_bit_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops tegra_clk_plle_ops = {
|
||||
.recalc_rate = clk_plle_recalc_rate,
|
||||
.is_enabled = clk_pll_is_enabled,
|
||||
.disable = clk_pll_disable,
|
||||
.enable = clk_plle_enable,
|
||||
};
|
||||
|
||||
static int clk_plle_tegra114_enable(struct clk *hw)
|
||||
{
|
||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||
unsigned long input_rate = clk_get_rate(clk_get_parent(hw));
|
||||
struct tegra_clk_pll_freq_table sel;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
|
||||
return -EINVAL;
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
val &= ~BIT(29); /* Disable lock override */
|
||||
pll_writel_base(val, pll);
|
||||
|
||||
val = pll_readl(pll->params->aux_reg, pll);
|
||||
val |= PLLE_AUX_ENABLE_SWCTL;
|
||||
val &= ~PLLE_AUX_SEQ_ENABLE;
|
||||
pll_writel(val, pll->params->aux_reg, pll);
|
||||
udelay(1);
|
||||
|
||||
val = pll_readl_misc(pll);
|
||||
val |= PLLE_MISC_LOCK_ENABLE;
|
||||
val |= PLLE_MISC_IDDQ_SW_CTRL;
|
||||
val &= ~PLLE_MISC_IDDQ_SW_VALUE;
|
||||
val |= PLLE_MISC_PLLE_PTS;
|
||||
val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
|
||||
pll_writel_misc(val, pll);
|
||||
udelay(5);
|
||||
|
||||
val = pll_readl(PLLE_SS_CTRL, pll);
|
||||
val |= PLLE_SS_CNTL_BYPASS_SS;
|
||||
pll_writel(val, PLLE_SS_CTRL, pll);
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
|
||||
divm_mask_shifted(pll));
|
||||
val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
|
||||
val |= sel.m << divm_shift(pll);
|
||||
val |= sel.n << divn_shift(pll);
|
||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||
pll_writel_base(val, pll);
|
||||
udelay(1);
|
||||
|
||||
clk_pll_enable(hw);
|
||||
ret = clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
|
||||
pll->params->lock_bit_idx);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
|
||||
/* Enable hw control of xusb brick pll */
|
||||
val = pll_readl_misc(pll);
|
||||
val &= ~PLLE_MISC_IDDQ_SW_CTRL;
|
||||
pll_writel_misc(val, pll);
|
||||
|
||||
val = pll_readl(pll->params->aux_reg, pll);
|
||||
val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SEQ_START_STATE);
|
||||
val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
|
||||
pll_writel(val, pll->params->aux_reg, pll);
|
||||
udelay(1);
|
||||
val |= PLLE_AUX_SEQ_ENABLE;
|
||||
pll_writel(val, pll->params->aux_reg, pll);
|
||||
|
||||
val = pll_readl(XUSBIO_PLL_CFG0, pll);
|
||||
val |= (XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
|
||||
XUSBIO_PLL_CFG0_SEQ_START_STATE);
|
||||
val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
|
||||
XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
|
||||
pll_writel(val, XUSBIO_PLL_CFG0, pll);
|
||||
udelay(1);
|
||||
val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
|
||||
pll_writel(val, XUSBIO_PLL_CFG0, pll);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_plle_tegra114_disable(struct clk *hw)
|
||||
{
|
||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 val;
|
||||
|
||||
clk_pll_disable(hw);
|
||||
|
||||
val = pll_readl_misc(pll);
|
||||
val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
|
||||
pll_writel_misc(val, pll);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
const struct clk_ops tegra_clk_plle_tegra114_ops = {
|
||||
.recalc_rate = clk_pll_recalc_rate,
|
||||
.is_enabled = clk_pll_is_enabled,
|
||||
.disable = clk_plle_tegra114_disable,
|
||||
.enable = clk_plle_tegra114_enable,
|
||||
};
|
||||
|
||||
static struct clk *_tegra_clk_register_pll(const char *name,
|
||||
const char *parent_name, void __iomem *clk_base,
|
||||
unsigned long flags, unsigned long fixed_rate,
|
||||
|
@ -447,3 +708,25 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
|||
flags, fixed_rate, pll_params, pll_flags, freq_table,
|
||||
&tegra_clk_pll_ops);
|
||||
}
|
||||
|
||||
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
||||
void __iomem *clk_base,
|
||||
unsigned long flags, unsigned long fixed_rate,
|
||||
struct tegra_clk_pll_params *pll_params, u8 pll_flags,
|
||||
struct tegra_clk_pll_freq_table *freq_table)
|
||||
{
|
||||
return _tegra_clk_register_pll(name, parent_name, clk_base,
|
||||
flags, fixed_rate, pll_params, pll_flags, freq_table,
|
||||
&tegra_clk_plle_ops);
|
||||
}
|
||||
|
||||
struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
||||
const char *parent_name, void __iomem *clk_base,
|
||||
unsigned long flags, unsigned long fixed_rate,
|
||||
struct tegra_clk_pll_params *pll_params, u8 pll_flags,
|
||||
struct tegra_clk_pll_freq_table *freq_table)
|
||||
{
|
||||
return _tegra_clk_register_pll(name, parent_name, clk_base,
|
||||
flags, fixed_rate, pll_params, pll_flags, freq_table,
|
||||
&tegra_clk_plle_tegra114_ops);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,15 @@ static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
|
|||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||
/* PLLE special case: use cpcon field to store cml divider value */
|
||||
{336000000, 100000000, 100, 21, 16, 11},
|
||||
{312000000, 100000000, 200, 26, 24, 13},
|
||||
{13000000, 100000000, 200, 1, 26, 13},
|
||||
{12000000, 100000000, 200, 1, 24, 13},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
|
||||
{12000000, 408000000, 408, 12, 0, 8},
|
||||
{13000000, 408000000, 408, 13, 0, 8},
|
||||
|
@ -114,6 +123,21 @@ static struct tegra_clk_pll_params pll_c_params = {
|
|||
.lock_delay = 300,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_e_params = {
|
||||
.input_min = 12000000,
|
||||
.input_max = 1000000000,
|
||||
.cf_min = 12000000,
|
||||
.cf_max = 75000000,
|
||||
.vco_min = 1600000000,
|
||||
.vco_max = 2400000000U,
|
||||
.base_reg = CRC_PLLE_BASE,
|
||||
.misc_reg = CRC_PLLE_MISC,
|
||||
.aux_reg = CRC_PLLE_AUX,
|
||||
.lock_bit_idx = CRC_PLLE_MISC_LOCK,
|
||||
.lock_enable_bit_idx = CRC_PLLE_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_p_params = {
|
||||
.input_min = 2000000,
|
||||
.input_max = 31000000,
|
||||
|
@ -220,6 +244,11 @@ static void tegra124_pll_init(void)
|
|||
clks[TEGRA124_CLK_PLL_U] = tegra_clk_register_pll("pll_u", "pll_ref",
|
||||
car_base, 0, 0, &pll_u_params, TEGRA_PLLU |
|
||||
TEGRA_PLL_HAS_CPCON, pll_u_freq_table);
|
||||
|
||||
/* PLLE */
|
||||
clks[TEGRA124_CLK_PLL_E] = tegra_clk_register_plle_tegra114("pll_e",
|
||||
"pll_ref", car_base, 0, 100000000, &pll_e_params,
|
||||
TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, pll_e_freq_table);
|
||||
}
|
||||
|
||||
static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c2", "pll_c", "pll_c3",
|
||||
|
@ -244,6 +273,12 @@ static void tegra124_periph_init(void)
|
|||
mux_pllpcm_clkm, ARRAY_SIZE(mux_pllpcm_clkm), car_base,
|
||||
CRC_CLK_SOURCE_UARTD, TEGRA124_CLK_UARTD,
|
||||
TEGRA_PERIPH_ON_APB);
|
||||
clks[TEGRA124_CLK_PCIE] = clk_gate("pcie", "clk_m",
|
||||
car_base + CRC_CLK_OUT_ENB_U, 6, 0, 0);
|
||||
clks[TEGRA124_CLK_AFI] = clk_gate("afi", "clk_m",
|
||||
car_base + CRC_CLK_OUT_ENB_U, 8, 0, 0);
|
||||
clks[TEGRA124_CLK_CML0] = clk_gate("cml0", "pll_e",
|
||||
car_base + CRC_PLLE_AUX, 0, 0, 0);
|
||||
|
||||
/* peripheral clocks with a divider */
|
||||
clks[TEGRA124_CLK_MSELECT] = tegra_clk_register_periph("mselect",
|
||||
|
@ -286,11 +321,11 @@ static struct tegra_clk_init_table init_table[] = {
|
|||
{TEGRA124_CLK_PLL_P_OUT2, TEGRA124_CLK_CLK_MAX, 48000000, 1},
|
||||
{TEGRA124_CLK_PLL_P_OUT3, TEGRA124_CLK_CLK_MAX, 102000000, 1},
|
||||
{TEGRA124_CLK_PLL_P_OUT4, TEGRA124_CLK_CLK_MAX, 204000000, 1},
|
||||
{TEGRA124_CLK_MSELECT, TEGRA124_CLK_PLL_P, 204000000, 1},
|
||||
{TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 0, 1},
|
||||
{TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 0, 1},
|
||||
{TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 0, 1},
|
||||
{TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 0, 1},
|
||||
{TEGRA124_CLK_MSELECT, TEGRA124_CLK_PLL_P, 102000000, 1},
|
||||
{TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 0, 0},
|
||||
{TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 0, 0},
|
||||
{TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 0, 0},
|
||||
{TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 0, 0},
|
||||
{TEGRA124_CLK_SDMMC1, TEGRA124_CLK_PLL_P, 48000000, 0},
|
||||
{TEGRA124_CLK_SDMMC2, TEGRA124_CLK_PLL_P, 48000000, 0},
|
||||
{TEGRA124_CLK_SDMMC3, TEGRA124_CLK_PLL_P, 48000000, 0},
|
||||
|
|
|
@ -324,11 +324,11 @@ static struct tegra_clk_init_table init_table[] = {
|
|||
{TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1},
|
||||
{TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1},
|
||||
{TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1},
|
||||
{TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 1},
|
||||
{TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 1},
|
||||
{TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 1},
|
||||
{TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 1},
|
||||
{TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 1},
|
||||
{TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0},
|
||||
{TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0},
|
||||
{TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0},
|
||||
{TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0},
|
||||
{TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0},
|
||||
{TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0},
|
||||
{TEGRA20_CLK_SDMMC2, TEGRA20_CLK_PLL_P, 48000000, 0},
|
||||
{TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0},
|
||||
|
|
|
@ -130,6 +130,13 @@ static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
|
|||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||
/* PLLE special case: use cpcon field to store cml divider value */
|
||||
{ 12000000, 100000000, 150, 1, 18, 11},
|
||||
{ 216000000, 100000000, 200, 18, 24, 13},
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
/* PLL parameters */
|
||||
static struct tegra_clk_pll_params pll_c_params = {
|
||||
.input_min = 2000000,
|
||||
|
@ -201,6 +208,19 @@ static struct tegra_clk_pll_params pll_u_params = {
|
|||
.lock_delay = 1000,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_e_params = {
|
||||
.input_min = 12000000,
|
||||
.input_max = 216000000,
|
||||
.cf_min = 12000000,
|
||||
.cf_max = 12000000,
|
||||
.vco_min = 1200000000,
|
||||
.vco_max = 2400000000U,
|
||||
.base_reg = CRC_PLLE_BASE,
|
||||
.misc_reg = CRC_PLLE_MISC,
|
||||
.lock_enable_bit_idx = CRC_PLLE_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
};
|
||||
|
||||
static void tegra30_pll_init(void)
|
||||
{
|
||||
/* PLLC */
|
||||
|
@ -251,6 +271,11 @@ static void tegra30_pll_init(void)
|
|||
clks[TEGRA30_CLK_PLL_U] = tegra_clk_register_pll("pll_u", "pll_ref",
|
||||
car_base, 0, 0, &pll_u_params, TEGRA_PLLU |
|
||||
TEGRA_PLL_HAS_CPCON, pll_u_freq_table);
|
||||
|
||||
/* PLLE */
|
||||
clks[TEGRA30_CLK_PLL_E] = tegra_clk_register_plle("pll_e", "pll_ref",
|
||||
car_base, 0, 100000000, &pll_e_params,
|
||||
TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, pll_e_freq_table);
|
||||
}
|
||||
|
||||
static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"};
|
||||
|
@ -278,6 +303,12 @@ static void tegra30_periph_init(void)
|
|||
mux_pllpcm_clkm, ARRAY_SIZE(mux_pllpcm_clkm), car_base,
|
||||
CRC_CLK_SOURCE_UARTE, TEGRA30_CLK_UARTE,
|
||||
TEGRA_PERIPH_ON_APB);
|
||||
clks[TEGRA30_CLK_PCIE] = clk_gate("pcie", "clk_m",
|
||||
car_base + CRC_CLK_OUT_ENB_U, 6, 0, 0);
|
||||
clks[TEGRA30_CLK_AFI] = clk_gate("afi", "clk_m",
|
||||
car_base + CRC_CLK_OUT_ENB_U, 8, 0, 0);
|
||||
clks[TEGRA30_CLK_CML0] = clk_gate("cml0", "pll_e",
|
||||
car_base + CRC_PLLE_AUX, 0, 0, 0);
|
||||
|
||||
/* peripheral clocks with a divider */
|
||||
clks[TEGRA30_CLK_MSELECT] = tegra_clk_register_periph("mselect",
|
||||
|
@ -320,12 +351,12 @@ static struct tegra_clk_init_table init_table[] = {
|
|||
{TEGRA30_CLK_PLL_P_OUT2, TEGRA30_CLK_CLK_MAX, 48000000, 1},
|
||||
{TEGRA30_CLK_PLL_P_OUT3, TEGRA30_CLK_CLK_MAX, 102000000, 1},
|
||||
{TEGRA30_CLK_PLL_P_OUT4, TEGRA30_CLK_CLK_MAX, 204000000, 1},
|
||||
{TEGRA30_CLK_MSELECT, TEGRA30_CLK_PLL_P, 204000000, 1},
|
||||
{TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 0, 1},
|
||||
{TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 0, 1},
|
||||
{TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 0, 1},
|
||||
{TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 0, 1},
|
||||
{TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 0, 1},
|
||||
{TEGRA30_CLK_MSELECT, TEGRA30_CLK_PLL_P, 102000000, 1},
|
||||
{TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 0, 0},
|
||||
{TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 0, 0},
|
||||
{TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 0, 0},
|
||||
{TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 0, 0},
|
||||
{TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 0, 0},
|
||||
{TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0},
|
||||
{TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0},
|
||||
{TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0},
|
||||
|
|
|
@ -63,6 +63,7 @@ struct tegra_clk_pll_params {
|
|||
|
||||
u32 base_reg;
|
||||
u32 misc_reg;
|
||||
u32 aux_reg;
|
||||
u32 lock_reg;
|
||||
u8 lock_bit_idx;
|
||||
u8 lock_enable_bit_idx;
|
||||
|
@ -101,6 +102,18 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
|
|||
struct tegra_clk_pll_params *pll_params, u8 pll_flags,
|
||||
struct tegra_clk_pll_freq_table *freq_table);
|
||||
|
||||
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
|
||||
void __iomem *clk_base,
|
||||
unsigned long flags, unsigned long fixed_rate,
|
||||
struct tegra_clk_pll_params *pll_params, u8 pll_flags,
|
||||
struct tegra_clk_pll_freq_table *freq_table);
|
||||
|
||||
struct clk *tegra_clk_register_plle_tegra114(const char *name,
|
||||
const char *parent_name, void __iomem *clk_base,
|
||||
unsigned long flags, unsigned long fixed_rate,
|
||||
struct tegra_clk_pll_params *pll_params, u8 pll_flags,
|
||||
struct tegra_clk_pll_freq_table *freq_table);
|
||||
|
||||
/* struct tegra_clk_pll_out - PLL output divider */
|
||||
struct tegra_clk_pll_out {
|
||||
struct clk hw;
|
||||
|
|
|
@ -696,4 +696,4 @@ static struct driver_d tegra_i2c_driver = {
|
|||
.probe = tegra_i2c_probe,
|
||||
.of_compatible = DRV_OF_COMPAT(tegra_i2c_compatible),
|
||||
};
|
||||
device_platform_driver(tegra_i2c_driver);
|
||||
register_driver_macro(fs, platform, tegra_i2c_driver);
|
||||
|
|
|
@ -156,6 +156,14 @@ config DRIVER_NET_RTL8139
|
|||
This is a driver for the Fast Ethernet PCI network cards based on
|
||||
the RTL 8139 chips.
|
||||
|
||||
config DRIVER_NET_RTL8169
|
||||
bool "RealTek RTL-8169 PCI Ethernet driver"
|
||||
depends on PCI
|
||||
select PHYLIB
|
||||
help
|
||||
This is a driver for the Fast Ethernet PCI network cards based on
|
||||
the RTL 8169 chips.
|
||||
|
||||
config DRIVER_NET_SMC911X
|
||||
bool "smc911x ethernet driver"
|
||||
select PHYLIB
|
||||
|
|
|
@ -22,6 +22,7 @@ obj-$(CONFIG_DRIVER_NET_MPC5200) += fec_mpc5200.o
|
|||
obj-$(CONFIG_DRIVER_NET_NETX) += netx_eth.o
|
||||
obj-$(CONFIG_DRIVER_NET_ORION) += orion-gbe.o
|
||||
obj-$(CONFIG_DRIVER_NET_RTL8139) += rtl8139.o
|
||||
obj-$(CONFIG_DRIVER_NET_RTL8169) += rtl8169.o
|
||||
obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o
|
||||
obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
|
||||
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
|
||||
|
|
|
@ -0,0 +1,578 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Lucas Stach <l.stach@pengutronix.de>
|
||||
*
|
||||
* 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 <asm/mmu.h>
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <net.h>
|
||||
#include <malloc.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#define NUM_TX_DESC 1
|
||||
#define NUM_RX_DESC 4
|
||||
#define PKT_BUF_SIZE 1536
|
||||
#define ETH_ZLEN 60
|
||||
|
||||
struct rtl8169_chip_info {
|
||||
const char *name;
|
||||
u8 version;
|
||||
u32 RxConfigMask;
|
||||
};
|
||||
|
||||
#define BD_STAT_OWN 0x80000000
|
||||
#define BD_STAT_EOR 0x40000000
|
||||
#define BD_STAT_FS 0x20000000
|
||||
#define BD_STAT_LS 0x10000000
|
||||
#define BD_STAT_RX_RES 0x00200000
|
||||
struct bufdesc {
|
||||
u32 status;
|
||||
u32 vlan_tag;
|
||||
u32 buf_addr;
|
||||
u32 buf_Haddr;
|
||||
};
|
||||
|
||||
struct rtl8169_priv {
|
||||
struct eth_device edev;
|
||||
void __iomem *base;
|
||||
struct pci_dev *pci_dev;
|
||||
int chipset;
|
||||
|
||||
struct bufdesc *tx_desc;
|
||||
void *tx_buf;
|
||||
unsigned int cur_tx;
|
||||
|
||||
struct bufdesc *rx_desc;
|
||||
void *rx_buf;
|
||||
unsigned int cur_rx;
|
||||
|
||||
struct mii_bus miibus;
|
||||
};
|
||||
|
||||
#define MAC0 0x00
|
||||
#define MAR0 0x08
|
||||
#define TxDescStartAddrLow 0x20
|
||||
#define TxDescStartAddrHigh 0x24
|
||||
#define TxHDescStartAddrLow 0x28
|
||||
#define TxHDescStartAddrHigh 0x2c
|
||||
#define FLASH 0x30
|
||||
#define ERSR 0x36
|
||||
#define ChipCmd 0x37
|
||||
#define CmdReset 0x10
|
||||
#define CmdRxEnb 0x08
|
||||
#define CmdTxEnb 0x04
|
||||
#define RxBufEmpty 0x01
|
||||
#define TxPoll 0x38
|
||||
#define IntrMask 0x3c
|
||||
#define IntrStatus 0x3e
|
||||
#define SYSErr 0x8000
|
||||
#define PCSTimeout 0x4000
|
||||
#define SWInt 0x0100
|
||||
#define TxDescUnavail 0x80
|
||||
#define RxFIFOOver 0x40
|
||||
#define RxUnderrun 0x20
|
||||
#define RxOverflow 0x10
|
||||
#define TxErr 0x08
|
||||
#define TxOK 0x04
|
||||
#define RxErr 0x02
|
||||
#define RxOK 0x01
|
||||
#define TxConfig 0x40
|
||||
#define TxInterFrameGapShift 24
|
||||
#define TxDMAShift 8
|
||||
#define RxConfig 0x44
|
||||
#define AcceptErr 0x20
|
||||
#define AcceptRunt 0x10
|
||||
#define AcceptBroadcast 0x08
|
||||
#define AcceptMulticast 0x04
|
||||
#define AcceptMyPhys 0x02
|
||||
#define AcceptAllPhys 0x01
|
||||
#define RxCfgFIFOShift 13
|
||||
#define RxCfgDMAShift 8
|
||||
#define RxMissed 0x4c
|
||||
#define Cfg9346 0x50
|
||||
#define Cfg9346_Lock 0x00
|
||||
#define Cfg9346_Unlock 0xc0
|
||||
#define Config0 0x51
|
||||
#define Config1 0x52
|
||||
#define Config2 0x53
|
||||
#define Config3 0x54
|
||||
#define Config4 0x55
|
||||
#define Config5 0x56
|
||||
#define MultiIntr 0x5c
|
||||
#define PHYAR 0x60
|
||||
#define TBICSR 0x64
|
||||
#define TBI_ANAR 0x68
|
||||
#define TBI_LPAR 0x6a
|
||||
#define PHYstatus 0x6c
|
||||
#define RxMaxSize 0xda
|
||||
#define CPlusCmd 0xe0
|
||||
#define RxDescStartAddrLow 0xe4
|
||||
#define RxDescStartAddrHigh 0xe8
|
||||
#define EarlyTxThres 0xec
|
||||
#define FuncEvent 0xf0
|
||||
#define FuncEventMask 0xf4
|
||||
#define FuncPresetState 0xf8
|
||||
#define FuncForceEvent 0xfc
|
||||
|
||||
/* write MMIO register */
|
||||
#define RTL_W8(priv, reg, val) writeb(val, ((char *)(priv->base) + reg))
|
||||
#define RTL_W16(priv, reg, val) writew(val, ((char *)(priv->base) + reg))
|
||||
#define RTL_W32(priv, reg, val) writel(val, ((char *)(priv->base) + reg))
|
||||
|
||||
/* read MMIO register */
|
||||
#define RTL_R8(priv, reg) readb(((char *)(priv->base) + reg))
|
||||
#define RTL_R16(priv, reg) readw(((char *)(priv->base) + reg))
|
||||
#define RTL_R32(priv, reg) readl(((char *)(priv->base) + reg))
|
||||
|
||||
static const u32 rtl8169_rx_config =
|
||||
(7 << RxCfgFIFOShift) | (6 << RxCfgDMAShift);
|
||||
|
||||
static void rtl8169_chip_reset(struct rtl8169_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Soft reset the chip. */
|
||||
RTL_W8(priv, ChipCmd, CmdReset);
|
||||
|
||||
/* Check that the chip has finished the reset. */
|
||||
for (i = 1000; i > 0; i--) {
|
||||
if ((RTL_R8(priv, ChipCmd) & CmdReset) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
static struct rtl8169_chip_info chip_info[] = {
|
||||
{"RTL-8169", 0x00, 0xff7e1880},
|
||||
{"RTL-8169", 0x04, 0xff7e1880},
|
||||
{"RTL-8169", 0x00, 0xff7e1880},
|
||||
{"RTL-8169s/8110s", 0x02, 0xff7e1880},
|
||||
{"RTL-8169s/8110s", 0x04, 0xff7e1880},
|
||||
{"RTL-8169sb/8110sb", 0x10, 0xff7e1880},
|
||||
{"RTL-8169sc/8110sc", 0x18, 0xff7e1880},
|
||||
{"RTL-8168b/8111sb", 0x30, 0xff7e1880},
|
||||
{"RTL-8168b/8111sb", 0x38, 0xff7e1880},
|
||||
{"RTL-8168d/8111d", 0x28, 0xff7e1880},
|
||||
{"RTL-8168evl/8111evl", 0x2e, 0xff7e1880},
|
||||
{"RTL-8168/8111g", 0x4c, 0xff7e1880,},
|
||||
{"RTL-8101e", 0x34, 0xff7e1880},
|
||||
{"RTL-8100e", 0x32, 0xff7e1880},
|
||||
};
|
||||
|
||||
static void rtl8169_chip_identify(struct rtl8169_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
val = RTL_R32(priv, TxConfig);
|
||||
val = ((val & 0x7c000000) + ((val & 0x00800000) << 2)) >> 24;
|
||||
|
||||
for (i = ARRAY_SIZE(chip_info) - 1; i >= 0; i--){
|
||||
if (val == chip_info[i].version) {
|
||||
priv->chipset = i;
|
||||
dev_dbg(&priv->pci_dev->dev, "found %s chipset\n",
|
||||
chip_info[i].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&priv->pci_dev->dev,
|
||||
"no matching chip version found, assuming RTL-8169\n");
|
||||
priv->chipset = 0;
|
||||
}
|
||||
|
||||
static int rtl8169_init_dev(struct eth_device *edev)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
|
||||
rtl8169_chip_reset(priv);
|
||||
rtl8169_chip_identify(priv);
|
||||
pci_set_master(priv->pci_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __set_rx_mode(struct rtl8169_priv *priv)
|
||||
{
|
||||
u32 mc_filter[2], val;
|
||||
|
||||
/* IFF_ALLMULTI */
|
||||
/* Too many to filter perfectly -- accept all multicasts. */
|
||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||
|
||||
val = AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
||||
rtl8169_rx_config | (RTL_R32(priv, RxConfig) &
|
||||
chip_info[priv->chipset].RxConfigMask);
|
||||
|
||||
RTL_W32(priv, RxConfig, val);
|
||||
RTL_W32(priv, MAR0 + 0, mc_filter[0]);
|
||||
RTL_W32(priv, MAR0 + 4, mc_filter[1]);
|
||||
}
|
||||
|
||||
static void rtl8169_init_ring(struct rtl8169_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
priv->cur_rx = priv->cur_tx = 0;
|
||||
|
||||
priv->tx_desc = dma_alloc_coherent(NUM_TX_DESC *
|
||||
sizeof(struct bufdesc));
|
||||
priv->tx_buf = malloc(NUM_TX_DESC * PKT_BUF_SIZE);
|
||||
priv->rx_desc = dma_alloc_coherent(NUM_RX_DESC *
|
||||
sizeof(struct bufdesc));
|
||||
priv->rx_buf = malloc(NUM_RX_DESC * PKT_BUF_SIZE);
|
||||
dma_clean_range((unsigned long)priv->rx_buf,
|
||||
(unsigned long)priv->rx_buf + NUM_RX_DESC * PKT_BUF_SIZE);
|
||||
|
||||
memset(priv->tx_desc, 0, NUM_TX_DESC * sizeof(struct bufdesc));
|
||||
memset(priv->rx_desc, 0, NUM_RX_DESC * sizeof(struct bufdesc));
|
||||
|
||||
for (i = 0; i < NUM_RX_DESC; i++) {
|
||||
if (i == (NUM_RX_DESC - 1))
|
||||
priv->rx_desc[i].status =
|
||||
BD_STAT_OWN | BD_STAT_EOR | PKT_BUF_SIZE;
|
||||
else
|
||||
priv->rx_desc[i].status =
|
||||
BD_STAT_OWN | PKT_BUF_SIZE;
|
||||
|
||||
priv->rx_desc[i].buf_addr =
|
||||
virt_to_phys(priv->rx_buf + i * PKT_BUF_SIZE);
|
||||
}
|
||||
|
||||
dma_flush_range((unsigned long)priv->rx_desc,
|
||||
(unsigned long)priv->rx_desc +
|
||||
NUM_RX_DESC * sizeof(struct bufdesc));
|
||||
}
|
||||
|
||||
static void rtl8169_hw_start(struct rtl8169_priv *priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
|
||||
|
||||
/* RTL-8169sb/8110sb or previous version */
|
||||
if (priv->chipset <= 5)
|
||||
RTL_W8(priv, ChipCmd, CmdTxEnb | CmdRxEnb);
|
||||
|
||||
RTL_W8(priv, EarlyTxThres, 0x3f);
|
||||
|
||||
/* For gigabit rtl8169 */
|
||||
RTL_W16(priv, RxMaxSize, 0x800);
|
||||
|
||||
/* Set Rx Config register */
|
||||
val = rtl8169_rx_config | (RTL_R32(priv, RxConfig) &
|
||||
chip_info[priv->chipset].RxConfigMask);
|
||||
RTL_W32(priv, RxConfig, val);
|
||||
|
||||
/* Set DMA burst size and Interframe Gap Time */
|
||||
RTL_W32(priv, TxConfig, (6 << TxDMAShift) | (3 << TxInterFrameGapShift));
|
||||
|
||||
RTL_W32(priv, TxDescStartAddrLow, virt_to_phys(priv->tx_desc));
|
||||
RTL_W32(priv, TxDescStartAddrHigh, 0);
|
||||
RTL_W32(priv, RxDescStartAddrLow, virt_to_phys(priv->rx_desc));
|
||||
RTL_W32(priv, RxDescStartAddrHigh, 0);
|
||||
|
||||
/* RTL-8169sc/8110sc or later version */
|
||||
if (priv->chipset > 5)
|
||||
RTL_W8(priv, ChipCmd, CmdTxEnb | CmdRxEnb);
|
||||
|
||||
RTL_W8(priv, Cfg9346, Cfg9346_Lock);
|
||||
udelay(10);
|
||||
|
||||
RTL_W32(priv, RxMissed, 0);
|
||||
|
||||
__set_rx_mode(priv);
|
||||
|
||||
/* no early-rx interrupts */
|
||||
RTL_W16(priv, MultiIntr, RTL_R16(priv, MultiIntr) & 0xf000);
|
||||
}
|
||||
|
||||
static int rtl8169_eth_open(struct eth_device *edev)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
int ret;
|
||||
|
||||
rtl8169_init_ring(priv);
|
||||
rtl8169_hw_start(priv);
|
||||
|
||||
ret = phy_device_connect(edev, &priv->miibus, 0, NULL, 0,
|
||||
PHY_INTERFACE_MODE_NA);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl8169_phy_write(struct mii_bus *bus, int phy_addr,
|
||||
int reg, u16 val)
|
||||
{
|
||||
struct rtl8169_priv *priv = bus->priv;
|
||||
int i;
|
||||
|
||||
if (phy_addr != 0)
|
||||
return -1;
|
||||
|
||||
RTL_W32(priv, PHYAR, 0x80000000 | (reg & 0xff) << 16 | val);
|
||||
mdelay(1);
|
||||
|
||||
for (i = 2000; i > 0; i--) {
|
||||
if (!(RTL_R32(priv, PHYAR) & 0x80000000)) {
|
||||
return 0;
|
||||
} else {
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rtl8169_phy_read(struct mii_bus *bus, int phy_addr, int reg)
|
||||
{
|
||||
struct rtl8169_priv *priv = bus->priv;
|
||||
int i, val = 0xffff;
|
||||
|
||||
RTL_W32(priv, PHYAR, 0x0 | (reg & 0xff) << 16);
|
||||
mdelay(10);
|
||||
|
||||
if (phy_addr != 0)
|
||||
return val;
|
||||
|
||||
for (i = 2000; i > 0; i--) {
|
||||
if (RTL_R32(priv, PHYAR) & 0x80000000) {
|
||||
val = (int) (RTL_R32(priv, PHYAR) & 0xffff);
|
||||
break;
|
||||
} else {
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static int rtl8169_eth_send(struct eth_device *edev, void *packet,
|
||||
int packet_length)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
unsigned int entry;
|
||||
|
||||
entry = priv->cur_tx % NUM_TX_DESC;
|
||||
|
||||
if (packet_length < ETH_ZLEN)
|
||||
memset(priv->tx_buf + entry * PKT_BUF_SIZE, 0, ETH_ZLEN);
|
||||
memcpy(priv->tx_buf + entry * PKT_BUF_SIZE, packet, packet_length);
|
||||
dma_flush_range((unsigned long)priv->tx_buf + entry * PKT_BUF_SIZE,
|
||||
(unsigned long)priv->tx_buf + (entry + 1) * PKT_BUF_SIZE);
|
||||
|
||||
priv->tx_desc[entry].buf_Haddr = 0;
|
||||
priv->tx_desc[entry].buf_addr =
|
||||
virt_to_phys(priv->tx_buf + entry * PKT_BUF_SIZE);
|
||||
|
||||
if (entry != (NUM_TX_DESC - 1)) {
|
||||
priv->tx_desc[entry].status =
|
||||
BD_STAT_OWN | BD_STAT_FS | BD_STAT_LS |
|
||||
((packet_length > ETH_ZLEN) ? packet_length : ETH_ZLEN);
|
||||
} else {
|
||||
priv->tx_desc[entry].status =
|
||||
BD_STAT_OWN | BD_STAT_EOR | BD_STAT_FS | BD_STAT_LS |
|
||||
((packet_length > ETH_ZLEN) ? packet_length : ETH_ZLEN);
|
||||
}
|
||||
|
||||
dma_flush_range((unsigned long)&priv->tx_desc[entry],
|
||||
(unsigned long)&priv->tx_desc[entry + 1]);
|
||||
|
||||
RTL_W8(priv, TxPoll, 0x40);
|
||||
do {
|
||||
dma_inv_range((unsigned long)&priv->tx_desc[entry],
|
||||
(unsigned long)&priv->tx_desc[entry + 1]);
|
||||
} while (priv->tx_desc[entry].status & BD_STAT_OWN);
|
||||
|
||||
priv->cur_tx++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8169_eth_rx(struct eth_device *edev)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
unsigned int entry, pkt_size = 0;
|
||||
u8 status;
|
||||
|
||||
entry = priv->cur_rx % NUM_RX_DESC;
|
||||
|
||||
dma_inv_range((unsigned long)&priv->rx_desc[entry],
|
||||
(unsigned long)&priv->rx_desc[entry + 1]);
|
||||
|
||||
if ((priv->rx_desc[entry].status & BD_STAT_OWN) == 0) {
|
||||
if (!(priv->rx_desc[entry].status & BD_STAT_RX_RES)) {
|
||||
pkt_size = (priv->rx_desc[entry].status & 0x1fff) - 4;
|
||||
|
||||
dma_inv_range((unsigned long)priv->rx_buf
|
||||
+ entry * PKT_BUF_SIZE,
|
||||
(unsigned long)priv->rx_buf
|
||||
+ entry * PKT_BUF_SIZE + pkt_size);
|
||||
|
||||
net_receive(edev, priv->rx_buf + entry * PKT_BUF_SIZE,
|
||||
pkt_size);
|
||||
|
||||
/*
|
||||
* the buffer is going to be reused by HW, make sure to
|
||||
* clean out any potentially modified data
|
||||
*/
|
||||
dma_clean_range((unsigned long)priv->rx_buf
|
||||
+ entry * PKT_BUF_SIZE,
|
||||
(unsigned long)priv->rx_buf
|
||||
+ entry * PKT_BUF_SIZE + pkt_size);
|
||||
|
||||
if (entry == NUM_RX_DESC - 1)
|
||||
priv->rx_desc[entry].status = BD_STAT_OWN |
|
||||
BD_STAT_EOR | PKT_BUF_SIZE;
|
||||
else
|
||||
priv->rx_desc[entry].status =
|
||||
BD_STAT_OWN | PKT_BUF_SIZE;
|
||||
priv->rx_desc[entry].buf_addr =
|
||||
virt_to_phys(priv->rx_buf +
|
||||
entry * PKT_BUF_SIZE);
|
||||
|
||||
dma_flush_range((unsigned long)&priv->rx_desc[entry],
|
||||
(unsigned long)&priv->rx_desc[entry + 1]);
|
||||
} else {
|
||||
dev_err(&edev->dev, "rx error\n");
|
||||
}
|
||||
|
||||
priv->cur_rx++;
|
||||
|
||||
return pkt_size;
|
||||
|
||||
} else {
|
||||
status = RTL_R8(priv, IntrStatus);
|
||||
RTL_W8(priv, IntrStatus, status & ~(TxErr | RxErr | SYSErr));
|
||||
udelay(100); /* wait */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8169_get_ethaddr(struct eth_device *edev, unsigned char *m)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
m[i] = RTL_R8(priv, MAC0 + i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8169_set_ethaddr(struct eth_device *edev, unsigned char *mac_addr)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
int i;
|
||||
|
||||
RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
RTL_W8(priv, (MAC0 + i), mac_addr[i]);
|
||||
RTL_R8(priv, mac_addr[i]);
|
||||
}
|
||||
|
||||
RTL_W8(priv, Cfg9346, Cfg9346_Lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl8169_eth_halt(struct eth_device *edev)
|
||||
{
|
||||
struct rtl8169_priv *priv = edev->priv;
|
||||
|
||||
/* Stop the chip's Tx and Rx DMA processes. */
|
||||
RTL_W8(priv, ChipCmd, 0x00);
|
||||
|
||||
/* Disable interrupts by clearing the interrupt mask. */
|
||||
RTL_W16(priv, IntrMask, 0x0000);
|
||||
RTL_W32(priv, RxMissed, 0);
|
||||
|
||||
pci_clear_master(priv->pci_dev);
|
||||
}
|
||||
|
||||
static int rtl8169_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct device_d *dev = &pdev->dev;
|
||||
struct eth_device *edev;
|
||||
struct rtl8169_priv *priv;
|
||||
int ret;
|
||||
|
||||
/* enable pci device */
|
||||
pci_enable_device(pdev);
|
||||
|
||||
priv = xzalloc(sizeof(struct rtl8169_priv));
|
||||
|
||||
edev = &priv->edev;
|
||||
dev->type_data = edev;
|
||||
edev->priv = priv;
|
||||
|
||||
priv->pci_dev = pdev;
|
||||
|
||||
priv->miibus.read = rtl8169_phy_read;
|
||||
priv->miibus.write = rtl8169_phy_write;
|
||||
priv->miibus.priv = priv;
|
||||
priv->miibus.parent = &edev->dev;
|
||||
|
||||
priv->base = pci_iomap(pdev, pdev->device == 0x8168 ? 2 : 1);
|
||||
|
||||
dev_dbg(dev, "rtl%04x (rev %02x) (base=%p)\n",
|
||||
pdev->device, pdev->revision, priv->base);
|
||||
|
||||
edev->init = rtl8169_init_dev;
|
||||
edev->open = rtl8169_eth_open;
|
||||
edev->send = rtl8169_eth_send;
|
||||
edev->recv = rtl8169_eth_rx;
|
||||
edev->get_ethaddr = rtl8169_get_ethaddr;
|
||||
edev->set_ethaddr = rtl8169_set_ethaddr;
|
||||
edev->halt = rtl8169_eth_halt;
|
||||
edev->parent = dev;
|
||||
ret = eth_register(edev);
|
||||
if (ret)
|
||||
goto eth_err;
|
||||
|
||||
ret = mdiobus_register(&priv->miibus);
|
||||
if (ret)
|
||||
goto mdio_err;
|
||||
|
||||
return 0;
|
||||
|
||||
mdio_err:
|
||||
eth_unregister(edev);
|
||||
|
||||
eth_err:
|
||||
free(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct pci_driver rtl8169_eth_driver = {
|
||||
.name = "rtl8169_eth",
|
||||
.id_table = rtl8169_pci_tbl,
|
||||
.probe = rtl8169_probe,
|
||||
};
|
||||
|
||||
static int rtl8169_init(void)
|
||||
{
|
||||
return pci_register_driver(&rtl8169_eth_driver);
|
||||
}
|
||||
device_initcall(rtl8169_init);
|
|
@ -30,6 +30,7 @@ config OF_GPIO
|
|||
config OF_PCI
|
||||
bool
|
||||
depends on PCI
|
||||
select OF_ADDRESS_PCI
|
||||
help
|
||||
OpenFirmware PCI bus accessors
|
||||
|
||||
|
|
|
@ -179,6 +179,74 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
|
|||
}
|
||||
#endif /* CONFIG_OF_ADDRESS_PCI */
|
||||
|
||||
#ifdef CONFIG_OF_PCI
|
||||
int of_pci_range_parser_init(struct of_pci_range_parser *parser,
|
||||
struct device_node *node)
|
||||
{
|
||||
const int na = 3, ns = 2;
|
||||
int rlen;
|
||||
|
||||
parser->node = node;
|
||||
parser->pna = of_n_addr_cells(node);
|
||||
parser->np = parser->pna + na + ns;
|
||||
|
||||
parser->range = of_get_property(node, "ranges", &rlen);
|
||||
if (parser->range == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
parser->end = parser->range + rlen / sizeof(__be32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
|
||||
|
||||
struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
|
||||
struct of_pci_range *range)
|
||||
{
|
||||
const int na = 3, ns = 2;
|
||||
|
||||
if (!range)
|
||||
return NULL;
|
||||
|
||||
if (!parser->range || parser->range + parser->np > parser->end)
|
||||
return NULL;
|
||||
|
||||
range->pci_space = parser->range[0];
|
||||
range->flags = of_bus_pci_get_flags(parser->range);
|
||||
range->pci_addr = of_read_number(parser->range + 1, ns);
|
||||
range->cpu_addr = of_translate_address(parser->node,
|
||||
parser->range + na);
|
||||
range->size = of_read_number(parser->range + parser->pna + na, ns);
|
||||
|
||||
parser->range += parser->np;
|
||||
|
||||
/* Now consume following elements while they are contiguous */
|
||||
while (parser->range + parser->np <= parser->end) {
|
||||
u32 flags, pci_space;
|
||||
u64 pci_addr, cpu_addr, size;
|
||||
|
||||
pci_space = be32_to_cpup(parser->range);
|
||||
flags = of_bus_pci_get_flags(parser->range);
|
||||
pci_addr = of_read_number(parser->range + 1, ns);
|
||||
cpu_addr = of_translate_address(parser->node,
|
||||
parser->range + na);
|
||||
size = of_read_number(parser->range + parser->pna + na, ns);
|
||||
|
||||
if (flags != range->flags)
|
||||
break;
|
||||
if (pci_addr != range->pci_addr + range->size ||
|
||||
cpu_addr != range->cpu_addr + range->size)
|
||||
break;
|
||||
|
||||
range->size += size;
|
||||
parser->range += parser->np;
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
|
||||
#endif /* CONFIG_OF_PCI */
|
||||
|
||||
/*
|
||||
* Array of bus specific translators
|
||||
*/
|
||||
|
|
|
@ -30,6 +30,13 @@ config PCI_MVEBU
|
|||
select OF_PCI
|
||||
select PCI
|
||||
|
||||
config PCI_TEGRA
|
||||
bool "NVDIA Tegra PCIe driver"
|
||||
depends on ARCH_TEGRA
|
||||
select OF_ADDRESS_PCI
|
||||
select OF_PCI
|
||||
select PCI
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
|
|
@ -8,3 +8,4 @@ ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
|
|||
CPPFLAGS += $(ccflags-y)
|
||||
|
||||
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o
|
||||
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
|
||||
|
|
|
@ -86,7 +86,8 @@ int pci_register_device(struct pci_dev *pdev)
|
|||
struct device_d *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
strcpy(dev->name, "pci");
|
||||
snprintf(dev->name, MAX_DRIVER_NAME, "pci-%04x:%04x.",
|
||||
pdev->vendor, pdev->device);
|
||||
dev->bus = &pci_bus;
|
||||
dev->id = DEVICE_ID_DYNAMIC;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,6 +12,9 @@ static struct pci_controller *hose_head, **hose_tail = &hose_head;
|
|||
LIST_HEAD(pci_root_buses);
|
||||
EXPORT_SYMBOL(pci_root_buses);
|
||||
static u8 bus_index;
|
||||
static resource_size_t last_mem;
|
||||
static resource_size_t last_mem_pref;
|
||||
static resource_size_t last_io;
|
||||
|
||||
static struct pci_bus *pci_alloc_bus(void)
|
||||
{
|
||||
|
@ -37,14 +40,32 @@ void register_pci_controller(struct pci_controller *hose)
|
|||
|
||||
bus = pci_alloc_bus();
|
||||
hose->bus = bus;
|
||||
bus->parent = hose->parent;
|
||||
bus->host = hose;
|
||||
bus->ops = hose->pci_ops;
|
||||
bus->resource[0] = hose->mem_resource;
|
||||
bus->resource[1] = hose->io_resource;
|
||||
bus->resource[PCI_BUS_RESOURCE_MEM] = hose->mem_resource;
|
||||
bus->resource[PCI_BUS_RESOURCE_MEM_PREF] = hose->mem_pref_resource;
|
||||
bus->resource[PCI_BUS_RESOURCE_IO] = hose->io_resource;
|
||||
bus->number = bus_index++;
|
||||
|
||||
if (hose->set_busno)
|
||||
hose->set_busno(hose, bus->number);
|
||||
|
||||
if (bus->resource[PCI_BUS_RESOURCE_MEM])
|
||||
last_mem = bus->resource[PCI_BUS_RESOURCE_MEM]->start;
|
||||
else
|
||||
last_mem = 0;
|
||||
|
||||
if (bus->resource[PCI_BUS_RESOURCE_MEM])
|
||||
last_mem_pref = bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->start;
|
||||
else
|
||||
last_mem_pref = 0;
|
||||
|
||||
if (bus->resource[PCI_BUS_RESOURCE_IO])
|
||||
last_io = bus->resource[PCI_BUS_RESOURCE_IO]->start;
|
||||
else
|
||||
last_io = 0;
|
||||
|
||||
pci_scan_bus(bus);
|
||||
|
||||
list_add_tail(&bus->node, &pci_root_buses);
|
||||
|
@ -111,27 +132,162 @@ static struct pci_dev *alloc_pci_dev(void)
|
|||
return dev;
|
||||
}
|
||||
|
||||
static void setup_device(struct pci_dev *dev, int max_bar)
|
||||
{
|
||||
int bar, size;
|
||||
u32 mask;
|
||||
u8 cmd;
|
||||
|
||||
pci_read_config_byte(dev, PCI_COMMAND, &cmd);
|
||||
pci_write_config_byte(dev, PCI_COMMAND,
|
||||
cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
|
||||
|
||||
for (bar = 0; bar < max_bar; bar++) {
|
||||
resource_size_t last_addr;
|
||||
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
|
||||
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
|
||||
|
||||
if (mask == 0 || mask == 0xffffffff) {
|
||||
DBG(" PCI: pbar%d set bad mask\n", bar);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mask & 0x01) { /* IO */
|
||||
size = -(mask & 0xfffffffe);
|
||||
DBG(" PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
|
||||
if (last_io + size >
|
||||
dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
|
||||
DBG("BAR does not fit within bus IO res\n");
|
||||
return;
|
||||
}
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
|
||||
dev->resource[bar].flags = IORESOURCE_IO;
|
||||
last_addr = last_io;
|
||||
last_io += size;
|
||||
} else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
|
||||
last_mem_pref) /* prefetchable MEM */ {
|
||||
size = -(mask & 0xfffffff0);
|
||||
DBG(" PCI: pbar%d: mask=%08x P memory %d bytes\n",
|
||||
bar, mask, size);
|
||||
if (last_mem_pref + size >
|
||||
dev->bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->end) {
|
||||
DBG("BAR does not fit within bus p-mem res\n");
|
||||
return;
|
||||
}
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem_pref);
|
||||
dev->resource[bar].flags = IORESOURCE_MEM |
|
||||
IORESOURCE_PREFETCH;
|
||||
last_addr = last_mem_pref;
|
||||
last_mem_pref += size;
|
||||
} else { /* non-prefetch MEM */
|
||||
size = -(mask & 0xfffffff0);
|
||||
DBG(" PCI: pbar%d: mask=%08x NP memory %d bytes\n",
|
||||
bar, mask, size);
|
||||
if (last_mem + size >
|
||||
dev->bus->resource[PCI_BUS_RESOURCE_MEM]->end) {
|
||||
DBG("BAR does not fit within bus np-mem res\n");
|
||||
return;
|
||||
}
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
|
||||
dev->resource[bar].flags = IORESOURCE_MEM;
|
||||
last_addr = last_mem;
|
||||
last_mem += size;
|
||||
}
|
||||
|
||||
dev->resource[bar].start = last_addr;
|
||||
dev->resource[bar].end = last_addr + size - 1;
|
||||
|
||||
if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
||||
dev->resource[bar].flags |= IORESOURCE_MEM_64;
|
||||
pci_write_config_dword(dev,
|
||||
PCI_BASE_ADDRESS_1 + bar * 4, 0);
|
||||
bar++;
|
||||
}
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, PCI_COMMAND, cmd);
|
||||
list_add_tail(&dev->bus_list, &dev->bus->devices);
|
||||
}
|
||||
|
||||
static void prescan_setup_bridge(struct pci_dev *dev)
|
||||
{
|
||||
u16 cmdstat;
|
||||
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmdstat);
|
||||
|
||||
/* Configure bus number registers */
|
||||
pci_write_config_byte(dev, PCI_PRIMARY_BUS, dev->bus->number);
|
||||
pci_write_config_byte(dev, PCI_SECONDARY_BUS, dev->subordinate->number);
|
||||
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, 0xff);
|
||||
|
||||
if (last_mem) {
|
||||
/* Set up memory and I/O filter limits, assume 32-bit I/O space */
|
||||
pci_write_config_word(dev, PCI_MEMORY_BASE,
|
||||
(last_mem & 0xfff00000) >> 16);
|
||||
cmdstat |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
|
||||
if (last_mem_pref) {
|
||||
/* Set up memory and I/O filter limits, assume 32-bit I/O space */
|
||||
pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
|
||||
(last_mem_pref & 0xfff00000) >> 16);
|
||||
cmdstat |= PCI_COMMAND_MEMORY;
|
||||
} else {
|
||||
|
||||
/* We don't support prefetchable memory for now, so disable */
|
||||
pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, 0x1000);
|
||||
pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, 0x0);
|
||||
}
|
||||
|
||||
if (last_io) {
|
||||
pci_write_config_byte(dev, PCI_IO_BASE,
|
||||
(last_io & 0x0000f000) >> 8);
|
||||
pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
|
||||
(last_io & 0xffff0000) >> 16);
|
||||
cmdstat |= PCI_COMMAND_IO;
|
||||
}
|
||||
|
||||
/* Enable memory and I/O accesses, enable bus master */
|
||||
pci_write_config_word(dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER);
|
||||
}
|
||||
|
||||
static void postscan_setup_bridge(struct pci_dev *dev)
|
||||
{
|
||||
/* limit subordinate to last used bus number */
|
||||
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, bus_index - 1);
|
||||
|
||||
if (last_mem)
|
||||
pci_write_config_word(dev, PCI_MEMORY_LIMIT,
|
||||
((last_mem - 1) & 0xfff00000) >> 16);
|
||||
|
||||
if (last_mem_pref)
|
||||
pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
|
||||
((last_mem_pref - 1) & 0xfff00000) >> 16);
|
||||
|
||||
if (last_io) {
|
||||
pci_write_config_byte(dev, PCI_IO_LIMIT,
|
||||
((last_io - 1) & 0x0000f000) >> 8);
|
||||
pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
|
||||
((last_io - 1) & 0xffff0000) >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int pci_scan_bus(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct pci_bus *child_bus;
|
||||
unsigned int devfn, l, max, class;
|
||||
unsigned char cmd, tmp, hdr_type, is_multi = 0;
|
||||
struct pci_dev *dev;
|
||||
resource_size_t last_mem;
|
||||
resource_size_t last_io;
|
||||
|
||||
/* FIXME: use res_start() */
|
||||
last_mem = bus->resource[0]->start;
|
||||
last_io = bus->resource[1]->start;
|
||||
|
||||
DBG("pci_scan_bus for bus %d\n", bus->number);
|
||||
DBG(" last_io = 0x%08x, last_mem = 0x%08x\n", last_io, last_mem);
|
||||
DBG(" last_io = 0x%08x, last_mem = 0x%08x, last_mem_pref = 0x%08x\n",
|
||||
last_io, last_mem, last_mem_pref);
|
||||
|
||||
max = bus->secondary;
|
||||
|
||||
for (devfn = 0; devfn < 0xff; ++devfn) {
|
||||
int bar;
|
||||
u32 old_bar, mask;
|
||||
int size;
|
||||
|
||||
if (PCI_FUNC(devfn) && !is_multi) {
|
||||
/* not a multi-function device */
|
||||
continue;
|
||||
|
@ -154,6 +310,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
|
|||
dev->devfn = devfn;
|
||||
dev->vendor = l & 0xffff;
|
||||
dev->device = (l >> 16) & 0xffff;
|
||||
dev->dev.parent = bus->parent;
|
||||
|
||||
/* non-destructively determine if device can be a master: */
|
||||
pci_read_config_byte(dev, PCI_COMMAND, &cmd);
|
||||
|
@ -169,9 +326,11 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
|
|||
dev->hdr_type = hdr_type;
|
||||
|
||||
DBG("PCI: class = %08x, hdr_type = %08x\n", class, hdr_type);
|
||||
DBG("PCI: %02x:%02x [%04x:%04x]\n", bus->number, dev->devfn,
|
||||
dev->vendor, dev->device);
|
||||
|
||||
switch (hdr_type & 0x7f) { /* header type */
|
||||
case PCI_HEADER_TYPE_NORMAL: /* standard header */
|
||||
switch (hdr_type & 0x7f) {
|
||||
case PCI_HEADER_TYPE_NORMAL:
|
||||
if (class == PCI_CLASS_BRIDGE_PCI)
|
||||
goto bad;
|
||||
|
||||
|
@ -181,70 +340,48 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
|
|||
*/
|
||||
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &l);
|
||||
dev->rom_address = (l == 0xffffffff) ? 0 : l;
|
||||
|
||||
setup_device(dev, 6);
|
||||
break;
|
||||
default: /* unknown header */
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
setup_device(dev, 2);
|
||||
|
||||
child_bus = pci_alloc_bus();
|
||||
/* inherit parent properties */
|
||||
child_bus->host = bus->host;
|
||||
child_bus->ops = bus->host->pci_ops;
|
||||
child_bus->resource[PCI_BUS_RESOURCE_MEM] =
|
||||
bus->resource[PCI_BUS_RESOURCE_MEM];
|
||||
child_bus->resource[PCI_BUS_RESOURCE_MEM_PREF] =
|
||||
bus->resource[PCI_BUS_RESOURCE_MEM_PREF];
|
||||
child_bus->resource[PCI_BUS_RESOURCE_IO] =
|
||||
bus->resource[PCI_BUS_RESOURCE_IO];
|
||||
|
||||
child_bus->parent = &dev->dev;
|
||||
child_bus->number = bus_index++;
|
||||
list_add_tail(&child_bus->node, &bus->children);
|
||||
dev->subordinate = child_bus;
|
||||
|
||||
prescan_setup_bridge(dev);
|
||||
pci_scan_bus(child_bus);
|
||||
postscan_setup_bridge(dev);
|
||||
/* first activate bridge then all devices on it's bus */
|
||||
pci_register_device(dev);
|
||||
list_for_each_entry(dev, &child_bus->devices, bus_list)
|
||||
if (!dev->subordinate)
|
||||
pci_register_device(dev);
|
||||
break;
|
||||
default:
|
||||
bad:
|
||||
printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
|
||||
bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device);
|
||||
|
||||
if (class == PCI_CLASS_BRIDGE_HOST) {
|
||||
DBG("PCI: skip pci host bridge\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
pci_read_config_byte(dev, PCI_COMMAND, &cmd);
|
||||
pci_write_config_byte(dev, PCI_COMMAND,
|
||||
cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
|
||||
|
||||
for (bar = 0; bar < 6; bar++) {
|
||||
resource_size_t last_addr;
|
||||
|
||||
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &old_bar);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
|
||||
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, old_bar);
|
||||
|
||||
if (mask == 0 || mask == 0xffffffff) {
|
||||
DBG(" PCI: pbar%d set bad mask\n", bar);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mask & 0x01) { /* IO */
|
||||
size = -(mask & 0xfffffffe);
|
||||
DBG(" PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
|
||||
dev->resource[bar].flags = IORESOURCE_IO;
|
||||
last_addr = last_io;
|
||||
last_io += size;
|
||||
} else { /* MEM */
|
||||
size = -(mask & 0xfffffff0);
|
||||
DBG(" PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
|
||||
dev->resource[bar].flags = IORESOURCE_MEM;
|
||||
last_addr = last_mem;
|
||||
last_mem += size;
|
||||
|
||||
if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
||||
dev->resource[bar].flags |= IORESOURCE_MEM_64;
|
||||
pci_write_config_dword(dev,
|
||||
PCI_BASE_ADDRESS_1 + bar * 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
dev->resource[bar].start = last_addr;
|
||||
dev->resource[bar].end = last_addr + size - 1;
|
||||
if (dev->resource[bar].flags & IORESOURCE_MEM_64)
|
||||
bar++;
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, PCI_COMMAND, cmd);
|
||||
list_add_tail(&dev->bus_list, &bus->devices);
|
||||
pci_register_device(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -254,6 +391,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
|
|||
*
|
||||
* Return how far we've got finding sub-buses.
|
||||
*/
|
||||
max = bus_index;
|
||||
DBG("PCI: pci_scan_bus returning with max=%02x\n", max);
|
||||
|
||||
return max;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# PHY
|
||||
#
|
||||
|
||||
menu "PHY Subsystem"
|
||||
|
||||
config GENERIC_PHY
|
||||
bool "PHY Core"
|
||||
help
|
||||
Generic PHY support.
|
||||
|
||||
This framework is designed to provide a generic interface for PHY
|
||||
devices present in the kernel. This layer will have the generic
|
||||
API by which phy drivers can create PHY using the phy framework and
|
||||
phy users can obtain reference to the PHY. All the users of this
|
||||
framework should select this config.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for the phy drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* phy-core.c -- Generic Phy framework.
|
||||
*
|
||||
* Copyright (C) 2014 Lucas Stach <l.stach@pengutronix.de>
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <linux/phy/phy.h>
|
||||
|
||||
static LIST_HEAD(phy_provider_list);
|
||||
static int phy_ida;
|
||||
|
||||
/**
|
||||
* phy_create() - create a new phy
|
||||
* @dev: device that is creating the new phy
|
||||
* @node: device node of the phy
|
||||
* @ops: function pointers for performing phy operations
|
||||
* @init_data: contains the list of PHY consumers or NULL
|
||||
*
|
||||
* Called to create a phy using phy framework.
|
||||
*/
|
||||
struct phy *phy_create(struct device_d *dev, struct device_node *node,
|
||||
const struct phy_ops *ops,
|
||||
struct phy_init_data *init_data)
|
||||
{
|
||||
int ret;
|
||||
int id;
|
||||
struct phy *phy;
|
||||
|
||||
if (WARN_ON(!dev))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
phy = kzalloc(sizeof(*phy), GFP_KERNEL);
|
||||
if (!phy)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
id = phy_ida++;
|
||||
|
||||
snprintf(phy->dev.name, MAX_DRIVER_NAME, "phy");
|
||||
phy->dev.id = id;
|
||||
phy->dev.parent = dev;
|
||||
phy->dev.device_node = node ?: dev->device_node;
|
||||
phy->id = id;
|
||||
phy->ops = ops;
|
||||
phy->init_data = init_data;
|
||||
|
||||
ret = register_device(&phy->dev);
|
||||
if (ret)
|
||||
goto free_ida;
|
||||
|
||||
return phy;
|
||||
|
||||
free_ida:
|
||||
phy_ida--;
|
||||
kfree(phy);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* __of_phy_provider_register() - create/register phy provider with the framework
|
||||
* @dev: struct device of the phy provider
|
||||
* @owner: the module owner containing of_xlate
|
||||
* @of_xlate: function pointer to obtain phy instance from phy provider
|
||||
*
|
||||
* Creates struct phy_provider from dev and of_xlate function pointer.
|
||||
* This is used in the case of dt boot for finding the phy instance from
|
||||
* phy provider.
|
||||
*/
|
||||
struct phy_provider *__of_phy_provider_register(struct device_d *dev,
|
||||
struct phy * (*of_xlate)(struct device_d *dev,
|
||||
struct of_phandle_args *args))
|
||||
{
|
||||
struct phy_provider *phy_provider;
|
||||
|
||||
phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
|
||||
if (!phy_provider)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
phy_provider->dev = dev;
|
||||
phy_provider->of_xlate = of_xlate;
|
||||
|
||||
list_add_tail(&phy_provider->list, &phy_provider_list);
|
||||
|
||||
return phy_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_phy_provider_unregister() - unregister phy provider from the framework
|
||||
* @phy_provider: phy provider returned by of_phy_provider_register()
|
||||
*
|
||||
* Removes the phy_provider created using of_phy_provider_register().
|
||||
*/
|
||||
void of_phy_provider_unregister(struct phy_provider *phy_provider)
|
||||
{
|
||||
if (IS_ERR(phy_provider))
|
||||
return;
|
||||
|
||||
list_del(&phy_provider->list);
|
||||
kfree(phy_provider);
|
||||
}
|
||||
|
||||
int phy_init(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!phy)
|
||||
return 0;
|
||||
|
||||
if (phy->init_count == 0 && phy->ops->init) {
|
||||
ret = phy->ops->init(phy);
|
||||
if (ret < 0) {
|
||||
dev_err(&phy->dev, "phy init failed --> %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
++phy->init_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int phy_exit(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!phy)
|
||||
return 0;
|
||||
|
||||
if (phy->init_count == 1 && phy->ops->exit) {
|
||||
ret = phy->ops->exit(phy);
|
||||
if (ret < 0) {
|
||||
dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
--phy->init_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int phy_power_on(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!phy)
|
||||
return 0;
|
||||
|
||||
if (phy->pwr) {
|
||||
ret = regulator_enable(phy->pwr);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (phy->power_count == 0 && phy->ops->power_on) {
|
||||
ret = phy->ops->power_on(phy);
|
||||
if (ret < 0) {
|
||||
dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
ret = 0; /* Override possible ret == -ENOTSUPP */
|
||||
}
|
||||
++phy->power_count;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (phy->pwr)
|
||||
regulator_disable(phy->pwr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int phy_power_off(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!phy)
|
||||
return 0;
|
||||
|
||||
if (phy->power_count == 1 && phy->ops->power_off) {
|
||||
ret = phy->ops->power_off(phy);
|
||||
if (ret < 0) {
|
||||
dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
--phy->power_count;
|
||||
|
||||
if (phy->pwr)
|
||||
regulator_disable(phy->pwr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
|
||||
{
|
||||
struct phy_provider *phy_provider;
|
||||
struct device_node *child;
|
||||
|
||||
list_for_each_entry(phy_provider, &phy_provider_list, list) {
|
||||
if (phy_provider->dev->device_node == node)
|
||||
return phy_provider;
|
||||
|
||||
for_each_child_of_node(phy_provider->dev->device_node, child)
|
||||
if (child == node)
|
||||
return phy_provider;
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
/**
|
||||
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
|
||||
* @np: device_node for which to get the phy
|
||||
* @index: the index of the phy
|
||||
*
|
||||
* Returns the phy associated with the given phandle value,
|
||||
* after getting a refcount to it or -ENODEV if there is no such phy or
|
||||
* -EPROBE_DEFER if there is a phandle to the phy, but the device is
|
||||
* not yet loaded. This function uses of_xlate call back function provided
|
||||
* while registering the phy_provider to find the phy instance.
|
||||
*/
|
||||
static struct phy *_of_phy_get(struct device_node *np, int index)
|
||||
{
|
||||
int ret;
|
||||
struct phy_provider *phy_provider;
|
||||
struct of_phandle_args args;
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "phys", "#phy-cells",
|
||||
index, &args);
|
||||
if (ret)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
phy_provider = of_phy_provider_lookup(args.np);
|
||||
if (IS_ERR(phy_provider)) {
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
return phy_provider->of_xlate(phy_provider->dev, &args);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_phy_get() - lookup and obtain a reference to a phy using a device_node.
|
||||
* @np: device_node for which to get the phy
|
||||
* @con_id: name of the phy from device's point of view
|
||||
*
|
||||
* Returns the phy driver, after getting a refcount to it; or
|
||||
* -ENODEV if there is no such phy. The caller is responsible for
|
||||
* calling phy_put() to release that count.
|
||||
*/
|
||||
struct phy *of_phy_get(struct device_node *np, const char *con_id)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (con_id)
|
||||
index = of_property_match_string(np, "phy-names", con_id);
|
||||
|
||||
return _of_phy_get(np, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_get() - lookup and obtain a reference to a phy.
|
||||
* @dev: device that requests this phy
|
||||
* @string: the phy name as given in the dt data or the name of the controller
|
||||
* port for non-dt case
|
||||
*
|
||||
* Returns the phy driver, after getting a refcount to it; or
|
||||
* -ENODEV if there is no such phy. The caller is responsible for
|
||||
* calling phy_put() to release that count.
|
||||
*/
|
||||
struct phy *phy_get(struct device_d *dev, const char *string)
|
||||
{
|
||||
int index = 0;
|
||||
struct phy *phy = ERR_PTR(-ENODEV);
|
||||
|
||||
if (string == NULL) {
|
||||
dev_warn(dev, "missing string\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (dev->device_node) {
|
||||
index = of_property_match_string(dev->device_node, "phy-names",
|
||||
string);
|
||||
phy = _of_phy_get(dev->device_node, index);
|
||||
}
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_optional_get() - lookup and obtain a reference to an optional phy.
|
||||
* @dev: device that requests this phy
|
||||
* @string: the phy name as given in the dt data or the name of the controller
|
||||
* port for non-dt case
|
||||
*
|
||||
* Returns the phy driver, after getting a refcount to it; or
|
||||
* NULL if there is no such phy. The caller is responsible for
|
||||
* calling phy_put() to release that count.
|
||||
*/
|
||||
struct phy *phy_optional_get(struct device_d *dev, const char *string)
|
||||
{
|
||||
struct phy *phy = phy_get(dev, string);
|
||||
|
||||
if (PTR_ERR(phy) == -ENODEV)
|
||||
phy = NULL;
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
|
@ -60,6 +60,14 @@ config PINCTRL_TEGRA30
|
|||
help
|
||||
The pinmux controller found on the Tegra 30+ line of SoCs.
|
||||
|
||||
config PINCTRL_TEGRA_XUSB
|
||||
bool
|
||||
default y if ARCH_TEGRA_124_SOC
|
||||
select GENERIC_PHY
|
||||
help
|
||||
The pinmux controller found on the Tegra 124 line of SoCs used for
|
||||
the SerDes lanes.
|
||||
|
||||
source drivers/pinctrl/mvebu/Kconfig
|
||||
|
||||
endif
|
||||
|
|
|
@ -7,5 +7,6 @@ obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
|||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
|
||||
|
||||
obj-$(CONFIG_ARCH_MVEBU) += mvebu/
|
||||
|
|
|
@ -0,0 +1,519 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Lucas Stach <l.stach@pengutronix.de>
|
||||
*
|
||||
* Partly based on code
|
||||
* Copyright (C) 2014, 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 <common.h>
|
||||
#include <clock.h>
|
||||
#include <init.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
#include <pinctrl.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/phy/phy.h>
|
||||
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
|
||||
|
||||
#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
|
||||
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
|
||||
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
|
||||
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
|
||||
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
|
||||
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
|
||||
|
||||
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
|
||||
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
|
||||
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
|
||||
|
||||
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
|
||||
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
|
||||
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
|
||||
|
||||
struct tegra_xusb_padctl_soc {
|
||||
const struct tegra_xusb_padctl_lane *lanes;
|
||||
unsigned int num_lanes;
|
||||
};
|
||||
|
||||
struct tegra_xusb_padctl_lane {
|
||||
const char *name;
|
||||
|
||||
unsigned int offset;
|
||||
unsigned int shift;
|
||||
unsigned int mask;
|
||||
unsigned int iddq;
|
||||
|
||||
const char **funcs;
|
||||
unsigned int num_funcs;
|
||||
};
|
||||
|
||||
struct tegra_xusb_padctl {
|
||||
struct device_d *dev;
|
||||
void __iomem *regs;
|
||||
struct reset_control *rst;
|
||||
|
||||
const struct tegra_xusb_padctl_soc *soc;
|
||||
struct pinctrl_device pinctrl;
|
||||
|
||||
struct phy_provider *provider;
|
||||
struct phy *phys[2];
|
||||
|
||||
unsigned int enable;
|
||||
};
|
||||
|
||||
static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
|
||||
unsigned long offset)
|
||||
{
|
||||
writel(value, padctl->regs + offset);
|
||||
}
|
||||
|
||||
static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
|
||||
unsigned long offset)
|
||||
{
|
||||
return readl(padctl->regs + offset);
|
||||
}
|
||||
|
||||
static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (padctl->enable++ > 0)
|
||||
return 0;
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
|
||||
udelay(100);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
|
||||
udelay(100);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (WARN_ON(padctl->enable == 0))
|
||||
return 0;
|
||||
|
||||
if (--padctl->enable > 0)
|
||||
return 0;
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
|
||||
udelay(100);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
|
||||
udelay(100);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_xusb_phy_init(struct phy *phy)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
|
||||
|
||||
return tegra_xusb_padctl_enable(padctl);
|
||||
}
|
||||
|
||||
static int tegra_xusb_phy_exit(struct phy *phy)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
|
||||
|
||||
return tegra_xusb_padctl_disable(padctl);
|
||||
}
|
||||
|
||||
static int pcie_phy_power_on(struct phy *phy)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
|
||||
int err;
|
||||
u32 value;
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
||||
value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
|
||||
value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
|
||||
XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
|
||||
XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
||||
value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
||||
|
||||
err = wait_on_timeout(50 * MSECOND,
|
||||
padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1) &
|
||||
XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int pcie_phy_power_off(struct phy *phy)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
|
||||
u32 value;
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
||||
value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops pcie_phy_ops = {
|
||||
|
||||
.init = tegra_xusb_phy_init,
|
||||
.exit = tegra_xusb_phy_exit,
|
||||
.power_on = pcie_phy_power_on,
|
||||
.power_off = pcie_phy_power_off,
|
||||
};
|
||||
|
||||
static int sata_phy_power_on(struct phy *phy)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
|
||||
int err;
|
||||
u32 value;
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
|
||||
value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
|
||||
value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
|
||||
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
|
||||
err = wait_on_timeout(50 * MSECOND,
|
||||
padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1) &
|
||||
XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sata_phy_power_off(struct phy *phy)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
|
||||
u32 value;
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
|
||||
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
|
||||
|
||||
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
|
||||
value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
|
||||
value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
|
||||
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops sata_phy_ops = {
|
||||
|
||||
.init = tegra_xusb_phy_init,
|
||||
.exit = tegra_xusb_phy_exit,
|
||||
.power_on = sata_phy_power_on,
|
||||
.power_off = sata_phy_power_off,
|
||||
};
|
||||
|
||||
static struct phy *tegra_xusb_padctl_xlate(struct device_d *dev,
|
||||
struct of_phandle_args *args)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = dev->priv;
|
||||
unsigned int index = args->args[0];
|
||||
|
||||
if (args->args_count <= 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (index >= ARRAY_SIZE(padctl->phys))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return padctl->phys[index];
|
||||
}
|
||||
|
||||
static int pinctrl_tegra_xusb_set_state(struct pinctrl_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl =
|
||||
container_of(pdev, struct tegra_xusb_padctl, pinctrl);
|
||||
struct device_node *childnode;
|
||||
int iddq = -1, i, j, k;
|
||||
const char *lanes, *func = NULL;
|
||||
const struct tegra_xusb_padctl_lane *lane = NULL;
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* At first look if the node we are pointed at has children,
|
||||
* which we may want to visit.
|
||||
*/
|
||||
list_for_each_entry(childnode, &np->children, parent_list)
|
||||
pinctrl_tegra_xusb_set_state(pdev, childnode);
|
||||
|
||||
/* read relevant state from devicetree */
|
||||
of_property_read_string(np, "nvidia,function", &func);
|
||||
of_property_read_u32_array(np, "nvidia,iddq", &iddq, 1);
|
||||
|
||||
/* iterate over all lanes referenced in the dt node */
|
||||
for (i = 0; ; i++) {
|
||||
if (of_property_read_string_index(np, "nvidia,lanes", i, &lanes))
|
||||
break;
|
||||
|
||||
for (j = 0; j < padctl->soc->num_lanes; j++) {
|
||||
if (!strcmp(lanes, padctl->soc->lanes[j].name)) {
|
||||
lane = &padctl->soc->lanes[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* if no matching lane is found */
|
||||
if (j == padctl->soc->num_lanes) {
|
||||
/* nothing matching found, warn and bail out */
|
||||
dev_warn(padctl->pinctrl.dev,
|
||||
"invalid lane %s referenced in node %s\n",
|
||||
lanes, np->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (func) {
|
||||
for (k = 0; k < lane->num_funcs; k++) {
|
||||
if (!strcmp(func, lane->funcs[k]))
|
||||
break;
|
||||
}
|
||||
if (k < lane->num_funcs) {
|
||||
val = padctl_readl(padctl, lane->offset);
|
||||
val &= ~(lane->mask << lane->shift);
|
||||
val |= k << lane->shift;
|
||||
padctl_writel(padctl, val, lane->offset);
|
||||
} else {
|
||||
dev_warn(padctl->pinctrl.dev,
|
||||
"invalid function %s for lane %s in node %s\n",
|
||||
func, lane->name, np->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (iddq >= 0) {
|
||||
if (lane->iddq) {
|
||||
val = padctl_readl(padctl, lane->offset);
|
||||
if (iddq)
|
||||
val &= ~BIT(lane->iddq);
|
||||
else
|
||||
val |= BIT(lane->iddq);
|
||||
padctl_writel(padctl, val, lane->offset);
|
||||
} else {
|
||||
dev_warn(padctl->pinctrl.dev,
|
||||
"invalid iddq setting for lane %s in node %s\n",
|
||||
lane->name, np->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinctrl_ops pinctrl_tegra_xusb_ops = {
|
||||
.set_state = pinctrl_tegra_xusb_set_state,
|
||||
};
|
||||
|
||||
static int pinctrl_tegra_xusb_probe(struct device_d *dev)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl;
|
||||
struct phy *phy;
|
||||
int err;
|
||||
|
||||
padctl = xzalloc(sizeof(*padctl));
|
||||
|
||||
dev->priv = padctl;
|
||||
padctl->dev = dev;
|
||||
|
||||
dev_get_drvdata(dev, (unsigned long *)&padctl->soc);
|
||||
|
||||
padctl->regs = dev_request_mem_region(dev, 0);
|
||||
if (IS_ERR(padctl->regs)) {
|
||||
dev_err(dev, "Could not get iomem region\n");
|
||||
return PTR_ERR(padctl->regs);
|
||||
}
|
||||
|
||||
padctl->rst = reset_control_get(dev, NULL);
|
||||
if (IS_ERR(padctl->rst))
|
||||
return PTR_ERR(padctl->rst);
|
||||
|
||||
err = reset_control_deassert(padctl->rst);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
padctl->pinctrl.dev = dev;
|
||||
padctl->pinctrl.ops = &pinctrl_tegra_xusb_ops;
|
||||
|
||||
err = pinctrl_register(&padctl->pinctrl);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to register pincontrol\n");
|
||||
err = -ENODEV;
|
||||
goto reset;
|
||||
}
|
||||
|
||||
phy = phy_create(dev, NULL, &pcie_phy_ops, NULL);
|
||||
if (IS_ERR(phy)) {
|
||||
err = PTR_ERR(phy);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
|
||||
phy_set_drvdata(phy, padctl);
|
||||
|
||||
phy = phy_create(dev, NULL, &sata_phy_ops, NULL);
|
||||
if (IS_ERR(phy)) {
|
||||
err = PTR_ERR(phy);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
|
||||
phy_set_drvdata(phy, padctl);
|
||||
|
||||
padctl->provider = of_phy_provider_register(dev, tegra_xusb_padctl_xlate);
|
||||
if (IS_ERR(padctl->provider)) {
|
||||
err = PTR_ERR(padctl->provider);
|
||||
dev_err(dev, "failed to register PHYs: %d\n", err);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unregister:
|
||||
pinctrl_unregister(&padctl->pinctrl);
|
||||
reset:
|
||||
reset_control_assert(padctl->rst);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const char *tegra124_otg_functions[] = {
|
||||
"snps",
|
||||
"xusb",
|
||||
"uart",
|
||||
"rsvd",
|
||||
};
|
||||
|
||||
static const char *tegra124_usb_functions[] = {
|
||||
"snps",
|
||||
"xusb",
|
||||
};
|
||||
|
||||
static const char *tegra124_pci_functions[] = {
|
||||
"pcie",
|
||||
"usb3",
|
||||
"sata",
|
||||
"rsvd",
|
||||
};
|
||||
|
||||
#define TEGRA124_LANE(_name, _offs, _shift, _mask, _iddq, _funcs, _num) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.offset = _offs, \
|
||||
.shift = _shift, \
|
||||
.mask = _mask, \
|
||||
.iddq = _iddq, \
|
||||
.num_funcs = _num, \
|
||||
.funcs = tegra124_##_funcs##_functions, \
|
||||
}
|
||||
|
||||
static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
|
||||
TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg, 4),
|
||||
TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg, 4),
|
||||
TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg, 4),
|
||||
TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb, 2),
|
||||
TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb, 2),
|
||||
TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb, 2),
|
||||
TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci, 4),
|
||||
TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci, 4),
|
||||
TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci, 4),
|
||||
TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci, 4),
|
||||
TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci, 4),
|
||||
TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci, 4),
|
||||
};
|
||||
|
||||
static const struct tegra_xusb_padctl_soc tegra124_soc = {
|
||||
.num_lanes = ARRAY_SIZE(tegra124_lanes),
|
||||
.lanes = tegra124_lanes,
|
||||
};
|
||||
|
||||
static __maybe_unused struct of_device_id pinctrl_tegra_xusb_dt_ids[] = {
|
||||
{
|
||||
.compatible = "nvidia,tegra124-xusb-padctl",
|
||||
.data = (unsigned long)&tegra124_soc,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct driver_d pinctrl_tegra_xusb_driver = {
|
||||
.name = "pinctrl-tegra-xusb",
|
||||
.probe = pinctrl_tegra_xusb_probe,
|
||||
.of_compatible = DRV_OF_COMPAT(pinctrl_tegra_xusb_dt_ids),
|
||||
};
|
||||
|
||||
static int pinctrl_tegra_xusb_init(void)
|
||||
{
|
||||
return platform_driver_register(&pinctrl_tegra_xusb_driver);
|
||||
}
|
||||
postcore_initcall(pinctrl_tegra_xusb_init);
|
|
@ -320,10 +320,14 @@ static int pinctrl_tegra20_probe(struct device_d *dev)
|
|||
ctrl->pinctrl.ops = &pinctrl_tegra20_ops;
|
||||
|
||||
ret = pinctrl_register(&ctrl->pinctrl);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
free(ctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
of_pinctrl_select_state(dev->device_node, "boot");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused struct of_device_id pinctrl_tegra20_dt_ids[] = {
|
||||
|
|
|
@ -897,10 +897,14 @@ static int pinctrl_tegra30_probe(struct device_d *dev)
|
|||
ctrl->pinctrl.ops = &pinctrl_tegra30_ops;
|
||||
|
||||
ret = pinctrl_register(&ctrl->pinctrl);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
free(ctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
of_pinctrl_select_state(dev->device_node, "boot");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused struct of_device_id pinctrl_tegra30_dt_ids[] = {
|
||||
|
|
|
@ -311,6 +311,11 @@ static __maybe_unused struct ns16550_drvdata jz_drvdata = {
|
|||
.init_port = ns16550_jz_init_port,
|
||||
};
|
||||
|
||||
static __maybe_unused struct ns16550_drvdata tegra_drvdata = {
|
||||
.init_port = ns16550_serial_init_port,
|
||||
.linux_console_name = "ttyS",
|
||||
};
|
||||
|
||||
static int ns16550_init_iomem(struct device_d *dev, struct ns16550_priv *priv)
|
||||
{
|
||||
struct resource *res;
|
||||
|
@ -418,6 +423,7 @@ static int ns16550_probe(struct device_d *dev)
|
|||
ret = PTR_ERR(priv->clk);
|
||||
goto err;
|
||||
}
|
||||
clk_enable(priv->clk);
|
||||
priv->plat.clock = clk_get_rate(priv->clk);
|
||||
}
|
||||
|
||||
|
@ -476,6 +482,12 @@ static struct of_device_id ns16550_serial_dt_ids[] = {
|
|||
.data = (unsigned long)&omap_drvdata,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA)
|
||||
{
|
||||
.compatible = "nvidia,tegra20-uart",
|
||||
.data = (unsigned long)&tegra_drvdata,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MACH_MIPS_XBURST)
|
||||
{
|
||||
.compatible = "ingenic,jz4740-uart",
|
||||
|
|
|
@ -114,8 +114,15 @@ struct pci_dev {
|
|||
};
|
||||
#define to_pci_dev(dev) container_of(dev, struct pci_dev, dev)
|
||||
|
||||
enum {
|
||||
PCI_BUS_RESOURCE_IO = 0,
|
||||
PCI_BUS_RESOURCE_MEM = 1,
|
||||
PCI_BUS_RESOURCE_MEM_PREF = 2,
|
||||
PCI_BUS_RESOURCE_BUSN = 3,
|
||||
};
|
||||
struct pci_bus {
|
||||
struct pci_controller *host; /* associated host controller */
|
||||
struct device_d *parent;
|
||||
struct list_head node; /* node in list of buses */
|
||||
struct list_head children; /* list of child buses */
|
||||
struct list_head devices; /* list of devices on this bus */
|
||||
|
@ -152,10 +159,12 @@ extern struct pci_ops *pci_ops;
|
|||
*/
|
||||
struct pci_controller {
|
||||
struct pci_controller *next;
|
||||
struct device_d *parent;
|
||||
struct pci_bus *bus;
|
||||
|
||||
struct pci_ops *pci_ops;
|
||||
struct resource *mem_resource;
|
||||
struct resource *mem_pref_resource;
|
||||
unsigned long mem_offset;
|
||||
struct resource *io_resource;
|
||||
unsigned long io_offset;
|
||||
|
|
|
@ -107,4 +107,32 @@
|
|||
#define PCI_ROM_ADDRESS_ENABLE 0x01
|
||||
#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
|
||||
|
||||
/* Header type 1 (PCI-to-PCI bridges) */
|
||||
#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
|
||||
#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
|
||||
#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
|
||||
#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
|
||||
#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
|
||||
#define PCI_IO_LIMIT 0x1d
|
||||
#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
|
||||
#define PCI_IO_RANGE_TYPE_16 0x00
|
||||
#define PCI_IO_RANGE_TYPE_32 0x01
|
||||
#define PCI_IO_RANGE_MASK (~0x0fUL) /* Standard 4K I/O windows */
|
||||
#define PCI_IO_1K_RANGE_MASK (~0x03UL) /* Intel 1K I/O windows */
|
||||
#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
|
||||
#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
|
||||
#define PCI_MEMORY_LIMIT 0x22
|
||||
#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
|
||||
#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
|
||||
#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
|
||||
#define PCI_PREF_MEMORY_LIMIT 0x26
|
||||
#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
|
||||
#define PCI_PREF_RANGE_TYPE_32 0x00
|
||||
#define PCI_PREF_RANGE_TYPE_64 0x01
|
||||
#define PCI_PREF_RANGE_MASK (~0x0fUL)
|
||||
#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
|
||||
#define PCI_PREF_LIMIT_UPPER32 0x2c
|
||||
#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
|
||||
#define PCI_IO_LIMIT_UPPER16 0x32
|
||||
|
||||
#endif /* LINUX_PCI_REGS_H */
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* phy.h -- generic phy header file
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_PHY_H
|
||||
#define __DRIVERS_PHY_H
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <of.h>
|
||||
#include <regulator.h>
|
||||
|
||||
struct phy;
|
||||
|
||||
/**
|
||||
* struct phy_ops - set of function pointers for performing phy operations
|
||||
* @init: operation to be performed for initializing phy
|
||||
* @exit: operation to be performed while exiting
|
||||
* @power_on: powering on the phy
|
||||
* @power_off: powering off the phy
|
||||
* @owner: the module owner containing the ops
|
||||
*/
|
||||
struct phy_ops {
|
||||
int (*init)(struct phy *phy);
|
||||
int (*exit)(struct phy *phy);
|
||||
int (*power_on)(struct phy *phy);
|
||||
int (*power_off)(struct phy *phy);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct phy_attrs - represents phy attributes
|
||||
* @bus_width: Data path width implemented by PHY
|
||||
*/
|
||||
struct phy_attrs {
|
||||
u32 bus_width;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct phy - represents the phy device
|
||||
* @dev: phy device
|
||||
* @id: id of the phy device
|
||||
* @ops: function pointers for performing phy operations
|
||||
* @init_data: list of PHY consumers (non-dt only)
|
||||
* @mutex: mutex to protect phy_ops
|
||||
* @init_count: used to protect when the PHY is used by multiple consumers
|
||||
* @power_count: used to protect when the PHY is used by multiple consumers
|
||||
* @phy_attrs: used to specify PHY specific attributes
|
||||
*/
|
||||
struct phy {
|
||||
struct device_d dev;
|
||||
int id;
|
||||
const struct phy_ops *ops;
|
||||
struct phy_init_data *init_data;
|
||||
int init_count;
|
||||
int power_count;
|
||||
struct phy_attrs attrs;
|
||||
struct regulator *pwr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct phy_provider - represents the phy provider
|
||||
* @dev: phy provider device
|
||||
* @owner: the module owner having of_xlate
|
||||
* @of_xlate: function pointer to obtain phy instance from phy pointer
|
||||
* @list: to maintain a linked list of PHY providers
|
||||
*/
|
||||
struct phy_provider {
|
||||
struct device_d *dev;
|
||||
struct list_head list;
|
||||
struct phy * (*of_xlate)(struct device_d *dev,
|
||||
struct of_phandle_args *args);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct phy_consumer - represents the phy consumer
|
||||
* @dev_name: the device name of the controller that will use this PHY device
|
||||
* @port: name given to the consumer port
|
||||
*/
|
||||
struct phy_consumer {
|
||||
const char *dev_name;
|
||||
const char *port;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct phy_init_data - contains the list of PHY consumers
|
||||
* @num_consumers: number of consumers for this PHY device
|
||||
* @consumers: list of PHY consumers
|
||||
*/
|
||||
struct phy_init_data {
|
||||
unsigned int num_consumers;
|
||||
struct phy_consumer *consumers;
|
||||
};
|
||||
|
||||
#define PHY_CONSUMER(_dev_name, _port) \
|
||||
{ \
|
||||
.dev_name = _dev_name, \
|
||||
.port = _port, \
|
||||
}
|
||||
|
||||
#define to_phy(dev) (container_of((dev), struct phy, dev))
|
||||
|
||||
#define of_phy_provider_register(dev, xlate) \
|
||||
__of_phy_provider_register((dev), (xlate))
|
||||
|
||||
|
||||
static inline void phy_set_drvdata(struct phy *phy, void *data)
|
||||
{
|
||||
phy->dev.priv = data;
|
||||
}
|
||||
|
||||
static inline void *phy_get_drvdata(struct phy *phy)
|
||||
{
|
||||
return phy->dev.priv;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_GENERIC_PHY)
|
||||
int phy_init(struct phy *phy);
|
||||
int phy_exit(struct phy *phy);
|
||||
int phy_power_on(struct phy *phy);
|
||||
int phy_power_off(struct phy *phy);
|
||||
static inline int phy_get_bus_width(struct phy *phy)
|
||||
{
|
||||
return phy->attrs.bus_width;
|
||||
}
|
||||
static inline void phy_set_bus_width(struct phy *phy, int bus_width)
|
||||
{
|
||||
phy->attrs.bus_width = bus_width;
|
||||
}
|
||||
struct phy *phy_get(struct device_d *dev, const char *string);
|
||||
struct phy *phy_optional_get(struct device_d *dev, const char *string);
|
||||
void phy_put(struct phy *phy);
|
||||
struct phy *of_phy_get(struct device_node *np, const char *con_id);
|
||||
struct phy *of_phy_simple_xlate(struct device_d *dev,
|
||||
struct of_phandle_args *args);
|
||||
struct phy *phy_create(struct device_d *dev, struct device_node *node,
|
||||
const struct phy_ops *ops,
|
||||
struct phy_init_data *init_data);
|
||||
void phy_destroy(struct phy *phy);
|
||||
struct phy_provider *__of_phy_provider_register(struct device_d *dev,
|
||||
struct phy * (*of_xlate)(struct device_d *dev,
|
||||
struct of_phandle_args *args));
|
||||
void of_phy_provider_unregister(struct phy_provider *phy_provider);
|
||||
#else
|
||||
static inline int phy_init(struct phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return 0;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int phy_exit(struct phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return 0;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int phy_power_on(struct phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return 0;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int phy_power_off(struct phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return 0;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int phy_get_bus_width(struct phy *phy)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void phy_set_bus_width(struct phy *phy, int bus_width)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline struct phy *phy_get(struct device_d *dev, const char *string)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct phy *phy_optional_get(struct device_d *dev,
|
||||
const char *string)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void phy_put(struct phy *phy)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct phy *of_phy_get(struct device_node *np, const char *con_id)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct phy *of_phy_simple_xlate(struct device_d *dev,
|
||||
struct of_phandle_args *args)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct phy *phy_create(struct device_d *dev,
|
||||
struct device_node *node,
|
||||
const struct phy_ops *ops,
|
||||
struct phy_init_data *init_data)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void phy_destroy(struct phy *phy)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct phy_provider *__of_phy_provider_register(
|
||||
struct device_d *dev, struct phy * (*of_xlate)(
|
||||
struct device_d *dev, struct of_phandle_args *args))
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void of_phy_provider_unregister(struct phy_provider *phy_provider)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVERS_PHY_H */
|
|
@ -4,6 +4,38 @@
|
|||
#include <common.h>
|
||||
#include <of.h>
|
||||
|
||||
struct of_pci_range_parser {
|
||||
struct device_node *node;
|
||||
const __be32 *range;
|
||||
const __be32 *end;
|
||||
int np;
|
||||
int pna;
|
||||
};
|
||||
|
||||
struct of_pci_range {
|
||||
u32 pci_space;
|
||||
u64 pci_addr;
|
||||
u64 cpu_addr;
|
||||
u64 size;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
#define for_each_of_pci_range(parser, range) \
|
||||
for (; of_pci_range_parser_one(parser, range);)
|
||||
|
||||
static inline void of_pci_range_to_resource(struct of_pci_range *range,
|
||||
struct device_node *np,
|
||||
struct resource *res)
|
||||
{
|
||||
res->flags = range->flags;
|
||||
res->start = range->cpu_addr;
|
||||
res->end = range->cpu_addr + range->size - 1;
|
||||
res->parent = NULL;
|
||||
INIT_LIST_HEAD(&res->children);
|
||||
INIT_LIST_HEAD(&res->sibling);
|
||||
res->name = np->full_name;
|
||||
}
|
||||
|
||||
#ifndef pci_address_to_pio
|
||||
static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
|
||||
#endif
|
||||
|
@ -69,4 +101,29 @@ static inline void __iomem *of_iomap(struct device_node *np, int index)
|
|||
|
||||
#endif /* CONFIG_OFTREE */
|
||||
|
||||
#ifdef CONFIG_OF_PCI
|
||||
|
||||
extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
|
||||
struct device_node *node);
|
||||
|
||||
extern struct of_pci_range *of_pci_range_parser_one(
|
||||
struct of_pci_range_parser *parser,
|
||||
struct of_pci_range *range);
|
||||
|
||||
#else
|
||||
|
||||
static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
|
||||
struct device_node *node)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline struct of_pci_range *of_pci_range_parser_one(
|
||||
struct of_pci_range_parser *parser,
|
||||
struct of_pci_range *range)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_OF_PCI */
|
||||
|
||||
#endif /* __OF_ADDRESS_H */
|
||||
|
|
|
@ -20,6 +20,7 @@ enum reset_src_type {
|
|||
RESET_WDG, /* watchdog */
|
||||
RESET_WKE, /* wake-up (some SoCs can handle this) */
|
||||
RESET_JTAG, /* JTAG reset */
|
||||
RESET_THERM, /* SoC shut down because of overtemperature */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RESET_SOURCE
|
||||
|
|
Loading…
Reference in New Issue