diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3c9b81a..2a00e5e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -198,6 +198,7 @@ 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 diff --git a/arch/arm/boards/nvidia-beaver/board.c b/arch/arm/boards/nvidia-beaver/board.c index e87594d..d270301 100644 --- a/arch/arm/boards/nvidia-beaver/board.c +++ b/arch/arm/boards/nvidia-beaver/board.c @@ -15,10 +15,12 @@ */ #include -#include +#include +#include #include +#include -static int nvidia_beaver_devices_init(void) +static int nvidia_beaver_fs_init(void) { struct i2c_client client; u8 data; @@ -33,6 +35,24 @@ 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); diff --git a/arch/arm/boards/nvidia-jetson-tk1/Makefile b/arch/arm/boards/nvidia-jetson-tk1/Makefile index f1e4620..16b203f 100644 --- a/arch/arm/boards/nvidia-jetson-tk1/Makefile +++ b/arch/arm/boards/nvidia-jetson-tk1/Makefile @@ -3,5 +3,5 @@ -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 diff --git a/arch/arm/boards/nvidia-jetson-tk1/board.c b/arch/arm/boards/nvidia-jetson-tk1/board.c new file mode 100644 index 0000000..564e6a0 --- /dev/null +++ b/arch/arm/boards/nvidia-jetson-tk1/board.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014 Lucas Stach + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#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); diff --git a/arch/arm/boards/toradex-colibri-t20/Makefile b/arch/arm/boards/toradex-colibri-t20/Makefile index 1f76732..d0347f2 100644 --- a/arch/arm/boards/toradex-colibri-t20/Makefile +++ b/arch/arm/boards/toradex-colibri-t20/Makefile @@ -3,6 +3,7 @@ -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 \ No newline at end of file diff --git a/arch/arm/boards/toradex-colibri-t20/board.c b/arch/arm/boards/toradex-colibri-t20/board.c new file mode 100644 index 0000000..7061981 --- /dev/null +++ b/arch/arm/boards/toradex-colibri-t20/board.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 Lucas Stach + * + * 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 . + */ + +#include +#include + +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); diff --git a/arch/arm/configs/tegra_v7_defconfig b/arch/arm/configs/tegra_v7_defconfig index 22f5765..47e594b 100644 --- a/arch/arm/configs/tegra_v7_defconfig +++ b/arch/arm/configs/tegra_v7_defconfig @@ -16,6 +16,7 @@ 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_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 diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts index 16082c0..26f405c 100644 --- a/arch/arm/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/dts/tegra124-jetson-tk1.dts @@ -1,1828 +1,17 @@ -/dts-v1/; - -#include +#include #include "tegra124.dtsi" / { - model = "NVIDIA Tegra124 Jetson TK1"; - compatible = "nvidia,jetson-tk1", "nvidia,tegra124"; + chosen { + stdout-path = "/serial@0,70006300/"; - aliases { - rtc0 = "/i2c@0,7000d000/pmic@40"; - rtc1 = "/rtc@0,7000e000"; - }; - - memory { - reg = <0x0 0x80000000 0x0 0x80000000>; - }; - - host1x@0,50000000 { - hdmi@0,54280000 { - status = "okay"; - - hdmi-supply = <&vdd_5v0_hdmi>; - pll-supply = <&vdd_hdmi_pll>; - vdd-supply = <&vdd_3v3_hdmi>; - - nvidia,ddc-i2c-bus = <&hdmi_ddc>; - nvidia,hpd-gpio = - <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + environment@0 { + compatible = "barebox,environment"; + device-path = &emmc, "partname:boot1"; }; }; - pinmux: pinmux@0,70000868 { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: pinmux { - clk_32k_out_pa0 { - nvidia,pins = "clk_32k_out_pa0"; - nvidia,function = "soc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart3_cts_n_pa1 { - nvidia,pins = "uart3_cts_n_pa1"; - nvidia,function = "uartc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap2_fs_pa2 { - nvidia,pins = "dap2_fs_pa2"; - nvidia,function = "i2s1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap2_sclk_pa3 { - nvidia,pins = "dap2_sclk_pa3"; - nvidia,function = "i2s1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap2_din_pa4 { - nvidia,pins = "dap2_din_pa4"; - nvidia,function = "i2s1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap2_dout_pa5 { - nvidia,pins = "dap2_dout_pa5"; - nvidia,function = "i2s1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_clk_pa6 { - nvidia,pins = "sdmmc3_clk_pa6"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_cmd_pa7 { - nvidia,pins = "sdmmc3_cmd_pa7"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pb0 { - nvidia,pins = "pb0"; - nvidia,function = "uartd"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pb1 { - nvidia,pins = "pb1"; - nvidia,function = "uartd"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_dat3_pb4 { - nvidia,pins = "sdmmc3_dat3_pb4"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_dat2_pb5 { - nvidia,pins = "sdmmc3_dat2_pb5"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_dat1_pb6 { - nvidia,pins = "sdmmc3_dat1_pb6"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_dat0_pb7 { - nvidia,pins = "sdmmc3_dat0_pb7"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart3_rts_n_pc0 { - nvidia,pins = "uart3_rts_n_pc0"; - nvidia,function = "uartc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart2_txd_pc2 { - nvidia,pins = "uart2_txd_pc2"; - nvidia,function = "irda"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart2_rxd_pc3 { - nvidia,pins = "uart2_rxd_pc3"; - nvidia,function = "irda"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gen1_i2c_scl_pc4 { - nvidia,pins = "gen1_i2c_scl_pc4"; - nvidia,function = "i2c1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - gen1_i2c_sda_pc5 { - nvidia,pins = "gen1_i2c_sda_pc5"; - nvidia,function = "i2c1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - pc7 { - nvidia,pins = "pc7"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg0 { - nvidia,pins = "pg0"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg1 { - nvidia,pins = "pg1"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg2 { - nvidia,pins = "pg2"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg3 { - nvidia,pins = "pg3"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg4 { - nvidia,pins = "pg4"; - nvidia,function = "spi4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg5 { - nvidia,pins = "pg5"; - nvidia,function = "spi4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg6 { - nvidia,pins = "pg6"; - nvidia,function = "spi4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pg7 { - nvidia,pins = "pg7"; - nvidia,function = "spi4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph0 { - nvidia,pins = "ph0"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph1 { - nvidia,pins = "ph1"; - nvidia,function = "pwm1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph2 { - nvidia,pins = "ph2"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph3 { - nvidia,pins = "ph3"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph4 { - nvidia,pins = "ph4"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph5 { - nvidia,pins = "ph5"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph6 { - nvidia,pins = "ph6"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ph7 { - nvidia,pins = "ph7"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi0 { - nvidia,pins = "pi0"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi1 { - nvidia,pins = "pi1"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi2 { - nvidia,pins = "pi2"; - nvidia,function = "rsvd4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi3 { - nvidia,pins = "pi3"; - nvidia,function = "spi4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi4 { - nvidia,pins = "pi4"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi5 { - nvidia,pins = "pi5"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi6 { - nvidia,pins = "pi6"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pi7 { - nvidia,pins = "pi7"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pj0 { - nvidia,pins = "pj0"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pj2 { - nvidia,pins = "pj2"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart2_cts_n_pj5 { - nvidia,pins = "uart2_cts_n_pj5"; - nvidia,function = "uartb"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart2_rts_n_pj6 { - nvidia,pins = "uart2_rts_n_pj6"; - nvidia,function = "uartb"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pj7 { - nvidia,pins = "pj7"; - nvidia,function = "uartd"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pk0 { - nvidia,pins = "pk0"; - nvidia,function = "soc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pk1 { - nvidia,pins = "pk1"; - nvidia,function = "rsvd4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pk2 { - nvidia,pins = "pk2"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pk3 { - nvidia,pins = "pk3"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pk4 { - nvidia,pins = "pk4"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - spdif_out_pk5 { - nvidia,pins = "spdif_out_pk5"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - spdif_in_pk6 { - nvidia,pins = "spdif_in_pk6"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pk7 { - nvidia,pins = "pk7"; - nvidia,function = "uartd"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap1_fs_pn0 { - nvidia,pins = "dap1_fs_pn0"; - nvidia,function = "i2s0"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap1_din_pn1 { - nvidia,pins = "dap1_din_pn1"; - nvidia,function = "i2s0"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap1_dout_pn2 { - nvidia,pins = "dap1_dout_pn2"; - nvidia,function = "sata"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap1_sclk_pn3 { - nvidia,pins = "dap1_sclk_pn3"; - nvidia,function = "i2s0"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - usb_vbus_en0_pn4 { - nvidia,pins = "usb_vbus_en0_pn4"; - nvidia,function = "usb"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - usb_vbus_en1_pn5 { - nvidia,pins = "usb_vbus_en1_pn5"; - nvidia,function = "usb"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - hdmi_int_pn7 { - nvidia,pins = "hdmi_int_pn7"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,rcv-sel = ; - }; - ulpi_data7_po0 { - nvidia,pins = "ulpi_data7_po0"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data0_po1 { - nvidia,pins = "ulpi_data0_po1"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data1_po2 { - nvidia,pins = "ulpi_data1_po2"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data2_po3 { - nvidia,pins = "ulpi_data2_po3"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data3_po4 { - nvidia,pins = "ulpi_data3_po4"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data4_po5 { - nvidia,pins = "ulpi_data4_po5"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data5_po6 { - nvidia,pins = "ulpi_data5_po6"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_data6_po7 { - nvidia,pins = "ulpi_data6_po7"; - nvidia,function = "ulpi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap3_fs_pp0 { - nvidia,pins = "dap3_fs_pp0"; - nvidia,function = "i2s2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap3_din_pp1 { - nvidia,pins = "dap3_din_pp1"; - nvidia,function = "i2s2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap3_dout_pp2 { - nvidia,pins = "dap3_dout_pp2"; - nvidia,function = "rsvd4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap3_sclk_pp3 { - nvidia,pins = "dap3_sclk_pp3"; - nvidia,function = "rsvd3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap4_fs_pp4 { - nvidia,pins = "dap4_fs_pp4"; - nvidia,function = "i2s3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap4_din_pp5 { - nvidia,pins = "dap4_din_pp5"; - nvidia,function = "i2s3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap4_dout_pp6 { - nvidia,pins = "dap4_dout_pp6"; - nvidia,function = "i2s3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap4_sclk_pp7 { - nvidia,pins = "dap4_sclk_pp7"; - nvidia,function = "i2s3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col0_pq0 { - nvidia,pins = "kb_col0_pq0"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col1_pq1 { - nvidia,pins = "kb_col1_pq1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col2_pq2 { - nvidia,pins = "kb_col2_pq2"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col3_pq3 { - nvidia,pins = "kb_col3_pq3"; - nvidia,function = "kbc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col4_pq4 { - nvidia,pins = "kb_col4_pq4"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col5_pq5 { - nvidia,pins = "kb_col5_pq5"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col6_pq6 { - nvidia,pins = "kb_col6_pq6"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_col7_pq7 { - nvidia,pins = "kb_col7_pq7"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row0_pr0 { - nvidia,pins = "kb_row0_pr0"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row1_pr1 { - nvidia,pins = "kb_row1_pr1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row2_pr2 { - nvidia,pins = "kb_row2_pr2"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row3_pr3 { - nvidia,pins = "kb_row3_pr3"; - nvidia,function = "sys"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row4_pr4 { - nvidia,pins = "kb_row4_pr4"; - nvidia,function = "rsvd3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row5_pr5 { - nvidia,pins = "kb_row5_pr5"; - nvidia,function = "rsvd3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row6_pr6 { - nvidia,pins = "kb_row6_pr6"; - nvidia,function = "displaya_alt"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row7_pr7 { - nvidia,pins = "kb_row7_pr7"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row8_ps0 { - nvidia,pins = "kb_row8_ps0"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row9_ps1 { - nvidia,pins = "kb_row9_ps1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row10_ps2 { - nvidia,pins = "kb_row10_ps2"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row11_ps3 { - nvidia,pins = "kb_row11_ps3"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row12_ps4 { - nvidia,pins = "kb_row12_ps4"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row13_ps5 { - nvidia,pins = "kb_row13_ps5"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row14_ps6 { - nvidia,pins = "kb_row14_ps6"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row15_ps7 { - nvidia,pins = "kb_row15_ps7"; - nvidia,function = "soc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row16_pt0 { - nvidia,pins = "kb_row16_pt0"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - kb_row17_pt1 { - nvidia,pins = "kb_row17_pt1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gen2_i2c_scl_pt5 { - nvidia,pins = "gen2_i2c_scl_pt5"; - nvidia,function = "i2c2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - gen2_i2c_sda_pt6 { - nvidia,pins = "gen2_i2c_sda_pt6"; - nvidia,function = "i2c2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - sdmmc4_cmd_pt7 { - nvidia,pins = "sdmmc4_cmd_pt7"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu0 { - nvidia,pins = "pu0"; - nvidia,function = "rsvd4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu1 { - nvidia,pins = "pu1"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu2 { - nvidia,pins = "pu2"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu3 { - nvidia,pins = "pu3"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu4 { - nvidia,pins = "pu4"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu5 { - nvidia,pins = "pu5"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pu6 { - nvidia,pins = "pu6"; - nvidia,function = "rsvd3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pv0 { - nvidia,pins = "pv0"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pv1 { - nvidia,pins = "pv1"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_cd_n_pv2 { - nvidia,pins = "sdmmc3_cd_n_pv2"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_wp_n_pv3 { - nvidia,pins = "sdmmc1_wp_n_pv3"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ddc_scl_pv4 { - nvidia,pins = "ddc_scl_pv4"; - nvidia,function = "i2c4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,rcv-sel = ; - }; - ddc_sda_pv5 { - nvidia,pins = "ddc_sda_pv5"; - nvidia,function = "i2c4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,rcv-sel = ; - }; - gpio_w2_aud_pw2 { - nvidia,pins = "gpio_w2_aud_pw2"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_w3_aud_pw3 { - nvidia,pins = "gpio_w3_aud_pw3"; - nvidia,function = "spi6"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap_mclk1_pw4 { - nvidia,pins = "dap_mclk1_pw4"; - nvidia,function = "extperiph1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - clk2_out_pw5 { - nvidia,pins = "clk2_out_pw5"; - nvidia,function = "extperiph2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart3_txd_pw6 { - nvidia,pins = "uart3_txd_pw6"; - nvidia,function = "uartc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - uart3_rxd_pw7 { - nvidia,pins = "uart3_rxd_pw7"; - nvidia,function = "uartc"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dvfs_pwm_px0 { - nvidia,pins = "dvfs_pwm_px0"; - nvidia,function = "cldvfs"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_x1_aud_px1 { - nvidia,pins = "gpio_x1_aud_px1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dvfs_clk_px2 { - nvidia,pins = "dvfs_clk_px2"; - nvidia,function = "cldvfs"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_x3_aud_px3 { - nvidia,pins = "gpio_x3_aud_px3"; - nvidia,function = "rsvd4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_x4_aud_px4 { - nvidia,pins = "gpio_x4_aud_px4"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_x5_aud_px5 { - nvidia,pins = "gpio_x5_aud_px5"; - nvidia,function = "rsvd4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_x6_aud_px6 { - nvidia,pins = "gpio_x6_aud_px6"; - nvidia,function = "gmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - gpio_x7_aud_px7 { - nvidia,pins = "gpio_x7_aud_px7"; - nvidia,function = "rsvd1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_clk_py0 { - nvidia,pins = "ulpi_clk_py0"; - nvidia,function = "spi1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_dir_py1 { - nvidia,pins = "ulpi_dir_py1"; - nvidia,function = "spi1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_nxt_py2 { - nvidia,pins = "ulpi_nxt_py2"; - nvidia,function = "spi1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - ulpi_stp_py3 { - nvidia,pins = "ulpi_stp_py3"; - nvidia,function = "spi1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_dat3_py4 { - nvidia,pins = "sdmmc1_dat3_py4"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_dat2_py5 { - nvidia,pins = "sdmmc1_dat2_py5"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_dat1_py6 { - nvidia,pins = "sdmmc1_dat1_py6"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_dat0_py7 { - nvidia,pins = "sdmmc1_dat0_py7"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_clk_pz0 { - nvidia,pins = "sdmmc1_clk_pz0"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc1_cmd_pz1 { - nvidia,pins = "sdmmc1_cmd_pz1"; - nvidia,function = "sdmmc1"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pwr_i2c_scl_pz6 { - nvidia,pins = "pwr_i2c_scl_pz6"; - nvidia,function = "i2cpwr"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - pwr_i2c_sda_pz7 { - nvidia,pins = "pwr_i2c_sda_pz7"; - nvidia,function = "i2cpwr"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - sdmmc4_dat0_paa0 { - nvidia,pins = "sdmmc4_dat0_paa0"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat1_paa1 { - nvidia,pins = "sdmmc4_dat1_paa1"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat2_paa2 { - nvidia,pins = "sdmmc4_dat2_paa2"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat3_paa3 { - nvidia,pins = "sdmmc4_dat3_paa3"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat4_paa4 { - nvidia,pins = "sdmmc4_dat4_paa4"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat5_paa5 { - nvidia,pins = "sdmmc4_dat5_paa5"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat6_paa6 { - nvidia,pins = "sdmmc4_dat6_paa6"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_dat7_paa7 { - nvidia,pins = "sdmmc4_dat7_paa7"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pbb0 { - nvidia,pins = "pbb0"; - nvidia,function = "vimclk2_alt"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - cam_i2c_scl_pbb1 { - nvidia,pins = "cam_i2c_scl_pbb1"; - nvidia,function = "i2c3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - cam_i2c_sda_pbb2 { - nvidia,pins = "cam_i2c_sda_pbb2"; - nvidia,function = "i2c3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - pbb3 { - nvidia,pins = "pbb3"; - nvidia,function = "vgp3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pbb4 { - nvidia,pins = "pbb4"; - nvidia,function = "vgp4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pbb5 { - nvidia,pins = "pbb5"; - nvidia,function = "rsvd3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pbb6 { - nvidia,pins = "pbb6"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pbb7 { - nvidia,pins = "pbb7"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - cam_mclk_pcc0 { - nvidia,pins = "cam_mclk_pcc0"; - nvidia,function = "vi_alt3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pcc1 { - nvidia,pins = "pcc1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pcc2 { - nvidia,pins = "pcc2"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc4_clk_pcc4 { - nvidia,pins = "sdmmc4_clk_pcc4"; - nvidia,function = "sdmmc4"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - clk2_req_pcc5 { - nvidia,pins = "clk2_req_pcc5"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - clk3_out_pee0 { - nvidia,pins = "clk3_out_pee0"; - nvidia,function = "extperiph3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - clk3_req_pee1 { - nvidia,pins = "clk3_req_pee1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dap_mclk1_req_pee2 { - nvidia,pins = "dap_mclk1_req_pee2"; - nvidia,function = "sata"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - hdmi_cec_pee3 { - nvidia,pins = "hdmi_cec_pee3"; - nvidia,function = "cec"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - sdmmc3_clk_lb_out_pee4 { - nvidia,pins = "sdmmc3_clk_lb_out_pee4"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - sdmmc3_clk_lb_in_pee5 { - nvidia,pins = "sdmmc3_clk_lb_in_pee5"; - nvidia,function = "sdmmc3"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - dp_hpd_pff0 { - nvidia,pins = "dp_hpd_pff0"; - nvidia,function = "dp"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - usb_vbus_en2_pff1 { - nvidia,pins = "usb_vbus_en2_pff1"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - pff2 { - nvidia,pins = "pff2"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,open-drain = ; - }; - core_pwr_req { - nvidia,pins = "core_pwr_req"; - nvidia,function = "pwron"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - cpu_pwr_req { - nvidia,pins = "cpu_pwr_req"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - pwr_int_n { - nvidia,pins = "pwr_int_n"; - nvidia,function = "pmi"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - reset_out_n { - nvidia,pins = "reset_out_n"; - nvidia,function = "reset_out_n"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - owr { - nvidia,pins = "owr"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,rcv-sel = ; - }; - clk_32k_in { - nvidia,pins = "clk_32k_in"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - jtag_rtck { - nvidia,pins = "jtag_rtck"; - nvidia,function = "rtck"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - }; - }; - }; - - /* DB9 serial port */ - serial@0,70006300 { - status = "okay"; - }; - - /* Expansion GEN1_I2C_*, mini-PCIe I2C, on-board components */ - i2c@0,7000c000 { - status = "okay"; - clock-frequency = <100000>; - - rt5639: audio-codec@1c { - compatible = "realtek,rt5639"; - reg = <0x1c>; - interrupt-parent = <&gpio>; - interrupts = ; - realtek,ldo1-en-gpios = - <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_HIGH>; - }; - - temperature-sensor@4c { - compatible = "ti,tmp451"; - reg = <0x4c>; - interrupt-parent = <&gpio>; - interrupts = ; - }; - - eeprom@56 { - compatible = "atmel,24c02"; - reg = <0x56>; - pagesize = <8>; - }; - }; - - /* Expansion GEN2_I2C_* */ - i2c@0,7000c400 { - status = "okay"; - clock-frequency = <100000>; - }; - - /* Expansion CAM_I2C_* */ - i2c@0,7000c500 { - status = "okay"; - clock-frequency = <100000>; - }; - - /* HDMI DDC */ - hdmi_ddc: i2c@0,7000c700 { - status = "okay"; - clock-frequency = <100000>; - }; - - /* Expansion PWR_I2C_*, on-board components */ - i2c@0,7000d000 { - status = "okay"; - clock-frequency = <400000>; - - pmic: pmic@40 { - compatible = "ams,as3722"; - reg = <0x40>; - interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>; - - ams,system-power-controller; - - #interrupt-cells = <2>; - interrupt-controller; - - gpio-controller; - #gpio-cells = <2>; - - pinctrl-names = "default"; - pinctrl-0 = <&as3722_default>; - - as3722_default: pinmux { - gpio0 { - pins = "gpio0"; - function = "gpio"; - bias-pull-down; - }; - - gpio1_2_4_7 { - pins = "gpio1", "gpio2", "gpio4", "gpio7"; - function = "gpio"; - bias-pull-up; - }; - - gpio3_5_6 { - pins = "gpio3", "gpio5", "gpio6"; - bias-high-impedance; - }; - }; - - regulators { - vsup-sd2-supply = <&vdd_5v0_sys>; - vsup-sd3-supply = <&vdd_5v0_sys>; - vsup-sd4-supply = <&vdd_5v0_sys>; - vsup-sd5-supply = <&vdd_5v0_sys>; - vin-ldo0-supply = <&vdd_1v35_lp0>; - vin-ldo1-6-supply = <&vdd_3v3_run>; - vin-ldo2-5-7-supply = <&vddio_1v8>; - vin-ldo3-4-supply = <&vdd_3v3_sys>; - vin-ldo9-10-supply = <&vdd_5v0_sys>; - vin-ldo11-supply = <&vdd_3v3_run>; - - sd0 { - regulator-name = "+VDD_CPU_AP"; - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <1400000>; - regulator-min-microamp = <3500000>; - regulator-max-microamp = <3500000>; - regulator-always-on; - regulator-boot-on; - ams,external-control = <2>; - }; - - sd1 { - regulator-name = "+VDD_CORE"; - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <1350000>; - regulator-min-microamp = <2500000>; - regulator-max-microamp = <2500000>; - regulator-always-on; - regulator-boot-on; - ams,external-control = <1>; - }; - - vdd_1v35_lp0: sd2 { - regulator-name = "+1.35V_LP0(sd2)"; - regulator-min-microvolt = <1350000>; - regulator-max-microvolt = <1350000>; - regulator-always-on; - regulator-boot-on; - }; - - sd3 { - regulator-name = "+1.35V_LP0(sd3)"; - regulator-min-microvolt = <1350000>; - regulator-max-microvolt = <1350000>; - regulator-always-on; - regulator-boot-on; - }; - - vdd_1v05_run: sd4 { - regulator-name = "+1.05V_RUN"; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1050000>; - }; - - vddio_1v8: sd5 { - regulator-name = "+1.8V_VDDIO"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - sd6 { - regulator-name = "+VDD_GPU_AP"; - regulator-min-microvolt = <650000>; - regulator-max-microvolt = <1200000>; - regulator-min-microamp = <3500000>; - regulator-max-microamp = <3500000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo0 { - regulator-name = "+1.05V_RUN_AVDD"; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1050000>; - regulator-boot-on; - regulator-always-on; - ams,external-control = <1>; - }; - - ldo1 { - regulator-name = "+1.8V_RUN_CAM"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - ldo2 { - regulator-name = "+1.2V_GEN_AVDD"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo3 { - regulator-name = "+1.05V_LP0_VDD_RTC"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-boot-on; - regulator-always-on; - ams,enable-tracking; - }; - - ldo4 { - regulator-name = "+2.8V_RUN_CAM"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - }; - - ldo5 { - regulator-name = "+1.2V_RUN_CAM_FRONT"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - vddio_sdmmc3: ldo6 { - regulator-name = "+VDDIO_SDMMC3"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - ldo7 { - regulator-name = "+1.05V_RUN_CAM_REAR"; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1050000>; - }; - - ldo9 { - regulator-name = "+3.3V_RUN_TOUCH"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - }; - - ldo10 { - regulator-name = "+2.8V_RUN_CAM_AF"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - }; - - ldo11 { - regulator-name = "+1.8V_RUN_VPP_FUSE"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - }; - }; - }; - - /* Expansion TS_SPI_* */ - spi@0,7000d400 { - status = "okay"; - }; - - /* Internal SPI */ - spi@0,7000da00 { - status = "okay"; - spi-max-frequency = <25000000>; - spi-flash@0 { - compatible = "winbond,w25q32dw"; - reg = <0>; - spi-max-frequency = <20000000>; - }; - }; - - pmc@0,7000e400 { - nvidia,invert-interrupt; - nvidia,suspend-mode = <1>; - nvidia,cpu-pwr-good-time = <500>; - nvidia,cpu-pwr-off-time = <300>; - nvidia,core-pwr-good-time = <641 3845>; - nvidia,core-pwr-off-time = <61036>; - nvidia,core-power-req-active-high; - nvidia,sys-clock-req-active-high; - }; - - /* SD card */ - sdhci@0,700b0400 { - status = "okay"; - cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; - power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>; - wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_HIGH>; - bus-width = <4>; - vqmmc-supply = <&vddio_sdmmc3>; - }; - /* eMMC */ - sdhci@0,700b0600 { - status = "okay"; - bus-width = <8>; - non-removable; - }; - - ahub@0,70300000 { - i2s@0,70301100 { - status = "okay"; - }; - }; - - /* mini-PCIe USB */ - usb@0,7d004000 { - status = "okay"; - }; - - usb-phy@0,7d004000 { - status = "okay"; - }; - - /* USB A connector */ - usb@0,7d008000 { - status = "okay"; - }; - - usb-phy@0,7d008000 { - status = "okay"; - vbus-supply = <&vdd_usb3_vbus>; - }; - - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - clk32k_in: clock@0 { - compatible = "fixed-clock"; - reg = <0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - - power { - label = "Power"; - gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; - linux,code = ; - debounce-interval = <10>; - gpio-key,wakeup; - }; - }; - - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - vdd_mux: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "+VDD_MUX"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - regulator-always-on; - regulator-boot-on; - }; - - vdd_5v0_sys: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "+5V_SYS"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vdd_mux>; - }; - - vdd_3v3_sys: regulator@2 { - compatible = "regulator-fixed"; - reg = <2>; - regulator-name = "+3.3V_SYS"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vdd_mux>; - }; - - vdd_3v3_run: regulator@3 { - compatible = "regulator-fixed"; - reg = <3>; - regulator-name = "+3.3V_RUN"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - gpio = <&pmic 1 GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&vdd_3v3_sys>; - }; - - vdd_3v3_hdmi: regulator@4 { - compatible = "regulator-fixed"; - reg = <4>; - regulator-name = "+3.3V_AVDD_HDMI_AP_GATED"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vdd_3v3_run>; - }; - - vdd_usb1_vbus: regulator@7 { - compatible = "regulator-fixed"; - reg = <7>; - regulator-name = "+USB0_VBUS_SW"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>; - enable-active-high; - gpio-open-drain; - vin-supply = <&vdd_5v0_sys>; - }; - - vdd_usb3_vbus: regulator@8 { - compatible = "regulator-fixed"; - reg = <8>; - regulator-name = "+5V_USB_HS"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>; - enable-active-high; - gpio-open-drain; - vin-supply = <&vdd_5v0_sys>; - }; - - vdd_3v3_lp0: regulator@10 { - compatible = "regulator-fixed"; - reg = <10>; - regulator-name = "+3.3V_LP0"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - gpio = <&pmic 2 GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&vdd_3v3_sys>; - }; - - vdd_hdmi_pll: regulator@11 { - compatible = "regulator-fixed"; - reg = <11>; - regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL"; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1050000>; - gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>; - vin-supply = <&vdd_1v05_run>; - }; - - vdd_5v0_hdmi: regulator@12 { - compatible = "regulator-fixed"; - reg = <12>; - regulator-name = "+5V_HDMI_CON"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&vdd_5v0_sys>; - }; - }; - - sound { - compatible = "nvidia,tegra-audio-rt5640-jetson-tk1", - "nvidia,tegra-audio-rt5640"; - nvidia,model = "NVIDIA Tegra Jetson TK1"; - - nvidia,audio-routing = - "Headphones", "HPOR", - "Headphones", "HPOL", - "Mic Jack", "MICBIAS1", - "IN2P", "Mic Jack"; - - nvidia,i2s-controller = <&tegra_i2s1>; - nvidia,audio-codec = <&rt5639>; - - nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_LOW>; - - clocks = <&tegra_car TEGRA124_CLK_PLL_A>, - <&tegra_car TEGRA124_CLK_PLL_A_OUT0>, - <&tegra_car TEGRA124_CLK_EXTERN1>; - clock-names = "pll_a", "pll_a_out0", "mclk"; + emmc: sdhci@0,700b0600 { }; }; diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi index 7d0fafa..c795811 100644 --- a/arch/arm/dts/tegra124.dtsi +++ b/arch/arm/dts/tegra124.dtsi @@ -1 +1,8 @@ -#include +/ { + aliases { + serial0 = "/serial@0,70006000/"; + serial1 = "/serial@0,70006040/"; + serial2 = "/serial@0,70006200/"; + serial3 = "/serial@0,70006300/"; + }; +}; diff --git a/arch/arm/dts/tegra20-colibri-iris.dts b/arch/arm/dts/tegra20-colibri-iris.dts index adfa917..9c61581 100644 --- a/arch/arm/dts/tegra20-colibri-iris.dts +++ b/arch/arm/dts/tegra20-colibri-iris.dts @@ -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"; diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts index 35b4d7e..5879353 100644 --- a/arch/arm/dts/tegra30-beaver.dts +++ b/arch/arm/dts/tegra30-beaver.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "tegra30.dtsi" +#include / { 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; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi deleted file mode 100644 index 19a84e9..0000000 --- a/arch/arm/dts/tegra30.dtsi +++ /dev/null @@ -1,892 +0,0 @@ -#include -#include -#include -#include - -#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 = ; /* 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 = , /* syncpt */ - ; /* 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 = ; - clocks = <&tegra_car TEGRA30_CLK_MPE>; - resets = <&tegra_car 60>; - reset-names = "mpe"; - }; - - vi@54080000 { - compatible = "nvidia,tegra30-vi"; - reg = <0x54080000 0x00040000>; - interrupts = ; - clocks = <&tegra_car TEGRA30_CLK_VI>; - resets = <&tegra_car 20>; - reset-names = "vi"; - }; - - epp@540c0000 { - compatible = "nvidia,tegra30-epp"; - reg = <0x540c0000 0x00040000>; - interrupts = ; - clocks = <&tegra_car TEGRA30_CLK_EPP>; - resets = <&tegra_car 19>; - reset-names = "epp"; - }; - - isp@54100000 { - compatible = "nvidia,tegra30-isp"; - reg = <0x54100000 0x00040000>; - interrupts = ; - clocks = <&tegra_car TEGRA30_CLK_ISP>; - resets = <&tegra_car 23>; - reset-names = "isp"; - }; - - gr2d@54140000 { - compatible = "nvidia,tegra30-gr2d"; - reg = <0x54140000 0x00040000>; - interrupts = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = , - , - , - , - , - ; - 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 = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; - 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 = , - , - , - , - , - , - , - ; - #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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - clocks = <&tegra_car TEGRA30_CLK_RTC>; - }; - - i2c@7000c000 { - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; - reg = <0x7000c000 0x100>; - interrupts = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - #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 = ; - 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 = ; - }; - - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = ; - 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 = , - , - , - ; - }; -}; diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 2c69406..160732f 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -7,39 +7,6 @@ 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_JETSON bool "NVIDIA Jetson TK1" select ARCH_TEGRA_124_SOC + select I2C + select I2C_TEGRA endmenu diff --git a/arch/arm/mach-tegra/include/mach/lowlevel.h b/arch/arm/mach-tegra/include/mach/lowlevel.h index c65be0b..3e7e41b 100644 --- a/arch/arm/mach-tegra/include/mach/lowlevel.h +++ b/arch/arm/mach-tegra/include/mach/lowlevel.h @@ -176,37 +176,6 @@ } } -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 @@ } } -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 diff --git a/arch/arm/mach-tegra/include/mach/tegra-powergate.h b/arch/arm/mach-tegra/include/mach/tegra-powergate.h new file mode 100644 index 0000000..e32250a --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/tegra-powergate.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010 Google, Inc + * + * Author: + * Colin Cross + * + * 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_ */ diff --git a/arch/arm/mach-tegra/include/mach/tegra20-car.h b/arch/arm/mach-tegra/include/mach/tegra20-car.h index 161e3d8..5a35f21 100644 --- a/arch/arm/mach-tegra/include/mach/tegra20-car.h +++ b/arch/arm/mach-tegra/include/mach/tegra20-car.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 diff --git a/arch/arm/mach-tegra/include/mach/tegra20-pmc.h b/arch/arm/mach-tegra/include/mach/tegra20-pmc.h index 30ac065..c379544 100644 --- a/arch/arm/mach-tegra/include/mach/tegra20-pmc.h +++ b/arch/arm/mach-tegra/include/mach/tegra20-pmc.h @@ -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 diff --git a/arch/arm/mach-tegra/include/mach/tegra30-car.h b/arch/arm/mach-tegra/include/mach/tegra30-car.h index c8f6c9f..7fb2238 100644 --- a/arch/arm/mach-tegra/include/mach/tegra30-car.h +++ b/arch/arm/mach-tegra/include/mach/tegra30-car.h @@ -33,3 +33,5 @@ #define CRC_RST_DEV_V_CLR 0x434 #define CRC_CLK_OUT_ENB_V_SET 0x440 + +#define CRC_PLLE_AUX 0x48c diff --git a/arch/arm/mach-tegra/tegra20-pmc.c b/arch/arm/mach-tegra/tegra20-pmc.c index d868094..eaa5ac7 100644 --- a/arch/arm/mach-tegra/tegra20-pmc.c +++ b/arch/arm/mach-tegra/tegra20-pmc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Lucas Stach + * Copyright (C) 2013-2014 Lucas Stach * * 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 #include +#include #include #include #include +#include +#include +#include +#include +#include #include static void __iomem *pmc_base; +static int tegra_num_powerdomains; /* main SoC reset trigger */ void __noreturn reset_cpu(ulong addr) @@ -38,6 +44,162 @@ } 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 @@ return PTR_ERR(pmc_base); } + tegra_powergate_init(); + + if (IS_ENABLED(CONFIG_RESET_SOURCE)) + tegra20_pmc_detect_reset_cause(); + return 0; } diff --git a/arch/arm/mach-tegra/tegra20.c b/arch/arm/mach-tegra/tegra20.c index dcc55ae..8d1cd5b 100644 --- a/arch/arm/mach-tegra/tegra20.c +++ b/arch/arm/mach-tegra/tegra20.c @@ -22,47 +22,6 @@ #include #include -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")) diff --git a/arch/mips/mach-malta/pci.c b/arch/mips/mach-malta/pci.c index 9035175..47c0e22 100644 --- a/arch/mips/mach-malta/pci.c +++ b/arch/mips/mach-malta/pci.c @@ -151,7 +151,7 @@ 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 @@ 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; diff --git a/commands/lspci.c b/commands/lspci.c index fdf0269..27edd5d 100644 --- a/commands/lspci.c +++ b/commands/lspci.c @@ -20,10 +20,24 @@ #include #include +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 @@ } 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; diff --git a/common/reset_source.c b/common/reset_source.c index 6026af1..946670b 100644 --- a/common/reset_source.c +++ b/common/reset_source.c @@ -25,6 +25,7 @@ [RESET_WDG] = "WDG", [RESET_WKE] = "WKE", [RESET_JTAG] = "JTAG", + [RESET_THERM] = "THERM", }; static enum reset_src_type reset_source; diff --git a/drivers/Kconfig b/drivers/Kconfig index e126f62..5984ccc 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -30,5 +30,6 @@ source "drivers/pci/Kconfig" source "drivers/rtc/Kconfig" source "drivers/firmware/Kconfig" +source "drivers/phy/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index cf42190..7ef5e90 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_PCI) += pci/ obj-y += rtc/ obj-$(CONFIG_FIRMWARE) += firmware/ +obj-$(CONFIG_GENERIC_PHY) += phy/ diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index c18c67f..e677eff 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -17,12 +17,15 @@ */ #include +#include #include #include #include #include #include +#include + #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 @@ .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 @@ 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); +} diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 514b22a..7a2f7c0 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -62,6 +62,15 @@ { 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 @@ .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 @@ 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 @@ 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 @@ {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}, diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 5b4365d..2ff42d8 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -324,11 +324,11 @@ {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}, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index ed6d736..46fd6dd 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -130,6 +130,13 @@ { 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 @@ .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 @@ 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 @@ 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 @@ {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}, diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index d5d0730..10d0357 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -63,6 +63,7 @@ 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 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; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c52da18..f793cbe 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -696,4 +696,4 @@ .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); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c99fcc8..24b9844 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -156,6 +156,14 @@ 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 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1b85778..3e66b31 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -22,6 +22,7 @@ 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 diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c new file mode 100644 index 0000000..5702900 --- /dev/null +++ b/drivers/net/rtl8169.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) 2014 Lucas Stach + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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); diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 97a1d93..97378ab 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -30,6 +30,7 @@ config OF_PCI bool depends on PCI + select OF_ADDRESS_PCI help OpenFirmware PCI bus accessors diff --git a/drivers/of/address.c b/drivers/of/address.c index b3cbb15..8018d78 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -179,6 +179,74 @@ } #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 */ diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index d17a151..0e9308e 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -30,6 +30,13 @@ 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 diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4423531..b93b28a 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -8,3 +8,4 @@ CPPFLAGS += $(ccflags-y) obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o +obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 8215ee5..866ab08 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -86,7 +86,8 @@ 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; diff --git a/drivers/pci/pci-tegra.c b/drivers/pci/pci-tegra.c new file mode 100644 index 0000000..f2ade77 --- /dev/null +++ b/drivers/pci/pci-tegra.c @@ -0,0 +1,1305 @@ +/* + * Copyright (C) 2014 Lucas Stach + * + * based on code + * Copyright (c) 2010, CompuLab, Ltd. + * Copyright (c) 2008-2009, 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* register definitions */ + +#define AFI_AXI_BAR0_SZ 0x00 +#define AFI_AXI_BAR1_SZ 0x04 +#define AFI_AXI_BAR2_SZ 0x08 +#define AFI_AXI_BAR3_SZ 0x0c +#define AFI_AXI_BAR4_SZ 0x10 +#define AFI_AXI_BAR5_SZ 0x14 + +#define AFI_AXI_BAR0_START 0x18 +#define AFI_AXI_BAR1_START 0x1c +#define AFI_AXI_BAR2_START 0x20 +#define AFI_AXI_BAR3_START 0x24 +#define AFI_AXI_BAR4_START 0x28 +#define AFI_AXI_BAR5_START 0x2c + +#define AFI_FPCI_BAR0 0x30 +#define AFI_FPCI_BAR1 0x34 +#define AFI_FPCI_BAR2 0x38 +#define AFI_FPCI_BAR3 0x3c +#define AFI_FPCI_BAR4 0x40 +#define AFI_FPCI_BAR5 0x44 + +#define AFI_CACHE_BAR0_SZ 0x48 +#define AFI_CACHE_BAR0_ST 0x4c +#define AFI_CACHE_BAR1_SZ 0x50 +#define AFI_CACHE_BAR1_ST 0x54 + +#define AFI_MSI_BAR_SZ 0x60 +#define AFI_MSI_FPCI_BAR_ST 0x64 +#define AFI_MSI_AXI_BAR_ST 0x68 + +#define AFI_MSI_VEC0 0x6c +#define AFI_MSI_VEC1 0x70 +#define AFI_MSI_VEC2 0x74 +#define AFI_MSI_VEC3 0x78 +#define AFI_MSI_VEC4 0x7c +#define AFI_MSI_VEC5 0x80 +#define AFI_MSI_VEC6 0x84 +#define AFI_MSI_VEC7 0x88 + +#define AFI_MSI_EN_VEC0 0x8c +#define AFI_MSI_EN_VEC1 0x90 +#define AFI_MSI_EN_VEC2 0x94 +#define AFI_MSI_EN_VEC3 0x98 +#define AFI_MSI_EN_VEC4 0x9c +#define AFI_MSI_EN_VEC5 0xa0 +#define AFI_MSI_EN_VEC6 0xa4 +#define AFI_MSI_EN_VEC7 0xa8 + +#define AFI_CONFIGURATION 0xac +#define AFI_CONFIGURATION_EN_FPCI (1 << 0) + +#define AFI_FPCI_ERROR_MASKS 0xb0 + +#define AFI_INTR_MASK 0xb4 +#define AFI_INTR_MASK_INT_MASK (1 << 0) +#define AFI_INTR_MASK_MSI_MASK (1 << 8) + +#define AFI_INTR_CODE 0xb8 +#define AFI_INTR_CODE_MASK 0xf +#define AFI_INTR_AXI_SLAVE_ERROR 1 +#define AFI_INTR_AXI_DECODE_ERROR 2 +#define AFI_INTR_TARGET_ABORT 3 +#define AFI_INTR_MASTER_ABORT 4 +#define AFI_INTR_INVALID_WRITE 5 +#define AFI_INTR_LEGACY 6 +#define AFI_INTR_FPCI_DECODE_ERROR 7 + +#define AFI_INTR_SIGNATURE 0xbc +#define AFI_UPPER_FPCI_ADDRESS 0xc0 +#define AFI_SM_INTR_ENABLE 0xc4 +#define AFI_SM_INTR_INTA_ASSERT (1 << 0) +#define AFI_SM_INTR_INTB_ASSERT (1 << 1) +#define AFI_SM_INTR_INTC_ASSERT (1 << 2) +#define AFI_SM_INTR_INTD_ASSERT (1 << 3) +#define AFI_SM_INTR_INTA_DEASSERT (1 << 4) +#define AFI_SM_INTR_INTB_DEASSERT (1 << 5) +#define AFI_SM_INTR_INTC_DEASSERT (1 << 6) +#define AFI_SM_INTR_INTD_DEASSERT (1 << 7) + +#define AFI_AFI_INTR_ENABLE 0xc8 +#define AFI_INTR_EN_INI_SLVERR (1 << 0) +#define AFI_INTR_EN_INI_DECERR (1 << 1) +#define AFI_INTR_EN_TGT_SLVERR (1 << 2) +#define AFI_INTR_EN_TGT_DECERR (1 << 3) +#define AFI_INTR_EN_TGT_WRERR (1 << 4) +#define AFI_INTR_EN_DFPCI_DECERR (1 << 5) +#define AFI_INTR_EN_AXI_DECERR (1 << 6) +#define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7) +#define AFI_INTR_EN_PRSNT_SENSE (1 << 8) + +#define AFI_PCIE_CONFIG 0x0f8 +#define AFI_PCIE_CONFIG_PCIE_DISABLE(x) (1 << ((x) + 1)) +#define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL 0xe +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420 (0x0 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1 (0x0 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222 (0x1 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1 (0x1 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411 (0x2 << 20) + +#define AFI_FUSE 0x104 +#define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) + +#define AFI_PEX0_CTRL 0x110 +#define AFI_PEX1_CTRL 0x118 +#define AFI_PEX2_CTRL 0x128 +#define AFI_PEX_CTRL_RST (1 << 0) +#define AFI_PEX_CTRL_CLKREQ_EN (1 << 1) +#define AFI_PEX_CTRL_REFCLK_EN (1 << 3) +#define AFI_PEX_CTRL_OVERRIDE_EN (1 << 4) + +#define AFI_PLLE_CONTROL 0x160 +#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9) +#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1) + +#define AFI_PEXBIAS_CTRL_0 0x168 + +#define RP_VEND_XP 0x00000F00 +#define RP_VEND_XP_DL_UP (1 << 30) + +#define RP_PRIV_MISC 0x00000FE0 +#define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0) +#define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0) + +#define RP_LINK_CONTROL_STATUS 0x00000090 +#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000 +#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000 + +#define PADS_CTL_SEL 0x0000009C + +#define PADS_CTL 0x000000A0 +#define PADS_CTL_IDDQ_1L (1 << 0) +#define PADS_CTL_TX_DATA_EN_1L (1 << 6) +#define PADS_CTL_RX_DATA_EN_1L (1 << 10) + +#define PADS_PLL_CTL_TEGRA20 0x000000B8 +#define PADS_PLL_CTL_TEGRA30 0x000000B4 +#define PADS_PLL_CTL_RST_B4SM (1 << 1) +#define PADS_PLL_CTL_LOCKDET (1 << 8) +#define PADS_PLL_CTL_REFCLK_MASK (0x3 << 16) +#define PADS_PLL_CTL_REFCLK_INTERNAL_CML (0 << 16) +#define PADS_PLL_CTL_REFCLK_INTERNAL_CMOS (1 << 16) +#define PADS_PLL_CTL_REFCLK_EXTERNAL (2 << 16) +#define PADS_PLL_CTL_TXCLKREF_MASK (0x1 << 20) +#define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20) +#define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20) +#define PADS_PLL_CTL_TXCLKREF_BUF_EN (1 << 22) + +#define PADS_REFCLK_CFG0 0x000000C8 +#define PADS_REFCLK_CFG1 0x000000CC + +/* + * Fields in PADS_REFCLK_CFG*. Those registers form an array of 16-bit + * entries, one entry per PCIe port. These field definitions and desired + * values aren't in the TRM, but do come from NVIDIA. + */ +#define PADS_REFCLK_CFG_TERM_SHIFT 2 /* 6:2 */ +#define PADS_REFCLK_CFG_E_TERM_SHIFT 7 +#define PADS_REFCLK_CFG_PREDI_SHIFT 8 /* 11:8 */ +#define PADS_REFCLK_CFG_DRVI_SHIFT 12 /* 15:12 */ + +/* Default value provided by HW engineering is 0xfa5c */ +#define PADS_REFCLK_CFG_VALUE \ + ( \ + (0x17 << PADS_REFCLK_CFG_TERM_SHIFT) | \ + (0 << PADS_REFCLK_CFG_E_TERM_SHIFT) | \ + (0xa << PADS_REFCLK_CFG_PREDI_SHIFT) | \ + (0xf << PADS_REFCLK_CFG_DRVI_SHIFT) \ + ) + +/* used to differentiate between Tegra SoC generations */ +struct tegra_pcie_soc_data { + unsigned int num_ports; + unsigned int msi_base_shift; + u32 pads_pll_ctl; + u32 tx_ref_sel; + bool has_pex_clkreq_en; + bool has_pex_bias_ctrl; + bool has_intr_prsnt_sense; + bool has_avdd_supply; + bool has_cml_clk; + bool has_gen2; +}; + +struct tegra_pcie { + struct device_d *dev; + struct pci_controller pci; + + void __iomem *pads; + void __iomem *afi; + void __iomem *cs; + + struct list_head buses; + + struct resource io; + struct resource mem; + struct resource prefetch; + struct resource busn; + struct resource *cs_res; + + struct clk *pex_clk; + struct clk *afi_clk; + struct clk *pll_e; + struct clk *cml_clk; + + struct reset_control *pex_rst; + struct reset_control *afi_rst; + struct reset_control *pcie_xrst; + + struct phy *phy; + + struct list_head ports; + unsigned int num_ports; + u32 xbar_config; + + struct regulator *pex_clk_supply; + struct regulator *vdd_supply; + struct regulator *avdd_supply; + + const struct tegra_pcie_soc_data *soc_data; +}; + +struct tegra_pcie_port { + struct tegra_pcie *pcie; + struct list_head list; + struct resource regs; + void __iomem *base; + unsigned int index; + unsigned int lanes; +}; + +static inline struct tegra_pcie *host_to_pcie(struct pci_controller *host) +{ + return container_of(host, struct tegra_pcie, pci); +} + +static inline void afi_writel(struct tegra_pcie *pcie, u32 value, + unsigned long offset) +{ + writel(value, pcie->afi + offset); +} + +static inline u32 afi_readl(struct tegra_pcie *pcie, unsigned long offset) +{ + return readl(pcie->afi + offset); +} + +static inline void pads_writel(struct tegra_pcie *pcie, u32 value, + unsigned long offset) +{ + writel(value, pcie->pads + offset); +} + +static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset) +{ + return readl(pcie->pads + offset); +} + +static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct tegra_pcie *pcie = host_to_pcie(bus->host); + void __iomem *addr = NULL; + + if (bus->number == 0) { + unsigned int slot = PCI_SLOT(devfn); + struct tegra_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) { + if (port->index + 1 == slot) { + addr = (void __force __iomem *) + port->regs.start + (where & ~3); + break; + } + } + } else { + addr = pcie->cs; + + addr += ((where & 0xf00) << 16) | (bus->number << 16) | + (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | + (where & 0xfc); + } + + return addr; +} + +static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + void __iomem *addr; + + addr = tegra_pcie_conf_address(bus, devfn, where); + if (!addr) { + *value = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + *value = readl(addr); + + if (size == 1) + *value = (*value >> (8 * (where & 3))) & 0xff; + else if (size == 2) + *value = (*value >> (8 * (where & 3))) & 0xffff; + + return PCIBIOS_SUCCESSFUL; +} + +static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + void __iomem *addr; + u32 mask, tmp; + + addr = tegra_pcie_conf_address(bus, devfn, where); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (size == 4) { + writel(value, addr); + return PCIBIOS_SUCCESSFUL; + } + + if (size == 2) + mask = ~(0xffff << ((where & 0x3) * 8)); + else if (size == 1) + mask = ~(0xff << ((where & 0x3) * 8)); + else + return PCIBIOS_BAD_REGISTER_NUMBER; + + tmp = readl(addr) & mask; + tmp |= value << ((where & 0x3) * 8); + writel(tmp, addr); + + return PCIBIOS_SUCCESSFUL; +} + +static int tegra_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr) +{ + return res_addr; +} + +static struct pci_ops tegra_pcie_ops = { + .read = tegra_pcie_read_conf, + .write = tegra_pcie_write_conf, + .res_start = tegra_pcie_res_start, +}; + +static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port) +{ + unsigned long ret = 0; + + switch (port->index) { + case 0: + ret = AFI_PEX0_CTRL; + break; + + case 1: + ret = AFI_PEX1_CTRL; + break; + + case 2: + ret = AFI_PEX2_CTRL; + break; + } + + return ret; +} + +static void tegra_pcie_port_reset(struct tegra_pcie_port *port) +{ + unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); + unsigned long value; + + /* pulse reset signal */ + value = afi_readl(port->pcie, ctrl); + value &= ~AFI_PEX_CTRL_RST; + afi_writel(port->pcie, value, ctrl); + + mdelay(1); + + value = afi_readl(port->pcie, ctrl); + value |= AFI_PEX_CTRL_RST; + afi_writel(port->pcie, value, ctrl); +} + +static void tegra_pcie_port_enable(struct tegra_pcie_port *port) +{ + const struct tegra_pcie_soc_data *soc = port->pcie->soc_data; + unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); + unsigned long value; + + /* enable reference clock */ + value = afi_readl(port->pcie, ctrl); + value |= AFI_PEX_CTRL_REFCLK_EN; + + if (soc->has_pex_clkreq_en) + value |= AFI_PEX_CTRL_CLKREQ_EN; + + value |= AFI_PEX_CTRL_OVERRIDE_EN; + + afi_writel(port->pcie, value, ctrl); + + tegra_pcie_port_reset(port); +} + +static void tegra_pcie_port_disable(struct tegra_pcie_port *port) +{ + unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); + unsigned long value; + + /* assert port reset */ + value = afi_readl(port->pcie, ctrl); + value &= ~AFI_PEX_CTRL_RST; + afi_writel(port->pcie, value, ctrl); + + /* disable reference clock */ + value = afi_readl(port->pcie, ctrl); + value &= ~AFI_PEX_CTRL_REFCLK_EN; + afi_writel(port->pcie, value, ctrl); +} + +static void tegra_pcie_port_free(struct tegra_pcie_port *port) +{ + list_del(&port->list); + kfree(port); +} + +#if 0 +static void tegra_pcie_fixup_bridge(struct pci_dev *dev) +{ + u16 reg; + + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) { + pci_read_config_word(dev, PCI_COMMAND, ®); + reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR); + pci_write_config_word(dev, PCI_COMMAND, reg); + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge); + +/* Tegra PCIE root complex wrongly reports device class */ +static void tegra_pcie_fixup_class(struct pci_dev *dev) +{ + dev->class = PCI_CLASS_BRIDGE_PCI << 8; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1c, tegra_pcie_fixup_class); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1d, tegra_pcie_fixup_class); + +/* Tegra PCIE requires relaxed ordering */ +static void tegra_pcie_relax_enable(struct pci_dev *dev) +{ + pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN); +} +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable); +#endif + +/* + * FPCI map is as follows: + * - 0xfdfc000000: I/O space + * - 0xfdfe000000: type 0 configuration space + * - 0xfdff000000: type 1 configuration space + * - 0xfe00000000: type 0 extended configuration space + * - 0xfe10000000: type 1 extended configuration space + */ +static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) +{ + u32 fpci_bar, size, axi_address; + + /* Bar 0: type 1 extended configuration space */ + fpci_bar = 0xfe100000; + size = resource_size(pcie->cs_res); + axi_address = pcie->cs_res->start; + afi_writel(pcie, axi_address, AFI_AXI_BAR0_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR0); + + /* Bar 1: downstream IO bar */ + fpci_bar = 0xfdfc0000; + size = resource_size(&pcie->io); + axi_address = pcie->io.start; + afi_writel(pcie, axi_address, AFI_AXI_BAR1_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1); + + /* Bar 2: prefetchable memory BAR */ + fpci_bar = (((pcie->prefetch.start >> 12) & 0x0fffffff) << 4) | 0x1; + size = resource_size(&pcie->prefetch); + axi_address = pcie->prefetch.start; + afi_writel(pcie, axi_address, AFI_AXI_BAR2_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR2); + + /* Bar 3: non prefetchable memory BAR */ + fpci_bar = (((pcie->mem.start >> 12) & 0x0fffffff) << 4) | 0x1; + size = resource_size(&pcie->mem); + axi_address = pcie->mem.start; + afi_writel(pcie, axi_address, AFI_AXI_BAR3_START); + afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ); + afi_writel(pcie, fpci_bar, AFI_FPCI_BAR3); + + /* NULL out the remaining BARs as they are not used */ + afi_writel(pcie, 0, AFI_AXI_BAR4_START); + afi_writel(pcie, 0, AFI_AXI_BAR4_SZ); + afi_writel(pcie, 0, AFI_FPCI_BAR4); + + afi_writel(pcie, 0, AFI_AXI_BAR5_START); + afi_writel(pcie, 0, AFI_AXI_BAR5_SZ); + afi_writel(pcie, 0, AFI_FPCI_BAR5); + + /* map all upstream transactions as uncached */ + /* FIXME: is 0 ok for BAR0 start ??? */ + afi_writel(pcie, 0, AFI_CACHE_BAR0_ST); + afi_writel(pcie, 0, AFI_CACHE_BAR0_SZ); + afi_writel(pcie, 0, AFI_CACHE_BAR1_ST); + afi_writel(pcie, 0, AFI_CACHE_BAR1_SZ); + + /* MSI translations are setup only when needed */ + afi_writel(pcie, 0, AFI_MSI_FPCI_BAR_ST); + afi_writel(pcie, 0, AFI_MSI_BAR_SZ); + afi_writel(pcie, 0, AFI_MSI_AXI_BAR_ST); + afi_writel(pcie, 0, AFI_MSI_BAR_SZ); +} + +static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) +{ + const struct tegra_pcie_soc_data *soc = pcie->soc_data; + u32 value; + + /* initialize internal PHY, enable up to 16 PCIE lanes */ + pads_writel(pcie, 0x0, PADS_CTL_SEL); + + /* override IDDQ to 1 on all 4 lanes */ + value = pads_readl(pcie, PADS_CTL); + value |= PADS_CTL_IDDQ_1L; + pads_writel(pcie, value, PADS_CTL); + + /* + * Set up PHY PLL inputs select PLLE output as refclock, + * set TX ref sel to div10 (not div5). + */ + value = pads_readl(pcie, soc->pads_pll_ctl); + value &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK); + value |= PADS_PLL_CTL_REFCLK_INTERNAL_CML | soc->tx_ref_sel; + pads_writel(pcie, value, soc->pads_pll_ctl); + + /* reset PLL */ + value = pads_readl(pcie, soc->pads_pll_ctl); + value &= ~PADS_PLL_CTL_RST_B4SM; + pads_writel(pcie, value, soc->pads_pll_ctl); + + udelay(20); + + /* take PLL out of reset */ + value = pads_readl(pcie, soc->pads_pll_ctl); + value |= PADS_PLL_CTL_RST_B4SM; + pads_writel(pcie, value, soc->pads_pll_ctl); + + /* Configure the reference clock driver */ + value = PADS_REFCLK_CFG_VALUE | (PADS_REFCLK_CFG_VALUE << 16); + pads_writel(pcie, value, PADS_REFCLK_CFG0); + if (soc->num_ports > 2) + pads_writel(pcie, PADS_REFCLK_CFG_VALUE, PADS_REFCLK_CFG1); + + /* wait for the PLL to lock */ + if (wait_on_timeout(300 * MSECOND, + (pads_readl(pcie, soc->pads_pll_ctl) & PADS_PLL_CTL_LOCKDET))) { + pr_err("Tegra PCIe error: timeout waiting for PLL\n"); + return -EBUSY; + } + + /* turn off IDDQ override */ + value = pads_readl(pcie, PADS_CTL); + value &= ~PADS_CTL_IDDQ_1L; + pads_writel(pcie, value, PADS_CTL); + + /* enable TX/RX data */ + value = pads_readl(pcie, PADS_CTL); + value |= PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L; + pads_writel(pcie, value, PADS_CTL); + + return 0; +} + +static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) +{ + const struct tegra_pcie_soc_data *soc = pcie->soc_data; + struct tegra_pcie_port *port; + unsigned long value; + int err; + + /* enable PLL power down */ + if (pcie->phy) { + value = afi_readl(pcie, AFI_PLLE_CONTROL); + value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL; + value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN; + afi_writel(pcie, value, AFI_PLLE_CONTROL); + } + + /* power down PCIe slot clock bias pad */ + if (soc->has_pex_bias_ctrl) + afi_writel(pcie, 0, AFI_PEXBIAS_CTRL_0); + + /* configure mode and disable all ports */ + value = afi_readl(pcie, AFI_PCIE_CONFIG); + value &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK; + value |= AFI_PCIE_CONFIG_PCIE_DISABLE_ALL | pcie->xbar_config; + + list_for_each_entry(port, &pcie->ports, list) + value &= ~AFI_PCIE_CONFIG_PCIE_DISABLE(port->index); + + afi_writel(pcie, value, AFI_PCIE_CONFIG); + + if (soc->has_gen2) { + value = afi_readl(pcie, AFI_FUSE); + value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS; + afi_writel(pcie, value, AFI_FUSE); + } else { + value = afi_readl(pcie, AFI_FUSE); + value |= AFI_FUSE_PCIE_T0_GEN2_DIS; + afi_writel(pcie, value, AFI_FUSE); + } + + if (!pcie->phy) + err = tegra_pcie_phy_enable(pcie); + else + err = phy_power_on(pcie->phy); + + /* take the PCIe interface module out of reset */ + reset_control_deassert(pcie->pcie_xrst); + + /* finally enable PCIe */ + value = afi_readl(pcie, AFI_CONFIGURATION); + value |= AFI_CONFIGURATION_EN_FPCI; + afi_writel(pcie, value, AFI_CONFIGURATION); + + value = AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR | + AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR | + AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR; + + if (soc->has_intr_prsnt_sense) + value |= AFI_INTR_EN_PRSNT_SENSE; + + afi_writel(pcie, value, AFI_AFI_INTR_ENABLE); + afi_writel(pcie, 0xffffffff, AFI_SM_INTR_ENABLE); + + /* don't enable MSI for now, only when needed */ + afi_writel(pcie, AFI_INTR_MASK_INT_MASK, AFI_INTR_MASK); + + /* disable all exceptions */ + afi_writel(pcie, 0, AFI_FPCI_ERROR_MASKS); + + return 0; +} + +static void tegra_pcie_power_off(struct tegra_pcie *pcie) +{ + const struct tegra_pcie_soc_data *soc = pcie->soc_data; + int err; + + /* TODO: disable and unprepare clocks? */ + + err = phy_power_off(pcie->phy); + if (err < 0) + dev_warn(pcie->dev, "failed to power off PHY: %d\n", err); + + reset_control_assert(pcie->pcie_xrst); + reset_control_assert(pcie->afi_rst); + reset_control_assert(pcie->pex_rst); + + tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); + + if (soc->has_avdd_supply) { + err = regulator_disable(pcie->avdd_supply); + if (err < 0) + dev_warn(pcie->dev, + "failed to disable AVDD regulator: %d\n", + err); + } + + err = regulator_disable(pcie->pex_clk_supply); + if (err < 0) + dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n", + err); + + err = regulator_disable(pcie->vdd_supply); + if (err < 0) + dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n", + err); +} + +static int tegra_pcie_power_on(struct tegra_pcie *pcie) +{ + const struct tegra_pcie_soc_data *soc = pcie->soc_data; + int err; + + reset_control_assert(pcie->pcie_xrst); + reset_control_assert(pcie->afi_rst); + reset_control_assert(pcie->pex_rst); + + tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); + + /* enable regulators */ + err = regulator_enable(pcie->vdd_supply); + if (err < 0) { + dev_err(pcie->dev, "failed to enable VDD regulator: %d\n", err); + return err; + } + + err = regulator_enable(pcie->pex_clk_supply); + if (err < 0) { + dev_err(pcie->dev, "failed to enable pex-clk regulator: %d\n", + err); + return err; + } + + if (soc->has_avdd_supply) { + err = regulator_enable(pcie->avdd_supply); + if (err < 0) { + dev_err(pcie->dev, + "failed to enable AVDD regulator: %d\n", + err); + return err; + } + } + + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, + pcie->pex_clk, + pcie->pex_rst); + if (err) { + dev_err(pcie->dev, "powerup sequence failed: %d\n", err); + return err; + } + + reset_control_deassert(pcie->afi_rst); + + err = clk_enable(pcie->afi_clk); + if (err < 0) { + dev_err(pcie->dev, "failed to enable AFI clock: %d\n", err); + return err; + } + + if (soc->has_cml_clk) { + err = clk_enable(pcie->cml_clk); + if (err < 0) { + dev_err(pcie->dev, "failed to enable CML clock: %d\n", + err); + return err; + } + } + + err = clk_enable(pcie->pll_e); + if (err < 0) { + dev_err(pcie->dev, "failed to enable PLLE clock: %d\n", err); + return err; + } + + return 0; +} + +static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) +{ + const struct tegra_pcie_soc_data *soc = pcie->soc_data; + + pcie->pex_clk = clk_get(pcie->dev, "pex"); + if (IS_ERR(pcie->pex_clk)) + return PTR_ERR(pcie->pex_clk); + + pcie->afi_clk = clk_get(pcie->dev, "afi"); + if (IS_ERR(pcie->afi_clk)) + return PTR_ERR(pcie->afi_clk); + + pcie->pll_e = clk_get(pcie->dev, "pll_e"); + if (IS_ERR(pcie->pll_e)) + return PTR_ERR(pcie->pll_e); + + if (soc->has_cml_clk) { + pcie->cml_clk = clk_get(pcie->dev, "cml"); + if (IS_ERR(pcie->cml_clk)) + return PTR_ERR(pcie->cml_clk); + } + + return 0; +} + +static int tegra_pcie_resets_get(struct tegra_pcie *pcie) +{ + pcie->pex_rst = reset_control_get(pcie->dev, "pex"); + if (IS_ERR(pcie->pex_rst)) + return PTR_ERR(pcie->pex_rst); + + pcie->afi_rst = reset_control_get(pcie->dev, "afi"); + if (IS_ERR(pcie->afi_rst)) + return PTR_ERR(pcie->afi_rst); + + pcie->pcie_xrst = reset_control_get(pcie->dev, "pcie_x"); + if (IS_ERR(pcie->pcie_xrst)) + return PTR_ERR(pcie->pcie_xrst); + + return 0; +} + +static int tegra_pcie_get_resources(struct tegra_pcie *pcie) +{ + struct device_d *dev = pcie->dev; + int err; + + err = tegra_pcie_clocks_get(pcie); + if (err) { + dev_err(dev, "failed to get clocks: %d\n", err); + return err; + } + + err = tegra_pcie_resets_get(pcie); + if (err) { + dev_err(dev, "failed to get resets: %d\n", err); + return err; + } + + pcie->phy = phy_optional_get(pcie->dev, "pcie"); + if (IS_ERR(pcie->phy)) { + err = PTR_ERR(pcie->phy); + dev_err(dev, "failed to get PHY: %d\n", err); + return err; + } + + err = phy_init(pcie->phy); + if (err < 0) { + dev_err(dev, "failed to initialize PHY: %d\n", err); + return err; + } + + err = tegra_pcie_power_on(pcie); + if (err) { + dev_err(dev, "failed to power up: %d\n", err); + return err; + } + + pcie->pads = dev_request_mem_region_by_name(dev, "pads"); + if (IS_ERR(pcie->pads)) { + err = PTR_ERR(pcie->pads); + goto poweroff; + } + + pcie->afi = dev_request_mem_region_by_name(dev, "afi"); + if (IS_ERR(pcie->afi)) { + err = PTR_ERR(pcie->afi); + goto poweroff; + } + + pcie->cs_res = dev_get_resource_by_name(dev, IORESOURCE_MEM, "cs"); + pcie->cs = dev_request_mem_region_by_name(dev, "cs"); + if (IS_ERR(pcie->cs)) { + err = PTR_ERR(pcie->cs); + goto poweroff; + } + + return 0; + +poweroff: + tegra_pcie_power_off(pcie); + return err; +} + +static int tegra_pcie_put_resources(struct tegra_pcie *pcie) +{ + int err; + + tegra_pcie_power_off(pcie); + + err = phy_exit(pcie->phy); + if (err < 0) + dev_err(pcie->dev, "failed to teardown PHY: %d\n", err); + + return 0; +} + +static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes, + u32 *xbar) +{ + struct device_node *np = pcie->dev->device_node; + + if (of_device_is_compatible(np, "nvidia,tegra124-pcie")) { + switch (lanes) { + case 0x0000104: + dev_info(pcie->dev, "4x1, 1x1 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1; + return 0; + + case 0x0000102: + dev_info(pcie->dev, "2x1, 1x1 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1; + return 0; + } + } else if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) { + switch (lanes) { + case 0x00000204: + dev_info(pcie->dev, "4x1, 2x1 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420; + return 0; + + case 0x00020202: + dev_info(pcie->dev, "2x3 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222; + return 0; + + case 0x00010104: + dev_info(pcie->dev, "4x1, 1x2 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411; + return 0; + } + } else if (of_device_is_compatible(np, "nvidia,tegra20-pcie")) { + switch (lanes) { + case 0x00000004: + dev_info(pcie->dev, "single-mode configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE; + return 0; + + case 0x00000202: + dev_info(pcie->dev, "dual-mode configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL; + return 0; + } + } + + return -EINVAL; +} + +static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) +{ + const struct tegra_pcie_soc_data *soc = pcie->soc_data; + struct device_node *np = pcie->dev->device_node, *port; + struct of_pci_range_parser parser; + struct of_pci_range range; + struct resource *rp_res; + struct resource res; + u32 lanes = 0; + int err; + + if (of_pci_range_parser_init(&parser, np)) { + dev_err(pcie->dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + pcie->vdd_supply = regulator_get(pcie->dev, "vdd"); + if (IS_ERR(pcie->vdd_supply)) + return PTR_ERR(pcie->vdd_supply); + + pcie->pex_clk_supply = regulator_get(pcie->dev, "pex-clk"); + if (IS_ERR(pcie->pex_clk_supply)) + return PTR_ERR(pcie->pex_clk_supply); + + if (soc->has_avdd_supply) { + pcie->avdd_supply = regulator_get(pcie->dev, "avdd"); + if (IS_ERR(pcie->avdd_supply)) + return PTR_ERR(pcie->avdd_supply); + } + + for_each_of_pci_range(&parser, &range) { + of_pci_range_to_resource(&range, np, &res); + + switch (res.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: + memcpy(&pcie->io, &res, sizeof(res)); + pcie->io.name = "I/O"; + break; + + case IORESOURCE_MEM: + if (res.flags & IORESOURCE_PREFETCH) { + memcpy(&pcie->prefetch, &res, sizeof(res)); + pcie->prefetch.name = "PREFETCH"; + } else { + memcpy(&pcie->mem, &res, sizeof(res)); + pcie->mem.name = "MEM"; + } + break; + } + } +#if 0 + err = of_pci_parse_bus_range(np, &pcie->busn); + if (err < 0) { + dev_err(pcie->dev, "failed to parse ranges property: %d\n", + err); + pcie->busn.name = np->name; + pcie->busn.start = 0; + pcie->busn.end = 0xff; + pcie->busn.flags = IORESOURCE_BUS; + } +#endif + /* parse root ports */ + for_each_child_of_node(np, port) { + struct tegra_pcie_port *rp; + unsigned int index; + u32 value; + + err = of_pci_get_devfn(port); + if (err < 0) { + dev_err(pcie->dev, "failed to parse address: %d\n", + err); + return err; + } + + index = PCI_SLOT(err); + + if (index < 1 || index > soc->num_ports) { + dev_err(pcie->dev, "invalid port number: %d\n", index); + return -EINVAL; + } + + index--; + + err = of_property_read_u32(port, "nvidia,num-lanes", &value); + if (err < 0) { + dev_err(pcie->dev, "failed to parse # of lanes: %d\n", + err); + return err; + } + + if (value > 16) { + dev_err(pcie->dev, "invalid # of lanes: %u\n", value); + return -EINVAL; + } + + lanes |= value << (index << 3); + + if (!of_device_is_available(port)) + continue; + + rp = kzalloc(sizeof(*rp), GFP_KERNEL); + if (!rp) + return -ENOMEM; + + err = of_address_to_resource(port, 0, &rp->regs); + if (err < 0) { + dev_err(pcie->dev, "failed to parse address: %d\n", + err); + return err; + } + + /* + * if the port address is inside the NULL page we alias this + * range at +1MB and fix up the resource, otherwise just request + */ + if (!(rp->regs.start & 0xfffff000)) { + rp_res = request_iomem_region(dev_name(pcie->dev), + rp->regs.start + SZ_1M, + rp->regs.end + SZ_1M); + if (!rp_res) + return -ENOMEM; + + map_io_sections(rp->regs.start, + (void *)rp_res->start, SZ_1M); + + rp->regs.start = rp_res->start; + rp->regs.end = rp_res->end; + } else { + rp_res = request_iomem_region(dev_name(pcie->dev), + rp->regs.start, rp->regs.end); + if (!rp_res) + return -ENOMEM; + } + + INIT_LIST_HEAD(&rp->list); + rp->index = index; + rp->lanes = value; + rp->pcie = pcie; + + rp->base = (void __force __iomem *)rp->regs.start; + if (IS_ERR(rp->base)) + return PTR_ERR(rp->base); + + list_add_tail(&rp->list, &pcie->ports); + } + + err = tegra_pcie_get_xbar_config(pcie, lanes, &pcie->xbar_config); + if (err < 0) { + dev_err(pcie->dev, "invalid lane configuration\n"); + return err; + } + + return 0; +} + +/* + * FIXME: If there are no PCIe cards attached, then calling this function + * can result in the increase of the bootup time as there are big timeout + * loops. + */ +#define TEGRA_PCIE_LINKUP_TIMEOUT 200 /* up to 1.2 seconds */ +static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port) +{ + unsigned int timeout; + unsigned int retries = 2; + u32 value; + + /* override presence detection */ + value = readl(port->base + RP_PRIV_MISC); + value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT; + value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT; + writel(value, port->base + RP_PRIV_MISC); + + do { + timeout = wait_on_timeout(50 * MSECOND, + readl(port->regs.start + RP_VEND_XP) & RP_VEND_XP_DL_UP); + + if (timeout) { + dev_dbg(port->pcie->dev, "link %u down, retrying\n", + port->index); + goto retry; + } + + timeout = wait_on_timeout(200 * MSECOND, + readl(port->regs.start + RP_LINK_CONTROL_STATUS) & + RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE); + + if (!timeout) + return true; + +retry: + tegra_pcie_port_reset(port); + } while (--retries); + + return false; +} + +static int tegra_pcie_enable(struct tegra_pcie *pcie) +{ + struct tegra_pcie_port *port, *tmp; + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + dev_dbg(pcie->dev, "probing port %u, using %u lanes\n", + port->index, port->lanes); + + tegra_pcie_port_enable(port); + + if (tegra_pcie_port_check_link(port)) + continue; + + dev_dbg(pcie->dev, "link %u down, ignoring\n", port->index); + + tegra_pcie_port_disable(port); + tegra_pcie_port_free(port); + } + + pcie->pci.parent = pcie->dev; + pcie->pci.pci_ops = &tegra_pcie_ops; + pcie->pci.mem_resource = &pcie->mem; + pcie->pci.mem_pref_resource = &pcie->prefetch; + pcie->pci.io_resource = &pcie->io; + + register_pci_controller(&pcie->pci); + + return 0; +} + +static const struct tegra_pcie_soc_data tegra20_pcie_data = { + .num_ports = 2, + .msi_base_shift = 0, + .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, + .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10, + .has_pex_clkreq_en = false, + .has_pex_bias_ctrl = false, + .has_intr_prsnt_sense = false, + .has_avdd_supply = false, + .has_cml_clk = false, + .has_gen2 = false, +}; + +static const struct tegra_pcie_soc_data tegra30_pcie_data = { + .num_ports = 3, + .msi_base_shift = 8, + .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, + .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .has_pex_clkreq_en = true, + .has_pex_bias_ctrl = true, + .has_intr_prsnt_sense = true, + .has_avdd_supply = true, + .has_cml_clk = true, + .has_gen2 = false, +}; + +static const struct tegra_pcie_soc_data tegra124_pcie_data = { + .num_ports = 2, + .msi_base_shift = 8, + .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, + .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .has_pex_clkreq_en = true, + .has_pex_bias_ctrl = true, + .has_intr_prsnt_sense = true, + .has_cml_clk = true, + .has_gen2 = true, +}; + +static __maybe_unused struct of_device_id tegra_pcie_of_match[] = { + { + .compatible = "nvidia,tegra124-pcie", + .data = (unsigned long)&tegra124_pcie_data + }, { + .compatible = "nvidia,tegra30-pcie", + .data = (unsigned long)&tegra30_pcie_data + }, { + .compatible = "nvidia,tegra20-pcie", + .data = (unsigned long)&tegra20_pcie_data + }, { + /* sentinel */ + }, +}; + +static int tegra_pcie_probe(struct device_d *dev) +{ + struct tegra_pcie *pcie; + int err; + + pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + + INIT_LIST_HEAD(&pcie->buses); + INIT_LIST_HEAD(&pcie->ports); + dev_get_drvdata(dev, (unsigned long *)&pcie->soc_data); + pcie->dev = dev; + + err = tegra_pcie_parse_dt(pcie); + if (err < 0) { + printk("parse DT failed\n"); + return err; + } + + err = tegra_pcie_get_resources(pcie); + if (err < 0) { + dev_err(dev, "failed to request resources: %d\n", err); + return err; + } + + err = tegra_pcie_enable_controller(pcie); + if (err) + goto put_resources; + + /* setup the AFI address translations */ + tegra_pcie_setup_translations(pcie); + + err = tegra_pcie_enable(pcie); + if (err < 0) { + dev_err(dev, "failed to enable PCIe ports: %d\n", err); + goto put_resources; + } + + return 0; + +put_resources: + tegra_pcie_put_resources(pcie); + return err; +} + +static struct driver_d tegra_pcie_driver = { + .name = "tegra-pcie", + .of_compatible = DRV_OF_COMPAT(tegra_pcie_of_match), + .probe = tegra_pcie_probe, +}; +device_platform_driver(tegra_pcie_driver); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index a1b7680..ba9d097 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -12,6 +12,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ */ 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 @@ * * 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; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig new file mode 100644 index 0000000..e9461e1 --- /dev/null +++ b/drivers/phy/Kconfig @@ -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 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile new file mode 100644 index 0000000..74514ae --- /dev/null +++ b/drivers/phy/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the phy drivers. +# + +obj-$(CONFIG_GENERIC_PHY) += phy-core.o diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c new file mode 100644 index 0000000..67af14f --- /dev/null +++ b/drivers/phy/phy-core.c @@ -0,0 +1,318 @@ +/* + * phy-core.c -- Generic Phy framework. + * + * Copyright (C) 2014 Lucas Stach + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Kishon Vijay Abraham I + * + * 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 +#include +#include + +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; +} + diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 770fb2d..4cbc167 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -60,6 +60,14 @@ 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 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 3ea8649..724e6d7 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -7,5 +7,6 @@ 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/ diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c new file mode 100644 index 0000000..05cdecb --- /dev/null +++ b/drivers/pinctrl/pinctrl-tegra-xusb.c @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2014 Lucas Stach + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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); diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c index 3c11be6..be9d8a9 100644 --- a/drivers/pinctrl/pinctrl-tegra20.c +++ b/drivers/pinctrl/pinctrl-tegra20.c @@ -320,10 +320,14 @@ 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[] = { diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 8277218..aac6760 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -897,10 +897,14 @@ 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[] = { diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 53d48a0..8f2e93f 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -311,6 +311,11 @@ .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 @@ ret = PTR_ERR(priv->clk); goto err; } + clk_enable(priv->clk); priv->plat.clock = clk_get_rate(priv->clk); } @@ -476,6 +482,12 @@ .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", diff --git a/include/linux/pci.h b/include/linux/pci.h index 0ec1320..3d0e73b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -114,8 +114,15 @@ }; #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 @@ */ 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; diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 14a3ed3..8669fc7 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -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 */ diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h new file mode 100644 index 0000000..94f0044 --- /dev/null +++ b/include/linux/phy/phy.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 + * + * 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 +#include +#include + +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 */ diff --git a/include/of_address.h b/include/of_address.h index 9022ab7..ebf3ec2 100644 --- a/include/of_address.h +++ b/include/of_address.h @@ -4,6 +4,38 @@ #include #include +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 @@ #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 */ diff --git a/include/reset_source.h b/include/reset_source.h index bff7f97..6620228 100644 --- a/include/reset_source.h +++ b/include/reset_source.h @@ -20,6 +20,7 @@ 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