diff options
Diffstat (limited to 'arch')
154 files changed, 3537 insertions, 900 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a750c1425c3a..1c5021002fe4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1693,6 +1693,12 @@ config HIGHMEM config HIGHPTE bool "Allocate 2nd-level pagetables from highmem" depends on HIGHMEM + help + The VM uses one page of physical memory for each page table. + For systems with a lot of processes, this can use a lot of + precious low memory, eventually leading to low memory being + consumed by page tables. Setting this option will allow + user-space 2nd level page tables to reside in high memory. config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f21daa87ce18..0cfd7f947f6b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -141,6 +141,12 @@ choice depends on ARCH_AT91 depends on SOC_SAMA5 + config AT91_DEBUG_LL_DBGU3 + bool "Kernel low-level debugging on sama5d2" + select DEBUG_AT91_UART + depends on ARCH_AT91 + depends on SOC_SAMA5 + config DEBUG_BCM2835 bool "Kernel low-level debugging on BCM2835 PL011 UART" depends on ARCH_BCM2835 @@ -1644,7 +1650,7 @@ config PID_IN_CONTEXTIDR config DEBUG_SET_MODULE_RONX bool "Set loadable kernel module data as NX and text as RO" - depends on MODULES + depends on MODULES && MMU ---help--- This option helps catch unintended modifications to loadable kernel module's text and read-only data. It also prevents execution diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts index 901739fcb85a..5c42d259fa68 100644 --- a/arch/arm/boot/dts/am335x-boneblack.dts +++ b/arch/arm/boot/dts/am335x-boneblack.dts @@ -80,3 +80,7 @@ status = "okay"; }; }; + +&rtc { + system-power-controller; +}; diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index c80a3e233792..359a3b6daf4f 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -86,6 +86,7 @@ prcm: prcm@1f0000 { compatible = "ti,am4-prcm"; reg = <0x1f0000 0x11000>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; prcm_clocks: clocks { #address-cells = <1>; @@ -132,6 +133,12 @@ }; }; + emif: emif@4c000000 { + compatible = "ti,emif-am4372"; + reg = <0x4c000000 0x1000000>; + ti,hwmods = "emif"; + }; + edma: edma@49000000 { compatible = "ti,edma3"; ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; @@ -941,6 +948,7 @@ ti,hwmods = "dss_rfbi"; clocks = <&disp_clk>; clock-names = "fck"; + status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index a42cc377a862..a63bf78191ea 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -605,6 +605,10 @@ phy-supply = <&ldousb_reg>; }; +&usb2_phy2 { + phy-supply = <&ldousb_reg>; +}; + &usb1 { dr_mode = "host"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/atlas7.dtsi b/arch/arm/boot/dts/atlas7.dtsi index 5dfd3a44bf82..3e21311f9514 100644 --- a/arch/arm/boot/dts/atlas7.dtsi +++ b/arch/arm/boot/dts/atlas7.dtsi @@ -135,6 +135,1025 @@ compatible = "sirf,atlas7-ioc"; reg = <0x18880000 0x1000>, <0x10E40000 0x1000>; + + audio_ac97_pmx: audio_ac97@0 { + audio_ac97 { + groups = "audio_ac97_grp"; + function = "audio_ac97"; + }; + }; + + audio_func_dbg_pmx: audio_func_dbg@0 { + audio_func_dbg { + groups = "audio_func_dbg_grp"; + function = "audio_func_dbg"; + }; + }; + + audio_i2s_pmx: audio_i2s@0 { + audio_i2s { + groups = "audio_i2s_grp"; + function = "audio_i2s"; + }; + }; + + audio_i2s_2ch_pmx: audio_i2s_2ch@0 { + audio_i2s_2ch { + groups = "audio_i2s_2ch_grp"; + function = "audio_i2s_2ch"; + }; + }; + + audio_i2s_extclk_pmx: audio_i2s_extclk@0 { + audio_i2s_extclk { + groups = "audio_i2s_extclk_grp"; + function = "audio_i2s_extclk"; + }; + }; + + audio_uart0_pmx: audio_uart0@0 { + audio_uart0 { + groups = "audio_uart0_grp"; + function = "audio_uart0"; + }; + }; + + audio_uart1_pmx: audio_uart1@0 { + audio_uart1 { + groups = "audio_uart1_grp"; + function = "audio_uart1"; + }; + }; + + audio_uart2_pmx0: audio_uart2@0 { + audio_uart2_0 { + groups = "audio_uart2_grp0"; + function = "audio_uart2_m0"; + }; + }; + + audio_uart2_pmx1: audio_uart2@1 { + audio_uart2_1 { + groups = "audio_uart2_grp1"; + function = "audio_uart2_m1"; + }; + }; + + c_can_trnsvr_pmx: c_can_trnsvr@0 { + c_can_trnsvr { + groups = "c_can_trnsvr_grp"; + function = "c_can_trnsvr"; + }; + }; + + c0_can_pmx0: c0_can@0 { + c0_can_0 { + groups = "c0_can_grp0"; + function = "c0_can_m0"; + }; + }; + + c0_can_pmx1: c0_can@1 { + c0_can_1 { + groups = "c0_can_grp1"; + function = "c0_can_m1"; + }; + }; + + c1_can_pmx0: c1_can@0 { + c1_can_0 { + groups = "c1_can_grp0"; + function = "c1_can_m0"; + }; + }; + + c1_can_pmx1: c1_can@1 { + c1_can_1 { + groups = "c1_can_grp1"; + function = "c1_can_m1"; + }; + }; + + c1_can_pmx2: c1_can@2 { + c1_can_2 { + groups = "c1_can_grp2"; + function = "c1_can_m2"; + }; + }; + + ca_audio_lpc_pmx: ca_audio_lpc@0 { + ca_audio_lpc { + groups = "ca_audio_lpc_grp"; + function = "ca_audio_lpc"; + }; + }; + + ca_bt_lpc_pmx: ca_bt_lpc@0 { + ca_bt_lpc { + groups = "ca_bt_lpc_grp"; + function = "ca_bt_lpc"; + }; + }; + + ca_coex_pmx: ca_coex@0 { + ca_coex { + groups = "ca_coex_grp"; + function = "ca_coex"; + }; + }; + + ca_curator_lpc_pmx: ca_curator_lpc@0 { + ca_curator_lpc { + groups = "ca_curator_lpc_grp"; + function = "ca_curator_lpc"; + }; + }; + + ca_pcm_debug_pmx: ca_pcm_debug@0 { + ca_pcm_debug { + groups = "ca_pcm_debug_grp"; + function = "ca_pcm_debug"; + }; + }; + + ca_pio_pmx: ca_pio@0 { + ca_pio { + groups = "ca_pio_grp"; + function = "ca_pio"; + }; + }; + + ca_sdio_debug_pmx: ca_sdio_debug@0 { + ca_sdio_debug { + groups = "ca_sdio_debug_grp"; + function = "ca_sdio_debug"; + }; + }; + + ca_spi_pmx: ca_spi@0 { + ca_spi { + groups = "ca_spi_grp"; + function = "ca_spi"; + }; + }; + + ca_trb_pmx: ca_trb@0 { + ca_trb { + groups = "ca_trb_grp"; + function = "ca_trb"; + }; + }; + + ca_uart_debug_pmx: ca_uart_debug@0 { + ca_uart_debug { + groups = "ca_uart_debug_grp"; + function = "ca_uart_debug"; + }; + }; + + clkc_pmx0: clkc@0 { + clkc_0 { + groups = "clkc_grp0"; + function = "clkc_m0"; + }; + }; + + clkc_pmx1: clkc@1 { + clkc_1 { + groups = "clkc_grp1"; + function = "clkc_m1"; + }; + }; + + gn_gnss_i2c_pmx: gn_gnss_i2c@0 { + gn_gnss_i2c { + groups = "gn_gnss_i2c_grp"; + function = "gn_gnss_i2c"; + }; + }; + + gn_gnss_uart_nopause_pmx: gn_gnss_uart_nopause@0 { + gn_gnss_uart_nopause { + groups = "gn_gnss_uart_nopause_grp"; + function = "gn_gnss_uart_nopause"; + }; + }; + + gn_gnss_uart_pmx: gn_gnss_uart@0 { + gn_gnss_uart { + groups = "gn_gnss_uart_grp"; + function = "gn_gnss_uart"; + }; + }; + + gn_trg_spi_pmx0: gn_trg_spi@0 { + gn_trg_spi_0 { + groups = "gn_trg_spi_grp0"; + function = "gn_trg_spi_m0"; + }; + }; + + gn_trg_spi_pmx1: gn_trg_spi@1 { + gn_trg_spi_1 { + groups = "gn_trg_spi_grp1"; + function = "gn_trg_spi_m1"; + }; + }; + + cvbs_dbg_pmx: cvbs_dbg@0 { + cvbs_dbg { + groups = "cvbs_dbg_grp"; + function = "cvbs_dbg"; + }; + }; + + cvbs_dbg_test_pmx0: cvbs_dbg_test@0 { + cvbs_dbg_test_0 { + groups = "cvbs_dbg_test_grp0"; + function = "cvbs_dbg_test_m0"; + }; + }; + + cvbs_dbg_test_pmx1: cvbs_dbg_test@1 { + cvbs_dbg_test_1 { + groups = "cvbs_dbg_test_grp1"; + function = "cvbs_dbg_test_m1"; + }; + }; + + cvbs_dbg_test_pmx2: cvbs_dbg_test@2 { + cvbs_dbg_test_2 { + groups = "cvbs_dbg_test_grp2"; + function = "cvbs_dbg_test_m2"; + }; + }; + + cvbs_dbg_test_pmx3: cvbs_dbg_test@3 { + cvbs_dbg_test_3 { + groups = "cvbs_dbg_test_grp3"; + function = "cvbs_dbg_test_m3"; + }; + }; + + cvbs_dbg_test_pmx4: cvbs_dbg_test@4 { + cvbs_dbg_test_4 { + groups = "cvbs_dbg_test_grp4"; + function = "cvbs_dbg_test_m4"; + }; + }; + + cvbs_dbg_test_pmx5: cvbs_dbg_test@5 { + cvbs_dbg_test_5 { + groups = "cvbs_dbg_test_grp5"; + function = "cvbs_dbg_test_m5"; + }; + }; + + cvbs_dbg_test_pmx6: cvbs_dbg_test@6 { + cvbs_dbg_test_6 { + groups = "cvbs_dbg_test_grp6"; + function = "cvbs_dbg_test_m6"; + }; + }; + + cvbs_dbg_test_pmx7: cvbs_dbg_test@7 { + cvbs_dbg_test_7 { + groups = "cvbs_dbg_test_grp7"; + function = "cvbs_dbg_test_m7"; + }; + }; + + cvbs_dbg_test_pmx8: cvbs_dbg_test@8 { + cvbs_dbg_test_8 { + groups = "cvbs_dbg_test_grp8"; + function = "cvbs_dbg_test_m8"; + }; + }; + + cvbs_dbg_test_pmx9: cvbs_dbg_test@9 { + cvbs_dbg_test_9 { + groups = "cvbs_dbg_test_grp9"; + function = "cvbs_dbg_test_m9"; + }; + }; + + cvbs_dbg_test_pmx10: cvbs_dbg_test@10 { + cvbs_dbg_test_10 { + groups = "cvbs_dbg_test_grp10"; + function = "cvbs_dbg_test_m10"; + }; + }; + + cvbs_dbg_test_pmx11: cvbs_dbg_test@11 { + cvbs_dbg_test_11 { + groups = "cvbs_dbg_test_grp11"; + function = "cvbs_dbg_test_m11"; + }; + }; + + cvbs_dbg_test_pmx12: cvbs_dbg_test@12 { + cvbs_dbg_test_12 { + groups = "cvbs_dbg_test_grp12"; + function = "cvbs_dbg_test_m12"; + }; + }; + + cvbs_dbg_test_pmx13: cvbs_dbg_test@13 { + cvbs_dbg_test_13 { + groups = "cvbs_dbg_test_grp13"; + function = "cvbs_dbg_test_m13"; + }; + }; + + cvbs_dbg_test_pmx14: cvbs_dbg_test@14 { + cvbs_dbg_test_14 { + groups = "cvbs_dbg_test_grp14"; + function = "cvbs_dbg_test_m14"; + }; + }; + + cvbs_dbg_test_pmx15: cvbs_dbg_test@15 { + cvbs_dbg_test_15 { + groups = "cvbs_dbg_test_grp15"; + function = "cvbs_dbg_test_m15"; + }; + }; + + gn_gnss_power_pmx: gn_gnss_power@0 { + gn_gnss_power { + groups = "gn_gnss_power_grp"; + function = "gn_gnss_power"; + }; + }; + + gn_gnss_sw_status_pmx: gn_gnss_sw_status@0 { + gn_gnss_sw_status { + groups = "gn_gnss_sw_status_grp"; + function = "gn_gnss_sw_status"; + }; + }; + + gn_gnss_eclk_pmx: gn_gnss_eclk@0 { + gn_gnss_eclk { + groups = "gn_gnss_eclk_grp"; + function = "gn_gnss_eclk"; + }; + }; + + gn_gnss_irq1_pmx0: gn_gnss_irq1@0 { + gn_gnss_irq1_0 { + groups = "gn_gnss_irq1_grp0"; + function = "gn_gnss_irq1_m0"; + }; + }; + + gn_gnss_irq2_pmx0: gn_gnss_irq2@0 { + gn_gnss_irq2_0 { + groups = "gn_gnss_irq2_grp0"; + function = "gn_gnss_irq2_m0"; + }; + }; + + gn_gnss_tm_pmx: gn_gnss_tm@0 { + gn_gnss_tm { + groups = "gn_gnss_tm_grp"; + function = "gn_gnss_tm"; + }; + }; + + gn_gnss_tsync_pmx: gn_gnss_tsync@0 { + gn_gnss_tsync { + groups = "gn_gnss_tsync_grp"; + function = "gn_gnss_tsync"; + }; + }; + + gn_io_gnsssys_sw_cfg_pmx: gn_io_gnsssys_sw_cfg@0 { + gn_io_gnsssys_sw_cfg { + groups = "gn_io_gnsssys_sw_cfg_grp"; + function = "gn_io_gnsssys_sw_cfg"; + }; + }; + + gn_trg_pmx0: gn_trg@0 { + gn_trg_0 { + groups = "gn_trg_grp0"; + function = "gn_trg_m0"; + }; + }; + + gn_trg_pmx1: gn_trg@1 { + gn_trg_1 { + groups = "gn_trg_grp1"; + function = "gn_trg_m1"; + }; + }; + + gn_trg_shutdown_pmx0: gn_trg_shutdown@0 { + gn_trg_shutdown_0 { + groups = "gn_trg_shutdown_grp0"; + function = "gn_trg_shutdown_m0"; + }; + }; + + gn_trg_shutdown_pmx1: gn_trg_shutdown@1 { + gn_trg_shutdown_1 { + groups = "gn_trg_shutdown_grp1"; + function = "gn_trg_shutdown_m1"; + }; + }; + + gn_trg_shutdown_pmx2: gn_trg_shutdown@2 { + gn_trg_shutdown_2 { + groups = "gn_trg_shutdown_grp2"; + function = "gn_trg_shutdown_m2"; + }; + }; + + gn_trg_shutdown_pmx3: gn_trg_shutdown@3 { + gn_trg_shutdown_3 { + groups = "gn_trg_shutdown_grp3"; + function = "gn_trg_shutdown_m3"; + }; + }; + + i2c0_pmx: i2c0@0 { + i2c0 { + groups = "i2c0_grp"; + function = "i2c0"; + }; + }; + + i2c1_pmx: i2c1@0 { + i2c1 { + groups = "i2c1_grp"; + function = "i2c1"; + }; + }; + + jtag_pmx0: jtag@0 { + jtag_0 { + groups = "jtag_grp0"; + function = "jtag_m0"; + }; + }; + + ks_kas_spi_pmx0: ks_kas_spi@0 { + ks_kas_spi_0 { + groups = "ks_kas_spi_grp0"; + function = "ks_kas_spi_m0"; + }; + }; + + ld_ldd_pmx: ld_ldd@0 { + ld_ldd { + groups = "ld_ldd_grp"; + function = "ld_ldd"; + }; + }; + + ld_ldd_16bit_pmx: ld_ldd_16bit@0 { + ld_ldd_16bit { + groups = "ld_ldd_16bit_grp"; + function = "ld_ldd_16bit"; + }; + }; + + ld_ldd_fck_pmx: ld_ldd_fck@0 { + ld_ldd_fck { + groups = "ld_ldd_fck_grp"; + function = "ld_ldd_fck"; + }; + }; + + ld_ldd_lck_pmx: ld_ldd_lck@0 { + ld_ldd_lck { + groups = "ld_ldd_lck_grp"; + function = "ld_ldd_lck"; + }; + }; + + lr_lcdrom_pmx: lr_lcdrom@0 { + lr_lcdrom { + groups = "lr_lcdrom_grp"; + function = "lr_lcdrom"; + }; + }; + + lvds_analog_pmx: lvds_analog@0 { + lvds_analog { + groups = "lvds_analog_grp"; + function = "lvds_analog"; + }; + }; + + nd_df_pmx: nd_df@0 { + nd_df { + groups = "nd_df_grp"; + function = "nd_df"; + }; + }; + + nd_df_nowp_pmx: nd_df_nowp@0 { + nd_df_nowp { + groups = "nd_df_nowp_grp"; + function = "nd_df_nowp"; + }; + }; + + ps_pmx: ps@0 { + ps { + groups = "ps_grp"; + function = "ps"; + }; + }; + + pwc_core_on_pmx: pwc_core_on@0 { + pwc_core_on { + groups = "pwc_core_on_grp"; + function = "pwc_core_on"; + }; + }; + + pwc_ext_on_pmx: pwc_ext_on@0 { + pwc_ext_on { + groups = "pwc_ext_on_grp"; + function = "pwc_ext_on"; + }; + }; + + pwc_gpio3_clk_pmx: pwc_gpio3_clk@0 { + pwc_gpio3_clk { + groups = "pwc_gpio3_clk_grp"; + function = "pwc_gpio3_clk"; + }; + }; + + pwc_io_on_pmx: pwc_io_on@0 { + pwc_io_on { + groups = "pwc_io_on_grp"; + function = "pwc_io_on"; + }; + }; + + pwc_lowbatt_b_pmx0: pwc_lowbatt_b@0 { + pwc_lowbatt_b_0 { + groups = "pwc_lowbatt_b_grp0"; + function = "pwc_lowbatt_b_m0"; + }; + }; + + pwc_mem_on_pmx: pwc_mem_on@0 { + pwc_mem_on { + groups = "pwc_mem_on_grp"; + function = "pwc_mem_on"; + }; + }; + + pwc_on_key_b_pmx0: pwc_on_key_b@0 { + pwc_on_key_b_0 { + groups = "pwc_on_key_b_grp0"; + function = "pwc_on_key_b_m0"; + }; + }; + + pwc_wakeup_src0_pmx: pwc_wakeup_src0@0 { + pwc_wakeup_src0 { + groups = "pwc_wakeup_src0_grp"; + function = "pwc_wakeup_src0"; + }; + }; + + pwc_wakeup_src1_pmx: pwc_wakeup_src1@0 { + pwc_wakeup_src1 { + groups = "pwc_wakeup_src1_grp"; + function = "pwc_wakeup_src1"; + }; + }; + + pwc_wakeup_src2_pmx: pwc_wakeup_src2@0 { + pwc_wakeup_src2 { + groups = "pwc_wakeup_src2_grp"; + function = "pwc_wakeup_src2"; + }; + }; + + pwc_wakeup_src3_pmx: pwc_wakeup_src3@0 { + pwc_wakeup_src3 { + groups = "pwc_wakeup_src3_grp"; + function = "pwc_wakeup_src3"; + }; + }; + + pw_cko0_pmx0: pw_cko0@0 { + pw_cko0_0 { + groups = "pw_cko0_grp0"; + function = "pw_cko0_m0"; + }; + }; + + pw_cko0_pmx1: pw_cko0@1 { + pw_cko0_1 { + groups = "pw_cko0_grp1"; + function = "pw_cko0_m1"; + }; + }; + + pw_cko0_pmx2: pw_cko0@2 { + pw_cko0_2 { + groups = "pw_cko0_grp2"; + function = "pw_cko0_m2"; + }; + }; + + pw_cko1_pmx0: pw_cko1@0 { + pw_cko1_0 { + groups = "pw_cko1_grp0"; + function = "pw_cko1_m0"; + }; + }; + + pw_cko1_pmx1: pw_cko1@1 { + pw_cko1_1 { + groups = "pw_cko1_grp1"; + function = "pw_cko1_m1"; + }; + }; + + pw_i2s01_clk_pmx0: pw_i2s01_clk@0 { + pw_i2s01_clk_0 { + groups = "pw_i2s01_clk_grp0"; + function = "pw_i2s01_clk_m0"; + }; + }; + + pw_i2s01_clk_pmx1: pw_i2s01_clk@1 { + pw_i2s01_clk_1 { + groups = "pw_i2s01_clk_grp1"; + function = "pw_i2s01_clk_m1"; + }; + }; + + pw_pwm0_pmx: pw_pwm0@0 { + pw_pwm0 { + groups = "pw_pwm0_grp"; + function = "pw_pwm0"; + }; + }; + + pw_pwm1_pmx: pw_pwm1@0 { + pw_pwm1 { + groups = "pw_pwm1_grp"; + function = "pw_pwm1"; + }; + }; + + pw_pwm2_pmx0: pw_pwm2@0 { + pw_pwm2_0 { + groups = "pw_pwm2_grp0"; + function = "pw_pwm2_m0"; + }; + }; + + pw_pwm2_pmx1: pw_pwm2@1 { + pw_pwm2_1 { + groups = "pw_pwm2_grp1"; + function = "pw_pwm2_m1"; + }; + }; + + pw_pwm3_pmx0: pw_pwm3@0 { + pw_pwm3_0 { + groups = "pw_pwm3_grp0"; + function = "pw_pwm3_m0"; + }; + }; + + pw_pwm3_pmx1: pw_pwm3@1 { + pw_pwm3_1 { + groups = "pw_pwm3_grp1"; + function = "pw_pwm3_m1"; + }; + }; + + pw_pwm_cpu_vol_pmx0: pw_pwm_cpu_vol@0 { + pw_pwm_cpu_vol_0 { + groups = "pw_pwm_cpu_vol_grp0"; + function = "pw_pwm_cpu_vol_m0"; + }; + }; + + pw_pwm_cpu_vol_pmx1: pw_pwm_cpu_vol@1 { + pw_pwm_cpu_vol_1 { + groups = "pw_pwm_cpu_vol_grp1"; + function = "pw_pwm_cpu_vol_m1"; + }; + }; + + pw_backlight_pmx0: pw_backlight@0 { + pw_backlight_0 { + groups = "pw_backlight_grp0"; + function = "pw_backlight_m0"; + }; + }; + + pw_backlight_pmx1: pw_backlight@1 { + pw_backlight_1 { + groups = "pw_backlight_grp1"; + function = "pw_backlight_m1"; + }; + }; + + rg_eth_mac_pmx: rg_eth_mac@0 { + rg_eth_mac { + groups = "rg_eth_mac_grp"; + function = "rg_eth_mac"; + }; + }; + + rg_gmac_phy_intr_n_pmx: rg_gmac_phy_intr_n@0 { + rg_gmac_phy_intr_n { + groups = "rg_gmac_phy_intr_n_grp"; + function = "rg_gmac_phy_intr_n"; + }; + }; + + rg_rgmii_mac_pmx: rg_rgmii_mac@0 { + rg_rgmii_mac { + groups = "rg_rgmii_mac_grp"; + function = "rg_rgmii_mac"; + }; + }; + + rg_rgmii_phy_ref_clk_pmx0: rg_rgmii_phy_ref_clk@0 { + rg_rgmii_phy_ref_clk_0 { + groups = + "rg_rgmii_phy_ref_clk_grp0"; + function = + "rg_rgmii_phy_ref_clk_m0"; + }; + }; + + rg_rgmii_phy_ref_clk_pmx1: rg_rgmii_phy_ref_clk@1 { + rg_rgmii_phy_ref_clk_1 { + groups = + "rg_rgmii_phy_ref_clk_grp1"; + function = + "rg_rgmii_phy_ref_clk_m1"; + }; + }; + + sd0_pmx: sd0@0 { + sd0 { + groups = "sd0_grp"; + function = "sd0"; + }; + }; + + sd0_4bit_pmx: sd0_4bit@0 { + sd0_4bit { + groups = "sd0_4bit_grp"; + function = "sd0_4bit"; + }; + }; + + sd1_pmx: sd1@0 { + sd1 { + groups = "sd1_grp"; + function = "sd1"; + }; + }; + + sd1_4bit_pmx0: sd1_4bit@0 { + sd1_4bit_0 { + groups = "sd1_4bit_grp0"; + function = "sd1_4bit_m0"; + }; + }; + + sd1_4bit_pmx1: sd1_4bit@1 { + sd1_4bit_1 { + groups = "sd1_4bit_grp1"; + function = "sd1_4bit_m1"; + }; + }; + + sd2_pmx0: sd2@0 { + sd2_0 { + groups = "sd2_grp0"; + function = "sd2_m0"; + }; + }; + + sd2_no_cdb_pmx0: sd2_no_cdb@0 { + sd2_no_cdb_0 { + groups = "sd2_no_cdb_grp0"; + function = "sd2_no_cdb_m0"; + }; + }; + + sd3_pmx: sd3@0 { + sd3 { + groups = "sd3_grp"; + function = "sd3"; + }; + }; + + sd5_pmx: sd5@0 { + sd5 { + groups = "sd5_grp"; + function = "sd5"; + }; + }; + + sd6_pmx0: sd6@0 { + sd6_0 { + groups = "sd6_grp0"; + function = "sd6_m0"; + }; + }; + + sd6_pmx1: sd6@1 { + sd6_1 { + groups = "sd6_grp1"; + function = "sd6_m1"; + }; + }; + + sp0_ext_ldo_on_pmx: sp0_ext_ldo_on@0 { + sp0_ext_ldo_on { + groups = "sp0_ext_ldo_on_grp"; + function = "sp0_ext_ldo_on"; + }; + }; + + sp0_qspi_pmx: sp0_qspi@0 { + sp0_qspi { + groups = "sp0_qspi_grp"; + function = "sp0_qspi"; + }; + }; + + sp1_spi_pmx: sp1_spi@0 { + sp1_spi { + groups = "sp1_spi_grp"; + function = "sp1_spi"; + }; + }; + + tpiu_trace_pmx: tpiu_trace@0 { + tpiu_trace { + groups = "tpiu_trace_grp"; + function = "tpiu_trace"; + }; + }; + + uart0_pmx: uart0@0 { + uart0 { + groups = "uart0_grp"; + function = "uart0"; + }; + }; + + uart0_nopause_pmx: uart0_nopause@0 { + uart0_nopause { + groups = "uart0_nopause_grp"; + function = "uart0_nopause"; + }; + }; + + uart1_pmx: uart1@0 { + uart1 { + groups = "uart1_grp"; + function = "uart1"; + }; + }; + + uart2_pmx: uart2@0 { + uart2 { + groups = "uart2_grp"; + function = "uart2"; + }; + }; + + uart3_pmx0: uart3@0 { + uart3_0 { + groups = "uart3_grp0"; + function = "uart3_m0"; + }; + }; + + uart3_pmx1: uart3@1 { + uart3_1 { + groups = "uart3_grp1"; + function = "uart3_m1"; + }; + }; + + uart3_pmx2: uart3@2 { + uart3_2 { + groups = "uart3_grp2"; + function = "uart3_m2"; + }; + }; + + uart3_pmx3: uart3@3 { + uart3_3 { + groups = "uart3_grp3"; + function = "uart3_m3"; + }; + }; + + uart3_nopause_pmx0: uart3_nopause@0 { + uart3_nopause_0 { + groups = "uart3_nopause_grp0"; + function = "uart3_nopause_m0"; + }; + }; + + uart3_nopause_pmx1: uart3_nopause@1 { + uart3_nopause_1 { + groups = "uart3_nopause_grp1"; + function = "uart3_nopause_m1"; + }; + }; + + uart4_pmx0: uart4@0 { + uart4_0 { + groups = "uart4_grp0"; + function = "uart4_m0"; + }; + }; + + uart4_pmx1: uart4@1 { + uart4_1 { + groups = "uart4_grp1"; + function = "uart4_m1"; + }; + }; + + uart4_pmx2: uart4@2 { + uart4_2 { + groups = "uart4_grp2"; + function = "uart4_m2"; + }; + }; + + uart4_nopause_pmx: uart4_nopause@0 { + uart4_nopause { + groups = "uart4_nopause_grp"; + function = "uart4_nopause"; + }; + }; + + usb0_drvvbus_pmx: usb0_drvvbus@0 { + usb0_drvvbus { + groups = "usb0_drvvbus_grp"; + function = "usb0_drvvbus"; + }; + }; + + usb1_drvvbus_pmx: usb1_drvvbus@0 { + usb1_drvvbus { + groups = "usb1_drvvbus_grp"; + function = "usb1_drvvbus"; + }; + }; + + visbus_dout_pmx: visbus_dout@0 { + visbus_dout { + groups = "visbus_dout_grp"; + function = "visbus_dout"; + }; + }; + + vi_vip1_pmx: vi_vip1@0 { + vi_vip1 { + groups = "vi_vip1_grp"; + function = "vi_vip1"; + }; + }; + + vi_vip1_ext_pmx: vi_vip1_ext@0 { + vi_vip1_ext { + groups = "vi_vip1_ext_grp"; + function = "vi_vip1_ext"; + }; + }; + + vi_vip1_low8bit_pmx: vi_vip1_low8bit@0 { + vi_vip1_low8bit { + groups = "vi_vip1_low8bit_grp"; + function = "vi_vip1_low8bit"; + }; + }; + + vi_vip1_high8bit_pmx: vi_vip1_high8bit@0 { + vi_vip1_high8bit { + groups = "vi_vip1_high8bit_grp"; + function = "vi_vip1_high8bit"; + }; + }; }; pmipc { @@ -356,6 +1375,12 @@ clock-names = "gpio0_io"; gpio-controller; interrupt-controller; + + gpio-banks = <2>; + gpio-ranges = <&pinctrl 0 0 0>, + <&pinctrl 32 0 0>; + gpio-ranges-group-names = "lvds_gpio_grp", + "uart_nand_gpio_grp"; }; nand@17050000 { @@ -461,11 +1486,22 @@ #interrupt-cells = <2>; compatible = "sirf,atlas7-gpio"; reg = <0x13300000 0x1000>; - interrupts = <0 43 0>, <0 44 0>, <0 45 0>; + interrupts = <0 43 0>, <0 44 0>, + <0 45 0>, <0 46 0>; clocks = <&car 84>; clock-names = "gpio1_io"; gpio-controller; interrupt-controller; + + gpio-banks = <4>; + gpio-ranges = <&pinctrl 0 0 0>, + <&pinctrl 32 0 0>, + <&pinctrl 64 0 0>, + <&pinctrl 96 0 0>; + gpio-ranges-group-names = "gnss_gpio_grp", + "lcd_vip_gpio_grp", + "sdio_i2s_gpio_grp", + "sp_rgmii_gpio_grp"; }; sd2: sdhci@14200000 { @@ -744,6 +1780,10 @@ interrupts = <0 47 0>; gpio-controller; interrupt-controller; + + gpio-banks = <1>; + gpio-ranges = <&pinctrl 0 0 0>; + gpio-ranges-group-names = "rtc_gpio_grp"; }; rtc-iobg@18840000 { diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 107395c32d82..17f63f7dfd9e 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -150,6 +150,16 @@ interface-type = "ace"; reg = <0x5000 0x1000>; }; + + pmu@9000 { + compatible = "arm,cci-400-pmu,r0"; + reg = <0x9000 0x5000>; + interrupts = <0 105 4>, + <0 101 4>, + <0 102 4>, + <0 103 4>, + <0 104 4>; + }; }; memory-controller@7ffd0000 { @@ -187,11 +197,22 @@ <1 10 0xf08>; }; - pmu { + pmu_a15 { compatible = "arm,cortex-a15-pmu"; interrupts = <0 68 4>, <0 69 4>; - interrupt-affinity = <&cpu0>, <&cpu1>; + interrupt-affinity = <&cpu0>, + <&cpu1>; + }; + + pmu_a7 { + compatible = "arm,cortex-a7-pmu"; + interrupts = <0 128 4>, + <0 129 4>, + <0 130 4>; + interrupt-affinity = <&cpu2>, + <&cpu3>, + <&cpu4>; }; oscclk6a: oscclk6a { diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6d83a1bf0c74..5fd8df6f50ea 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -353,7 +353,6 @@ CONFIG_POWER_RESET_AS3722=y CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_KEYSTONE=y -CONFIG_POWER_RESET_SUN6I=y CONFIG_POWER_RESET_RMOBILE=y CONFIG_SENSORS_LM90=y CONFIG_SENSORS_LM95245=y diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 8ecba00dcd83..7ebc346bf9fa 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -2,6 +2,7 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y CONFIG_PERF_EVENTS=y +CONFIG_MODULES=y CONFIG_ARCH_SUNXI=y CONFIG_SMP=y CONFIG_NR_CPUS=8 @@ -77,7 +78,6 @@ CONFIG_SPI_SUN6I=y CONFIG_GPIO_SYSFS=y CONFIG_POWER_SUPPLY=y CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SUN6I=y CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_WATCHDOG=y @@ -87,6 +87,10 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_GPIO=y +CONFIG_FB=y +CONFIG_FB_SIMPLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1c3938f26beb..485982084fe9 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -140,16 +140,11 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) * The _caller variety takes a __builtin_return_address(0) value for * /proc/vmalloc to use - and should only be used in non-inline functions. */ -extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, - size_t, unsigned int, void *); extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, void *); - extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); -extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int); extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); extern void __iounmap(volatile void __iomem *addr); -extern void __arm_iounmap(volatile void __iomem *addr); extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); @@ -321,21 +316,24 @@ extern void _memset_io(volatile void __iomem *, int, size_t); static inline void memset_io(volatile void __iomem *dst, unsigned c, size_t count) { - memset((void __force *)dst, c, count); + extern void mmioset(void *, unsigned int, size_t); + mmioset((void __force *)dst, c, count); } #define memset_io(dst,c,count) memset_io(dst,c,count) static inline void memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { - memcpy(to, (const void __force *)from, count); + extern void mmiocpy(void *, const void *, size_t); + mmiocpy(to, (const void __force *)from, count); } #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) static inline void memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { - memcpy((void __force *)to, from, count); + extern void mmiocpy(void *, const void *, size_t); + mmiocpy((void __force *)to, from, count); } #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) @@ -348,18 +346,61 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, #endif /* readl */ /* - * ioremap and friends. + * ioremap() and friends. + * + * ioremap() takes a resource address, and size. Due to the ARM memory + * types, it is important to use the correct ioremap() function as each + * mapping has specific properties. + * + * Function Memory type Cacheability Cache hint + * ioremap() Device n/a n/a + * ioremap_nocache() Device n/a n/a + * ioremap_cache() Normal Writeback Read allocate + * ioremap_wc() Normal Non-cacheable n/a + * ioremap_wt() Normal Non-cacheable n/a + * + * All device mappings have the following properties: + * - no access speculation + * - no repetition (eg, on return from an exception) + * - number, order and size of accesses are maintained + * - unaligned accesses are "unpredictable" + * - writes may be delayed before they hit the endpoint device * - * ioremap takes a PCI memory address, as specified in - * Documentation/io-mapping.txt. + * ioremap_nocache() is the same as ioremap() as there are too many device + * drivers using this for device registers, and documentation which tells + * people to use it for such for this to be any different. This is not a + * safe fallback for memory-like mappings, or memory regions where the + * compiler may generate unaligned accesses - eg, via inlining its own + * memcpy. * + * All normal memory mappings have the following properties: + * - reads can be repeated with no side effects + * - repeated reads return the last value written + * - reads can fetch additional locations without side effects + * - writes can be repeated (in certain cases) with no side effects + * - writes can be merged before accessing the target + * - unaligned accesses can be supported + * - ordering is not guaranteed without explicit dependencies or barrier + * instructions + * - writes may be delayed before they hit the endpoint memory + * + * The cache hint is only a performance hint: CPUs may alias these hints. + * Eg, a CPU not implementing read allocate but implementing write allocate + * will provide a write allocate mapping instead. */ -#define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) -#define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC) -#define ioremap_wt(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define iounmap __arm_iounmap +void __iomem *ioremap(resource_size_t res_cookie, size_t size); +#define ioremap ioremap +#define ioremap_nocache ioremap + +void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size); +#define ioremap_cache ioremap_cache + +void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size); +#define ioremap_wc ioremap_wc +#define ioremap_wt ioremap_wc + +void iounmap(volatile void __iomem *iomem_cookie); +#define iounmap iounmap /* * io{read,write}{16,32}be() macros diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 3a72d69b3255..6f225acc07c5 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -275,7 +275,7 @@ static inline void *phys_to_virt(phys_addr_t x) */ #define __pa(x) __virt_to_phys((unsigned long)(x)) #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) -#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) +#define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT) extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x); diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index bfd662e49a25..aeddd28b3595 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h @@ -129,7 +129,36 @@ /* * These are the memory types, defined to be compatible with - * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB + * pre-ARMv6 CPUs cacheable and bufferable bits: n/a,n/a,C,B + * ARMv6+ without TEX remapping, they are a table index. + * ARMv6+ with TEX remapping, they correspond to n/a,TEX(0),C,B + * + * MT type Pre-ARMv6 ARMv6+ type / cacheable status + * UNCACHED Uncached Strongly ordered + * BUFFERABLE Bufferable Normal memory / non-cacheable + * WRITETHROUGH Writethrough Normal memory / write through + * WRITEBACK Writeback Normal memory / write back, read alloc + * MINICACHE Minicache N/A + * WRITEALLOC Writeback Normal memory / write back, write alloc + * DEV_SHARED Uncached Device memory (shared) + * DEV_NONSHARED Uncached Device memory (non-shared) + * DEV_WC Bufferable Normal memory / non-cacheable + * DEV_CACHED Writeback Normal memory / write back, read alloc + * VECTORS Variable Normal memory / variable + * + * All normal memory mappings have the following properties: + * - reads can be repeated with no side effects + * - repeated reads return the last value written + * - reads can fetch additional locations without side effects + * - writes can be repeated (in certain cases) with no side effects + * - writes can be merged before accessing the target + * - unaligned accesses can be supported + * + * All device mappings have the following properties: + * - no access speculation + * - no repetition (eg, on return from an exception) + * - number, order and size of accesses are maintained + * - unaligned accesses are "unpredictable" */ #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ diff --git a/arch/arm/include/debug/at91.S b/arch/arm/include/debug/at91.S index c3c45e628e33..2556a8801c8c 100644 --- a/arch/arm/include/debug/at91.S +++ b/arch/arm/include/debug/at91.S @@ -13,9 +13,12 @@ #define AT91_DBGU 0xfffff200 /* AT91_BASE_DBGU0 */ #elif defined(CONFIG_AT91_DEBUG_LL_DBGU1) #define AT91_DBGU 0xffffee00 /* AT91_BASE_DBGU1 */ -#else +#elif defined(CONFIG_AT91_DEBUG_LL_DBGU2) /* On sama5d4, use USART3 as low level serial console */ #define AT91_DBGU 0xfc00c000 /* SAMA5D4_BASE_USART3 */ +#else +/* On sama5d2, use UART1 as low level serial console */ +#define AT91_DBGU 0xf8020000 #endif #ifdef CONFIG_MMU diff --git a/arch/arm/include/debug/zynq.S b/arch/arm/include/debug/zynq.S index bd13dedbdeff..de86b9247564 100644 --- a/arch/arm/include/debug/zynq.S +++ b/arch/arm/include/debug/zynq.S @@ -38,7 +38,7 @@ .endm .macro senduart,rd,rx - str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA + strb \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA .endm .macro waituart,rd,rx diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index a88671cfe1ff..5e5a51a99e68 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -50,6 +50,9 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); +void mmioset(void *, unsigned int, size_t); +void mmiocpy(void *, const void *, size_t); + /* platform dependent support */ EXPORT_SYMBOL(arm_delay_ops); @@ -88,6 +91,9 @@ EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(__memzero); +EXPORT_SYMBOL(mmioset); +EXPORT_SYMBOL(mmiocpy); + #ifdef CONFIG_MMU EXPORT_SYMBOL(copy_page); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7dac3086e361..cb4fb1e69778 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -410,7 +410,7 @@ ENDPROC(__fiq_abt) zero_fp .if \trace -#ifdef CONFIG_IRQSOFF_TRACER +#ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off #endif ct_user_exit save = 0 diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 90dfbedfbfb8..3d6b7821cff8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -578,7 +578,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); if ((unsigned)ipinr < NR_IPI) { - trace_ipi_entry(ipi_types[ipinr]); + trace_ipi_entry_rcuidle(ipi_types[ipinr]); __inc_irq_stat(cpu, ipi_irqs[ipinr]); } @@ -637,7 +637,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) } if ((unsigned)ipinr < NR_IPI) - trace_ipi_exit(ipi_types[ipinr]); + trace_ipi_exit_rcuidle(ipi_types[ipinr]); set_irq_regs(old_regs); } diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index 7797e81e40e0..64111bd4440b 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -61,8 +61,10 @@ /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ +ENTRY(mmiocpy) ENTRY(memcpy) #include "copy_template.S" ENDPROC(memcpy) +ENDPROC(mmiocpy) diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index a4ee97b5a2bf..3c65e3bd790f 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -16,6 +16,7 @@ .text .align 5 +ENTRY(mmioset) ENTRY(memset) UNWIND( .fnstart ) ands r3, r0, #3 @ 1 unaligned? @@ -133,3 +134,4 @@ UNWIND( .fnstart ) b 1b UNWIND( .fnend ) ENDPROC(memset) +ENDPROC(mmioset) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index fd95f34945f4..89a755b90db2 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -8,6 +8,18 @@ menuconfig ARCH_AT91 select SOC_BUS if ARCH_AT91 +config SOC_SAMA5D2 + bool "SAMA5D2 family" if ARCH_MULTI_V7 + select SOC_SAMA5 + select CACHE_L2X0 + select HAVE_FB_ATMEL + select HAVE_AT91_UTMI + select HAVE_AT91_USB_CLK + select HAVE_AT91_H32MX + select HAVE_AT91_GENERATED_CLK + help + Select this if ou are using one of Atmel's SAMA5D2 family SoC. + config SOC_SAMA5D3 bool "SAMA5D3 family" if ARCH_MULTI_V7 select SOC_SAMA5 diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index 41d829d8e7d5..90c3c3051ae7 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -18,6 +18,8 @@ #include "soc.h" static const struct at91_soc sama5_socs[] = { + AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27_EXID_MATCH, + "sama5d27", "sama5d2"), AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, "sama5d31", "sama5d3"), AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, @@ -64,6 +66,7 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5") MACHINE_END static const char *sama5_alt_dt_board_compat[] __initconst = { + "atmel,sama5d2", "atmel,sama5d4", NULL }; diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h index be23c400596b..8ede0ef86172 100644 --- a/arch/arm/mach-at91/soc.h +++ b/arch/arm/mach-at91/soc.h @@ -62,6 +62,9 @@ at91_soc_init(const struct at91_soc *socs); #define AT91SAM9XE256_CIDR_MATCH 0x329a93a0 #define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0 +#define SAMA5D2_CIDR_MATCH 0x0a5c08c0 +#define SAMA5D27_EXID_MATCH 0x00000021 + #define SAMA5D3_CIDR_MATCH 0x0a5c07c0 #define SAMA5D31_EXID_MATCH 0x00444300 #define SAMA5D33_EXID_MATCH 0x00414300 diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 0ac9e4b3b265..1319c3c14327 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -140,10 +140,12 @@ config ARCH_BCM_63XX config ARCH_BRCMSTB bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7 select ARM_GIC + select ARM_ERRATA_798181 if SMP select HAVE_ARM_ARCH_TIMER select BRCMSTB_GISB_ARB select BRCMSTB_L2_IRQ select BCM7120_L2_IRQ + select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_WANT_OPTIONAL_GPIOLIB help Say Y if you intend to run the kernel on a Broadcom ARM-based STB diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index 006dae8dfe44..9fda75c18c04 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -85,23 +85,13 @@ static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type) return 0; } -/* - * Faking this allows us to to work with suspend functions of - * generic drivers which call {enable|disable}_irq_wake for - * wake up interrupt sources (eg RTC on DA850). - */ -static int cp_intc_set_wake(struct irq_data *d, unsigned int on) -{ - return 0; -} - static struct irq_chip cp_intc_irq_chip = { .name = "cp_intc", .irq_ack = cp_intc_ack_irq, .irq_mask = cp_intc_mask_irq, .irq_unmask = cp_intc_unmask_irq, .irq_set_type = cp_intc_set_irq_type, - .irq_set_wake = cp_intc_set_wake, + .flags = IRQCHIP_SKIP_SET_WAKE, }; static struct irq_domain *cp_intc_domain; diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig index 9f59e58da3a4..aeece17e5cea 100644 --- a/arch/arm/mach-mediatek/Kconfig +++ b/arch/arm/mach-mediatek/Kconfig @@ -3,6 +3,7 @@ menuconfig ARCH_MEDIATEK select ARM_GIC select PINCTRL select MTK_TIMER + select MFD_SYSCON help Support for Mediatek MT65xx & MT81xx SoCs diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index e46e9ea1e187..44eedf331ae7 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -65,18 +65,6 @@ static const struct of_device_id of_coherency_table[] = { int ll_enable_coherency(void); void ll_add_cpu_to_smp_group(void); -int set_cpu_coherent(void) -{ - if (!coherency_base) { - pr_warn("Can't make current CPU cache coherent.\n"); - pr_warn("Coherency fabric is not initialized\n"); - return 1; - } - - ll_add_cpu_to_smp_group(); - return ll_enable_coherency(); -} - static int mvebu_hwcc_notifier(struct notifier_block *nb, unsigned long event, void *__dev) { @@ -206,6 +194,23 @@ static int coherency_type(void) return type; } +int set_cpu_coherent(void) +{ + int type = coherency_type(); + + if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) { + if (!coherency_base) { + pr_warn("Can't make current CPU cache coherent.\n"); + pr_warn("Coherency fabric is not initialized\n"); + return 1; + } + ll_add_cpu_to_smp_group(); + return ll_enable_coherency(); + } + + return 0; +} + int coherency_available(void) { return coherency_type() != COHERENCY_FABRIC_TYPE_NONE; diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index 3e0aca1f288a..6b775492cfad 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h @@ -25,6 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev); void __iomem *mvebu_get_scu_base(void); -int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)); - +int mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg, + u32 srcmd)); #endif diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c index 301ab38d38ba..db17121d7d63 100644 --- a/arch/arm/mach-mvebu/pm-board.c +++ b/arch/arm/mach-mvebu/pm-board.c @@ -1,7 +1,7 @@ /* * Board-level suspend/resume support. * - * Copyright (C) 2014 Marvell + * Copyright (C) 2014-2015 Marvell * * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * @@ -20,27 +20,27 @@ #include <linux/slab.h> #include "common.h" -#define ARMADA_XP_GP_PIC_NR_GPIOS 3 +#define ARMADA_PIC_NR_GPIOS 3 static void __iomem *gpio_ctrl; -static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; -static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; +static int pic_gpios[ARMADA_PIC_NR_GPIOS]; +static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS]; -static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd) +static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd) { u32 reg, ackcmd; int i; /* Put 001 as value on the GPIOs */ reg = readl(gpio_ctrl); - for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) + for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) reg &= ~BIT(pic_raw_gpios[i]); reg |= BIT(pic_raw_gpios[0]); writel(reg, gpio_ctrl); /* Prepare writing 111 to the GPIOs */ ackcmd = readl(gpio_ctrl); - for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) + for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) ackcmd |= BIT(pic_raw_gpios[i]); srcmd = cpu_to_le32(srcmd); @@ -76,7 +76,7 @@ static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd) [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1"); } -static int mvebu_armada_xp_gp_pm_init(void) +static int __init mvebu_armada_pm_init(void) { struct device_node *np; struct device_node *gpio_ctrl_np; @@ -89,7 +89,7 @@ static int mvebu_armada_xp_gp_pm_init(void) if (!np) return -ENODEV; - for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) { + for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) { char *name; struct of_phandle_args args; @@ -134,11 +134,19 @@ static int mvebu_armada_xp_gp_pm_init(void) if (!gpio_ctrl) return -ENOMEM; - mvebu_pm_init(mvebu_armada_xp_gp_pm_enter); + mvebu_pm_suspend_init(mvebu_armada_pm_enter); out: of_node_put(np); return ret; } -late_initcall(mvebu_armada_xp_gp_pm_init); +/* + * Registering the mvebu_board_pm_enter callback must be done before + * the platform_suspend_ops will be registered. In the same time we + * also need to have the gpio devices registered. That's why we use a + * device_initcall_sync which is called after all the device_initcall + * (used by the gpio device) but before the late_initcall (used to + * register the platform_suspend_ops) + */ +device_initcall_sync(mvebu_armada_pm_init); diff --git a/arch/arm/mach-mvebu/pm.c b/arch/arm/mach-mvebu/pm.c index 6573a8f11f70..8d32bf762b86 100644 --- a/arch/arm/mach-mvebu/pm.c +++ b/arch/arm/mach-mvebu/pm.c @@ -105,12 +105,10 @@ static phys_addr_t mvebu_internal_reg_base(void) return of_translate_address(np, in_addr); } -static void mvebu_pm_store_bootinfo(void) +static void mvebu_pm_store_armadaxp_bootinfo(u32 *store_addr) { - u32 *store_addr; phys_addr_t resume_pc; - store_addr = phys_to_virt(BOOT_INFO_ADDR); resume_pc = virt_to_phys(armada_370_xp_cpu_resume); /* @@ -151,14 +149,30 @@ static void mvebu_pm_store_bootinfo(void) writel(BOOT_MAGIC_LIST_END, store_addr); } -static int mvebu_pm_enter(suspend_state_t state) +static int mvebu_pm_store_bootinfo(void) { - if (state != PM_SUSPEND_MEM) - return -EINVAL; + u32 *store_addr; + + store_addr = phys_to_virt(BOOT_INFO_ADDR); + + if (of_machine_is_compatible("marvell,armadaxp")) + mvebu_pm_store_armadaxp_bootinfo(store_addr); + else + return -ENODEV; + + return 0; +} + +static int mvebu_enter_suspend(void) +{ + int ret; + + ret = mvebu_pm_store_bootinfo(); + if (ret) + return ret; cpu_pm_enter(); - mvebu_pm_store_bootinfo(); cpu_suspend(0, mvebu_pm_powerdown); outer_resume(); @@ -168,23 +182,62 @@ static int mvebu_pm_enter(suspend_state_t state) set_cpu_coherent(); cpu_pm_exit(); + return 0; +} + +static int mvebu_pm_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + cpu_do_idle(); + break; + case PM_SUSPEND_MEM: + pr_warn("Entering suspend to RAM. Only special wake-up sources will resume the system\n"); + return mvebu_enter_suspend(); + default: + return -EINVAL; + } + return 0; +} + +static int mvebu_pm_valid(suspend_state_t state) +{ + if (state == PM_SUSPEND_STANDBY) + return 1; + + if (state == PM_SUSPEND_MEM && mvebu_board_pm_enter != NULL) + return 1; return 0; } static const struct platform_suspend_ops mvebu_pm_ops = { .enter = mvebu_pm_enter, - .valid = suspend_valid_only_mem, + .valid = mvebu_pm_valid, }; -int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) +static int __init mvebu_pm_init(void) +{ + if (!of_machine_is_compatible("marvell,armadaxp") && + !of_machine_is_compatible("marvell,armada370") && + !of_machine_is_compatible("marvell,armada380") && + !of_machine_is_compatible("marvell,armada390")) + return -ENODEV; + + suspend_set_ops(&mvebu_pm_ops); + + return 0; +} + + +late_initcall(mvebu_pm_init); + +int __init mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg, + u32 srcmd)) { struct device_node *np; struct resource res; - if (!of_machine_is_compatible("marvell,armadaxp")) - return -ENODEV; - np = of_find_compatible_node(NULL, NULL, "marvell,armada-xp-sdram-controller"); if (!np) @@ -212,7 +265,5 @@ int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) mvebu_board_pm_enter = board_pm_enter; - suspend_set_ops(&mvebu_pm_ops); - return 0; } diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 903c85be2897..d4579f856b25 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -234,8 +234,7 @@ obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o # EMU peripherals obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o -iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o -obj-y += $(iommu-m) $(iommu-y) +obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o # OMAP2420 MSDI controller integration support ("MMC") obj-$(CONFIG_SOC_OMAP2420) += msdi.o diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 34ff14b7beab..24c9afc9e8a7 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -169,7 +169,7 @@ static const char *const ti814x_boards_compat[] __initconst = { NULL, }; -DT_MACHINE_START(TI81XX_DT, "Generic ti814x (Flattened Device Tree)") +DT_MACHINE_START(TI814X_DT, "Generic ti814x (Flattened Device Tree)") .reserve = omap_reserve, .map_io = ti81xx_map_io, .init_early = ti814x_init_early, @@ -297,7 +297,7 @@ static const char *const dra74x_boards_compat[] __initconst = { DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)") .reserve = omap_reserve, .smp = smp_ops(omap4_smp_ops), - .map_io = omap5_map_io, + .map_io = dra7xx_map_io, .init_early = dra7xx_init_early, .init_late = dra7xx_init_late, .init_irq = omap_gic_of_init, @@ -316,7 +316,7 @@ static const char *const dra72x_boards_compat[] __initconst = { DT_MACHINE_START(DRA72X_DT, "Generic DRA72X (Flattened Device Tree)") .reserve = omap_reserve, - .map_io = omap5_map_io, + .map_io = dra7xx_map_io, .init_early = dra7xx_init_early, .init_late = dra7xx_init_late, .init_irq = omap_gic_of_init, diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 77bab5fb6814..2c398ce1a0f2 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -216,7 +216,8 @@ extern void __init omap242x_clockdomains_init(void); extern void __init omap243x_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); extern void __init am33xx_clockdomains_init(void); -extern void __init ti81xx_clockdomains_init(void); +extern void __init ti814x_clockdomains_init(void); +extern void __init ti816x_clockdomains_init(void); extern void __init omap44xx_clockdomains_init(void); extern void __init omap54xx_clockdomains_init(void); extern void __init dra7xx_clockdomains_init(void); diff --git a/arch/arm/mach-omap2/clockdomains7xx_data.c b/arch/arm/mach-omap2/clockdomains7xx_data.c index 57d5df0c1fbd..7581e036bda6 100644 --- a/arch/arm/mach-omap2/clockdomains7xx_data.c +++ b/arch/arm/mach-omap2/clockdomains7xx_data.c @@ -331,7 +331,7 @@ static struct clockdomain l4per2_7xx_clkdm = { .dep_bit = DRA7XX_L4PER2_STATDEP_SHIFT, .wkdep_srcs = l4per2_wkup_sleep_deps, .sleepdep_srcs = l4per2_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, + .flags = CLKDM_CAN_SWSUP, }; static struct clockdomain mpu0_7xx_clkdm = { diff --git a/arch/arm/mach-omap2/clockdomains81xx_data.c b/arch/arm/mach-omap2/clockdomains81xx_data.c index ce2a82001d0d..53442c86a820 100644 --- a/arch/arm/mach-omap2/clockdomains81xx_data.c +++ b/arch/arm/mach-omap2/clockdomains81xx_data.c @@ -165,7 +165,24 @@ static struct clockdomain default_l3_slow_816x_clkdm = { .flags = CLKDM_CAN_SWSUP, }; -static struct clockdomain *clockdomains_ti81xx[] __initdata = { +static struct clockdomain *clockdomains_ti814x[] __initdata = { + &alwon_l3_slow_81xx_clkdm, + &alwon_l3_med_81xx_clkdm, + &alwon_l3_fast_81xx_clkdm, + &alwon_ethernet_81xx_clkdm, + &mmu_81xx_clkdm, + &mmu_cfg_81xx_clkdm, + NULL, +}; + +void __init ti814x_clockdomains_init(void) +{ + clkdm_register_platform_funcs(&am33xx_clkdm_operations); + clkdm_register_clkdms(clockdomains_ti814x); + clkdm_complete_init(); +} + +static struct clockdomain *clockdomains_ti816x[] __initdata = { &alwon_mpu_816x_clkdm, &alwon_l3_slow_81xx_clkdm, &alwon_l3_med_81xx_clkdm, @@ -185,10 +202,10 @@ static struct clockdomain *clockdomains_ti81xx[] __initdata = { NULL, }; -void __init ti81xx_clockdomains_init(void) +void __init ti816x_clockdomains_init(void) { clkdm_register_platform_funcs(&am33xx_clkdm_operations); - clkdm_register_clkdms(clockdomains_ti81xx); + clkdm_register_clkdms(clockdomains_ti816x); clkdm_complete_init(); } #endif diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index cf3cf22ecd42..749d50bb4ca5 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -198,6 +198,7 @@ void __init omap3_map_io(void); void __init am33xx_map_io(void); void __init omap4_map_io(void); void __init omap5_map_io(void); +void __init dra7xx_map_io(void); void __init ti81xx_map_io(void); /** diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index f008930277ed..cf5855174c93 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -652,6 +652,7 @@ static const struct of_device_id omap_scrm_dt_match_table[] = { { .compatible = "ti,am4-scm", .data = &ctrl_data }, { .compatible = "ti,omap2-scm", .data = &omap2_ctrl_data }, { .compatible = "ti,omap3-scm", .data = &omap2_ctrl_data }, + { .compatible = "ti,dm814-scm", .data = &ctrl_data }, { .compatible = "ti,dm816-scrm", .data = &ctrl_data }, { .compatible = "ti,omap4-scm-core", .data = &ctrl_data }, { .compatible = "ti,omap5-scm-core", .data = &ctrl_data }, diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index e1a56d87599e..1ed4be184a29 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -117,7 +117,6 @@ static void omap2_show_dma_caps(void) u8 revision = dma_read(REVISION, 0) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", revision >> 4, revision & 0xf); - return; } static unsigned configure_dma_errata(void) diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 820dde8b5b04..4025e734ebd2 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -236,7 +236,7 @@ static struct map_desc omap44xx_io_desc[] __initdata = { }; #endif -#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) +#ifdef CONFIG_SOC_OMAP5 static struct map_desc omap54xx_io_desc[] __initdata = { { .virtual = L3_54XX_VIRT, @@ -265,6 +265,53 @@ static struct map_desc omap54xx_io_desc[] __initdata = { }; #endif +#ifdef CONFIG_SOC_DRA7XX +static struct map_desc dra7xx_io_desc[] __initdata = { + { + .virtual = L4_CFG_MPU_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L4_CFG_MPU_DRA7XX_PHYS), + .length = L4_CFG_MPU_DRA7XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L3_MAIN_SN_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L3_MAIN_SN_DRA7XX_PHYS), + .length = L3_MAIN_SN_DRA7XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_PER1_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L4_PER1_DRA7XX_PHYS), + .length = L4_PER1_DRA7XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_PER2_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L4_PER2_DRA7XX_PHYS), + .length = L4_PER2_DRA7XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_PER3_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L4_PER3_DRA7XX_PHYS), + .length = L4_PER3_DRA7XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_CFG_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L4_CFG_DRA7XX_PHYS), + .length = L4_CFG_DRA7XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_WKUP_DRA7XX_VIRT, + .pfn = __phys_to_pfn(L4_WKUP_DRA7XX_PHYS), + .length = L4_WKUP_DRA7XX_SIZE, + .type = MT_DEVICE, + }, +}; +#endif + #ifdef CONFIG_SOC_OMAP2420 void __init omap242x_map_io(void) { @@ -309,12 +356,19 @@ void __init omap4_map_io(void) } #endif -#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) +#ifdef CONFIG_SOC_OMAP5 void __init omap5_map_io(void) { iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc)); } #endif + +#ifdef CONFIG_SOC_DRA7XX +void __init dra7xx_map_io(void) +{ + iotable_init(dra7xx_io_desc, ARRAY_SIZE(dra7xx_io_desc)); +} +#endif /* * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters * @@ -554,11 +608,11 @@ void __init ti814x_init_early(void) omap2_prcm_base_init(); omap3xxx_voltagedomains_init(); omap3xxx_powerdomains_init(); - ti81xx_clockdomains_init(); - ti81xx_hwmod_init(); + ti814x_clockdomains_init(); + dm814x_hwmod_init(); omap_hwmod_init_postsetup(); if (of_have_populated_dt()) - omap_clk_soc_init = ti81xx_dt_clk_init; + omap_clk_soc_init = dm814x_dt_clk_init; } void __init ti816x_init_early(void) @@ -571,11 +625,11 @@ void __init ti816x_init_early(void) omap2_prcm_base_init(); omap3xxx_voltagedomains_init(); omap3xxx_powerdomains_init(); - ti81xx_clockdomains_init(); - ti81xx_hwmod_init(); + ti816x_clockdomains_init(); + dm816x_hwmod_init(); omap_hwmod_init_postsetup(); if (of_have_populated_dt()) - omap_clk_soc_init = ti81xx_dt_clk_init; + omap_clk_soc_init = dm816x_dt_clk_init; } #endif diff --git a/arch/arm/mach-omap2/iomap.h b/arch/arm/mach-omap2/iomap.h index cce2b65039f1..6191d244438a 100644 --- a/arch/arm/mach-omap2/iomap.h +++ b/arch/arm/mach-omap2/iomap.h @@ -194,3 +194,66 @@ #define L4_PER_54XX_PHYS L4_PER_54XX_BASE /* 0x48000000 --> 0xfa000000 */ #define L4_PER_54XX_VIRT (L4_PER_54XX_PHYS + OMAP2_L4_IO_OFFSET) #define L4_PER_54XX_SIZE SZ_4M + +/* + * ---------------------------------------------------------------------------- + * DRA7xx specific IO mapping + * ---------------------------------------------------------------------------- + */ +/* + * L3_MAIN_SN_DRA7XX_PHYS 0x44000000 --> 0xf8000000 + * The overall space is 24MiB (0x4400_0000<->0x457F_FFFF), but mapping + * everything is just inefficient, since, there are too many address holes. + */ +#define L3_MAIN_SN_DRA7XX_PHYS L3_MAIN_SN_DRA7XX_BASE +#define L3_MAIN_SN_DRA7XX_VIRT (L3_MAIN_SN_DRA7XX_PHYS + OMAP4_L3_IO_OFFSET) +#define L3_MAIN_SN_DRA7XX_SIZE SZ_1M + +/* + * L4_PER1_DRA7XX_PHYS (0x4800_000<>0x480D_2FFF) -> 0.82MiB (alloc 1MiB) + * (0x48000000<->0x48100000) <=> (0xFA000000<->0xFA100000) + */ +#define L4_PER1_DRA7XX_PHYS L4_PER1_DRA7XX_BASE +#define L4_PER1_DRA7XX_VIRT (L4_PER1_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_PER1_DRA7XX_SIZE SZ_1M + +/* + * L4_CFG_MPU_DRA7XX_PHYS (0x48210000<>0x482A_F2FF) -> 0.62MiB (alloc 1MiB) + * (0x48210000<->0x48310000) <=> (0xFA210000<->0xFA310000) + * NOTE: This is a bit of an orphan memory map sitting isolated in TRM + */ +#define L4_CFG_MPU_DRA7XX_PHYS L4_CFG_MPU_DRA7XX_BASE +#define L4_CFG_MPU_DRA7XX_VIRT (L4_CFG_MPU_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_CFG_MPU_DRA7XX_SIZE SZ_1M + +/* + * L4_PER2_DRA7XX_PHYS (0x4840_0000<>0x4848_8FFF) -> .53MiB (alloc 1MiB) + * (0x48400000<->0x48500000) <=> (0xFA400000<->0xFA500000) + */ +#define L4_PER2_DRA7XX_PHYS L4_PER2_DRA7XX_BASE +#define L4_PER2_DRA7XX_VIRT (L4_PER2_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_PER2_DRA7XX_SIZE SZ_1M + +/* + * L4_PER3_DRA7XX_PHYS (0x4880_0000<>0x489E_0FFF) -> 1.87MiB (alloc 2MiB) + * (0x48800000<->0x48A00000) <=> (0xFA800000<->0xFAA00000) + */ +#define L4_PER3_DRA7XX_PHYS L4_PER3_DRA7XX_BASE +#define L4_PER3_DRA7XX_VIRT (L4_PER3_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_PER3_DRA7XX_SIZE SZ_2M + +/* + * L4_CFG_DRA7XX_PHYS (0x4A00_0000<>0x4A22_BFFF) ->2.17MiB (alloc 3MiB)? + * (0x4A000000<->0x4A300000) <=> (0xFC000000<->0xFC300000) + */ +#define L4_CFG_DRA7XX_PHYS L4_CFG_DRA7XX_BASE +#define L4_CFG_DRA7XX_VIRT (L4_CFG_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_CFG_DRA7XX_SIZE (SZ_1M + SZ_2M) + +/* + * L4_WKUP_DRA7XX_PHYS (0x4AE0_0000<>0x4AE3_EFFF) -> .24 mb (alloc 1MiB)? + * (0x4AE00000<->4AF00000) <=> (0xFCE00000<->0xFCF00000) + */ +#define L4_WKUP_DRA7XX_PHYS L4_WKUP_DRA7XX_BASE +#define L4_WKUP_DRA7XX_VIRT (L4_WKUP_DRA7XX_PHYS + OMAP2_L4_IO_OFFSET) +#define L4_WKUP_DRA7XX_SIZE SZ_1M diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c index 4068350f9059..8867eb4025bf 100644 --- a/arch/arm/mach-omap2/omap-iommu.c +++ b/arch/arm/mach-omap2/omap-iommu.c @@ -11,7 +11,6 @@ */ #include <linux/of.h> -#include <linux/module.h> #include <linux/platform_device.h> #include <linux/err.h> #include <linux/slab.h> @@ -63,15 +62,5 @@ static int __init omap_iommu_init(void) return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL); } -/* must be ready before omap3isp is probed */ omap_subsys_initcall(omap_iommu_init); - -static void __exit omap_iommu_exit(void) -{ - /* Do nothing */ -} -module_exit(omap_iommu_exit); - -MODULE_AUTHOR("Hiroshi DOYU"); -MODULE_DESCRIPTION("omap iommu: omap device registration"); -MODULE_LICENSE("GPL v2"); +/* must be ready before omap3isp is probed */ diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 79f49d904a06..65024af169d3 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -105,7 +105,7 @@ static void dummy_cpu_resume(void) static void dummy_scu_prepare(unsigned int cpu_id, unsigned int cpu_state) {} -struct cpu_pm_ops omap_pm_ops = { +static struct cpu_pm_ops omap_pm_ops = { .finish_suspend = default_finish_suspend, .resume = dummy_cpu_resume, .scu_prepare = dummy_scu_prepare, diff --git a/arch/arm/mach-omap2/omap3-restart.c b/arch/arm/mach-omap2/omap3-restart.c index 103a49f68bcb..4bdd22edb96b 100644 --- a/arch/arm/mach-omap2/omap3-restart.c +++ b/arch/arm/mach-omap2/omap3-restart.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/reboot.h> +#include "common.h" #include "control.h" #include "prm.h" diff --git a/arch/arm/mach-omap2/omap4-restart.c b/arch/arm/mach-omap2/omap4-restart.c index a99e7f7fb5be..e17136a50e27 100644 --- a/arch/arm/mach-omap2/omap4-restart.c +++ b/arch/arm/mach-omap2/omap4-restart.c @@ -9,6 +9,7 @@ #include <linux/types.h> #include <linux/reboot.h> +#include "common.h" #include "prm.h" /** diff --git a/arch/arm/mach-omap2/omap54xx.h b/arch/arm/mach-omap2/omap54xx.h index 2d35c5709408..0ca8e938096b 100644 --- a/arch/arm/mach-omap2/omap54xx.h +++ b/arch/arm/mach-omap2/omap54xx.h @@ -30,6 +30,14 @@ #define OMAP54XX_CTRL_BASE 0x4a002800 #define OMAP54XX_SAR_RAM_BASE 0x4ae26000 +/* DRA7 specific base addresses */ +#define L3_MAIN_SN_DRA7XX_BASE 0x44000000 +#define L4_PER1_DRA7XX_BASE 0x48000000 +#define L4_CFG_MPU_DRA7XX_BASE 0x48210000 +#define L4_PER2_DRA7XX_BASE 0x48400000 +#define L4_PER3_DRA7XX_BASE 0x48800000 +#define L4_CFG_DRA7XX_BASE 0x4A000000 +#define L4_WKUP_DRA7XX_BASE 0x4ae00000 #define DRA7XX_CM_CORE_AON_BASE 0x4a005000 #define DRA7XX_CTRL_BASE 0x4a003400 #define DRA7XX_TAP_BASE 0x4ae0c000 diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index d78c12e7cb5e..1ba175f7210a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -299,7 +299,20 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh) /* Module might have lost context, always update cache and register */ oh->_sysc_cache = v; + + /* + * Some IP blocks (such as RTC) require unlocking of IP before + * accessing its registers. If a function pointer is present + * to unlock, then call it before accessing sysconfig and + * call lock after writing sysconfig. + */ + if (oh->class->unlock) + oh->class->unlock(oh); + omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs); + + if (oh->class->lock) + oh->class->lock(oh); } /** @@ -3878,7 +3891,8 @@ void __init omap_hwmod_init(void) soc_ops.init_clkdm = _init_clkdm; soc_ops.update_context_lost = _omap4_update_context_lost; soc_ops.get_context_lost = _omap4_get_context_lost; - } else if (cpu_is_ti816x() || soc_is_am33xx() || soc_is_am43xx()) { + } else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() || + soc_is_am43xx()) { soc_ops.enable_module = _omap4_enable_module; soc_ops.disable_module = _omap4_disable_module; soc_ops.wait_target_ready = _omap4_wait_target_ready; diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index b5d27ec81610..ca6df1a73475 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -576,6 +576,8 @@ struct omap_hwmod_omap4_prcm { * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown * @reset: ptr to fn to be executed in place of the standard hwmod reset fn * @enable_preprogram: ptr to fn to be executed during device enable + * @lock: ptr to fn to be executed to lock IP registers + * @unlock: ptr to fn to be executed to unlock IP registers * * Represent the class of a OMAP hardware "modules" (e.g. timer, * smartreflex, gpio, uart...) @@ -600,6 +602,8 @@ struct omap_hwmod_class { int (*pre_shutdown)(struct omap_hwmod *oh); int (*reset)(struct omap_hwmod *oh); int (*enable_preprogram)(struct omap_hwmod *oh); + void (*lock)(struct omap_hwmod *oh); + void (*unlock)(struct omap_hwmod *oh); }; /** @@ -755,7 +759,8 @@ extern int omap3xxx_hwmod_init(void); extern int omap44xx_hwmod_init(void); extern int omap54xx_hwmod_init(void); extern int am33xx_hwmod_init(void); -extern int ti81xx_hwmod_init(void); +extern int dm814x_hwmod_init(void); +extern int dm816x_hwmod_init(void); extern int dra7xx_hwmod_init(void); int am43xx_hwmod_init(void); diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 6dcfd03ced8f..36bcd2e75422 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -20,7 +20,7 @@ #include "prm-regbits-24xx.h" #include "wd_timer.h" -struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = { +static struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = { { .name = "dispc", .dma_req = 5 }, { .dma_req = -1, }, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index 215d5efa0dba..e97a894b5f88 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -480,7 +480,7 @@ static struct omap_hwmod am43xx_dss_core_hwmod = { /* dispc */ -struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = { +static struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = { .manager_count = 1, .has_framedonetv_irq = 0 }; diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c index c92413769144..b1288f56d509 100644 --- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c @@ -32,21 +32,59 @@ */ /* - * The alwon .clkctrl_offs field is offset from the CM_ALWON, that's - * TRM 18.7.17 CM_ALWON device register values minus 0x1400. + * Common alwon .clkctrl_offs from dm814x TRM "Table 2-278. CM_ALWON REGISTERS" + * also dm816x TRM 18.7.17 CM_ALWON device register values minus 0x1400. */ +#define DM81XX_CM_ALWON_MCASP0_CLKCTRL 0x140 +#define DM81XX_CM_ALWON_MCASP1_CLKCTRL 0x144 +#define DM81XX_CM_ALWON_MCASP2_CLKCTRL 0x148 +#define DM81XX_CM_ALWON_MCBSP_CLKCTRL 0x14c +#define DM81XX_CM_ALWON_UART_0_CLKCTRL 0x150 +#define DM81XX_CM_ALWON_UART_1_CLKCTRL 0x154 +#define DM81XX_CM_ALWON_UART_2_CLKCTRL 0x158 +#define DM81XX_CM_ALWON_GPIO_0_CLKCTRL 0x15c +#define DM81XX_CM_ALWON_GPIO_1_CLKCTRL 0x160 +#define DM81XX_CM_ALWON_I2C_0_CLKCTRL 0x164 +#define DM81XX_CM_ALWON_I2C_1_CLKCTRL 0x168 +#define DM81XX_CM_ALWON_WDTIMER_CLKCTRL 0x18c +#define DM81XX_CM_ALWON_SPI_CLKCTRL 0x190 +#define DM81XX_CM_ALWON_MAILBOX_CLKCTRL 0x194 +#define DM81XX_CM_ALWON_SPINBOX_CLKCTRL 0x198 +#define DM81XX_CM_ALWON_MMUDATA_CLKCTRL 0x19c +#define DM81XX_CM_ALWON_MMUCFG_CLKCTRL 0x1a8 +#define DM81XX_CM_ALWON_CONTROL_CLKCTRL 0x1c4 +#define DM81XX_CM_ALWON_GPMC_CLKCTRL 0x1d0 +#define DM81XX_CM_ALWON_ETHERNET_0_CLKCTRL 0x1d4 +#define DM81XX_CM_ALWON_L3_CLKCTRL 0x1e4 +#define DM81XX_CM_ALWON_L4HS_CLKCTRL 0x1e8 +#define DM81XX_CM_ALWON_L4LS_CLKCTRL 0x1ec +#define DM81XX_CM_ALWON_RTC_CLKCTRL 0x1f0 +#define DM81XX_CM_ALWON_TPCC_CLKCTRL 0x1f4 +#define DM81XX_CM_ALWON_TPTC0_CLKCTRL 0x1f8 +#define DM81XX_CM_ALWON_TPTC1_CLKCTRL 0x1fc +#define DM81XX_CM_ALWON_TPTC2_CLKCTRL 0x200 +#define DM81XX_CM_ALWON_TPTC3_CLKCTRL 0x204 + +/* Registers specific to dm814x */ +#define DM814X_CM_ALWON_MCASP_3_4_5_CLKCTRL 0x16c +#define DM814X_CM_ALWON_ATL_CLKCTRL 0x170 +#define DM814X_CM_ALWON_MLB_CLKCTRL 0x174 +#define DM814X_CM_ALWON_PATA_CLKCTRL 0x178 +#define DM814X_CM_ALWON_UART_3_CLKCTRL 0x180 +#define DM814X_CM_ALWON_UART_4_CLKCTRL 0x184 +#define DM814X_CM_ALWON_UART_5_CLKCTRL 0x188 +#define DM814X_CM_ALWON_OCM_0_CLKCTRL 0x1b4 +#define DM814X_CM_ALWON_VCP_CLKCTRL 0x1b8 +#define DM814X_CM_ALWON_MPU_CLKCTRL 0x1dc +#define DM814X_CM_ALWON_DEBUGSS_CLKCTRL 0x1e0 +#define DM814X_CM_ALWON_DCAN_0_1_CLKCTRL 0x218 +#define DM814X_CM_ALWON_MMCHS_0_CLKCTRL 0x21c +#define DM814X_CM_ALWON_MMCHS_1_CLKCTRL 0x220 +#define DM814X_CM_ALWON_MMCHS_2_CLKCTRL 0x224 +#define DM814X_CM_ALWON_CUST_EFUSE_CLKCTRL 0x228 + +/* Registers specific to dm816x */ #define DM816X_DM_ALWON_BASE 0x1400 -#define DM816X_CM_ALWON_MCASP0_CLKCTRL (0x1540 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_MCASP1_CLKCTRL (0x1544 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_MCASP2_CLKCTRL (0x1548 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_MCBSP_CLKCTRL (0x154c - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_UART_0_CLKCTRL (0x1550 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_UART_1_CLKCTRL (0x1554 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_UART_2_CLKCTRL (0x1558 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_GPIO_0_CLKCTRL (0x155c - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_GPIO_1_CLKCTRL (0x1560 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_I2C_0_CLKCTRL (0x1564 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_I2C_1_CLKCTRL (0x1568 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_TIMER_1_CLKCTRL (0x1570 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_TIMER_2_CLKCTRL (0x1574 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_TIMER_3_CLKCTRL (0x1578 - DM816X_DM_ALWON_BASE) @@ -54,29 +92,11 @@ #define DM816X_CM_ALWON_TIMER_5_CLKCTRL (0x1580 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_TIMER_6_CLKCTRL (0x1584 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_TIMER_7_CLKCTRL (0x1588 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_WDTIMER_CLKCTRL (0x158c - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_SPI_CLKCTRL (0x1590 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_MAILBOX_CLKCTRL (0x1594 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_SPINBOX_CLKCTRL (0x1598 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_MMUDATA_CLKCTRL (0x159c - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_MMUCFG_CLKCTRL (0x15a8 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_SDIO_CLKCTRL (0x15b0 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_OCMC_0_CLKCTRL (0x15b4 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_OCMC_1_CLKCTRL (0x15b8 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_CONTRL_CLKCTRL (0x15c4 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_GPMC_CLKCTRL (0x15d0 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_ETHERNET_0_CLKCTRL (0x15d4 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_ETHERNET_1_CLKCTRL (0x15d8 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_MPU_CLKCTRL (0x15dc - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_L3_CLKCTRL (0x15e4 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_L4HS_CLKCTRL (0x15e8 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_L4LS_CLKCTRL (0x15ec - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_RTC_CLKCTRL (0x15f0 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_TPCC_CLKCTRL (0x15f4 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_TPTC0_CLKCTRL (0x15f8 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_TPTC1_CLKCTRL (0x15fc - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_TPTC2_CLKCTRL (0x1600 - DM816X_DM_ALWON_BASE) -#define DM816X_CM_ALWON_TPTC3_CLKCTRL (0x1604 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_SR_0_CLKCTRL (0x1608 - DM816X_DM_ALWON_BASE) #define DM816X_CM_ALWON_SR_1_CLKCTRL (0x160c - DM816X_DM_ALWON_BASE) @@ -88,28 +108,28 @@ #define DM816X_CM_DEFAULT_USB_CLKCTRL (0x558 - DM816X_CM_DEFAULT_OFFSET) /* L3 Interconnect entries clocked at 125, 250 and 500MHz */ -static struct omap_hwmod dm816x_alwon_l3_slow_hwmod = { +static struct omap_hwmod dm81xx_alwon_l3_slow_hwmod = { .name = "alwon_l3_slow", .clkdm_name = "alwon_l3s_clkdm", .class = &l3_hwmod_class, .flags = HWMOD_NO_IDLEST, }; -static struct omap_hwmod dm816x_default_l3_slow_hwmod = { +static struct omap_hwmod dm81xx_default_l3_slow_hwmod = { .name = "default_l3_slow", .clkdm_name = "default_l3_slow_clkdm", .class = &l3_hwmod_class, .flags = HWMOD_NO_IDLEST, }; -static struct omap_hwmod dm816x_alwon_l3_med_hwmod = { +static struct omap_hwmod dm81xx_alwon_l3_med_hwmod = { .name = "l3_med", .clkdm_name = "alwon_l3_med_clkdm", .class = &l3_hwmod_class, .flags = HWMOD_NO_IDLEST, }; -static struct omap_hwmod dm816x_alwon_l3_fast_hwmod = { +static struct omap_hwmod dm81xx_alwon_l3_fast_hwmod = { .name = "l3_fast", .clkdm_name = "alwon_l3_fast_clkdm", .class = &l3_hwmod_class, @@ -120,7 +140,7 @@ static struct omap_hwmod dm816x_alwon_l3_fast_hwmod = { * L4 standard peripherals, see TRM table 1-12 for devices using this. * See TRM table 1-73 for devices using the 125MHz SYSCLK6 clock. */ -static struct omap_hwmod dm816x_l4_ls_hwmod = { +static struct omap_hwmod dm81xx_l4_ls_hwmod = { .name = "l4_ls", .clkdm_name = "alwon_l3s_clkdm", .class = &l4_hwmod_class, @@ -131,27 +151,54 @@ static struct omap_hwmod dm816x_l4_ls_hwmod = { * table 1-13. On dm816x, only EMAC, MDIO and SATA use this. See also TRM * table 1-73 for devices using 250MHz SYSCLK5 clock. */ -static struct omap_hwmod dm816x_l4_hs_hwmod = { +static struct omap_hwmod dm81xx_l4_hs_hwmod = { .name = "l4_hs", .clkdm_name = "alwon_l3_med_clkdm", .class = &l4_hwmod_class, }; /* L3 slow -> L4 ls peripheral interface running at 125MHz */ -static struct omap_hwmod_ocp_if dm816x_alwon_l3_slow__l4_ls = { - .master = &dm816x_alwon_l3_slow_hwmod, - .slave = &dm816x_l4_ls_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_slow__l4_ls = { + .master = &dm81xx_alwon_l3_slow_hwmod, + .slave = &dm81xx_l4_ls_hwmod, .user = OCP_USER_MPU, }; /* L3 med -> L4 fast peripheral interface running at 250MHz */ -static struct omap_hwmod_ocp_if dm816x_alwon_l3_slow__l4_hs = { - .master = &dm816x_alwon_l3_med_hwmod, - .slave = &dm816x_l4_hs_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_slow__l4_hs = { + .master = &dm81xx_alwon_l3_med_hwmod, + .slave = &dm81xx_l4_hs_hwmod, .user = OCP_USER_MPU, }; /* MPU */ +static struct omap_hwmod dm814x_mpu_hwmod = { + .name = "mpu", + .clkdm_name = "alwon_l3s_clkdm", + .class = &mpu_hwmod_class, + .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "mpu_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM814X_CM_ALWON_MPU_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + +static struct omap_hwmod_ocp_if dm814x_mpu__alwon_l3_slow = { + .master = &dm814x_mpu_hwmod, + .slave = &dm81xx_alwon_l3_slow_hwmod, + .user = OCP_USER_MPU, +}; + +/* L3 med peripheral interface running at 200MHz */ +static struct omap_hwmod_ocp_if dm814x_mpu__alwon_l3_med = { + .master = &dm814x_mpu_hwmod, + .slave = &dm81xx_alwon_l3_med_hwmod, + .user = OCP_USER_MPU, +}; + static struct omap_hwmod dm816x_mpu_hwmod = { .name = "mpu", .clkdm_name = "alwon_mpu_clkdm", @@ -168,14 +215,14 @@ static struct omap_hwmod dm816x_mpu_hwmod = { static struct omap_hwmod_ocp_if dm816x_mpu__alwon_l3_slow = { .master = &dm816x_mpu_hwmod, - .slave = &dm816x_alwon_l3_slow_hwmod, + .slave = &dm81xx_alwon_l3_slow_hwmod, .user = OCP_USER_MPU, }; /* L3 med peripheral interface running at 250MHz */ static struct omap_hwmod_ocp_if dm816x_mpu__alwon_l3_med = { .master = &dm816x_mpu_hwmod, - .slave = &dm816x_alwon_l3_med_hwmod, + .slave = &dm81xx_alwon_l3_med_hwmod, .user = OCP_USER_MPU, }; @@ -197,13 +244,13 @@ static struct omap_hwmod_class uart_class = { .sysc = &uart_sysc, }; -static struct omap_hwmod dm816x_uart1_hwmod = { +static struct omap_hwmod dm81xx_uart1_hwmod = { .name = "uart1", .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk10_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_UART_0_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_UART_0_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -211,20 +258,20 @@ static struct omap_hwmod dm816x_uart1_hwmod = { .flags = DEBUG_TI81XXUART1_FLAGS, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__uart1 = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_uart1_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__uart1 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_uart1_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; -static struct omap_hwmod dm816x_uart2_hwmod = { +static struct omap_hwmod dm81xx_uart2_hwmod = { .name = "uart2", .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk10_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_UART_1_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_UART_1_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -232,20 +279,20 @@ static struct omap_hwmod dm816x_uart2_hwmod = { .flags = DEBUG_TI81XXUART2_FLAGS, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__uart2 = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_uart2_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__uart2 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_uart2_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; -static struct omap_hwmod dm816x_uart3_hwmod = { +static struct omap_hwmod dm81xx_uart3_hwmod = { .name = "uart3", .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk10_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_UART_2_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_UART_2_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -253,9 +300,9 @@ static struct omap_hwmod dm816x_uart3_hwmod = { .flags = DEBUG_TI81XXUART3_FLAGS, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__uart3 = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_uart3_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__uart3 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_uart3_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; @@ -276,23 +323,23 @@ static struct omap_hwmod_class wd_timer_class = { .reset = &omap2_wd_timer_reset, }; -static struct omap_hwmod dm816x_wd_timer_hwmod = { +static struct omap_hwmod dm81xx_wd_timer_hwmod = { .name = "wd_timer", .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk18_ck", .flags = HWMOD_NO_IDLEST, .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_WDTIMER_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_WDTIMER_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, .class = &wd_timer_class, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__wd_timer1 = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_wd_timer_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__wd_timer1 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_wd_timer_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; @@ -320,27 +367,27 @@ static struct omap_hwmod dm81xx_i2c1_hwmod = { .main_clk = "sysclk10_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_I2C_0_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_I2C_0_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, .class = &i2c_class, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__i2c1 = { - .master = &dm816x_l4_ls_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__i2c1 = { + .master = &dm81xx_l4_ls_hwmod, .slave = &dm81xx_i2c1_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; -static struct omap_hwmod dm816x_i2c2_hwmod = { +static struct omap_hwmod dm81xx_i2c2_hwmod = { .name = "i2c2", .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk10_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_I2C_1_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_I2C_1_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -358,9 +405,9 @@ static struct omap_hwmod_class_sysconfig dm81xx_elm_sysc = { .sysc_fields = &omap_hwmod_sysc_type1, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__i2c2 = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_i2c2_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__i2c2 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_i2c2_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; @@ -378,7 +425,7 @@ static struct omap_hwmod dm81xx_elm_hwmod = { }; static struct omap_hwmod_ocp_if dm81xx_l4_ls__elm = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm81xx_elm_hwmod, .user = OCP_USER_MPU, }; @@ -417,7 +464,7 @@ static struct omap_hwmod dm81xx_gpio1_hwmod = { .main_clk = "sysclk6_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_GPIO_0_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_GPIO_0_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -427,7 +474,7 @@ static struct omap_hwmod dm81xx_gpio1_hwmod = { }; static struct omap_hwmod_ocp_if dm81xx_l4_ls__gpio1 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm81xx_gpio1_hwmod, .user = OCP_USER_MPU, }; @@ -443,7 +490,7 @@ static struct omap_hwmod dm81xx_gpio2_hwmod = { .main_clk = "sysclk6_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_GPIO_1_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_GPIO_1_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -453,7 +500,7 @@ static struct omap_hwmod dm81xx_gpio2_hwmod = { }; static struct omap_hwmod_ocp_if dm81xx_l4_ls__gpio2 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm81xx_gpio2_hwmod, .user = OCP_USER_MPU, }; @@ -482,14 +529,14 @@ static struct omap_hwmod dm81xx_gpmc_hwmod = { .flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS, .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_GPMC_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_GPMC_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm81xx_alwon_l3_slow__gpmc = { - .master = &dm816x_alwon_l3_slow_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_slow__gpmc = { + .master = &dm81xx_alwon_l3_slow_hwmod, .slave = &dm81xx_gpmc_hwmod, .user = OCP_USER_MPU, }; @@ -522,7 +569,7 @@ static struct omap_hwmod dm81xx_usbss_hwmod = { }; static struct omap_hwmod_ocp_if dm81xx_default_l3_slow__usbss = { - .master = &dm816x_default_l3_slow_hwmod, + .master = &dm81xx_default_l3_slow_hwmod, .slave = &dm81xx_usbss_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -547,6 +594,22 @@ static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = { .timer_capability = OMAP_TIMER_ALWON, }; +static struct omap_hwmod dm814x_timer1_hwmod = { + .name = "timer1", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer_sys_ck", + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, + .flags = HWMOD_NO_IDLEST, +}; + +static struct omap_hwmod_ocp_if dm814x_l4_ls__timer1 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm814x_timer1_hwmod, + .clk = "timer_sys_ck", + .user = OCP_USER_MPU, +}; + static struct omap_hwmod dm816x_timer1_hwmod = { .name = "timer1", .clkdm_name = "alwon_l3s_clkdm", @@ -562,12 +625,28 @@ static struct omap_hwmod dm816x_timer1_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer1 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer1_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; +static struct omap_hwmod dm814x_timer2_hwmod = { + .name = "timer2", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer_sys_ck", + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, + .flags = HWMOD_NO_IDLEST, +}; + +static struct omap_hwmod_ocp_if dm814x_l4_ls__timer2 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm814x_timer2_hwmod, + .clk = "timer_sys_ck", + .user = OCP_USER_MPU, +}; + static struct omap_hwmod dm816x_timer2_hwmod = { .name = "timer2", .clkdm_name = "alwon_l3s_clkdm", @@ -583,7 +662,7 @@ static struct omap_hwmod dm816x_timer2_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer2 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer2_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -604,7 +683,7 @@ static struct omap_hwmod dm816x_timer3_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer3 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer3_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -625,7 +704,7 @@ static struct omap_hwmod dm816x_timer4_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer4 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer4_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -646,7 +725,7 @@ static struct omap_hwmod dm816x_timer5_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer5 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer5_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -667,7 +746,7 @@ static struct omap_hwmod dm816x_timer6_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer6 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer6_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -688,12 +767,68 @@ static struct omap_hwmod dm816x_timer7_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__timer7 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_timer7_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; +/* CPSW on dm814x */ +static struct omap_hwmod_class_sysconfig dm814x_cpgmac_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x8, + .syss_offs = 0x4, + .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | + SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE | + MSTANDBY_NO, + .sysc_fields = &omap_hwmod_sysc_type3, +}; + +static struct omap_hwmod_class dm814x_cpgmac0_hwmod_class = { + .name = "cpgmac0", + .sysc = &dm814x_cpgmac_sysc, +}; + +static struct omap_hwmod dm814x_cpgmac0_hwmod = { + .name = "cpgmac0", + .class = &dm814x_cpgmac0_hwmod_class, + .clkdm_name = "alwon_ethernet_clkdm", + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, + .main_clk = "cpsw_125mhz_gclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DM81XX_CM_ALWON_ETHERNET_0_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + +static struct omap_hwmod_class dm814x_mdio_hwmod_class = { + .name = "davinci_mdio", +}; + +static struct omap_hwmod dm814x_mdio_hwmod = { + .name = "davinci_mdio", + .class = &dm814x_mdio_hwmod_class, + .clkdm_name = "alwon_ethernet_clkdm", + .main_clk = "cpsw_125mhz_gclk", +}; + +static struct omap_hwmod_ocp_if dm814x_l4_hs__cpgmac0 = { + .master = &dm81xx_l4_hs_hwmod, + .slave = &dm814x_cpgmac0_hwmod, + .clk = "cpsw_125mhz_gclk", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_ocp_if dm814x_cpgmac0__mdio = { + .master = &dm814x_cpgmac0_hwmod, + .slave = &dm814x_mdio_hwmod, + .user = OCP_USER_MPU, + .flags = HWMOD_NO_IDLEST, +}; + /* EMAC Ethernet */ static struct omap_hwmod_class_sysconfig dm816x_emac_sysc = { .rev_offs = 0x0, @@ -717,21 +852,21 @@ static struct omap_hwmod dm816x_emac0_hwmod = { .class = &dm816x_emac_hwmod_class, }; -static struct omap_hwmod_ocp_if dm816x_l4_hs__emac0 = { - .master = &dm816x_l4_hs_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_hs__emac0 = { + .master = &dm81xx_l4_hs_hwmod, .slave = &dm816x_emac0_hwmod, .clk = "sysclk5_ck", .user = OCP_USER_MPU, }; -static struct omap_hwmod_class dm816x_mdio_hwmod_class = { +static struct omap_hwmod_class dm81xx_mdio_hwmod_class = { .name = "davinci_mdio", .sysc = &dm816x_emac_sysc, }; -struct omap_hwmod dm816x_emac0_mdio_hwmod = { +static struct omap_hwmod dm81xx_emac0_mdio_hwmod = { .name = "davinci_mdio", - .class = &dm816x_mdio_hwmod_class, + .class = &dm81xx_mdio_hwmod_class, .clkdm_name = "alwon_ethernet_clkdm", .main_clk = "sysclk24_ck", .flags = HWMOD_NO_IDLEST, @@ -741,15 +876,15 @@ struct omap_hwmod dm816x_emac0_mdio_hwmod = { */ .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_ETHERNET_0_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_ETHERNET_0_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm816x_emac0__mdio = { - .master = &dm816x_l4_hs_hwmod, - .slave = &dm816x_emac0_mdio_hwmod, +static struct omap_hwmod_ocp_if dm81xx_emac0__mdio = { + .master = &dm81xx_l4_hs_hwmod, + .slave = &dm81xx_emac0_mdio_hwmod, .user = OCP_USER_MPU, }; @@ -768,7 +903,7 @@ static struct omap_hwmod dm816x_emac1_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = { - .master = &dm816x_l4_hs_hwmod, + .master = &dm81xx_l4_hs_hwmod, .slave = &dm816x_emac1_hwmod, .clk = "sysclk5_ck", .user = OCP_USER_MPU, @@ -815,7 +950,7 @@ static struct omap_hwmod dm816x_mmc1_hwmod = { }; static struct omap_hwmod_ocp_if dm816x_l4_ls__mmc1 = { - .master = &dm816x_l4_ls_hwmod, + .master = &dm81xx_l4_ls_hwmod, .slave = &dm816x_mmc1_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, @@ -843,13 +978,13 @@ static struct omap2_mcspi_dev_attr dm816x_mcspi1_dev_attr = { .num_chipselect = 4, }; -static struct omap_hwmod dm816x_mcspi1_hwmod = { +static struct omap_hwmod dm81xx_mcspi1_hwmod = { .name = "mcspi1", .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk10_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_SPI_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_SPI_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, @@ -857,14 +992,14 @@ static struct omap_hwmod dm816x_mcspi1_hwmod = { .dev_attr = &dm816x_mcspi1_dev_attr, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__mcspi1 = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_mcspi1_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__mcspi1 = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_mcspi1_hwmod, .clk = "sysclk6_ck", .user = OCP_USER_MPU, }; -static struct omap_hwmod_class_sysconfig dm816x_mailbox_sysc = { +static struct omap_hwmod_class_sysconfig dm81xx_mailbox_sysc = { .rev_offs = 0x000, .sysc_offs = 0x010, .syss_offs = 0x014, @@ -874,55 +1009,55 @@ static struct omap_hwmod_class_sysconfig dm816x_mailbox_sysc = { .sysc_fields = &omap_hwmod_sysc_type1, }; -static struct omap_hwmod_class dm816x_mailbox_hwmod_class = { +static struct omap_hwmod_class dm81xx_mailbox_hwmod_class = { .name = "mailbox", - .sysc = &dm816x_mailbox_sysc, + .sysc = &dm81xx_mailbox_sysc, }; -static struct omap_hwmod dm816x_mailbox_hwmod = { +static struct omap_hwmod dm81xx_mailbox_hwmod = { .name = "mailbox", .clkdm_name = "alwon_l3s_clkdm", - .class = &dm816x_mailbox_hwmod_class, + .class = &dm81xx_mailbox_hwmod_class, .main_clk = "sysclk6_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_MAILBOX_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_MAILBOX_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -static struct omap_hwmod_ocp_if dm816x_l4_ls__mailbox = { - .master = &dm816x_l4_ls_hwmod, - .slave = &dm816x_mailbox_hwmod, +static struct omap_hwmod_ocp_if dm81xx_l4_ls__mailbox = { + .master = &dm81xx_l4_ls_hwmod, + .slave = &dm81xx_mailbox_hwmod, .user = OCP_USER_MPU, }; -static struct omap_hwmod_class dm816x_tpcc_hwmod_class = { +static struct omap_hwmod_class dm81xx_tpcc_hwmod_class = { .name = "tpcc", }; -struct omap_hwmod dm816x_tpcc_hwmod = { +static struct omap_hwmod dm81xx_tpcc_hwmod = { .name = "tpcc", - .class = &dm816x_tpcc_hwmod_class, + .class = &dm81xx_tpcc_hwmod_class, .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk4_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_TPCC_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_TPCC_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm816x_alwon_l3_fast__tpcc = { - .master = &dm816x_alwon_l3_fast_hwmod, - .slave = &dm816x_tpcc_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_fast__tpcc = { + .master = &dm81xx_alwon_l3_fast_hwmod, + .slave = &dm81xx_tpcc_hwmod, .clk = "sysclk4_ck", .user = OCP_USER_MPU, }; -static struct omap_hwmod_addr_space dm816x_tptc0_addr_space[] = { +static struct omap_hwmod_addr_space dm81xx_tptc0_addr_space[] = { { .pa_start = 0x49800000, .pa_end = 0x49800000 + SZ_8K - 1, @@ -931,40 +1066,40 @@ static struct omap_hwmod_addr_space dm816x_tptc0_addr_space[] = { { }, }; -static struct omap_hwmod_class dm816x_tptc0_hwmod_class = { +static struct omap_hwmod_class dm81xx_tptc0_hwmod_class = { .name = "tptc0", }; -struct omap_hwmod dm816x_tptc0_hwmod = { +static struct omap_hwmod dm81xx_tptc0_hwmod = { .name = "tptc0", - .class = &dm816x_tptc0_hwmod_class, + .class = &dm81xx_tptc0_hwmod_class, .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk4_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_TPTC0_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_TPTC0_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm816x_alwon_l3_fast__tptc0 = { - .master = &dm816x_alwon_l3_fast_hwmod, - .slave = &dm816x_tptc0_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_fast__tptc0 = { + .master = &dm81xx_alwon_l3_fast_hwmod, + .slave = &dm81xx_tptc0_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc0_addr_space, + .addr = dm81xx_tptc0_addr_space, .user = OCP_USER_MPU, }; -struct omap_hwmod_ocp_if dm816x_tptc0__alwon_l3_fast = { - .master = &dm816x_tptc0_hwmod, - .slave = &dm816x_alwon_l3_fast_hwmod, +static struct omap_hwmod_ocp_if dm81xx_tptc0__alwon_l3_fast = { + .master = &dm81xx_tptc0_hwmod, + .slave = &dm81xx_alwon_l3_fast_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc0_addr_space, + .addr = dm81xx_tptc0_addr_space, .user = OCP_USER_MPU, }; -static struct omap_hwmod_addr_space dm816x_tptc1_addr_space[] = { +static struct omap_hwmod_addr_space dm81xx_tptc1_addr_space[] = { { .pa_start = 0x49900000, .pa_end = 0x49900000 + SZ_8K - 1, @@ -973,40 +1108,40 @@ static struct omap_hwmod_addr_space dm816x_tptc1_addr_space[] = { { }, }; -static struct omap_hwmod_class dm816x_tptc1_hwmod_class = { +static struct omap_hwmod_class dm81xx_tptc1_hwmod_class = { .name = "tptc1", }; -struct omap_hwmod dm816x_tptc1_hwmod = { +static struct omap_hwmod dm81xx_tptc1_hwmod = { .name = "tptc1", - .class = &dm816x_tptc1_hwmod_class, + .class = &dm81xx_tptc1_hwmod_class, .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk4_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_TPTC1_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_TPTC1_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm816x_alwon_l3_fast__tptc1 = { - .master = &dm816x_alwon_l3_fast_hwmod, - .slave = &dm816x_tptc1_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_fast__tptc1 = { + .master = &dm81xx_alwon_l3_fast_hwmod, + .slave = &dm81xx_tptc1_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc1_addr_space, + .addr = dm81xx_tptc1_addr_space, .user = OCP_USER_MPU, }; -struct omap_hwmod_ocp_if dm816x_tptc1__alwon_l3_fast = { - .master = &dm816x_tptc1_hwmod, - .slave = &dm816x_alwon_l3_fast_hwmod, +static struct omap_hwmod_ocp_if dm81xx_tptc1__alwon_l3_fast = { + .master = &dm81xx_tptc1_hwmod, + .slave = &dm81xx_alwon_l3_fast_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc1_addr_space, + .addr = dm81xx_tptc1_addr_space, .user = OCP_USER_MPU, }; -static struct omap_hwmod_addr_space dm816x_tptc2_addr_space[] = { +static struct omap_hwmod_addr_space dm81xx_tptc2_addr_space[] = { { .pa_start = 0x49a00000, .pa_end = 0x49a00000 + SZ_8K - 1, @@ -1015,40 +1150,40 @@ static struct omap_hwmod_addr_space dm816x_tptc2_addr_space[] = { { }, }; -static struct omap_hwmod_class dm816x_tptc2_hwmod_class = { +static struct omap_hwmod_class dm81xx_tptc2_hwmod_class = { .name = "tptc2", }; -struct omap_hwmod dm816x_tptc2_hwmod = { +static struct omap_hwmod dm81xx_tptc2_hwmod = { .name = "tptc2", - .class = &dm816x_tptc2_hwmod_class, + .class = &dm81xx_tptc2_hwmod_class, .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk4_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_TPTC2_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_TPTC2_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm816x_alwon_l3_fast__tptc2 = { - .master = &dm816x_alwon_l3_fast_hwmod, - .slave = &dm816x_tptc2_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_fast__tptc2 = { + .master = &dm81xx_alwon_l3_fast_hwmod, + .slave = &dm81xx_tptc2_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc2_addr_space, + .addr = dm81xx_tptc2_addr_space, .user = OCP_USER_MPU, }; -struct omap_hwmod_ocp_if dm816x_tptc2__alwon_l3_fast = { - .master = &dm816x_tptc2_hwmod, - .slave = &dm816x_alwon_l3_fast_hwmod, +static struct omap_hwmod_ocp_if dm81xx_tptc2__alwon_l3_fast = { + .master = &dm81xx_tptc2_hwmod, + .slave = &dm81xx_alwon_l3_fast_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc2_addr_space, + .addr = dm81xx_tptc2_addr_space, .user = OCP_USER_MPU, }; -static struct omap_hwmod_addr_space dm816x_tptc3_addr_space[] = { +static struct omap_hwmod_addr_space dm81xx_tptc3_addr_space[] = { { .pa_start = 0x49b00000, .pa_end = 0x49b00000 + SZ_8K - 1, @@ -1057,50 +1192,96 @@ static struct omap_hwmod_addr_space dm816x_tptc3_addr_space[] = { { }, }; -static struct omap_hwmod_class dm816x_tptc3_hwmod_class = { +static struct omap_hwmod_class dm81xx_tptc3_hwmod_class = { .name = "tptc3", }; -struct omap_hwmod dm816x_tptc3_hwmod = { +static struct omap_hwmod dm81xx_tptc3_hwmod = { .name = "tptc3", - .class = &dm816x_tptc3_hwmod_class, + .class = &dm81xx_tptc3_hwmod_class, .clkdm_name = "alwon_l3s_clkdm", .main_clk = "sysclk4_ck", .prcm = { .omap4 = { - .clkctrl_offs = DM816X_CM_ALWON_TPTC3_CLKCTRL, + .clkctrl_offs = DM81XX_CM_ALWON_TPTC3_CLKCTRL, .modulemode = MODULEMODE_SWCTRL, }, }, }; -struct omap_hwmod_ocp_if dm816x_alwon_l3_fast__tptc3 = { - .master = &dm816x_alwon_l3_fast_hwmod, - .slave = &dm816x_tptc3_hwmod, +static struct omap_hwmod_ocp_if dm81xx_alwon_l3_fast__tptc3 = { + .master = &dm81xx_alwon_l3_fast_hwmod, + .slave = &dm81xx_tptc3_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc3_addr_space, + .addr = dm81xx_tptc3_addr_space, .user = OCP_USER_MPU, }; -struct omap_hwmod_ocp_if dm816x_tptc3__alwon_l3_fast = { - .master = &dm816x_tptc3_hwmod, - .slave = &dm816x_alwon_l3_fast_hwmod, +static struct omap_hwmod_ocp_if dm81xx_tptc3__alwon_l3_fast = { + .master = &dm81xx_tptc3_hwmod, + .slave = &dm81xx_alwon_l3_fast_hwmod, .clk = "sysclk4_ck", - .addr = dm816x_tptc3_addr_space, + .addr = dm81xx_tptc3_addr_space, .user = OCP_USER_MPU, }; +/* + * REVISIT: Test and enable the following once clocks work: + * dm81xx_l4_ls__gpio1 + * dm81xx_l4_ls__gpio2 + * dm81xx_l4_ls__mailbox + * dm81xx_alwon_l3_slow__gpmc + * dm81xx_default_l3_slow__usbss + * + * Also note that some devices share a single clkctrl_offs.. + * For example, i2c1 and 3 share one, and i2c2 and 4 share one. + */ +static struct omap_hwmod_ocp_if *dm814x_hwmod_ocp_ifs[] __initdata = { + &dm814x_mpu__alwon_l3_slow, + &dm814x_mpu__alwon_l3_med, + &dm81xx_alwon_l3_slow__l4_ls, + &dm81xx_alwon_l3_slow__l4_hs, + &dm81xx_l4_ls__uart1, + &dm81xx_l4_ls__uart2, + &dm81xx_l4_ls__uart3, + &dm81xx_l4_ls__wd_timer1, + &dm81xx_l4_ls__i2c1, + &dm81xx_l4_ls__i2c2, + &dm81xx_l4_ls__elm, + &dm81xx_l4_ls__mcspi1, + &dm81xx_alwon_l3_fast__tpcc, + &dm81xx_alwon_l3_fast__tptc0, + &dm81xx_alwon_l3_fast__tptc1, + &dm81xx_alwon_l3_fast__tptc2, + &dm81xx_alwon_l3_fast__tptc3, + &dm81xx_tptc0__alwon_l3_fast, + &dm81xx_tptc1__alwon_l3_fast, + &dm81xx_tptc2__alwon_l3_fast, + &dm81xx_tptc3__alwon_l3_fast, + &dm814x_l4_ls__timer1, + &dm814x_l4_ls__timer2, + &dm814x_l4_hs__cpgmac0, + &dm814x_cpgmac0__mdio, + NULL, +}; + +int __init dm814x_hwmod_init(void) +{ + omap_hwmod_init(); + return omap_hwmod_register_links(dm814x_hwmod_ocp_ifs); +} + static struct omap_hwmod_ocp_if *dm816x_hwmod_ocp_ifs[] __initdata = { &dm816x_mpu__alwon_l3_slow, &dm816x_mpu__alwon_l3_med, - &dm816x_alwon_l3_slow__l4_ls, - &dm816x_alwon_l3_slow__l4_hs, - &dm816x_l4_ls__uart1, - &dm816x_l4_ls__uart2, - &dm816x_l4_ls__uart3, - &dm816x_l4_ls__wd_timer1, - &dm816x_l4_ls__i2c1, - &dm816x_l4_ls__i2c2, + &dm81xx_alwon_l3_slow__l4_ls, + &dm81xx_alwon_l3_slow__l4_hs, + &dm81xx_l4_ls__uart1, + &dm81xx_l4_ls__uart2, + &dm81xx_l4_ls__uart3, + &dm81xx_l4_ls__wd_timer1, + &dm81xx_l4_ls__i2c1, + &dm81xx_l4_ls__i2c2, &dm81xx_l4_ls__gpio1, &dm81xx_l4_ls__gpio2, &dm81xx_l4_ls__elm, @@ -1112,26 +1293,26 @@ static struct omap_hwmod_ocp_if *dm816x_hwmod_ocp_ifs[] __initdata = { &dm816x_l4_ls__timer5, &dm816x_l4_ls__timer6, &dm816x_l4_ls__timer7, - &dm816x_l4_ls__mcspi1, - &dm816x_l4_ls__mailbox, - &dm816x_l4_hs__emac0, - &dm816x_emac0__mdio, + &dm81xx_l4_ls__mcspi1, + &dm81xx_l4_ls__mailbox, + &dm81xx_l4_hs__emac0, + &dm81xx_emac0__mdio, &dm816x_l4_hs__emac1, - &dm816x_alwon_l3_fast__tpcc, - &dm816x_alwon_l3_fast__tptc0, - &dm816x_alwon_l3_fast__tptc1, - &dm816x_alwon_l3_fast__tptc2, - &dm816x_alwon_l3_fast__tptc3, - &dm816x_tptc0__alwon_l3_fast, - &dm816x_tptc1__alwon_l3_fast, - &dm816x_tptc2__alwon_l3_fast, - &dm816x_tptc3__alwon_l3_fast, + &dm81xx_alwon_l3_fast__tpcc, + &dm81xx_alwon_l3_fast__tptc0, + &dm81xx_alwon_l3_fast__tptc1, + &dm81xx_alwon_l3_fast__tptc2, + &dm81xx_alwon_l3_fast__tptc3, + &dm81xx_tptc0__alwon_l3_fast, + &dm81xx_tptc1__alwon_l3_fast, + &dm81xx_tptc2__alwon_l3_fast, + &dm81xx_tptc3__alwon_l3_fast, &dm81xx_alwon_l3_slow__gpmc, &dm81xx_default_l3_slow__usbss, NULL, }; -int __init ti81xx_hwmod_init(void) +int __init dm816x_hwmod_init(void) { omap_hwmod_init(); return omap_hwmod_register_links(dm816x_hwmod_ocp_ifs); diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 821171cf6b7d..1a352f561113 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -31,7 +31,7 @@ struct pdata_init { void (*fn)(void); }; -struct of_dev_auxdata omap_auxdata_lookup[]; +static struct of_dev_auxdata omap_auxdata_lookup[]; static struct twl4030_gpio_platform_data twl_gpio_auxdata; #ifdef CONFIG_MACH_NOKIA_N8X0 @@ -128,7 +128,7 @@ static void __init omap3_sbc_t3530_legacy_init(void) omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub"); } -struct ti_st_plat_data wilink_pdata = { +static struct ti_st_plat_data wilink_pdata = { .nshutdown_gpio = 137, .dev_name = "/dev/ttyO1", .flow_cntrl = 1, @@ -323,7 +323,7 @@ static struct pdata_init auxdata_quirks[] __initdata = { { /* sentinel */ }, }; -struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { +static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { #ifdef CONFIG_MACH_NOKIA_N8X0 OF_DEV_AUXDATA("ti,omap2420-mmc", 0x4809c000, "mmci-omap.0", NULL), OF_DEV_AUXDATA("menelaus", 0x72, "1-0072", &n8x0_menelaus_platform_data), diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c index 70bc7066a4c2..7829d274e037 100644 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c @@ -349,6 +349,41 @@ static struct powerdomain device_81xx_pwrdm = { .voltdm = { .name = "core" }, }; +static struct powerdomain gem_814x_pwrdm = { + .name = "gem_pwrdm", + .prcm_offs = TI814X_PRM_DSP_MOD, + .pwrsts = PWRSTS_OFF_ON, + .voltdm = { .name = "dsp" }, +}; + +static struct powerdomain ivahd_814x_pwrdm = { + .name = "ivahd_pwrdm", + .prcm_offs = TI814X_PRM_HDVICP_MOD, + .pwrsts = PWRSTS_OFF_ON, + .voltdm = { .name = "iva" }, +}; + +static struct powerdomain hdvpss_814x_pwrdm = { + .name = "hdvpss_pwrdm", + .prcm_offs = TI814X_PRM_HDVPSS_MOD, + .pwrsts = PWRSTS_OFF_ON, + .voltdm = { .name = "dsp" }, +}; + +static struct powerdomain sgx_814x_pwrdm = { + .name = "sgx_pwrdm", + .prcm_offs = TI814X_PRM_GFX_MOD, + .pwrsts = PWRSTS_OFF_ON, + .voltdm = { .name = "core" }, +}; + +static struct powerdomain isp_814x_pwrdm = { + .name = "isp_pwrdm", + .prcm_offs = TI814X_PRM_ISP_MOD, + .pwrsts = PWRSTS_OFF_ON, + .voltdm = { .name = "core" }, +}; + static struct powerdomain active_816x_pwrdm = { .name = "active_pwrdm", .prcm_offs = TI816X_PRM_ACTIVE_MOD, @@ -448,7 +483,18 @@ static struct powerdomain *powerdomains_am35x[] __initdata = { NULL }; -static struct powerdomain *powerdomains_ti81xx[] __initdata = { +static struct powerdomain *powerdomains_ti814x[] __initdata = { + &alwon_81xx_pwrdm, + &device_81xx_pwrdm, + &gem_814x_pwrdm, + &ivahd_814x_pwrdm, + &hdvpss_814x_pwrdm, + &sgx_814x_pwrdm, + &isp_814x_pwrdm, + NULL +}; + +static struct powerdomain *powerdomains_ti816x[] __initdata = { &alwon_81xx_pwrdm, &device_81xx_pwrdm, &active_816x_pwrdm, @@ -460,6 +506,73 @@ static struct powerdomain *powerdomains_ti81xx[] __initdata = { NULL }; +/* TI81XX specific ops */ +#define TI81XX_PM_PWSTCTRL 0x0000 +#define TI81XX_RM_RSTCTRL 0x0010 +#define TI81XX_PM_PWSTST 0x0004 + +static int ti81xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) +{ + omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, + (pwrst << OMAP_POWERSTATE_SHIFT), + pwrdm->prcm_offs, TI81XX_PM_PWSTCTRL); + return 0; +} + +static int ti81xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) +{ + return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, + TI81XX_PM_PWSTCTRL, + OMAP_POWERSTATE_MASK); +} + +static int ti81xx_pwrdm_read_pwrst(struct powerdomain *pwrdm) +{ + return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, + (pwrdm->prcm_offs == TI814X_PRM_GFX_MOD) ? TI81XX_RM_RSTCTRL : + TI81XX_PM_PWSTST, + OMAP_POWERSTATEST_MASK); +} + +static int ti81xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) +{ + return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, + (pwrdm->prcm_offs == TI814X_PRM_GFX_MOD) ? TI81XX_RM_RSTCTRL : + TI81XX_PM_PWSTST, + OMAP3430_LOGICSTATEST_MASK); +} + +static int ti81xx_pwrdm_wait_transition(struct powerdomain *pwrdm) +{ + u32 c = 0; + + while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, + (pwrdm->prcm_offs == TI814X_PRM_GFX_MOD) ? TI81XX_RM_RSTCTRL : + TI81XX_PM_PWSTST) & + OMAP_INTRANSITION_MASK) && + (c++ < PWRDM_TRANSITION_BAILOUT)) + udelay(1); + + if (c > PWRDM_TRANSITION_BAILOUT) { + pr_err("powerdomain: %s timeout waiting for transition\n", + pwrdm->name); + return -EAGAIN; + } + + pr_debug("powerdomain: completed transition in %d loops\n", c); + + return 0; +} + +/* For dm814x we need to fix up fix GFX pwstst and rstctrl reg offsets */ +static struct pwrdm_ops ti81xx_pwrdm_operations = { + .pwrdm_set_next_pwrst = ti81xx_pwrdm_set_next_pwrst, + .pwrdm_read_next_pwrst = ti81xx_pwrdm_read_next_pwrst, + .pwrdm_read_pwrst = ti81xx_pwrdm_read_pwrst, + .pwrdm_read_logic_pwrst = ti81xx_pwrdm_read_logic_pwrst, + .pwrdm_wait_transition = ti81xx_pwrdm_wait_transition, +}; + void __init omap3xxx_powerdomains_init(void) { unsigned int rev; @@ -467,15 +580,18 @@ void __init omap3xxx_powerdomains_init(void) if (!cpu_is_omap34xx() && !cpu_is_ti81xx()) return; - pwrdm_register_platform_funcs(&omap3_pwrdm_operations); + pwrdm_register_platform_funcs(&ti81xx_pwrdm_operations); rev = omap_rev(); if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) { pwrdm_register_pwrdms(powerdomains_am35x); + } else if (rev == TI8148_REV_ES1_0 || rev == TI8148_REV_ES2_0 || + rev == TI8148_REV_ES2_1) { + pwrdm_register_pwrdms(powerdomains_ti814x); } else if (rev == TI8168_REV_ES1_0 || rev == TI8168_REV_ES1_1 || rev == TI8168_REV_ES2_0 || rev == TI8168_REV_ES2_1) { - pwrdm_register_pwrdms(powerdomains_ti81xx); + pwrdm_register_pwrdms(powerdomains_ti816x); } else { pwrdm_register_pwrdms(powerdomains_omap3430_common); diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 6ae0b3a1781e..c8f590b7c32d 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -51,6 +51,12 @@ /* * TI81XX PRM module offsets */ +#define TI814X_PRM_DSP_MOD 0x0a00 +#define TI814X_PRM_HDVICP_MOD 0x0c00 +#define TI814X_PRM_ISP_MOD 0x0d00 +#define TI814X_PRM_HDVPSS_MOD 0x0e00 +#define TI814X_PRM_GFX_MOD 0x0f00 + #define TI81XX_PRM_DEVICE_MOD 0x0000 #define TI816X_PRM_ACTIVE_MOD 0x0a00 #define TI81XX_PRM_DEFAULT_MOD 0x0b00 @@ -472,6 +478,7 @@ struct omap_prcm_irq { * struct omap_prcm_irq_setup - PRCM interrupt controller details * @ack: PRM register offset for the first PRM_IRQSTATUS_MPU register * @mask: PRM register offset for the first PRM_IRQENABLE_MPU register + * @pm_ctrl: PRM register offset for the PRM_IO_PMCTRL register * @nr_regs: number of PRM_IRQ{STATUS,ENABLE}_MPU* registers * @nr_irqs: number of entries in the @irqs array * @irqs: ptr to an array of PRCM interrupt bits (see @nr_irqs) @@ -494,6 +501,7 @@ struct omap_prcm_irq { struct omap_prcm_irq_setup { u16 ack; u16 mask; + u16 pm_ctrl; u8 nr_regs; u8 nr_irqs; const struct omap_prcm_irq *irqs; diff --git a/arch/arm/mach-omap2/prcm43xx.h b/arch/arm/mach-omap2/prcm43xx.h index 7eebc27fa892..7c34c44eb0ae 100644 --- a/arch/arm/mach-omap2/prcm43xx.h +++ b/arch/arm/mach-omap2/prcm43xx.h @@ -25,6 +25,13 @@ #define AM43XX_PRM_WKUP_INST 0x2000 #define AM43XX_PRM_DEVICE_INST 0x4000 +/* PRM_IRQ offsets */ +#define AM43XX_PRM_IRQSTATUS_MPU_OFFSET 0x0004 +#define AM43XX_PRM_IRQENABLE_MPU_OFFSET 0x0008 + +/* Other PRM offsets */ +#define AM43XX_PRM_IO_PMCTRL_OFFSET 0x0024 + /* RM RSTCTRL offsets */ #define AM43XX_RM_PER_RSTCTRL_OFFSET 0x0010 #define AM43XX_RM_GFX_RSTCTRL_OFFSET 0x0010 diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 4541700f743a..30768003f854 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -18,13 +18,14 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/of_irq.h> - +#include <linux/of.h> #include "soc.h" #include "iomap.h" #include "common.h" #include "vp.h" #include "prm44xx.h" +#include "prcm43xx.h" #include "prm-regbits-44xx.h" #include "prcm44xx.h" #include "prminst44xx.h" @@ -45,6 +46,7 @@ static const struct omap_prcm_irq omap4_prcm_irqs[] = { static struct omap_prcm_irq_setup omap4_prcm_irq_setup = { .ack = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, .mask = OMAP4_PRM_IRQENABLE_MPU_OFFSET, + .pm_ctrl = OMAP4_PRM_IO_PMCTRL_OFFSET, .nr_regs = 2, .irqs = omap4_prcm_irqs, .nr_irqs = ARRAY_SIZE(omap4_prcm_irqs), @@ -216,11 +218,11 @@ static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs) */ static void omap44xx_prm_read_pending_irqs(unsigned long *events) { - events[0] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_OFFSET, - OMAP4_PRM_IRQSTATUS_MPU_OFFSET); + int i; - events[1] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_2_OFFSET, - OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET); + for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) + events[i] = _read_pending_irq_reg(omap4_prcm_irq_setup.mask + + i * 4, omap4_prcm_irq_setup.ack + i * 4); } /** @@ -250,17 +252,17 @@ static void omap44xx_prm_ocp_barrier(void) */ static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask) { - saved_mask[0] = - omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, - OMAP4_PRM_IRQENABLE_MPU_OFFSET); - saved_mask[1] = - omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, - OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); + int i; + u16 reg; + + for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) { + reg = omap4_prcm_irq_setup.mask + i * 4; - omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, - OMAP4_PRM_IRQENABLE_MPU_OFFSET); - omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, - OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); + saved_mask[i] = + omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, + reg); + omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, reg); + } /* OCP barrier */ omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, @@ -279,10 +281,12 @@ static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask) */ static void omap44xx_prm_restore_irqen(u32 *saved_mask) { - omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST, - OMAP4_PRM_IRQENABLE_MPU_OFFSET); - omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST, - OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); + int i; + + for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) + omap4_prm_write_inst_reg(saved_mask[i], + OMAP4430_PRM_OCP_SOCKET_INST, + omap4_prcm_irq_setup.mask + i * 4); } /** @@ -306,10 +310,10 @@ static void omap44xx_prm_reconfigure_io_chain(void) omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, OMAP4430_WUCLK_CTRL_MASK, inst, - OMAP4_PRM_IO_PMCTRL_OFFSET); + omap4_prcm_irq_setup.pm_ctrl); omap_test_timeout( (((omap4_prm_read_inst_reg(inst, - OMAP4_PRM_IO_PMCTRL_OFFSET) & + omap4_prcm_irq_setup.pm_ctrl) & OMAP4430_WUCLK_STATUS_MASK) >> OMAP4430_WUCLK_STATUS_SHIFT) == 1), MAX_IOPAD_LATCH_TIME, i); @@ -319,10 +323,10 @@ static void omap44xx_prm_reconfigure_io_chain(void) /* Trigger WUCLKIN disable */ omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0, inst, - OMAP4_PRM_IO_PMCTRL_OFFSET); + omap4_prcm_irq_setup.pm_ctrl); omap_test_timeout( (((omap4_prm_read_inst_reg(inst, - OMAP4_PRM_IO_PMCTRL_OFFSET) & + omap4_prcm_irq_setup.pm_ctrl) & OMAP4430_WUCLK_STATUS_MASK) >> OMAP4430_WUCLK_STATUS_SHIFT) == 0), MAX_IOPAD_LATCH_TIME, i); @@ -350,7 +354,7 @@ static void __init omap44xx_prm_enable_io_wakeup(void) omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK, OMAP4430_GLOBAL_WUEN_MASK, inst, - OMAP4_PRM_IO_PMCTRL_OFFSET); + omap4_prcm_irq_setup.pm_ctrl); } /** @@ -719,6 +723,15 @@ int __init omap44xx_prm_init(const struct omap_prcm_init_data *data) omap4_prminst_set_prm_dev_inst(data->device_inst_offset); + /* Add AM437X specific differences */ + if (of_device_is_compatible(data->np, "ti,am4-prcm")) { + omap4_prcm_irq_setup.nr_irqs = 1; + omap4_prcm_irq_setup.nr_regs = 1; + omap4_prcm_irq_setup.pm_ctrl = AM43XX_PRM_IO_PMCTRL_OFFSET; + omap4_prcm_irq_setup.ack = AM43XX_PRM_IRQSTATUS_MPU_OFFSET; + omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET; + } + return prm_register(&omap44xx_prm_ll_data); } diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 7add7994dbfc..1730fc494221 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -696,6 +696,7 @@ static struct omap_prcm_init_data am4_prm_data __initdata = { .index = TI_CLKM_PRM, .init = omap44xx_prm_init, .device_inst_offset = AM43XX_PRM_DEVICE_INST, + .flags = PRM_HAS_IO_WAKEUP, }; #endif diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index cac46d852da1..f44bcab3f52f 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -208,8 +208,7 @@ static void __init omap_dmtimer_init(void) /* If we are a secure device, remove any secure timer nodes */ if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) { np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure"); - if (np) - of_node_put(np); + of_node_put(np); } } @@ -649,23 +648,10 @@ static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon", #ifdef CONFIG_ARCH_OMAP4 #ifdef CONFIG_HAVE_ARM_TWD -static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29); void __init omap4_local_timer_init(void) { omap4_sync32k_timer_init(); - /* Local timers are not supprted on OMAP4430 ES1.0 */ - if (omap_rev() != OMAP4430_REV_ES1_0) { - int err; - - if (of_have_populated_dt()) { - clocksource_of_init(); - return; - } - - err = twd_local_timer_register(&twd_local_timer); - if (err) - pr_err("twd_local_timer_register failed %d\n", err); - } + clocksource_of_init(); } #else void __init omap4_local_timer_init(void) diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig index e03d8b5c9ad0..9ab8932403e5 100644 --- a/arch/arm/mach-prima2/Kconfig +++ b/arch/arm/mach-prima2/Kconfig @@ -4,6 +4,7 @@ menuconfig ARCH_SIRF select ARCH_REQUIRE_GPIOLIB select GENERIC_IRQ_CHIP select NO_IOPORT_MAP + select REGMAP select PINCTRL select PINCTRL_SIRF help diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c index 8f66d8f7ca75..d4852d24dc7d 100644 --- a/arch/arm/mach-prima2/rtciobrg.c +++ b/arch/arm/mach-prima2/rtciobrg.c @@ -1,5 +1,5 @@ /* - * RTC I/O Bridge interfaces for CSR SiRFprimaII + * RTC I/O Bridge interfaces for CSR SiRFprimaII/atlas7 * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module * * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/regmap.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> @@ -66,6 +67,7 @@ u32 sirfsoc_rtc_iobrg_readl(u32 addr) { unsigned long flags, val; + /* TODO: add hwspinlock to sync with M3 */ spin_lock_irqsave(&rtciobrg_lock, flags); val = __sirfsoc_rtc_iobrg_readl(addr); @@ -90,6 +92,7 @@ void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr) { unsigned long flags; + /* TODO: add hwspinlock to sync with M3 */ spin_lock_irqsave(&rtciobrg_lock, flags); sirfsoc_rtc_iobrg_pre_writel(val, addr); @@ -102,6 +105,45 @@ void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr) } EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel); + +static int regmap_iobg_regwrite(void *context, unsigned int reg, + unsigned int val) +{ + sirfsoc_rtc_iobrg_writel(val, reg); + return 0; +} + +static int regmap_iobg_regread(void *context, unsigned int reg, + unsigned int *val) +{ + *val = (u32)sirfsoc_rtc_iobrg_readl(reg); + return 0; +} + +static struct regmap_bus regmap_iobg = { + .reg_write = regmap_iobg_regwrite, + .reg_read = regmap_iobg_regread, +}; + +/** + * devm_regmap_init_iobg(): Initialise managed register map + * + * @iobg: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +struct regmap *devm_regmap_init_iobg(struct device *dev, + const struct regmap_config *config) +{ + const struct regmap_bus *bus = ®map_iobg; + + return devm_regmap_init(dev, bus, dev, config); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_iobg); + static const struct of_device_id rtciobrg_ids[] = { { .compatible = "sirf,prima2-rtciobg" }, {} @@ -132,7 +174,7 @@ static int __init sirfsoc_rtciobrg_init(void) } postcore_initcall(sirfsoc_rtciobrg_init); -MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, " - "Barry Song <baohua.song@csr.com>"); +MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>"); +MODULE_AUTHOR("Barry Song <baohua.song@csr.com>"); MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge"); MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 35434662dc7c..e6ce669b54af 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -17,6 +17,7 @@ #include <linux/platform_data/camera-pxa.h> #include <mach/audio.h> #include <mach/hardware.h> +#include <linux/platform_data/mmp_dma.h> #include <linux/platform_data/mtd-nand-pxa3xx.h> #include "devices.h" @@ -1193,3 +1194,39 @@ void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info) pd->dev.platform_data = info; platform_device_add(pd); } + +static struct mmp_dma_platdata pxa_dma_pdata = { + .dma_channels = 0, +}; + +static struct resource pxa_dma_resource[] = { + [0] = { + .start = 0x40000000, + .end = 0x4000ffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_DMA, + .end = IRQ_DMA, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 pxadma_dmamask = 0xffffffffUL; + +static struct platform_device pxa2xx_pxa_dma = { + .name = "pxa-dma", + .id = 0, + .dev = { + .dma_mask = &pxadma_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pxa_dma_resource), + .resource = pxa_dma_resource, +}; + +void __init pxa2xx_set_dmac_info(int nb_channels) +{ + pxa_dma_pdata.dma_channels = nb_channels; + pxa_register_device(&pxa2xx_pxa_dma, &pxa_dma_pdata); +} diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 23a90c62ec11..1dc85ffc3e20 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -206,6 +206,7 @@ static int __init pxa25x_init(void) register_syscore_ops(&pxa_irq_syscore_ops); register_syscore_ops(&pxa2xx_mfp_syscore_ops); + pxa2xx_set_dmac_info(16); pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info); ret = platform_add_devices(pxa25x_devices, ARRAY_SIZE(pxa25x_devices)); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index b5abdeb5bb2d..e6aae9e8adfb 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -310,6 +310,7 @@ static int __init pxa27x_init(void) if (!of_have_populated_dt()) { pxa_register_device(&pxa27x_device_gpio, &pxa27x_gpio_info); + pxa2xx_set_dmac_info(32); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index bd4cbef15ccf..aa85ec1a3065 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -431,6 +431,7 @@ static int __init pxa3xx_init(void) if (of_have_populated_dt()) return 0; + pxa2xx_set_dmac_info(32); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); if (ret) return ret; diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 051a6555cbf9..bdc0c41bc4fd 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -841,11 +841,9 @@ static int sharpsl_pm_probe(struct platform_device *pdev) sharpsl_pm.charge_mode = CHRG_OFF; sharpsl_pm.flags = 0; - init_timer(&sharpsl_pm.ac_timer); - sharpsl_pm.ac_timer.function = sharpsl_ac_timer; + setup_timer(&sharpsl_pm.ac_timer, sharpsl_ac_timer, 0UL); - init_timer(&sharpsl_pm.chrg_full_timer); - sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; + setup_timer(&sharpsl_pm.chrg_full_timer, sharpsl_chrg_full_timer, 0UL); led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger); diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c index 685deff861d2..e0a53208880a 100644 --- a/arch/arm/mach-pxa/tosa-bt.c +++ b/arch/arm/mach-pxa/tosa-bt.c @@ -131,17 +131,4 @@ static struct platform_driver tosa_bt_driver = { .name = "tosa-bt", }, }; - - -static int __init tosa_bt_init(void) -{ - return platform_driver_register(&tosa_bt_driver); -} - -static void __exit tosa_bt_exit(void) -{ - platform_driver_unregister(&tosa_bt_driver); -} - -module_init(tosa_bt_init); -module_exit(tosa_bt_exit); +module_platform_driver(tosa_bt_driver); diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c index 8fcec1cc101e..3e7a4b761a95 100644 --- a/arch/arm/mach-rockchip/platsmp.c +++ b/arch/arm/mach-rockchip/platsmp.c @@ -72,29 +72,22 @@ static struct reset_control *rockchip_get_core_reset(int cpu) static int pmu_set_power_domain(int pd, bool on) { u32 val = (on) ? 0 : BIT(pd); + struct reset_control *rstc = rockchip_get_core_reset(pd); int ret; + if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { + pr_err("%s: could not get reset control for core %d\n", + __func__, pd); + return PTR_ERR(rstc); + } + /* * We need to soft reset the cpu when we turn off the cpu power domain, * or else the active processors might be stalled when the individual * processor is powered down. */ - if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { - struct reset_control *rstc = rockchip_get_core_reset(pd); - - if (IS_ERR(rstc)) { - pr_err("%s: could not get reset control for core %d\n", - __func__, pd); - return PTR_ERR(rstc); - } - - if (on) - reset_control_deassert(rstc); - else - reset_control_assert(rstc); - - reset_control_put(rstc); - } + if (!IS_ERR(rstc) && !on) + reset_control_assert(rstc); ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val); if (ret < 0) { @@ -107,11 +100,17 @@ static int pmu_set_power_domain(int pd, bool on) ret = pmu_power_domain_is_on(pd); if (ret < 0) { pr_err("%s: could not read power domain state\n", - __func__); + __func__); return ret; } } + if (!IS_ERR(rstc)) { + if (on) + reset_control_deassert(rstc); + reset_control_put(rstc); + } + return 0; } @@ -130,7 +129,7 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle) if (cpu >= ncores) { pr_err("%s: cpu %d outside maximum number of cpus %d\n", - __func__, cpu, ncores); + __func__, cpu, ncores); return -ENXIO; } @@ -140,14 +139,19 @@ static int rockchip_boot_secondary(unsigned int cpu, struct task_struct *idle) return ret; if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) { - /* We communicate with the bootrom to active the cpus other + /* + * We communicate with the bootrom to active the cpus other * than cpu0, after a blob of initialize code, they will * stay at wfe state, once they are actived, they will check * the mailbox: * sram_base_addr + 4: 0xdeadbeaf * sram_base_addr + 8: start address for pc - * */ - udelay(10); + * The cpu0 need to wait the other cpus other than cpu0 entering + * the wfe state.The wait time is affected by many aspects. + * (e.g: cpu frequency, bootrom frequency, sram frequency, ...) + */ + mdelay(1); /* ensure the cpus other than cpu0 to startup */ + writel(virt_to_phys(secondary_startup), sram_base_addr + 8); writel(0xDEADBEAF, sram_base_addr + 4); dsb_sev(); @@ -317,6 +321,13 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus) #ifdef CONFIG_HOTPLUG_CPU static int rockchip_cpu_kill(unsigned int cpu) { + /* + * We need a delay here to ensure that the dying CPU can finish + * executing v7_coherency_exit() and reach the WFI/WFE state + * prior to having the power domain disabled. + */ + mdelay(1); + pmu_set_power_domain(0 + cpu, false); return 1; } @@ -324,7 +335,7 @@ static int rockchip_cpu_kill(unsigned int cpu) static void rockchip_cpu_die(unsigned int cpu) { v7_exit_coherency_flush(louis); - while(1) + while (1) cpu_do_idle(); } #endif @@ -337,4 +348,5 @@ static struct smp_operations rockchip_smp_ops __initdata = { .cpu_die = rockchip_cpu_die, #endif }; + CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops); diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c index b0dcbe28f78c..156cd23dfba5 100644 --- a/arch/arm/mach-rockchip/pm.c +++ b/arch/arm/mach-rockchip/pm.c @@ -45,9 +45,11 @@ static phys_addr_t rk3288_bootram_phy; static struct regmap *pmu_regmap; static struct regmap *sgrf_regmap; +static struct regmap *grf_regmap; static u32 rk3288_pmu_pwr_mode_con; static u32 rk3288_sgrf_soc_con0; +static u32 rk3288_sgrf_cpu_con0; static inline u32 rk3288_l2_config(void) { @@ -66,10 +68,37 @@ static void rk3288_config_bootdata(void) rkpm_bootdata_l2ctlr = rk3288_l2_config(); } +#define GRF_UOC0_CON0 0x320 +#define GRF_UOC1_CON0 0x334 +#define GRF_UOC2_CON0 0x348 +#define GRF_SIDDQ BIT(13) + +static bool rk3288_slp_disable_osc(void) +{ + static const u32 reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0, + GRF_UOC2_CON0 }; + u32 reg, i; + + /* + * if any usb phy is still on(GRF_SIDDQ==0), that means we need the + * function of usb wakeup, so do not switch to 32khz, since the usb phy + * clk does not connect to 32khz osc + */ + for (i = 0; i < ARRAY_SIZE(reg_offset); i++) { + regmap_read(grf_regmap, reg_offset[i], ®); + if (!(reg & GRF_SIDDQ)) + return false; + } + + return true; +} + static void rk3288_slp_mode_set(int level) { u32 mode_set, mode_set1; + bool osc_disable = rk3288_slp_disable_osc(); + regmap_read(sgrf_regmap, RK3288_SGRF_CPU_CON0, &rk3288_sgrf_cpu_con0); regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0); regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON, @@ -94,9 +123,6 @@ static void rk3288_slp_mode_set(int level) regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR, rk3288_bootram_phy); - regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1, - PMU_ARMINT_WAKEUP_EN); - mode_set = BIT(PMU_GLOBAL_INT_DISABLE) | BIT(PMU_L2FLUSH_EN) | BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) | BIT(PMU_DDR0_GATING_EN) | BIT(PMU_DDR1_GATING_EN) | @@ -107,13 +133,31 @@ static void rk3288_slp_mode_set(int level) if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { /* arm off, logic deep sleep */ - mode_set |= BIT(PMU_BUS_PD_EN) | + mode_set |= BIT(PMU_BUS_PD_EN) | BIT(PMU_PMU_USE_LF) | BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) | - BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) | BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN); + if (osc_disable) + mode_set |= BIT(PMU_OSC_24M_DIS); + mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) | BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA); + + regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1, + PMU_ARMINT_WAKEUP_EN); + + /* + * In deep suspend we use PMU_PMU_USE_LF to let the rk3288 + * switch its main clock supply to the alternative 32kHz + * source. Therefore set 30ms on a 32kHz clock for pmic + * stabilization. Similar 30ms on 24MHz for the other + * mode below. + */ + regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, 32 * 30); + + /* only wait for stabilization, if we turned the osc off */ + regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT, + osc_disable ? 32 * 30 : 0); } else { /* * arm off, logic normal @@ -121,6 +165,15 @@ static void rk3288_slp_mode_set(int level) * wakeup will be error */ mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN); + + regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1, + PMU_ARMINT_WAKEUP_EN | PMU_GPIOINT_WAKEUP_EN); + + /* 30ms on a 24MHz clock for pmic stabilization */ + regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, 24000 * 30); + + /* oscillator is still running, so no need to wait */ + regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT, 0); } regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set); @@ -129,6 +182,9 @@ static void rk3288_slp_mode_set(int level) static void rk3288_slp_mode_set_resume(void) { + regmap_write(sgrf_regmap, RK3288_SGRF_CPU_CON0, + rk3288_sgrf_cpu_con0 | SGRF_DAPDEVICEEN_WRITE); + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, rk3288_pmu_pwr_mode_con); @@ -193,6 +249,13 @@ static int rk3288_suspend_init(struct device_node *np) return PTR_ERR(pmu_regmap); } + grf_regmap = syscon_regmap_lookup_by_compatible( + "rockchip,rk3288-grf"); + if (IS_ERR(grf_regmap)) { + pr_err("%s: could not find grf regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + sram_np = of_find_compatible_node(NULL, NULL, "rockchip,rk3288-pmu-sram"); if (!sram_np) { @@ -221,9 +284,6 @@ static int rk3288_suspend_init(struct device_node *np) memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume, rk3288_bootram_sz); - regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT, OSC_STABL_CNT_THRESH); - regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, PMU_STABL_CNT_THRESH); - return 0; } diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h index 3e8d39c0c3d5..b5af26f8336e 100644 --- a/arch/arm/mach-rockchip/pm.h +++ b/arch/arm/mach-rockchip/pm.h @@ -59,19 +59,9 @@ static inline void rockchip_suspend_init(void) #define SGRF_DAPDEVICEEN BIT(0) #define SGRF_DAPDEVICEEN_WRITE BIT(16) -#define RK3288_CRU_MODE_CON 0x50 -#define RK3288_CRU_SEL0_CON 0x60 -#define RK3288_CRU_SEL1_CON 0x64 -#define RK3288_CRU_SEL10_CON 0x88 -#define RK3288_CRU_SEL33_CON 0xe4 -#define RK3288_CRU_SEL37_CON 0xf4 - /* PMU_WAKEUP_CFG1 bits */ #define PMU_ARMINT_WAKEUP_EN BIT(0) - -/* wait 30ms for OSC stable and 30ms for pmic stable */ -#define OSC_STABL_CNT_THRESH (32 * 30) -#define PMU_STABL_CNT_THRESH (32 * 30) +#define PMU_GPIOINT_WAKEUP_EN BIT(3) enum rk3288_pwr_mode_con { PMU_PWR_MODE_EN = 0, diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 45006479d461..429157d437f5 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -80,6 +80,11 @@ config ARCH_R8A7791 select ARCH_RCAR_GEN2 select I2C +config ARCH_R8A7793 + bool "R-Car M2-N (R8A7793)" + select ARCH_RCAR_GEN2 + select I2C + config ARCH_R8A7794 bool "R-Car E2 (R8A77940)" select ARCH_RCAR_GEN2 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 89e463de4479..def7a093d99c 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o pm-r8a7779.o obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o +obj-$(CONFIG_ARCH_R8A7793) += setup-r8a7793.o obj-$(CONFIG_ARCH_R8A7794) += setup-r8a7794.o obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o @@ -34,6 +35,7 @@ obj-$(CONFIG_ARCH_RCAR_GEN2) += setup-rcar-gen2.o platsmp-apmu.o $(cpu-y) CFLAGS_setup-rcar-gen2.o += -march=armv7-a obj-$(CONFIG_ARCH_R8A7790) += regulator-quirk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += regulator-quirk-rcar-gen2.o +obj-$(CONFIG_ARCH_R8A7793) += regulator-quirk-rcar-gen2.o # SMP objects smp-y := $(cpu-y) diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c index 384e6e934b87..62437b57813e 100644 --- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c @@ -123,7 +123,8 @@ static int __init rcar_gen2_regulator_quirk(void) u32 mon; if (!of_machine_is_compatible("renesas,koelsch") && - !of_machine_is_compatible("renesas,lager")) + !of_machine_is_compatible("renesas,lager") && + !of_machine_is_compatible("renesas,gose")) return -ENODEV; irqc = ioremap(IRQC_BASE, PAGE_SIZE); diff --git a/arch/arm/mach-shmobile/setup-r8a7793.c b/arch/arm/mach-shmobile/setup-r8a7793.c new file mode 100644 index 000000000000..1d2825cb7a65 --- /dev/null +++ b/arch/arm/mach-shmobile/setup-r8a7793.c @@ -0,0 +1,33 @@ +/* + * r8a7793 processor support + * + * Copyright (C) 2015 Ulrich Hecht + * + * 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; version 2 of the License. + * + * 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. + */ + +#include <linux/init.h> +#include <asm/mach/arch.h> + +#include "common.h" +#include "rcar-gen2.h" + +static const char *r8a7793_boards_compat_dt[] __initconst = { + "renesas,r8a7793", + NULL, +}; + +DT_MACHINE_START(R8A7793_DT, "Generic R8A7793 (Flattened Device Tree)") + .init_early = shmobile_init_delay, + .init_time = rcar_gen2_timer_init, + .init_late = shmobile_init_late, + .reserve = rcar_gen2_reserve, + .dt_compat = r8a7793_boards_compat_dt, +MACHINE_END diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index 7259c3732702..5bc6ea87cdf7 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -25,6 +25,7 @@ #define SOCFPGA_RSTMGR_MODPERRST 0x14 #define SOCFPGA_RSTMGR_BRGMODRST 0x1c +#define SOCFPGA_A10_RSTMGR_CTRL 0xC #define SOCFPGA_A10_RSTMGR_MODMPURST 0x20 /* System Manager bits */ diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c index c6f1df89f9af..15c8ce8965f4 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c @@ -106,11 +106,23 @@ static void socfpga_cpu_die(unsigned int cpu) cpu_do_idle(); } +/* + * We need a dummy function so that platform_can_cpu_hotplug() knows + * we support CPU hotplug. However, the function does not need to do + * anything, because CPUs going offline just do WFI. We could reset + * the CPUs but it would increase power consumption. + */ +static int socfpga_cpu_kill(unsigned int cpu) +{ + return 1; +} + static struct smp_operations socfpga_smp_ops __initdata = { .smp_prepare_cpus = socfpga_smp_prepare_cpus, .smp_boot_secondary = socfpga_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = socfpga_cpu_die, + .cpu_kill = socfpga_cpu_kill, #endif }; @@ -119,6 +131,7 @@ static struct smp_operations socfpga_a10_smp_ops __initdata = { .smp_boot_secondary = socfpga_a10_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = socfpga_cpu_die, + .cpu_kill = socfpga_cpu_kill, #endif }; diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index 19643a756c48..a1c0efaa8794 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -74,6 +74,19 @@ static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) writel(temp, rst_manager_base_addr + SOCFPGA_RSTMGR_CTRL); } +static void socfpga_arria10_restart(enum reboot_mode mode, const char *cmd) +{ + u32 temp; + + temp = readl(rst_manager_base_addr + SOCFPGA_A10_RSTMGR_CTRL); + + if (mode == REBOOT_HARD) + temp |= RSTMGR_CTRL_SWCOLDRSTREQ; + else + temp |= RSTMGR_CTRL_SWWARMRSTREQ; + writel(temp, rst_manager_base_addr + SOCFPGA_A10_RSTMGR_CTRL); +} + static const char *altera_dt_match[] = { "altr,socfpga", NULL @@ -86,3 +99,16 @@ DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") .restart = socfpga_cyclone5_restart, .dt_compat = altera_dt_match, MACHINE_END + +static const char *altera_a10_dt_match[] = { + "altr,socfpga-arria10", + NULL +}; + +DT_MACHINE_START(SOCFPGA_A10, "Altera SOCFPGA Arria10") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, + .init_irq = socfpga_init_irq, + .restart = socfpga_arria10_restart, + .dt_compat = altera_a10_dt_match, +MACHINE_END diff --git a/arch/arm/mach-sti/headsmp.S b/arch/arm/mach-sti/headsmp.S index 4c09bae86edf..e0ad451700d5 100644 --- a/arch/arm/mach-sti/headsmp.S +++ b/arch/arm/mach-sti/headsmp.S @@ -37,6 +37,7 @@ pen: ldr r7, [r6] * should now contain the SVC stack for this core */ b secondary_startup +ENDPROC(sti_secondary_startup) 1: .long . .long pen_release diff --git a/arch/arm/mach-sti/platsmp.c b/arch/arm/mach-sti/platsmp.c index d4b624f8dfcb..c4ad6eae67fa 100644 --- a/arch/arm/mach-sti/platsmp.c +++ b/arch/arm/mach-sti/platsmp.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/memblock.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> @@ -38,8 +39,6 @@ static DEFINE_SPINLOCK(boot_lock); static void sti_secondary_init(unsigned int cpu) { - trace_hardirqs_off(); - /* * let the primary processor know we're out of the * pen, then head off into the C entry point @@ -99,14 +98,62 @@ static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) static void __init sti_smp_prepare_cpus(unsigned int max_cpus) { - void __iomem *scu_base = NULL; - struct device_node *np = of_find_compatible_node( - NULL, NULL, "arm,cortex-a9-scu"); + struct device_node *np; + void __iomem *scu_base; + u32 __iomem *cpu_strt_ptr; + u32 release_phys; + int cpu; + unsigned long entry_pa = virt_to_phys(sti_secondary_startup); + + np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (np) { scu_base = of_iomap(np, 0); scu_enable(scu_base); of_node_put(np); } + + if (max_cpus <= 1) + return; + + for_each_possible_cpu(cpu) { + + np = of_get_cpu_node(cpu, NULL); + + if (!np) + continue; + + if (of_property_read_u32(np, "cpu-release-addr", + &release_phys)) { + pr_err("CPU %d: missing or invalid cpu-release-addr " + "property\n", cpu); + continue; + } + + /* + * holding pen is usually configured in SBC DMEM but can also be + * in RAM. + */ + + if (!memblock_is_memory(release_phys)) + cpu_strt_ptr = + ioremap(release_phys, sizeof(release_phys)); + else + cpu_strt_ptr = + (u32 __iomem *)phys_to_virt(release_phys); + + __raw_writel(entry_pa, cpu_strt_ptr); + + /* + * wmb so that data is actually written + * before cache flush is done + */ + smp_wmb(); + sync_cache_w(cpu_strt_ptr); + + if (!memblock_is_memory(release_phys)) + iounmap(cpu_strt_ptr); + } } struct smp_operations __initdata sti_smp_ops = { diff --git a/arch/arm/mach-sti/smp.h b/arch/arm/mach-sti/smp.h index 1871b72b1a7e..ae22707d301f 100644 --- a/arch/arm/mach-sti/smp.h +++ b/arch/arm/mach-sti/smp.h @@ -14,4 +14,6 @@ extern struct smp_operations sti_smp_ops; +void sti_secondary_startup(void); + #endif diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 81502b90dd91..4efe2d43a126 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -35,7 +35,7 @@ config MACH_SUN7I select SUN5I_HSTIMER config MACH_SUN8I - bool "Allwinner A23 (sun8i) SoCs support" + bool "Allwinner sun8i Family SoCs support" default ARCH_SUNXI select ARM_GIC select MFD_SUN6I_PRCM diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 1bc811a74a9f..65bab2876343 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -67,10 +67,13 @@ MACHINE_END static const char * const sun8i_board_dt_compat[] = { "allwinner,sun8i-a23", + "allwinner,sun8i-a33", + "allwinner,sun8i-h3", NULL, }; -DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family") +DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family") + .init_time = sun6i_timer_init, .dt_compat = sun8i_board_dt_compat, .init_late = sunxi_dt_cpufreq_init, MACHINE_END diff --git a/arch/arm/mach-uniphier/platsmp.c b/arch/arm/mach-uniphier/platsmp.c index 5943e1cb7fe1..4b784f721135 100644 --- a/arch/arm/mach-uniphier/platsmp.c +++ b/arch/arm/mach-uniphier/platsmp.c @@ -60,12 +60,6 @@ err: sbcm_regmap = NULL; } -static void __naked uniphier_secondary_startup(void) -{ - asm("bl v7_invalidate_l1\n" - "b secondary_startup\n"); -}; - static int uniphier_boot_secondary(unsigned int cpu, struct task_struct *idle) { @@ -75,7 +69,7 @@ static int uniphier_boot_secondary(unsigned int cpu, return -ENODEV; ret = regmap_write(sbcm_regmap, 0x1208, - virt_to_phys(uniphier_secondary_startup)); + virt_to_phys(secondary_startup)); if (!ret) asm("sev"); /* wake up secondary CPU */ diff --git a/arch/arm/mach-zx/Kconfig b/arch/arm/mach-zx/Kconfig index 2a910dc0d15e..7fdc5bf24f9b 100644 --- a/arch/arm/mach-zx/Kconfig +++ b/arch/arm/mach-zx/Kconfig @@ -13,6 +13,7 @@ config SOC_ZX296702 select ARM_GLOBAL_TIMER select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP + select PM_GENERIC_DOMAINS help Support for ZTE ZX296702 SoC which is a dual core CortexA9MP endif diff --git a/arch/arm/mach-zx/Makefile b/arch/arm/mach-zx/Makefile index 7c2edf6e5f8b..a4b486433209 100644 --- a/arch/arm/mach-zx/Makefile +++ b/arch/arm/mach-zx/Makefile @@ -1,2 +1,2 @@ -obj-$(CONFIG_SOC_ZX296702) += zx296702.o +obj-$(CONFIG_SOC_ZX296702) += zx296702.o zx296702-pm-domain.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-zx/zx296702-pm-domain.c b/arch/arm/mach-zx/zx296702-pm-domain.c new file mode 100644 index 000000000000..e08574d4e2ca --- /dev/null +++ b/arch/arm/mach-zx/zx296702-pm-domain.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2015 Linaro Ltd. + * + * Author: Jun Nie <jun.nie@linaro.org> + * License terms: GNU General Public License (GPL) version 2 + */ +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_domain.h> +#include <linux/slab.h> + +#define PCU_DM_CLKEN 0x18 +#define PCU_DM_RSTEN 0x1C +#define PCU_DM_ISOEN 0x20 +#define PCU_DM_PWRDN 0x24 +#define PCU_DM_ACK_SYNC 0x28 + +enum { + PCU_DM_NEON0 = 0, + PCU_DM_NEON1, + PCU_DM_GPU, + PCU_DM_DECPPU, + PCU_DM_VOU, + PCU_DM_R2D, + PCU_DM_TOP, +}; + +static void __iomem *pcubase; + +struct zx_pm_domain { + struct generic_pm_domain dm; + unsigned int bit; +}; + +static int normal_power_off(struct generic_pm_domain *domain) +{ + struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain; + unsigned long loop = 1000; + u32 tmp; + + tmp = readl_relaxed(pcubase + PCU_DM_CLKEN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp, pcubase + PCU_DM_CLKEN); + udelay(5); + + tmp = readl_relaxed(pcubase + PCU_DM_ISOEN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_ISOEN); + udelay(5); + + tmp = readl_relaxed(pcubase + PCU_DM_RSTEN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp, pcubase + PCU_DM_RSTEN); + udelay(5); + + tmp = readl_relaxed(pcubase + PCU_DM_PWRDN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_PWRDN); + do { + tmp = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit); + } while (--loop && !tmp); + + if (!loop) { + pr_err("Error: %s %s fail\n", __func__, domain->name); + return -EIO; + } + + return 0; +} + +static int normal_power_on(struct generic_pm_domain *domain) +{ + struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain; + unsigned long loop = 10000; + u32 tmp; + + tmp = readl_relaxed(pcubase + PCU_DM_PWRDN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp, pcubase + PCU_DM_PWRDN); + do { + tmp = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit); + } while (--loop && tmp); + + if (!loop) { + pr_err("Error: %s %s fail\n", __func__, domain->name); + return -EIO; + } + + tmp = readl_relaxed(pcubase + PCU_DM_RSTEN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_RSTEN); + udelay(5); + + tmp = readl_relaxed(pcubase + PCU_DM_ISOEN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp, pcubase + PCU_DM_ISOEN); + udelay(5); + + tmp = readl_relaxed(pcubase + PCU_DM_CLKEN); + tmp &= ~BIT(zpd->bit); + writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_CLKEN); + udelay(5); + return 0; +} + +static struct zx_pm_domain gpu_domain = { + .dm = { + .name = "gpu_domain", + .power_off = normal_power_off, + .power_on = normal_power_on, + }, + .bit = PCU_DM_GPU, +}; + +static struct zx_pm_domain decppu_domain = { + .dm = { + .name = "decppu_domain", + .power_off = normal_power_off, + .power_on = normal_power_on, + }, + .bit = PCU_DM_DECPPU, +}; + +static struct zx_pm_domain vou_domain = { + .dm = { + .name = "vou_domain", + .power_off = normal_power_off, + .power_on = normal_power_on, + }, + .bit = PCU_DM_VOU, +}; + +static struct zx_pm_domain r2d_domain = { + .dm = { + .name = "r2d_domain", + .power_off = normal_power_off, + .power_on = normal_power_on, + }, + .bit = PCU_DM_R2D, +}; + +static struct generic_pm_domain *zx296702_pm_domains[] = { + &vou_domain.dm, + &gpu_domain.dm, + &decppu_domain.dm, + &r2d_domain.dm, +}; + +static int zx296702_pd_probe(struct platform_device *pdev) +{ + struct genpd_onecell_data *genpd_data; + struct resource *res; + int i; + + genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL); + if (!genpd_data) + return -ENOMEM; + + genpd_data->domains = zx296702_pm_domains; + genpd_data->num_domains = ARRAY_SIZE(zx296702_pm_domains); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + + pcubase = devm_ioremap_resource(&pdev->dev, res); + if (!pcubase) { + dev_err(&pdev->dev, "ioremap fail.\n"); + return -EIO; + } + + for (i = 0; i < ARRAY_SIZE(zx296702_pm_domains); ++i) + pm_genpd_init(zx296702_pm_domains[i], NULL, false); + + of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data); + return 0; +} + +static const struct of_device_id zx296702_pm_domain_matches[] __initconst = { + { .compatible = "zte,zx296702-pcu", }, + { }, +}; + +static struct platform_driver zx296702_pd_driver __initdata = { + .driver = { + .name = "zx-powerdomain", + .owner = THIS_MODULE, + .of_match_table = zx296702_pm_domain_matches, + }, + .probe = zx296702_pd_probe, +}; + +static int __init zx296702_pd_init(void) +{ + return platform_driver_register(&zx296702_pd_driver); +} +subsys_initcall(zx296702_pd_init); diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 616d5840fc2e..6bd4a43e1a78 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -197,8 +197,8 @@ static const char * const zynq_dt_match[] = { DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") /* 64KB way size, 8-way associativity, parity disabled */ - .l2c_aux_val = 0x00000000, - .l2c_aux_mask = 0xffffffff, + .l2c_aux_val = 0x00400000, + .l2c_aux_mask = 0xffbfffff, .smp = smp_ops(zynq_smp_ops), .map_io = zynq_map_io, .init_irq = zynq_irq_init, diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S index 045c72720a4d..f6d5de073e34 100644 --- a/arch/arm/mach-zynq/headsmp.S +++ b/arch/arm/mach-zynq/headsmp.S @@ -18,7 +18,7 @@ ARM_BE8(rev r0, r0) .globl zynq_secondary_trampoline_jump zynq_secondary_trampoline_jump: /* Space for jumping address */ - .word /* cpu 1 */ + .word 0 /* cpu 1 */ .globl zynq_secondary_trampoline_end zynq_secondary_trampoline_end: ENDPROC(zynq_secondary_trampoline) diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index d1e5ad7ab3bc..0c81056c1dd7 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -255,7 +255,7 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, } #endif -void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, +static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, size_t size, unsigned int mtype, void *caller) { const struct mem_type *type; @@ -363,7 +363,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, unsigned int mtype) { return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, - __builtin_return_address(0)); + __builtin_return_address(0)); } EXPORT_SYMBOL(__arm_ioremap_pfn); @@ -371,13 +371,26 @@ void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *) = __arm_ioremap_caller; -void __iomem * -__arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype) +void __iomem *ioremap(resource_size_t res_cookie, size_t size) +{ + return arch_ioremap_caller(res_cookie, size, MT_DEVICE, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap); + +void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) +{ + return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_cache); + +void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) { - return arch_ioremap_caller(phys_addr, size, mtype, - __builtin_return_address(0)); + return arch_ioremap_caller(res_cookie, size, MT_DEVICE_WC, + __builtin_return_address(0)); } -EXPORT_SYMBOL(__arm_ioremap); +EXPORT_SYMBOL(ioremap_wc); /* * Remap an arbitrary physical address space into the kernel virtual @@ -431,11 +444,11 @@ void __iounmap(volatile void __iomem *io_addr) void (*arch_iounmap)(volatile void __iomem *) = __iounmap; -void __arm_iounmap(volatile void __iomem *io_addr) +void iounmap(volatile void __iomem *cookie) { - arch_iounmap(io_addr); + arch_iounmap(cookie); } -EXPORT_SYMBOL(__arm_iounmap); +EXPORT_SYMBOL(iounmap); #ifdef CONFIG_PCI static int pci_ioremap_mem_type = MT_DEVICE; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6ca7d9aa896f..870838a46d52 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1072,6 +1072,7 @@ void __init sanity_check_meminfo(void) int highmem = 0; phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; struct memblock_region *reg; + bool should_use_highmem = false; for_each_memblock(memory, reg) { phys_addr_t block_start = reg->base; @@ -1090,6 +1091,7 @@ void __init sanity_check_meminfo(void) pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", &block_start, &block_end); memblock_remove(reg->base, reg->size); + should_use_highmem = true; continue; } @@ -1100,6 +1102,7 @@ void __init sanity_check_meminfo(void) &block_start, &block_end, &vmalloc_limit); memblock_remove(vmalloc_limit, overlap_size); block_end = vmalloc_limit; + should_use_highmem = true; } } @@ -1134,6 +1137,9 @@ void __init sanity_check_meminfo(void) } } + if (should_use_highmem) + pr_notice("Consider using a HIGHMEM enabled kernel.\n"); + high_memory = __va(arm_lowmem_limit - 1) + 1; /* @@ -1494,6 +1500,7 @@ void __init paging_init(const struct machine_desc *mdesc) build_mem_type_table(); prepare_page_table(); map_lowmem(); + memblock_set_current_limit(arm_lowmem_limit); dma_contiguous_remap(); devicemaps_init(mdesc); kmap_init(); diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index afd7e05d95f1..1dd10936d68d 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -351,30 +351,43 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, } EXPORT_SYMBOL(__arm_ioremap_pfn); -void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, - size_t size, unsigned int mtype, void *caller) +void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) { - return __arm_ioremap_pfn(pfn, offset, size, mtype); + return (void __iomem *)phys_addr; } -void __iomem *__arm_ioremap(phys_addr_t phys_addr, size_t size, - unsigned int mtype) +void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); + +void __iomem *ioremap(resource_size_t res_cookie, size_t size) { - return (void __iomem *)phys_addr; + return __arm_ioremap_caller(res_cookie, size, MT_DEVICE, + __builtin_return_address(0)); } -EXPORT_SYMBOL(__arm_ioremap); +EXPORT_SYMBOL(ioremap); -void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); +void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) +{ + return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_cache); -void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, - unsigned int mtype, void *caller) +void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) +{ + return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_WC, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_wc); + +void __iounmap(volatile void __iomem *addr) { - return __arm_ioremap(phys_addr, size, mtype); } +EXPORT_SYMBOL(__iounmap); void (*arch_iounmap)(volatile void __iomem *); -void __arm_iounmap(volatile void __iomem *addr) +void iounmap(volatile void __iomem *addr) { } -EXPORT_SYMBOL(__arm_iounmap); +EXPORT_SYMBOL(iounmap); diff --git a/arch/arm/plat-pxa/dma.c b/arch/arm/plat-pxa/dma.c index d92f07f6ecfb..de2b061889ec 100644 --- a/arch/arm/plat-pxa/dma.c +++ b/arch/arm/plat-pxa/dma.c @@ -289,7 +289,8 @@ int pxa_request_dma (char *name, pxa_dma_prio prio, /* try grabbing a DMA channel with the requested priority */ for (i = 0; i < num_dma_channels; i++) { if ((dma_channels[i].prio == prio) && - !dma_channels[i].name) { + !dma_channels[i].name && + !pxad_toggle_reserved_channel(i)) { found = 1; break; } @@ -326,13 +327,14 @@ void pxa_free_dma (int dma_ch) local_irq_save(flags); DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; dma_channels[dma_ch].name = NULL; + pxad_toggle_reserved_channel(dma_ch); local_irq_restore(flags); } EXPORT_SYMBOL(pxa_free_dma); static irqreturn_t dma_irq_handler(int irq, void *dev_id) { - int i, dint = DINT; + int i, dint = DINT, done = 0; struct dma_channel *channel; while (dint) { @@ -341,16 +343,13 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) channel = &dma_channels[i]; if (channel->name && channel->irq_handler) { channel->irq_handler(i, channel->data); - } else { - /* - * IRQ for an unregistered DMA channel: - * let's clear the interrupts and disable it. - */ - printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i); - DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + done++; } } - return IRQ_HANDLED; + if (done) + return IRQ_HANDLED; + else + return IRQ_NONE; } int __init pxa_init_dma(int irq, int num_ch) @@ -372,7 +371,8 @@ int __init pxa_init_dma(int irq, int num_ch) spin_lock_init(&dma_channels[i].lock); } - ret = request_irq(irq, dma_irq_handler, 0, "DMA", NULL); + ret = request_irq(irq, dma_irq_handler, IRQF_SHARED, "DMA", + dma_channels); if (ret) { printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); kfree(dma_channels); diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h index a7b91dc06852..28848b344e2d 100644 --- a/arch/arm/plat-pxa/include/plat/dma.h +++ b/arch/arm/plat-pxa/include/plat/dma.h @@ -82,4 +82,19 @@ int pxa_request_dma (char *name, void pxa_free_dma (int dma_ch); +/* + * Cooperation with pxa_dma + dmaengine while there remains at least one pxa + * driver not converted to dmaengine. + */ +#if defined(CONFIG_PXA_DMA) +extern int pxad_toggle_reserved_channel(int legacy_channel); +#else +static inline int pxad_toggle_reserved_channel(int legacy_channel) +{ + return 0; +} +#endif + +extern void __init pxa2xx_set_dmac_info(int nb_channels); + #endif /* __PLAT_DMA_H */ diff --git a/arch/arm/vdso/vdsomunge.c b/arch/arm/vdso/vdsomunge.c index 9005b07296c8..aedec81d1198 100644 --- a/arch/arm/vdso/vdsomunge.c +++ b/arch/arm/vdso/vdsomunge.c @@ -45,13 +45,11 @@ * it does. */ -#define _GNU_SOURCE - #include <byteswap.h> #include <elf.h> #include <errno.h> -#include <error.h> #include <fcntl.h> +#include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -82,11 +80,25 @@ #define EF_ARM_ABI_FLOAT_HARD 0x400 #endif +static int failed; +static const char *argv0; static const char *outfile; +static void fail(const char *fmt, ...) +{ + va_list ap; + + failed = 1; + fprintf(stderr, "%s: ", argv0); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + static void cleanup(void) { - if (error_message_count > 0 && outfile != NULL) + if (failed && outfile != NULL) unlink(outfile); } @@ -119,68 +131,66 @@ int main(int argc, char **argv) int infd; atexit(cleanup); + argv0 = argv[0]; if (argc != 3) - error(EXIT_FAILURE, 0, "Usage: %s [infile] [outfile]", argv[0]); + fail("Usage: %s [infile] [outfile]\n", argv[0]); infile = argv[1]; outfile = argv[2]; infd = open(infile, O_RDONLY); if (infd < 0) - error(EXIT_FAILURE, errno, "Cannot open %s", infile); + fail("Cannot open %s: %s\n", infile, strerror(errno)); if (fstat(infd, &stat) != 0) - error(EXIT_FAILURE, errno, "Failed stat for %s", infile); + fail("Failed stat for %s: %s\n", infile, strerror(errno)); inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0); if (inbuf == MAP_FAILED) - error(EXIT_FAILURE, errno, "Failed to map %s", infile); + fail("Failed to map %s: %s\n", infile, strerror(errno)); close(infd); inhdr = inbuf; if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0) - error(EXIT_FAILURE, 0, "Not an ELF file"); + fail("Not an ELF file\n"); if (inhdr->e_ident[EI_CLASS] != ELFCLASS32) - error(EXIT_FAILURE, 0, "Unsupported ELF class"); + fail("Unsupported ELF class\n"); swap = inhdr->e_ident[EI_DATA] != HOST_ORDER; if (read_elf_half(inhdr->e_type, swap) != ET_DYN) - error(EXIT_FAILURE, 0, "Not a shared object"); + fail("Not a shared object\n"); - if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) { - error(EXIT_FAILURE, 0, "Unsupported architecture %#x", - inhdr->e_machine); - } + if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) + fail("Unsupported architecture %#x\n", inhdr->e_machine); e_flags = read_elf_word(inhdr->e_flags, swap); if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) { - error(EXIT_FAILURE, 0, "Unsupported EABI version %#x", - EF_ARM_EABI_VERSION(e_flags)); + fail("Unsupported EABI version %#x\n", + EF_ARM_EABI_VERSION(e_flags)); } if (e_flags & EF_ARM_ABI_FLOAT_HARD) - error(EXIT_FAILURE, 0, - "Unexpected hard-float flag set in e_flags"); + fail("Unexpected hard-float flag set in e_flags\n"); clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT); outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (outfd < 0) - error(EXIT_FAILURE, errno, "Cannot open %s", outfile); + fail("Cannot open %s: %s\n", outfile, strerror(errno)); if (ftruncate(outfd, stat.st_size) != 0) - error(EXIT_FAILURE, errno, "Cannot truncate %s", outfile); + fail("Cannot truncate %s: %s\n", outfile, strerror(errno)); outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, outfd, 0); if (outbuf == MAP_FAILED) - error(EXIT_FAILURE, errno, "Failed to map %s", outfile); + fail("Failed to map %s: %s\n", outfile, strerror(errno)); close(outfd); @@ -195,7 +205,7 @@ int main(int argc, char **argv) } if (msync(outbuf, stat.st_size, MS_SYNC) != 0) - error(EXIT_FAILURE, errno, "Failed to sync %s", outfile); + fail("Failed to sync %s: %s\n", outfile, strerror(errno)); return EXIT_SUCCESS; } diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0f6edb14b7e4..318175f62c24 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -23,9 +23,9 @@ config ARM64 select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK - select EDAC_SUPPORT select CPU_PM if (SUSPEND || CPU_IDLE) select DCACHE_WORD_ACCESS + select EDAC_SUPPORT select GENERIC_ALLOCATOR select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST if SMP diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts index 83578e766b94..4c55833d8a41 100644 --- a/arch/arm64/boot/dts/apm/apm-mustang.dts +++ b/arch/arm64/boot/dts/apm/apm-mustang.dts @@ -23,6 +23,16 @@ device_type = "memory"; reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */ }; + + gpio-keys { + compatible = "gpio-keys"; + button@1 { + label = "POWER"; + linux,code = <116>; + linux,input-type = <0x1>; + interrupts = <0x0 0x2d 0x1>; + }; + }; }; &pcie0clk { diff --git a/arch/arm64/boot/dts/arm/Makefile b/arch/arm64/boot/dts/arm/Makefile index c5c98b91514e..bb3c07209676 100644 --- a/arch/arm64/boot/dts/arm/Makefile +++ b/arch/arm64/boot/dts/arm/Makefile @@ -1,6 +1,7 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb juno-r1.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb +dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2f-1xv7-ca53x2.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts new file mode 100644 index 000000000000..5b1d0181023b --- /dev/null +++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts @@ -0,0 +1,191 @@ +/* + * ARM Ltd. Versatile Express + * + * LogicTile Express 20MG + * V2F-1XV7 + * + * Cortex-A53 (2 cores) Soft Macrocell Model + * + * HBI-0247C + */ + +/dts-v1/; + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + model = "V2F-1XV7 Cortex-A53x2 SMM"; + arm,hbi = <0x247>; + arm,vexpress,site = <0xf>; + compatible = "arm,vexpress,v2f-1xv7,ca53x2", "arm,vexpress,v2f-1xv7", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + stdout-path = "serial0:38400n8"; + }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + i2c0 = &v2m_i2c_dvi; + i2c1 = &v2m_i2c_pcie; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0>; + next-level-cache = <&L2_0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 1>; + next-level-cache = <&L2_0>; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x80000000>; /* 2GB @ 2GB */ + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x2000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + }; + + dcc { + compatible = "arm,vexpress,config-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + smbclk: osc@4 { + /* SMC clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 4>; + freq-range = <40000000 40000000>; + #clock-cells = <0>; + clock-output-names = "smclk"; + }; + + volt@0 { + /* VIO to expansion board above */ + compatible = "arm,vexpress-volt"; + arm,vexpress-sysreg,func = <2 0>; + regulator-name = "VIO_UP"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + volt@1 { + /* 12V from power connector J6 */ + compatible = "arm,vexpress-volt"; + arm,vexpress-sysreg,func = <2 1>; + regulator-name = "12"; + regulator-always-on; + }; + + temp@0 { + /* FPGA temperature */ + compatible = "arm,vexpress-temp"; + arm,vexpress-sysreg,func = <4 0>; + label = "FPGA"; + }; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, + <0 0 1 &gic GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, + <0 0 2 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, + <0 0 3 &gic GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, + <0 0 4 &gic GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, + <0 0 5 &gic GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, + <0 0 6 &gic GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <0 0 7 &gic GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, + <0 0 8 &gic GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <0 0 9 &gic GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <0 0 10 &gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <0 0 11 &gic GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <0 0 12 &gic GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <0 0 13 &gic GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, + <0 0 14 &gic GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, + <0 0 15 &gic GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>, + <0 0 16 &gic GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>, + <0 0 17 &gic GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>, + <0 0 18 &gic GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>, + <0 0 19 &gic GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, + <0 0 20 &gic GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>, + <0 0 21 &gic GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>, + <0 0 22 &gic GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>, + <0 0 23 &gic GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>, + <0 0 24 &gic GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>, + <0 0 25 &gic GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>, + <0 0 26 &gic GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, + <0 0 27 &gic GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>, + <0 0 28 &gic GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>, + <0 0 29 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>, + <0 0 30 &gic GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>, + <0 0 31 &gic GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>, + <0 0 32 &gic GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>, + <0 0 33 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>, + <0 0 34 &gic GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>, + <0 0 35 &gic GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>, + <0 0 36 &gic GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>, + <0 0 37 &gic GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, + <0 0 38 &gic GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>, + <0 0 39 &gic GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, + <0 0 40 &gic GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, + <0 0 41 &gic GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>, + <0 0 42 &gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + + /include/ "../../../../arm/boot/dts/vexpress-v2m-rs1.dtsi" + }; +}; diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi index d8c0bdc51882..9cb7cf94284a 100644 --- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi +++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi @@ -376,10 +376,19 @@ gic0: interrupt-controller@8010,00000000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; interrupt-controller; reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */ <0x8010 0x80000000 0x0 0x600000>; /* GICR */ interrupts = <1 9 0xf04>; + + its: gic-its@8010,00020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x8010 0x20000 0x0 0x200000>; + }; }; uaa0: serial@87e0,24000000 { diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f38c94f1d898..4e17e7ede33d 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -83,6 +83,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_CEVA=y CONFIG_AHCI_XGENE=y CONFIG_PATA_PLATFORM=y CONFIG_PATA_OF_PLATFORM=y diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 39248d3adf5d..406485ed110a 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -19,6 +19,14 @@ #include <asm/psci.h> #include <asm/smp_plat.h> +/* Macros for consistency checks of the GICC subtable of MADT */ +#define ACPI_MADT_GICC_LENGTH \ + (acpi_gbl_FADT.header.revision < 6 ? 76 : 80) + +#define BAD_MADT_GICC_ENTRY(entry, end) \ + (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \ + (entry)->header.length != ACPI_MADT_GICC_LENGTH) + /* Basic configuration for ACPI */ #ifdef CONFIG_ACPI /* ACPI table mapping after acpi_gbl_permanent_mmap is set */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a7691a378668..f860bfda454a 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -352,8 +352,8 @@ el1_inv: // TODO: add support for undefined instructions in kernel mode enable_dbg mov x0, sp + mov x2, x1 mov x1, #BAD_SYNC - mrs x2, esr_el1 b bad_mode ENDPROC(el1_sync) @@ -553,7 +553,7 @@ el0_inv: ct_user_exit mov x0, sp mov x1, #BAD_SYNC - mrs x2, esr_el1 + mov x2, x25 bl bad_mode b ret_to_user ENDPROC(el0_sync) diff --git a/arch/arm64/kernel/entry32.S b/arch/arm64/kernel/entry32.S index bd9bfaa9269b..f332d5d1f6b4 100644 --- a/arch/arm64/kernel/entry32.S +++ b/arch/arm64/kernel/entry32.S @@ -32,13 +32,11 @@ ENTRY(compat_sys_sigreturn_wrapper) mov x0, sp - mov x27, #0 // prevent syscall restart handling (why) b compat_sys_sigreturn ENDPROC(compat_sys_sigreturn_wrapper) ENTRY(compat_sys_rt_sigreturn_wrapper) mov x0, sp - mov x27, #0 // prevent syscall restart handling (why) b compat_sys_rt_sigreturn ENDPROC(compat_sys_rt_sigreturn_wrapper) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 695801a54ca5..50fb4696654e 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -438,7 +438,7 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, struct acpi_madt_generic_interrupt *processor; processor = (struct acpi_madt_generic_interrupt *)header; - if (BAD_MADT_ENTRY(processor, end)) + if (BAD_MADT_GICC_ENTRY(processor, end)) return -EINVAL; acpi_table_print_madt_entry(header); diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 9d84feb41a16..773d37a14039 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -4,5 +4,3 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ context.o proc.o pageattr.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_ARM64_PTDUMP) += dump.o - -CFLAGS_mmu.o := -I$(srctree)/scripts/dtc/libfdt/ diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index 4dda9bd6b8fb..e989cee77414 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c @@ -1464,7 +1464,7 @@ static inline void handle_rx_packet(struct sync_port *port) if (port->write_ts_idx == NBR_IN_DESCR) port->write_ts_idx = 0; idx = port->write_ts_idx++; - do_posix_clock_monotonic_gettime(&port->timestamp[idx]); + ktime_get_ts(&port->timestamp[idx]); port->in_buffer_len += port->inbufchunk; } spin_unlock_irqrestore(&port->lock, flags); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2a14585c90d2..aab7e46cadd5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2231,7 +2231,7 @@ config MIPS_CMP config MIPS_CPS bool "MIPS Coherent Processing System support" - depends on SYS_SUPPORTS_MIPS_CPS && !64BIT + depends on SYS_SUPPORTS_MIPS_CPS select MIPS_CM select MIPS_CPC select MIPS_CPS_PM if HOTPLUG_CPU diff --git a/arch/mips/include/asm/mach-loongson64/mmzone.h b/arch/mips/include/asm/mach-loongson64/mmzone.h index 37c08a27b4f0..c9f7e231e66b 100644 --- a/arch/mips/include/asm/mach-loongson64/mmzone.h +++ b/arch/mips/include/asm/mach-loongson64/mmzone.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & - * Insititute of Computing Technology + * Institute of Computing Technology * Author: Xiang Gao, gaoxiang@ict.ac.cn * Huacai Chen, chenhc@lemote.com * Xiaofu Meng, Shuangshuang Zhang diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 2b25d1ba1ea0..16f1ea9ab191 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -23,6 +23,7 @@ extern int smp_num_siblings; extern cpumask_t cpu_sibling_map[]; extern cpumask_t cpu_core_map[]; +extern cpumask_t cpu_foreign_map; #define raw_smp_processor_id() (current_thread_info()->cpu) diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index c0c5e5972256..d8f9b357b222 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -600,7 +600,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, break; case blezl_op: /* not really i_format */ - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) goto sigill_r6; case blez_op: /* @@ -635,7 +635,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, break; case bgtzl_op: - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) goto sigill_r6; case bgtz_op: /* diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 55b759a0019e..1b6ca634e646 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -60,7 +60,7 @@ LEAF(mips_cps_core_entry) nop /* This is an NMI */ - la k0, nmi_handler + PTR_LA k0, nmi_handler jr k0 nop @@ -107,10 +107,10 @@ not_nmi: mul t1, t1, t0 mul t1, t1, t2 - li a0, KSEG0 - add a1, a0, t1 + li a0, CKSEG0 + PTR_ADD a1, a0, t1 1: cache Index_Store_Tag_I, 0(a0) - add a0, a0, t0 + PTR_ADD a0, a0, t0 bne a0, a1, 1b nop icache_done: @@ -134,12 +134,12 @@ icache_done: mul t1, t1, t0 mul t1, t1, t2 - li a0, KSEG0 - addu a1, a0, t1 - subu a1, a1, t0 + li a0, CKSEG0 + PTR_ADDU a1, a0, t1 + PTR_SUBU a1, a1, t0 1: cache Index_Store_Tag_D, 0(a0) bne a0, a1, 1b - add a0, a0, t0 + PTR_ADD a0, a0, t0 dcache_done: /* Set Kseg0 CCA to that in s0 */ @@ -152,11 +152,11 @@ dcache_done: /* Enter the coherent domain */ li t0, 0xff - sw t0, GCR_CL_COHERENCE_OFS(v1) + PTR_S t0, GCR_CL_COHERENCE_OFS(v1) ehb /* Jump to kseg0 */ - la t0, 1f + PTR_LA t0, 1f jr t0 nop @@ -178,9 +178,9 @@ dcache_done: nop /* Off we go! */ - lw t1, VPEBOOTCFG_PC(v0) - lw gp, VPEBOOTCFG_GP(v0) - lw sp, VPEBOOTCFG_SP(v0) + PTR_L t1, VPEBOOTCFG_PC(v0) + PTR_L gp, VPEBOOTCFG_GP(v0) + PTR_L sp, VPEBOOTCFG_SP(v0) jr t1 nop END(mips_cps_core_entry) @@ -217,7 +217,7 @@ LEAF(excep_intex) .org 0x480 LEAF(excep_ejtag) - la k0, ejtag_debug_handler + PTR_LA k0, ejtag_debug_handler jr k0 nop END(excep_ejtag) @@ -229,7 +229,7 @@ LEAF(mips_cps_core_init) nop .set push - .set mips32r2 + .set mips64r2 .set mt /* Only allow 1 TC per VPE to execute... */ @@ -237,7 +237,7 @@ LEAF(mips_cps_core_init) /* ...and for the moment only 1 VPE */ dvpe - la t1, 1f + PTR_LA t1, 1f jr.hb t1 nop @@ -250,25 +250,25 @@ LEAF(mips_cps_core_init) mfc0 t0, CP0_MVPCONF0 srl t0, t0, MVPCONF0_PVPE_SHIFT andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT) - addiu t7, t0, 1 + addiu ta3, t0, 1 /* If there's only 1, we're done */ beqz t0, 2f nop /* Loop through each VPE within this core */ - li t5, 1 + li ta1, 1 1: /* Operate on the appropriate TC */ - mtc0 t5, CP0_VPECONTROL + mtc0 ta1, CP0_VPECONTROL ehb /* Bind TC to VPE (1:1 TC:VPE mapping) */ - mttc0 t5, CP0_TCBIND + mttc0 ta1, CP0_TCBIND /* Set exclusive TC, non-active, master */ li t0, VPECONF0_MVP - sll t1, t5, VPECONF0_XTC_SHIFT + sll t1, ta1, VPECONF0_XTC_SHIFT or t0, t0, t1 mttc0 t0, CP0_VPECONF0 @@ -280,8 +280,8 @@ LEAF(mips_cps_core_init) mttc0 t0, CP0_TCHALT /* Next VPE */ - addiu t5, t5, 1 - slt t0, t5, t7 + addiu ta1, ta1, 1 + slt t0, ta1, ta3 bnez t0, 1b nop @@ -298,19 +298,19 @@ LEAF(mips_cps_core_init) LEAF(mips_cps_boot_vpes) /* Retrieve CM base address */ - la t0, mips_cm_base - lw t0, 0(t0) + PTR_LA t0, mips_cm_base + PTR_L t0, 0(t0) /* Calculate a pointer to this cores struct core_boot_config */ - lw t0, GCR_CL_ID_OFS(t0) + PTR_L t0, GCR_CL_ID_OFS(t0) li t1, COREBOOTCFG_SIZE mul t0, t0, t1 - la t1, mips_cps_core_bootcfg - lw t1, 0(t1) - addu t0, t0, t1 + PTR_LA t1, mips_cps_core_bootcfg + PTR_L t1, 0(t1) + PTR_ADDU t0, t0, t1 /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ - has_mt t6, 1f + has_mt ta2, 1f li t9, 0 /* Find the number of VPEs present in the core */ @@ -334,24 +334,24 @@ LEAF(mips_cps_boot_vpes) 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ li t1, VPEBOOTCFG_SIZE mul v0, t9, t1 - lw t7, COREBOOTCFG_VPECONFIG(t0) - addu v0, v0, t7 + PTR_L ta3, COREBOOTCFG_VPECONFIG(t0) + PTR_ADDU v0, v0, ta3 #ifdef CONFIG_MIPS_MT /* If the core doesn't support MT then return */ - bnez t6, 1f + bnez ta2, 1f nop jr ra nop .set push - .set mips32r2 + .set mips64r2 .set mt 1: /* Enter VPE configuration state */ dvpe - la t1, 1f + PTR_LA t1, 1f jr.hb t1 nop 1: mfc0 t1, CP0_MVPCONTROL @@ -360,12 +360,12 @@ LEAF(mips_cps_boot_vpes) ehb /* Loop through each VPE */ - lw t6, COREBOOTCFG_VPEMASK(t0) - move t8, t6 - li t5, 0 + PTR_L ta2, COREBOOTCFG_VPEMASK(t0) + move t8, ta2 + li ta1, 0 /* Check whether the VPE should be running. If not, skip it */ -1: andi t0, t6, 1 +1: andi t0, ta2, 1 beqz t0, 2f nop @@ -373,7 +373,7 @@ LEAF(mips_cps_boot_vpes) mfc0 t0, CP0_VPECONTROL ori t0, t0, VPECONTROL_TARGTC xori t0, t0, VPECONTROL_TARGTC - or t0, t0, t5 + or t0, t0, ta1 mtc0 t0, CP0_VPECONTROL ehb @@ -384,8 +384,8 @@ LEAF(mips_cps_boot_vpes) /* Calculate a pointer to the VPEs struct vpe_boot_config */ li t0, VPEBOOTCFG_SIZE - mul t0, t0, t5 - addu t0, t0, t7 + mul t0, t0, ta1 + addu t0, t0, ta3 /* Set the TC restart PC */ lw t1, VPEBOOTCFG_PC(t0) @@ -423,9 +423,9 @@ LEAF(mips_cps_boot_vpes) mttc0 t0, CP0_VPECONF0 /* Next VPE */ -2: srl t6, t6, 1 - addiu t5, t5, 1 - bnez t6, 1b +2: srl ta2, ta2, 1 + addiu ta1, ta1, 1 + bnez ta2, 1b nop /* Leave VPE configuration state */ @@ -445,7 +445,7 @@ LEAF(mips_cps_boot_vpes) /* This VPE should be offline, halt the TC */ li t0, TCHALT_H mtc0 t0, CP0_TCHALT - la t0, 1f + PTR_LA t0, 1f 1: jr.hb t0 nop @@ -466,10 +466,10 @@ LEAF(mips_cps_boot_vpes) .set noat lw $1, TI_CPU(gp) sll $1, $1, LONGLOG - la \dest, __per_cpu_offset + PTR_LA \dest, __per_cpu_offset addu $1, $1, \dest lw $1, 0($1) - la \dest, cps_cpu_state + PTR_LA \dest, cps_cpu_state addu \dest, \dest, $1 .set pop .endm diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 6e8de80bb446..4cc13508d967 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -73,10 +73,11 @@ NESTED(handle_sys, PT_SIZE, sp) .set noreorder .set nomacro -1: user_lw(t5, 16(t0)) # argument #5 from usp -4: user_lw(t6, 20(t0)) # argument #6 from usp -3: user_lw(t7, 24(t0)) # argument #7 from usp -2: user_lw(t8, 28(t0)) # argument #8 from usp +load_a4: user_lw(t5, 16(t0)) # argument #5 from usp +load_a5: user_lw(t6, 20(t0)) # argument #6 from usp +load_a6: user_lw(t7, 24(t0)) # argument #7 from usp +load_a7: user_lw(t8, 28(t0)) # argument #8 from usp +loads_done: sw t5, 16(sp) # argument #5 to ksp sw t6, 20(sp) # argument #6 to ksp @@ -85,10 +86,10 @@ NESTED(handle_sys, PT_SIZE, sp) .set pop .section __ex_table,"a" - PTR 1b,bad_stack - PTR 2b,bad_stack - PTR 3b,bad_stack - PTR 4b,bad_stack + PTR load_a4, bad_stack_a4 + PTR load_a5, bad_stack_a5 + PTR load_a6, bad_stack_a6 + PTR load_a7, bad_stack_a7 .previous lw t0, TI_FLAGS($28) # syscall tracing enabled? @@ -153,8 +154,8 @@ syscall_trace_entry: /* ------------------------------------------------------------------------ */ /* - * The stackpointer for a call with more than 4 arguments is bad. - * We probably should handle this case a bit more drastic. + * Our open-coded access area sanity test for the stack pointer + * failed. We probably should handle this case a bit more drastic. */ bad_stack: li v0, EFAULT @@ -163,6 +164,22 @@ bad_stack: sw t0, PT_R7(sp) j o32_syscall_exit +bad_stack_a4: + li t5, 0 + b load_a5 + +bad_stack_a5: + li t6, 0 + b load_a6 + +bad_stack_a6: + li t7, 0 + b load_a7 + +bad_stack_a7: + li t8, 0 + b loads_done + /* * The system call does not exist in this kernel */ diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d07b210fbeff..f543ff4feef9 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -69,16 +69,17 @@ NESTED(handle_sys, PT_SIZE, sp) daddu t1, t0, 32 bltz t1, bad_stack -1: lw a4, 16(t0) # argument #5 from usp -2: lw a5, 20(t0) # argument #6 from usp -3: lw a6, 24(t0) # argument #7 from usp -4: lw a7, 28(t0) # argument #8 from usp (for indirect syscalls) +load_a4: lw a4, 16(t0) # argument #5 from usp +load_a5: lw a5, 20(t0) # argument #6 from usp +load_a6: lw a6, 24(t0) # argument #7 from usp +load_a7: lw a7, 28(t0) # argument #8 from usp +loads_done: .section __ex_table,"a" - PTR 1b, bad_stack - PTR 2b, bad_stack - PTR 3b, bad_stack - PTR 4b, bad_stack + PTR load_a4, bad_stack_a4 + PTR load_a5, bad_stack_a5 + PTR load_a6, bad_stack_a6 + PTR load_a7, bad_stack_a7 .previous li t1, _TIF_WORK_SYSCALL_ENTRY @@ -167,6 +168,22 @@ bad_stack: sd t0, PT_R7(sp) j o32_syscall_exit +bad_stack_a4: + li a4, 0 + b load_a5 + +bad_stack_a5: + li a5, 0 + b load_a6 + +bad_stack_a6: + li a6, 0 + b load_a7 + +bad_stack_a7: + li a7, 0 + b loads_done + not_o32_scall: /* * This is not an o32 compatibility syscall, pass it on @@ -383,7 +400,7 @@ EXPORT(sys32_call_table) PTR sys_connect /* 4170 */ PTR sys_getpeername PTR sys_getsockname - PTR sys_getsockopt + PTR compat_sys_getsockopt PTR sys_listen PTR compat_sys_recv /* 4175 */ PTR compat_sys_recvfrom diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index be73c491182b..008b3378653a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -337,6 +337,11 @@ static void __init bootmem_init(void) min_low_pfn = start; if (end <= reserved_end) continue; +#ifdef CONFIG_BLK_DEV_INITRD + /* mapstart should be after initrd_end */ + if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end))) + continue; +#endif if (start >= mapstart) continue; mapstart = max(reserved_end, start); @@ -366,14 +371,6 @@ static void __init bootmem_init(void) max_low_pfn = PFN_DOWN(HIGHMEM_START); } -#ifdef CONFIG_BLK_DEV_INITRD - /* - * mapstart should be after initrd_end - */ - if (initrd_end) - mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end))); -#endif - /* * Initialize the boot-time allocator with low memory only. */ diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 4251d390b5b6..c88937745b4e 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -133,7 +133,7 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) /* * Patch the start of mips_cps_core_entry to provide: * - * v0 = CM base address + * v1 = CM base address * s0 = kseg0 CCA */ entry_code = (u32 *)&mips_cps_core_entry; @@ -369,7 +369,7 @@ void play_dead(void) static void wait_for_sibling_halt(void *ptr_cpu) { - unsigned cpu = (unsigned)ptr_cpu; + unsigned cpu = (unsigned long)ptr_cpu; unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); unsigned halted; unsigned long flags; @@ -430,7 +430,7 @@ static void cps_cpu_die(unsigned int cpu) */ err = smp_call_function_single(cpu_death_sibling, wait_for_sibling_halt, - (void *)cpu, 1); + (void *)(unsigned long)cpu, 1); if (err) panic("Failed to call remote sibling CPU\n"); } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index faa46ebd9dda..d0744cc77ea7 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -63,6 +63,13 @@ EXPORT_SYMBOL(cpu_sibling_map); cpumask_t cpu_core_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_core_map); +/* + * A logcal cpu mask containing only one VPE per core to + * reduce the number of IPIs on large MT systems. + */ +cpumask_t cpu_foreign_map __read_mostly; +EXPORT_SYMBOL(cpu_foreign_map); + /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; @@ -103,6 +110,29 @@ static inline void set_cpu_core_map(int cpu) } } +/* + * Calculate a new cpu_foreign_map mask whenever a + * new cpu appears or disappears. + */ +static inline void calculate_cpu_foreign_map(void) +{ + int i, k, core_present; + cpumask_t temp_foreign_map; + + /* Re-calculate the mask */ + for_each_online_cpu(i) { + core_present = 0; + for_each_cpu(k, &temp_foreign_map) + if (cpu_data[i].package == cpu_data[k].package && + cpu_data[i].core == cpu_data[k].core) + core_present = 1; + if (!core_present) + cpumask_set_cpu(i, &temp_foreign_map); + } + + cpumask_copy(&cpu_foreign_map, &temp_foreign_map); +} + struct plat_smp_ops *mp_ops; EXPORT_SYMBOL(mp_ops); @@ -146,6 +176,8 @@ asmlinkage void start_secondary(void) set_cpu_sibling_map(cpu); set_cpu_core_map(cpu); + calculate_cpu_foreign_map(); + cpumask_set_cpu(cpu, &cpu_callin_map); synchronise_count_slave(cpu); @@ -173,9 +205,18 @@ void __irq_entry smp_call_function_interrupt(void) static void stop_this_cpu(void *dummy) { /* - * Remove this CPU: + * Remove this CPU. Be a bit slow here and + * set the bits for every online CPU so we don't miss + * any IPI whilst taking this VPE down. */ + + cpumask_copy(&cpu_foreign_map, cpu_online_mask); + + /* Make it visible to every other CPU */ + smp_mb(); + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); local_irq_disable(); while (1); } @@ -197,6 +238,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) mp_ops->prepare_cpus(max_cpus); set_cpu_sibling_map(0); set_cpu_core_map(0); + calculate_cpu_foreign_map(); #ifndef CONFIG_HOTPLUG_CPU init_cpu_present(cpu_possible_mask); #endif diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 2a7b38ed23f0..e207a43b5f8f 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2130,10 +2130,10 @@ void per_cpu_trap_init(bool is_boot_cpu) BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); - /* Boot CPU's cache setup in setup_arch(). */ - if (!is_boot_cpu) - cpu_cache_init(); - tlb_init(); + /* Boot CPU's cache setup in setup_arch(). */ + if (!is_boot_cpu) + cpu_cache_init(); + tlb_init(); TLBMISS_HANDLER_SETUP(); } diff --git a/arch/mips/loongson64/common/bonito-irq.c b/arch/mips/loongson64/common/bonito-irq.c index cc0e4fd548e6..4e116d23bab3 100644 --- a/arch/mips/loongson64/common/bonito-irq.c +++ b/arch/mips/loongson64/common/bonito-irq.c @@ -3,7 +3,7 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c index 72fed003a536..01fbed137028 100644 --- a/arch/mips/loongson64/common/cmdline.c +++ b/arch/mips/loongson64/common/cmdline.c @@ -6,7 +6,7 @@ * Copyright 2003 ICT CAS * Author: Michael Guo <guoyi@ict.ac.cn> * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * Copyright (C) 2009 Lemote Inc. diff --git a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index 12c75db23420..875037063a80 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c @@ -1,7 +1,7 @@ /* * CS5536 General timer functions * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Yanhua, yanh@lemote.com * * Copyright (C) 2009 Lemote Inc. diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c index 22f04ca2ff3e..f6c44dd332e2 100644 --- a/arch/mips/loongson64/common/env.c +++ b/arch/mips/loongson64/common/env.c @@ -6,7 +6,7 @@ * Copyright 2003 ICT CAS * Author: Michael Guo <guoyi@ict.ac.cn> * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * Copyright (C) 2009 Lemote Inc. diff --git a/arch/mips/loongson64/common/irq.c b/arch/mips/loongson64/common/irq.c index 687003b19b45..d36d969a4a87 100644 --- a/arch/mips/loongson64/common/irq.c +++ b/arch/mips/loongson64/common/irq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/common/setup.c b/arch/mips/loongson64/common/setup.c index d477dd6bb326..2dc5122f0e09 100644 --- a/arch/mips/loongson64/common/setup.c +++ b/arch/mips/loongson64/common/setup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/fuloong-2e/irq.c b/arch/mips/loongson64/fuloong-2e/irq.c index ef5ec8f3de5f..892963f860b7 100644 --- a/arch/mips/loongson64/fuloong-2e/irq.c +++ b/arch/mips/loongson64/fuloong-2e/irq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/lemote-2f/clock.c b/arch/mips/loongson64/lemote-2f/clock.c index 462e34d46b4a..a78fb657068c 100644 --- a/arch/mips/loongson64/lemote-2f/clock.c +++ b/arch/mips/loongson64/lemote-2f/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology * Author: Yanhua, yanh@lemote.com * * This file is subject to the terms and conditions of the GNU General Public @@ -15,7 +15,7 @@ #include <linux/spinlock.h> #include <asm/clock.h> -#include <asm/mach-loongson/loongson.h> +#include <asm/mach-loongson64/loongson.h> static LIST_HEAD(clock_list); static DEFINE_SPINLOCK(clock_lock); diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c index 12d14ed48778..6f9e010cec4d 100644 --- a/arch/mips/loongson64/loongson-3/numa.c +++ b/arch/mips/loongson64/loongson-3/numa.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & - * Insititute of Computing Technology + * Institute of Computing Technology * Author: Xiang Gao, gaoxiang@ict.ac.cn * Huacai Chen, chenhc@lemote.com * Xiaofu Meng, Shuangshuang Zhang diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 22b9b2cb9219..712f17a2ecf2 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -451,7 +451,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, /* Fall through */ case jr_op: /* For R6, JR already emulated in jalr_op */ - if (NO_R6EMU && insn.r_format.opcode == jr_op) + if (NO_R6EMU && insn.r_format.func == jr_op) break; *contpc = regs->regs[insn.r_format.rs]; return 1; @@ -551,7 +551,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; return 1; case blezl_op: - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) break; case blez_op: @@ -588,7 +588,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; return 1; case bgtzl_op: - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) break; case bgtz_op: /* diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 7f660dc67596..fbea4432f3f2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -37,6 +37,7 @@ #include <asm/cacheflush.h> /* for run_uncached() */ #include <asm/traps.h> #include <asm/dma-coherence.h> +#include <asm/mips-cm.h> /* * Special Variant of smp_call_function for use by cache functions: @@ -51,9 +52,16 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info) { preempt_disable(); -#ifndef CONFIG_MIPS_MT_SMP - smp_call_function(func, info, 1); -#endif + /* + * The Coherent Manager propagates address-based cache ops to other + * cores but not index-based ops. However, r4k_on_each_cpu is used + * in both cases so there is no easy way to tell what kind of op is + * executed to the other cores. The best we can probably do is + * to restrict that call when a CM is not present because both + * CM-based SMP protocols (CMP & CPS) restrict index-based cache ops. + */ + if (!mips_cm_present()) + smp_call_function_many(&cpu_foreign_map, func, info, 1); func(info); preempt_enable(); } @@ -937,7 +945,9 @@ static void b5k_instruction_hazard(void) } static char *way_string[] = { NULL, "direct mapped", "2-way", - "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" + "3-way", "4-way", "5-way", "6-way", "7-way", "8-way", + "9-way", "10-way", "11-way", "12-way", + "13-way", "14-way", "15-way", "16-way", }; static void probe_pcache(void) diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 185e68261f45..5625b190edc0 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -119,18 +119,24 @@ void read_persistent_clock(struct timespec *ts) int get_c0_fdc_int(void) { - int mips_cpu_fdc_irq; + /* + * Some cores claim the FDC is routable through the GIC, but it doesn't + * actually seem to be connected for those Malta bitstreams. + */ + switch (current_cpu_type()) { + case CPU_INTERAPTIV: + case CPU_PROAPTIV: + return -1; + }; if (cpu_has_veic) - mips_cpu_fdc_irq = -1; + return -1; else if (gic_present) - mips_cpu_fdc_irq = gic_get_c0_fdc_int(); + return gic_get_c0_fdc_int(); else if (cp0_fdc_irq >= 0) - mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq; + return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; else - mips_cpu_fdc_irq = -1; - - return mips_cpu_fdc_irq; + return -1; } int get_c0_perfcount_int(void) diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c index d2dc836523a3..8bd8ebb20a72 100644 --- a/arch/mips/pistachio/init.c +++ b/arch/mips/pistachio/init.c @@ -63,13 +63,19 @@ void __init plat_mem_setup(void) plat_setup_iocoherency(); } -#define DEFAULT_CPC_BASE_ADDR 0x1bde0000 +#define DEFAULT_CPC_BASE_ADDR 0x1bde0000 +#define DEFAULT_CDMM_BASE_ADDR 0x1bdd0000 phys_addr_t mips_cpc_default_phys_base(void) { return DEFAULT_CPC_BASE_ADDR; } +phys_addr_t mips_cdmm_phys_base(void) +{ + return DEFAULT_CDMM_BASE_ADDR; +} + static void __init mips_nmi_setup(void) { void *base; diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c index 67889fcea8aa..7c73fcb92a10 100644 --- a/arch/mips/pistachio/time.c +++ b/arch/mips/pistachio/time.c @@ -27,6 +27,11 @@ int get_c0_perfcount_int(void) return gic_get_c0_perfcount_int(); } +int get_c0_fdc_int(void) +{ + return gic_get_c0_fdc_int(); +} + void __init plat_time_init(void) { struct device_node *np; diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 0a183756d6ec..f93c4a4e6580 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -16,7 +16,7 @@ #include <asm/processor.h> #include <asm/cache.h> -extern spinlock_t pa_dbit_lock; +extern spinlock_t pa_tlb_lock; /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel @@ -33,6 +33,19 @@ extern spinlock_t pa_dbit_lock; */ #define kern_addr_valid(addr) (1) +/* Purge data and instruction TLB entries. Must be called holding + * the pa_tlb_lock. The TLB purge instructions are slow on SMP + * machines since the purge must be broadcast to all CPUs. + */ + +static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) +{ + mtsp(mm->context, 1); + pdtlb(addr); + if (unlikely(split_tlb)) + pitlb(addr); +} + /* Certain architectures need to do special things when PTEs * within a page table are directly modified. Thus, the following * hook is made available. @@ -42,15 +55,20 @@ extern spinlock_t pa_dbit_lock; *(pteptr) = (pteval); \ } while(0) -extern void purge_tlb_entries(struct mm_struct *, unsigned long); +#define pte_inserted(x) \ + ((pte_val(x) & (_PAGE_PRESENT|_PAGE_ACCESSED)) \ + == (_PAGE_PRESENT|_PAGE_ACCESSED)) -#define set_pte_at(mm, addr, ptep, pteval) \ - do { \ +#define set_pte_at(mm, addr, ptep, pteval) \ + do { \ + pte_t old_pte; \ unsigned long flags; \ - spin_lock_irqsave(&pa_dbit_lock, flags); \ - set_pte(ptep, pteval); \ - purge_tlb_entries(mm, addr); \ - spin_unlock_irqrestore(&pa_dbit_lock, flags); \ + spin_lock_irqsave(&pa_tlb_lock, flags); \ + old_pte = *ptep; \ + set_pte(ptep, pteval); \ + if (pte_inserted(old_pte)) \ + purge_tlb_entries(mm, addr); \ + spin_unlock_irqrestore(&pa_tlb_lock, flags); \ } while (0) #endif /* !__ASSEMBLY__ */ @@ -268,7 +286,7 @@ extern unsigned long *empty_zero_page; #define pte_none(x) (pte_val(x) == 0) #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) -#define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) +#define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0)) #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) @@ -435,15 +453,15 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned if (!pte_young(*ptep)) return 0; - spin_lock_irqsave(&pa_dbit_lock, flags); + spin_lock_irqsave(&pa_tlb_lock, flags); pte = *ptep; if (!pte_young(pte)) { - spin_unlock_irqrestore(&pa_dbit_lock, flags); + spin_unlock_irqrestore(&pa_tlb_lock, flags); return 0; } set_pte(ptep, pte_mkold(pte)); purge_tlb_entries(vma->vm_mm, addr); - spin_unlock_irqrestore(&pa_dbit_lock, flags); + spin_unlock_irqrestore(&pa_tlb_lock, flags); return 1; } @@ -453,11 +471,12 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t old_pte; unsigned long flags; - spin_lock_irqsave(&pa_dbit_lock, flags); + spin_lock_irqsave(&pa_tlb_lock, flags); old_pte = *ptep; - pte_clear(mm,addr,ptep); - purge_tlb_entries(mm, addr); - spin_unlock_irqrestore(&pa_dbit_lock, flags); + set_pte(ptep, __pte(0)); + if (pte_inserted(old_pte)) + purge_tlb_entries(mm, addr); + spin_unlock_irqrestore(&pa_tlb_lock, flags); return old_pte; } @@ -465,10 +484,10 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { unsigned long flags; - spin_lock_irqsave(&pa_dbit_lock, flags); + spin_lock_irqsave(&pa_tlb_lock, flags); set_pte(ptep, pte_wrprotect(*ptep)); purge_tlb_entries(mm, addr); - spin_unlock_irqrestore(&pa_dbit_lock, flags); + spin_unlock_irqrestore(&pa_tlb_lock, flags); } #define pte_same(A,B) (pte_val(A) == pte_val(B)) diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 9d086a599fa0..e84b96478193 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h @@ -13,6 +13,9 @@ * active at any one time on the Merced bus. This tlb purge * synchronisation is fairly lightweight and harmless so we activate * it on all systems not just the N class. + + * It is also used to ensure PTE updates are atomic and consistent + * with the TLB. */ extern spinlock_t pa_tlb_lock; @@ -24,20 +27,24 @@ extern void flush_tlb_all_local(void *); #define smp_flush_tlb_all() flush_tlb_all() +int __flush_tlb_range(unsigned long sid, + unsigned long start, unsigned long end); + +#define flush_tlb_range(vma, start, end) \ + __flush_tlb_range((vma)->vm_mm->context, start, end) + +#define flush_tlb_kernel_range(start, end) \ + __flush_tlb_range(0, start, end) + /* * flush_tlb_mm() * - * XXX This code is NOT valid for HP-UX compatibility processes, - * (although it will probably work 99% of the time). HP-UX - * processes are free to play with the space id's and save them - * over long periods of time, etc. so we have to preserve the - * space and just flush the entire tlb. We need to check the - * personality in order to do that, but the personality is not - * currently being set correctly. - * - * Of course, Linux processes could do the same thing, but - * we don't support that (and the compilers, dynamic linker, - * etc. do not do that). + * The code to switch to a new context is NOT valid for processes + * which play with the space id's. Thus, we have to preserve the + * space and just flush the entire tlb. However, the compilers, + * dynamic linker, etc, do not manipulate space id's, so there + * could be a significant performance benefit in switching contexts + * and not flushing the whole tlb. */ static inline void flush_tlb_mm(struct mm_struct *mm) @@ -45,10 +52,18 @@ static inline void flush_tlb_mm(struct mm_struct *mm) BUG_ON(mm == &init_mm); /* Should never happen */ #if 1 || defined(CONFIG_SMP) + /* Except for very small threads, flushing the whole TLB is + * faster than using __flush_tlb_range. The pdtlb and pitlb + * instructions are very slow because of the TLB broadcast. + * It might be faster to do local range flushes on all CPUs + * on PA 2.0 systems. + */ flush_tlb_all(); #else /* FIXME: currently broken, causing space id and protection ids - * to go out of sync, resulting in faults on userspace accesses. + * to go out of sync, resulting in faults on userspace accesses. + * This approach needs further investigation since running many + * small applications (e.g., GCC testsuite) is faster on HP-UX. */ if (mm) { if (mm->context != 0) @@ -65,22 +80,12 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, { unsigned long flags, sid; - /* For one page, it's not worth testing the split_tlb variable */ - - mb(); sid = vma->vm_mm->context; purge_tlb_start(flags); mtsp(sid, 1); pdtlb(addr); - pitlb(addr); + if (unlikely(split_tlb)) + pitlb(addr); purge_tlb_end(flags); } - -void __flush_tlb_range(unsigned long sid, - unsigned long start, unsigned long end); - -#define flush_tlb_range(vma,start,end) __flush_tlb_range((vma)->vm_mm->context,start,end) - -#define flush_tlb_kernel_range(start, end) __flush_tlb_range(0,start,end) - #endif diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index f6448c7c62b5..cda6dbbe9842 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -342,12 +342,15 @@ EXPORT_SYMBOL(flush_data_cache_local); EXPORT_SYMBOL(flush_kernel_icache_range_asm); #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ -int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; +static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; + +#define FLUSH_TLB_THRESHOLD (2*1024*1024) /* 2MB initial TLB threshold */ +static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD; void __init parisc_setup_cache_timing(void) { unsigned long rangetime, alltime; - unsigned long size; + unsigned long size, start; alltime = mfctl(16); flush_data_cache(); @@ -364,14 +367,43 @@ void __init parisc_setup_cache_timing(void) /* Racy, but if we see an intermediate value, it's ok too... */ parisc_cache_flush_threshold = size * alltime / rangetime; - parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); + parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold); if (!parisc_cache_flush_threshold) parisc_cache_flush_threshold = FLUSH_THRESHOLD; if (parisc_cache_flush_threshold > cache_info.dc_size) parisc_cache_flush_threshold = cache_info.dc_size; - printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); + printk(KERN_INFO "Setting cache flush threshold to %lu kB\n", + parisc_cache_flush_threshold/1024); + + /* calculate TLB flush threshold */ + + alltime = mfctl(16); + flush_tlb_all(); + alltime = mfctl(16) - alltime; + + size = PAGE_SIZE; + start = (unsigned long) _text; + rangetime = mfctl(16); + while (start < (unsigned long) _end) { + flush_tlb_kernel_range(start, start + PAGE_SIZE); + start += PAGE_SIZE; + size += PAGE_SIZE; + } + rangetime = mfctl(16) - rangetime; + + printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n", + alltime, size, rangetime); + + parisc_tlb_flush_threshold = size * alltime / rangetime; + parisc_tlb_flush_threshold *= num_online_cpus(); + parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold); + if (!parisc_tlb_flush_threshold) + parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; + + printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n", + parisc_tlb_flush_threshold/1024); } extern void purge_kernel_dcache_page_asm(unsigned long); @@ -403,48 +435,45 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, } EXPORT_SYMBOL(copy_user_page); -void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) -{ - unsigned long flags; - - /* Note: purge_tlb_entries can be called at startup with - no context. */ - - purge_tlb_start(flags); - mtsp(mm->context, 1); - pdtlb(addr); - pitlb(addr); - purge_tlb_end(flags); -} -EXPORT_SYMBOL(purge_tlb_entries); - -void __flush_tlb_range(unsigned long sid, unsigned long start, - unsigned long end) +/* __flush_tlb_range() + * + * returns 1 if all TLBs were flushed. + */ +int __flush_tlb_range(unsigned long sid, unsigned long start, + unsigned long end) { - unsigned long npages; + unsigned long flags, size; - npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ + size = (end - start); + if (size >= parisc_tlb_flush_threshold) { flush_tlb_all(); - else { - unsigned long flags; + return 1; + } + /* Purge TLB entries for small ranges using the pdtlb and + pitlb instructions. These instructions execute locally + but cause a purge request to be broadcast to other TLBs. */ + if (likely(!split_tlb)) { + while (start < end) { + purge_tlb_start(flags); + mtsp(sid, 1); + pdtlb(start); + purge_tlb_end(flags); + start += PAGE_SIZE; + } + return 0; + } + + /* split TLB case */ + while (start < end) { purge_tlb_start(flags); mtsp(sid, 1); - if (split_tlb) { - while (npages--) { - pdtlb(start); - pitlb(start); - start += PAGE_SIZE; - } - } else { - while (npages--) { - pdtlb(start); - start += PAGE_SIZE; - } - } + pdtlb(start); + pitlb(start); purge_tlb_end(flags); + start += PAGE_SIZE; } + return 0; } static void cacheflush_h_tmp_function(void *dummy) diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 75819617f93b..c5ef4081b01d 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -45,7 +45,7 @@ .level 2.0 #endif - .import pa_dbit_lock,data + .import pa_tlb_lock,data /* space_to_prot macro creates a prot id from a space id */ @@ -420,8 +420,8 @@ SHLREG %r9,PxD_VALUE_SHIFT,\pmd extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */ - shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd - LDREG %r0(\pmd),\pte /* pmd is now pte */ + shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */ + LDREG %r0(\pmd),\pte bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault .endm @@ -453,57 +453,53 @@ L2_ptep \pgd,\pte,\index,\va,\fault .endm - /* Acquire pa_dbit_lock lock. */ - .macro dbit_lock spc,tmp,tmp1 + /* Acquire pa_tlb_lock lock and recheck page is still present. */ + .macro tlb_lock spc,ptp,pte,tmp,tmp1,fault #ifdef CONFIG_SMP cmpib,COND(=),n 0,\spc,2f - load32 PA(pa_dbit_lock),\tmp + load32 PA(pa_tlb_lock),\tmp 1: LDCW 0(\tmp),\tmp1 cmpib,COND(=) 0,\tmp1,1b nop + LDREG 0(\ptp),\pte + bb,<,n \pte,_PAGE_PRESENT_BIT,2f + b \fault + stw \spc,0(\tmp) 2: #endif .endm - /* Release pa_dbit_lock lock without reloading lock address. */ - .macro dbit_unlock0 spc,tmp + /* Release pa_tlb_lock lock without reloading lock address. */ + .macro tlb_unlock0 spc,tmp #ifdef CONFIG_SMP or,COND(=) %r0,\spc,%r0 stw \spc,0(\tmp) #endif .endm - /* Release pa_dbit_lock lock. */ - .macro dbit_unlock1 spc,tmp + /* Release pa_tlb_lock lock. */ + .macro tlb_unlock1 spc,tmp #ifdef CONFIG_SMP - load32 PA(pa_dbit_lock),\tmp - dbit_unlock0 \spc,\tmp + load32 PA(pa_tlb_lock),\tmp + tlb_unlock0 \spc,\tmp #endif .endm /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and * don't needlessly dirty the cache line if it was already set */ - .macro update_ptep spc,ptep,pte,tmp,tmp1 -#ifdef CONFIG_SMP - or,COND(=) %r0,\spc,%r0 - LDREG 0(\ptep),\pte -#endif + .macro update_accessed ptp,pte,tmp,tmp1 ldi _PAGE_ACCESSED,\tmp1 or \tmp1,\pte,\tmp and,COND(<>) \tmp1,\pte,%r0 - STREG \tmp,0(\ptep) + STREG \tmp,0(\ptp) .endm /* Set the dirty bit (and accessed bit). No need to be * clever, this is only used from the dirty fault */ - .macro update_dirty spc,ptep,pte,tmp -#ifdef CONFIG_SMP - or,COND(=) %r0,\spc,%r0 - LDREG 0(\ptep),\pte -#endif + .macro update_dirty ptp,pte,tmp ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp or \tmp,\pte,\pte - STREG \pte,0(\ptep) + STREG \pte,0(\ptp) .endm /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) @@ -1148,14 +1144,14 @@ dtlb_miss_20w: L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20w + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1174,14 +1170,14 @@ nadtlb_miss_20w: L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20w + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1202,20 +1198,20 @@ dtlb_miss_11: L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_11 + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1235,21 +1231,20 @@ nadtlb_miss_11: L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_11 + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1269,16 +1264,16 @@ dtlb_miss_20: L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20 + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 idtlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1297,16 +1292,16 @@ nadtlb_miss_20: L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20 + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 - idtlbt pte,prot - dbit_unlock1 spc,t0 + idtlbt pte,prot + tlb_unlock1 spc,t0 rfir nop @@ -1406,14 +1401,14 @@ itlb_miss_20w: L3_ptep ptp,pte,t0,va,itlb_fault - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1430,14 +1425,14 @@ naitlb_miss_20w: L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20w + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1458,20 +1453,20 @@ itlb_miss_11: L2_ptep ptp,pte,t0,va,itlb_fault - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 iitlba pte,(%sr1,va) iitlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1482,20 +1477,20 @@ naitlb_miss_11: L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_11 + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 iitlba pte,(%sr1,va) iitlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1516,16 +1511,16 @@ itlb_miss_20: L2_ptep ptp,pte,t0,va,itlb_fault - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1536,16 +1531,16 @@ naitlb_miss_20: L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20 + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1568,14 +1563,14 @@ dbit_trap_20w: L3_ptep ptp,pte,t0,va,dbit_fault - dbit_lock spc,t0,t1 - update_dirty spc,ptp,pte,t1 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault + update_dirty ptp,pte,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot - dbit_unlock0 spc,t0 + tlb_unlock0 spc,t0 rfir nop #else @@ -1588,8 +1583,8 @@ dbit_trap_11: L2_ptep ptp,pte,t0,va,dbit_fault - dbit_lock spc,t0,t1 - update_dirty spc,ptp,pte,t1 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault + update_dirty ptp,pte,t1 make_insert_tlb_11 spc,pte,prot @@ -1600,8 +1595,8 @@ dbit_trap_11: idtlbp prot,(%sr1,va) mtsp t1, %sr1 /* Restore sr1 */ - dbit_unlock0 spc,t0 + tlb_unlock0 spc,t0 rfir nop @@ -1612,16 +1607,16 @@ dbit_trap_20: L2_ptep ptp,pte,t0,va,dbit_fault - dbit_lock spc,t0,t1 - update_dirty spc,ptp,pte,t1 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault + update_dirty ptp,pte,t1 make_insert_tlb spc,pte,prot f_extend pte,t1 - idtlbt pte,prot - dbit_unlock0 spc,t0 + idtlbt pte,prot + tlb_unlock0 spc,t0 rfir nop #endif diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 6548fd1d2e62..b99b39f1da02 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -43,10 +43,6 @@ #include "../math-emu/math-emu.h" /* for handle_fpe() */ -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) -DEFINE_SPINLOCK(pa_dbit_lock); -#endif - static void parisc_show_stack(struct task_struct *task, unsigned long *sp, struct pt_regs *regs); diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index ccde8f084ce4..112ccf497562 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S @@ -52,6 +52,22 @@ .text /* + * Used by threads when the lock bit of core_idle_state is set. + * Threads will spin in HMT_LOW until the lock bit is cleared. + * r14 - pointer to core_idle_state + * r15 - used to load contents of core_idle_state + */ + +core_idle_lock_held: + HMT_LOW +3: lwz r15,0(r14) + andi. r15,r15,PNV_CORE_IDLE_LOCK_BIT + bne 3b + HMT_MEDIUM + lwarx r15,0,r14 + blr + +/* * Pass requested state in r3: * r3 - PNV_THREAD_NAP/SLEEP/WINKLE * @@ -150,6 +166,10 @@ power7_enter_nap_mode: ld r14,PACA_CORE_IDLE_STATE_PTR(r13) lwarx_loop1: lwarx r15,0,r14 + + andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT + bnel core_idle_lock_held + andc r15,r15,r7 /* Clear thread bit */ andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS @@ -294,7 +314,7 @@ lwarx_loop2: * workaround undo code or resyncing timebase or restoring context * In either case loop until the lock bit is cleared. */ - bne core_idle_lock_held + bnel core_idle_lock_held cmpwi cr2,r15,0 lbz r4,PACA_SUBCORE_SIBLING_MASK(r13) @@ -319,15 +339,6 @@ lwarx_loop2: isync b common_exit -core_idle_lock_held: - HMT_LOW -core_idle_lock_loop: - lwz r15,0(14) - andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT - bne core_idle_lock_loop - HMT_MEDIUM - b lwarx_loop2 - first_thread_in_subcore: /* First thread in subcore to wakeup */ ori r15,r15,PNV_CORE_IDLE_LOCK_BIT diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6530f1b8874d..37de90f8a845 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -297,6 +297,8 @@ long machine_check_early(struct pt_regs *regs) __this_cpu_inc(irq_stat.mce_exceptions); + add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); + if (cur_cpu_spec && cur_cpu_spec->machine_check_early) handled = cur_cpu_spec->machine_check_early(regs); return handled; diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 6d535973b200..a67c6d781c52 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -529,6 +529,10 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) printk(KERN_ALERT "Unable to handle kernel paging request for " "instruction fetch\n"); break; + case 0x600: + printk(KERN_ALERT "Unable to handle kernel paging request for " + "unaligned access at address 0x%08lx\n", regs->dar); + break; default: printk(KERN_ALERT "Unable to handle kernel paging request for " "unknown fault\n"); diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index ec2eb20631d1..df956295c2a7 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c @@ -320,6 +320,8 @@ static struct attribute *device_str_attr_create_(char *name, char *str) if (!attr) return NULL; + sysfs_attr_init(&attr->attr.attr); + attr->var = str; attr->attr.attr.name = name; attr->attr.attr.mode = 0444; diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c index 4949ef0d9400..37f959bf392e 100644 --- a/arch/powerpc/platforms/powernv/opal-elog.c +++ b/arch/powerpc/platforms/powernv/opal-elog.c @@ -237,7 +237,7 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) return elog; } -static void elog_work_fn(struct work_struct *work) +static irqreturn_t elog_event(int irq, void *data) { __be64 size; __be64 id; @@ -251,7 +251,7 @@ static void elog_work_fn(struct work_struct *work) rc = opal_get_elog_size(&id, &size, &type); if (rc != OPAL_SUCCESS) { pr_err("ELOG: OPAL log info read failed\n"); - return; + return IRQ_HANDLED; } elog_size = be64_to_cpu(size); @@ -270,16 +270,10 @@ static void elog_work_fn(struct work_struct *work) * entries. */ if (kset_find_obj(elog_kset, name)) - return; + return IRQ_HANDLED; create_elog_obj(log_id, elog_size, elog_type); -} - -static DECLARE_WORK(elog_work, elog_work_fn); -static irqreturn_t elog_event(int irq, void *data) -{ - schedule_work(&elog_work); return IRQ_HANDLED; } @@ -304,8 +298,8 @@ int __init opal_elog_init(void) return irq; } - rc = request_irq(irq, elog_event, - IRQ_TYPE_LEVEL_HIGH, "opal-elog", NULL); + rc = request_threaded_irq(irq, NULL, elog_event, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "opal-elog", NULL); if (rc) { pr_err("%s: Can't request OPAL event irq (%d)\n", __func__, rc); diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c index 46cb3feb0a13..4ece8e40dd54 100644 --- a/arch/powerpc/platforms/powernv/opal-prd.c +++ b/arch/powerpc/platforms/powernv/opal-prd.c @@ -112,6 +112,7 @@ static int opal_prd_open(struct inode *inode, struct file *file) static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) { size_t addr, size; + pgprot_t page_prot; int rc; pr_devel("opal_prd_mmap(0x%016lx, 0x%016lx, 0x%lx, 0x%lx)\n", @@ -125,13 +126,11 @@ static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) if (!opal_prd_range_is_valid(addr, size)) return -EINVAL; - vma->vm_page_prot = __pgprot(pgprot_val(phys_mem_access_prot(file, - vma->vm_pgoff, - size, vma->vm_page_prot)) - | _PAGE_SPECIAL); + page_prot = phys_mem_access_prot(file, vma->vm_pgoff, + size, vma->vm_page_prot); rc = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, - vma->vm_page_prot); + page_prot); return rc; } diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c index 2bc33674ebfc..87f9623ca805 100644 --- a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c @@ -18,6 +18,7 @@ #include <linux/pci.h> #include <linux/semaphore.h> #include <asm/msi_bitmap.h> +#include <asm/ppc-pci.h> struct ppc4xx_hsta_msi { struct device *dev; diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c index 88c7016492c4..97bbb6060b25 100644 --- a/arch/tile/lib/memcpy_user_64.c +++ b/arch/tile/lib/memcpy_user_64.c @@ -28,7 +28,7 @@ #define _ST(p, inst, v) \ ({ \ asm("1: " #inst " %0, %1;" \ - ".pushsection .coldtext.memcpy,\"ax\";" \ + ".pushsection .coldtext,\"ax\";" \ "2: { move r0, %2; jrp lr };" \ ".section __ex_table,\"a\";" \ ".align 8;" \ @@ -41,7 +41,7 @@ ({ \ unsigned long __v; \ asm("1: " #inst " %0, %1;" \ - ".pushsection .coldtext.memcpy,\"ax\";" \ + ".pushsection .coldtext,\"ax\";" \ "2: { move r0, %2; jrp lr };" \ ".section __ex_table,\"a\";" \ ".align 8;" \ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 55bced17dc95..3dbb7e7909ca 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -254,6 +254,11 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING config ARCH_SUPPORTS_DEBUG_PAGEALLOC def_bool y +config KASAN_SHADOW_OFFSET + hex + depends on KASAN + default 0xdffffc0000000000 + config HAVE_INTEL_TXT def_bool y depends on INTEL_IOMMU && ACPI @@ -2015,7 +2020,7 @@ config CMDLINE_BOOL To compile command line arguments into the kernel, set this option to 'Y', then fill in the - the boot arguments in CONFIG_CMDLINE. + boot arguments in CONFIG_CMDLINE. Systems with fully functional boot loaders (i.e. non-embedded) should leave this option set to 'N'. diff --git a/arch/x86/include/asm/espfix.h b/arch/x86/include/asm/espfix.h index 99efebb2f69d..ca3ce9ab9385 100644 --- a/arch/x86/include/asm/espfix.h +++ b/arch/x86/include/asm/espfix.h @@ -9,7 +9,7 @@ DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); extern void init_espfix_bsp(void); -extern void init_espfix_ap(void); +extern void init_espfix_ap(int cpu); #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h index 8b22422fbad8..74a2a8dc9908 100644 --- a/arch/x86/include/asm/kasan.h +++ b/arch/x86/include/asm/kasan.h @@ -14,15 +14,11 @@ #ifndef __ASSEMBLY__ -extern pte_t kasan_zero_pte[]; -extern pte_t kasan_zero_pmd[]; -extern pte_t kasan_zero_pud[]; - #ifdef CONFIG_KASAN -void __init kasan_map_early_shadow(pgd_t *pgd); +void __init kasan_early_init(void); void __init kasan_init(void); #else -static inline void kasan_map_early_shadow(pgd_t *pgd) { } +static inline void kasan_early_init(void) { } static inline void kasan_init(void) { } #endif diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 28eba2d38b15..f813261d9740 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -409,12 +409,6 @@ static void __setup_vector_irq(int cpu) int irq, vector; struct apic_chip_data *data; - /* - * vector_lock will make sure that we don't run into irq vector - * assignments that might be happening on another cpu in parallel, - * while we setup our initial vector to irq mappings. - */ - raw_spin_lock(&vector_lock); /* Mark the inuse vectors */ for_each_active_irq(irq) { data = apic_chip_data(irq_get_irq_data(irq)); @@ -436,16 +430,16 @@ static void __setup_vector_irq(int cpu) if (!cpumask_test_cpu(cpu, data->domain)) per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; } - raw_spin_unlock(&vector_lock); } /* - * Setup the vector to irq mappings. + * Setup the vector to irq mappings. Must be called with vector_lock held. */ void setup_vector_irq(int cpu) { int irq; + lockdep_assert_held(&vector_lock); /* * On most of the platforms, legacy PIC delivers the interrupts on the * boot cpu. But there are certain platforms where PIC interrupts are diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 89427d8d4fc5..eec40f595ab9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -175,7 +175,9 @@ static __init void early_serial_init(char *s) } if (*s) { - if (kstrtoul(s, 0, &baud) < 0 || baud == 0) + baud = simple_strtoull(s, &e, 0); + + if (baud == 0 || s == e) baud = DEFAULT_BAUD; } diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c index f5d0730e7b08..ce95676abd60 100644 --- a/arch/x86/kernel/espfix_64.c +++ b/arch/x86/kernel/espfix_64.c @@ -131,25 +131,24 @@ void __init init_espfix_bsp(void) init_espfix_random(); /* The rest is the same as for any other processor */ - init_espfix_ap(); + init_espfix_ap(0); } -void init_espfix_ap(void) +void init_espfix_ap(int cpu) { - unsigned int cpu, page; + unsigned int page; unsigned long addr; pud_t pud, *pud_p; pmd_t pmd, *pmd_p; pte_t pte, *pte_p; - int n; + int n, node; void *stack_page; pteval_t ptemask; /* We only have to do this once... */ - if (likely(this_cpu_read(espfix_stack))) + if (likely(per_cpu(espfix_stack, cpu))) return; /* Already initialized */ - cpu = smp_processor_id(); addr = espfix_base_addr(cpu); page = cpu/ESPFIX_STACKS_PER_PAGE; @@ -165,12 +164,15 @@ void init_espfix_ap(void) if (stack_page) goto unlock_done; + node = cpu_to_node(cpu); ptemask = __supported_pte_mask; pud_p = &espfix_pud_page[pud_index(addr)]; pud = *pud_p; if (!pud_present(pud)) { - pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); + struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); + + pmd_p = (pmd_t *)page_address(page); pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); for (n = 0; n < ESPFIX_PUD_CLONES; n++) @@ -180,7 +182,9 @@ void init_espfix_ap(void) pmd_p = pmd_offset(&pud, addr); pmd = *pmd_p; if (!pmd_present(pmd)) { - pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); + struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); + + pte_p = (pte_t *)page_address(page); pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); for (n = 0; n < ESPFIX_PMD_CLONES; n++) @@ -188,7 +192,7 @@ void init_espfix_ap(void) } pte_p = pte_offset_kernel(&pmd, addr); - stack_page = (void *)__get_free_page(GFP_KERNEL); + stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0)); pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); for (n = 0; n < ESPFIX_PTE_CLONES; n++) set_pte(&pte_p[n*PTE_STRIDE], pte); @@ -199,7 +203,7 @@ void init_espfix_ap(void) unlock_done: mutex_unlock(&espfix_init_mutex); done: - this_cpu_write(espfix_stack, addr); - this_cpu_write(espfix_waddr, (unsigned long)stack_page - + (addr & ~PAGE_MASK)); + per_cpu(espfix_stack, cpu) = addr; + per_cpu(espfix_waddr, cpu) = (unsigned long)stack_page + + (addr & ~PAGE_MASK); } diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 5a4668136e98..f129a9af6357 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -161,11 +161,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) /* Kill off the identity-map trampoline */ reset_early_page_tables(); - kasan_map_early_shadow(early_level4_pgt); - - /* clear bss before set_intr_gate with early_idt_handler */ clear_bss(); + clear_page(init_level4_pgt); + + kasan_early_init(); + for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) set_intr_gate(i, early_idt_handler_array[i]); load_idt((const struct desc_ptr *)&idt_descr); @@ -177,12 +178,9 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) */ load_ucode_bsp(); - clear_page(init_level4_pgt); /* set init_level4_pgt kernel high mapping*/ init_level4_pgt[511] = early_level4_pgt[511]; - kasan_map_early_shadow(init_level4_pgt); - x86_64_start_reservations(real_mode_data); } diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index e5c27f729a38..1d40ca8a73f2 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -516,38 +516,9 @@ ENTRY(phys_base) /* This must match the first entry in level2_kernel_pgt */ .quad 0x0000000000000000 -#ifdef CONFIG_KASAN -#define FILL(VAL, COUNT) \ - .rept (COUNT) ; \ - .quad (VAL) ; \ - .endr - -NEXT_PAGE(kasan_zero_pte) - FILL(kasan_zero_page - __START_KERNEL_map + _KERNPG_TABLE, 512) -NEXT_PAGE(kasan_zero_pmd) - FILL(kasan_zero_pte - __START_KERNEL_map + _KERNPG_TABLE, 512) -NEXT_PAGE(kasan_zero_pud) - FILL(kasan_zero_pmd - __START_KERNEL_map + _KERNPG_TABLE, 512) - -#undef FILL -#endif - - #include "../../x86/xen/xen-head.S" __PAGE_ALIGNED_BSS NEXT_PAGE(empty_zero_page) .skip PAGE_SIZE -#ifdef CONFIG_KASAN -/* - * This page used as early shadow. We don't use empty_zero_page - * at early stages, stack instrumentation could write some garbage - * to this page. - * Latter we reuse it as zero shadow for large ranges of memory - * that allowed to access, but not instrumented by kasan - * (vmalloc/vmemmap ...). - */ -NEXT_PAGE(kasan_zero_page) - .skip PAGE_SIZE -#endif diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 88b366487b0e..c7dfe1be784e 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -347,14 +347,22 @@ int check_irq_vectors_for_cpu_disable(void) if (!desc) continue; + /* + * Protect against concurrent action removal, + * affinity changes etc. + */ + raw_spin_lock(&desc->lock); data = irq_desc_get_irq_data(desc); cpumask_copy(&affinity_new, data->affinity); cpumask_clear_cpu(this_cpu, &affinity_new); /* Do not count inactive or per-cpu irqs. */ - if (!irq_has_action(irq) || irqd_is_per_cpu(data)) + if (!irq_has_action(irq) || irqd_is_per_cpu(data)) { + raw_spin_unlock(&desc->lock); continue; + } + raw_spin_unlock(&desc->lock); /* * A single irq may be mapped to multiple * cpu's vector_irq[] (for example IOAPIC cluster @@ -385,6 +393,9 @@ int check_irq_vectors_for_cpu_disable(void) * vector. If the vector is marked in the used vectors * bitmap or an irq is assigned to it, we don't count * it as available. + * + * As this is an inaccurate snapshot anyway, we can do + * this w/o holding vector_lock. */ for (vector = FIRST_EXTERNAL_VECTOR; vector < first_system_vector; vector++) { @@ -486,6 +497,11 @@ void fixup_irqs(void) */ mdelay(1); + /* + * We can walk the vector array of this cpu without holding + * vector_lock because the cpu is already marked !online, so + * nothing else will touch it. + */ for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { unsigned int irr; @@ -497,9 +513,9 @@ void fixup_irqs(void) irq = __this_cpu_read(vector_irq[vector]); desc = irq_to_desc(irq); + raw_spin_lock(&desc->lock); data = irq_desc_get_irq_data(desc); chip = irq_data_get_irq_chip(data); - raw_spin_lock(&desc->lock); if (chip->irq_retrigger) { chip->irq_retrigger(data); __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 8add66b22f33..d3010aa79daf 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -171,11 +171,6 @@ static void smp_callin(void) apic_ap_setup(); /* - * Need to setup vector mappings before we enable interrupts. - */ - setup_vector_irq(smp_processor_id()); - - /* * Save our processor parameters. Note: this information * is needed for clock calibration. */ @@ -239,18 +234,13 @@ static void notrace start_secondary(void *unused) check_tsc_sync_target(); /* - * Enable the espfix hack for this CPU - */ -#ifdef CONFIG_X86_ESPFIX64 - init_espfix_ap(); -#endif - - /* - * We need to hold vector_lock so there the set of online cpus - * does not change while we are assigning vectors to cpus. Holding - * this lock ensures we don't half assign or remove an irq from a cpu. + * Lock vector_lock and initialize the vectors on this cpu + * before setting the cpu online. We must set it online with + * vector_lock held to prevent a concurrent setup/teardown + * from seeing a half valid vector space. */ lock_vector_lock(); + setup_vector_irq(smp_processor_id()); set_cpu_online(smp_processor_id(), true); unlock_vector_lock(); cpu_set_state_online(smp_processor_id()); @@ -854,6 +844,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) initial_code = (unsigned long)start_secondary; stack_start = idle->thread.sp; + /* + * Enable the espfix hack for this CPU + */ +#ifdef CONFIG_X86_ESPFIX64 + init_espfix_ap(cpu); +#endif + /* So we see what's up */ announce_cpu(cpu, apicid); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 505449700e0c..7437b41f6a47 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -598,10 +598,19 @@ static unsigned long quick_pit_calibrate(void) if (!pit_expect_msb(0xff-i, &delta, &d2)) break; + delta -= tsc; + + /* + * Extrapolate the error and fail fast if the error will + * never be below 500 ppm. + */ + if (i == 1 && + d1 + d2 >= (delta * MAX_QUICK_PIT_ITERATIONS) >> 11) + return 0; + /* * Iterate until the error is less than 500 ppm */ - delta -= tsc; if (d1+d2 >= delta >> 11) continue; diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index ddf9ecb53cc3..e342586db6e4 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -20,7 +20,7 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) unsigned long ret; if (__range_not_ok(from, n, TASK_SIZE)) - return 0; + return n; /* * Even though this function is typically called from NMI/IRQ context diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 4860906c6b9f..e1840f3db5b5 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c @@ -1,3 +1,4 @@ +#define pr_fmt(fmt) "kasan: " fmt #include <linux/bootmem.h> #include <linux/kasan.h> #include <linux/kdebug.h> @@ -11,7 +12,19 @@ extern pgd_t early_level4_pgt[PTRS_PER_PGD]; extern struct range pfn_mapped[E820_X_MAX]; -extern unsigned char kasan_zero_page[PAGE_SIZE]; +static pud_t kasan_zero_pud[PTRS_PER_PUD] __page_aligned_bss; +static pmd_t kasan_zero_pmd[PTRS_PER_PMD] __page_aligned_bss; +static pte_t kasan_zero_pte[PTRS_PER_PTE] __page_aligned_bss; + +/* + * This page used as early shadow. We don't use empty_zero_page + * at early stages, stack instrumentation could write some garbage + * to this page. + * Latter we reuse it as zero shadow for large ranges of memory + * that allowed to access, but not instrumented by kasan + * (vmalloc/vmemmap ...). + */ +static unsigned char kasan_zero_page[PAGE_SIZE] __page_aligned_bss; static int __init map_range(struct range *range) { @@ -36,7 +49,7 @@ static void __init clear_pgds(unsigned long start, pgd_clear(pgd_offset_k(start)); } -void __init kasan_map_early_shadow(pgd_t *pgd) +static void __init kasan_map_early_shadow(pgd_t *pgd) { int i; unsigned long start = KASAN_SHADOW_START; @@ -73,7 +86,7 @@ static int __init zero_pmd_populate(pud_t *pud, unsigned long addr, while (IS_ALIGNED(addr, PMD_SIZE) && addr + PMD_SIZE <= end) { WARN_ON(!pmd_none(*pmd)); set_pmd(pmd, __pmd(__pa_nodebug(kasan_zero_pte) - | __PAGE_KERNEL_RO)); + | _KERNPG_TABLE)); addr += PMD_SIZE; pmd = pmd_offset(pud, addr); } @@ -99,7 +112,7 @@ static int __init zero_pud_populate(pgd_t *pgd, unsigned long addr, while (IS_ALIGNED(addr, PUD_SIZE) && addr + PUD_SIZE <= end) { WARN_ON(!pud_none(*pud)); set_pud(pud, __pud(__pa_nodebug(kasan_zero_pmd) - | __PAGE_KERNEL_RO)); + | _KERNPG_TABLE)); addr += PUD_SIZE; pud = pud_offset(pgd, addr); } @@ -124,7 +137,7 @@ static int __init zero_pgd_populate(unsigned long addr, unsigned long end) while (IS_ALIGNED(addr, PGDIR_SIZE) && addr + PGDIR_SIZE <= end) { WARN_ON(!pgd_none(*pgd)); set_pgd(pgd, __pgd(__pa_nodebug(kasan_zero_pud) - | __PAGE_KERNEL_RO)); + | _KERNPG_TABLE)); addr += PGDIR_SIZE; pgd = pgd_offset_k(addr); } @@ -166,6 +179,26 @@ static struct notifier_block kasan_die_notifier = { }; #endif +void __init kasan_early_init(void) +{ + int i; + pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL; + pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE; + pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE; + + for (i = 0; i < PTRS_PER_PTE; i++) + kasan_zero_pte[i] = __pte(pte_val); + + for (i = 0; i < PTRS_PER_PMD; i++) + kasan_zero_pmd[i] = __pmd(pmd_val); + + for (i = 0; i < PTRS_PER_PUD; i++) + kasan_zero_pud[i] = __pud(pud_val); + + kasan_map_early_shadow(early_level4_pgt); + kasan_map_early_shadow(init_level4_pgt); +} + void __init kasan_init(void) { int i; @@ -176,6 +209,7 @@ void __init kasan_init(void) memcpy(early_level4_pgt, init_level4_pgt, sizeof(early_level4_pgt)); load_cr3(early_level4_pgt); + __flush_tlb_all(); clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); @@ -202,5 +236,8 @@ void __init kasan_init(void) memset(kasan_zero_page, 0, PAGE_SIZE); load_cr3(init_level4_pgt); + __flush_tlb_all(); init_task.kasan_depth = 0; + + pr_info("Kernel address sanitizer initialized\n"); } |