diff --git a/Documentation/arm/sti/stih418-overview.txt b/Documentation/arm/sti/stih418-overview.txt new file mode 100644 index 000000000000..1cd8fc80646d --- /dev/null +++ b/Documentation/arm/sti/stih418-overview.txt @@ -0,0 +1,20 @@ + STiH418 Overview + ================ + +Introduction +------------ + + The STiH418 is the new generation of SoC for UHDp60 set-top boxes + and server/connected client application for satellite, cable, terrestrial + and IP-STB markets. + + Features + - ARM Cortex-A9 1.5 GHz quad core CPU (28nm) + - SATA2, USB 3.0, PCIe, Gbit Ethernet + - HEVC L5.1 Main 10 + - VP9 + + Document Author + --------------- + + Maxime Coquelin , (c) 2015 ST Microelectronics diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README index e68d163df33d..1fe2d7fd4108 100644 --- a/Documentation/arm/sunxi/README +++ b/Documentation/arm/sunxi/README @@ -50,7 +50,6 @@ SunXi family http://dl.linux-sunxi.org/A31/A3x_release_document/A31/IC/A31%20user%20manual%20V1.1%2020130630.pdf - Allwinner A31s (sun6i) - + Not Supported + Datasheet http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20datasheet%20V1.3%2020131106.pdf + User Manual diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 562cda9d86d9..ad319f84f560 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -24,6 +24,7 @@ compatible: must be one of: o "atmel,at91sam9g45" o "atmel,at91sam9n12" o "atmel,at91sam9rl" + o "atmel,at91sam9xe" * "atmel,sama5" for SoCs using a Cortex-A5, shall be extended with the specific SoC family: o "atmel,sama5d3" shall be extended with the specific SoC compatible: @@ -136,3 +137,19 @@ Example: compatible = "atmel,at91sam9260-rstc"; reg = <0xfffffd00 0x10>; }; + +Special Function Registers (SFR) + +Special Function Registers (SFR) manage specific aspects of the integrated +memory, bridge implementations, processor and other functionality not controlled +elsewhere. + +required properties: +- compatible: Should be "atmel,-sfr", "syscon". + can be "sama5d3" or "sama5d4". +- reg: Should contain registers location and length + + sfr@f0038000 { + compatible = "atmel,sama5d3-sfr", "syscon"; + reg = <0xf0038000 0x60>; + }; diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt index 4e8b7df7fc62..c830b5b65882 100644 --- a/Documentation/devicetree/bindings/arm/fsl.txt +++ b/Documentation/devicetree/bindings/arm/fsl.txt @@ -75,6 +75,18 @@ i.MX6q generic board Required root node properties: - compatible = "fsl,imx6q"; +Freescale Vybrid Platform Device Tree Bindings +---------------------------------------------- + +For the Vybrid SoC familiy all variants with DDR controller are supported, +which is the VF5xx and VF6xx series. Out of historical reasons, in most +places the kernel uses vf610 to refer to the whole familiy. + +Required root node compatible property (one of them): + - compatible = "fsl,vf500"; + - compatible = "fsl,vf510"; + - compatible = "fsl,vf600"; + - compatible = "fsl,vf610"; Freescale LS1021A Platform Device Tree Bindings ------------------------------------------------ diff --git a/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt b/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt new file mode 100644 index 000000000000..6b42fda306ff --- /dev/null +++ b/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt @@ -0,0 +1,16 @@ +Rockchip SRAM for pmu: +------------------------------ + +The sram of pmu is used to store the function of resume from maskrom(the 1st +level loader). This is a common use of the "pmu-sram" because it keeps power +even in low power states in the system. + +Required node properties: +- compatible : should be "rockchip,rk3288-pmu-sram" +- reg : physical base address and the size of the registers window + +Example: + sram@ff720000 { + compatible = "rockchip,rk3288-pmu-sram", "mmio-sram"; + reg = <0xff720000 0x1000>; + }; diff --git a/Documentation/devicetree/bindings/arm/sti.txt b/Documentation/devicetree/bindings/arm/sti.txt index 92f16c78bb69..d70ec358736c 100644 --- a/Documentation/devicetree/bindings/arm/sti.txt +++ b/Documentation/devicetree/bindings/arm/sti.txt @@ -13,3 +13,7 @@ Boards with the ST STiH407 SoC shall have the following properties: Required root node property: compatible = "st,stih407"; +Boards with the ST STiH418 SoC shall have the following properties: +Required root node property: +compatible = "st,stih418"; + diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt index dd75b972ee37..02c27004d4a8 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt @@ -51,6 +51,23 @@ Required properties when nvidia,suspend-mode=<0>: sleep mode, the warm boot code will restore some PLLs, clocks and then bring up CPU0 for resuming the system. +Hardware-triggered thermal reset: +On Tegra30, Tegra114 and Tegra124, if the 'i2c-thermtrip' subnode exists, +hardware-triggered thermal reset will be enabled. + +Required properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'): +- nvidia,i2c-controller-id : ID of I2C controller to send poweroff command to. Valid values are + described in section 9.2.148 "APBDEV_PMC_SCRATCH53_0" of the + Tegra K1 Technical Reference Manual. +- nvidia,bus-addr : Bus address of the PMU on the I2C bus +- nvidia,reg-addr : I2C register address to write poweroff command to +- nvidia,reg-data : Poweroff command to write to PMU + +Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'): +- nvidia,pinmux-id : Pinmux used by the hardware when issuing poweroff command. + Defaults to 0. Valid values are described in section 12.5.2 + "Pinmux Support" of the Tegra4 Technical Reference Manual. + Example: / SoC dts including file @@ -72,6 +89,15 @@ pmc@7000f400 { / Tegra board dts file { + ... + pmc@7000f400 { + i2c-thermtrip { + nvidia,i2c-controller-id = <4>; + nvidia,bus-addr = <0x40>; + nvidia,reg-addr = <0x36>; + nvidia,reg-data = <0x2>; + }; + }; ... clocks { compatible = "simple-bus"; diff --git a/MAINTAINERS b/MAINTAINERS index bfe852899647..85024e23309f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1310,10 +1310,13 @@ S: Maintained ARM/QUALCOMM SUPPORT M: Kumar Gala +M: Andy Gross M: David Brown L: linux-arm-msm@vger.kernel.org +L: linux-soc@vger.kernel.org S: Maintained F: arch/arm/mach-qcom/ +F: drivers/soc/qcom/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git ARM/RADISYS ENP2611 MACHINE SUPPORT diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0850fc0f9658..9f1f09a2bc9b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -860,6 +860,8 @@ source "arch/arm/mach-cns3xxx/Kconfig" source "arch/arm/mach-davinci/Kconfig" +source "arch/arm/mach-digicolor/Kconfig" + source "arch/arm/mach-dove/Kconfig" source "arch/arm/mach-ep93xx/Kconfig" @@ -1493,7 +1495,7 @@ config ARM_PSCI # selected platforms. config ARCH_NR_GPIO int - default 1024 if ARCH_SHMOBILE || ARCH_TEGRA + default 1024 if ARCH_SHMOBILE || ARCH_TEGRA || ARCH_ZYNQ default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \ SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210 default 416 if ARCH_SUNXI diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 8fecefe881cd..970de7518341 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -117,17 +117,20 @@ choice config AT91_DEBUG_LL_DBGU0 bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10, 9rl, 9x5, 9n12" select DEBUG_AT91_UART - depends on HAVE_AT91_DBGU0 + depends on ARCH_AT91 + depends on SOC_AT91RM9200 || SOC_AT91SAM9 config AT91_DEBUG_LL_DBGU1 bool "Kernel low-level debugging on 9263, 9g45 and sama5d3" select DEBUG_AT91_UART - depends on HAVE_AT91_DBGU1 + depends on ARCH_AT91 + depends on SOC_AT91SAM9 || SOC_SAMA5 config AT91_DEBUG_LL_DBGU2 bool "Kernel low-level debugging on sama5d4" select DEBUG_AT91_UART - depends on HAVE_AT91_DBGU2 + depends on ARCH_AT91 + depends on SOC_SAMA5 config DEBUG_BCM2835 bool "Kernel low-level debugging on BCM2835 PL011 UART" @@ -244,6 +247,13 @@ choice Say Y here if you want the debug print routines to direct their output to the serial port in the DC21285 (Footbridge). + config DEBUG_DIGICOLOR_UA0 + bool "Kernel low-level debugging messages via Digicolor UA0" + depends on ARCH_DIGICOLOR + help + Say Y here if you want the debug print routines to direct + their output to the UA0 serial port in the CX92755. + config DEBUG_FOOTBRIDGE_COM1 bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1" depends on FOOTBRIDGE @@ -275,6 +285,14 @@ choice Say Y here if you want the debug print routines to direct their output to the UART on Highbank based devices. + config DEBUG_HIP01_UART + bool "Hisilicon Hip01 Debug UART" + depends on ARCH_HIP01 + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on HIP01 UART. + config DEBUG_HIP04_UART bool "Hisilicon HiP04 Debug UART" depends on ARCH_HIP04 @@ -437,7 +455,7 @@ choice Say Y here if you want the debug print routines to direct their output to the serial port on MSM devices. - ARCH DEBUG_UART_PHYS DEBUG_UART_BASE # + ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT # MSM7X00A, QSD8X50 0xa9a00000 0xe1000000 UART1 MSM7X00A, QSD8X50 0xa9b00000 0xe1000000 UART2 MSM7X00A, QSD8X50 0xa9c00000 0xe1000000 UART3 @@ -456,7 +474,8 @@ choice Say Y here if you want the debug print routines to direct their output to the serial port on Qualcomm devices. - ARCH DEBUG_UART_PHYS DEBUG_UART_BASE + ARCH DEBUG_UART_PHYS DEBUG_UART_VIRT + APQ8064 0x16640000 0xf0040000 APQ8084 0xf995e000 0xfa75e000 MSM8X60 0x19c40000 0xf0040000 MSM8960 0x16440000 0xf0040000 @@ -465,13 +484,13 @@ choice Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration options based on your needs. - config DEBUG_MVEBU_UART - bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)" + config DEBUG_MVEBU_UART0 + bool "Kernel low-level debugging messages via MVEBU UART0 (old bootloaders)" depends on ARCH_MVEBU select DEBUG_UART_8250 help Say Y here if you want kernel low-level debugging support - on MVEBU based platforms. + on MVEBU based platforms on UART0. This option should be used with the old bootloaders that left the internal registers mapped at @@ -484,13 +503,28 @@ choice when u-boot hands over to the kernel, the system silently crashes, with no serial output at all. - config DEBUG_MVEBU_UART_ALTERNATE - bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)" + config DEBUG_MVEBU_UART0_ALTERNATE + bool "Kernel low-level debugging messages via MVEBU UART0 (new bootloaders)" depends on ARCH_MVEBU select DEBUG_UART_8250 help Say Y here if you want kernel low-level debugging support - on MVEBU based platforms. + on MVEBU based platforms on UART0. + + This option should be used with the new bootloaders + that remap the internal registers at 0xf1000000. + + If the wrong DEBUG_MVEBU_UART* option is selected, + when u-boot hands over to the kernel, the system + silently crashes, with no serial output at all. + + config DEBUG_MVEBU_UART1_ALTERNATE + bool "Kernel low-level debugging messages via MVEBU UART1 (new bootloaders)" + depends on ARCH_MVEBU + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on MVEBU based platforms on UART1. This option should be used with the new bootloaders that remap the internal registers at 0xf1000000. @@ -981,16 +1015,28 @@ choice config DEBUG_SIRFPRIMA2_UART1 bool "Kernel low-level debugging messages via SiRFprimaII UART1" depends on ARCH_PRIMA2 + select DEBUG_SIRFSOC_UART help Say Y here if you want the debug print routines to direct their output to the uart1 port on SiRFprimaII devices. - config DEBUG_SIRFMARCO_UART1 - bool "Kernel low-level debugging messages via SiRFmarco UART1" - depends on ARCH_MARCO + config DEBUG_SIRFATLAS7_UART0 + bool "Kernel low-level debugging messages via SiRFatlas7 UART0" + depends on ARCH_ATLAS7 + select DEBUG_SIRFSOC_UART help Say Y here if you want the debug print routines to direct - their output to the uart1 port on SiRFmarco devices. + their output to the uart0 port on SiRFATLAS7 devices.The uart0 + is used on SiRFATLAS7 as a extra debug port.sometimes an extra + debug port can be very useful. + + config DEBUG_SIRFATLAS7_UART1 + bool "Kernel low-level debugging messages via SiRFatlas7 UART1" + depends on ARCH_ATLAS7 + select DEBUG_SIRFSOC_UART + help + Say Y here if you want the debug print routines to direct + their output to the uart1 port on SiRFATLAS7 devices. config STIH41X_DEBUG_ASC2 bool "Use StiH415/416 ASC2 UART for low-level debug" @@ -1038,7 +1084,7 @@ choice for Mediatek mt6589 based platforms on UART0. config DEBUG_MT8127_UART0 - bool "Mediatek mt8127 UART0" + bool "Mediatek mt8127/mt6592 UART0" depends on ARCH_MEDIATEK select DEBUG_UART_8250 help @@ -1165,6 +1211,10 @@ choice endchoice +config DEBUG_AT91_UART + bool + depends on ARCH_AT91 + config DEBUG_EXYNOS_UART bool @@ -1217,12 +1267,15 @@ config DEBUG_STI_UART bool depends on ARCH_STI +config DEBUG_SIRFSOC_UART + bool + depends on ARCH_SIRF + config DEBUG_LL_INCLUDE string default "debug/sa1100.S" if DEBUG_SA1100 default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250 - default "debug/at91.S" if AT91_DEBUG_LL_DBGU0 || AT91_DEBUG_LL_DBGU1 || \ - AT91_DEBUG_LL_DBGU2 + default "debug/at91.S" if DEBUG_AT91_UART default "debug/asm9260.S" if DEBUG_ASM9260_UART default "debug/clps711x.S" if DEBUG_CLPS711X_UART1 || DEBUG_CLPS711X_UART2 default "debug/meson.S" if DEBUG_MESON_UARTAO @@ -1255,7 +1308,7 @@ config DEBUG_LL_INCLUDE default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA4 default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART default "debug/s5pv210.S" if DEBUG_S5PV210_UART - default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1 + default "debug/sirf.S" if DEBUG_SIRFSOC_UART default "debug/sti.S" if DEBUG_STI_UART default "debug/tegra.S" if DEBUG_TEGRA_UART default "debug/ux500.S" if DEBUG_UX500_UART @@ -1264,6 +1317,7 @@ config DEBUG_LL_INCLUDE default "debug/vt8500.S" if DEBUG_VT8500_UART0 default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 default "debug/bcm63xx.S" if DEBUG_UART_BCM63XX + default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0 default "mach/debug-macro.S" # Compatibility options for PL01x @@ -1307,7 +1361,10 @@ config DEBUG_UART_PHYS default 0x11009000 if DEBUG_MT8135_UART3 default 0x16000000 if ARCH_INTEGRATOR default 0x18000300 if DEBUG_BCM_5301X + default 0x18010000 if DEBUG_SIRFATLAS7_UART0 + default 0x18020000 if DEBUG_SIRFATLAS7_UART1 default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1 + default 0x20001000 if DEBUG_HIP01_UART default 0x20060000 if DEBUG_RK29_UART0 default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2 default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3 @@ -1332,12 +1389,13 @@ config DEBUG_UART_PHYS default 0x808c0000 if ARCH_EP93XX default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART default 0xa9a00000 if DEBUG_MSM_UART + default 0xb0060000 if DEBUG_SIRFPRIMA2_UART1 default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX default 0xc0013000 if DEBUG_U300_UART default 0xc8000000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN default 0xc8000003 if ARCH_IXP4XX && CPU_BIG_ENDIAN default 0xd0000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX - default 0xd0012000 if DEBUG_MVEBU_UART + default 0xd0012000 if DEBUG_MVEBU_UART0 default 0xc81004c0 if DEBUG_MESON_UARTAO default 0xd4017000 if DEBUG_MMP_UART2 default 0xd4018000 if DEBUG_MMP_UART3 @@ -1351,7 +1409,8 @@ config DEBUG_UART_PHYS default 0xe8008000 if DEBUG_R7S72100_SCIF2 default 0xf0000be0 if ARCH_EBSA110 default 0xf040ab00 if DEBUG_BRCMSTB_UART - default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE + default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE + default 0xf1012100 if DEBUG_MVEBU_UART1_ALTERNATE default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \ ARCH_ORION5X default 0xf7fc9000 if DEBUG_BERLIN_UART @@ -1380,7 +1439,8 @@ config DEBUG_UART_PHYS DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \ DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \ DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \ - DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART + DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \ + DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 config DEBUG_UART_VIRT hex "Virtual base address of debug UART" @@ -1438,8 +1498,12 @@ config DEBUG_UART_VIRT default 0xfeb30c00 if DEBUG_KEYSTONE_UART0 default 0xfeb31000 if DEBUG_KEYSTONE_UART1 default 0xfec02000 if DEBUG_SOCFPGA_UART - default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE + default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE + default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE + default 0xfec10000 if DEBUG_SIRFATLAS7_UART0 default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0 + default 0xfec20000 if DEBUG_SIRFATLAS7_UART1 + default 0xfec60000 if DEBUG_SIRFPRIMA2_UART1 default 0xfec90000 if DEBUG_RK32_UART2 default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1 default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2 @@ -1458,12 +1522,14 @@ config DEBUG_UART_VIRT default 0xfefb9800 if DEBUG_OMAP1UART3 || DEBUG_OMAP7XXUART3 default 0xfefff700 if ARCH_IOP33X default 0xff003000 if DEBUG_U300_UART + default 0xffd01000 if DEBUG_HIP01_UART default DEBUG_UART_PHYS if !MMU depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \ DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \ DEBUG_MSM_UART || DEBUG_NETX_UART || \ DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \ - DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART + DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \ + DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 config DEBUG_UART_8250_SHIFT int "Register offset shift for the 8250 debug UART" diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi index 6c97d4af61ee..21c2b504f977 100644 --- a/arch/arm/boot/dts/at91rm9200.dtsi +++ b/arch/arm/boot/dts/at91rm9200.dtsi @@ -66,6 +66,11 @@ main_xtal: main_xtal { }; }; + sram: sram@00200000 { + compatible = "mmio-sram"; + reg = <0x00200000 0x4000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -356,6 +361,13 @@ st: timer@fffffd00 { interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; }; + rtc: rtc@fffffe00 { + compatible = "atmel,at91rm9200-rtc"; + reg = <0xfffffe00 0x40>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + status = "disabled"; + }; + tcb0: timer@fffa0000 { compatible = "atmel,at91rm9200-tcb"; reg = <0xfffa0000 0x100>; diff --git a/arch/arm/boot/dts/at91rm9200ek.dts b/arch/arm/boot/dts/at91rm9200ek.dts index 43eb779dd6f6..2a5d21247d7e 100644 --- a/arch/arm/boot/dts/at91rm9200ek.dts +++ b/arch/arm/boot/dts/at91rm9200ek.dts @@ -77,6 +77,10 @@ mtd_dataflash@0 { dbgu: serial@fffff200 { status = "okay"; }; + + rtc: rtc@fffffe00 { + status = "okay"; + }; }; usb0: ohci@00300000 { diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index dd1313cbc314..fff0ee69aab4 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -69,6 +69,11 @@ adc_op_clk: adc_op_clk{ }; }; + sram0: sram@002ff000 { + compatible = "mmio-sram"; + reg = <0x002ff000 0x2000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/at91sam9261.dtsi b/arch/arm/boot/dts/at91sam9261.dtsi index cdb9ed612109..e247b0b5fdab 100644 --- a/arch/arm/boot/dts/at91sam9261.dtsi +++ b/arch/arm/boot/dts/at91sam9261.dtsi @@ -60,6 +60,11 @@ slow_xtal: slow_xtal { }; }; + sram: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x28000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index e8c6c600a5b6..e087a93bea26 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi @@ -62,6 +62,16 @@ slow_xtal: slow_xtal { }; }; + sram0: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x14000>; + }; + + sram1: sram@00500000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x4000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -294,7 +304,7 @@ ssc1_clk: ssc1_clk { reg = <17>; }; - ac91_clk: ac97_clk { + ac97_clk: ac97_clk { #clock-cells = <0>; reg = <18>; }; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index a50ee587a7af..f59301618163 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -16,6 +16,15 @@ memory { reg = <0x20000000 0x08000000>; }; + sram0: sram@002ff000 { + status = "disabled"; + }; + + sram1: sram@002fc000 { + compatible = "mmio-sram"; + reg = <0x002fc000 0x8000>; + }; + ahb { apb { i2c0: i2c@fffac000 { diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 2a8da8a884b4..ee80aa9c0759 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -74,6 +74,11 @@ adc_op_clk: adc_op_clk{ }; }; + sram: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x10000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -1287,7 +1292,6 @@ usb0: ohci@00700000 { compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00700000 0x100000>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>; - //TODO clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck"; status = "disabled"; @@ -1297,7 +1301,6 @@ usb1: ehci@00800000 { compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; reg = <0x00800000 0x100000>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>; - //TODO clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; clock-names = "usb_clk", "ehci_clk", "hclk", "uhpck"; status = "disabled"; diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index 68eb9aded164..c2666a7cb5b1 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -64,6 +64,11 @@ main_xtal: main_xtal { }; }; + sram: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x8000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -893,6 +898,13 @@ watchdog@fffffe40 { status = "disabled"; }; + rtc@fffffeb0 { + compatible = "atmel,at91rm9200-rtc"; + reg = <0xfffffeb0 0x40>; + interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; + status = "disabled"; + }; + pwm0: pwm@f8034000 { compatible = "atmel,at91sam9rl-pwm"; reg = <0xf8034000 0x300>; diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/at91sam9rl.dtsi index 72424371413e..40f645b8fe25 100644 --- a/arch/arm/boot/dts/at91sam9rl.dtsi +++ b/arch/arm/boot/dts/at91sam9rl.dtsi @@ -70,6 +70,11 @@ adc_op_clk: adc_op_clk{ }; }; + sram: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x10000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index bbb3ba65165f..818dabdd8c0e 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -72,6 +72,11 @@ adc_op_clk: adc_op_clk{ }; }; + sram: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x8000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/at91sam9xe.dtsi b/arch/arm/boot/dts/at91sam9xe.dtsi new file mode 100644 index 000000000000..0278f63b2daf --- /dev/null +++ b/arch/arm/boot/dts/at91sam9xe.dtsi @@ -0,0 +1,60 @@ +/* + * at91sam9xe.dtsi - Device Tree Include file for AT91SAM9XE family SoC + * + * Copyright (C) 2015 Atmel, + * 2015 Alexandre Belloni + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "at91sam9260.dtsi" + +/ { + model = "Atmel AT91SAM9XE family SoC"; + compatible = "atmel,at91sam9xe", "atmel,at91sam9260"; + + sram0: sram@002ff000 { + status = "disabled"; + }; + + sram1: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x4000>; + }; +}; diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts index 8f941c2db7c6..243044343ee8 100644 --- a/arch/arm/boot/dts/ethernut5.dts +++ b/arch/arm/boot/dts/ethernut5.dts @@ -6,7 +6,7 @@ * Licensed under GPLv2. */ /dts-v1/; -#include "at91sam9260.dtsi" +#include "at91sam9xe.dtsi" / { model = "Ethernut 5"; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 5f4144d1e3a1..261311bdf65b 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -78,6 +78,11 @@ adc_op_clk: adc_op_clk{ }; }; + sram: sram@00300000 { + compatible = "mmio-sram"; + reg = <0x00300000 0x20000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -214,7 +219,20 @@ isi: isi@f0034000 { compatible = "atmel,at91sam9g45-isi"; reg = <0xf0034000 0x4000>; interrupts = <37 IRQ_TYPE_LEVEL_HIGH 5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_isi_data_0_7>; + clocks = <&isi_clk>; + clock-names = "isi_clk"; status = "disabled"; + port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + sfr: sfr@f0038000 { + compatible = "atmel,sama5d3-sfr", "syscon"; + reg = <0xf0038000 0x60>; }; mmc1: mmc@f8000000 { @@ -545,7 +563,7 @@ pinctrl_i2c2: i2c2-0 { }; isi { - pinctrl_isi: isi-0 { + pinctrl_isi_data_0_7: isi-0-data-0-7 { atmel,pins = ; /* PA30 periph C ISI_VSYNC, conflicts with TWD0, URXD1 */ + }; + + pinctrl_isi_data_8_9: isi-0-data-8-9 { + atmel,pins = + ; /* PC28 periph C ISI_PD9, conflicts with SPI1_NPCS3, PWMFI0 */ }; - pinctrl_isi_pck_as_mck: isi_pck_as_mck-0 { + + pinctrl_isi_data_10_11: isi-0-data-10-11 { atmel,pins = - ; /* PD31 periph B ISI_MCK */ + ; /* PC26 periph C ISI_PD11, conflicts with SPI1_NPCS1, TWD1 */ }; }; diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi index cfcd200b0c17..7d6babdab039 100644 --- a/arch/arm/boot/dts/sama5d3xcm.dtsi +++ b/arch/arm/boot/dts/sama5d3xcm.dtsi @@ -122,6 +122,7 @@ leds { d2 { label = "d2"; gpios = <&pioE 25 GPIO_ACTIVE_LOW>; /* PE25, conflicts with A25, RXD2 */ + linux,default-trigger = "heartbeat"; }; }; }; diff --git a/arch/arm/boot/dts/sama5d3xmb.dtsi b/arch/arm/boot/dts/sama5d3xmb.dtsi index 77e03655aca3..be2ccc53abb5 100644 --- a/arch/arm/boot/dts/sama5d3xmb.dtsi +++ b/arch/arm/boot/dts/sama5d3xmb.dtsi @@ -52,6 +52,29 @@ wm8904: wm8904@1a { }; }; + i2c1: i2c@f0018000 { + ov2640: camera@0x30 { + compatible = "ovti,ov2640"; + reg = <0x30>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pck1_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>; + resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>; + /* use pck1 for the master clock of ov2640 */ + clocks = <&pck1>; + clock-names = "xvclk"; + assigned-clocks = <&pck1>; + assigned-clock-rates = <25000000>; + + port { + ov2640_0: endpoint { + remote-endpoint = <&isi_0>; + bus-width = <8>; + }; + }; + }; + }; + usart1: serial@f0020000 { dmas = <0>, <0>; /* Do not use DMA for usart1 */ pinctrl-names = "default"; @@ -60,8 +83,12 @@ usart1: serial@f0020000 { }; isi: isi@f0034000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_isi &pinctrl_isi_pck_as_mck &pinctrl_isi_power &pinctrl_isi_reset>; + port { + isi_0: endpoint { + remote-endpoint = <&ov2640_0>; + bus-width = <8>; + }; + }; }; mmc1: mmc@f8000000 { @@ -117,12 +144,17 @@ pinctrl_pck0_as_audio_mck: pck0_as_audio_mck { ; /* PD30 periph B */ }; - pinctrl_isi_reset: isi_reset-0 { + pinctrl_pck1_as_isi_mck: pck1_as_isi_mck-0 { + atmel,pins = + ; /* PD31 periph B ISI_MCK */ + }; + + pinctrl_sensor_reset: sensor_reset-0 { atmel,pins = ; /* PE24 gpio */ }; - pinctrl_isi_power: isi_power-0 { + pinctrl_sensor_power: sensor_power-0 { atmel,pins = ; /* PE29 gpio */ }; diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index b94995d1889f..2a31d66164ac 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -103,6 +103,11 @@ adc_op_clk: adc_op_clk{ }; }; + ns_sram: sram@00210000 { + compatible = "mmio-sram"; + reg = <0x00210000 0x10000>; + }; + ahb { compatible = "simple-bus"; #address-cells = <1>; @@ -870,6 +875,11 @@ i2c2: i2c@f8024000 { status = "disabled"; }; + sfr: sfr@f8028000 { + compatible = "atmel,sama5d4-sfr", "syscon"; + reg = <0xf8028000 0x60>; + }; + mmc1: mmc@fc000000 { compatible = "atmel,hsmci"; reg = <0xfc000000 0x600>; diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts index 4eb540be368f..dbfaba09703a 100644 --- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts @@ -1673,6 +1673,13 @@ pmc@0,7000e400 { nvidia,core-pwr-off-time = <61036>; nvidia,core-power-req-active-high; nvidia,sys-clock-req-active-high; + + i2c-thermtrip { + nvidia,i2c-controller-id = <4>; + nvidia,bus-addr = <0x40>; + nvidia,reg-addr = <0x36>; + nvidia,reg-data = <0x2>; + }; }; /* Serial ATA */ diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index a67375f24b21..f2670f638e97 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -15,15 +15,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_AT91=y CONFIG_SOC_AT91RM9200=y -CONFIG_SOC_AT91SAM9260=y -CONFIG_SOC_AT91SAM9261=y -CONFIG_SOC_AT91SAM9263=y -CONFIG_SOC_AT91SAM9RL=y -CONFIG_SOC_AT91SAM9G45=y -CONFIG_SOC_AT91SAM9X5=y -CONFIG_SOC_AT91SAM9N12=y -CONFIG_MACH_AT91RM9200_DT=y -CONFIG_MACH_AT91SAM9_DT=y +CONFIG_SOC_AT91SAM9=y CONFIG_AT91_TIMER_HZ=128 CONFIG_AEABI=y CONFIG_UACCESS_WITH_MEMCPY=y diff --git a/arch/arm/include/debug/digicolor.S b/arch/arm/include/debug/digicolor.S new file mode 100644 index 000000000000..c9517150766a --- /dev/null +++ b/arch/arm/include/debug/digicolor.S @@ -0,0 +1,35 @@ +/* + * Debugging macro include header for Conexant Digicolor USART + * + * Copyright (C) 2014 Paradox Innovation Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#define UA0_STATUS 0x0742 +#define UA0_EMI_REC 0x0744 + +#define UA0_STATUS_TX_READY 0x40 + +#ifdef CONFIG_DEBUG_UART_PHYS + .macro addruart, rp, rv, tmp + ldr \rp, =CONFIG_DEBUG_UART_PHYS + ldr \rv, =CONFIG_DEBUG_UART_VIRT + .endm +#endif + + .macro senduart,rd,rx + strb \rd, [\rx, #UA0_EMI_REC] + .endm + + .macro waituart,rd,rx + .endm + + .macro busyuart,rd,rx +1001: ldrb \rd, [\rx, #UA0_STATUS] + tst \rd, #UA0_STATUS_TX_READY + beq 1001b + .endm diff --git a/arch/arm/include/debug/msm.S b/arch/arm/include/debug/msm.S index 9ef57612811d..e55a9426b496 100644 --- a/arch/arm/include/debug/msm.S +++ b/arch/arm/include/debug/msm.S @@ -23,6 +23,7 @@ .endm .macro senduart, rd, rx +ARM_BE8(rev \rd, \rd ) #ifdef CONFIG_DEBUG_QCOM_UARTDM @ Write the 1 character to UARTDM_TF str \rd, [\rx, #0x70] @@ -35,24 +36,29 @@ #ifdef CONFIG_DEBUG_QCOM_UARTDM @ check for TX_EMT in UARTDM_SR ldr \rd, [\rx, #0x08] +ARM_BE8(rev \rd, \rd ) tst \rd, #0x08 bne 1002f @ wait for TXREADY in UARTDM_ISR 1001: ldr \rd, [\rx, #0x14] +ARM_BE8(rev \rd, \rd ) tst \rd, #0x80 beq 1001b 1002: @ Clear TX_READY by writing to the UARTDM_CR register mov \rd, #0x300 +ARM_BE8(rev \rd, \rd ) str \rd, [\rx, #0x10] @ Write 0x1 to NCF register mov \rd, #0x1 +ARM_BE8(rev \rd, \rd ) str \rd, [\rx, #0x40] @ UARTDM reg. Read to induce delay ldr \rd, [\rx, #0x08] #else @ wait for TX_READY 1001: ldr \rd, [\rx, #0x08] +ARM_BE8(rev \rd, \rd ) tst \rd, #0x04 beq 1001b #endif diff --git a/arch/arm/include/debug/sirf.S b/arch/arm/include/debug/sirf.S index dbf250cf18e6..630f231f2f37 100644 --- a/arch/arm/include/debug/sirf.S +++ b/arch/arm/include/debug/sirf.S @@ -6,37 +6,33 @@ * Licensed under GPLv2 or later. */ -#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1) -#define SIRFSOC_UART1_PA_BASE 0xb0060000 -#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1) -#define SIRFSOC_UART1_PA_BASE 0xcc060000 +#define SIRF_LLUART_TXFIFO_STATUS 0x0114 +#define SIRF_LLUART_TXFIFO_DATA 0x0118 + +#define SIRF_LLUART_TXFIFO_FULL (1 << 5) + +#ifdef CONFIG_DEBUG_SIRFATLAS7_UART0 +#define SIRF_LLUART_TXFIFO_EMPTY (1 << 8) #else -#define SIRFSOC_UART1_PA_BASE 0 +#define SIRF_LLUART_TXFIFO_EMPTY (1 << 6) #endif -#define SIRFSOC_UART1_VA_BASE 0xFEC60000 - -#define SIRFSOC_UART_TXFIFO_STATUS 0x0114 -#define SIRFSOC_UART_TXFIFO_DATA 0x0118 - -#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5) -#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6) .macro addruart, rp, rv, tmp - ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical - ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual + ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical + ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virtual .endm .macro senduart,rd,rx - str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA] + str \rd, [\rx, #SIRF_LLUART_TXFIFO_DATA] .endm .macro busyuart,rd,rx .endm .macro waituart,rd,rx -1001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS] - tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY +1001: ldr \rd, [\rx, #SIRF_LLUART_TXFIFO_STATUS] + tst \rd, #SIRF_LLUART_TXFIFO_EMPTY beq 1001b .endm diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index cec0fb5d621a..c6740e359a44 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -6,15 +6,6 @@ config HAVE_AT91_UTMI config HAVE_AT91_USB_CLK bool -config HAVE_AT91_DBGU0 - bool - -config HAVE_AT91_DBGU1 - bool - -config HAVE_AT91_DBGU2 - bool - config COMMON_CLK_AT91 bool select COMMON_CLK @@ -25,15 +16,6 @@ config HAVE_AT91_SMD config HAVE_AT91_H32MX bool -config SOC_AT91SAM9 - bool - select ATMEL_AIC_IRQ - select COMMON_CLK_AT91 - select CPU_ARM926T - select GENERIC_CLOCKEVENTS - select MEMORY - select ATMEL_SDRAMC - config SOC_SAMA5 bool select ATMEL_AIC5_IRQ @@ -70,7 +52,6 @@ config SOC_SAMA5D3 bool "SAMA5D3 family" select SOC_SAMA5 select HAVE_FB_ATMEL - select HAVE_AT91_DBGU1 select HAVE_AT91_UTMI select HAVE_AT91_SMD select HAVE_AT91_USB_CLK @@ -81,7 +62,6 @@ config SOC_SAMA5D3 config SOC_SAMA5D4 bool "SAMA5D4 family" select SOC_SAMA5 - select HAVE_AT91_DBGU2 select CLKSRC_MMIO select CACHE_L2X0 select CACHE_PL310 @@ -101,83 +81,45 @@ config SOC_AT91RM9200 select COMMON_CLK_AT91 select CPU_ARM920T select GENERIC_CLOCKEVENTS - select HAVE_AT91_DBGU0 select HAVE_AT91_USB_CLK -config SOC_AT91SAM9260 - bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20" - select HAVE_AT91_DBGU0 - select SOC_AT91SAM9 - select HAVE_AT91_USB_CLK - help - Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE - or AT91SAM9G20 SoC. - -config SOC_AT91SAM9261 - bool "AT91SAM9261 or AT91SAM9G10" - select HAVE_AT91_DBGU0 - select HAVE_FB_ATMEL - select SOC_AT91SAM9 - select HAVE_AT91_USB_CLK - help - Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. - -config SOC_AT91SAM9263 - bool "AT91SAM9263" - select HAVE_AT91_DBGU1 - select HAVE_FB_ATMEL - select SOC_AT91SAM9 - select HAVE_AT91_USB_CLK - -config SOC_AT91SAM9RL - bool "AT91SAM9RL" - select HAVE_AT91_DBGU0 - select HAVE_FB_ATMEL - select SOC_AT91SAM9 - select HAVE_AT91_UTMI - -config SOC_AT91SAM9G45 - bool "AT91SAM9G45 or AT91SAM9M10 families" - select HAVE_AT91_DBGU1 - select HAVE_FB_ATMEL - select SOC_AT91SAM9 - select HAVE_AT91_UTMI - select HAVE_AT91_USB_CLK - help - Select this if you are using one of Atmel's AT91SAM9G45 family SoC. - This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. - -config SOC_AT91SAM9X5 - bool "AT91SAM9x5 family" - select HAVE_AT91_DBGU0 - select HAVE_FB_ATMEL - select SOC_AT91SAM9 - select HAVE_AT91_UTMI +config SOC_AT91SAM9 + bool "AT91SAM9" + select ATMEL_AIC_IRQ + select ATMEL_SDRAMC + select COMMON_CLK_AT91 + select CPU_ARM926T + select GENERIC_CLOCKEVENTS select HAVE_AT91_SMD select HAVE_AT91_USB_CLK - help - Select this if you are using one of Atmel's AT91SAM9x5 family SoC. - This means that your SAM9 name finishes with a '5' (except if it is - AT91SAM9G45!). - This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35 - and AT91SAM9X35. - -config SOC_AT91SAM9N12 - bool "AT91SAM9N12 family" - select HAVE_AT91_DBGU0 + select HAVE_AT91_UTMI select HAVE_FB_ATMEL - select SOC_AT91SAM9 - select HAVE_AT91_USB_CLK + select MEMORY help - Select this if you are using Atmel's AT91SAM9N12 SoC. - -# ---------------------------------------------------------- + Select this if you are using one of those Atmel SoC: + AT91SAM9260 + AT91SAM9261 + AT91SAM9263 + AT91SAM9G15 + AT91SAM9G20 + AT91SAM9G25 + AT91SAM9G35 + AT91SAM9G45 + AT91SAM9G46 + AT91SAM9M10 + AT91SAM9M11 + AT91SAM9N12 + AT91SAM9RL + AT91SAM9X25 + AT91SAM9X35 + AT91SAM9XE endif # SOC_SAM_V4_V5 comment "AT91 Feature Selections" config AT91_SLOW_CLOCK bool "Suspend-to-RAM disables main oscillator" + select SRAM depends on SUSPEND help Select this if you want Suspend-to-RAM to save the most power diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 8ef7d9a2e855..827fdbcce1c7 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -8,22 +8,8 @@ obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o # CPU-specific support obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o at91rm9200_time.o -obj-$(CONFIG_SOC_AT91SAM9260) += at91sam9260.o -obj-$(CONFIG_SOC_AT91SAM9261) += at91sam9261.o -obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o -obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o -obj-$(CONFIG_SOC_AT91SAM9N12) += at91sam9n12.o -obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o -obj-$(CONFIG_SOC_AT91SAM9RL) += at91sam9rl.o -obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o -obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o - -# AT91SAM board with device-tree -obj-$(CONFIG_SOC_AT91RM9200) += board-dt-rm9200.o -obj-$(CONFIG_SOC_AT91SAM9) += board-dt-sam9.o - -# SAMA5 board with device-tree -obj-$(CONFIG_SOC_SAMA5) += board-dt-sama5.o +obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o +obj-$(CONFIG_SOC_SAMA5) += sama5.o # Power Management obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index b52916947535..8fcfb70f7124 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -1,35 +1,33 @@ /* - * arch/arm/mach-at91/at91rm9200.c + * Setup code for AT91RM9200 * - * Copyright (C) 2005 SAN People - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre + * 2012 Joachim Eastwood * + * Licensed under GPLv2 or later. */ +#include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include + #include -#include -#include "soc.h" #include "generic.h" -static void at91rm9200_idle(void) -{ - /* - * Disable the processor clock. The processor will be automatically - * re-enabled by an interrupt or by a reset. - */ - at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); -} - static void at91rm9200_restart(enum reboot_mode reboot_mode, const char *cmd) { /* @@ -39,23 +37,31 @@ static void at91rm9200_restart(enum reboot_mode reboot_mode, const char *cmd) at91_st_write(AT91_ST_CR, AT91_ST_WDRST); } -/* -------------------------------------------------------------------- - * AT91RM9200 processor initialization - * -------------------------------------------------------------------- */ -static void __init at91rm9200_map_io(void) +static void __init at91rm9200_dt_timer_init(void) { - /* Map peripherals */ - at91_init_sram(0, AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE); + of_clk_init(NULL); + at91rm9200_timer_init(); } -static void __init at91rm9200_initialize(void) +static void __init at91rm9200_dt_device_init(void) { + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + arm_pm_idle = at91rm9200_idle; arm_pm_restart = at91rm9200_restart; + at91rm9200_pm_init(); } -AT91_SOC_START(at91rm9200) - .map_io = at91rm9200_map_io, - .init = at91rm9200_initialize, -AT91_SOC_END + +static const char *at91rm9200_dt_board_compat[] __initconst = { + "atmel,at91rm9200", + NULL +}; + +DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200") + .init_time = at91rm9200_dt_timer_init, + .map_io = at91_map_io, + .init_machine = at91rm9200_dt_device_init, + .dt_compat = at91rm9200_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c new file mode 100644 index 000000000000..56e3ba73ec40 --- /dev/null +++ b/arch/arm/mach-at91/at91sam9.c @@ -0,0 +1,87 @@ +/* + * Setup code for AT91SAM9 + * + * Copyright (C) 2011 Atmel, + * 2011 Nicolas Ferre + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "generic.h" + +static void __init at91sam9_dt_device_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + + arm_pm_idle = at91sam9_idle; + at91sam9260_pm_init(); +} + +static const char *at91_dt_board_compat[] __initconst = { + "atmel,at91sam9", + NULL +}; + +DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9") + /* Maintainer: Atmel */ + .map_io = at91_map_io, + .init_machine = at91sam9_dt_device_init, + .dt_compat = at91_dt_board_compat, +MACHINE_END + +static void __init at91sam9g45_dt_device_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + + arm_pm_idle = at91sam9_idle; + at91sam9g45_pm_init(); +} + +static const char *at91sam9g45_board_compat[] __initconst = { + "atmel,at91sam9g45", + NULL +}; + +DT_MACHINE_START(at91sam9g45_dt, "Atmel AT91SAM9G45") + /* Maintainer: Atmel */ + .map_io = at91_map_io, + .init_machine = at91sam9g45_dt_device_init, + .dt_compat = at91sam9g45_board_compat, +MACHINE_END + +static void __init at91sam9x5_dt_device_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + + arm_pm_idle = at91sam9_idle; + at91sam9x5_pm_init(); +} + +static const char *at91sam9x5_board_compat[] __initconst = { + "atmel,at91sam9x5", + "atmel,at91sam9n12", + NULL +}; + +DT_MACHINE_START(at91sam9x5_dt, "Atmel AT91SAM9") + /* Maintainer: Atmel */ + .map_io = at91_map_io, + .init_machine = at91sam9x5_dt_device_init, + .dt_compat = at91sam9x5_board_compat, +MACHINE_END diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c deleted file mode 100644 index 34e2abe82ae4..000000000000 --- a/arch/arm/mach-at91/at91sam9260.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * arch/arm/mach-at91/at91sam9260.c - * - * Copyright (C) 2006 SAN People - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9260 processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9xe_map_io(void) -{ - unsigned long sram_size; - - switch (at91_soc_initdata.cidr & AT91_CIDR_SRAMSIZ) { - case AT91_CIDR_SRAMSIZ_32K: - sram_size = 2 * SZ_16K; - break; - case AT91_CIDR_SRAMSIZ_16K: - default: - sram_size = SZ_16K; - } - - at91_init_sram(0, AT91SAM9XE_SRAM_BASE, sram_size); -} - -static void __init at91sam9260_map_io(void) -{ - if (cpu_is_at91sam9xe()) - at91sam9xe_map_io(); - else if (cpu_is_at91sam9g20()) - at91_init_sram(0, AT91SAM9G20_SRAM_BASE, AT91SAM9G20_SRAM_SIZE); - else - at91_init_sram(0, AT91SAM9260_SRAM_BASE, AT91SAM9260_SRAM_SIZE); -} - -static void __init at91sam9260_initialize(void) -{ - arm_pm_idle = at91sam9_idle; -} - -AT91_SOC_START(at91sam9260) - .map_io = at91sam9260_map_io, - .init = at91sam9260_initialize, -AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c deleted file mode 100644 index 47878b849975..000000000000 --- a/arch/arm/mach-at91/at91sam9261.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * arch/arm/mach-at91/at91sam9261.c - * - * Copyright (C) 2005 SAN People - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9261 processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9261_map_io(void) -{ - if (cpu_is_at91sam9g10()) - at91_init_sram(0, AT91SAM9G10_SRAM_BASE, AT91SAM9G10_SRAM_SIZE); - else - at91_init_sram(0, AT91SAM9261_SRAM_BASE, AT91SAM9261_SRAM_SIZE); -} - -static void __init at91sam9261_initialize(void) -{ - arm_pm_idle = at91sam9_idle; -} - -AT91_SOC_START(at91sam9261) - .map_io = at91sam9261_map_io, - .init = at91sam9261_initialize, -AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c deleted file mode 100644 index aabcb66145d0..000000000000 --- a/arch/arm/mach-at91/at91sam9263.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * arch/arm/mach-at91/at91sam9263.c - * - * Copyright (C) 2007 Atmel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9263 processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9263_map_io(void) -{ - at91_init_sram(0, AT91SAM9263_SRAM0_BASE, AT91SAM9263_SRAM0_SIZE); - at91_init_sram(1, AT91SAM9263_SRAM1_BASE, AT91SAM9263_SRAM1_SIZE); -} - -static void __init at91sam9263_initialize(void) -{ - arm_pm_idle = at91sam9_idle; -} - -AT91_SOC_START(at91sam9263) - .map_io = at91sam9263_map_io, - .init = at91sam9263_initialize, -AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c deleted file mode 100644 index 000166777a8d..000000000000 --- a/arch/arm/mach-at91/at91sam9g45.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Chip-specific setup code for the AT91SAM9G45 family - * - * Copyright (C) 2009 Atmel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9G45 processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9g45_map_io(void) -{ - at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE); -} - -static void __init at91sam9g45_initialize(void) -{ - arm_pm_idle = at91sam9_idle; -} - -AT91_SOC_START(at91sam9g45) - .map_io = at91sam9g45_map_io, - .init = at91sam9g45_initialize, -AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c deleted file mode 100644 index 0135f868ea4f..000000000000 --- a/arch/arm/mach-at91/at91sam9n12.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SoC specific setup code for the AT91SAM9N12 - * - * Copyright (C) 2012 Atmel Corporation. - * - * Licensed under GPLv2 or later. - */ - -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9N12 processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9n12_map_io(void) -{ - at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE); -} - -AT91_SOC_START(at91sam9n12) - .map_io = at91sam9n12_map_io, -AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c deleted file mode 100644 index 1babfb27694a..000000000000 --- a/arch/arm/mach-at91/at91sam9rl.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * arch/arm/mach-at91/at91sam9rl.c - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2007 Atmel Corporation - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9RL processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9rl_map_io(void) -{ - unsigned long sram_size; - - switch (at91_soc_initdata.cidr & AT91_CIDR_SRAMSIZ) { - case AT91_CIDR_SRAMSIZ_32K: - sram_size = 2 * SZ_16K; - break; - case AT91_CIDR_SRAMSIZ_16K: - default: - sram_size = SZ_16K; - } - - /* Map SRAM */ - at91_init_sram(0, AT91SAM9RL_SRAM_BASE, sram_size); -} - -static void __init at91sam9rl_initialize(void) -{ - arm_pm_idle = at91sam9_idle; -} - -AT91_SOC_START(at91sam9rl) - .map_io = at91sam9rl_map_io, - .init = at91sam9rl_initialize, -AT91_SOC_END diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c deleted file mode 100644 index aa17520ccb0a..000000000000 --- a/arch/arm/mach-at91/at91sam9x5.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Chip-specific setup code for the AT91SAM9x5 family - * - * Copyright (C) 2010-2012 Atmel Corporation. - * - * Licensed under GPLv2 or later. - */ - -#include -#include - -#include "soc.h" -#include "generic.h" - -/* -------------------------------------------------------------------- - * AT91SAM9x5 processor initialization - * -------------------------------------------------------------------- */ - -static void __init at91sam9x5_map_io(void) -{ - at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); -} - -AT91_SOC_START(at91sam9x5) - .map_io = at91sam9x5_map_io, -AT91_SOC_END diff --git a/arch/arm/mach-at91/board-dt-rm9200.c b/arch/arm/mach-at91/board-dt-rm9200.c deleted file mode 100644 index a15ab6f8de00..000000000000 --- a/arch/arm/mach-at91/board-dt-rm9200.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Setup code for AT91RM9200 Evaluation Kits with Device Tree support - * - * Copyright (C) 2011 Atmel, - * 2011 Nicolas Ferre - * 2012 Joachim Eastwood - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "generic.h" - -static void __init at91rm9200_dt_timer_init(void) -{ - of_clk_init(NULL); - at91rm9200_timer_init(); -} - -static const char *at91rm9200_dt_board_compat[] __initdata = { - "atmel,at91rm9200", - NULL -}; - -DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)") - .init_time = at91rm9200_dt_timer_init, - .map_io = at91_map_io, - .init_early = at91_dt_initialize, - .dt_compat = at91rm9200_dt_board_compat, -MACHINE_END diff --git a/arch/arm/mach-at91/board-dt-sam9.c b/arch/arm/mach-at91/board-dt-sam9.c deleted file mode 100644 index f99246aa9b38..000000000000 --- a/arch/arm/mach-at91/board-dt-sam9.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Setup code for AT91SAM Evaluation Kits with Device Tree support - * - * Copyright (C) 2011 Atmel, - * 2011 Nicolas Ferre - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "generic.h" - -static const char *at91_dt_board_compat[] __initdata = { - "atmel,at91sam9", - NULL -}; - -DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)") - /* Maintainer: Atmel */ - .map_io = at91_map_io, - .init_early = at91_dt_initialize, - .dt_compat = at91_dt_board_compat, -MACHINE_END diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 54f3837a0a4d..a6e726a6e0b5 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -17,18 +17,28 @@ /* Map io */ extern void __init at91_map_io(void); extern void __init at91_alt_map_io(void); -extern void __init at91_init_sram(int bank, unsigned long base, - unsigned int length); - - /* Processors */ -extern void __init at91_dt_initialize(void); /* Timer */ extern void at91rm9200_timer_init(void); /* idle */ +extern void at91rm9200_idle(void); extern void at91sam9_idle(void); /* Matrix */ extern void at91_ioremap_matrix(u32 base_addr); + + +#ifdef CONFIG_PM +extern void __init at91rm9200_pm_init(void); +extern void __init at91sam9260_pm_init(void); +extern void __init at91sam9g45_pm_init(void); +extern void __init at91sam9x5_pm_init(void); +#else +void __init at91rm9200_pm_init(void) { } +void __init at91sam9260_pm_init(void) { } +void __init at91sam9g45_pm_init(void) { } +void __init at91sam9x5_pm_init(void) { } +#endif + #endif /* _AT91_GENERIC_H */ diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index 61914fb35f5d..ce7c80a44983 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -152,69 +152,45 @@ static inline int at91_soc_is_detected(void) #define cpu_is_at91rm9200_pqfp() (0) #endif -#ifdef CONFIG_SOC_AT91SAM9260 +#ifdef CONFIG_SOC_AT91SAM9 #define cpu_is_at91sam9xe() (at91_soc_initdata.subtype == AT91_SOC_SAM9XE) #define cpu_is_at91sam9260() (at91_soc_initdata.type == AT91_SOC_SAM9260) #define cpu_is_at91sam9g20() (at91_soc_initdata.type == AT91_SOC_SAM9G20) -#else -#define cpu_is_at91sam9xe() (0) -#define cpu_is_at91sam9260() (0) -#define cpu_is_at91sam9g20() (0) -#endif - -#ifdef CONFIG_SOC_AT91SAM9261 #define cpu_is_at91sam9261() (at91_soc_initdata.type == AT91_SOC_SAM9261) #define cpu_is_at91sam9g10() (at91_soc_initdata.type == AT91_SOC_SAM9G10) -#else -#define cpu_is_at91sam9261() (0) -#define cpu_is_at91sam9g10() (0) -#endif - -#ifdef CONFIG_SOC_AT91SAM9263 #define cpu_is_at91sam9263() (at91_soc_initdata.type == AT91_SOC_SAM9263) -#else -#define cpu_is_at91sam9263() (0) -#endif - -#ifdef CONFIG_SOC_AT91SAM9RL #define cpu_is_at91sam9rl() (at91_soc_initdata.type == AT91_SOC_SAM9RL) -#else -#define cpu_is_at91sam9rl() (0) -#endif - -#ifdef CONFIG_SOC_AT91SAM9G45 #define cpu_is_at91sam9g45() (at91_soc_initdata.type == AT91_SOC_SAM9G45) #define cpu_is_at91sam9g45es() (at91_soc_initdata.subtype == AT91_SOC_SAM9G45ES) #define cpu_is_at91sam9m10() (at91_soc_initdata.subtype == AT91_SOC_SAM9M10) #define cpu_is_at91sam9g46() (at91_soc_initdata.subtype == AT91_SOC_SAM9G46) #define cpu_is_at91sam9m11() (at91_soc_initdata.subtype == AT91_SOC_SAM9M11) -#else -#define cpu_is_at91sam9g45() (0) -#define cpu_is_at91sam9g45es() (0) -#define cpu_is_at91sam9m10() (0) -#define cpu_is_at91sam9g46() (0) -#define cpu_is_at91sam9m11() (0) -#endif - -#ifdef CONFIG_SOC_AT91SAM9X5 #define cpu_is_at91sam9x5() (at91_soc_initdata.type == AT91_SOC_SAM9X5) #define cpu_is_at91sam9g15() (at91_soc_initdata.subtype == AT91_SOC_SAM9G15) #define cpu_is_at91sam9g35() (at91_soc_initdata.subtype == AT91_SOC_SAM9G35) #define cpu_is_at91sam9x35() (at91_soc_initdata.subtype == AT91_SOC_SAM9X35) #define cpu_is_at91sam9g25() (at91_soc_initdata.subtype == AT91_SOC_SAM9G25) #define cpu_is_at91sam9x25() (at91_soc_initdata.subtype == AT91_SOC_SAM9X25) +#define cpu_is_at91sam9n12() (at91_soc_initdata.type == AT91_SOC_SAM9N12) #else +#define cpu_is_at91sam9xe() (0) +#define cpu_is_at91sam9260() (0) +#define cpu_is_at91sam9g20() (0) +#define cpu_is_at91sam9261() (0) +#define cpu_is_at91sam9g10() (0) +#define cpu_is_at91sam9263() (0) +#define cpu_is_at91sam9rl() (0) +#define cpu_is_at91sam9g45() (0) +#define cpu_is_at91sam9g45es() (0) +#define cpu_is_at91sam9m10() (0) +#define cpu_is_at91sam9g46() (0) +#define cpu_is_at91sam9m11() (0) #define cpu_is_at91sam9x5() (0) #define cpu_is_at91sam9g15() (0) #define cpu_is_at91sam9g35() (0) #define cpu_is_at91sam9x35() (0) #define cpu_is_at91sam9g25() (0) #define cpu_is_at91sam9x25() (0) -#endif - -#ifdef CONFIG_SOC_AT91SAM9N12 -#define cpu_is_at91sam9n12() (at91_soc_initdata.type == AT91_SOC_SAM9N12) -#else #define cpu_is_at91sam9n12() (0) #endif diff --git a/arch/arm/mach-at91/include/mach/system_rev.h b/arch/arm/mach-at91/include/mach/system_rev.h deleted file mode 100644 index ef79a9aafc08..000000000000 --- a/arch/arm/mach-at91/include/mach/system_rev.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD - * - * Under GPLv2 only - */ - -#ifndef __ARCH_SYSTEM_REV_H__ -#define __ARCH_SYSTEM_REV_H__ - -#include - -/* - * board revision encoding - * mach specific - * the 16-31 bit are reserved for at91 generic information - * - * bit 31: - * 0 => nand 8 bit - * 1 => nand 16 bit - */ -#define BOARD_HAVE_NAND_16BIT (1 << 31) -static inline int board_have_nand_16bit(void) -{ - return (system_rev & BOARD_HAVE_NAND_16BIT) ? 1 : 0; -} - -#endif /* __ARCH_SYSTEM_REV_H__ */ diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 9b15169a1c62..af8d8afc2e12 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -14,9 +14,13 @@ #include #include #include +#include #include #include #include +#include +#include +#include #include #include #include @@ -32,7 +36,13 @@ #include "generic.h" #include "pm.h" +static struct { + unsigned long uhp_udp_mask; + int memctrl; +} at91_pm_data; + static void (*at91_pm_standby)(void); +void __iomem *at91_ramc_base[2]; static int at91_pm_valid_state(suspend_state_t state) { @@ -71,17 +81,9 @@ static int at91_pm_verify_clocks(void) scsr = at91_pmc_read(AT91_PMC_SCSR); /* USB must not be using PLLB */ - if (cpu_is_at91rm9200()) { - if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) { - pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); - return 0; - } - } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() - || cpu_is_at91sam9g20() || cpu_is_at91sam9g10()) { - if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) { - pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); - return 0; - } + if ((scsr & at91_pm_data.uhp_udp_mask) != 0) { + pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; } /* PCK0..PCK3 must be disabled, or configured to use clk32k */ @@ -149,18 +151,13 @@ static int at91_pm_enter(suspend_state_t state) * turning off the main oscillator; reverse on wakeup. */ if (slow_clock) { - int memctrl = AT91_MEMCTRL_SDRAMC; - - if (cpu_is_at91rm9200()) - memctrl = AT91_MEMCTRL_MC; - else if (cpu_is_at91sam9g45()) - memctrl = AT91_MEMCTRL_DDRSDR; #ifdef CONFIG_AT91_SLOW_CLOCK /* copy slow_clock handler to SRAM, and call it */ memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz); #endif slow_clock(at91_pmc_base, at91_ramc_base[0], - at91_ramc_base[1], memctrl); + at91_ramc_base[1], + at91_pm_data.memctrl); break; } else { pr_info("AT91: PM - no slow clock mode enabled ...\n"); @@ -229,23 +226,134 @@ void at91_pm_set_standby(void (*at91_standby)(void)) } } -static int __init at91_pm_init(void) +static struct of_device_id ramc_ids[] = { + { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, + { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, + { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, + { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby }, + { /*sentinel*/ } +}; + +static void at91_dt_ramc(void) +{ + struct device_node *np; + const struct of_device_id *of_id; + int idx = 0; + const void *standby = NULL; + + for_each_matching_node_and_match(np, ramc_ids, &of_id) { + at91_ramc_base[idx] = of_iomap(np, 0); + if (!at91_ramc_base[idx]) + panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); + + if (!standby) + standby = of_id->data; + + idx++; + } + + if (!idx) + panic(pr_fmt("unable to find compatible ram controller node in dtb\n")); + + if (!standby) { + pr_warn("ramc no standby function available\n"); + return; + } + + at91_pm_set_standby(standby); +} + +#ifdef CONFIG_AT91_SLOW_CLOCK +static void __init at91_pm_sram_init(void) +{ + struct gen_pool *sram_pool; + phys_addr_t sram_pbase; + unsigned long sram_base; + struct device_node *node; + struct platform_device *pdev; + + node = of_find_compatible_node(NULL, NULL, "mmio-sram"); + if (!node) { + pr_warn("%s: failed to find sram node!\n", __func__); + return; + } + + pdev = of_find_device_by_node(node); + if (!pdev) { + pr_warn("%s: failed to find sram device!\n", __func__); + goto put_node; + } + + sram_pool = dev_get_gen_pool(&pdev->dev); + if (!sram_pool) { + pr_warn("%s: sram pool unavailable!\n", __func__); + goto put_node; + } + + sram_base = gen_pool_alloc(sram_pool, at91_slow_clock_sz); + if (!sram_base) { + pr_warn("%s: unable to alloc ocram!\n", __func__); + goto put_node; + } + + sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base); + slow_clock = __arm_ioremap_exec(sram_pbase, at91_slow_clock_sz, false); + +put_node: + of_node_put(node); +} +#endif + + +static void __init at91_pm_init(void) { #ifdef CONFIG_AT91_SLOW_CLOCK - slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz); + at91_pm_sram_init(); #endif pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : "")); - /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */ - if (cpu_is_at91rm9200()) - at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0); - if (at91_cpuidle_device.dev.platform_data) platform_device_register(&at91_cpuidle_device); suspend_set_ops(&at91_pm_ops); - - return 0; } -arch_initcall(at91_pm_init); + +void __init at91rm9200_pm_init(void) +{ + at91_dt_ramc(); + + /* + * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. + */ + at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0); + + at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP; + at91_pm_data.memctrl = AT91_MEMCTRL_MC; + + at91_pm_init(); +} + +void __init at91sam9260_pm_init(void) +{ + at91_dt_ramc(); + at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC; + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; + return at91_pm_init(); +} + +void __init at91sam9g45_pm_init(void) +{ + at91_dt_ramc(); + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP; + at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; + return at91_pm_init(); +} + +void __init at91sam9x5_pm_init(void) +{ + at91_dt_ramc(); + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; + at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; + return at91_pm_init(); +} diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 20018779bae7..556151e85ec4 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -17,15 +17,6 @@ #include #include - -#ifdef CONFIG_SOC_AT91SAM9263 -/* - * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use; - * handle those cases both here and in the Suspend-To-RAM support. - */ -#warning Assuming EB1 SDRAM controller is *NOT* used -#endif - /* * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master * clock during suspend by adjusting its prescalar and divisor. diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/sama5.c similarity index 54% rename from arch/arm/mach-at91/board-dt-sama5.c rename to arch/arm/mach-at91/sama5.c index 97f7367d32b8..03dcb441f3d2 100644 --- a/arch/arm/mach-at91/board-dt-sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -1,5 +1,5 @@ /* - * Setup code for SAMA5 Evaluation Kits with Device Tree support + * Setup code for SAMA5 * * Copyright (C) 2013 Atmel, * 2013 Ludovic Desroches @@ -19,6 +19,8 @@ #include #include +#include + #include #include #include @@ -47,6 +49,7 @@ static void __init sama5_dt_device_init(void) } of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + at91sam9x5_pm_init(); } static const char *sama5_dt_board_compat[] __initconst = { @@ -54,23 +57,54 @@ static const char *sama5_dt_board_compat[] __initconst = { NULL }; -DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)") +DT_MACHINE_START(sama5_dt, "Atmel SAMA5") /* Maintainer: Atmel */ .map_io = at91_map_io, - .init_early = at91_dt_initialize, .init_machine = sama5_dt_device_init, .dt_compat = sama5_dt_board_compat, MACHINE_END +static struct map_desc at91_io_desc[] __initdata = { + { + .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_MPDDRC), + .pfn = __phys_to_pfn(SAMA5D4_BASE_MPDDRC), + .length = SZ_512, + .type = MT_DEVICE, + }, + { + .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_PMC), + .pfn = __phys_to_pfn(SAMA5D4_BASE_PMC), + .length = SZ_512, + .type = MT_DEVICE, + }, + { /* On sama5d4, we use USART3 as serial console */ + .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_USART3), + .pfn = __phys_to_pfn(SAMA5D4_BASE_USART3), + .length = SZ_256, + .type = MT_DEVICE, + }, + { /* A bunch of peripheral with fine grained IO space */ + .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_SYS2), + .pfn = __phys_to_pfn(SAMA5D4_BASE_SYS2), + .length = SZ_2K, + .type = MT_DEVICE, + }, +}; + +static void __init sama5_alt_map_io(void) +{ + at91_alt_map_io(); + iotable_init(at91_io_desc, ARRAY_SIZE(at91_io_desc)); +} + static const char *sama5_alt_dt_board_compat[] __initconst = { "atmel,sama5d4", NULL }; -DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5 (Device Tree)") +DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5") /* Maintainer: Atmel */ - .map_io = at91_alt_map_io, - .init_early = at91_dt_initialize, + .map_io = sama5_alt_map_io, .init_machine = sama5_dt_device_init, .dt_compat = sama5_alt_dt_board_compat, .l2c_aux_mask = ~0UL, diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c deleted file mode 100644 index ae58feada72b..000000000000 --- a/arch/arm/mach-at91/sama5d3.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Chip-specific setup code for the SAMA5D3 family - * - * Copyright (C) 2013 Atmel, - * 2013 Ludovic Desroches - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "soc.h" -#include "generic.h" -#include "sam9_smc.h" - -/* -------------------------------------------------------------------- - * AT91SAM9x5 processor initialization - * -------------------------------------------------------------------- */ - -static void __init sama5d3_map_io(void) -{ - at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE); -} - -AT91_SOC_START(sama5d3) - .map_io = sama5d3_map_io, -AT91_SOC_END diff --git a/arch/arm/mach-at91/sama5d4.c b/arch/arm/mach-at91/sama5d4.c deleted file mode 100644 index 7638509639f4..000000000000 --- a/arch/arm/mach-at91/sama5d4.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Chip-specific setup code for the SAMA5D4 family - * - * Copyright (C) 2013 Atmel Corporation, - * Nicolas Ferre - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "soc.h" -#include "generic.h" -#include "sam9_smc.h" - -/* -------------------------------------------------------------------- - * Processor initialization - * -------------------------------------------------------------------- */ -static struct map_desc at91_io_desc[] __initdata = { - { - .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_MPDDRC), - .pfn = __phys_to_pfn(SAMA5D4_BASE_MPDDRC), - .length = SZ_512, - .type = MT_DEVICE, - }, - { - .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_PMC), - .pfn = __phys_to_pfn(SAMA5D4_BASE_PMC), - .length = SZ_512, - .type = MT_DEVICE, - }, - { /* On sama5d4, we use USART3 as serial console */ - .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_USART3), - .pfn = __phys_to_pfn(SAMA5D4_BASE_USART3), - .length = SZ_256, - .type = MT_DEVICE, - }, - { /* A bunch of peripheral with fine grained IO space */ - .virtual = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_SYS2), - .pfn = __phys_to_pfn(SAMA5D4_BASE_SYS2), - .length = SZ_2K, - .type = MT_DEVICE, - }, -}; - - -static void __init sama5d4_map_io(void) -{ - iotable_init(at91_io_desc, ARRAY_SIZE(at91_io_desc)); - at91_init_sram(0, SAMA5D4_NS_SRAM_BASE, SAMA5D4_NS_SRAM_SIZE); -} - -AT91_SOC_START(sama5d4) - .map_io = sama5d4_map_io, -AT91_SOC_END diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index e3c21b458bb8..4e58bc90ed21 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -22,38 +22,12 @@ #include #include -#include "soc.h" #include "generic.h" #include "pm.h" -struct at91_init_soc __initdata at91_boot_soc; - struct at91_socinfo at91_soc_initdata; EXPORT_SYMBOL(at91_soc_initdata); -void __iomem *at91_ramc_base[2]; -EXPORT_SYMBOL_GPL(at91_ramc_base); - -static struct map_desc sram_desc[2] __initdata; - -void __init at91_init_sram(int bank, unsigned long base, unsigned int length) -{ - struct map_desc *desc = &sram_desc[bank]; - - desc->virtual = (unsigned long)AT91_IO_VIRT_BASE - length; - if (bank > 0) - desc->virtual -= sram_desc[bank - 1].length; - - desc->pfn = __phys_to_pfn(base); - desc->length = length; - desc->type = MT_MEMORY_RWX_NONCACHED; - - pr_info("sram at 0x%lx of 0x%x mapped at 0x%lx\n", - base, length, desc->virtual); - - iotable_init(desc, 1); -} - static struct map_desc at91_io_desc __initdata __maybe_unused = { .virtual = (unsigned long)AT91_VA_BASE_SYS, .pfn = __phys_to_pfn(AT91_BASE_SYS), @@ -80,61 +54,51 @@ static void __init soc_detect(u32 dbgu_base) at91_soc_initdata.type = AT91_SOC_RM9200; if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_UNKNOWN) at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; - at91_boot_soc = at91rm9200_soc; break; case ARCH_ID_AT91SAM9260: at91_soc_initdata.type = AT91_SOC_SAM9260; at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; - at91_boot_soc = at91sam9260_soc; break; case ARCH_ID_AT91SAM9261: at91_soc_initdata.type = AT91_SOC_SAM9261; at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; - at91_boot_soc = at91sam9261_soc; break; case ARCH_ID_AT91SAM9263: at91_soc_initdata.type = AT91_SOC_SAM9263; at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; - at91_boot_soc = at91sam9263_soc; break; case ARCH_ID_AT91SAM9G20: at91_soc_initdata.type = AT91_SOC_SAM9G20; at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; - at91_boot_soc = at91sam9260_soc; break; case ARCH_ID_AT91SAM9G45: at91_soc_initdata.type = AT91_SOC_SAM9G45; if (cidr == ARCH_ID_AT91SAM9G45ES) at91_soc_initdata.subtype = AT91_SOC_SAM9G45ES; - at91_boot_soc = at91sam9g45_soc; break; case ARCH_ID_AT91SAM9RL64: at91_soc_initdata.type = AT91_SOC_SAM9RL; at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; - at91_boot_soc = at91sam9rl_soc; break; case ARCH_ID_AT91SAM9X5: at91_soc_initdata.type = AT91_SOC_SAM9X5; - at91_boot_soc = at91sam9x5_soc; break; case ARCH_ID_AT91SAM9N12: at91_soc_initdata.type = AT91_SOC_SAM9N12; - at91_boot_soc = at91sam9n12_soc; break; case ARCH_ID_SAMA5: at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID); if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) { at91_soc_initdata.type = AT91_SOC_SAMA5D3; - at91_boot_soc = sama5d3_soc; } break; } @@ -143,13 +107,11 @@ static void __init soc_detect(u32 dbgu_base) if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; - at91_boot_soc = at91sam9261_soc; } /* at91sam9xe */ else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) { at91_soc_initdata.type = AT91_SOC_SAM9260; at91_soc_initdata.subtype = AT91_SOC_SAM9XE; - at91_boot_soc = at91sam9260_soc; } if (!at91_soc_is_detected()) @@ -229,10 +191,8 @@ static void __init alt_soc_detect(u32 dbgu_base) at91_soc_initdata.exid = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_EXID); if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) { at91_soc_initdata.type = AT91_SOC_SAMA5D3; - at91_boot_soc = sama5d3_soc; } else if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D4) { at91_soc_initdata.type = AT91_SOC_SAMA5D4; - at91_boot_soc = sama5d4_soc; } break; } @@ -338,12 +298,6 @@ void __init at91_map_io(void) if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE) pr_info("Detected soc subtype: %s\n", at91_get_soc_subtype(&at91_soc_initdata)); - - if (!at91_soc_is_enabled()) - panic(pr_fmt("Soc not enabled")); - - if (at91_boot_soc.map_io) - at91_boot_soc.map_io(); } void __init at91_alt_map_io(void) @@ -363,12 +317,6 @@ void __init at91_alt_map_io(void) if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE) pr_info("AT91: Detected soc subtype: %s\n", at91_get_soc_subtype(&at91_soc_initdata)); - - if (!at91_soc_is_enabled()) - panic("AT91: Soc not enabled"); - - if (at91_boot_soc.map_io) - at91_boot_soc.map_io(); } void __iomem *at91_matrix_base; @@ -380,48 +328,3 @@ void __init at91_ioremap_matrix(u32 base_addr) if (!at91_matrix_base) panic(pr_fmt("Impossible to ioremap at91_matrix_base\n")); } - -static struct of_device_id ramc_ids[] = { - { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, - { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, - { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, - { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby }, - { /*sentinel*/ } -}; - -static void at91_dt_ramc(void) -{ - struct device_node *np; - const struct of_device_id *of_id; - int idx = 0; - const void *standby = NULL; - - for_each_matching_node_and_match(np, ramc_ids, &of_id) { - at91_ramc_base[idx] = of_iomap(np, 0); - if (!at91_ramc_base[idx]) - panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx); - - if (!standby) - standby = of_id->data; - - idx++; - } - - if (!idx) - panic(pr_fmt("unable to find compatible ram controller node in dtb\n")); - - if (!standby) { - pr_warn("ramc no standby function available\n"); - return; - } - - at91_pm_set_standby(standby); -} - -void __init at91_dt_initialize(void) -{ - at91_dt_ramc(); - - if (at91_boot_soc.init) - at91_boot_soc.init(); -} diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h deleted file mode 100644 index ae6c0b2f1146..000000000000 --- a/arch/arm/mach-at91/soc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD - * - * Under GPLv2 - */ - -struct at91_init_soc { - int builtin; - void (*map_io)(void); - void (*init)(void); -}; - -extern struct at91_init_soc at91_boot_soc; -extern struct at91_init_soc at91rm9200_soc; -extern struct at91_init_soc at91sam9260_soc; -extern struct at91_init_soc at91sam9261_soc; -extern struct at91_init_soc at91sam9263_soc; -extern struct at91_init_soc at91sam9g45_soc; -extern struct at91_init_soc at91sam9rl_soc; -extern struct at91_init_soc at91sam9x5_soc; -extern struct at91_init_soc at91sam9n12_soc; -extern struct at91_init_soc sama5d3_soc; -extern struct at91_init_soc sama5d4_soc; - -#define AT91_SOC_START(_name) \ -struct at91_init_soc __initdata _name##_soc \ - __used \ - = { \ - .builtin = 1, \ - -#define AT91_SOC_END \ -}; - -static inline int at91_soc_is_enabled(void) -{ - return at91_boot_soc.builtin; -} - -#if !defined(CONFIG_SOC_AT91RM9200) -#define at91rm9200_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9260) -#define at91sam9260_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9261) -#define at91sam9261_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9263) -#define at91sam9263_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9G45) -#define at91sam9g45_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9RL) -#define at91sam9rl_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9X5) -#define at91sam9x5_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_AT91SAM9N12) -#define at91sam9n12_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_SAMA5D3) -#define sama5d3_soc at91_boot_soc -#endif - -#if !defined(CONFIG_SOC_SAMA5D4) -#define sama5d4_soc at91_boot_soc -#endif diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c index 31c87a284a34..e209e6fc7caf 100644 --- a/arch/arm/mach-bcm/platsmp-brcmstb.c +++ b/arch/arm/mach-bcm/platsmp-brcmstb.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -94,10 +95,35 @@ static u32 pwr_ctrl_rd(u32 cpu) return readl_relaxed(base); } -static void pwr_ctrl_wr(u32 cpu, u32 val) +static void pwr_ctrl_set(unsigned int cpu, u32 val, u32 mask) { void __iomem *base = pwr_ctrl_get_base(cpu); - writel(val, base); + writel((readl(base) & mask) | val, base); +} + +static void pwr_ctrl_clr(unsigned int cpu, u32 val, u32 mask) +{ + void __iomem *base = pwr_ctrl_get_base(cpu); + writel((readl(base) & mask) & ~val, base); +} + +#define POLL_TMOUT_MS 500 +static int pwr_ctrl_wait_tmout(unsigned int cpu, u32 set, u32 mask) +{ + const unsigned long timeo = jiffies + msecs_to_jiffies(POLL_TMOUT_MS); + u32 tmp; + + do { + tmp = pwr_ctrl_rd(cpu) & mask; + if (!set == !tmp) + return 0; + } while (time_before(jiffies, timeo)); + + tmp = pwr_ctrl_rd(cpu) & mask; + if (!set == !tmp) + return 0; + + return -ETIMEDOUT; } static void cpu_rst_cfg_set(u32 cpu, int set) @@ -139,15 +165,22 @@ static void brcmstb_cpu_power_on(u32 cpu) * The secondary cores power was cut, so we must go through * power-on initialization. */ - u32 tmp; + pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, 0xffffff00); + pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1); + pwr_ctrl_set(cpu, ZONE_RESERVED_1_MASK, -1); - /* Request zone power up */ - pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK); + pwr_ctrl_set(cpu, ZONE_MAN_MEM_PWR_MASK, -1); - /* Wait for the power up FSM to complete */ - do { - tmp = pwr_ctrl_rd(cpu); - } while (!(tmp & ZONE_PWR_ON_STATE_MASK)); + if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_MEM_PWR_STATE_MASK)) + panic("ZONE_MEM_PWR_STATE_MASK set timeout"); + + pwr_ctrl_set(cpu, ZONE_MAN_CLKEN_MASK, -1); + + if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_DPG_PWR_STATE_MASK)) + panic("ZONE_DPG_PWR_STATE_MASK set timeout"); + + pwr_ctrl_clr(cpu, ZONE_MAN_ISO_CNTL_MASK, -1); + pwr_ctrl_set(cpu, ZONE_MAN_RESET_CNTL_MASK, -1); } static int brcmstb_cpu_get_power_state(u32 cpu) @@ -174,25 +207,33 @@ static void brcmstb_cpu_die(u32 cpu) static int brcmstb_cpu_kill(u32 cpu) { - u32 tmp; + /* + * Ordinarily, the hardware forbids power-down of CPU0 (which is good + * because it is the boot CPU), but this is not true when using BPCM + * manual mode. Consequently, we must avoid turning off CPU0 here to + * ensure that TI2C master reset will work. + */ + if (cpu == 0) { + pr_warn("SMP: refusing to power off CPU0\n"); + return 1; + } while (per_cpu_sw_state_rd(cpu)) ; - /* Program zone reset */ - pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK | - ZONE_PWR_DN_REQ_MASK); + pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1); + pwr_ctrl_clr(cpu, ZONE_MAN_RESET_CNTL_MASK, -1); + pwr_ctrl_clr(cpu, ZONE_MAN_CLKEN_MASK, -1); + pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, -1); + pwr_ctrl_clr(cpu, ZONE_MAN_MEM_PWR_MASK, -1); - /* Verify zone reset */ - tmp = pwr_ctrl_rd(cpu); - if (!(tmp & ZONE_RESET_STATE_MASK)) - pr_err("%s: Zone reset bit for CPU %d not asserted!\n", - __func__, cpu); + if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_MEM_PWR_STATE_MASK)) + panic("ZONE_MEM_PWR_STATE_MASK clear timeout"); - /* Wait for power down */ - do { - tmp = pwr_ctrl_rd(cpu); - } while (!(tmp & ZONE_PWR_OFF_STATE_MASK)); + pwr_ctrl_clr(cpu, ZONE_RESERVED_1_MASK, -1); + + if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_DPG_PWR_STATE_MASK)) + panic("ZONE_DPG_PWR_STATE_MASK clear timeout"); /* Flush pipeline before resetting CPU */ mb(); diff --git a/arch/arm/mach-digicolor/Kconfig b/arch/arm/mach-digicolor/Kconfig new file mode 100644 index 000000000000..4f36d8d2bc57 --- /dev/null +++ b/arch/arm/mach-digicolor/Kconfig @@ -0,0 +1,7 @@ +config ARCH_DIGICOLOR + bool "Conexant Digicolor SoC Support" + depends on ARCH_MULTI_V7 + select CLKSRC_MMIO + select DIGICOLOR_TIMER + select GENERIC_IRQ_CHIP + select MFD_SYSCON diff --git a/arch/arm/mach-digicolor/Makefile b/arch/arm/mach-digicolor/Makefile new file mode 100644 index 000000000000..3d8a1d228408 --- /dev/null +++ b/arch/arm/mach-digicolor/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_DIGICOLOR) += digicolor.o diff --git a/arch/arm/mach-digicolor/digicolor.c b/arch/arm/mach-digicolor/digicolor.c new file mode 100644 index 000000000000..cfc88d1caa47 --- /dev/null +++ b/arch/arm/mach-digicolor/digicolor.c @@ -0,0 +1,18 @@ +/* + * Support for Conexant Digicolor SoCs + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include + +static const char *digicolor_dt_compat[] __initconst = { + "cnxt,cx92755", + NULL, +}; + +DT_MACHINE_START(DIGICOLOR, "Conexant Digicolor (Flattened Device Tree)") + .dt_compat = digicolor_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 2c844393cc4b..78eca99b98d1 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -247,6 +247,7 @@ static void __init exynos_reserve(void) "samsung,mfc-v5", "samsung,mfc-v6", "samsung,mfc-v7", + "samsung,mfc-v8", }; for (i = 0; i < ARRAY_SIZE(mfc_mem); i++) diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index b5f4406fc1b5..eb461e1c325a 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h @@ -160,12 +160,14 @@ #define EXYNOS5_L2RSTDISABLE_VALUE BIT(3) #define S5P_PAD_RET_MAUDIO_OPTION 0x3028 +#define S5P_PAD_RET_MMC2_OPTION 0x30c8 #define S5P_PAD_RET_GPIO_OPTION 0x3108 #define S5P_PAD_RET_UART_OPTION 0x3128 #define S5P_PAD_RET_MMCA_OPTION 0x3148 #define S5P_PAD_RET_MMCB_OPTION 0x3168 #define S5P_PAD_RET_EBIA_OPTION 0x3188 #define S5P_PAD_RET_EBIB_OPTION 0x31A8 +#define S5P_PAD_RET_SPI_OPTION 0x31c8 #define S5P_PS_HOLD_CONTROL 0x330C #define S5P_PS_HOLD_EN (1 << 31) @@ -326,6 +328,7 @@ (EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80)) #define EXYNOS3_ARM_COMMON_OPTION 0x2408 +#define EXYNOS3_ARM_L2_OPTION 0x2608 #define EXYNOS3_TOP_PWR_OPTION 0x2C48 #define EXYNOS3_CORE_TOP_PWR_OPTION 0x2CA8 #define EXYNOS3_XUSBXTI_DURATION 0x341C diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 342797b9bf3b..82e6b6fba23f 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -86,6 +86,12 @@ static unsigned int exynos_pmu_spare3; static u32 exynos_irqwake_intmask = 0xffffffff; +static const struct exynos_wkup_irq exynos3250_wkup_irq[] = { + { 73, BIT(1) }, /* RTC alarm */ + { 74, BIT(2) }, /* RTC tick */ + { /* sentinel */ }, +}; + static const struct exynos_wkup_irq exynos4_wkup_irq[] = { { 76, BIT(1) }, /* RTC alarm */ { 77, BIT(2) }, /* RTC tick */ @@ -109,6 +115,19 @@ unsigned int exynos_release_ret_regs[] = { REG_TABLE_END, }; +unsigned int exynos3250_release_ret_regs[] = { + S5P_PAD_RET_MAUDIO_OPTION, + S5P_PAD_RET_GPIO_OPTION, + S5P_PAD_RET_UART_OPTION, + S5P_PAD_RET_MMCA_OPTION, + S5P_PAD_RET_MMCB_OPTION, + S5P_PAD_RET_EBIA_OPTION, + S5P_PAD_RET_EBIB_OPTION, + S5P_PAD_RET_MMC2_OPTION, + S5P_PAD_RET_SPI_OPTION, + REG_TABLE_END, +}; + unsigned int exynos5420_release_ret_regs[] = { EXYNOS_PAD_RET_DRAM_OPTION, EXYNOS_PAD_RET_MAUDIO_OPTION, @@ -168,6 +187,12 @@ static int exynos_cpu_suspend(unsigned long arg) return exynos_cpu_do_idle(); } +static int exynos3250_cpu_suspend(unsigned long arg) +{ + flush_cache_all(); + return exynos_cpu_do_idle(); +} + static int exynos5420_cpu_suspend(unsigned long arg) { /* MCPM works with HW CPU identifiers */ @@ -225,6 +250,23 @@ static void exynos_pm_prepare(void) pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); } +static void exynos3250_pm_prepare(void) +{ + unsigned int tmp; + + /* Set wake-up mask registers */ + exynos_pm_set_wakeup_mask(); + + tmp = pmu_raw_readl(EXYNOS3_ARM_L2_OPTION); + tmp &= ~EXYNOS5_OPTION_USE_RETENTION; + pmu_raw_writel(tmp, EXYNOS3_ARM_L2_OPTION); + + exynos_pm_enter_sleep_mode(); + + /* ensure at least INFORM0 has the resume address */ + pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); +} + static void exynos5420_pm_prepare(void) { unsigned int tmp; @@ -339,6 +381,28 @@ static void exynos_pm_resume(void) pmu_raw_writel(0x0, S5P_INFORM1); } +static void exynos3250_pm_resume(void) +{ + u32 cpuid = read_cpuid_part(); + + if (exynos_pm_central_resume()) + goto early_wakeup; + + /* For release retention */ + exynos_pm_release_retention(); + + pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION); + + if (call_firmware_op(resume) == -ENOSYS + && cpuid == ARM_CPU_PART_CORTEX_A9) + exynos_cpu_restore_register(); + +early_wakeup: + + /* Clear SLEEP mode set in INFORM1 */ + pmu_raw_writel(0x0, S5P_INFORM1); +} + static void exynos5420_prepare_pm_resume(void) { if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) @@ -478,6 +542,16 @@ static const struct platform_suspend_ops exynos_suspend_ops = { .valid = suspend_valid_only_mem, }; +static const struct exynos_pm_data exynos3250_pm_data = { + .wkup_irq = exynos3250_wkup_irq, + .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), + .release_ret_regs = exynos3250_release_ret_regs, + .pm_suspend = exynos_pm_suspend, + .pm_resume = exynos3250_pm_resume, + .pm_prepare = exynos3250_pm_prepare, + .cpu_suspend = exynos3250_cpu_suspend, +}; + static const struct exynos_pm_data exynos4_pm_data = { .wkup_irq = exynos4_wkup_irq, .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), @@ -511,6 +585,9 @@ static struct exynos_pm_data exynos5420_pm_data = { static struct of_device_id exynos_pmu_of_device_ids[] = { { + .compatible = "samsung,exynos3250-pmu", + .data = &exynos3250_pm_data, + }, { .compatible = "samsung,exynos4210-pmu", .data = &exynos4_pm_data, }, { diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index cd19433f76d3..83061ad0e282 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -22,6 +22,14 @@ config ARCH_HI3xxx help Support for Hisilicon Hi36xx SoC family +config ARCH_HIP01 + bool "Hisilicon HIP01 family" if ARCH_MULTI_V7 + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select ARM_GLOBAL_TIMER + help + Support for Hisilicon HIP01 SoC family + config ARCH_HIP04 bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7 select ARM_ERRATA_798181 if SMP diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h index 88b1f487d065..92a682d8e939 100644 --- a/arch/arm/mach-hisi/core.h +++ b/arch/arm/mach-hisi/core.h @@ -12,9 +12,12 @@ extern void hi3xxx_cpu_die(unsigned int cpu); extern int hi3xxx_cpu_kill(unsigned int cpu); extern void hi3xxx_set_cpu(int cpu, bool enable); -extern void hix5hd2_secondary_startup(void); +extern void hisi_secondary_startup(void); extern struct smp_operations hix5hd2_smp_ops; extern void hix5hd2_set_cpu(int cpu, bool enable); extern void hix5hd2_cpu_die(unsigned int cpu); +extern struct smp_operations hip01_smp_ops; +extern void hip01_set_cpu(int cpu, bool enable); +extern void hip01_cpu_die(unsigned int cpu); #endif diff --git a/arch/arm/mach-hisi/headsmp.S b/arch/arm/mach-hisi/headsmp.S index 278889c00b77..81e35b159e75 100644 --- a/arch/arm/mach-hisi/headsmp.S +++ b/arch/arm/mach-hisi/headsmp.S @@ -11,6 +11,6 @@ __CPUINIT -ENTRY(hix5hd2_secondary_startup) +ENTRY(hisi_secondary_startup) bl v7_invalidate_l1 b secondary_startup diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c index 7744c351bbfd..76b907078b58 100644 --- a/arch/arm/mach-hisi/hisilicon.c +++ b/arch/arm/mach-hisi/hisilicon.c @@ -72,3 +72,13 @@ static const char *hip04_compat[] __initconst = { DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)") .dt_compat = hip04_compat, MACHINE_END + +static const char *hip01_compat[] __initconst = { + "hisilicon,hip01", + "hisilicon,hip01-ca9x2", + NULL, +}; + +DT_MACHINE_START(HIP01, "Hisilicon HIP01 (Flattened Device Tree)") + .dt_compat = hip01_compat, +MACHINE_END diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c index 84e6919f68c7..a129aae72602 100644 --- a/arch/arm/mach-hisi/hotplug.c +++ b/arch/arm/mach-hisi/hotplug.c @@ -65,6 +65,9 @@ #define PMC0_CPU1_PMC_ENABLE (1 << 7) #define PMC0_CPU1_POWERDOWN (1 << 3) +#define HIP01_PERI9 0x50 +#define PERI9_CPU1_RESET (1 << 1) + enum { HI3620_CTRL, ERROR_CTRL, @@ -209,6 +212,34 @@ void hix5hd2_set_cpu(int cpu, bool enable) } } +void hip01_set_cpu(int cpu, bool enable) +{ + unsigned int temp; + struct device_node *np; + + if (!ctrl_base) { + np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); + if (np) + ctrl_base = of_iomap(np, 0); + else + BUG(); + } + + if (enable) { + /* reset on CPU1 */ + temp = readl_relaxed(ctrl_base + HIP01_PERI9); + temp |= PERI9_CPU1_RESET; + writel_relaxed(temp, ctrl_base + HIP01_PERI9); + + udelay(50); + + /* unreset on CPU1 */ + temp = readl_relaxed(ctrl_base + HIP01_PERI9); + temp &= ~PERI9_CPU1_RESET; + writel_relaxed(temp, ctrl_base + HIP01_PERI9); + } +} + static inline void cpu_enter_lowpower(void) { unsigned int v; diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c index 575dd8285f1f..8880c8e8b296 100644 --- a/arch/arm/mach-hisi/platsmp.c +++ b/arch/arm/mach-hisi/platsmp.c @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include +#include #include "core.h" @@ -96,7 +98,7 @@ struct smp_operations hi3xxx_smp_ops __initdata = { #endif }; -static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus) +static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus) { hisi_enable_scu_a9(); } @@ -116,7 +118,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) { phys_addr_t jumpaddr; - jumpaddr = virt_to_phys(hix5hd2_secondary_startup); + jumpaddr = virt_to_phys(hisi_secondary_startup); hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); hix5hd2_set_cpu(cpu, true); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); @@ -125,12 +127,60 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) struct smp_operations hix5hd2_smp_ops __initdata = { - .smp_prepare_cpus = hix5hd2_smp_prepare_cpus, + .smp_prepare_cpus = hisi_common_smp_prepare_cpus, .smp_boot_secondary = hix5hd2_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = hix5hd2_cpu_die, #endif }; + +#define SC_SCTL_REMAP_CLR 0x00000100 +#define HIP01_BOOT_ADDRESS 0x80000000 +#define REG_SC_CTRL 0x000 + +void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) +{ + void __iomem *virt; + + virt = phys_to_virt(start_addr); + + writel_relaxed(0xe51ff004, virt); + writel_relaxed(jump_addr, virt + 4); +} + +static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + phys_addr_t jumpaddr; + unsigned int remap_reg_value = 0; + struct device_node *node; + + + jumpaddr = virt_to_phys(hisi_secondary_startup); + hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr); + + node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); + if (WARN_ON(!node)) + return -1; + ctrl_base = of_iomap(node, 0); + + /* set the secondary core boot from DDR */ + remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL); + barrier(); + remap_reg_value |= SC_SCTL_REMAP_CLR; + barrier(); + writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL); + + hip01_set_cpu(cpu, true); + + return 0; +} + +struct smp_operations hip01_smp_ops __initdata = { + .smp_prepare_cpus = hisi_common_smp_prepare_cpus, + .smp_boot_secondary = hip01_boot_secondary, +}; + CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops); CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops); +CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops); diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index f5ac685a29fc..8d1b10180908 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o -# i.MX6SX reuses i.MX6Q cpuidle driver -obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o endif ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c index 5a75cdc81891..8935bff99fe7 100644 --- a/arch/arm/mach-imx/clk-gate2.c +++ b/arch/arm/mach-imx/clk-gate2.c @@ -96,15 +96,30 @@ static int clk_gate2_is_enabled(struct clk_hw *hw) { struct clk_gate2 *gate = to_clk_gate2(hw); - if (gate->share_count) - return !!__clk_get_enable_count(hw->clk); - else - return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); + return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); +} + +static void clk_gate2_disable_unused(struct clk_hw *hw) +{ + struct clk_gate2 *gate = to_clk_gate2(hw); + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(gate->lock, flags); + + if (!gate->share_count || *gate->share_count == 0) { + reg = readl(gate->reg); + reg &= ~(3 << gate->bit_idx); + writel(reg, gate->reg); + } + + spin_unlock_irqrestore(gate->lock, flags); } static struct clk_ops clk_gate2_ops = { .enable = clk_gate2_enable, .disable = clk_gate2_disable, + .disable_unused = clk_gate2_disable_unused, .is_enabled = clk_gate2_is_enabled, }; diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 2daef619d053..d04a430607b8 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -386,7 +386,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); clk[IMX6QDL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai); - clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ipg", base + 0x6c, 16, &share_count_esai); + clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai); clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai); clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 0ad6e5442fd8..641ebc508920 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -31,6 +31,7 @@ * @base: base address of PLL registers * @powerup_set: set POWER bit to power up the PLL * @div_mask: mask of divider bits + * @div_shift: shift of divider bits * * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 * is actually a multiplier, and always sits at bit 0. @@ -40,6 +41,7 @@ struct clk_pllv3 { void __iomem *base; bool powerup_set; u32 div_mask; + u32 div_shift; }; #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) @@ -97,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 div = readl_relaxed(pll->base) & pll->div_mask; + u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask; return (div == 1) ? parent_rate * 22 : parent_rate * 20; } @@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; val = readl_relaxed(pll->base); - val &= ~pll->div_mask; - val |= div; + val &= ~(pll->div_mask << pll->div_shift); + val |= (div << pll->div_shift); writel_relaxed(val, pll->base); return clk_pllv3_wait_lock(pll); @@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, case IMX_PLLV3_SYS: ops = &clk_pllv3_sys_ops; break; + case IMX_PLLV3_USB_VF610: + pll->div_shift = 1; case IMX_PLLV3_USB: ops = &clk_pllv3_ops; pll->powerup_set = true; diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index 5937ddee1a99..61876ed6e11e 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c @@ -172,11 +172,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); - clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1); + clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2); clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); - clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1); + clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2); clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); @@ -267,6 +267,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8)); clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9)); clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10)); + clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9)); + clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10)); clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); @@ -380,6 +382,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1)); clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2)); + clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7)); + imx_check_clocks(clk, ARRAY_SIZE(clk)); clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]); diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 5ef82e2f8fc5..6a07903a28bc 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -20,6 +20,7 @@ enum imx_pllv3_type { IMX_PLLV3_GENERIC, IMX_PLLV3_SYS, IMX_PLLV3_USB, + IMX_PLLV3_USB_VF610, IMX_PLLV3_AV, IMX_PLLV3_ENET, }; diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index cfcdb623d78f..1028b6c505c4 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev); unsigned int imx_get_soc_revision(void); void imx_init_revision_from_anatop(void); struct device *imx_soc_device_init(void); +void imx6_enable_rbc(bool enable); +void imx_gpc_set_arm_power_in_lpm(bool power_off); +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw); +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw); enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c new file mode 100644 index 000000000000..5a36722b089d --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "cpuidle.h" + +static int imx6sx_idle_finish(unsigned long val) +{ + cpu_do_idle(); + + return 0; +} + +static int imx6sx_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + imx6q_set_lpm(WAIT_UNCLOCKED); + + switch (index) { + case 1: + cpu_do_idle(); + break; + case 2: + imx6_enable_rbc(true); + imx_gpc_set_arm_power_in_lpm(true); + imx_set_cpu_jump(0, v7_cpu_resume); + /* Need to notify there is a cpu pm operation. */ + cpu_pm_enter(); + cpu_cluster_pm_enter(); + + cpu_suspend(0, imx6sx_idle_finish); + + cpu_cluster_pm_exit(); + cpu_pm_exit(); + imx_gpc_set_arm_power_in_lpm(false); + imx6_enable_rbc(false); + break; + default: + break; + } + + imx6q_set_lpm(WAIT_CLOCKED); + + return index; +} + +static struct cpuidle_driver imx6sx_cpuidle_driver = { + .name = "imx6sx_cpuidle", + .owner = THIS_MODULE, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIMER_STOP, + .enter = imx6sx_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + /* WAIT + ARM power off */ + { + /* + * ARM gating 31us * 5 + RBC clear 65us + * and some margin for SW execution, here set it + * to 300us. + */ + .exit_latency = 300, + .target_residency = 500, + .enter = imx6sx_enter_wait, + .name = "LOW-POWER-IDLE", + .desc = "ARM power off", + }, + }, + .state_count = 3, + .safe_state_index = 0, +}; + +int __init imx6sx_cpuidle_init(void) +{ + imx6_enable_rbc(false); + /* + * set ARM power up/down timing to the fastest, + * sw2iso and sw can be set to one 32K cycle = 31us + * except for power up sw2iso which need to be + * larger than LDO ramp up time. + */ + imx_gpc_set_arm_power_up_timing(2, 1); + imx_gpc_set_arm_power_down_timing(1, 1); + + return cpuidle_register(&imx6sx_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index 24e33670417c..f9140128ba05 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -14,6 +14,7 @@ extern int imx5_cpuidle_init(void); extern int imx6q_cpuidle_init(void); extern int imx6sl_cpuidle_init(void); +extern int imx6sx_cpuidle_init(void); #else static inline int imx5_cpuidle_init(void) { @@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void) { return 0; } +static inline int imx6sx_cpuidle_init(void) +{ + return 0; +} #endif diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 5f3602ec74fa..745caa18ab2c 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -20,6 +20,10 @@ #define GPC_IMR1 0x008 #define GPC_PGC_CPU_PDN 0x2a0 +#define GPC_PGC_CPU_PUPSCR 0x2a4 +#define GPC_PGC_CPU_PDNSCR 0x2a8 +#define GPC_PGC_SW2ISO_SHIFT 0x8 +#define GPC_PGC_SW_SHIFT 0x0 #define IMR_NUM 4 @@ -27,6 +31,23 @@ static void __iomem *gpc_base; static u32 gpc_wake_irqs[IMR_NUM]; static u32 gpc_saved_imrs[IMR_NUM]; +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR); +} + +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR); +} + +void imx_gpc_set_arm_power_in_lpm(bool power_off) +{ + writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN); +} + void imx_gpc_pre_suspend(bool arm_power_off) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1; @@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off) /* Tell GPC to power off ARM core when suspend */ if (arm_power_off) - writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(arm_power_off); for (i = 0; i < IMR_NUM; i++) { gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); @@ -48,7 +69,7 @@ void imx_gpc_post_resume(void) int i; /* Keep ARM core powered on for other low-power modes */ - writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(false); for (i = 0; i < IMR_NUM; i++) writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 5057d61298b7..4ad6e473cf83 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -329,7 +329,7 @@ static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev) if (dev_pm_opp_disable(cpu_dev, 852000000)) pr_warn("failed to disable 852 MHz OPP\n"); } - + iounmap(base); put_node: of_node_put(np); } diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 7a96c6577234..66988eb6a3a4 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void) static void __init imx6sx_init_late(void) { - imx6q_cpuidle_init(); + imx6sx_cpuidle_init(); if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index c11ab6a1dc87..2e7c75b66fe0 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -13,11 +13,14 @@ #include static const char * const vf610_dt_compat[] __initconst = { + "fsl,vf500", + "fsl,vf510", + "fsl,vf600", "fsl,vf610", NULL, }; -DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") +DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, .dt_compat = vf610_dt_compat, diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 5d2c1bd5f5ef..46fd695203c7 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable) writel_relaxed(val, ccm_base + CGPR); } -static void imx6q_enable_rbc(bool enable) +void imx6_enable_rbc(bool enable) { u32 val; @@ -359,17 +359,16 @@ static int imx6q_pm_enter(suspend_state_t state) * RBC setting, so we do NOT need to do that here. */ if (!imx6_suspend_in_ocram_fn) - imx6q_enable_rbc(true); + imx6_enable_rbc(true); imx_gpc_pre_suspend(true); imx_anatop_pre_suspend(); - imx_set_cpu_jump(0, v7_cpu_resume); /* Zzz ... */ cpu_suspend(0, imx6q_suspend_finish); if (cpu_is_imx6q() || cpu_is_imx6dl()) imx_smp_prepare(); imx_anatop_post_resume(); imx_gpc_post_resume(); - imx6q_enable_rbc(false); + imx6_enable_rbc(false); imx6q_enable_wb(false); imx6q_set_int_mem_clk_lpm(true); imx6q_set_lpm(WAIT_CLOCKED); diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig index f73f588f649c..f7e463ca0287 100644 --- a/arch/arm/mach-mediatek/Kconfig +++ b/arch/arm/mach-mediatek/Kconfig @@ -1,6 +1,26 @@ -config ARCH_MEDIATEK +menuconfig ARCH_MEDIATEK bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7 select ARM_GIC select MTK_TIMER help Support for Mediatek MT65xx & MT81xx SoCs + +if ARCH_MEDIATEK + +config MACH_MT6589 + bool "MediaTek MT6589 SoCs support" + default ARCH_MEDIATEK + +config MACH_MT6592 + bool "MediaTek MT6592 SoCs support" + default ARCH_MEDIATEK + +config MACH_MT8127 + bool "MediaTek MT8127 SoCs support" + default ARCH_MEDIATEK + +config MACH_MT8135 + bool "MediaTek MT8135 SoCs support" + default ARCH_MEDIATEK + +endif diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index ccef8806bb58..b5895f040caa 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "coherency.h" #include "mvebu-soc-id.h" @@ -76,54 +77,6 @@ int set_cpu_coherent(void) return ll_enable_coherency(); } -static inline void mvebu_hwcc_sync_io_barrier(void) -{ - writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET); - while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1); -} - -static dma_addr_t mvebu_hwcc_dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, - struct dma_attrs *attrs) -{ - if (dir != DMA_TO_DEVICE) - mvebu_hwcc_sync_io_barrier(); - return pfn_to_dma(dev, page_to_pfn(page)) + offset; -} - - -static void mvebu_hwcc_dma_unmap_page(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction dir, - struct dma_attrs *attrs) -{ - if (dir != DMA_TO_DEVICE) - mvebu_hwcc_sync_io_barrier(); -} - -static void mvebu_hwcc_dma_sync(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction dir) -{ - if (dir != DMA_TO_DEVICE) - mvebu_hwcc_sync_io_barrier(); -} - -static struct dma_map_ops mvebu_hwcc_dma_ops = { - .alloc = arm_dma_alloc, - .free = arm_dma_free, - .mmap = arm_dma_mmap, - .map_page = mvebu_hwcc_dma_map_page, - .unmap_page = mvebu_hwcc_dma_unmap_page, - .get_sgtable = arm_dma_get_sgtable, - .map_sg = arm_dma_map_sg, - .unmap_sg = arm_dma_unmap_sg, - .sync_single_for_cpu = mvebu_hwcc_dma_sync, - .sync_single_for_device = mvebu_hwcc_dma_sync, - .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu, - .sync_sg_for_device = arm_dma_sync_sg_for_device, - .set_dma_mask = arm_dma_set_mask, -}; - static int mvebu_hwcc_notifier(struct notifier_block *nb, unsigned long event, void *__dev) { @@ -131,7 +84,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb, if (event != BUS_NOTIFY_ADD_DEVICE) return NOTIFY_DONE; - set_dma_ops(dev, &mvebu_hwcc_dma_ops); + set_dma_ops(dev, &arm_coherent_dma_ops); return NOTIFY_OK; } @@ -253,14 +206,9 @@ static int coherency_type(void) return type; } -/* - * As a precaution, we currently completely disable hardware I/O - * coherency, until enough testing is done with automatic I/O - * synchronization barriers to validate that it is a proper solution. - */ int coherency_available(void) { - return false; + return coherency_type() != COHERENCY_FABRIC_TYPE_NONE; } int __init coherency_init(void) diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h index c16bb68ca81f..e124a0b82a3e 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.h +++ b/arch/arm/mach-mvebu/mvebu-soc-id.h @@ -20,10 +20,28 @@ #define MV78XX0_A0_REV 0x1 #define MV78XX0_B0_REV 0x2 +/* Amada 370 ID */ +#define ARMADA_370_DEV_ID 0x6710 + +/* Amada 370 Revision */ +#define ARMADA_370_A1_REV 0x1 + +/* Armada 375 ID */ +#define ARMADA_375_DEV_ID 0x6720 + /* Armada 375 */ #define ARMADA_375_Z1_REV 0x0 #define ARMADA_375_A0_REV 0x3 +/* Armada 38x ID */ +#define ARMADA_380_DEV_ID 0x6810 +#define ARMADA_385_DEV_ID 0x6820 +#define ARMADA_388_DEV_ID 0x6828 + +/* Armada 38x Revision */ +#define ARMADA_38x_Z1_REV 0x0 +#define ARMADA_38x_A0_REV 0x4 + #ifdef CONFIG_ARCH_MVEBU int mvebu_get_soc_id(u32 *dev, u32 *rev); #else diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index fb78744f546b..00d5d8f9f150 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -121,6 +121,7 @@ obj-$(CONFIG_ARCH_OMAP4) += $(omap-prcm-4-5-common) obj-$(CONFIG_SOC_OMAP5) += $(omap-prcm-4-5-common) obj-$(CONFIG_SOC_DRA7XX) += $(omap-prcm-4-5-common) am33xx-43xx-prcm-common += prm33xx.o cm33xx.o +obj-$(CONFIG_SOC_TI81XX) += $(am33xx-43xx-prcm-common) obj-$(CONFIG_SOC_AM33XX) += $(am33xx-43xx-prcm-common) obj-$(CONFIG_SOC_AM43XX) += $(omap-prcm-4-5-common) \ $(am33xx-43xx-prcm-common) @@ -171,6 +172,8 @@ obj-$(CONFIG_ARCH_OMAP4) += $(clockdomain-common) obj-$(CONFIG_ARCH_OMAP4) += clockdomains44xx_data.o obj-$(CONFIG_SOC_AM33XX) += $(clockdomain-common) obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o +obj-$(CONFIG_SOC_TI81XX) += $(clockdomain-common) +obj-$(CONFIG_SOC_TI81XX) += clockdomains81xx_data.o obj-$(CONFIG_SOC_AM43XX) += $(clockdomain-common) obj-$(CONFIG_SOC_AM43XX) += clockdomains43xx_data.o obj-$(CONFIG_SOC_OMAP5) += $(clockdomain-common) @@ -223,6 +226,7 @@ obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_43xx_ipblock_data.o obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_43xx_data.o obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_33xx_43xx_interconnect_data.o obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_33xx_43xx_ipblock_data.o +obj-$(CONFIG_SOC_TI81XX) += omap_hwmod_81xx_data.o obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 42b7f4c9169b..34ff14b7beab 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -162,6 +162,42 @@ DT_MACHINE_START(AM3517_DT, "Generic AM3517 (Flattened Device Tree)") MACHINE_END #endif +#ifdef CONFIG_SOC_TI81XX +static const char *const ti814x_boards_compat[] __initconst = { + "ti,dm8148", + "ti,dm814", + NULL, +}; + +DT_MACHINE_START(TI81XX_DT, "Generic ti814x (Flattened Device Tree)") + .reserve = omap_reserve, + .map_io = ti81xx_map_io, + .init_early = ti814x_init_early, + .init_machine = omap_generic_init, + .init_late = ti81xx_init_late, + .init_time = omap3_gptimer_timer_init, + .dt_compat = ti814x_boards_compat, + .restart = ti81xx_restart, +MACHINE_END + +static const char *const ti816x_boards_compat[] __initconst = { + "ti,dm8168", + "ti,dm816", + NULL, +}; + +DT_MACHINE_START(TI816X_DT, "Generic ti816x (Flattened Device Tree)") + .reserve = omap_reserve, + .map_io = ti81xx_map_io, + .init_early = ti816x_init_early, + .init_machine = omap_generic_init, + .init_late = ti81xx_init_late, + .init_time = omap3_gptimer_timer_init, + .dt_compat = ti816x_boards_compat, + .restart = ti81xx_restart, +MACHINE_END +#endif + #ifdef CONFIG_SOC_AM33XX static const char *const am33xx_boards_compat[] __initconst = { "ti,am33xx", diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 82c37b1becc4..77bab5fb6814 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -216,6 +216,7 @@ 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 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/clockdomains81xx_data.c b/arch/arm/mach-omap2/clockdomains81xx_data.c new file mode 100644 index 000000000000..ce2a82001d0d --- /dev/null +++ b/arch/arm/mach-omap2/clockdomains81xx_data.c @@ -0,0 +1,194 @@ +/* + * TI81XX Clock Domain data. + * + * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/ + * Copyright (C) 2013 SKTB SKiT, http://www.skitlab.ru/ + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_81XX_H +#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_81XX_H + +#include +#include + +#include "clockdomain.h" +#include "cm81xx.h" + +/* + * Note that 814x seems to have HWSUP_SWSUP for many clockdomains + * while 816x does not. According to the TRM, 816x only has HWSUP + * for ALWON_L3_FAST. Also note that the TI tree clockdomains81xx.h + * seems to have the related ifdef the wrong way around claiming + * 816x supports HWSUP while 814x does not. For now, we only set + * HWSUP for ALWON_L3_FAST as that seems to be supported for both + * dm814x and dm816x. + */ + +/* Common for 81xx */ + +static struct clockdomain alwon_l3_slow_81xx_clkdm = { + .name = "alwon_l3s_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_ALWON_L3_SLOW_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain alwon_l3_med_81xx_clkdm = { + .name = "alwon_l3_med_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_ALWON_L3_MED_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain alwon_l3_fast_81xx_clkdm = { + .name = "alwon_l3_fast_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_ALWON_L3_FAST_CLKDM, + .flags = CLKDM_CAN_HWSUP_SWSUP, +}; + +static struct clockdomain alwon_ethernet_81xx_clkdm = { + .name = "alwon_ethernet_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_ETHERNET_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain mmu_81xx_clkdm = { + .name = "mmu_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_MMU_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain mmu_cfg_81xx_clkdm = { + .name = "mmu_cfg_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_MMUCFG_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +/* 816x only */ + +static struct clockdomain alwon_mpu_816x_clkdm = { + .name = "alwon_mpu_clkdm", + .pwrdm = { .name = "alwon_pwrdm" }, + .cm_inst = TI81XX_CM_ALWON_MOD, + .clkdm_offs = TI81XX_CM_ALWON_MPU_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain active_gem_816x_clkdm = { + .name = "active_gem_clkdm", + .pwrdm = { .name = "active_pwrdm" }, + .cm_inst = TI816X_CM_ACTIVE_MOD, + .clkdm_offs = TI816X_CM_ACTIVE_GEM_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain ivahd0_816x_clkdm = { + .name = "ivahd0_clkdm", + .pwrdm = { .name = "ivahd0_pwrdm" }, + .cm_inst = TI816X_CM_IVAHD0_MOD, + .clkdm_offs = TI816X_CM_IVAHD0_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain ivahd1_816x_clkdm = { + .name = "ivahd1_clkdm", + .pwrdm = { .name = "ivahd1_pwrdm" }, + .cm_inst = TI816X_CM_IVAHD1_MOD, + .clkdm_offs = TI816X_CM_IVAHD1_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain ivahd2_816x_clkdm = { + .name = "ivahd2_clkdm", + .pwrdm = { .name = "ivahd2_pwrdm" }, + .cm_inst = TI816X_CM_IVAHD2_MOD, + .clkdm_offs = TI816X_CM_IVAHD2_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain sgx_816x_clkdm = { + .name = "sgx_clkdm", + .pwrdm = { .name = "sgx_pwrdm" }, + .cm_inst = TI816X_CM_SGX_MOD, + .clkdm_offs = TI816X_CM_SGX_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain default_l3_med_816x_clkdm = { + .name = "default_l3_med_clkdm", + .pwrdm = { .name = "default_pwrdm" }, + .cm_inst = TI816X_CM_DEFAULT_MOD, + .clkdm_offs = TI816X_CM_DEFAULT_L3_MED_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain default_ducati_816x_clkdm = { + .name = "default_ducati_clkdm", + .pwrdm = { .name = "default_pwrdm" }, + .cm_inst = TI816X_CM_DEFAULT_MOD, + .clkdm_offs = TI816X_CM_DEFAULT_DUCATI_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain default_pci_816x_clkdm = { + .name = "default_pci_clkdm", + .pwrdm = { .name = "default_pwrdm" }, + .cm_inst = TI816X_CM_DEFAULT_MOD, + .clkdm_offs = TI816X_CM_DEFAULT_PCI_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain default_l3_slow_816x_clkdm = { + .name = "default_l3_slow_clkdm", + .pwrdm = { .name = "default_pwrdm" }, + .cm_inst = TI816X_CM_DEFAULT_MOD, + .clkdm_offs = TI816X_CM_DEFAULT_L3_SLOW_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + +static struct clockdomain *clockdomains_ti81xx[] __initdata = { + &alwon_mpu_816x_clkdm, + &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, + &active_gem_816x_clkdm, + &ivahd0_816x_clkdm, + &ivahd1_816x_clkdm, + &ivahd2_816x_clkdm, + &sgx_816x_clkdm, + &default_l3_med_816x_clkdm, + &default_ducati_816x_clkdm, + &default_pci_816x_clkdm, + &default_l3_slow_816x_clkdm, + NULL, +}; + +void __init ti81xx_clockdomains_init(void) +{ + clkdm_register_platform_funcs(&am33xx_clkdm_operations); + clkdm_register_clkdms(clockdomains_ti81xx); + clkdm_complete_init(); +} +#endif diff --git a/arch/arm/mach-omap2/cm81xx.h b/arch/arm/mach-omap2/cm81xx.h new file mode 100644 index 000000000000..45cb407da222 --- /dev/null +++ b/arch/arm/mach-omap2/cm81xx.h @@ -0,0 +1,61 @@ +/* + * Clock domain register offsets for TI81XX. + * + * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/ + * Copyright (C) 2013 SKTB SKiT, http://www.skitlab.ru/ + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_CM_TI81XX_H +#define __ARCH_ARM_MACH_OMAP2_CM_TI81XX_H + +/* TI81XX common CM module offsets */ +#define TI81XX_CM_ALWON_MOD 0x1400 /* 1KB */ + +/* TI816X CM module offsets */ +#define TI816X_CM_ACTIVE_MOD 0x0400 /* 256B */ +#define TI816X_CM_DEFAULT_MOD 0x0500 /* 256B */ +#define TI816X_CM_IVAHD0_MOD 0x0600 /* 256B */ +#define TI816X_CM_IVAHD1_MOD 0x0700 /* 256B */ +#define TI816X_CM_IVAHD2_MOD 0x0800 /* 256B */ +#define TI816X_CM_SGX_MOD 0x0900 /* 256B */ + +/* ALWON */ +#define TI81XX_CM_ALWON_L3_SLOW_CLKDM 0x0000 +#define TI81XX_CM_ALWON_L3_MED_CLKDM 0x0004 +#define TI81XX_CM_ETHERNET_CLKDM 0x0004 +#define TI81XX_CM_MMU_CLKDM 0x000C +#define TI81XX_CM_MMUCFG_CLKDM 0x0010 +#define TI81XX_CM_ALWON_MPU_CLKDM 0x001C +#define TI81XX_CM_ALWON_L3_FAST_CLKDM 0x0030 + +/* ACTIVE */ +#define TI816X_CM_ACTIVE_GEM_CLKDM 0x0000 + +/* IVAHD0 */ +#define TI816X_CM_IVAHD0_CLKDM 0x0000 + +/* IVAHD1 */ +#define TI816X_CM_IVAHD1_CLKDM 0x0000 + +/* IVAHD2 */ +#define TI816X_CM_IVAHD2_CLKDM 0x0000 + +/* SGX */ +#define TI816X_CM_SGX_CLKDM 0x0000 + +/* DEFAULT */ +#define TI816X_CM_DEFAULT_L3_MED_CLKDM 0x0004 +#define TI816X_CM_DEFAULT_PCI_CLKDM 0x0010 +#define TI816X_CM_DEFAULT_L3_SLOW_CLKDM 0x0014 +#define TI816X_CM_DEFAULT_DUCATI_CLKDM 0x0018 + +#endif diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index e4a5630149e1..e60780f05374 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -492,44 +492,6 @@ void __init am35xx_init_early(void) omap_clk_soc_init = am35xx_dt_clk_init; } -void __init ti814x_init_early(void) -{ - omap2_set_globals_tap(TI814X_CLASS, - OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE)); - omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE), - NULL); - omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE)); - omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL); - omap3xxx_check_revision(); - ti81xx_check_features(); - omap3xxx_voltagedomains_init(); - omap3xxx_powerdomains_init(); - omap3xxx_clockdomains_init(); - omap3xxx_hwmod_init(); - omap_hwmod_init_postsetup(); - if (of_have_populated_dt()) - omap_clk_soc_init = ti81xx_dt_clk_init; -} - -void __init ti816x_init_early(void) -{ - omap2_set_globals_tap(TI816X_CLASS, - OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE)); - omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE), - NULL); - omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE)); - omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL); - omap3xxx_check_revision(); - ti81xx_check_features(); - omap3xxx_voltagedomains_init(); - omap3xxx_powerdomains_init(); - omap3xxx_clockdomains_init(); - omap3xxx_hwmod_init(); - omap_hwmod_init_postsetup(); - if (of_have_populated_dt()) - omap_clk_soc_init = ti81xx_dt_clk_init; -} - void __init omap3_init_late(void) { omap_common_late_init(); @@ -572,6 +534,50 @@ void __init ti81xx_init_late(void) } #endif +#ifdef CONFIG_SOC_TI81XX +void __init ti814x_init_early(void) +{ + omap2_set_globals_tap(TI814X_CLASS, + OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE)); + omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE), + NULL); + omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE)); + omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL); + omap3xxx_check_revision(); + ti81xx_check_features(); + am33xx_prm_init(); + am33xx_cm_init(); + omap3xxx_voltagedomains_init(); + omap3xxx_powerdomains_init(); + ti81xx_clockdomains_init(); + ti81xx_hwmod_init(); + omap_hwmod_init_postsetup(); + if (of_have_populated_dt()) + omap_clk_soc_init = ti81xx_dt_clk_init; +} + +void __init ti816x_init_early(void) +{ + omap2_set_globals_tap(TI816X_CLASS, + OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE)); + omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE), + NULL); + omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE)); + omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL); + omap3xxx_check_revision(); + ti81xx_check_features(); + am33xx_prm_init(); + am33xx_cm_init(); + omap3xxx_voltagedomains_init(); + omap3xxx_powerdomains_init(); + ti81xx_clockdomains_init(); + ti81xx_hwmod_init(); + omap_hwmod_init_postsetup(); + if (of_have_populated_dt()) + omap_clk_soc_init = ti81xx_dt_clk_init; +} +#endif + #ifdef CONFIG_SOC_AM33XX void __init am33xx_init_early(void) { diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bb41dc2b580e..92afb723dcfc 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3916,7 +3916,7 @@ void __init omap_hwmod_init(void) soc_ops.deassert_hardreset = _omap4_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; soc_ops.init_clkdm = _init_clkdm; - } else if (soc_is_am33xx()) { + } else if (cpu_is_ti816x() || soc_is_am33xx()) { 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 fcfdd85aad62..9d4bec6ee742 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -748,6 +748,7 @@ 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 dra7xx_hwmod_init(void); int am43xx_hwmod_init(void); diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c new file mode 100644 index 000000000000..cab1eb61ac96 --- /dev/null +++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c @@ -0,0 +1,1136 @@ +/* + * DM81xx hwmod data. + * + * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/ + * Copyright (C) 2013 SKTB SKiT, http://www.skitlab.ru/ + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include + +#include "omap_hwmod_common_data.h" +#include "cm81xx.h" +#include "ti81xx.h" +#include "wd_timer.h" + +/* + * DM816X hardware modules integration data + * + * Note: This is incomplete and at present, not generated from h/w database. + */ + +/* + * The alwon .clkctrl_offs field is offset from the CM_ALWON, that's + * TRM 18.7.17 CM_ALWON device register values minus 0x1400. + */ +#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) +#define DM816X_CM_ALWON_TIMER_4_CLKCTRL (0x157c - DM816X_DM_ALWON_BASE) +#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) + +/* + * The default .clkctrl_offs field is offset from CM_DEFAULT, that's + * TRM 18.7.6 CM_DEFAULT device register values minus 0x500 + */ +#define DM816X_CM_DEFAULT_OFFSET 0x500 +#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 = { + .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 = { + .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 = { + .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 = { + .name = "l3_fast", + .clkdm_name = "alwon_l3_fast_clkdm", + .class = &l3_hwmod_class, + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 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 = { + .name = "l4_ls", + .clkdm_name = "alwon_l3s_clkdm", + .class = &l4_hwmod_class, +}; + +/* + * L4 high-speed peripherals. For devices using this, please see the TRM + * 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 = { + .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, + .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, + .user = OCP_USER_MPU, +}; + +/* MPU */ +static struct omap_hwmod dm816x_mpu_hwmod = { + .name = "mpu", + .clkdm_name = "alwon_mpu_clkdm", + .class = &mpu_hwmod_class, + .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "mpu_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_MPU_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + +static struct omap_hwmod_ocp_if dm816x_mpu__alwon_l3_slow = { + .master = &dm816x_mpu_hwmod, + .slave = &dm816x_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, + .user = OCP_USER_MPU, +}; + +/* UART common */ +static struct omap_hwmod_class_sysconfig uart_sysc = { + .rev_offs = 0x50, + .sysc_offs = 0x54, + .syss_offs = 0x58, + .sysc_flags = SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_SMART_WKUP, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class uart_class = { + .name = "uart", + .sysc = &uart_sysc, +}; + +static struct omap_hwmod dm816x_uart1_hwmod = { + .name = "uart1", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_UART_0_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &uart_class, + .flags = DEBUG_TI81XXUART1_FLAGS, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__uart1 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_uart1_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_uart2_hwmod = { + .name = "uart2", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_UART_1_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &uart_class, + .flags = DEBUG_TI81XXUART2_FLAGS, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__uart2 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_uart2_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_uart3_hwmod = { + .name = "uart3", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_UART_2_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &uart_class, + .flags = DEBUG_TI81XXUART3_FLAGS, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__uart3 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_uart3_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig wd_timer_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x10, + .syss_offs = 0x14, + .sysc_flags = SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class wd_timer_class = { + .name = "wd_timer", + .sysc = &wd_timer_sysc, + .pre_shutdown = &omap2_wd_timer_disable, + .reset = &omap2_wd_timer_reset, +}; + +static struct omap_hwmod dm816x_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, + .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, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +/* I2C common */ +static struct omap_hwmod_class_sysconfig i2c_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x10, + .syss_offs = 0x90, + .sysc_flags = SYSC_HAS_SIDLEMODE | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class i2c_class = { + .name = "i2c", + .sysc = &i2c_sysc, +}; + +static struct omap_hwmod dm81xx_i2c1_hwmod = { + .name = "i2c1", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .slave = &dm81xx_i2c1_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_i2c2_hwmod = { + .name = "i2c2", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_I2C_1_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &i2c_class, +}; + +static struct omap_hwmod_class_sysconfig dm81xx_elm_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART, + .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, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class dm81xx_elm_hwmod_class = { + .name = "elm", + .sysc = &dm81xx_elm_sysc, +}; + +static struct omap_hwmod dm81xx_elm_hwmod = { + .name = "elm", + .clkdm_name = "alwon_l3s_clkdm", + .class = &dm81xx_elm_hwmod_class, + .main_clk = "sysclk6_ck", +}; + +static struct omap_hwmod_ocp_if dm81xx_l4_ls__elm = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm81xx_elm_hwmod, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig dm81xx_gpio_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0114, + .sysc_flags = SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + SIDLE_SMART_WKUP, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class dm81xx_gpio_hwmod_class = { + .name = "gpio", + .sysc = &dm81xx_gpio_sysc, + .rev = 2, +}; + +static struct omap_gpio_dev_attr gpio_dev_attr = { + .bank_width = 32, + .dbck_flag = true, +}; + +static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { + { .role = "dbclk", .clk = "sysclk18_ck" }, +}; + +static struct omap_hwmod dm81xx_gpio1_hwmod = { + .name = "gpio1", + .clkdm_name = "alwon_l3s_clkdm", + .class = &dm81xx_gpio_hwmod_class, + .main_clk = "sysclk6_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_GPIO_0_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = gpio1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .dev_attr = &gpio_dev_attr, +}; + +static struct omap_hwmod_ocp_if dm81xx_l4_ls__gpio1 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm81xx_gpio1_hwmod, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { + { .role = "dbclk", .clk = "sysclk18_ck" }, +}; + +static struct omap_hwmod dm81xx_gpio2_hwmod = { + .name = "gpio2", + .clkdm_name = "alwon_l3s_clkdm", + .class = &dm81xx_gpio_hwmod_class, + .main_clk = "sysclk6_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_GPIO_1_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .opt_clks = gpio2_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks), + .dev_attr = &gpio_dev_attr, +}; + +static struct omap_hwmod_ocp_if dm81xx_l4_ls__gpio2 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm81xx_gpio2_hwmod, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig dm81xx_gpmc_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x10, + .syss_offs = 0x14, + .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class dm81xx_gpmc_hwmod_class = { + .name = "gpmc", + .sysc = &dm81xx_gpmc_sysc, +}; + +static struct omap_hwmod dm81xx_gpmc_hwmod = { + .name = "gpmc", + .clkdm_name = "alwon_l3s_clkdm", + .class = &dm81xx_gpmc_hwmod_class, + .main_clk = "sysclk6_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_GPMC_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + +struct omap_hwmod_ocp_if dm81xx_alwon_l3_slow__gpmc = { + .master = &dm816x_alwon_l3_slow_hwmod, + .slave = &dm81xx_gpmc_hwmod, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig dm81xx_usbhsotg_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x10, + .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SOFTRESET, + .idlemodes = SIDLE_SMART | MSTANDBY_FORCE | MSTANDBY_SMART, + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class dm81xx_usbotg_class = { + .name = "usbotg", + .sysc = &dm81xx_usbhsotg_sysc, +}; + +static struct omap_hwmod dm81xx_usbss_hwmod = { + .name = "usb_otg_hs", + .clkdm_name = "default_l3_slow_clkdm", + .main_clk = "sysclk6_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_DEFAULT_USB_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &dm81xx_usbotg_class, +}; + +static struct omap_hwmod_ocp_if dm81xx_default_l3_slow__usbss = { + .master = &dm816x_default_l3_slow_hwmod, + .slave = &dm81xx_usbss_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig dm816x_timer_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + SIDLE_SMART_WKUP, + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class dm816x_timer_hwmod_class = { + .name = "timer", + .sysc = &dm816x_timer_sysc, +}; + +static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = { + .timer_capability = OMAP_TIMER_ALWON, +}; + +static struct omap_hwmod dm816x_timer1_hwmod = { + .name = "timer1", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer1_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_1_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer1 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer1_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_timer2_hwmod = { + .name = "timer2", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer2_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_2_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer2 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer2_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_timer3_hwmod = { + .name = "timer3", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer3_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_3_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer3 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer3_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_timer4_hwmod = { + .name = "timer4", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer4_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_4_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer4 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer4_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_timer5_hwmod = { + .name = "timer5", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer5_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_5_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer5 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer5_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_timer6_hwmod = { + .name = "timer6", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer6_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_6_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer6 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer6_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_timer7_hwmod = { + .name = "timer7", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "timer7_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_TIMER_7_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &capability_alwon_dev_attr, + .class = &dm816x_timer_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__timer7 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_timer7_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +/* EMAC Ethernet */ +static struct omap_hwmod_class_sysconfig dm816x_emac_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x4, + .sysc_flags = SYSC_HAS_SOFTRESET, + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class dm816x_emac_hwmod_class = { + .name = "emac", + .sysc = &dm816x_emac_sysc, +}; + +/* + * On dm816x the MDIO is within EMAC0. As the MDIO driver is a separate + * driver probed before EMAC0, we let MDIO do the clock idling. + */ +static struct omap_hwmod dm816x_emac0_hwmod = { + .name = "emac0", + .clkdm_name = "alwon_ethernet_clkdm", + .class = &dm816x_emac_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_hs__emac0 = { + .master = &dm816x_l4_hs_hwmod, + .slave = &dm816x_emac0_hwmod, + .clk = "sysclk5_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class dm816x_mdio_hwmod_class = { + .name = "davinci_mdio", + .sysc = &dm816x_emac_sysc, +}; + +struct omap_hwmod dm816x_emac0_mdio_hwmod = { + .name = "davinci_mdio", + .class = &dm816x_mdio_hwmod_class, + .clkdm_name = "alwon_ethernet_clkdm", + .main_clk = "sysclk24_ck", + .flags = HWMOD_NO_IDLEST, + /* + * REVISIT: This should be moved to the emac0_hwmod + * once we have a better way to handle device slaves. + */ + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod dm816x_emac1_hwmod = { + .name = "emac1", + .clkdm_name = "alwon_ethernet_clkdm", + .main_clk = "sysclk24_ck", + .flags = HWMOD_NO_IDLEST, + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_ETHERNET_1_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &dm816x_emac_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = { + .master = &dm816x_l4_hs_hwmod, + .slave = &dm816x_emac1_hwmod, + .clk = "sysclk5_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig dm816x_mmc_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x110, + .syss_offs = 0x114, + .sysc_flags = SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class dm816x_mmc_class = { + .name = "mmc", + .sysc = &dm816x_mmc_sysc, +}; + +static struct omap_hwmod_opt_clk dm816x_mmc1_opt_clks[] = { + { .role = "dbck", .clk = "sysclk18_ck", }, +}; + +static struct omap_hsmmc_dev_attr mmc1_dev_attr = { + .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, +}; + +static struct omap_hwmod dm816x_mmc1_hwmod = { + .name = "mmc1", + .clkdm_name = "alwon_l3s_clkdm", + .opt_clks = dm816x_mmc1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dm816x_mmc1_opt_clks), + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_SDIO_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .dev_attr = &mmc1_dev_attr, + .class = &dm816x_mmc_class, +}; + +static struct omap_hwmod_ocp_if dm816x_l4_ls__mmc1 = { + .master = &dm816x_l4_ls_hwmod, + .slave = &dm816x_mmc1_hwmod, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, + .flags = OMAP_FIREWALL_L4 +}; + +static struct omap_hwmod_class_sysconfig dm816x_mcspi_sysc = { + .rev_offs = 0x0, + .sysc_offs = 0x110, + .syss_offs = 0x114, + .sysc_flags = SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class dm816x_mcspi_class = { + .name = "mcspi", + .sysc = &dm816x_mcspi_sysc, + .rev = OMAP3_MCSPI_REV, +}; + +static struct omap2_mcspi_dev_attr dm816x_mcspi1_dev_attr = { + .num_chipselect = 4, +}; + +static struct omap_hwmod dm816x_mcspi1_hwmod = { + .name = "mcspi1", + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk10_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_CM_ALWON_SPI_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &dm816x_mcspi_class, + .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, + .clk = "sysclk6_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig dm816x_mailbox_sysc = { + .rev_offs = 0x000, + .sysc_offs = 0x010, + .syss_offs = 0x014, + .sysc_flags = SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE, + .idlemodes = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class dm816x_mailbox_hwmod_class = { + .name = "mailbox", + .sysc = &dm816x_mailbox_sysc, +}; + +static struct omap_hwmod dm816x_mailbox_hwmod = { + .name = "mailbox", + .clkdm_name = "alwon_l3s_clkdm", + .class = &dm816x_mailbox_hwmod_class, + .main_clk = "sysclk6_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class dm816x_tpcc_hwmod_class = { + .name = "tpcc", +}; + +struct omap_hwmod dm816x_tpcc_hwmod = { + .name = "tpcc", + .class = &dm816x_tpcc_hwmod_class, + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk4_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .clk = "sysclk4_ck", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space dm816x_tptc0_addr_space[] = { + { + .pa_start = 0x49800000, + .pa_end = 0x49800000 + SZ_8K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; + +static struct omap_hwmod_class dm816x_tptc0_hwmod_class = { + .name = "tptc0", +}; + +struct omap_hwmod dm816x_tptc0_hwmod = { + .name = "tptc0", + .class = &dm816x_tptc0_hwmod_class, + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk4_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .clk = "sysclk4_ck", + .addr = dm816x_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, + .clk = "sysclk4_ck", + .addr = dm816x_tptc0_addr_space, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space dm816x_tptc1_addr_space[] = { + { + .pa_start = 0x49900000, + .pa_end = 0x49900000 + SZ_8K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; + +static struct omap_hwmod_class dm816x_tptc1_hwmod_class = { + .name = "tptc1", +}; + +struct omap_hwmod dm816x_tptc1_hwmod = { + .name = "tptc1", + .class = &dm816x_tptc1_hwmod_class, + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk4_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .clk = "sysclk4_ck", + .addr = dm816x_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, + .clk = "sysclk4_ck", + .addr = dm816x_tptc1_addr_space, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space dm816x_tptc2_addr_space[] = { + { + .pa_start = 0x49a00000, + .pa_end = 0x49a00000 + SZ_8K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; + +static struct omap_hwmod_class dm816x_tptc2_hwmod_class = { + .name = "tptc2", +}; + +struct omap_hwmod dm816x_tptc2_hwmod = { + .name = "tptc2", + .class = &dm816x_tptc2_hwmod_class, + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk4_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .clk = "sysclk4_ck", + .addr = dm816x_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, + .clk = "sysclk4_ck", + .addr = dm816x_tptc2_addr_space, + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space dm816x_tptc3_addr_space[] = { + { + .pa_start = 0x49b00000, + .pa_end = 0x49b00000 + SZ_8K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; + +static struct omap_hwmod_class dm816x_tptc3_hwmod_class = { + .name = "tptc3", +}; + +struct omap_hwmod dm816x_tptc3_hwmod = { + .name = "tptc3", + .class = &dm816x_tptc3_hwmod_class, + .clkdm_name = "alwon_l3s_clkdm", + .main_clk = "sysclk4_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DM816X_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, + .clk = "sysclk4_ck", + .addr = dm816x_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, + .clk = "sysclk4_ck", + .addr = dm816x_tptc3_addr_space, + .user = OCP_USER_MPU, +}; + +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_l4_ls__gpio1, + &dm81xx_l4_ls__gpio2, + &dm81xx_l4_ls__elm, + &dm816x_l4_ls__mmc1, + &dm816x_l4_ls__timer1, + &dm816x_l4_ls__timer2, + &dm816x_l4_ls__timer3, + &dm816x_l4_ls__timer4, + &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, + &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_slow__gpmc, + &dm81xx_default_l3_slow__usbss, + NULL, +}; + +int __init ti81xx_hwmod_init(void) +{ + omap_hwmod_init(); + return omap_hwmod_register_links(dm816x_hwmod_ocp_ifs); +} diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig index 042f693ef423..a219dc310d5d 100644 --- a/arch/arm/mach-prima2/Kconfig +++ b/arch/arm/mach-prima2/Kconfig @@ -11,7 +11,7 @@ menuconfig ARCH_SIRF if ARCH_SIRF -comment "CSR SiRF atlas6/primaII/Marco/Polo Specific Features" +comment "CSR SiRF atlas6/primaII/Atlas7 Specific Features" config ARCH_ATLAS6 bool "CSR SiRFSoC ATLAS6 ARM Cortex A9 Platform" @@ -20,6 +20,17 @@ config ARCH_ATLAS6 help Support for CSR SiRFSoC ARM Cortex A9 Platform +config ARCH_ATLAS7 + bool "CSR SiRFSoC ATLAS7 ARM Cortex A7 Platform" + default y + select ARM_GIC + select CPU_V7 + select HAVE_ARM_SCU if SMP + select HAVE_SMP + select SMP_ON_UP if SMP + help + Support for CSR SiRFSoC ARM Cortex A7 Platform + config ARCH_PRIMA2 bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform" default y @@ -28,15 +39,6 @@ config ARCH_PRIMA2 help Support for CSR SiRFSoC ARM Cortex A9 Platform -config ARCH_MARCO - bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform" - default y - select ARM_GIC - select HAVE_ARM_SCU if SMP - select SMP_ON_UP if SMP - help - Support for CSR SiRFSoC ARM Cortex A9 Platform - config SIRF_IRQ bool diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile index 8846e7d87ea5..d7d02b043449 100644 --- a/arch/arm/mach-prima2/Makefile +++ b/arch/arm/mach-prima2/Makefile @@ -1,7 +1,6 @@ obj-y += rstc.o obj-y += common.o obj-y += rtciobrg.o -obj-$(CONFIG_DEBUG_LL) += lluart.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c index a860ea27e8ae..0c819bb88418 100644 --- a/arch/arm/mach-prima2/common.c +++ b/arch/arm/mach-prima2/common.c @@ -20,12 +20,6 @@ static void __init sirfsoc_init_late(void) sirfsoc_pm_init(); } -static __init void sirfsoc_map_io(void) -{ - sirfsoc_map_lluart(); - sirfsoc_map_scu(); -} - #ifdef CONFIG_ARCH_ATLAS6 static const char *atlas6_dt_match[] __initconst = { "sirf,atlas6", @@ -36,7 +30,6 @@ DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)") /* Maintainer: Barry Song */ .l2c_aux_val = 0, .l2c_aux_mask = ~0, - .map_io = sirfsoc_map_io, .init_late = sirfsoc_init_late, .dt_compat = atlas6_dt_match, MACHINE_END @@ -52,26 +45,21 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") /* Maintainer: Barry Song */ .l2c_aux_val = 0, .l2c_aux_mask = ~0, - .map_io = sirfsoc_map_io, .dma_zone_size = SZ_256M, .init_late = sirfsoc_init_late, .dt_compat = prima2_dt_match, MACHINE_END #endif -#ifdef CONFIG_ARCH_MARCO -static const char *marco_dt_match[] __initconst = { - "sirf,marco", +#ifdef CONFIG_ARCH_ATLAS7 +static const char *atlas7_dt_match[] __initdata = { + "sirf,atlas7", NULL }; -DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)") +DT_MACHINE_START(ATLAS7_DT, "Generic ATLAS7 (Flattened Device Tree)") /* Maintainer: Barry Song */ - .l2c_aux_val = 0, - .l2c_aux_mask = ~0, .smp = smp_ops(sirfsoc_smp_ops), - .map_io = sirfsoc_map_io, - .init_late = sirfsoc_init_late, - .dt_compat = marco_dt_match, + .dt_compat = atlas7_dt_match, MACHINE_END #endif diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c deleted file mode 100644 index 99c0c927ca4a..000000000000 --- a/arch/arm/mach-prima2/lluart.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Static memory mapping for DEBUG_LL - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include -#include "common.h" - -#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1) -#define SIRFSOC_UART1_PA_BASE 0xb0060000 -#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1) -#define SIRFSOC_UART1_PA_BASE 0xcc060000 -#else -#define SIRFSOC_UART1_PA_BASE 0 -#endif - -#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000) -#define SIRFSOC_UART1_SIZE SZ_4K - -void __init sirfsoc_map_lluart(void) -{ - struct map_desc sirfsoc_lluart_map = { - .virtual = SIRFSOC_UART1_VA_BASE, - .pfn = __phys_to_pfn(SIRFSOC_UART1_PA_BASE), - .length = SIRFSOC_UART1_SIZE, - .type = MT_DEVICE, - }; - - iotable_init(&sirfsoc_lluart_map, 1); -} diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c index 335c12e92262..fc2b03c81e5f 100644 --- a/arch/arm/mach-prima2/platsmp.c +++ b/arch/arm/mach-prima2/platsmp.c @@ -20,30 +20,10 @@ #include "common.h" -static void __iomem *scu_base; -static void __iomem *rsc_base; +static void __iomem *clk_base; static DEFINE_SPINLOCK(boot_lock); -static struct map_desc scu_io_desc __initdata = { - .length = SZ_4K, - .type = MT_DEVICE, -}; - -void __init sirfsoc_map_scu(void) -{ - unsigned long base; - - /* Get SCU base */ - asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); - - scu_io_desc.virtual = SIRFSOC_VA(base); - scu_io_desc.pfn = __phys_to_pfn(base); - iotable_init(&scu_io_desc, 1); - - scu_base = (void __iomem *)SIRFSOC_VA(base); -} - static void sirfsoc_secondary_init(unsigned int cpu) { /* @@ -60,8 +40,8 @@ static void sirfsoc_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static struct of_device_id rsc_ids[] = { - { .compatible = "sirf,marco-rsc" }, +static struct of_device_id clk_ids[] = { + { .compatible = "sirf,atlas7-clkc" }, {}, }; @@ -70,27 +50,27 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle) unsigned long timeout; struct device_node *np; - np = of_find_matching_node(NULL, rsc_ids); + np = of_find_matching_node(NULL, clk_ids); if (!np) return -ENODEV; - rsc_base = of_iomap(np, 0); - if (!rsc_base) + clk_base = of_iomap(np, 0); + if (!clk_base) return -ENOMEM; /* - * write the address of secondary startup into the sram register - * at offset 0x2C, then write the magic number 0x3CAF5D62 to the - * RSC register at offset 0x28, which is what boot rom code is + * write the address of secondary startup into the clkc register + * at offset 0x2bC, then write the magic number 0x3CAF5D62 to the + * clkc register at offset 0x2b8, which is what boot rom code is * waiting for. This would wake up the secondary core from WFE */ -#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C +#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2bc __raw_writel(virt_to_phys(sirfsoc_secondary_startup), - rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET); + clk_base + SIRFSOC_CPU1_JUMPADDR_OFFSET); -#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28 +#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x2b8 __raw_writel(0x3CAF5D62, - rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET); + clk_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET); /* make sure write buffer is drained */ mb(); @@ -132,13 +112,7 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle) return pen_release != -1 ? -ENOSYS : 0; } -static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus) -{ - scu_enable(scu_base); -} - struct smp_operations sirfsoc_smp_ops __initdata = { - .smp_prepare_cpus = sirfsoc_smp_prepare_cpus, .smp_secondary_init = sirfsoc_secondary_init, .smp_boot_secondary = sirfsoc_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c index e1f1f86f6a95..7c251eb11d01 100644 --- a/arch/arm/mach-prima2/rstc.c +++ b/arch/arm/mach-prima2/rstc.c @@ -34,36 +34,20 @@ static int sirfsoc_reset_module(struct reset_controller_dev *rcdev, mutex_lock(&rstc_lock); - if (of_device_is_compatible(rcdev->of_node, "sirf,prima2-rstc")) { - /* - * Writing 1 to this bit resets corresponding block. - * Writing 0 to this bit de-asserts reset signal of the - * corresponding block. datasheet doesn't require explicit - * delay between the set and clear of reset bit. it could - * be shorter if tests pass. - */ - writel(readl(sirfsoc_rstc_base + + /* + * Writing 1 to this bit resets corresponding block. + * Writing 0 to this bit de-asserts reset signal of the + * corresponding block. datasheet doesn't require explicit + * delay between the set and clear of reset bit. it could + * be shorter if tests pass. + */ + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | (1 << reset_bit), - sirfsoc_rstc_base + (reset_bit / 32) * 4); - msleep(20); - writel(readl(sirfsoc_rstc_base + + sirfsoc_rstc_base + (reset_bit / 32) * 4); + msleep(20); + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~(1 << reset_bit), - sirfsoc_rstc_base + (reset_bit / 32) * 4); - } else { - /* - * For MARCO and POLO - * Writing 1 to SET register resets corresponding block. - * Writing 1 to CLEAR register de-asserts reset signal of the - * corresponding block. - * datasheet doesn't require explicit delay between the set and - * clear of reset bit. it could be shorter if tests pass. - */ - writel(1 << reset_bit, - sirfsoc_rstc_base + (reset_bit / 32) * 8); - msleep(20); - writel(1 << reset_bit, - sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); - } + sirfsoc_rstc_base + (reset_bit / 32) * 4); mutex_unlock(&rstc_lock); @@ -106,7 +90,6 @@ static int sirfsoc_rstc_probe(struct platform_device *pdev) static const struct of_device_id rstc_ids[] = { { .compatible = "sirf,prima2-rstc" }, - { .compatible = "sirf,marco-rstc" }, {}, }; diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c index 70a0b475062b..8f66d8f7ca75 100644 --- a/arch/arm/mach-prima2/rtciobrg.c +++ b/arch/arm/mach-prima2/rtciobrg.c @@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel); static const struct of_device_id rtciobrg_ids[] = { { .compatible = "sirf,prima2-rtciobg" }, - { .compatible = "sirf,marco-rtciobg" }, {} }; diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig index ee5697ba05bc..48003ea652b9 100644 --- a/arch/arm/mach-qcom/Kconfig +++ b/arch/arm/mach-qcom/Kconfig @@ -1,9 +1,8 @@ menuconfig ARCH_QCOM bool "Qualcomm Support" if ARCH_MULTI_V7 - select ARCH_REQUIRE_GPIOLIB + select ARCH_SUPPORTS_BIG_ENDIAN select ARM_GIC select ARM_AMBA - select CLKSRC_OF select PINCTRL select QCOM_SCM if SMP help diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c index 45cee3e469a5..e8ff7beb6218 100644 --- a/arch/arm/mach-qcom/scm-boot.c +++ b/arch/arm/mach-qcom/scm-boot.c @@ -24,15 +24,15 @@ /* * Set the cold/warm boot address for one of the CPU cores. */ -int scm_set_boot_addr(phys_addr_t addr, int flags) +int scm_set_boot_addr(u32 addr, int flags) { struct { - unsigned int flags; - phys_addr_t addr; + __le32 flags; + __le32 addr; } cmd; - cmd.addr = addr; - cmd.flags = flags; + cmd.addr = cpu_to_le32(addr); + cmd.flags = cpu_to_le32(flags); return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, &cmd, sizeof(cmd), NULL, 0); } diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h index 6aabb2428176..3e210fb818bb 100644 --- a/arch/arm/mach-qcom/scm-boot.h +++ b/arch/arm/mach-qcom/scm-boot.h @@ -18,7 +18,9 @@ #define SCM_FLAG_COLDBOOT_CPU3 0x20 #define SCM_FLAG_WARMBOOT_CPU0 0x04 #define SCM_FLAG_WARMBOOT_CPU1 0x02 +#define SCM_FLAG_WARMBOOT_CPU2 0x10 +#define SCM_FLAG_WARMBOOT_CPU3 0x40 -int scm_set_boot_addr(phys_addr_t addr, int flags); +int scm_set_boot_addr(u32 addr, int flags); #endif diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index c536fd6bf827..1d9cf18c7091 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c @@ -22,13 +22,11 @@ #include #include +#include #include #include "scm.h" -/* Cache line size for msm8x60 */ -#define CACHELINESIZE 32 - #define SCM_ENOMEM -5 #define SCM_EOPNOTSUPP -4 #define SCM_EINVAL_ADDR -3 @@ -63,11 +61,11 @@ static DEFINE_MUTEX(scm_lock); * to access the buffers in a safe manner. */ struct scm_command { - u32 len; - u32 buf_offset; - u32 resp_hdr_offset; - u32 id; - u32 buf[0]; + __le32 len; + __le32 buf_offset; + __le32 resp_hdr_offset; + __le32 id; + __le32 buf[0]; }; /** @@ -77,9 +75,9 @@ struct scm_command { * @is_complete: indicates if the command has finished processing */ struct scm_response { - u32 len; - u32 buf_offset; - u32 is_complete; + __le32 len; + __le32 buf_offset; + __le32 is_complete; }; /** @@ -97,12 +95,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size) struct scm_command *cmd; size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + resp_size; + u32 offset; cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); if (cmd) { - cmd->len = len; - cmd->buf_offset = offsetof(struct scm_command, buf); - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; + cmd->len = cpu_to_le32(len); + offset = offsetof(struct scm_command, buf); + cmd->buf_offset = cpu_to_le32(offset); + cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size); } return cmd; } @@ -127,7 +127,7 @@ static inline void free_scm_command(struct scm_command *cmd) static inline struct scm_response *scm_command_to_response( const struct scm_command *cmd) { - return (void *)cmd + cmd->resp_hdr_offset; + return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); } /** @@ -149,11 +149,12 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd) */ static inline void *scm_get_response_buffer(const struct scm_response *rsp) { - return (void *)rsp + rsp->buf_offset; + return (void *)rsp + le32_to_cpu(rsp->buf_offset); } static int scm_remap_error(int err) { + pr_err("scm_call failed with error code %d\n", err); switch (err) { case SCM_ERROR: return -EIO; @@ -198,11 +199,12 @@ static int __scm_call(const struct scm_command *cmd) u32 cmd_addr = virt_to_phys(cmd); /* - * Flush the entire cache here so callers don't have to remember - * to flush the cache when passing physical addresses to the secure - * side in the buffer. + * Flush the command buffer so that the secure world sees + * the correct data. */ - flush_cache_all(); + __cpuc_flush_dcache_area((void *)cmd, cmd->len); + outer_flush_range(cmd_addr, cmd_addr + cmd->len); + ret = smc(cmd_addr); if (ret < 0) ret = scm_remap_error(ret); @@ -210,6 +212,25 @@ static int __scm_call(const struct scm_command *cmd) return ret; } +static void scm_inv_range(unsigned long start, unsigned long end) +{ + u32 cacheline_size, ctr; + + asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); + cacheline_size = 4 << ((ctr >> 16) & 0xf); + + start = round_down(start, cacheline_size); + end = round_up(end, cacheline_size); + outer_inv_range(start, end); + while (start < end) { + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) + : "memory"); + start += cacheline_size; + } + dsb(); + isb(); +} + /** * scm_call() - Send an SCM command * @svc_id: service identifier @@ -220,6 +241,13 @@ static int __scm_call(const struct scm_command *cmd) * @resp_len: length of the response buffer * * Sends a command to the SCM and waits for the command to finish processing. + * + * A note on cache maintenance: + * Note that any buffers that are expected to be accessed by the secure world + * must be flushed before invoking scm_call and invalidated in the cache + * immediately after scm_call returns. Cache maintenance on the command and + * response buffers is taken care of by scm_call; however, callers are + * responsible for any other cached buffers passed over to the secure world. */ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, void *resp_buf, size_t resp_len) @@ -227,12 +255,13 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, int ret; struct scm_command *cmd; struct scm_response *rsp; + unsigned long start, end; cmd = alloc_scm_command(cmd_len, resp_len); if (!cmd) return -ENOMEM; - cmd->id = (svc_id << 10) | cmd_id; + cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); if (cmd_buf) memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); @@ -243,17 +272,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, goto out; rsp = scm_command_to_response(cmd); + start = (unsigned long)rsp; + do { - u32 start = (u32)rsp; - u32 end = (u32)scm_get_response_buffer(rsp) + resp_len; - start &= ~(CACHELINESIZE - 1); - while (start < end) { - asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) - : "memory"); - start += CACHELINESIZE; - } + scm_inv_range(start, start + sizeof(*rsp)); } while (!rsp->is_complete); + end = (unsigned long)scm_get_response_buffer(rsp) + resp_len; + scm_inv_range(start, end); + if (resp_buf) memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); out: diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b29d8ead4cf2..5c3a9b2de920 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -1,4 +1,5 @@ CFLAGS_platsmp.o := -march=armv7-a obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o +obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c new file mode 100644 index 000000000000..50cb781aaa36 --- /dev/null +++ b/arch/arm/mach-rockchip/pm.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pm.h" + +/* These enum are option of low power mode */ +enum { + ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0, + ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1, +}; + +struct rockchip_pm_data { + const struct platform_suspend_ops *ops; + int (*init)(struct device_node *np); +}; + +static void __iomem *rk3288_bootram_base; +static phys_addr_t rk3288_bootram_phy; + +static struct regmap *pmu_regmap; +static struct regmap *sgrf_regmap; + +static u32 rk3288_pmu_pwr_mode_con; +static u32 rk3288_sgrf_soc_con0; + +static inline u32 rk3288_l2_config(void) +{ + u32 l2ctlr; + + asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr)); + return l2ctlr; +} + +static void rk3288_config_bootdata(void) +{ + rkpm_bootdata_cpusp = rk3288_bootram_phy + (SZ_4K - 8); + rkpm_bootdata_cpu_code = virt_to_phys(cpu_resume); + + rkpm_bootdata_l2ctlr_f = 1; + rkpm_bootdata_l2ctlr = rk3288_l2_config(); +} + +static void rk3288_slp_mode_set(int level) +{ + u32 mode_set, mode_set1; + + regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0); + + regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON, + &rk3288_pmu_pwr_mode_con); + + /* set bit 8 so that system will resume to FAST_BOOT_ADDR */ + regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, + SGRF_FAST_BOOT_EN | SGRF_FAST_BOOT_EN_WRITE); + + /* booting address of resuming system is from this register value */ + 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) | + BIT(PMU_PWR_MODE_EN) | BIT(PMU_CHIP_PD_EN) | + BIT(PMU_SCU_EN); + + mode_set1 = BIT(PMU_CLR_CORE) | BIT(PMU_CLR_CPUP); + + if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { + /* arm off, logic deep sleep */ + mode_set |= BIT(PMU_BUS_PD_EN) | + 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); + + mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) | + BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA); + } else { + /* + * arm off, logic normal + * if pmu_clk_core_src_gate_en is not set, + * wakeup will be error + */ + mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN); + } + + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set); + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON1, mode_set1); +} + +static void rk3288_slp_mode_set_resume(void) +{ + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, + rk3288_pmu_pwr_mode_con); + + regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, + rk3288_sgrf_soc_con0 | SGRF_FAST_BOOT_EN_WRITE); +} + +static int rockchip_lpmode_enter(unsigned long arg) +{ + flush_cache_all(); + + cpu_do_idle(); + + pr_err("%s: Failed to suspend\n", __func__); + + return 1; +} + +static int rk3288_suspend_enter(suspend_state_t state) +{ + local_fiq_disable(); + + rk3288_slp_mode_set(ROCKCHIP_ARM_OFF_LOGIC_NORMAL); + + cpu_suspend(0, rockchip_lpmode_enter); + + rk3288_slp_mode_set_resume(); + + local_fiq_enable(); + + return 0; +} + +static int rk3288_suspend_prepare(void) +{ + return regulator_suspend_prepare(PM_SUSPEND_MEM); +} + +static void rk3288_suspend_finish(void) +{ + if (regulator_suspend_finish()) + pr_err("%s: Suspend finish failed\n", __func__); +} + +static int rk3288_suspend_init(struct device_node *np) +{ + struct device_node *sram_np; + struct resource res; + int ret; + + pmu_regmap = syscon_node_to_regmap(np); + if (IS_ERR(pmu_regmap)) { + pr_err("%s: could not find pmu regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + + sgrf_regmap = syscon_regmap_lookup_by_compatible( + "rockchip,rk3288-sgrf"); + if (IS_ERR(sgrf_regmap)) { + pr_err("%s: could not find sgrf regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + + sram_np = of_find_compatible_node(NULL, NULL, + "rockchip,rk3288-pmu-sram"); + if (!sram_np) { + pr_err("%s: could not find bootram dt node\n", __func__); + return -ENODEV; + } + + rk3288_bootram_base = of_iomap(sram_np, 0); + if (!rk3288_bootram_base) { + pr_err("%s: could not map bootram base\n", __func__); + return -ENOMEM; + } + + ret = of_address_to_resource(sram_np, 0, &res); + if (ret) { + pr_err("%s: could not get bootram phy addr\n", __func__); + return ret; + } + rk3288_bootram_phy = res.start; + + of_node_put(sram_np); + + rk3288_config_bootdata(); + + /* copy resume code and data to bootsram */ + memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume, + rk3288_bootram_sz); + + return 0; +} + +static const struct platform_suspend_ops rk3288_suspend_ops = { + .enter = rk3288_suspend_enter, + .valid = suspend_valid_only_mem, + .prepare = rk3288_suspend_prepare, + .finish = rk3288_suspend_finish, +}; + +static const struct rockchip_pm_data rk3288_pm_data __initconst = { + .ops = &rk3288_suspend_ops, + .init = rk3288_suspend_init, +}; + +static const struct of_device_id rockchip_pmu_of_device_ids[] __initconst = { + { + .compatible = "rockchip,rk3288-pmu", + .data = &rk3288_pm_data, + }, + { /* sentinel */ }, +}; + +void __init rockchip_suspend_init(void) +{ + const struct rockchip_pm_data *pm_data; + const struct of_device_id *match; + struct device_node *np; + int ret; + + np = of_find_matching_node_and_match(NULL, rockchip_pmu_of_device_ids, + &match); + if (!match) { + pr_err("Failed to find PMU node\n"); + return; + } + pm_data = (struct rockchip_pm_data *) match->data; + + if (pm_data->init) { + ret = pm_data->init(np); + + if (ret) { + pr_err("%s: matches init error %d\n", __func__, ret); + return; + } + } + + suspend_set_ops(pm_data->ops); +} diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h new file mode 100644 index 000000000000..7d752ff39f91 --- /dev/null +++ b/arch/arm/mach-rockchip/pm.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __MACH_ROCKCHIP_PM_H +#define __MACH_ROCKCHIP_PM_H + +extern unsigned long rkpm_bootdata_cpusp; +extern unsigned long rkpm_bootdata_cpu_code; +extern unsigned long rkpm_bootdata_l2ctlr_f; +extern unsigned long rkpm_bootdata_l2ctlr; +extern unsigned long rkpm_bootdata_ddr_code; +extern unsigned long rkpm_bootdata_ddr_data; +extern unsigned long rk3288_bootram_sz; + +void rockchip_slp_cpu_resume(void); +void __init rockchip_suspend_init(void); + +/****** following is rk3288 defined **********/ +#define RK3288_PMU_WAKEUP_CFG0 0x00 +#define RK3288_PMU_WAKEUP_CFG1 0x04 +#define RK3288_PMU_PWRMODE_CON 0x18 +#define RK3288_PMU_OSC_CNT 0x20 +#define RK3288_PMU_PLL_CNT 0x24 +#define RK3288_PMU_STABL_CNT 0x28 +#define RK3288_PMU_DDR0IO_PWRON_CNT 0x2c +#define RK3288_PMU_DDR1IO_PWRON_CNT 0x30 +#define RK3288_PMU_CORE_PWRDWN_CNT 0x34 +#define RK3288_PMU_CORE_PWRUP_CNT 0x38 +#define RK3288_PMU_GPU_PWRDWN_CNT 0x3c +#define RK3288_PMU_GPU_PWRUP_CNT 0x40 +#define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44 +#define RK3288_PMU_PWRMODE_CON1 0x90 + +#define RK3288_SGRF_SOC_CON0 (0x0000) +#define RK3288_SGRF_FAST_BOOT_ADDR (0x0120) +#define SGRF_FAST_BOOT_EN BIT(8) +#define SGRF_FAST_BOOT_EN_WRITE BIT(24) + +#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) + +enum rk3288_pwr_mode_con { + PMU_PWR_MODE_EN = 0, + PMU_CLK_CORE_SRC_GATE_EN, + PMU_GLOBAL_INT_DISABLE, + PMU_L2FLUSH_EN, + PMU_BUS_PD_EN, + PMU_A12_0_PD_EN, + PMU_SCU_EN, + PMU_PLL_PD_EN, + PMU_CHIP_PD_EN, /* POWER OFF PIN ENABLE */ + PMU_PWROFF_COMB, + PMU_ALIVE_USE_LF, + PMU_PMU_USE_LF, + PMU_OSC_24M_DIS, + PMU_INPUT_CLAMP_EN, + PMU_WAKEUP_RESET_EN, + PMU_SREF0_ENTER_EN, + PMU_SREF1_ENTER_EN, + PMU_DDR0IO_RET_EN, + PMU_DDR1IO_RET_EN, + PMU_DDR0_GATING_EN, + PMU_DDR1_GATING_EN, + PMU_DDR0IO_RET_DE_REQ, + PMU_DDR1IO_RET_DE_REQ +}; + +enum rk3288_pwr_mode_con1 { + PMU_CLR_BUS = 0, + PMU_CLR_CORE, + PMU_CLR_CPUP, + PMU_CLR_ALIVE, + PMU_CLR_DMA, + PMU_CLR_PERI, + PMU_CLR_GPU, + PMU_CLR_VIDEO, + PMU_CLR_HEVC, + PMU_CLR_VIO, +}; + +#endif /* __MACH_ROCKCHIP_PM_H */ diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index a611f4852582..d360ec044b66 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -27,6 +27,7 @@ #include #include #include "core.h" +#include "pm.h" #define RK3288_GRF_SOC_CON0 0x244 @@ -52,6 +53,7 @@ static void __init rockchip_timer_init(void) static void __init rockchip_dt_init(void) { + rockchip_suspend_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register_simple("cpufreq-dt", 0, NULL, 0); } @@ -65,7 +67,7 @@ static const char * const rockchip_board_dt_compat[] = { NULL, }; -DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)") +DT_MACHINE_START(ROCKCHIP_DT, "Rockchip (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, .init_time = rockchip_timer_init, diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S new file mode 100644 index 000000000000..2eec9a341f05 --- /dev/null +++ b/arch/arm/mach-rockchip/sleep.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +.data +/* + * this code will be copied from + * ddr to sram for system resumeing. + * so it is ".data section". + */ +.align + +ENTRY(rockchip_slp_cpu_resume) + setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set svc, irqs off + mrc p15, 0, r1, c0, c0, 5 + and r1, r1, #0xf + cmp r1, #0 + /* olny cpu0 can continue to run, the others is halt here */ + beq cpu0run +secondary_loop: + wfe + b secondary_loop +cpu0run: + ldr r3, rkpm_bootdata_l2ctlr_f + cmp r3, #0 + beq sp_set + ldr r3, rkpm_bootdata_l2ctlr + mcr p15, 1, r3, c9, c0, 2 +sp_set: + ldr sp, rkpm_bootdata_cpusp + ldr r1, rkpm_bootdata_cpu_code + bx r1 +ENDPROC(rockchip_slp_cpu_resume) + +/* Parameters filled in by the kernel */ + +/* Flag for whether to restore L2CTLR on resume */ + .global rkpm_bootdata_l2ctlr_f +rkpm_bootdata_l2ctlr_f: + .long 0 + +/* Saved L2CTLR to restore on resume */ + .global rkpm_bootdata_l2ctlr +rkpm_bootdata_l2ctlr: + .long 0 + +/* CPU resume SP addr */ + .globl rkpm_bootdata_cpusp +rkpm_bootdata_cpusp: + .long 0 + +/* CPU resume function (physical address) */ + .globl rkpm_bootdata_cpu_code +rkpm_bootdata_cpu_code: + .long 0 + +ENTRY(rk3288_bootram_sz) + .word . - rockchip_slp_cpu_resume diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index bb3d07504d8b..2f36c85eec4b 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -7,6 +7,7 @@ config PM_RCAR config PM_RMOBILE bool + select PM_GENERIC_DOMAINS config ARCH_RCAR_GEN1 bool @@ -23,7 +24,7 @@ config ARCH_RCAR_GEN2 config ARCH_RMOBILE bool - select PM_RMOBILE if PM && !ARCH_SHMOBILE_MULTI + select PM_RMOBILE if PM select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_TMU @@ -51,6 +52,11 @@ config ARCH_R7S72100 bool "RZ/A1H (R7S72100)" select SYS_SUPPORTS_SH_MTU2 +config ARCH_R8A73A4 + bool "R-Mobile APE6 (R8A73A40)" + select ARCH_RMOBILE + select RENESAS_IRQC + config ARCH_R8A7740 bool "R-Mobile A1 (R8A77400)" select ARCH_RMOBILE diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 6b4c1f313cc9..3855fb024fdb 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -553,6 +553,7 @@ enum { MSTP001, MSTP314, MSTP313, MSTP312, MSTP311, MSTP304, MSTP303, MSTP302, MSTP301, MSTP300, MSTP411, MSTP410, MSTP403, + MSTP508, MSTP_NR }; #define MSTP(_parent, _reg, _bit, _flags) \ @@ -597,6 +598,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ + [MSTP508] = MSTP(&div4_clks[DIV4_HP], SMSTPCR5, 8, 0), /* INTCA0 */ }; /* The lookups structure below includes duplicate entries for some clocks @@ -677,6 +679,14 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ + CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900000.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900004.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900008.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e690000c.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ /* ICK */ CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c index ac2eecd6f5ea..34608fcf0648 100644 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -9,10 +9,14 @@ * for more details. */ #include +#include #include + #include "common.h" #include "pm-rmobile.h" +#define SYSC_BASE IOMEM(0xe6180000) + #if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) static int r8a7740_pd_a3sm_suspend(void) { @@ -45,41 +49,51 @@ static int r8a7740_pd_d4_suspend(void) static struct rmobile_pm_domain r8a7740_pm_domains[] = { { .genpd.name = "A4LC", + .base = SYSC_BASE, .bit_shift = 1, }, { .genpd.name = "A4MP", + .base = SYSC_BASE, .bit_shift = 2, }, { .genpd.name = "D4", + .base = SYSC_BASE, .bit_shift = 3, .gov = &pm_domain_always_on_gov, .suspend = r8a7740_pd_d4_suspend, }, { .genpd.name = "A4R", + .base = SYSC_BASE, .bit_shift = 5, }, { .genpd.name = "A3RV", + .base = SYSC_BASE, .bit_shift = 6, }, { .genpd.name = "A4S", + .base = SYSC_BASE, .bit_shift = 10, .no_debug = true, }, { .genpd.name = "A3SP", + .base = SYSC_BASE, .bit_shift = 11, .gov = &pm_domain_always_on_gov, .no_debug = true, .suspend = r8a7740_pd_a3sp_suspend, }, { .genpd.name = "A3SM", + .base = SYSC_BASE, .bit_shift = 12, .gov = &pm_domain_always_on_gov, .suspend = r8a7740_pd_a3sm_suspend, }, { .genpd.name = "A3SG", + .base = SYSC_BASE, .bit_shift = 13, }, { .genpd.name = "A4SU", + .base = SYSC_BASE, .bit_shift = 20, }, }; diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index 6f7d56ecf969..95018209ff0b 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -3,6 +3,7 @@ * * Copyright (C) 2012 Renesas Solutions Corp. * Copyright (C) 2012 Kuninori Morimoto + * Copyright (C) 2014 Glider bvba * * based on pm-sh7372.c * Copyright (C) 2011 Magnus Damm @@ -13,16 +14,22 @@ */ #include #include +#include +#include +#include #include #include #include +#include + #include + #include "pm-rmobile.h" /* SYSC */ -#define SPDCR IOMEM(0xe6180008) -#define SWUCR IOMEM(0xe6180014) -#define PSTR IOMEM(0xe6180080) +#define SPDCR 0x08 /* SYS Power Down Control Register */ +#define SWUCR 0x14 /* SYS Wakeup Control Register */ +#define PSTR 0x80 /* Power Status Register */ #define PSTR_RETRIES 100 #define PSTR_DELAY_US 10 @@ -30,8 +37,12 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) { struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); - unsigned int mask = 1 << rmobile_pd->bit_shift; + unsigned int mask; + if (rmobile_pd->bit_shift == ~0) + return -EBUSY; + + mask = 1 << rmobile_pd->bit_shift; if (rmobile_pd->suspend) { int ret = rmobile_pd->suspend(); @@ -39,12 +50,12 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) return ret; } - if (__raw_readl(PSTR) & mask) { + if (__raw_readl(rmobile_pd->base + PSTR) & mask) { unsigned int retry_count; - __raw_writel(mask, SPDCR); + __raw_writel(mask, rmobile_pd->base + SPDCR); for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SPDCR) & mask)) + if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask)) break; cpu_relax(); } @@ -52,7 +63,8 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) if (!rmobile_pd->no_debug) pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", - genpd->name, mask, __raw_readl(PSTR)); + genpd->name, mask, + __raw_readl(rmobile_pd->base + PSTR)); return 0; } @@ -60,17 +72,21 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, bool do_resume) { - unsigned int mask = 1 << rmobile_pd->bit_shift; + unsigned int mask; unsigned int retry_count; int ret = 0; - if (__raw_readl(PSTR) & mask) + if (rmobile_pd->bit_shift == ~0) + return 0; + + mask = 1 << rmobile_pd->bit_shift; + if (__raw_readl(rmobile_pd->base + PSTR) & mask) goto out; - __raw_writel(mask, SWUCR); + __raw_writel(mask, rmobile_pd->base + SWUCR); for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SWUCR) & mask)) + if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask)) break; if (retry_count > PSTR_RETRIES) udelay(PSTR_DELAY_US); @@ -82,7 +98,8 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, if (!rmobile_pd->no_debug) pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", - rmobile_pd->genpd.name, mask, __raw_readl(PSTR)); + rmobile_pd->genpd.name, mask, + __raw_readl(rmobile_pd->base + PSTR)); out: if (ret == 0 && rmobile_pd->resume && do_resume) @@ -101,6 +118,36 @@ static bool rmobile_pd_active_wakeup(struct device *dev) return true; } +static int rmobile_pd_attach_dev(struct generic_pm_domain *domain, + struct device *dev) +{ + int error; + + error = pm_clk_create(dev); + if (error) { + dev_err(dev, "pm_clk_create failed %d\n", error); + return error; + } + + error = pm_clk_add(dev, NULL); + if (error) { + dev_err(dev, "pm_clk_add failed %d\n", error); + goto fail; + } + + return 0; + +fail: + pm_clk_destroy(dev); + return error; +} + +static void rmobile_pd_detach_dev(struct generic_pm_domain *domain, + struct device *dev) +{ + pm_clk_destroy(dev); +} + static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) { struct generic_pm_domain *genpd = &rmobile_pd->genpd; @@ -111,9 +158,13 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; genpd->power_off = rmobile_pd_power_down; genpd->power_on = rmobile_pd_power_up; + genpd->attach_dev = rmobile_pd_attach_dev; + genpd->detach_dev = rmobile_pd_detach_dev; __rmobile_pd_power_up(rmobile_pd, false); } +#ifdef CONFIG_ARCH_SHMOBILE_LEGACY + void rmobile_init_domains(struct rmobile_pm_domain domains[], int num) { int j; @@ -129,8 +180,6 @@ void rmobile_add_device_to_domain_td(const char *domain_name, struct device *dev = &pdev->dev; __pm_genpd_name_add_device(domain_name, dev, td); - if (pm_clk_no_clocks(dev)) - pm_clk_add(dev, NULL); } void rmobile_add_devices_to_domains(struct pm_domain_device data[], @@ -148,3 +197,238 @@ void rmobile_add_devices_to_domains(struct pm_domain_device data[], rmobile_add_device_to_domain_td(data[j].domain_name, data[j].pdev, &latencies); } + +#else /* !CONFIG_ARCH_SHMOBILE_LEGACY */ + +static int rmobile_pd_suspend_busy(void) +{ + /* + * This domain should not be turned off. + */ + return -EBUSY; +} + +static int rmobile_pd_suspend_console(void) +{ + /* + * Serial consoles make use of SCIF hardware located in this domain, + * hence keep the power domain on if "no_console_suspend" is set. + */ + return console_suspend_enabled ? 0 : -EBUSY; +} + +enum pd_types { + PD_NORMAL, + PD_CPU, + PD_CONSOLE, + PD_DEBUG, + PD_MEMCTL, +}; + +#define MAX_NUM_SPECIAL_PDS 16 + +static struct special_pd { + struct device_node *pd; + enum pd_types type; +} special_pds[MAX_NUM_SPECIAL_PDS] __initdata; + +static unsigned int num_special_pds __initdata; + +static const struct of_device_id special_ids[] __initconst = { + { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG }, + { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, }, + { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, }, + { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, }, + { /* sentinel */ }, +}; + +static void __init add_special_pd(struct device_node *np, enum pd_types type) +{ + unsigned int i; + struct device_node *pd; + + pd = of_parse_phandle(np, "power-domains", 0); + if (!pd) + return; + + for (i = 0; i < num_special_pds; i++) + if (pd == special_pds[i].pd && type == special_pds[i].type) { + of_node_put(pd); + return; + } + + if (num_special_pds == ARRAY_SIZE(special_pds)) { + pr_warn("Too many special PM domains\n"); + of_node_put(pd); + return; + } + + pr_debug("Special PM domain %s type %d for %s\n", pd->name, type, + np->full_name); + + special_pds[num_special_pds].pd = pd; + special_pds[num_special_pds].type = type; + num_special_pds++; +} + +static void __init get_special_pds(void) +{ + struct device_node *np; + const struct of_device_id *id; + + /* PM domains containing CPUs */ + for_each_node_by_type(np, "cpu") + add_special_pd(np, PD_CPU); + + /* PM domain containing console */ + if (of_stdout) + add_special_pd(of_stdout, PD_CONSOLE); + + /* PM domains containing other special devices */ + for_each_matching_node_and_match(np, special_ids, &id) + add_special_pd(np, (enum pd_types)id->data); +} + +static void __init put_special_pds(void) +{ + unsigned int i; + + for (i = 0; i < num_special_pds; i++) + of_node_put(special_pds[i].pd); +} + +static enum pd_types __init pd_type(const struct device_node *pd) +{ + unsigned int i; + + for (i = 0; i < num_special_pds; i++) + if (pd == special_pds[i].pd) + return special_pds[i].type; + + return PD_NORMAL; +} + +static void __init rmobile_setup_pm_domain(struct device_node *np, + struct rmobile_pm_domain *pd) +{ + const char *name = pd->genpd.name; + + switch (pd_type(np)) { + case PD_CPU: + /* + * This domain contains the CPU core and therefore it should + * only be turned off if the CPU is not in use. + */ + pr_debug("PM domain %s contains CPU\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_busy; + break; + + case PD_CONSOLE: + pr_debug("PM domain %s contains serial console\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_console; + break; + + case PD_DEBUG: + /* + * This domain contains the Coresight-ETM hardware block and + * therefore it should only be turned off if the debug module + * is not in use. + */ + pr_debug("PM domain %s contains Coresight-ETM\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_busy; + break; + + case PD_MEMCTL: + /* + * This domain contains a memory-controller and therefore it + * should only be turned off if memory is not in use. + */ + pr_debug("PM domain %s contains MEMCTL\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_busy; + break; + + case PD_NORMAL: + break; + } + + rmobile_init_pm_domain(pd); +} + +static int __init rmobile_add_pm_domains(void __iomem *base, + struct device_node *parent, + struct generic_pm_domain *genpd_parent) +{ + struct device_node *np; + + for_each_child_of_node(parent, np) { + struct rmobile_pm_domain *pd; + u32 idx = ~0; + + if (of_property_read_u32(np, "reg", &idx)) { + /* always-on domain */ + } + + pd = kzalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + + pd->genpd.name = np->name; + pd->base = base; + pd->bit_shift = idx; + + rmobile_setup_pm_domain(np, pd); + if (genpd_parent) + pm_genpd_add_subdomain(genpd_parent, &pd->genpd); + of_genpd_add_provider_simple(np, &pd->genpd); + + rmobile_add_pm_domains(base, np, &pd->genpd); + } + return 0; +} + +static int __init rmobile_init_pm_domains(void) +{ + struct device_node *np, *pmd; + bool scanned = false; + void __iomem *base; + int ret = 0; + + for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") { + base = of_iomap(np, 0); + if (!base) { + pr_warn("%s cannot map reg 0\n", np->full_name); + continue; + } + + pmd = of_get_child_by_name(np, "pm-domains"); + if (!pmd) { + pr_warn("%s lacks pm-domains node\n", np->full_name); + continue; + } + + if (!scanned) { + /* Find PM domains containing special blocks */ + get_special_pds(); + scanned = true; + } + + ret = rmobile_add_pm_domains(base, pmd, NULL); + of_node_put(pmd); + if (ret) { + of_node_put(np); + break; + } + } + + put_special_pds(); + + return ret; +} + +core_initcall(rmobile_init_pm_domains); + +#endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h index 8f66b343162b..53219786f539 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.h +++ b/arch/arm/mach-shmobile/pm-rmobile.h @@ -21,6 +21,7 @@ struct rmobile_pm_domain { struct dev_power_governor *gov; int (*suspend)(void); void (*resume)(void); + void __iomem *base; unsigned int bit_shift; bool no_debug; }; @@ -36,7 +37,7 @@ struct pm_domain_device { struct platform_device *pdev; }; -#ifdef CONFIG_PM_RMOBILE +#if defined(CONFIG_PM_RMOBILE) && defined(CONFIG_ARCH_SHMOBILE_LEGACY) extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num); extern void rmobile_add_device_to_domain_td(const char *domain_name, struct platform_device *pdev, diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 0e37da654ed5..c0293ae4b013 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -45,6 +45,8 @@ #define PLLC01STPCR IOMEM(0xe61500c8) /* SYSC */ +#define SYSC_BASE IOMEM(0xe6180000) + #define SBAR IOMEM(0xe6180020) #define WUPRMSK IOMEM(0xe6180028) #define WUPSMSK IOMEM(0xe618002c) @@ -118,24 +120,28 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A4LC", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 1, }, { .genpd.name = "A4MP", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 2, }, { .genpd.name = "D4", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 3, }, { .genpd.name = "A4R", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 5, .suspend = sh7372_a4r_pd_suspend, .resume = sh7372_intcs_resume, @@ -144,18 +150,21 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A3RV", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 6, }, { .genpd.name = "A3RI", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 8, }, { .genpd.name = "A4S", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 10, .gov = &pm_domain_always_on_gov, .no_debug = true, @@ -166,6 +175,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A3SP", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 11, .gov = &pm_domain_always_on_gov, .no_debug = true, @@ -175,6 +185,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A3SG", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 13, }, }; diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index cc9470dfb1ce..d1fa625e61f5 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -52,15 +52,13 @@ void __init rcar_gen2_timer_init(void) { #if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK) u32 mode = rcar_gen2_read_mode_pins(); - bool is_e2 = (bool)of_find_compatible_node(NULL, NULL, - "renesas,r8a7794"); #endif #ifdef CONFIG_ARM_ARCH_TIMER void __iomem *base; int extal_mhz = 0; u32 freq; - if (is_e2) { + if (of_machine_is_compatible("renesas,r8a7794")) { freq = 260000000 / 8; /* ZS / 8 */ /* CNTVOFF has to be initialized either from non-secure * Hypervisor mode or secure Monitor mode with SCR.NS==1. diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 3f761f839043..9fc280e24ef4 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -56,7 +56,7 @@ static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = { [3] = &r8a7779_ch_cpu3, }; -#ifdef CONFIG_HAVE_ARM_TWD +#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM) static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29); void __init r8a7779_register_twd(void) { diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c index 3cf6ef8d4317..b067390cef4e 100644 --- a/arch/arm/mach-sti/board-dt.c +++ b/arch/arm/mach-sti/board-dt.c @@ -18,6 +18,7 @@ static const char *stih41x_dt_match[] __initdata = { "st,stih415", "st,stih416", "st,stih407", + "st,stih418", NULL }; diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c index e44d028555a4..587b0468efcc 100644 --- a/arch/arm/mach-sunxi/platsmp.c +++ b/arch/arm/mach-sunxi/platsmp.c @@ -120,4 +120,4 @@ static struct smp_operations sun6i_smp_ops __initdata = { .smp_prepare_cpus = sun6i_smp_prepare_cpus, .smp_boot_secondary = sun6i_smp_boot_secondary, }; -CPU_METHOD_OF_DECLARE(sun6i_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); +CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 1f986758784a..1bc811a74a9f 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -13,9 +13,15 @@ #include #include #include +#include #include +static void __init sunxi_dt_cpufreq_init(void) +{ + platform_device_register_simple("cpufreq-dt", -1, NULL, 0); +} + static const char * const sunxi_board_dt_compat[] = { "allwinner,sun4i-a10", "allwinner,sun5i-a10s", @@ -25,10 +31,12 @@ static const char * const sunxi_board_dt_compat[] = { DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") .dt_compat = sunxi_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun6i_board_dt_compat[] = { "allwinner,sun6i-a31", + "allwinner,sun6i-a31s", NULL, }; @@ -44,6 +52,7 @@ static void __init sun6i_timer_init(void) DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family") .init_time = sun6i_timer_init, .dt_compat = sun6i_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun7i_board_dt_compat[] = { @@ -53,6 +62,7 @@ static const char * const sun7i_board_dt_compat[] = { DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family") .dt_compat = sun7i_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun8i_board_dt_compat[] = { @@ -62,6 +72,7 @@ static const char * const sun8i_board_dt_compat[] = { DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family") .dt_compat = sun8i_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun9i_board_dt_compat[] = { diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d0be9a1ef6b8..5d1a318f1302 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -27,6 +27,7 @@ config ARCH_TEGRA_2x_SOC select PINCTRL_TEGRA20 select PL310_ERRATA_727915 if CACHE_L2X0 select PL310_ERRATA_769419 if CACHE_L2X0 + select TEGRA_TIMER help Support for NVIDIA Tegra AP20 and T20 processors, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -37,6 +38,7 @@ config ARCH_TEGRA_3x_SOC select ARM_ERRATA_764369 if SMP select PINCTRL_TEGRA30 select PL310_ERRATA_769419 if CACHE_L2X0 + select TEGRA_TIMER help Support for NVIDIA Tegra T30 processor family, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -47,6 +49,7 @@ config ARCH_TEGRA_114_SOC select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA114 + select TEGRA_TIMER help Support for NVIDIA Tegra T114 processor family, based on the ARM CortexA15MP CPU @@ -56,6 +59,7 @@ config ARCH_TEGRA_124_SOC select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA124 + select TEGRA_TIMER help Support for NVIDIA Tegra T124 processor family, based on the ARM CortexA15MP CPU diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index aaa5162c1509..78e5e007f52d 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -9,6 +9,8 @@ config ARCH_ZYNQ select HAVE_ARM_TWD if SMP select ICST select MFD_SYSCON + select PINCTRL + select PINCTRL_ZYNQ select SOC_BUS help Support for Xilinx Zynq ARM Cortex A9 Platform diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 26f92c28d22b..c887196cfdbe 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -146,8 +146,6 @@ static void __init zynq_init_machine(void) platform_device_register(&zynq_cpuidle_device); platform_device_register_full(&devinfo); - - zynq_slcr_init(); } static void __init zynq_timer_init(void) diff --git a/arch/arm/mach-zynq/pm.c b/arch/arm/mach-zynq/pm.c index 911fcf865be8..fa44fc1b6dd5 100644 --- a/arch/arm/mach-zynq/pm.c +++ b/arch/arm/mach-zynq/pm.c @@ -61,7 +61,7 @@ static void __iomem *zynq_pm_ioremap(const char *comp) /** * zynq_pm_late_init() - Power management init * - * Initialization of power management related featurs and infrastructure. + * Initialization of power management related features and infrastructure. */ void __init zynq_pm_late_init(void) { diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index d4cb50cf97c0..c3c24fd8b306 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -47,11 +47,6 @@ static struct regmap *zynq_slcr_regmap; */ static int zynq_slcr_write(u32 val, u32 offset) { - if (!zynq_slcr_regmap) { - writel(val, zynq_slcr_base + offset); - return 0; - } - return regmap_write(zynq_slcr_regmap, offset, val); } @@ -65,12 +60,7 @@ static int zynq_slcr_write(u32 val, u32 offset) */ static int zynq_slcr_read(u32 *val, u32 offset) { - if (zynq_slcr_regmap) - return regmap_read(zynq_slcr_regmap, offset, val); - - *val = readl(zynq_slcr_base + offset); - - return 0; + return regmap_read(zynq_slcr_regmap, offset, val); } /** @@ -195,23 +185,6 @@ void zynq_slcr_cpu_state_write(int cpu, bool die) writel(state, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); } -/** - * zynq_slcr_init - Regular slcr driver init - * Return: 0 on success, negative errno otherwise. - * - * Called early during boot from platform code to remap SLCR area. - */ -int __init zynq_slcr_init(void) -{ - zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr"); - if (IS_ERR(zynq_slcr_regmap)) { - pr_err("%s: failed to find zynq-slcr\n", __func__); - return -ENODEV; - } - - return 0; -} - /** * zynq_early_slcr_init - Early slcr init function * @@ -237,6 +210,12 @@ int __init zynq_early_slcr_init(void) np->data = (__force void *)zynq_slcr_base; + zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr"); + if (IS_ERR(zynq_slcr_regmap)) { + pr_err("%s: failed to find zynq-slcr\n", __func__); + return -ENODEV; + } + /* unlock the SLCR so that registers can be changed */ zynq_slcr_unlock(); diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c index 360618ee39e5..71333bb61013 100644 --- a/arch/arm/plat-samsung/cpu.c +++ b/arch/arm/plat-samsung/cpu.c @@ -40,10 +40,14 @@ void __init s3c64xx_init_cpu(void) } samsung_cpu_rev = 0; + + pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id); } void __init s5p_init_cpu(void __iomem *cpuid_addr) { samsung_cpu_id = __raw_readl(cpuid_addr); samsung_cpu_rev = samsung_cpu_id & 0xFF; + + pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id); } diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 81bf297f1034..fb9ec6221730 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -58,6 +58,7 @@ #include #include #include +#include /* * DDR target is the same on all platforms. @@ -69,6 +70,7 @@ */ #define WIN_CTRL_OFF 0x0000 #define WIN_CTRL_ENABLE BIT(0) +#define WIN_CTRL_SYNCBARRIER BIT(1) #define WIN_CTRL_TGT_MASK 0xf0 #define WIN_CTRL_TGT_SHIFT 4 #define WIN_CTRL_ATTR_MASK 0xff00 @@ -82,6 +84,9 @@ #define WIN_REMAP_LOW 0xffff0000 #define WIN_REMAP_HI_OFF 0x000c +#define UNIT_SYNC_BARRIER_OFF 0x84 +#define UNIT_SYNC_BARRIER_ALL 0xFFFF + #define ATTR_HW_COHERENCY (0x1 << 4) #define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) @@ -97,7 +102,9 @@ /* Relative to mbusbridge_base */ #define MBUS_BRIDGE_CTRL_OFF 0x0 +#define MBUS_BRIDGE_SIZE_MASK 0xffff0000 #define MBUS_BRIDGE_BASE_OFF 0x4 +#define MBUS_BRIDGE_BASE_MASK 0xffff0000 /* Maximum number of windows, for all known platforms */ #define MBUS_WINS_MAX 20 @@ -106,9 +113,9 @@ struct mvebu_mbus_state; struct mvebu_mbus_soc_data { unsigned int num_wins; - unsigned int num_remappable_wins; bool has_mbus_bridge; unsigned int (*win_cfg_offset)(const int win); + unsigned int (*win_remap_offset)(const int win); void (*setup_cpu_target)(struct mvebu_mbus_state *s); int (*save_cpu_target)(struct mvebu_mbus_state *s, u32 *store_addr); @@ -154,6 +161,13 @@ const struct mbus_dram_target_info *mv_mbus_dram_info(void) } EXPORT_SYMBOL_GPL(mv_mbus_dram_info); +/* Checks whether the given window has remap capability */ +static bool mvebu_mbus_window_is_remappable(struct mvebu_mbus_state *mbus, + const int win) +{ + return mbus->soc->win_remap_offset(win) != MVEBU_MBUS_NO_REMAP; +} + /* * Functions to manipulate the address decoding windows */ @@ -185,9 +199,12 @@ static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus, *attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT; if (remap) { - if (win < mbus->soc->num_remappable_wins) { - u32 remap_low = readl(addr + WIN_REMAP_LO_OFF); - u32 remap_hi = readl(addr + WIN_REMAP_HI_OFF); + if (mvebu_mbus_window_is_remappable(mbus, win)) { + u32 remap_low, remap_hi; + void __iomem *addr_rmp = mbus->mbuswins_base + + mbus->soc->win_remap_offset(win); + remap_low = readl(addr_rmp + WIN_REMAP_LO_OFF); + remap_hi = readl(addr_rmp + WIN_REMAP_HI_OFF); *remap = ((u64)remap_hi << 32) | remap_low; } else *remap = 0; @@ -200,10 +217,11 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus, void __iomem *addr; addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win); - writel(0, addr + WIN_BASE_OFF); writel(0, addr + WIN_CTRL_OFF); - if (win < mbus->soc->num_remappable_wins) { + + if (mvebu_mbus_window_is_remappable(mbus, win)) { + addr = mbus->mbuswins_base + mbus->soc->win_remap_offset(win); writel(0, addr + WIN_REMAP_LO_OFF); writel(0, addr + WIN_REMAP_HI_OFF); } @@ -211,14 +229,6 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus, /* Checks whether the given window number is available */ -/* On Armada XP, 375 and 38x the MBus window 13 has the remap - * capability, like windows 0 to 7. However, the mvebu-mbus driver - * isn't currently taking into account this special case, which means - * that when window 13 is actually used, the remap registers are left - * to 0, making the device using this MBus window unavailable. The - * quick fix for stable is to not use window 13. A follow up patch - * will correctly handle this window. -*/ static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus, const int win) { @@ -226,9 +236,6 @@ static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus, mbus->soc->win_cfg_offset(win); u32 ctrl = readl(addr + WIN_CTRL_OFF); - if (win == 13) - return false; - return !(ctrl & WIN_CTRL_ENABLE); } @@ -316,17 +323,22 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus, ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | (attr << WIN_CTRL_ATTR_SHIFT) | (target << WIN_CTRL_TGT_SHIFT) | + WIN_CTRL_SYNCBARRIER | WIN_CTRL_ENABLE; writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF); writel(ctrl, addr + WIN_CTRL_OFF); - if (win < mbus->soc->num_remappable_wins) { + + if (mvebu_mbus_window_is_remappable(mbus, win)) { + void __iomem *addr_rmp = mbus->mbuswins_base + + mbus->soc->win_remap_offset(win); + if (remap == MVEBU_MBUS_NO_REMAP) remap_addr = base; else remap_addr = remap; - writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF); - writel(0, addr + WIN_REMAP_HI_OFF); + writel(remap_addr & WIN_REMAP_LOW, addr_rmp + WIN_REMAP_LO_OFF); + writel(0, addr_rmp + WIN_REMAP_HI_OFF); } return 0; @@ -340,19 +352,27 @@ static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus, int win; if (remap == MVEBU_MBUS_NO_REMAP) { - for (win = mbus->soc->num_remappable_wins; - win < mbus->soc->num_wins; win++) + for (win = 0; win < mbus->soc->num_wins; win++) { + if (mvebu_mbus_window_is_remappable(mbus, win)) + continue; + if (mvebu_mbus_window_is_free(mbus, win)) return mvebu_mbus_setup_window(mbus, win, base, size, remap, target, attr); + } } + for (win = 0; win < mbus->soc->num_wins; win++) { + /* Skip window if need remap but is not supported */ + if ((remap != MVEBU_MBUS_NO_REMAP) && + !mvebu_mbus_window_is_remappable(mbus, win)) + continue; - for (win = 0; win < mbus->soc->num_wins; win++) if (mvebu_mbus_window_is_free(mbus, win)) return mvebu_mbus_setup_window(mbus, win, base, size, remap, target, attr); + } return -ENOMEM; } @@ -464,7 +484,7 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) ((wbase & (u64)(wsize - 1)) != 0)) seq_puts(seq, " (Invalid base/size!!)"); - if (win < mbus->soc->num_remappable_wins) { + if (mvebu_mbus_window_is_remappable(mbus, win)) { seq_printf(seq, " (remap %016llx)\n", (unsigned long long)wremap); } else @@ -490,12 +510,12 @@ static const struct file_operations mvebu_devs_debug_fops = { * SoC-specific functions and definitions */ -static unsigned int orion_mbus_win_offset(int win) +static unsigned int generic_mbus_win_cfg_offset(int win) { return win << 4; } -static unsigned int armada_370_xp_mbus_win_offset(int win) +static unsigned int armada_370_xp_mbus_win_cfg_offset(int win) { /* The register layout is a bit annoying and the below code * tries to cope with it. @@ -515,7 +535,7 @@ static unsigned int armada_370_xp_mbus_win_offset(int win) return 0x90 + ((win - 8) << 3); } -static unsigned int mv78xx0_mbus_win_offset(int win) +static unsigned int mv78xx0_mbus_win_cfg_offset(int win) { if (win < 8) return win << 4; @@ -523,36 +543,140 @@ static unsigned int mv78xx0_mbus_win_offset(int win) return 0x900 + ((win - 8) << 4); } +static unsigned int generic_mbus_win_remap_2_offset(int win) +{ + if (win < 2) + return generic_mbus_win_cfg_offset(win); + else + return MVEBU_MBUS_NO_REMAP; +} + +static unsigned int generic_mbus_win_remap_4_offset(int win) +{ + if (win < 4) + return generic_mbus_win_cfg_offset(win); + else + return MVEBU_MBUS_NO_REMAP; +} + +static unsigned int generic_mbus_win_remap_8_offset(int win) +{ + if (win < 8) + return generic_mbus_win_cfg_offset(win); + else + return MVEBU_MBUS_NO_REMAP; +} + +static unsigned int armada_xp_mbus_win_remap_offset(int win) +{ + if (win < 8) + return generic_mbus_win_cfg_offset(win); + else if (win == 13) + return 0xF0 - WIN_REMAP_LO_OFF; + else + return MVEBU_MBUS_NO_REMAP; +} + +/* + * Use the memblock information to find the MBus bridge hole in the + * physical address space. + */ +static void __init +mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end) +{ + struct memblock_region *r; + uint64_t s = 0; + + for_each_memblock(memory, r) { + /* + * This part of the memory is above 4 GB, so we don't + * care for the MBus bridge hole. + */ + if (r->base >= 0x100000000) + continue; + + /* + * The MBus bridge hole is at the end of the RAM under + * the 4 GB limit. + */ + if (r->base + r->size > s) + s = r->base + r->size; + } + + *start = s; + *end = 0x100000000; +} + static void __init mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) { int i; int cs; + uint64_t mbus_bridge_base, mbus_bridge_end; mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; + mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end); + for (i = 0, cs = 0; i < 4; i++) { - u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i)); - u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i)); + u64 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i)); + u64 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i)); + u64 end; + struct mbus_dram_window *w; + + /* Ignore entries that are not enabled */ + if (!(size & DDR_SIZE_ENABLED)) + continue; /* - * We only take care of entries for which the chip - * select is enabled, and that don't have high base - * address bits set (devices can only access the first - * 32 bits of the memory). + * Ignore entries whose base address is above 2^32, + * since devices cannot DMA to such high addresses */ - if ((size & DDR_SIZE_ENABLED) && - !(base & DDR_BASE_CS_HIGH_MASK)) { - struct mbus_dram_window *w; + if (base & DDR_BASE_CS_HIGH_MASK) + continue; - w = &mvebu_mbus_dram_info.cs[cs++]; - w->cs_index = i; - w->mbus_attr = 0xf & ~(1 << i); - if (mbus->hw_io_coherency) - w->mbus_attr |= ATTR_HW_COHERENCY; - w->base = base & DDR_BASE_CS_LOW_MASK; - w->size = (size | ~DDR_SIZE_MASK) + 1; + base = base & DDR_BASE_CS_LOW_MASK; + size = (size | ~DDR_SIZE_MASK) + 1; + end = base + size; + + /* + * Adjust base/size of the current CS to make sure it + * doesn't overlap with the MBus bridge hole. This is + * particularly important for devices that do DMA from + * DRAM to a SRAM mapped in a MBus window, such as the + * CESA cryptographic engine. + */ + + /* + * The CS is fully enclosed inside the MBus bridge + * area, so ignore it. + */ + if (base >= mbus_bridge_base && end <= mbus_bridge_end) + continue; + + /* + * Beginning of CS overlaps with end of MBus, raise CS + * base address, and shrink its size. + */ + if (base >= mbus_bridge_base && end > mbus_bridge_end) { + size -= mbus_bridge_end - base; + base = mbus_bridge_end; } + + /* + * End of CS overlaps with beginning of MBus, shrink + * CS size. + */ + if (base < mbus_bridge_base && end > mbus_bridge_base) + size -= end - mbus_bridge_base; + + w = &mvebu_mbus_dram_info.cs[cs++]; + w->cs_index = i; + w->mbus_attr = 0xf & ~(1 << i); + if (mbus->hw_io_coherency) + w->mbus_attr |= ATTR_HW_COHERENCY; + w->base = base; + w->size = size; } mvebu_mbus_dram_info.num_cs = cs; } @@ -632,30 +756,40 @@ int mvebu_mbus_save_cpu_target(u32 *store_addr) return mbus_state.soc->save_cpu_target(&mbus_state, store_addr); } -static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = { +static const struct mvebu_mbus_soc_data armada_370_mbus_data = { .num_wins = 20, - .num_remappable_wins = 8, .has_mbus_bridge = true, - .win_cfg_offset = armada_370_xp_mbus_win_offset, - .save_cpu_target = mvebu_mbus_default_save_cpu_target, + .win_cfg_offset = armada_370_xp_mbus_win_cfg_offset, + .win_remap_offset = generic_mbus_win_remap_8_offset, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, +}; + +static const struct mvebu_mbus_soc_data armada_xp_mbus_data = { + .num_wins = 20, + .has_mbus_bridge = true, + .win_cfg_offset = armada_370_xp_mbus_win_cfg_offset, + .win_remap_offset = armada_xp_mbus_win_remap_offset, + .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, + .show_cpu_target = mvebu_sdram_debug_show_orion, + .save_cpu_target = mvebu_mbus_default_save_cpu_target, }; static const struct mvebu_mbus_soc_data kirkwood_mbus_data = { .num_wins = 8, - .num_remappable_wins = 4, - .win_cfg_offset = orion_mbus_win_offset, + .win_cfg_offset = generic_mbus_win_cfg_offset, .save_cpu_target = mvebu_mbus_default_save_cpu_target, + .win_remap_offset = generic_mbus_win_remap_4_offset, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; static const struct mvebu_mbus_soc_data dove_mbus_data = { .num_wins = 8, - .num_remappable_wins = 4, - .win_cfg_offset = orion_mbus_win_offset, + .win_cfg_offset = generic_mbus_win_cfg_offset, .save_cpu_target = mvebu_mbus_dove_save_cpu_target, + .win_remap_offset = generic_mbus_win_remap_4_offset, .setup_cpu_target = mvebu_mbus_dove_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_dove, }; @@ -666,36 +800,40 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = { */ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = { .num_wins = 8, - .num_remappable_wins = 4, - .win_cfg_offset = orion_mbus_win_offset, + .win_cfg_offset = generic_mbus_win_cfg_offset, .save_cpu_target = mvebu_mbus_default_save_cpu_target, + .win_remap_offset = generic_mbus_win_remap_4_offset, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = { .num_wins = 8, - .num_remappable_wins = 2, - .win_cfg_offset = orion_mbus_win_offset, + .win_cfg_offset = generic_mbus_win_cfg_offset, .save_cpu_target = mvebu_mbus_default_save_cpu_target, + .win_remap_offset = generic_mbus_win_remap_2_offset, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = { .num_wins = 14, - .num_remappable_wins = 8, - .win_cfg_offset = mv78xx0_mbus_win_offset, + .win_cfg_offset = mv78xx0_mbus_win_cfg_offset, .save_cpu_target = mvebu_mbus_default_save_cpu_target, + .win_remap_offset = generic_mbus_win_remap_8_offset, .setup_cpu_target = mvebu_mbus_default_setup_cpu_target, .show_cpu_target = mvebu_sdram_debug_show_orion, }; static const struct of_device_id of_mvebu_mbus_ids[] = { { .compatible = "marvell,armada370-mbus", - .data = &armada_370_xp_mbus_data, }, + .data = &armada_370_mbus_data, }, + { .compatible = "marvell,armada375-mbus", + .data = &armada_xp_mbus_data, }, + { .compatible = "marvell,armada380-mbus", + .data = &armada_xp_mbus_data, }, { .compatible = "marvell,armadaxp-mbus", - .data = &armada_370_xp_mbus_data, }, + .data = &armada_xp_mbus_data, }, { .compatible = "marvell,kirkwood-mbus", .data = &kirkwood_mbus_data, }, { .compatible = "marvell,dove-mbus", @@ -802,15 +940,19 @@ static int mvebu_mbus_suspend(void) for (win = 0; win < s->soc->num_wins; win++) { void __iomem *addr = s->mbuswins_base + s->soc->win_cfg_offset(win); + void __iomem *addr_rmp; s->wins[win].base = readl(addr + WIN_BASE_OFF); s->wins[win].ctrl = readl(addr + WIN_CTRL_OFF); - if (win >= s->soc->num_remappable_wins) + if (!mvebu_mbus_window_is_remappable(s, win)) continue; - s->wins[win].remap_lo = readl(addr + WIN_REMAP_LO_OFF); - s->wins[win].remap_hi = readl(addr + WIN_REMAP_HI_OFF); + addr_rmp = s->mbuswins_base + + s->soc->win_remap_offset(win); + + s->wins[win].remap_lo = readl(addr_rmp + WIN_REMAP_LO_OFF); + s->wins[win].remap_hi = readl(addr_rmp + WIN_REMAP_HI_OFF); } s->mbus_bridge_ctrl = readl(s->mbusbridge_base + @@ -834,15 +976,19 @@ static void mvebu_mbus_resume(void) for (win = 0; win < s->soc->num_wins; win++) { void __iomem *addr = s->mbuswins_base + s->soc->win_cfg_offset(win); + void __iomem *addr_rmp; writel(s->wins[win].base, addr + WIN_BASE_OFF); writel(s->wins[win].ctrl, addr + WIN_CTRL_OFF); - if (win >= s->soc->num_remappable_wins) + if (!mvebu_mbus_window_is_remappable(s, win)) continue; - writel(s->wins[win].remap_lo, addr + WIN_REMAP_LO_OFF); - writel(s->wins[win].remap_hi, addr + WIN_REMAP_HI_OFF); + addr_rmp = s->mbuswins_base + + s->soc->win_remap_offset(win); + + writel(s->wins[win].remap_lo, addr_rmp + WIN_REMAP_LO_OFF); + writel(s->wins[win].remap_hi, addr_rmp + WIN_REMAP_HI_OFF); } } @@ -857,7 +1003,8 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, phys_addr_t sdramwins_phys_base, size_t sdramwins_size, phys_addr_t mbusbridge_phys_base, - size_t mbusbridge_size) + size_t mbusbridge_size, + bool is_coherent) { int win; @@ -889,6 +1036,10 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, mbus->soc->setup_cpu_target(mbus); + if (is_coherent) + writel(UNIT_SYNC_BARRIER_ALL, + mbus->mbuswins_base + UNIT_SYNC_BARRIER_OFF); + register_syscore_ops(&mvebu_mbus_syscore_ops); return 0; @@ -916,7 +1067,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, mbuswins_phys_base, mbuswins_size, sdramwins_phys_base, - sdramwins_size, 0, 0); + sdramwins_size, 0, 0, false); } #ifdef CONFIG_OF @@ -1118,7 +1269,8 @@ int __init mvebu_mbus_dt_init(bool is_coherent) sdramwins_res.start, resource_size(&sdramwins_res), mbusbridge_res.start, - resource_size(&mbusbridge_res)); + resource_size(&mbusbridge_res), + is_coherent); if (ret) return ret; diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 386999b4f8eb..f07c8152e5cc 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -27,6 +27,15 @@ void __iomem *at91_pmc_base; EXPORT_SYMBOL_GPL(at91_pmc_base); +void at91rm9200_idle(void) +{ + /* + * Disable the processor clock. The processor will be automatically + * re-enabled by an interrupt or by a reset. + */ + at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); +} + void at91sam9_idle(void) { at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK); diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 570202582dcf..1818f404538d 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -1226,6 +1226,7 @@ static void __init sun6i_init_clocks(struct device_node *node) ARRAY_SIZE(sun6i_critical_clocks)); } CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); +CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); static void __init sun9i_init_clocks(struct device_node *node) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 717f40e875fc..1c2506f68122 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -54,6 +54,9 @@ config SUN5I_HSTIMER select CLKSRC_MMIO bool +config TEGRA_TIMER + bool + config VT8500_TIMER bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 3359121570c7..752d5c70b0ef 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -29,7 +29,7 @@ obj-$(CONFIG_ARCH_U300) += timer-u300.o obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o -obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o +obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 011a3363c265..c0d660f1aaac 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -81,6 +81,7 @@ static const struct of_device_id car_match[] __initconst = { { .compatible = "nvidia,tegra30-car", }, { .compatible = "nvidia,tegra114-car", }, { .compatible = "nvidia,tegra124-car", }, + { .compatible = "nvidia,tegra132-car", }, {}, }; diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index 8646fa920d8d..4d2f71bf65c5 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -56,7 +56,7 @@ struct tegra_fuse_info { static void __iomem *fuse_base; static struct clk *fuse_clk; -static struct tegra_fuse_info *fuse_info; +static const struct tegra_fuse_info *fuse_info; u32 tegra30_fuse_readl(const unsigned int offset) { @@ -78,18 +78,18 @@ u32 tegra30_fuse_readl(const unsigned int offset) return val; } -static struct tegra_fuse_info tegra30_info = { +static const struct tegra_fuse_info tegra30_info = { .size = 0x2a4, .spare_bit = 0x144, .speedo_idx = SPEEDO_TEGRA30, }; -static struct tegra_fuse_info tegra114_info = { +static const struct tegra_fuse_info tegra114_info = { .size = 0x2a0, .speedo_idx = SPEEDO_TEGRA114, }; -static struct tegra_fuse_info tegra124_info = { +static const struct tegra_fuse_info tegra124_info = { .size = 0x300, .speedo_idx = SPEEDO_TEGRA124, }; @@ -182,6 +182,7 @@ static void __init legacy_fuse_init(void) fuse_info = &tegra114_info; break; case TEGRA124: + case TEGRA132: fuse_info = &tegra124_info; break; default: diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index a2c0ceb95f8f..c956395cf46f 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -70,6 +70,10 @@ #define PMC_SCRATCH41 0x140 +#define PMC_SENSOR_CTRL 0x1b0 +#define PMC_SENSOR_CTRL_SCRATCH_WRITE (1 << 2) +#define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1) + #define IO_DPD_REQ 0x1b8 #define IO_DPD_REQ_CODE_IDLE (0 << 30) #define IO_DPD_REQ_CODE_OFF (1 << 30) @@ -81,6 +85,18 @@ #define IO_DPD2_STATUS 0x1c4 #define SEL_DPD_TIM 0x1c8 +#define PMC_SCRATCH54 0x258 +#define PMC_SCRATCH54_DATA_SHIFT 8 +#define PMC_SCRATCH54_ADDR_SHIFT 0 + +#define PMC_SCRATCH55 0x25c +#define PMC_SCRATCH55_RESET_TEGRA (1 << 31) +#define PMC_SCRATCH55_CNTRL_ID_SHIFT 27 +#define PMC_SCRATCH55_PINMUX_SHIFT 24 +#define PMC_SCRATCH55_16BITOP (1 << 15) +#define PMC_SCRATCH55_CHECKSUM_SHIFT 16 +#define PMC_SCRATCH55_I2CSLV1_SHIFT 0 + #define GPU_RG_CNTRL 0x2d4 struct tegra_pmc_soc { @@ -88,6 +104,9 @@ struct tegra_pmc_soc { const char *const *powergates; unsigned int num_cpu_powergates; const u8 *cpu_powergates; + + bool has_tsense_reset; + bool has_gpu_clamps; }; /** @@ -110,6 +129,7 @@ struct tegra_pmc_soc { * @powergates_lock: mutex for power gate register access */ struct tegra_pmc { + struct device *dev; void __iomem *base; struct clk *clk; @@ -225,11 +245,11 @@ int tegra_powergate_remove_clamping(int id) return -EINVAL; /* - * The Tegra124 GPU has a separate register (with different semantics) - * to remove clamps. + * On Tegra124 and later, the clamps for the GPU are controlled by a + * separate register (with different semantics). */ - if (tegra_get_chip_id() == TEGRA124) { - if (id == TEGRA_POWERGATE_3D) { + if (id == TEGRA_POWERGATE_3D) { + if (pmc->soc->has_gpu_clamps) { tegra_pmc_writel(0, GPU_RG_CNTRL); return 0; } @@ -703,6 +723,83 @@ static void tegra_pmc_init(struct tegra_pmc *pmc) tegra_pmc_writel(value, PMC_CNTRL); } +void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) +{ + static const char disabled[] = "emergency thermal reset disabled"; + u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux; + struct device *dev = pmc->dev; + struct device_node *np; + u32 value, checksum; + + if (!pmc->soc->has_tsense_reset) + goto out; + + np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip"); + if (!np) { + dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled); + goto out; + } + + if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) { + dev_err(dev, "I2C controller ID missing, %s.\n", disabled); + goto out; + } + + if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) { + dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled); + goto out; + } + + if (of_property_read_u32(np, "nvidia,reg-addr", ®_addr)) { + dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled); + goto out; + } + + if (of_property_read_u32(np, "nvidia,reg-data", ®_data)) { + dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled); + goto out; + } + + if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux)) + pinmux = 0; + + value = tegra_pmc_readl(PMC_SENSOR_CTRL); + value |= PMC_SENSOR_CTRL_SCRATCH_WRITE; + tegra_pmc_writel(value, PMC_SENSOR_CTRL); + + value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) | + (reg_addr << PMC_SCRATCH54_ADDR_SHIFT); + tegra_pmc_writel(value, PMC_SCRATCH54); + + value = PMC_SCRATCH55_RESET_TEGRA; + value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT; + value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT; + value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT; + + /* + * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will + * contain the checksum and are currently zero, so they are not added. + */ + checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff) + + ((value >> 24) & 0xff); + checksum &= 0xff; + checksum = 0x100 - checksum; + + value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT; + + tegra_pmc_writel(value, PMC_SCRATCH55); + + value = tegra_pmc_readl(PMC_SENSOR_CTRL); + value |= PMC_SENSOR_CTRL_ENABLE_RST; + tegra_pmc_writel(value, PMC_SENSOR_CTRL); + + dev_info(pmc->dev, "emergency thermal reset enabled\n"); + +out: + of_node_put(np); + return; +} + static int tegra_pmc_probe(struct platform_device *pdev) { void __iomem *base = pmc->base; @@ -728,8 +825,12 @@ static int tegra_pmc_probe(struct platform_device *pdev) return err; } + pmc->dev = &pdev->dev; + tegra_pmc_init(pmc); + tegra_pmc_init_tsense_reset(pmc); + if (IS_ENABLED(CONFIG_DEBUG_FS)) { err = tegra_powergate_debugfs_init(); if (err < 0) @@ -739,7 +840,7 @@ static int tegra_pmc_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) static int tegra_pmc_suspend(struct device *dev) { tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41); @@ -753,10 +854,11 @@ static int tegra_pmc_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume); +#endif + static const char * const tegra20_powergates[] = { [TEGRA_POWERGATE_CPU] = "cpu", [TEGRA_POWERGATE_3D] = "3d", @@ -772,6 +874,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .powergates = tegra20_powergates, .num_cpu_powergates = 0, .cpu_powergates = NULL, + .has_tsense_reset = false, + .has_gpu_clamps = false, }; static const char * const tegra30_powergates[] = { @@ -803,6 +907,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .powergates = tegra30_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), .cpu_powergates = tegra30_cpu_powergates, + .has_tsense_reset = true, + .has_gpu_clamps = false, }; static const char * const tegra114_powergates[] = { @@ -838,6 +944,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .powergates = tegra114_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), .cpu_powergates = tegra114_cpu_powergates, + .has_tsense_reset = true, + .has_gpu_clamps = false, }; static const char * const tegra124_powergates[] = { @@ -879,6 +987,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { .powergates = tegra124_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates), .cpu_powergates = tegra124_cpu_powergates, + .has_tsense_reset = true, + .has_gpu_clamps = true, }; static const struct of_device_id tegra_pmc_match[] = { @@ -894,7 +1004,9 @@ static struct platform_driver tegra_pmc_driver = { .name = "tegra-pmc", .suppress_bind_attrs = true, .of_match_table = tegra_pmc_match, +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) .pm = &tegra_pmc_pm_ops, +#endif }, .probe = tegra_pmc_probe, }; diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index 801c0ac50c47..979d24a6799f 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h @@ -192,6 +192,7 @@ #define VF610_PLL5_BYPASS 179 #define VF610_PLL6_BYPASS 180 #define VF610_PLL7_BYPASS 181 -#define VF610_CLK_END 182 +#define VF610_CLK_SNVS 182 +#define VF610_CLK_END 183 #endif /* __DT_BINDINGS_CLOCK_VF610_H */ diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 8e1249474e84..b5f7b5f8d008 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -21,6 +21,7 @@ #define TEGRA30 0x30 #define TEGRA114 0x35 #define TEGRA124 0x40 +#define TEGRA132 0x13 #define TEGRA_FUSE_SKU_CALIB_0 0xf0 #define TEGRA30_FUSE_SATA_CALIB 0x124 diff --git a/include/soc/tegra/pm.h b/include/soc/tegra/pm.h index 30fe2078a547..03909101d4e7 100644 --- a/include/soc/tegra/pm.h +++ b/include/soc/tegra/pm.h @@ -17,7 +17,7 @@ enum tegra_suspend_mode { TEGRA_MAX_SUSPEND_MODE, }; -#ifdef CONFIG_PM_SLEEP +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) enum tegra_suspend_mode tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);