diff options
281 files changed, 6271 insertions, 2321 deletions
diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt new file mode 100644 index 0000000..f8d4134 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt @@ -0,0 +1,53 @@ +Ingenic SoC CGU binding + +The CGU in an Ingenic SoC provides all the clocks generated on-chip. It +typically includes a variety of PLLs, multiplexers, dividers & gates in order +to provide many different clock signals derived from only 2 external source +clocks. + +Required properties: +- compatible : Should be "ingenic,<soctype>-cgu". + For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu". +- reg : The address & length of the CGU registers. +- clocks : List of phandle & clock specifiers for clocks external to the CGU. + Two such external clocks should be specified - first the external crystal + "ext" and second the RTC clock source "rtc". +- clock-names : List of name strings for the external clocks. +- #clock-cells: Should be 1. + Clock consumers specify this argument to identify a clock. The valid values + may be found in <dt-bindings/clock/<soctype>-cgu.h>. + +Example SoC include file: + +/ { + cgu: jz4740-cgu { + compatible = "ingenic,jz4740-cgu"; + reg = <0x10000000 0x100>; + #clock-cells = <1>; + }; + + uart0: serial@10030000 { + clocks = <&cgu JZ4740_CLK_UART0>; + }; +}; + +Example board file: + +/ { + ext: clock@0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12000000>; + }; + + rtc: clock@1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + &cgu { + clocks = <&ext> <&rtc>; + clock-names: "ext", "rtc"; + }; +}; diff --git a/Documentation/devicetree/bindings/clock/qca,ath79-pll.txt b/Documentation/devicetree/bindings/clock/qca,ath79-pll.txt new file mode 100644 index 0000000..e0fc2c1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qca,ath79-pll.txt @@ -0,0 +1,33 @@ +Binding for Qualcomm Atheros AR7xxx/AR9XXX PLL controller + +The PPL controller provides the 3 main clocks of the SoC: CPU, DDR and AHB. + +Required Properties: +- compatible: has to be "qca,<soctype>-cpu-intc" and one of the following + fallbacks: + - "qca,ar7100-pll" + - "qca,ar7240-pll" + - "qca,ar9130-pll" + - "qca,ar9330-pll" + - "qca,ar9340-pll" + - "qca,qca9550-pll" +- reg: Base address and size of the controllers memory area +- clock-names: Name of the input clock, has to be "ref" +- clocks: phandle of the external reference clock +- #clock-cells: has to be one + +Optional properties: +- clock-output-names: should be "cpu", "ddr", "ahb" + +Example: + + memory-controller@18050000 { + compatible = "qca,ar9132-ppl", "qca,ar9130-pll"; + reg = <0x18050000 0x20>; + + clock-names = "ref"; + clocks = <&extosc>; + + #clock-cells = <1>; + clock-output-names = "cpu", "ddr", "ahb"; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-ath79.txt b/Documentation/devicetree/bindings/gpio/gpio-ath79.txt new file mode 100644 index 0000000..c522851 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-ath79.txt @@ -0,0 +1,38 @@ +Binding for Qualcomm Atheros AR7xxx/AR9xxx GPIO controller + +Required properties: +- compatible: has to be "qca,<soctype>-gpio" and one of the following + fallbacks: + - "qca,ar7100-gpio" + - "qca,ar9340-gpio" +- reg: Base address and size of the controllers memory area +- gpio-controller : Marks the device node as a GPIO controller. +- #gpio-cells : Should be two. The first cell is the pin number and the + second cell is used to specify optional parameters. +- ngpios: Should be set to the number of GPIOs available on the SoC. + +Optional properties: +- interrupt-parent: phandle of the parent interrupt controller. +- interrupts: Interrupt specifier for the controllers interrupt. +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode interrupt + source, should be 2 + +Please refer to interrupts.txt in this directory for details of the common +Interrupt Controllers bindings used by client devices. + +Example: + + gpio@18040000 { + compatible = "qca,ar9132-gpio", "qca,ar7100-gpio"; + reg = <0x18040000 0x30>; + interrupts = <2>; + + ngpios = <22>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt new file mode 100644 index 0000000..5f89fb6 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt @@ -0,0 +1,28 @@ +Ingenic SoC Interrupt Controller + +Required properties: + +- compatible : should be "ingenic,<socname>-intc". Valid strings are: + ingenic,jz4740-intc + ingenic,jz4770-intc + ingenic,jz4775-intc + ingenic,jz4780-intc +- reg : Specifies base physical address and size of the registers. +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode an + interrupt source. The value shall be 1. +- interrupt-parent : phandle of the CPU interrupt controller. +- interrupts : Specifies the CPU interrupt the controller is connected to. + +Example: + +intc: interrupt-controller@10001000 { + compatible = "ingenic,jz4740-intc"; + reg = <0x10001000 0x14>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; +}; diff --git a/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-cpu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-cpu-intc.txt new file mode 100644 index 0000000..aabce78 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-cpu-intc.txt @@ -0,0 +1,44 @@ +Binding for Qualcomm Atheros AR7xxx/AR9XXX CPU interrupt controller + +On most SoC the IRQ controller need to flush the DDR FIFO before running +the interrupt handler of some devices. This is configured using the +qca,ddr-wb-channels and qca,ddr-wb-channel-interrupts properties. + +Required Properties: + +- compatible: has to be "qca,<soctype>-cpu-intc", "qca,ar7100-cpu-intc" + as fallback +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode interrupt + source, should be 1 for intc + +Please refer to interrupts.txt in this directory for details of the common +Interrupt Controllers bindings used by client devices. + +Optional Properties: + +- qca,ddr-wb-channel-interrupts: List of the interrupts needing a write + buffer flush +- qca,ddr-wb-channels: List of phandles to the write buffer channels for + each interrupt. If qca,ddr-wb-channel-interrupts is not present the interrupt + default to the entry's index. + +Example: + + interrupt-controller { + compatible = "qca,ar9132-cpu-intc", "qca,ar7100-cpu-intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + qca,ddr-wb-channel-interrupts = <2>, <3>, <4>, <5>; + qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>, + <&ddr_ctrl 0>, <&ddr_ctrl 1>; + }; + + ... + + ddr_ctrl: memory-controller@18000000 { + ... + #qca,ddr-wb-channel-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt new file mode 100644 index 0000000..391717a --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt @@ -0,0 +1,30 @@ +Binding for Qualcomm Atheros AR7xxx/AR9XXX MISC interrupt controller + +The MISC interrupt controller is a secondary controller for lower priority +interrupt. + +Required Properties: +- compatible: has to be "qca,<soctype>-cpu-intc", "qca,ar7100-misc-intc" + as fallback +- reg: Base address and size of the controllers memory area +- interrupt-parent: phandle of the parent interrupt controller. +- interrupts: Interrupt specifier for the controllers interrupt. +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode interrupt + source, should be 1 + +Please refer to interrupts.txt in this directory for details of the common +Interrupt Controllers bindings used by client devices. + +Example: + + interrupt-controller@18060010 { + compatible = "qca,ar9132-misc-intc", qca,ar7100-misc-intc"; + reg = <0x18060010 0x4>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + interrupt-controller; + #interrupt-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt b/Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt new file mode 100644 index 0000000..efe35a06 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/ath79-ddr-controller.txt @@ -0,0 +1,35 @@ +Binding for Qualcomm Atheros AR7xxx/AR9xxx DDR controller + +The DDR controller of the ARxxx and AR9xxx families provides an interface +to flush the FIFO between various devices and the DDR. This is mainly used +by the IRQ controller to flush the FIFO before running the interrupt handler +of such devices. + +Required properties: + +- compatible: has to be "qca,<soc-type>-ddr-controller", + "qca,[ar7100|ar7240]-ddr-controller" as fallback. + On SoC with PCI support "qca,ar7100-ddr-controller" should be used as + fallback, otherwise "qca,ar7240-ddr-controller" should be used. +- reg: Base address and size of the controllers memory area +- #qca,ddr-wb-channel-cells: has to be 1, the index of the write buffer + channel + +Example: + + ddr_ctrl: memory-controller@18000000 { + compatible = "qca,ar9132-ddr-controller", + "qca,ar7240-ddr-controller"; + reg = <0x18000000 0x100>; + + #qca,ddr-wb-channel-cells = <1>; + }; + + ... + + interrupt-controller { + ... + qca,ddr-wb-channel-interrupts = <2>, <3>, <4>, <5>; + qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>, + <&ddr_ctrl 0>, <&ddr_ctrl 1>; + }; diff --git a/Documentation/devicetree/bindings/mips/ath79-soc.txt b/Documentation/devicetree/bindings/mips/ath79-soc.txt new file mode 100644 index 0000000..88a12a4 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/ath79-soc.txt @@ -0,0 +1,21 @@ +Binding for Qualcomm Atheros AR7xxx/AR9XXX SoC + +Each device tree must specify a compatible value for the AR SoC +it uses in the compatible property of the root node. The compatible +value must be one of the following values: + +- qca,ar7130 +- qca,ar7141 +- qca,ar7161 +- qca,ar7240 +- qca,ar7241 +- qca,ar7242 +- qca,ar9130 +- qca,ar9132 +- qca,ar9330 +- qca,ar9331 +- qca,ar9341 +- qca,ar9342 +- qca,ar9344 +- qca,qca9556 +- qca,qca9558 diff --git a/Documentation/devicetree/bindings/phy/pistachio-usb-phy.txt b/Documentation/devicetree/bindings/phy/pistachio-usb-phy.txt new file mode 100644 index 0000000..afbc7e2 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/pistachio-usb-phy.txt @@ -0,0 +1,29 @@ +IMG Pistachio USB PHY +===================== + +Required properties: +-------------------- + - compatible: Must be "img,pistachio-usb-phy". + - #phy-cells: Must be 0. See ./phy-bindings.txt for details. + - clocks: Must contain an entry for each entry in clock-names. + See ../clock/clock-bindings.txt for details. + - clock-names: Must include "usb_phy". + - img,cr-top: Must constain a phandle to the CR_TOP syscon node. + - img,refclk: Indicates the reference clock source for the USB PHY. + See <dt-bindings/phy/phy-pistachio-usb.h> for a list of valid values. + +Optional properties: +-------------------- + - phy-supply: USB VBUS supply. Must supply 5.0V. + +Example: +-------- +usb_phy: usb-phy { + compatible = "img,pistachio-usb-phy"; + clocks = <&clk_core CLK_USB_PHY>; + clock-names = "usb_phy"; + phy-supply = <&usb_vbus>; + img,refclk = <REFCLK_CLK_CORE>; + img,cr-top = <&cr_top>; + #phy-cells = <0>; +}; diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt new file mode 100644 index 0000000..c2d3b3a --- /dev/null +++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt @@ -0,0 +1,22 @@ +* Ingenic SoC UART + +Required properties: +- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart" +- reg : offset and length of the register set for the device. +- interrupts : should contain uart interrupt. +- clocks : phandles to the module & baud clocks. +- clock-names: tuple listing input clock names. + Required elements: "baud", "module" + +Example: + +uart0: serial@10030000 { + compatible = "ingenic,jz4740-uart"; + reg = <0x10030000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <9>; + + clocks = <&ext>, <&cgu JZ4740_CLK_UART0>; + clock-names = "baud", "module"; +}; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 8e8f4bc..7b607761 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -106,6 +106,7 @@ ibm International Business Machines (IBM) idt Integrated Device Technologies, Inc. iom Iomega Corporation img Imagination Technologies Ltd. +ingenic Ingenic Semiconductor innolux Innolux Corporation intel Intel Corporation intercontrol Inter Control Group @@ -161,6 +162,7 @@ powervr PowerVR (deprecated, use img) qca Qualcomm Atheros, Inc. qcom Qualcomm Technologies, Inc qemu QEMU, a generic and open source machine emulator and virtualizer +qi Qi Hardware qnap QNAP Systems, Inc. radxa Radxa raidsonic RaidSonic Technology GmbH @@ -206,6 +208,7 @@ tlm Trusted Logic Mobility toradex Toradex AG toshiba Toshiba Corporation toumaz Toumaz +tplink TP-LINK Technologies Co., Ltd. truly Truly Semiconductors Limited usi Universal Scientific Industrial Co., Ltd. v3 V3 Semiconductor diff --git a/MAINTAINERS b/MAINTAINERS index c54a674..6aedd50 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2229,6 +2229,14 @@ F: arch/mips/bcm3384/* F: arch/mips/include/asm/mach-bcm3384/* F: arch/mips/kernel/*bmips* +BROADCOM BCM47XX MIPS ARCHITECTURE +M: Hauke Mehrtens <hauke@hauke-m.de> +M: Rafał Miłecki <zajec5@gmail.com> +L: linux-mips@linux-mips.org +S: Maintained +F: arch/mips/bcm47xx/* +F: arch/mips/include/asm/mach-bcm47xx/* + BROADCOM BCM5301X ARM ARCHITECTURE M: Hauke Mehrtens <hauke@hauke-m.de> L: linux-arm-kernel@lists.infradead.org @@ -2333,6 +2341,12 @@ S: Supported F: drivers/gpio/gpio-bcm-kona.c F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +BROADCOM NVRAM DRIVER +M: Rafał Miłecki <zajec5@gmail.com> +L: linux-mips@linux-mips.org +S: Maintained +F: drivers/firmware/broadcom/* + BROADCOM STB NAND FLASH DRIVER M: Brian Norris <computersforpeace@gmail.com> L: linux-mtd@lists.infradead.org diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 39cf40d..a424e46 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -15,8 +15,8 @@ platforms += jazz platforms += jz4740 platforms += lantiq platforms += lasat -platforms += loongson -platforms += loongson1 +platforms += loongson32 +platforms += loongson64 platforms += mti-malta platforms += mti-sead3 platforms += netlogic diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b65edf5..2a14585 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -21,11 +21,12 @@ config MIPS select HAVE_FUNCTION_GRAPH_TRACER select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_SYSCALL_TRACEPOINTS select HAVE_DEBUG_KMEMLEAK select HAVE_SYSCALL_TRACEPOINTS select ARCH_HAS_ELF_RANDOMIZE select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT - select RTC_LIB if !MACH_LOONGSON + select RTC_LIB if !MACH_LOONGSON64 select GENERIC_ATOMIC64 if !64BIT select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_DMA_ATTRS @@ -70,7 +71,7 @@ config MIPS_ALCHEMY select ARCH_PHYS_ADDR_T_64BIT select CEVT_R4K select CSRC_R4K - select IRQ_CPU + select IRQ_MIPS_CPU select DMA_MAYBE_COHERENT # Au1000,1500,1100 aren't, rest is select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL @@ -85,7 +86,7 @@ config AR7 select DMA_NONCOHERENT select CEVT_R4K select CSRC_R4K - select IRQ_CPU + select IRQ_MIPS_CPU select NO_EXCEPT_FILL select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 @@ -106,7 +107,7 @@ config ATH25 select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select IRQ_DOMAIN select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_BIG_ENDIAN @@ -123,14 +124,17 @@ config ATH79 select CSRC_R4K select DMA_NONCOHERENT select HAVE_CLK + select COMMON_CLK select CLKDEV_LOOKUP - select IRQ_CPU + select IRQ_MIPS_CPU select MIPS_MACHINE select SYS_HAS_CPU_MIPS32_R2 select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_MIPS16 + select SYS_SUPPORTS_ZBOOT + select USE_OF help Support for the Atheros AR71XX/AR724X/AR913X SoCs. @@ -146,7 +150,7 @@ config BMIPS_GENERIC select BCM7038_L1_IRQ select BCM7120_L2_IRQ select BRCMSTB_L2_IRQ - select IRQ_CPU + select IRQ_MIPS_CPU select RAW_IRQ_ACCESSORS select DMA_NONCOHERENT select SYS_SUPPORTS_32BIT_KERNEL @@ -176,7 +180,7 @@ config BCM47XX select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_HAS_CPU_MIPS32_R1 select NO_EXCEPT_FILL select SYS_SUPPORTS_32BIT_KERNEL @@ -186,6 +190,7 @@ config BCM47XX select USE_GENERIC_EARLY_PRINTK_8250 select GPIOLIB select LEDS_GPIO_REGISTER + select BCM47XX_NVRAM help Support for BCM47XX based boards @@ -196,7 +201,7 @@ config BCM63XX select CSRC_R4K select SYNC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_HAS_EARLY_PRINTK @@ -216,7 +221,7 @@ config MIPS_COBALT select HW_HAS_PCI select I8253 select I8259 - select IRQ_CPU + select IRQ_MIPS_CPU select IRQ_GT641XX select PCI_GT64XXX_PCI0 select PCI @@ -239,7 +244,7 @@ config MACH_DECSTATION select CPU_R4400_WORKAROUNDS if 64BIT select DMA_NONCOHERENT select NO_IOPORT_MAP - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_HAS_CPU_R3000 select SYS_HAS_CPU_R4X00 select SYS_SUPPORTS_32BIT_KERNEL @@ -274,7 +279,7 @@ config MACH_JAZZ select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN select GENERIC_ISA_DMA select HAVE_PCSPKR_PLATFORM - select IRQ_CPU + select IRQ_MIPS_CPU select I8253 select I8259 select ISA @@ -288,23 +293,24 @@ config MACH_JAZZ Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and Olivetti M700-10 workstations. -config MACH_JZ4740 - bool "Ingenic JZ4740 based machines" - select SYS_HAS_CPU_MIPS32_R1 +config MACH_INGENIC + bool "Ingenic SoC based machines" select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_ZBOOT_UART16550 select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select ARCH_REQUIRE_GPIOLIB - select SYS_HAS_EARLY_PRINTK - select HAVE_CLK + select COMMON_CLK select GENERIC_IRQ_CHIP + select BUILTIN_DTB + select USE_OF + select LIBFDT config LANTIQ bool "Lantiq based platforms" select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select CEVT_R4K select CSRC_R4K select SYS_HAS_CPU_MIPS32_R1 @@ -333,7 +339,7 @@ config LASAT select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select PCI_GT64XXX_PCI0 select MIPS_NILE4 select R5000_CPU_SCACHE @@ -342,26 +348,28 @@ config LASAT select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_LITTLE_ENDIAN -config MACH_LOONGSON - bool "Loongson family of machines" +config MACH_LOONGSON32 + bool "Loongson-1 family of machines" select SYS_SUPPORTS_ZBOOT help - This enables the support of Loongson family of machines. + This enables support for the Loongson-1 family of machines. - Loongson is a family of general-purpose MIPS-compatible CPUs. - developed at Institute of Computing Technology (ICT), - Chinese Academy of Sciences (CAS) in the People's Republic - of China. The chief architect is Professor Weiwu Hu. + Loongson-1 is a family of 32-bit MIPS-compatible SoCs developed by + the Institute of Computing Technology (ICT), Chinese Academy of + Sciences (CAS). -config MACH_LOONGSON1 - bool "Loongson 1 family of machines" +config MACH_LOONGSON64 + bool "Loongson-2/3 family of machines" select SYS_SUPPORTS_ZBOOT help - This enables support for the Loongson 1 based machines. + This enables the support of Loongson-2/3 family of machines. - Loongson 1 is a family of 32-bit MIPS-compatible SoCs developed by - the ICT (Institute of Computing Technology) and the Chinese Academy - of Sciences. + Loongson-2 is a family of single-core CPUs and Loongson-3 is a + family of multi-core CPUs. They are both 64-bit general-purpose + MIPS-compatible CPUs. Loongson-2/3 are developed by the Institute + of Computing Technology (ICT), Chinese Academy of Sciences (CAS) + in the People's Republic of China. The chief architect is Professor + Weiwu Hu. config MACH_PISTACHIO bool "IMG Pistachio SoC based boards" @@ -373,7 +381,7 @@ config MACH_PISTACHIO select COMMON_CLK select CSRC_R4K select DMA_MAYBE_COHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select LIBFDT select MFD_SYSCON select MIPS_CPU_SCACHE @@ -386,6 +394,8 @@ config MACH_PISTACHIO select SYS_SUPPORTS_MIPS_CPS select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_ZBOOT + select SYS_HAS_EARLY_PRINTK + select USE_GENERIC_EARLY_PRINTK_8250 select USE_OF help This enables support for the IMG Pistachio SoC platform. @@ -395,13 +405,14 @@ config MIPS_MALTA select ARCH_MAY_HAVE_PC_FDC select BOOT_ELF32 select BOOT_RAW + select BUILTIN_DTB select CEVT_R4K select CSRC_R4K select CLKSRC_MIPS_GIC select DMA_MAYBE_COHERENT select GENERIC_ISA_DMA select HAVE_PCSPKR_PLATFORM - select IRQ_CPU + select IRQ_MIPS_CPU select MIPS_GIC select HW_HAS_PCI select I8253 @@ -434,6 +445,8 @@ config MIPS_MALTA select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_SMARTMIPS select SYS_SUPPORTS_ZBOOT + select USE_OF + select ZONE_DMA32 if 64BIT help This enables support for the MIPS Technologies Malta evaluation board. @@ -449,7 +462,7 @@ config MIPS_SEAD3 select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select MIPS_GIC select LIBFDT select MIPS_MSC @@ -512,7 +525,7 @@ config PMC_MSP select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_MIPS16 - select IRQ_CPU + select IRQ_MIPS_CPU select SERIAL_8250 select SERIAL_8250_CONSOLE select USB_EHCI_BIG_ENDIAN_MMIO @@ -529,7 +542,7 @@ config RALINK select CSRC_R4K select BOOT_RAW select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select USE_OF select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 @@ -555,7 +568,7 @@ config SGI_IP22 select I8253 select I8259 select IP22_CPU_SCACHE - select IRQ_CPU + select IRQ_MIPS_CPU select GENERIC_ISA_DMA_SUPPORT_BROKEN select SGI_HAS_I8042 select SGI_HAS_INDYDOG @@ -614,7 +627,7 @@ config SGI_IP28 select DEFAULT_SGI_PARTITION select DMA_NONCOHERENT select GENERIC_ISA_DMA_SUPPORT_BROKEN - select IRQ_CPU + select IRQ_MIPS_CPU select HW_HAS_EISA select I8253 select I8259 @@ -650,7 +663,7 @@ config SGI_IP32 select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select R5000_CPU_SCACHE select RM7000_CPU_SCACHE select SYS_HAS_CPU_R5000 @@ -766,7 +779,7 @@ config SNI_RM select HAVE_PCSPKR_PLATFORM select HW_HAS_EISA select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select I8253 select I8259 select ISA @@ -799,7 +812,7 @@ config MIKROTIK_RB532 select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -866,7 +879,7 @@ config NLM_XLR_BOARD select NR_CPUS_DEFAULT_32 select CEVT_R4K select CSRC_R4K - select IRQ_CPU + select IRQ_MIPS_CPU select ZONE_DMA32 if 64BIT select SYNC_R4K select SYS_HAS_EARLY_PRINTK @@ -893,7 +906,7 @@ config NLM_XLP_BOARD select NR_CPUS_DEFAULT_32 select CEVT_R4K select CSRC_R4K - select IRQ_CPU + select IRQ_MIPS_CPU select ZONE_DMA32 if 64BIT select SYNC_R4K select SYS_HAS_EARLY_PRINTK @@ -942,8 +955,8 @@ source "arch/mips/sibyte/Kconfig" source "arch/mips/txx9/Kconfig" source "arch/mips/vr41xx/Kconfig" source "arch/mips/cavium-octeon/Kconfig" -source "arch/mips/loongson/Kconfig" -source "arch/mips/loongson1/Kconfig" +source "arch/mips/loongson32/Kconfig" +source "arch/mips/loongson64/Kconfig" source "arch/mips/netlogic/Kconfig" source "arch/mips/paravirt/Kconfig" @@ -1142,10 +1155,6 @@ config SYS_SUPPORTS_HUGETLBFS config MIPS_HUGE_TLB_SUPPORT def_bool HUGETLB_PAGE || TRANSPARENT_HUGEPAGE -config IRQ_CPU - bool - select IRQ_DOMAIN - config IRQ_CPU_RM7K bool @@ -1172,7 +1181,7 @@ config SOC_EMMA2RH select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select SWAP_IO_SPACE select SYS_HAS_CPU_R5500 select SYS_SUPPORTS_32BIT_KERNEL @@ -1183,7 +1192,7 @@ config SOC_PNX833X bool select CEVT_R4K select CSRC_R4K - select IRQ_CPU + select IRQ_MIPS_CPU select DMA_NONCOHERENT select SYS_HAS_CPU_MIPS32_R2 select SYS_SUPPORTS_32BIT_KERNEL @@ -1569,7 +1578,8 @@ config CPU_CAVIUM_OCTEON select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HUGEPAGES - select USB_EHCI_BIG_ENDIAN_MMIO + select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN + select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN select MIPS_L1_CACHE_SHIFT_7 help The Cavium Octeon processor is a highly integrated chip containing @@ -1587,7 +1597,7 @@ config CPU_BMIPS select CPU_BMIPS5000 if SYS_HAS_CPU_BMIPS5000 select CPU_SUPPORTS_32BIT_KERNEL select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select SWAP_IO_SPACE select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM @@ -2672,6 +2682,51 @@ config USE_OF config BUILTIN_DTB bool +choice + prompt "Kernel appended dtb support" if OF + default MIPS_NO_APPENDED_DTB + + config MIPS_NO_APPENDED_DTB + bool "None" + help + Do not enable appended dtb support. + + config MIPS_RAW_APPENDED_DTB + bool "vmlinux.bin" + help + With this option, the boot code will look for a device tree binary + DTB) appended to raw vmlinux.bin (without decompressor). + (e.g. cat vmlinux.bin <filename>.dtb > vmlinux_w_dtb). + + This is meant as a backward compatibility convenience for those + systems with a bootloader that can't be upgraded to accommodate + the documented boot protocol using a device tree. + + Beware that there is very little in terms of protection against + this option being confused by leftover garbage in memory that might + look like a DTB header after a reboot if no actual DTB is appended + to vmlinux.bin. Do not leave this option active in a production kernel + if you don't intend to always append a DTB. + + config MIPS_ZBOOT_APPENDED_DTB + bool "vmlinuz.bin" + depends on SYS_SUPPORTS_ZBOOT + help + With this option, the boot code will look for a device tree binary + DTB) appended to raw vmlinuz.bin (with decompressor). + (e.g. cat vmlinuz.bin <filename>.dtb > vmlinuz_w_dtb). + + This is meant as a backward compatibility convenience for those + systems with a bootloader that can't be upgraded to accommodate + the documented boot protocol using a device tree. + + Beware that there is very little in terms of protection against + this option being confused by leftover garbage in memory that might + look like a DTB header after a reboot if no actual DTB is appended + to vmlinuz.bin. Do not leave this option active in a production kernel + if you don't intend to always append a DTB. +endchoice + endmenu config LOCKDEP_SUPPORT diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 6a98d2c..6e46abe 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -752,12 +752,12 @@ static int __init alchemy_clk_init_fgens(int ctype) switch (ctype) { case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200: id.ops = &alchemy_clkops_fgenv1; - id.parent_names = (const char **)alchemy_clk_fgv1_parents; + id.parent_names = alchemy_clk_fgv1_parents; id.num_parents = 2; break; case ALCHEMY_CPU_AU1300: id.ops = &alchemy_clkops_fgenv2; - id.parent_names = (const char **)alchemy_clk_fgv2_parents; + id.parent_names = alchemy_clk_fgv2_parents; id.num_parents = 3; break; default: @@ -961,7 +961,7 @@ static int __init alchemy_clk_setup_imux(int ctype) struct clk *c; id.ops = &alchemy_clkops_csrc; - id.parent_names = (const char **)alchemy_clk_csrc_parents; + id.parent_names = alchemy_clk_csrc_parents; id.num_parents = 7; id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE; diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c index 2befa7d..8742e1c 100644 --- a/arch/mips/ath25/ar2315.c +++ b/arch/mips/ath25/ar2315.c @@ -76,7 +76,7 @@ static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc) unsigned nr, misc_irq = 0; if (pending) { - struct irq_domain *domain = irq_get_handler_data(irq); + struct irq_domain *domain = irq_desc_get_handler_data(desc); nr = __ffs(pending); misc_irq = irq_find_mapping(domain, nr); diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c index b6887f7..094b938 100644 --- a/arch/mips/ath25/ar5312.c +++ b/arch/mips/ath25/ar5312.c @@ -80,7 +80,7 @@ static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc) unsigned nr, misc_irq = 0; if (pending) { - struct irq_domain *domain = irq_get_handler_data(irq); + struct irq_domain *domain = irq_desc_get_handler_data(desc); nr = __ffs(pending); misc_irq = irq_find_mapping(domain, nr); diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c index b8bb782..9ab48ff 100644 --- a/arch/mips/ath25/board.c +++ b/arch/mips/ath25/board.c @@ -216,7 +216,7 @@ void __init plat_time_init(void) ar2315_plat_time_init(); } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; } diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index dfc6020..13c04cf 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -71,6 +71,18 @@ config ATH79_MACH_UBNT_XM Say 'Y' here if you want your kernel to support the Ubiquiti Networks XM (rev 1.0) board. +choice + prompt "Build a DTB in the kernel" + optional + help + Select a devicetree that should be built into the kernel. + + config DTB_TL_WR1043ND_V1 + bool "TL-WR1043ND Version 1" + select BUILTIN_DTB + select SOC_AR913X +endchoice + endmenu config SOC_AR71XX diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 26479f4..eb5117c 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -17,6 +17,7 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/clk-provider.h> #include <asm/div64.h> @@ -28,24 +29,27 @@ #define AR724X_BASE_FREQ 5000000 #define AR913X_BASE_FREQ 5000000 -struct clk { - unsigned long rate; +static struct clk *clks[3]; +static struct clk_onecell_data clk_data = { + .clks = clks, + .clk_num = ARRAY_SIZE(clks), }; -static void __init ath79_add_sys_clkdev(const char *id, unsigned long rate) +static struct clk *__init ath79_add_sys_clkdev( + const char *id, unsigned long rate) { struct clk *clk; int err; - clk = kzalloc(sizeof(*clk), GFP_KERNEL); + clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate); if (!clk) panic("failed to allocate %s clock structure", id); - clk->rate = rate; - err = clk_register_clkdev(clk, id, NULL); if (err) panic("unable to register %s clock device", id); + + return clk; } static void __init ar71xx_clocks_init(void) @@ -62,7 +66,7 @@ static void __init ar71xx_clocks_init(void) pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); - div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; + div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1; freq = div * ref_rate; div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; @@ -75,9 +79,9 @@ static void __init ar71xx_clocks_init(void) ahb_rate = cpu_rate / div; ath79_add_sys_clkdev("ref", ref_rate); - ath79_add_sys_clkdev("cpu", cpu_rate); - ath79_add_sys_clkdev("ddr", ddr_rate); - ath79_add_sys_clkdev("ahb", ahb_rate); + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -96,7 +100,7 @@ static void __init ar724x_clocks_init(void) ref_rate = AR724X_BASE_FREQ; pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); - div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK); + div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); freq = div * ref_rate; div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); @@ -111,9 +115,9 @@ static void __init ar724x_clocks_init(void) ahb_rate = cpu_rate / div; ath79_add_sys_clkdev("ref", ref_rate); - ath79_add_sys_clkdev("cpu", cpu_rate); - ath79_add_sys_clkdev("ddr", ddr_rate); - ath79_add_sys_clkdev("ahb", ahb_rate); + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -132,7 +136,7 @@ static void __init ar913x_clocks_init(void) ref_rate = AR913X_BASE_FREQ; pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG); - div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK); + div = ((pll >> AR913X_PLL_FB_SHIFT) & AR913X_PLL_FB_MASK); freq = div * ref_rate; cpu_rate = freq; @@ -144,9 +148,9 @@ static void __init ar913x_clocks_init(void) ahb_rate = cpu_rate / div; ath79_add_sys_clkdev("ref", ref_rate); - ath79_add_sys_clkdev("cpu", cpu_rate); - ath79_add_sys_clkdev("ddr", ddr_rate); - ath79_add_sys_clkdev("ahb", ahb_rate); + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ahb", NULL); @@ -206,9 +210,9 @@ static void __init ar933x_clocks_init(void) } ath79_add_sys_clkdev("ref", ref_rate); - ath79_add_sys_clkdev("cpu", cpu_rate); - ath79_add_sys_clkdev("ddr", ddr_rate); - ath79_add_sys_clkdev("ahb", ahb_rate); + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ahb", NULL); clk_add_alias("uart", NULL, "ref", NULL); @@ -340,9 +344,9 @@ static void __init ar934x_clocks_init(void) ahb_rate = cpu_pll / (postdiv + 1); ath79_add_sys_clkdev("ref", ref_rate); - ath79_add_sys_clkdev("cpu", cpu_rate); - ath79_add_sys_clkdev("ddr", ddr_rate); - ath79_add_sys_clkdev("ahb", ahb_rate); + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ref", NULL); clk_add_alias("uart", NULL, "ref", NULL); @@ -427,9 +431,9 @@ static void __init qca955x_clocks_init(void) ahb_rate = cpu_pll / (postdiv + 1); ath79_add_sys_clkdev("ref", ref_rate); - ath79_add_sys_clkdev("cpu", cpu_rate); - ath79_add_sys_clkdev("ddr", ddr_rate); - ath79_add_sys_clkdev("ahb", ahb_rate); + clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate); + clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate); + clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate); clk_add_alias("wdt", NULL, "ref", NULL); clk_add_alias("uart", NULL, "ref", NULL); @@ -451,6 +455,8 @@ void __init ath79_clocks_init(void) qca955x_clocks_init(); else BUG(); + + of_clk_init(NULL); } unsigned long __init @@ -469,22 +475,16 @@ ath79_get_sys_clk_rate(const char *id) return rate; } -/* - * Linux clock API - */ -int clk_enable(struct clk *clk) +#ifdef CONFIG_OF +static void __init ath79_clocks_init_dt(struct device_node *np) { - return 0; + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } -EXPORT_SYMBOL(clk_enable); -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); +CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); +CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); +CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt); +CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt); +CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); +CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); +#endif diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index eb3966c..3cedd1f 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -38,11 +38,27 @@ unsigned int ath79_soc_rev; void __iomem *ath79_pll_base; void __iomem *ath79_reset_base; EXPORT_SYMBOL_GPL(ath79_reset_base); -void __iomem *ath79_ddr_base; +static void __iomem *ath79_ddr_base; +static void __iomem *ath79_ddr_wb_flush_base; +static void __iomem *ath79_ddr_pci_win_base; + +void ath79_ddr_ctrl_init(void) +{ + ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, + AR71XX_DDR_CTRL_SIZE); + if (soc_is_ar71xx() || soc_is_ar934x()) { + ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; + ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c; + } else { + ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c; + ath79_ddr_pci_win_base = 0; + } +} +EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init); void ath79_ddr_wb_flush(u32 reg) { - void __iomem *flush_reg = ath79_ddr_base + reg; + void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg; /* Flush the DDR write buffer. */ __raw_writel(0x1, flush_reg); @@ -56,6 +72,21 @@ void ath79_ddr_wb_flush(u32 reg) } EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush); +void ath79_ddr_set_pci_windows(void) +{ + BUG_ON(!ath79_ddr_pci_win_base); + + __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0); + __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1); + __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2); + __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3); + __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4); + __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5); + __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6); + __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7); +} +EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows); + void ath79_device_reset_set(u32 mask) { unsigned long flags; diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h index c39de61..e5ea712 100644 --- a/arch/mips/ath79/common.h +++ b/arch/mips/ath79/common.h @@ -22,6 +22,7 @@ void ath79_clocks_init(void); unsigned long ath79_get_sys_clk_rate(const char *id); +void ath79_ddr_ctrl_init(void); void ath79_ddr_wb_flush(unsigned int reg); void ath79_gpio_function_enable(u32 mask); diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c index 516225d..9d0172a 100644 --- a/arch/mips/ath79/dev-common.c +++ b/arch/mips/ath79/dev-common.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/platform_data/gpio-ath79.h> #include <linux/serial_8250.h> #include <linux/clk.h> #include <linux/err.h> @@ -106,3 +107,53 @@ void __init ath79_register_wdt(void) platform_device_register_simple("ath79-wdt", -1, &res, 1); } + +static struct ath79_gpio_platform_data ath79_gpio_pdata; + +static struct resource ath79_gpio_resources[] = { + { + .flags = IORESOURCE_MEM, + .start = AR71XX_GPIO_BASE, + .end = AR71XX_GPIO_BASE + AR71XX_GPIO_SIZE - 1, + }, + { + .start = ATH79_MISC_IRQ(2), + .end = ATH79_MISC_IRQ(2), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ath79_gpio_device = { + .name = "ath79-gpio", + .id = -1, + .resource = ath79_gpio_resources, + .num_resources = ARRAY_SIZE(ath79_gpio_resources), + .dev = { + .platform_data = &ath79_gpio_pdata + }, +}; + +void __init ath79_gpio_init(void) +{ + if (soc_is_ar71xx()) { + ath79_gpio_pdata.ngpios = AR71XX_GPIO_COUNT; + } else if (soc_is_ar7240()) { + ath79_gpio_pdata.ngpios = AR7240_GPIO_COUNT; + } else if (soc_is_ar7241() || soc_is_ar7242()) { + ath79_gpio_pdata.ngpios = AR7241_GPIO_COUNT; + } else if (soc_is_ar913x()) { + ath79_gpio_pdata.ngpios = AR913X_GPIO_COUNT; + } else if (soc_is_ar933x()) { + ath79_gpio_pdata.ngpios = AR933X_GPIO_COUNT; + } else if (soc_is_ar934x()) { + ath79_gpio_pdata.ngpios = AR934X_GPIO_COUNT; + ath79_gpio_pdata.oe_inverted = 1; + } else if (soc_is_qca955x()) { + ath79_gpio_pdata.ngpios = QCA955X_GPIO_COUNT; + ath79_gpio_pdata.oe_inverted = 1; + } else { + BUG(); + } + + platform_device_register(&ath79_gpio_device); +} diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c index 8d025b0..f59ccb2 100644 --- a/arch/mips/ath79/gpio.c +++ b/arch/mips/ath79/gpio.c @@ -20,13 +20,15 @@ #include <linux/io.h> #include <linux/ioport.h> #include <linux/gpio.h> +#include <linux/platform_data/gpio-ath79.h> +#include <linux/of_device.h> #include <asm/mach-ath79/ar71xx_regs.h> #include <asm/mach-ath79/ath79.h> #include "common.h" static void __iomem *ath79_gpio_base; -static unsigned long ath79_gpio_count; +static u32 ath79_gpio_count; static DEFINE_SPINLOCK(ath79_gpio_lock); static void __ath79_gpio_set_value(unsigned gpio, int value) @@ -178,39 +180,72 @@ void ath79_gpio_function_disable(u32 mask) ath79_gpio_function_setup(0, mask); } -void __init ath79_gpio_init(void) +static const struct of_device_id ath79_gpio_of_match[] = { + { .compatible = "qca,ar7100-gpio" }, + { .compatible = "qca,ar9340-gpio" }, + {}, +}; + +static int ath79_gpio_probe(struct platform_device *pdev) { + struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; + struct resource *res; + bool oe_inverted; int err; - if (soc_is_ar71xx()) - ath79_gpio_count = AR71XX_GPIO_COUNT; - else if (soc_is_ar7240()) - ath79_gpio_count = AR7240_GPIO_COUNT; - else if (soc_is_ar7241() || soc_is_ar7242()) - ath79_gpio_count = AR7241_GPIO_COUNT; - else if (soc_is_ar913x()) - ath79_gpio_count = AR913X_GPIO_COUNT; - else if (soc_is_ar933x()) - ath79_gpio_count = AR933X_GPIO_COUNT; - else if (soc_is_ar934x()) - ath79_gpio_count = AR934X_GPIO_COUNT; - else if (soc_is_qca955x()) - ath79_gpio_count = QCA955X_GPIO_COUNT; - else - BUG(); + if (np) { + err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); + if (err) { + dev_err(&pdev->dev, "ngpios property is not valid\n"); + return err; + } + if (ath79_gpio_count >= 32) { + dev_err(&pdev->dev, "ngpios must be less than 32\n"); + return -EINVAL; + } + oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio"); + } else if (pdata) { + ath79_gpio_count = pdata->ngpios; + oe_inverted = pdata->oe_inverted; + } else { + dev_err(&pdev->dev, "No DT node or platform data found\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ath79_gpio_base = devm_ioremap_nocache( + &pdev->dev, res->start, resource_size(res)); + if (!ath79_gpio_base) + return -ENOMEM; - ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); + ath79_gpio_chip.dev = &pdev->dev; ath79_gpio_chip.ngpio = ath79_gpio_count; - if (soc_is_ar934x() || soc_is_qca955x()) { + if (oe_inverted) { ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; } err = gpiochip_add(&ath79_gpio_chip); - if (err) - panic("cannot add AR71xx GPIO chip, error=%d", err); + if (err) { + dev_err(&pdev->dev, + "cannot add AR71xx GPIO chip, error=%d", err); + return err; + } + + return 0; } +static struct platform_driver ath79_gpio_driver = { + .driver = { + .name = "ath79-gpio", + .of_match_table = ath79_gpio_of_match, + }, + .probe = ath79_gpio_probe, +}; + +module_platform_driver(ath79_gpio_driver); + int gpio_get_value(unsigned gpio) { if (gpio < ath79_gpio_count) diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 6adae36..afb0096 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -15,7 +15,9 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/of_irq.h> +#include "../../../drivers/irqchip/irqchip.h" #include <asm/irq_cpu.h> #include <asm/mipsregs.h> @@ -23,9 +25,7 @@ #include <asm/mach-ath79/ath79.h> #include <asm/mach-ath79/ar71xx_regs.h> #include "common.h" - -static void (*ath79_ip2_handler)(void); -static void (*ath79_ip3_handler)(void); +#include "machtypes.h" static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) { @@ -129,10 +129,10 @@ static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { - ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE); + ath79_ddr_wb_flush(3); generic_handle_irq(ATH79_IP2_IRQ(0)); } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { - ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC); + ath79_ddr_wb_flush(4); generic_handle_irq(ATH79_IP2_IRQ(1)); } else { spurious_interrupt(); @@ -235,128 +235,132 @@ static void qca955x_irq_init(void) irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); } -asmlinkage void plat_irq_dispatch(void) -{ - unsigned long pending; - - pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP7) - do_IRQ(ATH79_CPU_IRQ(7)); - - else if (pending & STATUSF_IP2) - ath79_ip2_handler(); - - else if (pending & STATUSF_IP4) - do_IRQ(ATH79_CPU_IRQ(4)); - - else if (pending & STATUSF_IP5) - do_IRQ(ATH79_CPU_IRQ(5)); - - else if (pending & STATUSF_IP3) - ath79_ip3_handler(); - - else if (pending & STATUSF_IP6) - do_IRQ(ATH79_CPU_IRQ(6)); - - else - spurious_interrupt(); -} - /* * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for * these devices typically allocate coherent DMA memory, however the * DMA controller may still have some unsynchronized data in the FIFO. * Issue a flush in the handlers to ensure that the driver sees * the update. + * + * This array map the interrupt lines to the DDR write buffer channels. */ -static void ath79_default_ip2_handler(void) -{ - do_IRQ(ATH79_CPU_IRQ(2)); -} +static unsigned irq_wb_chan[8] = { + -1, -1, -1, -1, -1, -1, -1, -1, +}; -static void ath79_default_ip3_handler(void) +asmlinkage void plat_irq_dispatch(void) { - do_IRQ(ATH79_CPU_IRQ(3)); -} + unsigned long pending; + int irq; -static void ar71xx_ip2_handler(void) -{ - ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); - do_IRQ(ATH79_CPU_IRQ(2)); -} + pending = read_c0_status() & read_c0_cause() & ST0_IM; -static void ar724x_ip2_handler(void) -{ - ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); - do_IRQ(ATH79_CPU_IRQ(2)); -} + if (!pending) { + spurious_interrupt(); + return; + } -static void ar913x_ip2_handler(void) -{ - ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); - do_IRQ(ATH79_CPU_IRQ(2)); + pending >>= CAUSEB_IP; + while (pending) { + irq = fls(pending) - 1; + if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1) + ath79_ddr_wb_flush(irq_wb_chan[irq]); + do_IRQ(MIPS_CPU_IRQ_BASE + irq); + pending &= ~BIT(irq); + } } -static void ar933x_ip2_handler(void) +#ifdef CONFIG_IRQCHIP +static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { - ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); - do_IRQ(ATH79_CPU_IRQ(2)); + irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq); + return 0; } -static void ar71xx_ip3_handler(void) -{ - ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ(3)); -} +static const struct irq_domain_ops misc_irq_domain_ops = { + .xlate = irq_domain_xlate_onecell, + .map = misc_map, +}; -static void ar724x_ip3_handler(void) +static int __init ath79_misc_intc_of_init( + struct device_node *node, struct device_node *parent) { - ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ(3)); -} + void __iomem *base = ath79_reset_base; + struct irq_domain *domain; + int irq; -static void ar913x_ip3_handler(void) -{ - ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ(3)); -} + irq = irq_of_parse_and_map(node, 0); + if (!irq) + panic("Failed to get MISC IRQ"); -static void ar933x_ip3_handler(void) -{ - ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ(3)); + domain = irq_domain_add_legacy(node, ATH79_MISC_IRQ_COUNT, + ATH79_MISC_IRQ_BASE, 0, &misc_irq_domain_ops, NULL); + if (!domain) + panic("Failed to add MISC irqdomain"); + + /* Disable and clear all interrupts */ + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); + + + irq_set_chained_handler(irq, ath79_misc_irq_handler); + + return 0; } +IRQCHIP_DECLARE(ath79_misc_intc, "qca,ar7100-misc-intc", + ath79_misc_intc_of_init); -static void ar934x_ip3_handler(void) +static int __init ar79_cpu_intc_of_init( + struct device_node *node, struct device_node *parent) { - ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ(3)); + int err, i, count; + + /* Fill the irq_wb_chan table */ + count = of_count_phandle_with_args( + node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); + + for (i = 0; i < count; i++) { + struct of_phandle_args args; + u32 irq = i; + + of_property_read_u32_index( + node, "qca,ddr-wb-channel-interrupts", i, &irq); + if (irq >= ARRAY_SIZE(irq_wb_chan)) + continue; + + err = of_parse_phandle_with_args( + node, "qca,ddr-wb-channels", + "#qca,ddr-wb-channel-cells", + i, &args); + if (err) + return err; + + irq_wb_chan[irq] = args.args[0]; + pr_info("IRQ: Set flush channel of IRQ%d to %d\n", + irq, args.args[0]); + } + + return mips_cpu_irq_of_init(node, parent); } +IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", + ar79_cpu_intc_of_init); + +#endif void __init arch_init_irq(void) { - if (soc_is_ar71xx()) { - ath79_ip2_handler = ar71xx_ip2_handler; - ath79_ip3_handler = ar71xx_ip3_handler; - } else if (soc_is_ar724x()) { - ath79_ip2_handler = ar724x_ip2_handler; - ath79_ip3_handler = ar724x_ip3_handler; - } else if (soc_is_ar913x()) { - ath79_ip2_handler = ar913x_ip2_handler; - ath79_ip3_handler = ar913x_ip3_handler; - } else if (soc_is_ar933x()) { - ath79_ip2_handler = ar933x_ip2_handler; - ath79_ip3_handler = ar933x_ip3_handler; + if (mips_machtype == ATH79_MACH_GENERIC_OF) { + irqchip_init(); + return; + } + + if (soc_is_ar71xx() || soc_is_ar724x() || + soc_is_ar913x() || soc_is_ar933x()) { + irq_wb_chan[2] = 3; + irq_wb_chan[3] = 2; } else if (soc_is_ar934x()) { - ath79_ip2_handler = ath79_default_ip2_handler; - ath79_ip3_handler = ar934x_ip3_handler; - } else if (soc_is_qca955x()) { - ath79_ip2_handler = ath79_default_ip2_handler; - ath79_ip3_handler = ath79_default_ip3_handler; - } else { - BUG(); + irq_wb_chan[3] = 2; } mips_cpu_irq_init(); diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h index 2625405..a13db3d 100644 --- a/arch/mips/ath79/machtypes.h +++ b/arch/mips/ath79/machtypes.h @@ -15,6 +15,7 @@ #include <asm/mips_machine.h> enum ath79_mach_type { + ATH79_MACH_GENERIC_OF = -1, /* Device tree board */ ATH79_MACH_GENERIC = 0, ATH79_MACH_AP121, /* Atheros AP121 reference board */ ATH79_MACH_AP136_010, /* Atheros AP136-010 reference board */ diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 7fc8397..01a644f 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -17,12 +17,16 @@ #include <linux/bootmem.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/of_platform.h> +#include <linux/of_fdt.h> #include <asm/bootinfo.h> #include <asm/idle.h> #include <asm/time.h> /* for mips_hpt_frequency */ #include <asm/reboot.h> /* for _machine_{restart,halt} */ #include <asm/mips_machine.h> +#include <asm/prom.h> +#include <asm/fw/fw.h> #include <asm/mach-ath79/ath79.h> #include <asm/mach-ath79/ar71xx_regs.h> @@ -194,17 +198,28 @@ unsigned int get_c0_compare_int(void) void __init plat_mem_setup(void) { + unsigned long fdt_start; + set_io_port_base(KSEG1); + /* Get the position of the FDT passed by the bootloader */ + fdt_start = fw_getenvl("fdt_start"); + if (fdt_start) + __dt_setup_arch((void *)KSEG0ADDR(fdt_start)); +#ifdef CONFIG_BUILTIN_DTB + else + __dt_setup_arch(__dtb_start); +#endif + ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, AR71XX_RESET_SIZE); ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); - ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, - AR71XX_DDR_CTRL_SIZE); + ath79_ddr_ctrl_init(); ath79_detect_sys_type(); - detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); + if (mips_machtype != ATH79_MACH_GENERIC_OF) + detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); _machine_restart = ath79_restart; _machine_halt = ath79_halt; @@ -236,6 +251,10 @@ void __init plat_time_init(void) static int __init ath79_setup(void) { + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + if (mips_machtype == ATH79_MACH_GENERIC_OF) + return 0; + ath79_gpio_init(); ath79_register_uart(); ath79_register_wdt(); @@ -247,6 +266,11 @@ static int __init ath79_setup(void) arch_initcall(ath79_setup); +void __init device_tree_init(void) +{ + unflatten_and_copy_device_tree(); +} + static void __init ath79_generic_init(void) { /* Nothing to do */ diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index fc21d36..51ed599 100644 --- a/arch/mips/bcm47xx/Kconfig +++ b/arch/mips/bcm47xx/Kconfig @@ -25,7 +25,6 @@ config BCM47XX_BCMA select BCMA select BCMA_HOST_SOC select BCMA_DRIVER_MIPS - select BCMA_HOST_PCI if PCI select BCMA_DRIVER_PCI_HOSTMODE if PCI select BCMA_DRIVER_GPIO default y diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile index d58c51b..66bea4e 100644 --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile @@ -3,5 +3,5 @@ # under Linux. # -obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o +obj-y += irq.o prom.o serial.o setup.o time.o sprom.o obj-y += board.o buttons.o leds.o workarounds.o diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c index bd56415..a88975a 100644 --- a/arch/mips/bcm47xx/board.c +++ b/arch/mips/bcm47xx/board.c @@ -149,6 +149,7 @@ struct bcm47xx_board_type_list2 bcm47xx_board_list_boot_hw[] __initconst = { /* board_id */ static const struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = { + {{BCM47XX_BOARD_LUXUL_XWR_1750_V1, "Luxul XWR-1750 V1"}, "luxul_xwr1750_v1"}, {{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WGR614_V10, "Netgear WGR614 V10"}, "U12H139T01_NETGEAR"}, diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c index 276276a..08a4abf 100644 --- a/arch/mips/bcm47xx/buttons.c +++ b/arch/mips/bcm47xx/buttons.c @@ -299,6 +299,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = { BCM47XX_GPIO_KEY(6, KEY_RESTART), }; +/* Luxul */ + +static const struct gpio_keys_button +bcm47xx_buttons_luxul_xwr_1750_v1[] = { + BCM47XX_GPIO_KEY(14, BTN_TASK), +}; + /* Microsoft */ static const struct gpio_keys_button @@ -555,6 +562,10 @@ int __init bcm47xx_buttons_register(void) err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs); break; + case BCM47XX_BOARD_LUXUL_XWR_1750_V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xwr_1750_v1); + break; + case BCM47XX_BOARD_MICROSOFT_MN700: err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700); break; diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c index 0e4ade3..d20ae63 100644 --- a/arch/mips/bcm47xx/leds.c +++ b/arch/mips/bcm47xx/leds.c @@ -370,6 +370,16 @@ bcm47xx_leds_linksys_wrtsl54gs[] __initconst = { BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), }; +/* Luxul */ + +static const struct gpio_led +bcm47xx_leds_luxul_xwr_1750_v1[] __initconst = { + BCM47XX_GPIO_LED(5, "green", "5ghz", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(12, "green", "usb", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED_TRIGGER(13, "green", "status", 0, "timer"), + BCM47XX_GPIO_LED(15, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + /* Microsoft */ static const struct gpio_led @@ -623,6 +633,10 @@ void __init bcm47xx_leds_register(void) bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs); break; + case BCM47XX_BOARD_LUXUL_XWR_1750_V1: + bcm47xx_set_pdata(bcm47xx_leds_luxul_xwr_1750_v1); + break; + case BCM47XX_BOARD_MICROSOFT_MN700: bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700); break; diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index ab698ba..135a540 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -126,7 +126,7 @@ void __init prom_free_prom_memory(void) /* Stripped version of tlb_init, with the call to build_tlb_refill_handler * dropped. Calling it at this stage causes a hang. */ -void __cpuinit early_tlb_init(void) +void early_tlb_init(void) { write_c0_pagemask(PM_DEFAULT_MASK); write_c0_wired(0); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 82ff9fd..98c075f 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -206,9 +206,6 @@ void __init bcm47xx_bus_setup(void) err = bcma_host_soc_init(&bcm47xx_bus.bcma); if (err) panic("Failed to initialize BCMA bus (err %d)", err); - - bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, - NULL); } #endif diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index 68ebf23..2d5c7a7 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -200,7 +200,13 @@ static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom, const char *pre = prefix; bool fb = fallback; + /* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */ + ENTRY(0xfffffffe, u16, pre, "devid", dev_id, 0, fallback); + ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true); + ENTRY(0xfffffffe, u32, pre, "boardflags", boardflags, 0, fb); + ENTRY(0xfffffff0, u32, pre, "boardflags2", boardflags2, 0, fb); + ENTRY(0xfffff800, u32, pre, "boardflags3", boardflags3, 0, fb); ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb); ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true); ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb); @@ -409,27 +415,6 @@ static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom, } #undef ENTRY /* It's specififc, uses local variable, don't use it (again). */ -static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback); - nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback); -} - -static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, - &sprom->leddc_off_time, fallback); -} - -static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, - &sprom->leddc_off_time, fallback); -} - static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom, const char *prefix, bool fallback) { @@ -528,6 +513,8 @@ static int mac_addr_used = 2; static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix, bool fallback) { + bool fb = fallback; + nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback); nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0, fallback); @@ -540,6 +527,10 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0, fallback); + nvram_read_macaddr(prefix, "et2macaddr", sprom->et2mac, fb); + nvram_read_u8(prefix, NULL, "et2mdcport", &sprom->et2mdcport, 0, fb); + nvram_read_u8(prefix, NULL, "et2phyaddr", &sprom->et2phyaddr, 0, fb); + nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback); nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback); @@ -580,39 +571,22 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback); + /* Entries requiring custom functions */ + nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback); + if (sprom->revision >= 3) + nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, + &sprom->leddc_off_time, fallback); + switch (sprom->revision) { - case 1: - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - break; - case 2: - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - break; - case 3: - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r3(sprom, prefix, fallback); - break; case 4: case 5: - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r4589(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback); break; case 8: - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r4589(sprom, prefix, fallback); - bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); - break; case 9: - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r4589(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); break; - default: - pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", - sprom->revision); - sprom->revision = 1; - bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); } bcm47xx_sprom_fill_auto(sprom, prefix, fallback); @@ -631,19 +605,6 @@ void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo, } #endif -#ifdef CONFIG_BCM47XX_BCMA -void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo, - const char *prefix) -{ - nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0, - true); - if (!boardinfo->vendor) - boardinfo->vendor = SSB_BOARDVENDOR_BCM; - - nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true); -} -#endif - #if defined(CONFIG_BCM47XX_SSB) static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) { @@ -698,33 +659,46 @@ static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size) static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) { - char prefix[10]; + struct bcma_boardinfo *binfo = &bus->boardinfo; struct bcma_device *core; + char buf[10]; + char *prefix; + bool fallback = false; switch (bus->hosttype) { case BCMA_HOSTTYPE_PCI: memset(out, 0, sizeof(struct ssb_sprom)); - snprintf(prefix, sizeof(prefix), "pci/%u/%u/", + snprintf(buf, sizeof(buf), "pci/%u/%u/", bus->host_pci->bus->number + 1, PCI_SLOT(bus->host_pci->devfn)); - bcm47xx_sprom_apply_prefix_alias(prefix, sizeof(prefix)); - bcm47xx_fill_sprom(out, prefix, false); - return 0; + bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf)); + prefix = buf; + break; case BCMA_HOSTTYPE_SOC: memset(out, 0, sizeof(struct ssb_sprom)); core = bcma_find_core(bus, BCMA_CORE_80211); if (core) { - snprintf(prefix, sizeof(prefix), "sb/%u/", + snprintf(buf, sizeof(buf), "sb/%u/", core->core_index); - bcm47xx_fill_sprom(out, prefix, true); + prefix = buf; + fallback = true; } else { - bcm47xx_fill_sprom(out, NULL, false); + prefix = NULL; } - return 0; + break; default: pr_warn("Unable to fill SPROM for given bustype.\n"); return -EINVAL; } + + nvram_read_u16(prefix, NULL, "boardvendor", &binfo->vendor, 0, true); + if (!binfo->vendor) + binfo->vendor = SSB_BOARDVENDOR_BCM; + nvram_read_u16(prefix, NULL, "boardtype", &binfo->type, 0, true); + + bcm47xx_fill_sprom(out, prefix, fallback); + + return 0; } #endif diff --git a/arch/mips/bmips/Kconfig b/arch/mips/bmips/Kconfig index f35c84c..e2c4fd6 100644 --- a/arch/mips/bmips/Kconfig +++ b/arch/mips/bmips/Kconfig @@ -57,6 +57,10 @@ config DT_BCM97425SVMB bool "BCM97425SVMB" select BUILTIN_DTB +config DT_BCM97435SVMB + bool "BCM97435SVMB" + select BUILTIN_DTB + endchoice endif diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index fae800e..526ec27 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -149,6 +149,8 @@ void __init plat_mem_setup(void) /* intended to somewhat resemble ARM; see Documentation/arm/Booting */ if (fw_arg0 == 0 && fw_arg1 == 0xffffffff) dtb = phys_to_virt(fw_arg2); + else if (fw_arg0 == -2) /* UHI interface */ + dtb = (void *)fw_arg1; else if (__dtb_start != __dtb_end) dtb = (void *)__dtb_start; else diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S index 409cb48..c580e85 100644 --- a/arch/mips/boot/compressed/head.S +++ b/arch/mips/boot/compressed/head.S @@ -25,6 +25,22 @@ start: move s2, a2 move s3, a3 +#ifdef CONFIG_MIPS_ZBOOT_APPENDED_DTB + PTR_LA t0, __appended_dtb +#ifdef CONFIG_CPU_BIG_ENDIAN + li t1, 0xd00dfeed +#else + li t1, 0xedfe0dd0 +#endif + lw t2, (t0) + bne t1, t2, not_found + nop + + move s1, t0 + PTR_LI s0, -2 +not_found: +#endif + /* Clear BSS */ PTR_LA a0, _edata PTR_LA a2, _end diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script index 5a33409..2ed08fb 100644 --- a/arch/mips/boot/compressed/ld.script +++ b/arch/mips/boot/compressed/ld.script @@ -29,8 +29,12 @@ SECTIONS *(.image) __image_end = .; CONSTRUCTORS + . = ALIGN(16); } - . = ALIGN(16); + __appended_dtb = .; + /* leave space for appended DTB */ + . += 0x100000; + _edata = .; /* End of data section */ diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c index 237494b..408799a 100644 --- a/arch/mips/boot/compressed/uart-16550.c +++ b/arch/mips/boot/compressed/uart-16550.c @@ -7,7 +7,7 @@ #include <asm/addrspace.h> -#if defined(CONFIG_MACH_LOONGSON) || defined(CONFIG_MIPS_MALTA) +#if defined(CONFIG_MACH_LOONGSON64) || defined(CONFIG_MIPS_MALTA) #define UART_BASE 0x1fd003f8 #define PORT(offset) (CKSEG1ADDR(UART_BASE) + (offset)) #endif diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile index 5d95e4b..778a340 100644 --- a/arch/mips/boot/dts/Makefile +++ b/arch/mips/boot/dts/Makefile @@ -1,8 +1,10 @@ dts-dirs += brcm dts-dirs += cavium-octeon +dts-dirs += ingenic dts-dirs += lantiq dts-dirs += mti dts-dirs += netlogic +dts-dirs += qca dts-dirs += ralink obj-y := $(addsuffix /, $(dts-dirs)) diff --git a/arch/mips/boot/dts/brcm/Makefile b/arch/mips/boot/dts/brcm/Makefile index 1c8353b..eabeb60 100644 --- a/arch/mips/boot/dts/brcm/Makefile +++ b/arch/mips/boot/dts/brcm/Makefile @@ -9,6 +9,20 @@ dtb-$(CONFIG_DT_BCM97360SVMB) += bcm97360svmb.dtb dtb-$(CONFIG_DT_BCM97362SVMB) += bcm97362svmb.dtb dtb-$(CONFIG_DT_BCM97420C) += bcm97420c.dtb dtb-$(CONFIG_DT_BCM97425SVMB) += bcm97425svmb.dtb +dtb-$(CONFIG_DT_BCM97435SVMB) += bcm97435svmb.dtb + +dtb-$(CONFIG_DT_NONE) += \ + bcm93384wvg.dtb \ + bcm93384wvg_viper.dtb \ + bcm96368mvwg.dtb \ + bcm9ejtagprb.dtb \ + bcm97125cbmb.dtb \ + bcm97346dbsmb.dtb \ + bcm97358svmb.dtb \ + bcm97360svmb.dtb \ + bcm97362svmb.dtb \ + bcm97420c.dtb \ + bcm97425svmb.dtb obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index 1f30728..d817bb4 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -24,6 +24,8 @@ aliases { uart0 = &uart0; + uart1 = &uart1; + uart2 = &uart2; }; cpu_intc: cpu_intc { @@ -118,6 +120,30 @@ status = "disabled"; }; + uart1: serial@406940 { + compatible = "ns16550a"; + reg = <0x406940 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406980 { + compatible = "ns16550a"; + reg = <0x406980 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <66>; + clocks = <&uart_clk>; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi index 2c2aa93..277a90a 100644 --- a/arch/mips/boot/dts/brcm/bcm7358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi @@ -18,6 +18,8 @@ aliases { uart0 = &uart0; + uart1 = &uart1; + uart2 = &uart2; }; cpu_intc: cpu_intc { @@ -112,6 +114,30 @@ status = "disabled"; }; + uart1: serial@406840 { + compatible = "ns16550a"; + reg = <0x406840 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <62>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406880 { + compatible = "ns16550a"; + reg = <0x406880 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <63>; + clocks = <&uart_clk>; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi index f23b0ae..9e1e571 100644 --- a/arch/mips/boot/dts/brcm/bcm7360.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi @@ -18,6 +18,8 @@ aliases { uart0 = &uart0; + uart1 = &uart1; + uart2 = &uart2; }; cpu_intc: cpu_intc { @@ -112,6 +114,30 @@ status = "disabled"; }; + uart1: serial@406840 { + compatible = "ns16550a"; + reg = <0x406840 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <62>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406880 { + compatible = "ns16550a"; + reg = <0x406880 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <63>; + clocks = <&uart_clk>; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index da99db6..6e65db8 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -24,6 +24,8 @@ aliases { uart0 = &uart0; + uart1 = &uart1; + uart2 = &uart2; }; cpu_intc: cpu_intc { @@ -118,6 +120,30 @@ status = "disabled"; }; + uart1: serial@406840 { + compatible = "ns16550a"; + reg = <0x406840 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <62>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@406880 { + compatible = "ns16550a"; + reg = <0x406880 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <63>; + clocks = <&uart_clk>; + status = "disabled"; + }; + enet0: ethernet@430000 { phy-mode = "internal"; phy-handle = <&phy1>; diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi new file mode 100644 index 0000000..8b9432c --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi @@ -0,0 +1,239 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7435"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <163125000>; + + cpu@0 { + compatible = "brcm,bmips5200"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips5200"; + device_type = "cpu"; + reg = <1>; + }; + + cpu@2 { + compatible = "brcm,bmips5200"; + device_type = "cpu"; + reg = <2>; + }; + + cpu@3 { + compatible = "brcm,bmips5200"; + device_type = "cpu"; + reg = <3>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@41b500 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x41b500 0x40>, <0x41b600 0x40>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + sun_l2_intc: sun_l2_intc@403000 { + compatible = "brcm,l2-intc"; + reg = <0x403000 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <52>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0xf77f>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "webcpu_0", + "pcie_0", "bsp_0", + "rdc_0", "raaga_0", + "avd_1", "jtag_0", + "svd_0", "vice_0", + "vice_1", "raaga_1", + "scpu"; + }; + + upg_irq0_intc: upg_irq0_intc@406780 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406780 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <60>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; + reg = <0x404000 0x51c>; + little-endian; + }; + + reboot { + compatible = "brcm,brcmstb-reboot"; + syscon = <&sun_top_ctrl 0x304 0x308>; + }; + + uart0: serial@406b00 { + compatible = "ns16550a"; + reg = <0x406b00 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <66>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@b80000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v3"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0xb80000 0x11c88>; + interrupts = <17>, <18>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v3"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,40nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@480300 { + compatible = "brcm,bcm7435-ehci", "generic-ehci"; + reg = <0x480300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <70>; + status = "disabled"; + }; + + ohci0: usb@480400 { + compatible = "brcm,bcm7435-ohci", "generic-ohci"; + reg = <0x480400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <72>; + status = "disabled"; + }; + + ehci1: usb@480500 { + compatible = "brcm,bcm7435-ehci", "generic-ehci"; + reg = <0x480500 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <71>; + status = "disabled"; + }; + + ohci1: usb@480600 { + compatible = "brcm,bcm7435-ohci", "generic-ohci"; + reg = <0x480600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <73>; + status = "disabled"; + }; + + ehci2: usb@490300 { + compatible = "brcm,bcm7435-ehci", "generic-ehci"; + reg = <0x490300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <75>; + status = "disabled"; + }; + + ohci2: usb@490400 { + compatible = "brcm,bcm7435-ohci", "generic-ohci"; + reg = <0x490400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <77>; + status = "disabled"; + }; + + ehci3: usb@490500 { + compatible = "brcm,bcm7435-ehci", "generic-ehci"; + reg = <0x490500 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <76>; + status = "disabled"; + }; + + ohci3: usb@490600 { + compatible = "brcm,bcm7435-ohci", "generic-ohci"; + reg = <0x490600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <78>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts index 70f196d..3fe0445 100644 --- a/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts @@ -21,6 +21,14 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + &enet0 { status = "okay"; }; diff --git a/arch/mips/boot/dts/brcm/bcm97358svmb.dts b/arch/mips/boot/dts/brcm/bcm97358svmb.dts index d18e6d9..a8dc01e 100644 --- a/arch/mips/boot/dts/brcm/bcm97358svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97358svmb.dts @@ -21,6 +21,14 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + &enet0 { status = "okay"; }; diff --git a/arch/mips/boot/dts/brcm/bcm97360svmb.dts b/arch/mips/boot/dts/brcm/bcm97360svmb.dts index 4fe5155..eee8b0e 100644 --- a/arch/mips/boot/dts/brcm/bcm97360svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97360svmb.dts @@ -21,6 +21,14 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + &enet0 { status = "okay"; }; diff --git a/arch/mips/boot/dts/brcm/bcm97362svmb.dts b/arch/mips/boot/dts/brcm/bcm97362svmb.dts index b7b88e5..739c2ef 100644 --- a/arch/mips/boot/dts/brcm/bcm97362svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97362svmb.dts @@ -21,6 +21,14 @@ status = "okay"; }; +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + &enet0 { status = "okay"; }; diff --git a/arch/mips/boot/dts/brcm/bcm97435svmb.dts b/arch/mips/boot/dts/brcm/bcm97435svmb.dts new file mode 100644 index 0000000..1df0881 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97435svmb.dts @@ -0,0 +1,60 @@ +/dts-v1/; + +/include/ "bcm7435.dtsi" + +/ { + compatible = "brcm,bcm97435svmb", "brcm,bcm7435"; + model = "Broadcom BCM97435SVMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, + <0x20000000 0x30000000>, + <0x90000000 0x40000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200 maxcpus=1"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&enet0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&ohci3 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile new file mode 100644 index 0000000..f2b864f --- /dev/null +++ b/arch/mips/boot/dts/ingenic/Makefile @@ -0,0 +1,10 @@ +dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb +dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts new file mode 100644 index 0000000..9fcb9e7 --- /dev/null +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -0,0 +1,44 @@ +/dts-v1/; + +#include "jz4780.dtsi" + +/ { + compatible = "img,ci20", "ingenic,jz4780"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial3 = &uart3; + serial4 = &uart4; + }; + + chosen { + stdout-path = &uart4; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x10000000 + 0x30000000 0x30000000>; + }; +}; + +&ext { + clock-frequency = <48000000>; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi new file mode 100644 index 0000000..8b2437c --- /dev/null +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -0,0 +1,68 @@ +#include <dt-bindings/clock/jz4740-cgu.h> + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ingenic,jz4740"; + + cpuintc: interrupt-controller@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: interrupt-controller@10001000 { + compatible = "ingenic,jz4740-intc"; + reg = <0x10001000 0x14>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + rtc: rtc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + cgu: jz4740-cgu@10000000 { + compatible = "ingenic,jz4740-cgu"; + reg = <0x10000000 0x100>; + + clocks = <&ext>, <&rtc>; + clock-names = "ext", "rtc"; + + #clock-cells = <1>; + }; + + uart0: serial@10030000 { + compatible = "ingenic,jz4740-uart"; + reg = <0x10030000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <9>; + + clocks = <&ext>, <&cgu JZ4740_CLK_UART0>; + clock-names = "baud", "module"; + }; + + uart1: serial@10031000 { + compatible = "ingenic,jz4740-uart"; + reg = <0x10031000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <8>; + + clocks = <&ext>, <&cgu JZ4740_CLK_UART1>; + clock-names = "baud", "module"; + }; +}; diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi new file mode 100644 index 0000000..65389f6 --- /dev/null +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi @@ -0,0 +1,111 @@ +#include <dt-bindings/clock/jz4780-cgu.h> + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ingenic,jz4780"; + + cpuintc: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: interrupt-controller@10001000 { + compatible = "ingenic,jz4780-intc"; + reg = <0x10001000 0x50>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + rtc: rtc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + cgu: jz4780-cgu@10000000 { + compatible = "ingenic,jz4780-cgu"; + reg = <0x10000000 0x100>; + + clocks = <&ext>, <&rtc>; + clock-names = "ext", "rtc"; + + #clock-cells = <1>; + }; + + uart0: serial@10030000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10030000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <51>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART0>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart1: serial@10031000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10031000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <50>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART1>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart2: serial@10032000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10032000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <49>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART2>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart3: serial@10033000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10033000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <48>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART3>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart4: serial@10034000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10034000 0x100>; + + interrupt-parent = <&intc>; + interrupts = <34>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART4>; + clock-names = "baud", "module"; + + status = "disabled"; + }; +}; diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts new file mode 100644 index 0000000..2414d63 --- /dev/null +++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts @@ -0,0 +1,15 @@ +/dts-v1/; + +#include "jz4740.dtsi" + +/ { + compatible = "qi,lb60", "ingenic,jz4740"; + + chosen { + stdout-path = &uart0; + }; +}; + +&ext { + clock-frequency = <12000000>; +}; diff --git a/arch/mips/boot/dts/mti/Makefile b/arch/mips/boot/dts/mti/Makefile index ef1f3db..144d776 100644 --- a/arch/mips/boot/dts/mti/Makefile +++ b/arch/mips/boot/dts/mti/Makefile @@ -1,3 +1,4 @@ +dtb-$(CONFIG_MIPS_MALTA) += malta.dtb dtb-$(CONFIG_MIPS_SEAD3) += sead3.dtb obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) diff --git a/arch/mips/boot/dts/mti/malta.dts b/arch/mips/boot/dts/mti/malta.dts new file mode 100644 index 0000000..c678115 --- /dev/null +++ b/arch/mips/boot/dts/mti/malta.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mti,malta"; +}; diff --git a/arch/mips/boot/dts/qca/Makefile b/arch/mips/boot/dts/qca/Makefile new file mode 100644 index 0000000..2d61455d --- /dev/null +++ b/arch/mips/boot/dts/qca/Makefile @@ -0,0 +1,11 @@ +# All DTBs +dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb + +# Select a DTB to build in the kernel +obj-$(CONFIG_DTB_TL_WR1043ND_V1) += ar9132_tl_wr1043nd_v1.dtb.o + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/qca/ar9132.dtsi b/arch/mips/boot/dts/qca/ar9132.dtsi new file mode 100644 index 0000000..4759cff --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9132.dtsi @@ -0,0 +1,133 @@ +/ { + compatible = "qca,ar9132"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips24Kc"; + reg = <0>; + }; + }; + + cpuintc: interrupt-controller { + compatible = "qca,ar9132-cpu-intc", "qca,ar7100-cpu-intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + qca,ddr-wb-channel-interrupts = <2>, <3>, <4>, <5>; + qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>, + <&ddr_ctrl 0>, <&ddr_ctrl 1>; + }; + + ahb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&cpuintc>; + + apb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&miscintc>; + + ddr_ctrl: memory-controller@18000000 { + compatible = "qca,ar9132-ddr-controller", + "qca,ar7240-ddr-controller"; + reg = <0x18000000 0x100>; + + #qca,ddr-wb-channel-cells = <1>; + }; + + uart@18020000 { + compatible = "ns8250"; + reg = <0x18020000 0x20>; + interrupts = <3>; + + clocks = <&pll 2>; + clock-names = "uart"; + + reg-io-width = <4>; + reg-shift = <2>; + no-loopback-test; + + status = "disabled"; + }; + + gpio: gpio@18040000 { + compatible = "qca,ar9132-gpio", + "qca,ar7100-gpio"; + reg = <0x18040000 0x30>; + interrupts = <2>; + + ngpios = <22>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + pll: pll-controller@18050000 { + compatible = "qca,ar9132-ppl", + "qca,ar9130-pll"; + reg = <0x18050000 0x20>; + + clock-names = "ref"; + /* The board must provides the ref clock */ + + #clock-cells = <1>; + clock-output-names = "cpu", "ddr", "ahb"; + }; + + wdt@18060008 { + compatible = "qca,ar7130-wdt"; + reg = <0x18060008 0x8>; + + interrupts = <4>; + + clocks = <&pll 2>; + clock-names = "wdt"; + }; + + miscintc: interrupt-controller@18060010 { + compatible = "qca,ar9132-misc-intc", + "qca,ar7100-misc-intc"; + reg = <0x18060010 0x4>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + spi@1f000000 { + compatible = "qca,ar9132-spi", "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + + clocks = <&pll 2>; + clock-names = "ahb"; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; diff --git a/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts b/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts new file mode 100644 index 0000000..003015a --- /dev/null +++ b/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts @@ -0,0 +1,112 @@ +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +#include "ar9132.dtsi" + +/ { + compatible = "tplink,tl-wr1043nd-v1", "qca,ar9132"; + model = "TP-Link TL-WR1043ND Version 1"; + + alias { + serial0 = "/ahb/apb/uart@18020000"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x2000000>; + }; + + extosc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <40000000>; + }; + + ahb { + apb { + uart@18020000 { + status = "okay"; + }; + + pll-controller@18050000 { + clocks = <&extosc>; + }; + }; + + spi@1f000000 { + status = "okay"; + num-cs = <1>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25sl064a"; + reg = <0>; + spi-max-frequency = <25000000>; + + partition@0 { + label = "u-boot"; + reg = <0x000000 0x020000>; + }; + + partition@1 { + label = "firmware"; + reg = <0x020000 0x7D0000>; + }; + + partition@2 { + label = "art"; + reg = <0x7F0000 0x010000>; + read-only; + }; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + + poll-interval = <20>; + button@0 { + label = "reset"; + linux,code = <KEY_RESTART>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + + button@1 { + label = "qss"; + linux,code = <KEY_WPS_BUTTON>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + led@0 { + label = "tp-link:green:usb"; + gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + }; + + led@1 { + label = "tp-link:green:system"; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + + led@2 { + label = "tp-link:green:qss"; + gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; + }; + + led@3 { + label = "tp-link:green:wlan"; + gpios = <&gpio 9 GPIO_ACTIVE_LOW>; + }; + }; +}; diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 10f7625..d8124a3 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -698,7 +698,9 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data) static void octeon_irq_handle_trigger(unsigned int irq, struct irq_desc *desc) { - if (irq_get_trigger_type(irq) & IRQ_TYPE_EDGE_BOTH) + struct irq_data *data = irq_desc_get_irq_data(desc); + + if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH) handle_edge_irq(irq, desc); else handle_level_irq(irq, desc); diff --git a/arch/mips/cobalt/mtd.c b/arch/mips/cobalt/mtd.c index 8db7b5d..83e1b10 100644 --- a/arch/mips/cobalt/mtd.c +++ b/arch/mips/cobalt/mtd.c @@ -57,5 +57,4 @@ static int __init cobalt_mtd_init(void) return 0; } - -module_init(cobalt_mtd_init); +device_initcall(cobalt_mtd_init); diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig new file mode 100644 index 0000000..4e36b6e --- /dev/null +++ b/arch/mips/configs/ci20_defconfig @@ -0,0 +1,162 @@ +CONFIG_MACH_INGENIC=y +CONFIG_JZ4780_CI20=y +CONFIG_HIGHMEM=y +# CONFIG_COMPACTION is not set +CONFIG_CMA=y +CONFIG_HZ_100=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_XZ=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_SCHED=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +# CONFIG_FW_LOADER is not set +# CONFIG_ALLOW_DEV_COREDUMP is not set +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=32 +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_DM9000=y +CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=2 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +CONFIG_SERIAL_8250_INGENIC=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_JZ4780=y +CONFIG_GPIO_SYSFS=y +# CONFIG_HWMON is not set +CONFIG_REGULATOR=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_HID is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_MEMORY=y +# CONFIG_DNOTIFY is not set +CONFIG_PROC_KCORE=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_TMPFS=y +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_STRIP_ASM_SYMS=y +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=10 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_STACKTRACE=y +# CONFIG_FTRACE is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="earlycon console=ttyS4,115200 clk_ignore_unused" diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig index b2a577e..a75c65d 100644 --- a/arch/mips/configs/fuloong2e_defconfig +++ b/arch/mips/configs/fuloong2e_defconfig @@ -1,4 +1,4 @@ -CONFIG_MACH_LOONGSON=y +CONFIG_MACH_LOONGSON64=y CONFIG_64BIT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig index 0cbc986..54cc385 100644 --- a/arch/mips/configs/lemote2f_defconfig +++ b/arch/mips/configs/lemote2f_defconfig @@ -1,4 +1,4 @@ -CONFIG_MACH_LOONGSON=y +CONFIG_MACH_LOONGSON64=y CONFIG_LEMOTE_MACH2F=y CONFIG_CS5536_MFGPT=y CONFIG_64BIT=y diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig index c844299..f8bf915c 100644 --- a/arch/mips/configs/loongson3_defconfig +++ b/arch/mips/configs/loongson3_defconfig @@ -1,4 +1,4 @@ -CONFIG_MACH_LOONGSON=y +CONFIG_MACH_LOONGSON64=y CONFIG_SWIOTLB=y CONFIG_LOONGSON_MACH3X=y CONFIG_CPU_LOONGSON3=y diff --git a/arch/mips/configs/ls1b_defconfig b/arch/mips/configs/ls1b_defconfig index 7eb7554..1b2cc1f 100644 --- a/arch/mips/configs/ls1b_defconfig +++ b/arch/mips/configs/ls1b_defconfig @@ -1,4 +1,4 @@ -CONFIG_MACH_LOONGSON1=y +CONFIG_MACH_LOONGSON32=y CONFIG_PREEMPT=y # CONFIG_SECCOMP is not set CONFIG_EXPERIMENTAL=y diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig index f8a3231..ac0eb4d 100644 --- a/arch/mips/configs/maltasmvp_defconfig +++ b/arch/mips/configs/maltasmvp_defconfig @@ -84,15 +84,12 @@ CONFIG_NET_CLS_IND=y CONFIG_DEVTMPFS=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_IDE=y -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +# CONFIG_SATA_PMP is not set +CONFIG_ATA_PIIX=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set @@ -138,7 +135,6 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_HW_RANDOM=y # CONFIG_HWMON is not set -CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y CONFIG_FIRMWARE_EDID=y CONFIG_FB_MATROX=y @@ -152,7 +148,6 @@ CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_IDE_DISK=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y @@ -160,7 +155,11 @@ CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_CMOS=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y CONFIG_XFS_FS=y CONFIG_XFS_QUOTA=y CONFIG_XFS_POSIX_ACL=y diff --git a/arch/mips/configs/pistachio_defconfig b/arch/mips/configs/pistachio_defconfig index f22e92e..1646cce 100644 --- a/arch/mips/configs/pistachio_defconfig +++ b/arch/mips/configs/pistachio_defconfig @@ -272,6 +272,7 @@ CONFIG_IIO=y CONFIG_CC10001_ADC=y CONFIG_PWM=y CONFIG_PWM_IMG=y +CONFIG_PHY_PISTACHIO_USB=y CONFIG_ANDROID=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig index 2b96547..d7bb8cc 100644 --- a/arch/mips/configs/qi_lb60_defconfig +++ b/arch/mips/configs/qi_lb60_defconfig @@ -1,4 +1,4 @@ -CONFIG_MACH_JZ4740=y +CONFIG_MACH_INGENIC=y # CONFIG_COMPACTION is not set # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_HZ_100=y @@ -66,6 +66,7 @@ CONFIG_SERIAL_8250_CONSOLE=y # CONFIG_SERIAL_8250_DMA is not set CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_INGENIC=y # CONFIG_HW_RANDOM is not set CONFIG_SPI=y CONFIG_SPI_GPIO=y diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 6156ac8..76317a7 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -211,9 +211,13 @@ .endm #ifdef TOOLCHAIN_SUPPORTS_MSA +/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ +#undef fp + .macro _cfcmsa rd, cs .set push .set mips32r2 + .set fp=64 .set msa cfcmsa \rd, $\cs .set pop @@ -222,6 +226,7 @@ .macro _ctcmsa cd, rs .set push .set mips32r2 + .set fp=64 .set msa ctcmsa $\cd, \rs .set pop @@ -230,6 +235,7 @@ .macro ld_d wd, off, base .set push .set mips32r2 + .set fp=64 .set msa ld.d $w\wd, \off(\base) .set pop @@ -238,6 +244,7 @@ .macro st_d wd, off, base .set push .set mips32r2 + .set fp=64 .set msa st.d $w\wd, \off(\base) .set pop @@ -246,6 +253,7 @@ .macro copy_u_w ws, n .set push .set mips32r2 + .set fp=64 .set msa copy_u.w $1, $w\ws[\n] .set pop @@ -254,6 +262,7 @@ .macro copy_u_d ws, n .set push .set mips64r2 + .set fp=64 .set msa copy_u.d $1, $w\ws[\n] .set pop @@ -262,6 +271,7 @@ .macro insert_w wd, n .set push .set mips32r2 + .set fp=64 .set msa insert.w $w\wd[\n], $1 .set pop @@ -270,6 +280,7 @@ .macro insert_d wd, n .set push .set mips64r2 + .set fp=64 .set msa insert.d $w\wd[\n], $1 .set pop diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 0cf29bd..ce9666c 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -469,7 +469,7 @@ static inline int test_and_change_bit(unsigned long nr, */ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr) { - smp_mb(); + smp_mb__before_llsc(); __clear_bit(nr, addr); } diff --git a/arch/mips/include/asm/bmips-spaces.h b/arch/mips/include/asm/bmips-spaces.h new file mode 100644 index 0000000..eb96541 --- /dev/null +++ b/arch/mips/include/asm/bmips-spaces.h @@ -0,0 +1,7 @@ +#ifndef __ASM_BMIPS_SPACES_H +#define __ASM_BMIPS_SPACES_H + +/* Avoid collisions with system base register (SBR) region on BMIPS3300 */ +#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) + +#endif /* __ASM_BMIPS_SPACES_H */ diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 5aeaf19..f25de77 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -108,6 +108,9 @@ #ifndef cpu_has_llsc #define cpu_has_llsc (cpu_data[0].options & MIPS_CPU_LLSC) #endif +#ifndef cpu_has_bp_ghist +#define cpu_has_bp_ghist (cpu_data[0].options & MIPS_CPU_BP_GHIST) +#endif #ifndef kernel_uses_llsc #define kernel_uses_llsc cpu_has_llsc #endif diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index 33f3cab..d41e8e2 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -32,12 +32,12 @@ static inline int __pure __get_cpu_type(const int cpu_type) case CPU_4KC: case CPU_ALCHEMY: case CPU_PR4450: - case CPU_JZRISC: #endif #if defined(CONFIG_SYS_HAS_CPU_MIPS32_R1) || \ defined(CONFIG_SYS_HAS_CPU_MIPS32_R2) case CPU_4KEC: + case CPU_JZRISC: #endif #ifdef CONFIG_SYS_HAS_CPU_MIPS32_R2 diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index e3adca1..e46e406 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -42,7 +42,9 @@ #define PRID_COMP_LEXRA 0x0b0000 #define PRID_COMP_NETLOGIC 0x0c0000 #define PRID_COMP_CAVIUM 0x0d0000 -#define PRID_COMP_INGENIC 0xd00000 +#define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750 */ +#define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775 */ +#define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */ /* * Assigned Processor ID (implementation) values for bits 15:8 of the PRId @@ -168,7 +170,7 @@ #define PRID_IMP_CAVIUM_CN70XX 0x9600 /* - * These are the PRID's for when 23:16 == PRID_COMP_INGENIC + * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_* */ #define PRID_IMP_JZRISC 0x0200 @@ -379,6 +381,7 @@ enum cpu_type_enum { #define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */ #define MIPS_CPU_XPA 0x2000000000ull /* CPU supports Extended Physical Addressing */ #define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */ +#define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 4087b47..7b99efd 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -31,9 +31,15 @@ #define __mtc0_tlbw_hazard \ ___ehb +#define __mtc0_tlbr_hazard \ + ___ehb + #define __tlbw_use_hazard \ ___ehb +#define __tlb_read_hazard \ + ___ehb + #define __tlb_probe_hazard \ ___ehb @@ -80,12 +86,23 @@ do { \ ___ssnop; \ ___ehb +#define __mtc0_tlbr_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ehb + #define __tlbw_use_hazard \ ___ssnop; \ ___ssnop; \ ___ssnop; \ ___ehb +#define __tlb_read_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop; \ + ___ehb + #define __tlb_probe_hazard \ ___ssnop; \ ___ssnop; \ @@ -147,8 +164,12 @@ do { \ #define __mtc0_tlbw_hazard +#define __mtc0_tlbr_hazard + #define __tlbw_use_hazard +#define __tlb_read_hazard + #define __tlb_probe_hazard #define __irq_enable_hazard @@ -166,8 +187,12 @@ do { \ */ #define __mtc0_tlbw_hazard +#define __mtc0_tlbr_hazard + #define __tlbw_use_hazard +#define __tlb_read_hazard + #define __tlb_probe_hazard #define __irq_enable_hazard @@ -196,11 +221,20 @@ do { \ nop; \ nop +#define __mtc0_tlbr_hazard \ + nop; \ + nop + #define __tlbw_use_hazard \ nop; \ nop; \ nop +#define __tlb_read_hazard \ + nop; \ + nop; \ + nop + #define __tlb_probe_hazard \ nop; \ nop; \ @@ -267,7 +301,9 @@ do { \ #define _ssnop ___ssnop #define _ehb ___ehb #define mtc0_tlbw_hazard __mtc0_tlbw_hazard +#define mtc0_tlbr_hazard __mtc0_tlbr_hazard #define tlbw_use_hazard __tlbw_use_hazard +#define tlb_read_hazard __tlb_read_hazard #define tlb_probe_hazard __tlb_probe_hazard #define irq_enable_hazard __irq_enable_hazard #define irq_disable_hazard __irq_disable_hazard @@ -300,6 +336,14 @@ do { \ } while (0) +#define mtc0_tlbr_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__mtc0_tlbr_hazard) \ + ); \ +} while (0) + + #define tlbw_use_hazard() \ do { \ __asm__ __volatile__( \ @@ -308,6 +352,14 @@ do { \ } while (0) +#define tlb_read_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__tlb_read_hazard) \ + ); \ +} while (0) + + #define tlb_probe_hazard() \ do { \ __asm__ __volatile__( \ diff --git a/arch/mips/include/asm/i8259.h b/arch/mips/include/asm/i8259.h index c7e2784..a7fbcd6 100644 --- a/arch/mips/include/asm/i8259.h +++ b/arch/mips/include/asm/i8259.h @@ -41,6 +41,7 @@ extern int i8259A_irq_pending(unsigned int irq); extern void make_8259A_irq(unsigned int irq); extern void init_i8259_irqs(void); +extern int i8259_of_init(struct device_node *node, struct device_node *parent); /* * Do the traditional i8259 interrupt polling thing. This is for the few diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index d60cc68..e7b138b 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -60,7 +60,7 @@ static inline void arch_local_irq_restore(unsigned long flags) " .set push \n" " .set noreorder \n" " .set noat \n" -#if defined(CONFIG_IRQ_CPU) +#if defined(CONFIG_IRQ_MIPS_CPU) /* * Slow, but doesn't suffer from a relatively unlikely race * condition we're having since days 1. @@ -90,7 +90,7 @@ static inline void __arch_local_irq_restore(unsigned long flags) " .set push \n" " .set noreorder \n" " .set noat \n" -#if defined(CONFIG_IRQ_CPU) +#if defined(CONFIG_IRQ_MIPS_CPU) /* * Slow, but doesn't suffer from a relatively unlikely race * condition we're having since days 1. diff --git a/arch/mips/include/asm/kgdb.h b/arch/mips/include/asm/kgdb.h index e6c0b0e..69dc0df 100644 --- a/arch/mips/include/asm/kgdb.h +++ b/arch/mips/include/asm/kgdb.h @@ -33,7 +33,6 @@ #define CACHE_FLUSH_IS_SAFE 0 extern void arch_kgdb_breakpoint(void); -extern int kgdb_early_setup; extern void *saved_vectors[32]; extern void handle_exception(struct pt_regs *regs); extern void breakinst(void); diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h index cd41e93..aa3800c 100644 --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h @@ -157,8 +157,8 @@ #define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 #define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 -#define AR71XX_PLL_DIV_SHIFT 3 -#define AR71XX_PLL_DIV_MASK 0x1f +#define AR71XX_PLL_FB_SHIFT 3 +#define AR71XX_PLL_FB_MASK 0x1f #define AR71XX_CPU_DIV_SHIFT 16 #define AR71XX_CPU_DIV_MASK 0x3 #define AR71XX_DDR_DIV_SHIFT 18 @@ -169,8 +169,8 @@ #define AR724X_PLL_REG_CPU_CONFIG 0x00 #define AR724X_PLL_REG_PCIE_CONFIG 0x18 -#define AR724X_PLL_DIV_SHIFT 0 -#define AR724X_PLL_DIV_MASK 0x3ff +#define AR724X_PLL_FB_SHIFT 0 +#define AR724X_PLL_FB_MASK 0x3ff #define AR724X_PLL_REF_DIV_SHIFT 10 #define AR724X_PLL_REF_DIV_MASK 0xf #define AR724X_AHB_DIV_SHIFT 19 @@ -183,8 +183,8 @@ #define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 #define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18 -#define AR913X_PLL_DIV_SHIFT 0 -#define AR913X_PLL_DIV_MASK 0x3ff +#define AR913X_PLL_FB_SHIFT 0 +#define AR913X_PLL_FB_MASK 0x3ff #define AR913X_DDR_DIV_SHIFT 22 #define AR913X_DDR_DIV_MASK 0x3 #define AR913X_AHB_DIV_SHIFT 19 diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h index 1557934..4eee221 100644 --- a/arch/mips/include/asm/mach-ath79/ath79.h +++ b/arch/mips/include/asm/mach-ath79/ath79.h @@ -115,7 +115,8 @@ static inline int soc_is_qca955x(void) return soc_is_qca9556() || soc_is_qca9558(); } -extern void __iomem *ath79_ddr_base; +void ath79_ddr_set_pci_windows(void); + extern void __iomem *ath79_pll_base; extern void __iomem *ath79_reset_base; diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h index 8ed77f6..1461c10 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h @@ -52,10 +52,6 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo, const char *prefix); #endif -#ifdef CONFIG_BCM47XX_BCMA -void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo, - const char *prefix); -#endif void bcm47xx_set_system_type(u16 chip_id); diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h index c41d1dce1..2afb840 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h @@ -80,6 +80,8 @@ enum bcm47xx_board { BCM47XX_BOARD_LINKSYS_WRT610NV2, BCM47XX_BOARD_LINKSYS_WRTSL54GS, + BCM47XX_BOARD_LUXUL_XWR_1750_V1, + BCM47XX_BOARD_MICROSOFT_MN700, BCM47XX_BOARD_MOTOROLA_WE800G, diff --git a/arch/mips/include/asm/mach-bcm63xx/spaces.h b/arch/mips/include/asm/mach-bcm63xx/spaces.h index 61e750f..1410ed0 100644 --- a/arch/mips/include/asm/mach-bcm63xx/spaces.h +++ b/arch/mips/include/asm/mach-bcm63xx/spaces.h @@ -10,7 +10,7 @@ #ifndef _ASM_BCM63XX_SPACES_H #define _ASM_BCM63XX_SPACES_H -#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) +#include <asm/bmips-spaces.h> #include <asm/mach-generic/spaces.h> diff --git a/arch/mips/include/asm/mach-bmips/spaces.h b/arch/mips/include/asm/mach-bmips/spaces.h index 1b05bdd..c59b28f 100644 --- a/arch/mips/include/asm/mach-bmips/spaces.h +++ b/arch/mips/include/asm/mach-bmips/spaces.h @@ -11,7 +11,7 @@ #define _ASM_BMIPS_SPACES_H /* Avoid collisions with system base register (SBR) region on BMIPS3300 */ -#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) +#include <asm/bmips-spaces.h> #include <asm/mach-generic/spaces.h> diff --git a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h index bdf045f..21eae03 100644 --- a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h @@ -14,6 +14,13 @@ /* Generic ones first. */ #define cpu_has_tlb 1 +#define cpu_has_tlbinv 0 +#define cpu_has_segments 0 +#define cpu_has_eva 0 +#define cpu_has_htw 0 +#define cpu_has_rixiex 0 +#define cpu_has_maar 0 +#define cpu_has_rw_llb 0 #define cpu_has_tx39_cache 0 #define cpu_has_divec 0 #define cpu_has_prefetch 0 @@ -24,6 +31,7 @@ #define cpu_has_mips3d 0 #define cpu_has_smartmips 0 #define cpu_has_rixi 0 +#define cpu_has_xpa 0 #define cpu_has_vtag_icache 0 #define cpu_has_ic_fills_f_dc 0 #define cpu_has_pindexed_dcache 0 @@ -36,11 +44,18 @@ #define cpu_has_mips64r1 0 #define cpu_has_mips64r2 0 #define cpu_has_dsp 0 +#define cpu_has_dsp2 0 #define cpu_has_mipsmt 0 #define cpu_has_userlocal 0 +#define cpu_hwrena_impl_bits 0 +#define cpu_has_perf_cntr_intr_bit 0 +#define cpu_has_vz 0 +#define cpu_has_fre 0 +#define cpu_has_cdmm 0 /* R3k-specific ones. */ #ifdef CONFIG_CPU_R3000 +#define cpu_has_3kex 1 #define cpu_has_4kex 0 #define cpu_has_3k_cache 1 #define cpu_has_4k_cache 0 @@ -63,6 +78,7 @@ /* R4k-specific ones. */ #ifdef CONFIG_CPU_R4X00 +#define cpu_has_3kex 0 #define cpu_has_4kex 1 #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 diff --git a/arch/mips/include/asm/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h index 050e18b..be546a0 100644 --- a/arch/mips/include/asm/mach-generic/irq.h +++ b/arch/mips/include/asm/mach-generic/irq.h @@ -18,7 +18,7 @@ #endif #endif -#ifdef CONFIG_IRQ_CPU +#ifdef CONFIG_IRQ_MIPS_CPU #ifndef MIPS_CPU_IRQ_BASE #ifdef CONFIG_I8259 @@ -34,7 +34,7 @@ #endif #endif -#endif /* CONFIG_IRQ_CPU */ +#endif /* CONFIG_IRQ_MIPS_CPU */ #ifdef CONFIG_MIPS_GIC #ifndef MIPS_GIC_IRQ_BASE diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h index 9488fa5..afc96ec 100644 --- a/arch/mips/include/asm/mach-generic/spaces.h +++ b/arch/mips/include/asm/mach-generic/spaces.h @@ -94,7 +94,11 @@ #endif #ifndef FIXADDR_TOP +#ifdef CONFIG_KVM_GUEST +#define FIXADDR_TOP ((unsigned long)(long)(int)0x7ffe0000) +#else #define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) #endif +#endif #endif /* __ASM_MACH_GENERIC_SPACES_H */ diff --git a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h index d6111aa..7449794 100644 --- a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h @@ -11,47 +11,69 @@ #include <asm/cpu.h> /* - * IP27 only comes with R10000 family processors all using the same config + * IP27 only comes with R1x000 family processors, all using the same config */ -#define cpu_has_watch 1 -#define cpu_has_mips16 0 -#define cpu_has_divec 0 -#define cpu_has_vce 0 -#define cpu_has_cache_cdex_p 0 -#define cpu_has_cache_cdex_s 0 -#define cpu_has_prefetch 1 -#define cpu_has_mcheck 0 -#define cpu_has_ejtag 0 +#define cpu_has_tlb 1 +#define cpu_has_tlbinv 0 +#define cpu_has_segments 0 +#define cpu_has_eva 0 +#define cpu_has_htw 0 +#define cpu_has_rixiex 0 +#define cpu_has_maar 0 +#define cpu_has_rw_llb 0 +#define cpu_has_3kex 0 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_6k_cache 0 +#define cpu_has_8k_cache 0 +#define cpu_has_tx39_cache 0 +#define cpu_has_fpu 1 +#define cpu_has_nofpuex 0 +#define cpu_has_32fpr 1 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_64bits 1 +#define cpu_has_divec 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 +#define cpu_has_llsc 1 +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 +#define cpu_has_rixi 0 +#define cpu_has_xpa 0 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 -#define cpu_has_llsc 1 -#define cpu_has_vtag_icache 0 -#define cpu_has_dc_aliases 0 -#define cpu_has_ic_fills_f_dc 0 -#define cpu_has_dsp 0 -#define cpu_has_dsp2 0 #define cpu_icache_snoops_remote_store 1 -#define cpu_has_mipsmt 0 -#define cpu_has_userlocal 0 -#define cpu_has_nofpuex 0 -#define cpu_has_64bits 1 - -#define cpu_has_4kex 1 -#define cpu_has_3k_cache 0 -#define cpu_has_6k_cache 0 -#define cpu_has_4k_cache 1 -#define cpu_has_8k_cache 0 -#define cpu_has_tx39_cache 0 +#define cpu_has_mips32r1 0 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 +#define cpu_has_mips32r6 0 +#define cpu_has_mips64r6 0 +#define cpu_has_dsp 0 +#define cpu_has_dsp2 0 +#define cpu_has_mipsmt 0 +#define cpu_has_userlocal 0 #define cpu_has_inclusive_pcaches 1 +#define cpu_hwrena_impl_bits 0 +#define cpu_has_perf_cntr_intr_bit 0 +#define cpu_has_vz 0 +#define cpu_has_fre 0 +#define cpu_has_cdmm 0 -#define cpu_dcache_line_size() 32 -#define cpu_icache_line_size() 64 -#define cpu_scache_line_size() 128 - -#define cpu_has_mips32r1 0 -#define cpu_has_mips32r2 0 -#define cpu_has_mips64r1 0 -#define cpu_has_mips64r2 0 +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 64 +#define cpu_scache_line_size() 128 #endif /* __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h index 16659cd..104d2df 100644 --- a/arch/mips/include/asm/mach-jz4740/clock.h +++ b/arch/mips/include/asm/mach-jz4740/clock.h @@ -22,6 +22,9 @@ enum jz4740_wait_mode { void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode); +void jz4740_clock_suspend(void); +void jz4740_clock_resume(void); + void jz4740_clock_udc_enable_auto_suspend(void); void jz4740_clock_udc_disable_auto_suspend(void); diff --git a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h index a225baa..0933f94 100644 --- a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h @@ -12,8 +12,6 @@ #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 #define cpu_has_tx39_cache 0 -#define cpu_has_fpu 0 -#define cpu_has_32fpr 0 #define cpu_has_counter 0 #define cpu_has_watch 1 #define cpu_has_divec 1 @@ -34,7 +32,6 @@ #define cpu_has_ic_fills_f_dc 0 #define cpu_has_pindexed_dcache 0 #define cpu_has_mips32r1 1 -#define cpu_has_mips32r2 0 #define cpu_has_mips64r1 0 #define cpu_has_mips64r2 0 #define cpu_has_dsp 0 diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h index df50736..9b439fc 100644 --- a/arch/mips/include/asm/mach-jz4740/irq.h +++ b/arch/mips/include/asm/mach-jz4740/irq.h @@ -19,6 +19,12 @@ #define MIPS_CPU_IRQ_BASE 0 #define JZ4740_IRQ_BASE 8 +#ifdef CONFIG_MACH_JZ4740 +# define NR_INTC_IRQS 32 +#else +# define NR_INTC_IRQS 64 +#endif + /* 1st-level interrupts */ #define JZ4740_IRQ(x) (JZ4740_IRQ_BASE + (x)) #define JZ4740_IRQ_I2C JZ4740_IRQ(1) @@ -44,13 +50,15 @@ #define JZ4740_IRQ_IPU JZ4740_IRQ(29) #define JZ4740_IRQ_LCD JZ4740_IRQ(30) +#define JZ4780_IRQ_TCU2 JZ4740_IRQ(25) + /* 2nd-level interrupts */ -#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(32) + (x)) +#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(NR_INTC_IRQS) + (x)) #define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x)) -#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x)) +#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(NR_INTC_IRQS + 16) + (x)) -#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(176) +#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(NR_INTC_IRQS + 144) #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6) diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index 069b43a..32cfbe6 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -35,6 +35,4 @@ extern struct platform_device jz4740_wdt_device; extern struct platform_device jz4740_pwm_device; extern struct platform_device jz4740_dma_device; -void jz4740_serial_device_register(void); - #endif diff --git a/arch/mips/include/asm/mach-loongson/workarounds.h b/arch/mips/include/asm/mach-loongson/workarounds.h deleted file mode 100644 index e180c14..0000000 --- a/arch/mips/include/asm/mach-loongson/workarounds.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_MACH_LOONGSON_WORKAROUNDS_H_ -#define __ASM_MACH_LOONGSON_WORKAROUNDS_H_ - -#define WORKAROUND_CPUFREQ 0x00000001 -#define WORKAROUND_CPUHOTPLUG 0x00000002 - -#endif diff --git a/arch/mips/include/asm/mach-loongson1/cpufreq.h b/arch/mips/include/asm/mach-loongson32/cpufreq.h index e7765ce..6843fa1 100644 --- a/arch/mips/include/asm/mach-loongson1/cpufreq.h +++ b/arch/mips/include/asm/mach-loongson32/cpufreq.h @@ -10,8 +10,8 @@ */ -#ifndef __ASM_MACH_LOONGSON1_CPUFREQ_H -#define __ASM_MACH_LOONGSON1_CPUFREQ_H +#ifndef __ASM_MACH_LOONGSON32_CPUFREQ_H +#define __ASM_MACH_LOONGSON32_CPUFREQ_H struct plat_ls1x_cpufreq { const char *clk_name; /* CPU clk */ @@ -20,4 +20,4 @@ struct plat_ls1x_cpufreq { unsigned int min_freq; /* in kHz */ }; -#endif /* __ASM_MACH_LOONGSON1_CPUFREQ_H */ +#endif /* __ASM_MACH_LOONGSON32_CPUFREQ_H */ diff --git a/arch/mips/include/asm/mach-loongson1/irq.h b/arch/mips/include/asm/mach-loongson32/irq.h index 96bfb1c..0d35b99 100644 --- a/arch/mips/include/asm/mach-loongson1/irq.h +++ b/arch/mips/include/asm/mach-loongson32/irq.h @@ -10,8 +10,8 @@ */ -#ifndef __ASM_MACH_LOONGSON1_IRQ_H -#define __ASM_MACH_LOONGSON1_IRQ_H +#ifndef __ASM_MACH_LOONGSON32_IRQ_H +#define __ASM_MACH_LOONGSON32_IRQ_H /* * CPU core Interrupt Numbers @@ -70,4 +70,4 @@ #define NR_IRQS (MIPS_CPU_IRQS + LS1X_IRQS) -#endif /* __ASM_MACH_LOONGSON1_IRQ_H */ +#endif /* __ASM_MACH_LOONGSON32_IRQ_H */ diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index 20e0c2b..12aa129 100644 --- a/arch/mips/include/asm/mach-loongson1/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -10,8 +10,8 @@ */ -#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H -#define __ASM_MACH_LOONGSON1_LOONGSON1_H +#ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H +#define __ASM_MACH_LOONGSON32_LOONGSON1_H #define DEFAULT_MEMSIZE 256 /* If no memsize provided */ @@ -47,4 +47,4 @@ #include <regs-pwm.h> #include <regs-wdt.h> -#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */ +#endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */ diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson32/platform.h index 47de55e..c32f03f 100644 --- a/arch/mips/include/asm/mach-loongson1/platform.h +++ b/arch/mips/include/asm/mach-loongson32/platform.h @@ -8,8 +8,8 @@ */ -#ifndef __ASM_MACH_LOONGSON1_PLATFORM_H -#define __ASM_MACH_LOONGSON1_PLATFORM_H +#ifndef __ASM_MACH_LOONGSON32_PLATFORM_H +#define __ASM_MACH_LOONGSON32_PLATFORM_H #include <linux/platform_device.h> @@ -23,4 +23,4 @@ extern struct platform_device ls1x_rtc_pdev; extern void __init ls1x_clk_init(void); extern void __init ls1x_serial_setup(struct platform_device *pdev); -#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */ +#endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */ diff --git a/arch/mips/include/asm/mach-loongson1/prom.h b/arch/mips/include/asm/mach-loongson32/prom.h index 34859a4..a08503c 100644 --- a/arch/mips/include/asm/mach-loongson1/prom.h +++ b/arch/mips/include/asm/mach-loongson32/prom.h @@ -7,8 +7,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON1_PROM_H -#define __ASM_MACH_LOONGSON1_PROM_H +#ifndef __ASM_MACH_LOONGSON32_PROM_H +#define __ASM_MACH_LOONGSON32_PROM_H #include <linux/io.h> #include <linux/init.h> @@ -21,4 +21,4 @@ extern unsigned long memsize, highmemsize; extern char *prom_getenv(char *name); extern void __init prom_init_cmdline(void); -#endif /* __ASM_MACH_LOONGSON1_PROM_H */ +#endif /* __ASM_MACH_LOONGSON32_PROM_H */ diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson32/regs-clk.h index ee2445b..1f5a715 100644 --- a/arch/mips/include/asm/mach-loongson1/regs-clk.h +++ b/arch/mips/include/asm/mach-loongson32/regs-clk.h @@ -9,8 +9,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H -#define __ASM_MACH_LOONGSON1_REGS_CLK_H +#ifndef __ASM_MACH_LOONGSON32_REGS_CLK_H +#define __ASM_MACH_LOONGSON32_REGS_CLK_H #define LS1X_CLK_REG(x) \ ((void __iomem *)KSEG1ADDR(LS1X_CLK_BASE + (x))) @@ -48,4 +48,4 @@ #define BYPASS_DDR_WIDTH 1 #define BYPASS_CPU_WIDTH 1 -#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */ +#endif /* __ASM_MACH_LOONGSON32_REGS_CLK_H */ diff --git a/arch/mips/include/asm/mach-loongson1/regs-mux.h b/arch/mips/include/asm/mach-loongson32/regs-mux.h index fb1e36e..8302d92 100644 --- a/arch/mips/include/asm/mach-loongson1/regs-mux.h +++ b/arch/mips/include/asm/mach-loongson32/regs-mux.h @@ -9,8 +9,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON1_REGS_MUX_H -#define __ASM_MACH_LOONGSON1_REGS_MUX_H +#ifndef __ASM_MACH_LOONGSON32_REGS_MUX_H +#define __ASM_MACH_LOONGSON32_REGS_MUX_H #define LS1X_MUX_REG(x) \ ((void __iomem *)KSEG1ADDR(LS1X_MUX_BASE + (x))) @@ -64,4 +64,4 @@ #define GMAC1_USE_PWM23 (0x1 << 1) #define GMAC0_USE_PWM01 0x1 -#endif /* __ASM_MACH_LOONGSON1_REGS_MUX_H */ +#endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */ diff --git a/arch/mips/include/asm/mach-loongson1/regs-pwm.h b/arch/mips/include/asm/mach-loongson32/regs-pwm.h index 99f2bcc..69f174e 100644 --- a/arch/mips/include/asm/mach-loongson1/regs-pwm.h +++ b/arch/mips/include/asm/mach-loongson32/regs-pwm.h @@ -9,8 +9,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON1_REGS_PWM_H -#define __ASM_MACH_LOONGSON1_REGS_PWM_H +#ifndef __ASM_MACH_LOONGSON32_REGS_PWM_H +#define __ASM_MACH_LOONGSON32_REGS_PWM_H /* Loongson 1 PWM Timer Register Definitions */ #define PWM_CNT 0x0 @@ -26,4 +26,4 @@ #define PWM_OE (0x1 << 3) #define CNT_EN 0x1 -#endif /* __ASM_MACH_LOONGSON1_REGS_PWM_H */ +#endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */ diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/arch/mips/include/asm/mach-loongson32/regs-wdt.h index c39ee98..6644ab6 100644 --- a/arch/mips/include/asm/mach-loongson1/regs-wdt.h +++ b/arch/mips/include/asm/mach-loongson32/regs-wdt.h @@ -9,11 +9,11 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H -#define __ASM_MACH_LOONGSON1_REGS_WDT_H +#ifndef __ASM_MACH_LOONGSON32_REGS_WDT_H +#define __ASM_MACH_LOONGSON32_REGS_WDT_H #define WDT_EN 0x0 #define WDT_TIMER 0x4 #define WDT_SET 0x8 -#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */ +#endif /* __ASM_MACH_LOONGSON32_REGS_WDT_H */ diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h index fa80292..d3f3258 100644 --- a/arch/mips/include/asm/mach-loongson/boot_param.h +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_ -#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_ +#ifndef __ASM_MACH_LOONGSON64_BOOT_PARAM_H_ +#define __ASM_MACH_LOONGSON64_BOOT_PARAM_H_ #define SYSTEM_RAM_LOW 1 #define SYSTEM_RAM_HIGH 2 diff --git a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h index acc3768..98963c2 100644 --- a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h @@ -13,8 +13,8 @@ * loongson2f user manual. */ -#ifndef __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H -#define __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H +#ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H #define cpu_dcache_line_size() 32 #define cpu_icache_line_size() 32 @@ -58,4 +58,4 @@ #define cpu_has_wsbh IS_ENABLED(CONFIG_CPU_LOONGSON3) -#endif /* __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H */ +#endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536.h index a0ee0cb..a0ee0cb 100644 --- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h +++ b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536.h diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_mfgpt.h index 021d017..021d017 100644 --- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h +++ b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_mfgpt.h diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_pci.h index 8a7ecb4..8a7ecb4 100644 --- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h +++ b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_pci.h diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_vsm.h index 1f17c18..1f17c18 100644 --- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h +++ b/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_vsm.h diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson64/dma-coherence.h index 4bf4e19..1602a9e 100644 --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h +++ b/arch/mips/include/asm/mach-loongson64/dma-coherence.h @@ -8,8 +8,8 @@ * Author: Fuxin Zhang, zhangfx@lemote.com * */ -#ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H -#define __ASM_MACH_LOONGSON_DMA_COHERENCE_H +#ifndef __ASM_MACH_LOONGSON64_DMA_COHERENCE_H +#define __ASM_MACH_LOONGSON64_DMA_COHERENCE_H #ifdef CONFIG_SWIOTLB #include <linux/swiotlb.h> @@ -82,4 +82,4 @@ static inline void plat_post_dma_flush(struct device *dev) { } -#endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */ +#endif /* __ASM_MACH_LOONGSON64_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-loongson/gpio.h b/arch/mips/include/asm/mach-loongson64/gpio.h index b3b2169..b3b2169 100644 --- a/arch/mips/include/asm/mach-loongson/gpio.h +++ b/arch/mips/include/asm/mach-loongson64/gpio.h diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson64/irq.h index a281cca..d18c45c 100644 --- a/arch/mips/include/asm/mach-loongson/irq.h +++ b/arch/mips/include/asm/mach-loongson64/irq.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_LOONGSON_IRQ_H_ -#define __ASM_MACH_LOONGSON_IRQ_H_ +#ifndef __ASM_MACH_LOONGSON64_IRQ_H_ +#define __ASM_MACH_LOONGSON64_IRQ_H_ #include <boot_param.h> @@ -40,4 +40,4 @@ extern void fixup_irqs(void); extern void loongson3_ipi_interrupt(struct pt_regs *regs); #include_next <irq.h> -#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */ +#endif /* __ASM_MACH_LOONGSON64_IRQ_H_ */ diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index df5fca8..3f2f84f 100644 --- a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -8,8 +8,8 @@ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn) * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com) */ -#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H -#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H +#ifndef __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H +#define __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H /* * Override macros used in arch/mips/kernel/head.S. @@ -49,4 +49,4 @@ #endif .endm -#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */ +#endif /* __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H */ diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h index 9783103..d1ff774 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson64/loongson.h @@ -8,8 +8,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON_LOONGSON_H -#define __ASM_MACH_LOONGSON_LOONGSON_H +#ifndef __ASM_MACH_LOONGSON64_LOONGSON_H +#define __ASM_MACH_LOONGSON64_LOONGSON_H #include <linux/io.h> #include <linux/init.h> @@ -357,4 +357,4 @@ extern unsigned long _loongson_addrwincfg_base; #endif /* ! CONFIG_CPU_SUPPORTS_ADDRWINCFG */ -#endif /* __ASM_MACH_LOONGSON_LOONGSON_H */ +#endif /* __ASM_MACH_LOONGSON64_LOONGSON_H */ diff --git a/arch/mips/include/asm/mach-loongson/loongson_hwmon.h b/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h index 4431fc5..4431fc5 100644 --- a/arch/mips/include/asm/mach-loongson/loongson_hwmon.h +++ b/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson64/machine.h index cb2b602..c52549b 100644 --- a/arch/mips/include/asm/mach-loongson/machine.h +++ b/arch/mips/include/asm/mach-loongson64/machine.h @@ -8,8 +8,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON_MACHINE_H -#define __ASM_MACH_LOONGSON_MACHINE_H +#ifndef __ASM_MACH_LOONGSON64_MACHINE_H +#define __ASM_MACH_LOONGSON64_MACHINE_H #ifdef CONFIG_LEMOTE_FULOONG2E @@ -30,4 +30,4 @@ #endif /* CONFIG_LOONGSON_MACH3X */ -#endif /* __ASM_MACH_LOONGSON_MACHINE_H */ +#endif /* __ASM_MACH_LOONGSON64_MACHINE_H */ diff --git a/arch/mips/include/asm/mach-loongson/mc146818rtc.h b/arch/mips/include/asm/mach-loongson64/mc146818rtc.h index ed7fe97..ebdccfe 100644 --- a/arch/mips/include/asm/mach-loongson/mc146818rtc.h +++ b/arch/mips/include/asm/mach-loongson64/mc146818rtc.h @@ -7,8 +7,8 @@ * * RTC routines for PC style attached Dallas chip. */ -#ifndef __ASM_MACH_LOONGSON_MC146818RTC_H -#define __ASM_MACH_LOONGSON_MC146818RTC_H +#ifndef __ASM_MACH_LOONGSON64_MC146818RTC_H +#define __ASM_MACH_LOONGSON64_MC146818RTC_H #include <linux/io.h> @@ -33,4 +33,4 @@ static inline void CMOS_WRITE(unsigned char data, unsigned long addr) #define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970) #endif -#endif /* __ASM_MACH_LOONGSON_MC146818RTC_H */ +#endif /* __ASM_MACH_LOONGSON64_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-loongson/mem.h b/arch/mips/include/asm/mach-loongson64/mem.h index f4a36d7..75c16be 100644 --- a/arch/mips/include/asm/mach-loongson/mem.h +++ b/arch/mips/include/asm/mach-loongson64/mem.h @@ -8,8 +8,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON_MEM_H -#define __ASM_MACH_LOONGSON_MEM_H +#ifndef __ASM_MACH_LOONGSON64_MEM_H +#define __ASM_MACH_LOONGSON64_MEM_H /* * high memory space @@ -38,4 +38,4 @@ #define LOONGSON_MMIO_MEM_END 0x80000000 #endif -#endif /* __ASM_MACH_LOONGSON_MEM_H */ +#endif /* __ASM_MACH_LOONGSON64_MEM_H */ diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson64/mmzone.h index 37c08a2..37c08a2 100644 --- a/arch/mips/include/asm/mach-loongson/mmzone.h +++ b/arch/mips/include/asm/mach-loongson64/mmzone.h diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h index 1212774..3401f55 100644 --- a/arch/mips/include/asm/mach-loongson/pci.h +++ b/arch/mips/include/asm/mach-loongson64/pci.h @@ -9,8 +9,8 @@ * option) any later version. */ -#ifndef __ASM_MACH_LOONGSON_PCI_H_ -#define __ASM_MACH_LOONGSON_PCI_H_ +#ifndef __ASM_MACH_LOONGSON64_PCI_H_ +#define __ASM_MACH_LOONGSON64_PCI_H_ extern struct pci_ops loongson_pci_ops; @@ -52,4 +52,4 @@ extern struct pci_ops loongson_pci_ops; #endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */ -#endif /* !__ASM_MACH_LOONGSON_PCI_H_ */ +#endif /* !__ASM_MACH_LOONGSON64_PCI_H_ */ diff --git a/arch/mips/include/asm/mach-loongson/spaces.h b/arch/mips/include/asm/mach-loongson64/spaces.h index e2506ee..c6040b9 100644 --- a/arch/mips/include/asm/mach-loongson/spaces.h +++ b/arch/mips/include/asm/mach-loongson64/spaces.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_LOONGSON_SPACES_H_ -#define __ASM_MACH_LOONGSON_SPACES_H_ +#ifndef __ASM_MACH_LOONGSON64_SPACES_H_ +#define __ASM_MACH_LOONGSON64_SPACES_H_ #if defined(CONFIG_64BIT) #define CAC_BASE _AC(0x9800000000000000, UL) diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson64/topology.h index 0d8f3b5..0d8f3b5 100644 --- a/arch/mips/include/asm/mach-loongson/topology.h +++ b/arch/mips/include/asm/mach-loongson64/topology.h diff --git a/arch/mips/include/asm/mach-loongson64/workarounds.h b/arch/mips/include/asm/mach-loongson64/workarounds.h new file mode 100644 index 0000000..e659f04 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson64/workarounds.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_LOONGSON64_WORKAROUNDS_H_ +#define __ASM_MACH_LOONGSON64_WORKAROUNDS_H_ + +#define WORKAROUND_CPUFREQ 0x00000001 +#define WORKAROUND_CPUHOTPLUG 0x00000002 + +#endif diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 59c0901..edc7ee9 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -11,6 +11,7 @@ #ifndef __MIPS_ASM_MIPS_CM_H__ #define __MIPS_ASM_MIPS_CM_H__ +#include <linux/errno.h> #include <linux/io.h> #include <linux/types.h> @@ -216,6 +217,10 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_CPC_BASE_CPCEN_SHF 0 #define CM_GCR_CPC_BASE_CPCEN_MSK (_ULCAST_(0x1) << 0) +/* GCR_GIC_STATUS register fields */ +#define CM_GCR_GIC_STATUS_GICEX_SHF 0 +#define CM_GCR_GIC_STATUS_GICEX_MSK (_ULCAST_(0x1) << 0) + /* GCR_REGn_BASE register fields */ #define CM_GCR_REGn_BASE_BASEADDR_SHF 16 #define CM_GCR_REGn_BASE_BASEADDR_MSK (_ULCAST_(0xffff) << 16) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 764e275..c5b0956 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -589,6 +589,28 @@ /* EntryHI bit definition */ #define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10) +/* R3000 EntryLo bit definitions */ +#define R3K_ENTRYLO_G (_ULCAST_(1) << 8) +#define R3K_ENTRYLO_V (_ULCAST_(1) << 9) +#define R3K_ENTRYLO_D (_ULCAST_(1) << 10) +#define R3K_ENTRYLO_N (_ULCAST_(1) << 11) + +/* R4000 compatible EntryLo bit definitions */ +#define MIPS_ENTRYLO_G (_ULCAST_(1) << 0) +#define MIPS_ENTRYLO_V (_ULCAST_(1) << 1) +#define MIPS_ENTRYLO_D (_ULCAST_(1) << 2) +#define MIPS_ENTRYLO_C_SHIFT 3 +#define MIPS_ENTRYLO_C (_ULCAST_(7) << MIPS_ENTRYLO_C_SHIFT) +#ifdef CONFIG_64BIT +/* as read by dmfc0 */ +#define MIPS_ENTRYLO_XI (_ULCAST_(1) << 62) +#define MIPS_ENTRYLO_RI (_ULCAST_(1) << 63) +#else +/* as read by mfc0 */ +#define MIPS_ENTRYLO_XI (_ULCAST_(1) << 30) +#define MIPS_ENTRYLO_RI (_ULCAST_(1) << 31) +#endif + /* CMGCRBase bit definitions */ #define MIPS_CMGCRB_BASE 11 #define MIPS_CMGCRF_BASE (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1)) @@ -685,6 +707,15 @@ #define TX39_CONF_DRSIZE_SHIFT 0 #define TX39_CONF_DRSIZE_MASK 0x00000003 +/* + * Interesting Bits in the R10K CP0 Branch Diagnostic Register + */ +/* Disable Branch Target Address Cache */ +#define R10K_DIAG_D_BTAC (_ULCAST_(1) << 27) +/* Enable Branch Prediction Global History */ +#define R10K_DIAG_E_GHIST (_ULCAST_(1) << 26) +/* Disable Branch Return Cache */ +#define R10K_DIAG_D_BRC (_ULCAST_(1) << 22) /* * Coprocessor 1 (FPU) register names @@ -1247,6 +1278,10 @@ do { \ #define read_c0_diag() __read_32bit_c0_register($22, 0) #define write_c0_diag(val) __write_32bit_c0_register($22, 0, val) +/* R10K CP0 Branch Diagnostic register is 64bits wide */ +#define read_c0_r10k_diag() __read_64bit_c0_register($22, 0) +#define write_c0_r10k_diag(val) __write_64bit_c0_register($22, 0, val) + #define read_c0_diag1() __read_32bit_c0_register($22, 1) #define write_c0_diag1(val) __write_32bit_c0_register($22, 1, val) diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index 7d56686..832e216 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -18,7 +18,7 @@ #include <asm-generic/pgtable-nopmd.h> -extern int temp_tlb_entry __cpuinitdata; +extern int temp_tlb_entry; /* * - add_temporary_entry() add a temporary TLB entry. We use TLB entries diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index 8ebc2aa..0b4b668 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h @@ -11,7 +11,7 @@ #ifndef __ASM_PROM_H #define __ASM_PROM_H -#ifdef CONFIG_OF +#ifdef CONFIG_USE_OF #include <linux/bug.h> #include <linux/io.h> #include <linux/types.h> diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index 1fca2e0..9de4ba4 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h @@ -109,7 +109,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) " subu %[ticket], %[my_ticket], %[ticket] \n" "2: \n" " .subsection 2 \n" - "4: andi %[ticket], %[ticket], 0x1fff \n" + "4: andi %[ticket], %[ticket], 0xffff \n" " sll %[ticket], 5 \n" " \n" "6: bnez %[ticket], 6b \n" @@ -317,7 +317,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw) static inline void arch_write_unlock(arch_rwlock_t *rw) { - smp_mb(); + smp_mb__before_llsc(); __asm__ __volatile__( " # arch_write_unlock \n" diff --git a/arch/mips/include/asm/txx9irq.h b/arch/mips/include/asm/txx9irq.h index 5620879..68a6650 100644 --- a/arch/mips/include/asm/txx9irq.h +++ b/arch/mips/include/asm/txx9irq.h @@ -11,7 +11,7 @@ #include <irq.h> -#ifdef CONFIG_IRQ_CPU +#ifdef CONFIG_IRQ_MIPS_CPU #define TXX9_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) #else #ifdef CONFIG_I8259 diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index 9722357..5305d69 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -78,6 +78,21 @@ extern u64 __ua_limit; #define segment_eq(a, b) ((a).seg == (b).seg) +/* + * eva_kernel_access() - determine whether kernel memory access on an EVA system + * + * Determines whether memory accesses should be performed to kernel memory + * on a system using Extended Virtual Addressing (EVA). + * + * Return: true if a kernel memory access on an EVA system, else false. + */ +static inline bool eva_kernel_access(void) +{ + if (!config_enabled(CONFIG_EVA)) + return false; + + return segment_eq(get_fs(), get_ds()); +} /* * Is a address valid? This does a straighforward calculation rather @@ -286,7 +301,7 @@ do { \ ({ \ int __gu_err; \ \ - if (segment_eq(get_fs(), get_ds())) { \ + if (eva_kernel_access()) { \ __get_kernel_common((x), size, ptr); \ } else { \ __chk_user_ptr(ptr); \ @@ -302,7 +317,7 @@ do { \ \ might_fault(); \ if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) { \ - if (segment_eq(get_fs(), get_ds())) \ + if (eva_kernel_access()) \ __get_kernel_common((x), size, __gu_ptr); \ else \ __get_user_common((x), size, __gu_ptr); \ @@ -427,7 +442,7 @@ do { \ int __pu_err = 0; \ \ __pu_val = (x); \ - if (segment_eq(get_fs(), get_ds())) { \ + if (eva_kernel_access()) { \ __put_kernel_common(ptr, size); \ } else { \ __chk_user_ptr(ptr); \ @@ -444,7 +459,7 @@ do { \ \ might_fault(); \ if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \ - if (segment_eq(get_fs(), get_ds())) \ + if (eva_kernel_access()) \ __put_kernel_common(__pu_addr, size); \ else \ __put_user_common(__pu_addr, size); \ @@ -843,7 +858,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n); __cu_from = (from); \ __cu_len = (n); \ might_fault(); \ - if (segment_eq(get_fs(), get_ds())) \ + if (eva_kernel_access()) \ __cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \ __cu_len); \ else \ @@ -863,7 +878,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); __cu_to = (to); \ __cu_from = (from); \ __cu_len = (n); \ - if (segment_eq(get_fs(), get_ds())) \ + if (eva_kernel_access()) \ __cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \ __cu_len); \ else \ @@ -881,7 +896,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); __cu_to = (to); \ __cu_from = (from); \ __cu_len = (n); \ - if (segment_eq(get_fs(), get_ds())) \ + if (eva_kernel_access()) \ __cu_len = __invoke_copy_from_kernel_inatomic(__cu_to, \ __cu_from,\ __cu_len);\ @@ -915,7 +930,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); __cu_to = (to); \ __cu_from = (from); \ __cu_len = (n); \ - if (segment_eq(get_fs(), get_ds())) { \ + if (eva_kernel_access()) { \ __cu_len = __invoke_copy_to_kernel(__cu_to, \ __cu_from, \ __cu_len); \ @@ -1139,7 +1154,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n); __cu_to = (to); \ __cu_from = (from); \ __cu_len = (n); \ - if (segment_eq(get_fs(), get_ds())) { \ + if (eva_kernel_access()) { \ __cu_len = __invoke_copy_from_kernel(__cu_to, \ __cu_from, \ __cu_len); \ @@ -1163,7 +1178,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n); __cu_to = (to); \ __cu_from = (from); \ __cu_len = (n); \ - if (segment_eq(get_fs(), get_ds())) { \ + if (eva_kernel_access()) { \ __cu_len = ___invoke_copy_in_kernel(__cu_to, __cu_from, \ __cu_len); \ } else { \ @@ -1183,7 +1198,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n); __cu_to = (to); \ __cu_from = (from); \ __cu_len = (n); \ - if (segment_eq(get_fs(), get_ds())) { \ + if (eva_kernel_access()) { \ __cu_len = ___invoke_copy_in_kernel(__cu_to,__cu_from, \ __cu_len); \ } else { \ @@ -1263,7 +1278,7 @@ __strncpy_from_user(char *__to, const char __user *__from, long __len) { long res; - if (segment_eq(get_fs(), get_ds())) { + if (eva_kernel_access()) { __asm__ __volatile__( "move\t$4, %1\n\t" "move\t$5, %2\n\t" @@ -1312,7 +1327,7 @@ strncpy_from_user(char *__to, const char __user *__from, long __len) { long res; - if (segment_eq(get_fs(), get_ds())) { + if (eva_kernel_access()) { __asm__ __volatile__( "move\t$4, %1\n\t" "move\t$5, %2\n\t" @@ -1357,7 +1372,7 @@ static inline long strlen_user(const char __user *s) { long res; - if (segment_eq(get_fs(), get_ds())) { + if (eva_kernel_access()) { __asm__ __volatile__( "move\t$4, %1\n\t" __MODULE_JAL(__strlen_kernel_asm) @@ -1384,7 +1399,7 @@ static inline long __strnlen_user(const char __user *s, long n) { long res; - if (segment_eq(get_fs(), get_ds())) { + if (eva_kernel_access()) { __asm__ __volatile__( "move\t$4, %1\n\t" "move\t$5, %2\n\t" @@ -1426,7 +1441,7 @@ static inline long strnlen_user(const char __user *s, long n) long res; might_fault(); - if (segment_eq(get_fs(), get_ds())) { + if (eva_kernel_access()) { __asm__ __volatile__( "move\t$4, %1\n\t" "move\t$5, %2\n\t" diff --git a/arch/mips/include/asm/xtalk/xwidget.h b/arch/mips/include/asm/xtalk/xwidget.h index 32e4e88..24f121d 100644 --- a/arch/mips/include/asm/xtalk/xwidget.h +++ b/arch/mips/include/asm/xtalk/xwidget.h @@ -84,6 +84,118 @@ #define WIDGET_LLP_MAXBURST 0x000003ff #define WIDGET_LLP_MAXBURST_SHFT 0 +/* Xtalk Widget Device Mfgr Nums */ +#define WIDGET_XBOW_MFGR_NUM 0x0 /* IP30 XBow Chip */ +#define WIDGET_XXBOW_MFGR_NUM 0x0 /* IP35 Xbow + XBridge Chip */ +#define WIDGET_ODYS_MFGR_NUM 0x023 /* Odyssey / VPro GFX */ +#define WIDGET_TPU_MFGR_NUM 0x024 /* Tensor Processor Unit */ +#define WIDGET_XBRDG_MFGR_NUM 0x024 /* IP35 XBridge Chip */ +#define WIDGET_HEART_MFGR_NUM 0x036 /* IP30 HEART Chip */ +#define WIDGET_BRIDG_MFGR_NUM 0x036 /* PCI Bridge */ +#define WIDGET_HUB_MFGR_NUM 0x036 /* IP27 Hub Chip */ +#define WIDGET_BDRCK_MFGR_NUM 0x036 /* IP35 Bedrock Chip */ +#define WIDGET_IMPCT_MFGR_NUM 0x2aa /* HQ4 / Impact GFX */ +#define WIDGET_KONA_MFGR_NUM 0x2aa /* InfiniteReality3 / Kona GFX */ +#define WIDGET_NULL_MFGR_NUM -1 /* NULL */ + +/* Xtalk Widget Device Part Nums */ +#define WIDGET_XBOW_PART_NUM 0x0000 +#define WIDGET_HEART_PART_NUM 0xc001 +#define WIDGET_BRIDG_PART_NUM 0xc002 +#define WIDGET_IMPCT_PART_NUM 0xc003 +#define WIDGET_ODYS_PART_NUM 0xc013 +#define WIDGET_HUB_PART_NUM 0xc101 +#define WIDGET_KONA_PART_NUM 0xc102 +#define WIDGET_BDRCK_PART_NUM 0xc110 +#define WIDGET_TPU_PART_NUM 0xc202 +#define WIDGET_XXBOW_PART_NUM 0xd000 +#define WIDGET_XBRDG_PART_NUM 0xd002 +#define WIDGET_NULL_PART_NUM -1 + +/* For Xtalk Widget identification */ +struct widget_ident { + u32 mfgr; + u32 part; + char *name; + char *revs[16]; +}; + +/* Known Xtalk Widgets */ +static const struct widget_ident __initconst widget_idents[] = { + { + WIDGET_XBOW_MFGR_NUM, + WIDGET_XBOW_PART_NUM, + "xbow", + {NULL, "1.0", "1.1", "1.2", "1.3", "2.0", NULL}, + }, + { + WIDGET_HEART_MFGR_NUM, + WIDGET_HEART_PART_NUM, + "heart", + {NULL, "A", "B", "C", "D", "E", "F", NULL}, + }, + { + WIDGET_BRIDG_MFGR_NUM, + WIDGET_BRIDG_PART_NUM, + "bridge", + {NULL, "A", "B", "C", "D", NULL}, + }, + { + WIDGET_IMPCT_MFGR_NUM, + WIDGET_IMPCT_PART_NUM, + "impact", + {NULL, "A", "B", NULL}, + }, + { + WIDGET_ODYS_MFGR_NUM, + WIDGET_ODYS_PART_NUM, + "odyssey", + {NULL, "A", "B", NULL}, + }, + { + WIDGET_HUB_MFGR_NUM, + WIDGET_HUB_PART_NUM, + "hub", + {NULL, "1.0", "2.0", "2.1", "2.2", "2.3", "2.4", NULL}, + }, + { + WIDGET_KONA_MFGR_NUM, + WIDGET_KONA_PART_NUM, + "kona", + {NULL}, + }, + { + WIDGET_BDRCK_MFGR_NUM, + WIDGET_BDRCK_PART_NUM, + "bedrock", + {NULL, "1.0", "1.1", NULL}, + }, + { + WIDGET_TPU_MFGR_NUM, + WIDGET_TPU_PART_NUM, + "tpu", + {"0", NULL}, + }, + { + WIDGET_XXBOW_MFGR_NUM, + WIDGET_XXBOW_PART_NUM, + "xxbow", + {NULL, "1.0", "2.0", NULL}, + }, + { + WIDGET_XBRDG_MFGR_NUM, + WIDGET_XBRDG_PART_NUM, + "xbridge", + {NULL, "A", "B", NULL}, + }, + { + WIDGET_NULL_MFGR_NUM, + WIDGET_NULL_PART_NUM, + NULL, + {NULL}, + } +}; + /* * according to the crosstalk spec, only 32-bits access to the widget * configuration registers is allowed. some widgets may allow 64-bits diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig index 4689030..36f8201 100644 --- a/arch/mips/jz4740/Kconfig +++ b/arch/mips/jz4740/Kconfig @@ -1,9 +1,24 @@ choice prompt "Machine type" - depends on MACH_JZ4740 + depends on MACH_INGENIC default JZ4740_QI_LB60 config JZ4740_QI_LB60 bool "Qi Hardware Ben NanoNote" + select MACH_JZ4740 + +config JZ4780_CI20 + bool "MIPS Creator CI20" + select MACH_JZ4780 endchoice + +config MACH_JZ4740 + bool + select SYS_HAS_CPU_MIPS32_R1 + +config MACH_JZ4780 + bool + select MIPS_CPU_SCACHE + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_HIGHMEM diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index 28e5535..39d70bd 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile @@ -4,10 +4,12 @@ # Object file lists. -obj-y += prom.o irq.o time.o reset.o setup.o \ - gpio.o clock.o platform.o timer.o serial.o +obj-y += prom.o time.o reset.o setup.o \ + platform.o timer.o -obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o +obj-$(CONFIG_MACH_JZ4740) += gpio.o + +CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt # board specific support diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform index c41d300..28448d35 100644 --- a/arch/mips/jz4740/Platform +++ b/arch/mips/jz4740/Platform @@ -1,4 +1,4 @@ -platform-$(CONFIG_MACH_JZ4740) += jz4740/ -cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 -load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 -zload-$(CONFIG_MACH_JZ4740) += 0xffffffff80600000 +platform-$(CONFIG_MACH_INGENIC) += jz4740/ +cflags-$(CONFIG_MACH_INGENIC) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 +load-$(CONFIG_MACH_INGENIC) += 0xffffffff80010000 +zload-$(CONFIG_MACH_INGENIC) += 0xffffffff80600000 diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 9dd051e..4e62bf8 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -482,8 +482,6 @@ static int __init qi_lb60_init_platform_devices(void) gpiod_add_lookup_table(&qi_lb60_audio_gpio_table); gpiod_add_lookup_table(&qi_lb60_nand_gpio_table); - jz4740_serial_device_register(); - spi_register_board_info(qi_lb60_spi_board_info, ARRAY_SIZE(qi_lb60_spi_board_info)); @@ -497,11 +495,6 @@ static int __init qi_lb60_init_platform_devices(void) } -struct jz4740_clock_board_data jz4740_clock_bdata = { - .ext_rate = 12000000, - .rtc_rate = 32768, -}; - static __init int board_avt2(char *str) { qi_lb60_mmc_pdata.card_detect_active_low = 1; diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c deleted file mode 100644 index 325422d0..0000000 --- a/arch/mips/jz4740/clock-debugfs.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 SoC clock support debugfs entries - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/clk.h> -#include <linux/err.h> - -#include <linux/debugfs.h> -#include <linux/uaccess.h> - -#include <asm/mach-jz4740/clock.h> -#include "clock.h" - -static struct dentry *jz4740_clock_debugfs; - -static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value) -{ - struct clk *clk = data; - *value = clk_is_enabled(clk); - - return 0; -} - -static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value) -{ - struct clk *clk = data; - - if (value) - return clk_enable(clk); - else - clk_disable(clk); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled, - jz4740_clock_debugfs_show_enabled, - jz4740_clock_debugfs_set_enabled, - "%llu\n"); - -static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value) -{ - struct clk *clk = data; - *value = clk_get_rate(clk); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate, - jz4740_clock_debugfs_show_rate, - NULL, - "%llu\n"); - -void jz4740_clock_debugfs_add_clk(struct clk *clk) -{ - if (!jz4740_clock_debugfs) - return; - - clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs); - debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk, - &jz4740_clock_debugfs_ops_rate); - debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk, - &jz4740_clock_debugfs_ops_enabled); - - if (clk->parent) { - char parent_path[100]; - snprintf(parent_path, 100, "../%s", clk->parent->name); - clk->debugfs_parent_entry = debugfs_create_symlink("parent", - clk->debugfs_entry, - parent_path); - } -} - -/* TODO: Locking */ -void jz4740_clock_debugfs_update_parent(struct clk *clk) -{ - debugfs_remove(clk->debugfs_parent_entry); - - if (clk->parent) { - char parent_path[100]; - snprintf(parent_path, 100, "../%s", clk->parent->name); - clk->debugfs_parent_entry = debugfs_create_symlink("parent", - clk->debugfs_entry, - parent_path); - } else { - clk->debugfs_parent_entry = NULL; - } -} - -void jz4740_clock_debugfs_init(void) -{ - jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL); - if (IS_ERR(jz4740_clock_debugfs)) - jz4740_clock_debugfs = NULL; -} diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c deleted file mode 100644 index 1b5f554..0000000 --- a/arch/mips/jz4740/clock.c +++ /dev/null @@ -1,924 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 SoC clock support - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/clk.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/err.h> - -#include <asm/mach-jz4740/clock.h> -#include <asm/mach-jz4740/base.h> - -#include "clock.h" - -#define JZ_REG_CLOCK_CTRL 0x00 -#define JZ_REG_CLOCK_LOW_POWER 0x04 -#define JZ_REG_CLOCK_PLL 0x10 -#define JZ_REG_CLOCK_GATE 0x20 -#define JZ_REG_CLOCK_SLEEP_CTRL 0x24 -#define JZ_REG_CLOCK_I2S 0x60 -#define JZ_REG_CLOCK_LCD 0x64 -#define JZ_REG_CLOCK_MMC 0x68 -#define JZ_REG_CLOCK_UHC 0x6C -#define JZ_REG_CLOCK_SPI 0x74 - -#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31) -#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30) -#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29) -#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000 -#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22) -#define JZ_CLOCK_CTRL_PLL_HALF BIT(21) -#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000 -#define JZ_CLOCK_CTRL_UDIV_OFFSET 23 -#define JZ_CLOCK_CTRL_LDIV_OFFSET 16 -#define JZ_CLOCK_CTRL_MDIV_OFFSET 12 -#define JZ_CLOCK_CTRL_PDIV_OFFSET 8 -#define JZ_CLOCK_CTRL_HDIV_OFFSET 4 -#define JZ_CLOCK_CTRL_CDIV_OFFSET 0 - -#define JZ_CLOCK_GATE_UART0 BIT(0) -#define JZ_CLOCK_GATE_TCU BIT(1) -#define JZ_CLOCK_GATE_RTC BIT(2) -#define JZ_CLOCK_GATE_I2C BIT(3) -#define JZ_CLOCK_GATE_SPI BIT(4) -#define JZ_CLOCK_GATE_AIC BIT(5) -#define JZ_CLOCK_GATE_I2S BIT(6) -#define JZ_CLOCK_GATE_MMC BIT(7) -#define JZ_CLOCK_GATE_ADC BIT(8) -#define JZ_CLOCK_GATE_CIM BIT(9) -#define JZ_CLOCK_GATE_LCD BIT(10) -#define JZ_CLOCK_GATE_UDC BIT(11) -#define JZ_CLOCK_GATE_DMAC BIT(12) -#define JZ_CLOCK_GATE_IPU BIT(13) -#define JZ_CLOCK_GATE_UHC BIT(14) -#define JZ_CLOCK_GATE_UART1 BIT(15) - -#define JZ_CLOCK_I2S_DIV_MASK 0x01ff - -#define JZ_CLOCK_LCD_DIV_MASK 0x01ff - -#define JZ_CLOCK_MMC_DIV_MASK 0x001f - -#define JZ_CLOCK_UHC_DIV_MASK 0x000f - -#define JZ_CLOCK_SPI_SRC_PLL BIT(31) -#define JZ_CLOCK_SPI_DIV_MASK 0x000f - -#define JZ_CLOCK_PLL_M_MASK 0x01ff -#define JZ_CLOCK_PLL_N_MASK 0x001f -#define JZ_CLOCK_PLL_OD_MASK 0x0003 -#define JZ_CLOCK_PLL_STABLE BIT(10) -#define JZ_CLOCK_PLL_BYPASS BIT(9) -#define JZ_CLOCK_PLL_ENABLED BIT(8) -#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f -#define JZ_CLOCK_PLL_M_OFFSET 23 -#define JZ_CLOCK_PLL_N_OFFSET 18 -#define JZ_CLOCK_PLL_OD_OFFSET 16 - -#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2) -#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0) - -#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7) -#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6) - -static void __iomem *jz_clock_base; -static spinlock_t jz_clock_lock; -static LIST_HEAD(jz_clocks); - -struct main_clk { - struct clk clk; - uint32_t div_offset; -}; - -struct divided_clk { - struct clk clk; - uint32_t reg; - uint32_t mask; -}; - -struct static_clk { - struct clk clk; - unsigned long rate; -}; - -static uint32_t jz_clk_reg_read(int reg) -{ - return readl(jz_clock_base + reg); -} - -static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask) -{ - uint32_t val2; - - spin_lock(&jz_clock_lock); - val2 = readl(jz_clock_base + reg); - val2 &= ~mask; - val2 |= val; - writel(val2, jz_clock_base + reg); - spin_unlock(&jz_clock_lock); -} - -static void jz_clk_reg_set_bits(int reg, uint32_t mask) -{ - uint32_t val; - - spin_lock(&jz_clock_lock); - val = readl(jz_clock_base + reg); - val |= mask; - writel(val, jz_clock_base + reg); - spin_unlock(&jz_clock_lock); -} - -static void jz_clk_reg_clear_bits(int reg, uint32_t mask) -{ - uint32_t val; - - spin_lock(&jz_clock_lock); - val = readl(jz_clock_base + reg); - val &= ~mask; - writel(val, jz_clock_base + reg); - spin_unlock(&jz_clock_lock); -} - -static int jz_clk_enable_gating(struct clk *clk) -{ - if (clk->gate_bit == JZ4740_CLK_NOT_GATED) - return -EINVAL; - - jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); - return 0; -} - -static int jz_clk_disable_gating(struct clk *clk) -{ - if (clk->gate_bit == JZ4740_CLK_NOT_GATED) - return -EINVAL; - - jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); - return 0; -} - -static int jz_clk_is_enabled_gating(struct clk *clk) -{ - if (clk->gate_bit == JZ4740_CLK_NOT_GATED) - return 1; - - return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit); -} - -static unsigned long jz_clk_static_get_rate(struct clk *clk) -{ - return ((struct static_clk *)clk)->rate; -} - -static int jz_clk_ko_enable(struct clk *clk) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); - return 0; -} - -static int jz_clk_ko_disable(struct clk *clk) -{ - jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); - return 0; -} - -static int jz_clk_ko_is_enabled(struct clk *clk) -{ - return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE); -} - -static const int pllno[] = {1, 2, 2, 4}; - -static unsigned long jz_clk_pll_get_rate(struct clk *clk) -{ - uint32_t val; - int m; - int n; - int od; - - val = jz_clk_reg_read(JZ_REG_CLOCK_PLL); - - if (val & JZ_CLOCK_PLL_BYPASS) - return clk_get_rate(clk->parent); - - m = ((val >> 23) & 0x1ff) + 2; - n = ((val >> 18) & 0x1f) + 2; - od = (val >> 16) & 0x3; - - return ((clk_get_rate(clk->parent) / n) * m) / pllno[od]; -} - -static unsigned long jz_clk_pll_half_get_rate(struct clk *clk) -{ - uint32_t reg; - - reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); - if (reg & JZ_CLOCK_CTRL_PLL_HALF) - return jz_clk_pll_get_rate(clk->parent); - return jz_clk_pll_get_rate(clk->parent) >> 1; -} - -static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; - -static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); - int div; - - div = parent_rate / rate; - if (div > 32) - return parent_rate / 32; - else if (div < 1) - return parent_rate; - - div &= (0x3 << (ffs(div) - 1)); - - return parent_rate / div; -} - -static unsigned long jz_clk_main_get_rate(struct clk *clk) -{ - struct main_clk *mclk = (struct main_clk *)clk; - uint32_t div; - - div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); - - div >>= mclk->div_offset; - div &= 0xf; - - if (div >= ARRAY_SIZE(jz_clk_main_divs)) - div = ARRAY_SIZE(jz_clk_main_divs) - 1; - - return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div]; -} - -static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate) -{ - struct main_clk *mclk = (struct main_clk *)clk; - int i; - int div; - unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent); - - rate = jz_clk_main_round_rate(clk, rate); - - div = parent_rate / rate; - - i = (ffs(div) - 1) << 1; - if (i > 0 && !(div & BIT(i-1))) - i -= 1; - - jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset, - 0xf << mclk->div_offset); - - return 0; -} - -static struct clk_ops jz_clk_static_ops = { - .get_rate = jz_clk_static_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct static_clk jz_clk_ext = { - .clk = { - .name = "ext", - .gate_bit = JZ4740_CLK_NOT_GATED, - .ops = &jz_clk_static_ops, - }, -}; - -static struct clk_ops jz_clk_pll_ops = { - .get_rate = jz_clk_pll_get_rate, -}; - -static struct clk jz_clk_pll = { - .name = "pll", - .parent = &jz_clk_ext.clk, - .ops = &jz_clk_pll_ops, -}; - -static struct clk_ops jz_clk_pll_half_ops = { - .get_rate = jz_clk_pll_half_get_rate, -}; - -static struct clk jz_clk_pll_half = { - .name = "pll half", - .parent = &jz_clk_pll, - .ops = &jz_clk_pll_half_ops, -}; - -static const struct clk_ops jz_clk_main_ops = { - .get_rate = jz_clk_main_get_rate, - .set_rate = jz_clk_main_set_rate, - .round_rate = jz_clk_main_round_rate, -}; - -static struct main_clk jz_clk_cpu = { - .clk = { - .name = "cclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET, -}; - -static struct main_clk jz_clk_memory = { - .clk = { - .name = "mclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET, -}; - -static struct main_clk jz_clk_high_speed_peripheral = { - .clk = { - .name = "hclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET, -}; - - -static struct main_clk jz_clk_low_speed_peripheral = { - .clk = { - .name = "pclk", - .parent = &jz_clk_pll, - .ops = &jz_clk_main_ops, - }, - .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET, -}; - -static const struct clk_ops jz_clk_ko_ops = { - .enable = jz_clk_ko_enable, - .disable = jz_clk_ko_disable, - .is_enabled = jz_clk_ko_is_enabled, -}; - -static struct clk jz_clk_ko = { - .name = "cko", - .parent = &jz_clk_memory.clk, - .ops = &jz_clk_ko_ops, -}; - -static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent) -{ - if (parent == &jz_clk_pll) - jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); - else if (parent == &jz_clk_ext.clk) - jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); - else - return -EINVAL; - - clk->parent = parent; - - return 0; -} - -static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent) -{ - if (parent == &jz_clk_pll_half) - jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); - else if (parent == &jz_clk_ext.clk) - jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); - else - return -EINVAL; - - clk->parent = parent; - - return 0; -} - -static int jz_clk_udc_enable(struct clk *clk) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL, - JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); - - return 0; -} - -static int jz_clk_udc_disable(struct clk *clk) -{ - jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL, - JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); - - return 0; -} - -static int jz_clk_udc_is_enabled(struct clk *clk) -{ - return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) & - JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); -} - -static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) -{ - if (parent == &jz_clk_pll_half) - jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); - else if (parent == &jz_clk_ext.clk) - jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); - else - return -EINVAL; - - clk->parent = parent; - - return 0; -} - -static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate) -{ - int div; - - if (clk->parent == &jz_clk_ext.clk) - return -EINVAL; - - div = clk_get_rate(clk->parent) / rate - 1; - - if (div < 0) - div = 0; - else if (div > 63) - div = 63; - - jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET, - JZ_CLOCK_CTRL_UDIV_MASK); - return 0; -} - -static unsigned long jz_clk_udc_get_rate(struct clk *clk) -{ - int div; - - if (clk->parent == &jz_clk_ext.clk) - return clk_get_rate(clk->parent); - - div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK); - div >>= JZ_CLOCK_CTRL_UDIV_OFFSET; - div += 1; - - return clk_get_rate(clk->parent) / div; -} - -static unsigned long jz_clk_divided_get_rate(struct clk *clk) -{ - struct divided_clk *dclk = (struct divided_clk *)clk; - int div; - - if (clk->parent == &jz_clk_ext.clk) - return clk_get_rate(clk->parent); - - div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1; - - return clk_get_rate(clk->parent) / div; -} - -static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate) -{ - struct divided_clk *dclk = (struct divided_clk *)clk; - int div; - - if (clk->parent == &jz_clk_ext.clk) - return -EINVAL; - - div = clk_get_rate(clk->parent) / rate - 1; - - if (div < 0) - div = 0; - else if (div > dclk->mask) - div = dclk->mask; - - jz_clk_reg_write_mask(dclk->reg, div, dclk->mask); - - return 0; -} - -static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate) -{ - int div; - unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent); - - if (rate > 150000000) - return 150000000; - - div = parent_rate / rate; - if (div < 1) - div = 1; - else if (div > 32) - div = 32; - - return parent_rate / div; -} - -static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate) -{ - int div; - - if (rate > 150000000) - return -EINVAL; - - div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1; - if (div < 0) - div = 0; - else if (div > 31) - div = 31; - - jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET, - JZ_CLOCK_CTRL_LDIV_MASK); - - return 0; -} - -static unsigned long jz_clk_ldclk_get_rate(struct clk *clk) -{ - int div; - - div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK; - div >>= JZ_CLOCK_CTRL_LDIV_OFFSET; - - return jz_clk_pll_half_get_rate(clk->parent) / (div + 1); -} - -static const struct clk_ops jz_clk_ops_ld = { - .set_rate = jz_clk_ldclk_set_rate, - .get_rate = jz_clk_ldclk_get_rate, - .round_rate = jz_clk_ldclk_round_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct clk jz_clk_ld = { - .name = "lcd", - .gate_bit = JZ_CLOCK_GATE_LCD, - .parent = &jz_clk_pll_half, - .ops = &jz_clk_ops_ld, -}; - -static const struct clk_ops jz_clk_i2s_ops = { - .set_rate = jz_clk_divided_set_rate, - .get_rate = jz_clk_divided_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, - .set_parent = jz_clk_i2s_set_parent, -}; - -static const struct clk_ops jz_clk_spi_ops = { - .set_rate = jz_clk_divided_set_rate, - .get_rate = jz_clk_divided_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, - .set_parent = jz_clk_spi_set_parent, -}; - -static const struct clk_ops jz_clk_divided_ops = { - .set_rate = jz_clk_divided_set_rate, - .get_rate = jz_clk_divided_get_rate, - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct divided_clk jz4740_clock_divided_clks[] = { - [0] = { - .clk = { - .name = "i2s", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_I2S, - .ops = &jz_clk_i2s_ops, - }, - .reg = JZ_REG_CLOCK_I2S, - .mask = JZ_CLOCK_I2S_DIV_MASK, - }, - [1] = { - .clk = { - .name = "spi", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_SPI, - .ops = &jz_clk_spi_ops, - }, - .reg = JZ_REG_CLOCK_SPI, - .mask = JZ_CLOCK_SPI_DIV_MASK, - }, - [2] = { - .clk = { - .name = "lcd_pclk", - .parent = &jz_clk_pll_half, - .gate_bit = JZ4740_CLK_NOT_GATED, - .ops = &jz_clk_divided_ops, - }, - .reg = JZ_REG_CLOCK_LCD, - .mask = JZ_CLOCK_LCD_DIV_MASK, - }, - [3] = { - .clk = { - .name = "mmc", - .parent = &jz_clk_pll_half, - .gate_bit = JZ_CLOCK_GATE_MMC, - .ops = &jz_clk_divided_ops, - }, - .reg = JZ_REG_CLOCK_MMC, - .mask = JZ_CLOCK_MMC_DIV_MASK, - }, - [4] = { - .clk = { - .name = "uhc", - .parent = &jz_clk_pll_half, - .gate_bit = JZ_CLOCK_GATE_UHC, - .ops = &jz_clk_divided_ops, - }, - .reg = JZ_REG_CLOCK_UHC, - .mask = JZ_CLOCK_UHC_DIV_MASK, - }, -}; - -static const struct clk_ops jz_clk_udc_ops = { - .set_parent = jz_clk_udc_set_parent, - .set_rate = jz_clk_udc_set_rate, - .get_rate = jz_clk_udc_get_rate, - .enable = jz_clk_udc_enable, - .disable = jz_clk_udc_disable, - .is_enabled = jz_clk_udc_is_enabled, -}; - -static const struct clk_ops jz_clk_simple_ops = { - .enable = jz_clk_enable_gating, - .disable = jz_clk_disable_gating, - .is_enabled = jz_clk_is_enabled_gating, -}; - -static struct clk jz4740_clock_simple_clks[] = { - [0] = { - .name = "udc", - .parent = &jz_clk_ext.clk, - .ops = &jz_clk_udc_ops, - }, - [1] = { - .name = "uart0", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_UART0, - .ops = &jz_clk_simple_ops, - }, - [2] = { - .name = "uart1", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_UART1, - .ops = &jz_clk_simple_ops, - }, - [3] = { - .name = "dma", - .parent = &jz_clk_high_speed_peripheral.clk, - .gate_bit = JZ_CLOCK_GATE_DMAC, - .ops = &jz_clk_simple_ops, - }, - [4] = { - .name = "ipu", - .parent = &jz_clk_high_speed_peripheral.clk, - .gate_bit = JZ_CLOCK_GATE_IPU, - .ops = &jz_clk_simple_ops, - }, - [5] = { - .name = "adc", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_ADC, - .ops = &jz_clk_simple_ops, - }, - [6] = { - .name = "i2c", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_I2C, - .ops = &jz_clk_simple_ops, - }, - [7] = { - .name = "aic", - .parent = &jz_clk_ext.clk, - .gate_bit = JZ_CLOCK_GATE_AIC, - .ops = &jz_clk_simple_ops, - }, -}; - -static struct static_clk jz_clk_rtc = { - .clk = { - .name = "rtc", - .gate_bit = JZ_CLOCK_GATE_RTC, - .ops = &jz_clk_static_ops, - }, - .rate = 32768, -}; - -int clk_enable(struct clk *clk) -{ - if (!clk->ops->enable) - return -EINVAL; - - return clk->ops->enable(clk); -} -EXPORT_SYMBOL_GPL(clk_enable); - -void clk_disable(struct clk *clk) -{ - if (clk->ops->disable) - clk->ops->disable(clk); -} -EXPORT_SYMBOL_GPL(clk_disable); - -int clk_is_enabled(struct clk *clk) -{ - if (clk->ops->is_enabled) - return clk->ops->is_enabled(clk); - - return 1; -} - -unsigned long clk_get_rate(struct clk *clk) -{ - if (clk->ops->get_rate) - return clk->ops->get_rate(clk); - if (clk->parent) - return clk_get_rate(clk->parent); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - if (!clk->ops->set_rate) - return -EINVAL; - return clk->ops->set_rate(clk, rate); -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (clk->ops->round_rate) - return clk->ops->round_rate(clk, rate); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - int ret; - int enabled; - - if (!clk->ops->set_parent) - return -EINVAL; - - enabled = clk_is_enabled(clk); - if (enabled) - clk_disable(clk); - ret = clk->ops->set_parent(clk, parent); - if (enabled) - clk_enable(clk); - - jz4740_clock_debugfs_update_parent(clk); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -struct clk *clk_get(struct device *dev, const char *name) -{ - struct clk *clk; - - list_for_each_entry(clk, &jz_clocks, list) { - if (strcmp(clk->name, name) == 0) - return clk; - } - return ERR_PTR(-ENXIO); -} -EXPORT_SYMBOL_GPL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL_GPL(clk_put); - -static inline void clk_add(struct clk *clk) -{ - list_add_tail(&clk->list, &jz_clocks); - - jz4740_clock_debugfs_add_clk(clk); -} - -static void clk_register_clks(void) -{ - size_t i; - - clk_add(&jz_clk_ext.clk); - clk_add(&jz_clk_pll); - clk_add(&jz_clk_pll_half); - clk_add(&jz_clk_cpu.clk); - clk_add(&jz_clk_high_speed_peripheral.clk); - clk_add(&jz_clk_low_speed_peripheral.clk); - clk_add(&jz_clk_ko); - clk_add(&jz_clk_ld); - clk_add(&jz_clk_rtc.clk); - - for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i) - clk_add(&jz4740_clock_divided_clks[i].clk); - - for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i) - clk_add(&jz4740_clock_simple_clks[i]); -} - -void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) -{ - switch (mode) { - case JZ4740_WAIT_MODE_IDLE: - jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); - break; - case JZ4740_WAIT_MODE_SLEEP: - jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); - break; - } -} - -void jz4740_clock_udc_disable_auto_suspend(void) -{ - jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); -} -EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); - -void jz4740_clock_udc_enable_auto_suspend(void) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); -} -EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); - -void jz4740_clock_suspend(void) -{ - jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, - JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); - - jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); -} - -void jz4740_clock_resume(void) -{ - uint32_t pll; - - jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); - - do { - pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL); - } while (!(pll & JZ_CLOCK_PLL_STABLE)); - - jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, - JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); -} - -static int jz4740_clock_init(void) -{ - uint32_t val; - - jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100); - if (!jz_clock_base) - return -EBUSY; - - spin_lock_init(&jz_clock_lock); - - jz_clk_ext.rate = jz4740_clock_bdata.ext_rate; - jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate; - - val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); - - if (val & JZ_CLOCK_SPI_SRC_PLL) - jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; - - val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); - - if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) - jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; - - if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) - jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half; - - jz4740_clock_debugfs_init(); - - clk_register_clks(); - - return 0; -} -arch_initcall(jz4740_clock_init); diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h deleted file mode 100644 index 5d07499..0000000 --- a/arch/mips/jz4740/clock.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 SoC clock support - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __MIPS_JZ4740_CLOCK_H__ -#define __MIPS_JZ4740_CLOCK_H__ - -#include <linux/list.h> - -struct jz4740_clock_board_data { - unsigned long ext_rate; - unsigned long rtc_rate; -}; - -extern struct jz4740_clock_board_data jz4740_clock_bdata; - -void jz4740_clock_suspend(void); -void jz4740_clock_resume(void); - -struct clk; - -struct clk_ops { - unsigned long (*get_rate)(struct clk *clk); - unsigned long (*round_rate)(struct clk *clk, unsigned long rate); - int (*set_rate)(struct clk *clk, unsigned long rate); - int (*enable)(struct clk *clk); - int (*disable)(struct clk *clk); - int (*is_enabled)(struct clk *clk); - - int (*set_parent)(struct clk *clk, struct clk *parent); - -}; - -struct clk { - const char *name; - struct clk *parent; - - uint32_t gate_bit; - - const struct clk_ops *ops; - - struct list_head list; - -#ifdef CONFIG_DEBUG_FS - struct dentry *debugfs_entry; - struct dentry *debugfs_parent_entry; -#endif - -}; - -#define JZ4740_CLK_NOT_GATED ((uint32_t)-1) - -int clk_is_enabled(struct clk *clk); - -#ifdef CONFIG_DEBUG_FS -void jz4740_clock_debugfs_init(void); -void jz4740_clock_debugfs_add_clk(struct clk *clk); -void jz4740_clock_debugfs_update_parent(struct clk *clk); -#else -static inline void jz4740_clock_debugfs_init(void) {}; -static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {}; -static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {}; -#endif - -#endif diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 00b798d..54c80d4 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c @@ -21,6 +21,7 @@ #include <linux/gpio.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/irqchip/ingenic.h> #include <linux/bitops.h> #include <linux/debugfs.h> @@ -28,8 +29,6 @@ #include <asm/mach-jz4740/base.h> -#include "irq.h" - #define JZ4740_GPIO_BASE_A (32*0) #define JZ4740_GPIO_BASE_B (32*1) #define JZ4740_GPIO_BASE_C (32*2) @@ -442,8 +441,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) ct->chip.irq_mask = irq_gc_mask_disable_reg; ct->chip.irq_unmask = jz_gpio_irq_unmask; ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_suspend = jz4740_irq_suspend; - ct->chip.irq_resume = jz4740_irq_resume; + ct->chip.irq_suspend = ingenic_intc_irq_suspend; + ct->chip.irq_resume = ingenic_intc_irq_resume; ct->chip.irq_startup = jz_gpio_irq_startup; ct->chip.irq_shutdown = jz_gpio_irq_shutdown; ct->chip.irq_set_type = jz_gpio_irq_set_type; diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c deleted file mode 100644 index 97206b3..0000000 --- a/arch/mips/jz4740/irq.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 platform IRQ support - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/delay.h> - -#include <linux/debugfs.h> -#include <linux/seq_file.h> - -#include <asm/io.h> -#include <asm/mipsregs.h> -#include <asm/irq_cpu.h> - -#include <asm/mach-jz4740/base.h> -#include <asm/mach-jz4740/irq.h> - -#include "irq.h" - -static void __iomem *jz_intc_base; - -#define JZ_REG_INTC_STATUS 0x00 -#define JZ_REG_INTC_MASK 0x04 -#define JZ_REG_INTC_SET_MASK 0x08 -#define JZ_REG_INTC_CLEAR_MASK 0x0c -#define JZ_REG_INTC_PENDING 0x10 - -static irqreturn_t jz4740_cascade(int irq, void *data) -{ - uint32_t irq_reg; - - irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING); - - if (irq_reg) - generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE); - - return IRQ_HANDLED; -} - -static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask) -{ - struct irq_chip_regs *regs = &gc->chip_types->regs; - - writel(mask, gc->reg_base + regs->enable); - writel(~mask, gc->reg_base + regs->disable); -} - -void jz4740_irq_suspend(struct irq_data *data) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - jz4740_irq_set_mask(gc, gc->wake_active); -} - -void jz4740_irq_resume(struct irq_data *data) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - jz4740_irq_set_mask(gc, gc->mask_cache); -} - -static struct irqaction jz4740_cascade_action = { - .handler = jz4740_cascade, - .name = "JZ4740 cascade interrupt", -}; - -void __init arch_init_irq(void) -{ - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - - mips_cpu_irq_init(); - - jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14); - - /* Mask all irqs */ - writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK); - - gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base, - handle_level_irq); - - gc->wake_enabled = IRQ_MSK(32); - - ct = gc->chip_types; - ct->regs.enable = JZ_REG_INTC_CLEAR_MASK; - ct->regs.disable = JZ_REG_INTC_SET_MASK; - ct->chip.irq_unmask = irq_gc_unmask_enable_reg; - ct->chip.irq_mask = irq_gc_mask_disable_reg; - ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; - ct->chip.irq_set_wake = irq_gc_set_wake; - ct->chip.irq_suspend = jz4740_irq_suspend; - ct->chip.irq_resume = jz4740_irq_resume; - - irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL); - - setup_irq(2, &jz4740_cascade_action); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - if (pending & STATUSF_IP2) - do_IRQ(2); - else if (pending & STATUSF_IP3) - do_IRQ(3); - else - spurious_interrupt(); -} - -#ifdef CONFIG_DEBUG_FS - -static inline void intc_seq_reg(struct seq_file *s, const char *name, - unsigned int reg) -{ - seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg)); -} - -static int intc_regs_show(struct seq_file *s, void *unused) -{ - intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS); - intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK); - intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING); - - return 0; -} - -static int intc_regs_open(struct inode *inode, struct file *file) -{ - return single_open(file, intc_regs_show, NULL); -} - -static const struct file_operations intc_regs_operations = { - .open = intc_regs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init intc_debugfs_init(void) -{ - (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO, - NULL, NULL, &intc_regs_operations); - return 0; -} -subsys_initcall(intc_debugfs_init); - -#endif diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 0b12f27..e8a463b 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -13,6 +13,7 @@ * */ +#include <linux/clk.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/platform_device.h> @@ -29,7 +30,6 @@ #include <linux/serial_core.h> #include <linux/serial_8250.h> -#include "serial.h" #include "clock.h" /* OHCI controller */ @@ -279,42 +279,6 @@ struct platform_device jz4740_adc_device = { .resource = jz4740_adc_resources, }; -/* Serial */ -#define JZ4740_UART_DATA(_id) \ - { \ - .flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \ - .iotype = UPIO_MEM, \ - .regshift = 2, \ - .serial_out = jz4740_serial_out, \ - .type = PORT_16550, \ - .mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \ - .irq = JZ4740_IRQ_UART ## _id, \ - } - -static struct plat_serial8250_port jz4740_uart_data[] = { - JZ4740_UART_DATA(0), - JZ4740_UART_DATA(1), - {}, -}; - -static struct platform_device jz4740_uart_device = { - .name = "serial8250", - .id = 0, - .dev = { - .platform_data = jz4740_uart_data, - }, -}; - -void jz4740_serial_device_register(void) -{ - struct plat_serial8250_port *p; - - for (p = jz4740_uart_data; p->flags != 0; ++p) - p->uartclk = jz4740_clock_bdata.ext_rate; - - platform_device_register(&jz4740_uart_device); -} - /* Watchdog */ static struct resource jz4740_wdt_resources[] = { { diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c index d8e2130..2d8653f 100644 --- a/arch/mips/jz4740/pm.c +++ b/arch/mips/jz4740/pm.c @@ -20,8 +20,6 @@ #include <asm/mach-jz4740/clock.h> -#include "clock.h" - static int jz4740_pm_enter(suspend_state_t state) { jz4740_clock_suspend(); diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c index 5a93f38..6984683 100644 --- a/arch/mips/jz4740/prom.c +++ b/arch/mips/jz4740/prom.c @@ -53,16 +53,3 @@ void __init prom_init(void) void __init prom_free_prom_memory(void) { } - -#define UART_REG(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 2))) - -void prom_putchar(char c) -{ - uint8_t lsr; - - do { - lsr = readb(UART_REG(UART_LSR)); - } while ((lsr & UART_LSR_TEMT) == 0); - - writeb(c, UART_REG(UART_TX)); -} diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c index b6c6343..954e669 100644 --- a/arch/mips/jz4740/reset.c +++ b/arch/mips/jz4740/reset.c @@ -12,6 +12,7 @@ * */ +#include <linux/clk.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/pm.h> @@ -79,12 +80,20 @@ static void jz4740_power_off(void) void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38); unsigned long wakeup_filter_ticks; unsigned long reset_counter_ticks; + struct clk *rtc_clk; + unsigned long rtc_rate; + + rtc_clk = clk_get(NULL, "rtc"); + if (IS_ERR(rtc_clk)) + panic("unable to get RTC clock"); + rtc_rate = clk_get_rate(rtc_clk); + clk_put(rtc_clk); /* * Set minimum wakeup pin assertion time: 100 ms. * Range is 0 to 2 sec if RTC is clocked at 32 kHz. */ - wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000; + wakeup_filter_ticks = (100 * rtc_rate) / 1000; if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; else @@ -96,7 +105,7 @@ static void jz4740_power_off(void) * Set reset pin low-level assertion time after wakeup: 60 ms. * Range is 0 to 125 ms if RTC is clocked at 32 kHz. */ - reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000; + reset_counter_ticks = (60 * rtc_rate) / 1000; if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; else diff --git a/arch/mips/jz4740/serial.c b/arch/mips/jz4740/serial.c deleted file mode 100644 index d23de45..0000000 --- a/arch/mips/jz4740/serial.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 serial support - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/io.h> -#include <linux/serial_core.h> -#include <linux/serial_reg.h> - -void jz4740_serial_out(struct uart_port *p, int offset, int value) -{ - switch (offset) { - case UART_FCR: - value |= 0x10; /* Enable uart module */ - break; - case UART_IER: - value |= (value & 0x4) << 2; - break; - default: - break; - } - writeb(value, p->membase + (offset << p->regshift)); -} diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h deleted file mode 100644 index 8eb715b..0000000 --- a/arch/mips/jz4740/serial.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> - * JZ4740 serial support - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __MIPS_JZ4740_SERIAL_H__ -#define __MIPS_JZ4740_SERIAL_H__ - -struct uart_port; - -void jz4740_serial_out(struct uart_port *p, int offset, int value); - -#endif diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c index ef796f9..510fc0d 100644 --- a/arch/mips/jz4740/setup.c +++ b/arch/mips/jz4740/setup.c @@ -16,9 +16,14 @@ #include <linux/init.h> #include <linux/io.h> +#include <linux/irqchip.h> #include <linux/kernel.h> +#include <linux/libfdt.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> #include <asm/bootinfo.h> +#include <asm/prom.h> #include <asm/mach-jz4740/base.h> @@ -51,11 +56,40 @@ static void __init jz4740_detect_mem(void) void __init plat_mem_setup(void) { + int offset; + jz4740_reset_init(); - jz4740_detect_mem(); + __dt_setup_arch(__dtb_start); + + offset = fdt_path_offset(__dtb_start, "/memory"); + if (offset < 0) + jz4740_detect_mem(); } +void __init device_tree_init(void) +{ + if (!initial_boot_params) + return; + + unflatten_and_copy_device_tree(); +} + +static int __init populate_machine(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + return 0; +} +arch_initcall(populate_machine); + const char *get_system_type(void) { + if (config_enabled(CONFIG_MACH_JZ4780)) + return "JZ4780"; + return "JZ4740"; } + +void __init arch_init_irq(void) +{ + irqchip_init(); +} diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c index 72b0cec..7ab47fe 100644 --- a/arch/mips/jz4740/time.c +++ b/arch/mips/jz4740/time.c @@ -13,6 +13,8 @@ * */ +#include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/time.h> @@ -20,6 +22,7 @@ #include <linux/clockchips.h> #include <linux/sched_clock.h> +#include <asm/mach-jz4740/clock.h> #include <asm/mach-jz4740/irq.h> #include <asm/mach-jz4740/timer.h> #include <asm/time.h> @@ -99,7 +102,12 @@ static struct clock_event_device jz4740_clockevent = { .set_next_event = jz4740_clockevent_set_next, .set_mode = jz4740_clockevent_set_mode, .rating = 200, +#ifdef CONFIG_MACH_JZ4740 .irq = JZ4740_IRQ_TCU0, +#endif +#ifdef CONFIG_MACH_JZ4780 + .irq = JZ4780_IRQ_TCU2, +#endif }; static struct irqaction timer_irqaction = { @@ -114,10 +122,17 @@ void __init plat_time_init(void) int ret; uint32_t clk_rate; uint16_t ctrl; + struct clk *ext_clk; + of_clk_init(NULL); jz4740_timer_init(); - clk_rate = jz4740_clock_bdata.ext_rate >> 4; + ext_clk = clk_get(NULL, "ext"); + if (IS_ERR(ext_clk)) + panic("unable to get ext clock"); + clk_rate = clk_get_rate(ext_clk) >> 4; + clk_put(ext_clk); + jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ); clockevent_set_clock(&jz4740_clockevent, clk_rate); @@ -134,7 +149,7 @@ void __init plat_time_init(void) sched_clock_register(jz4740_read_sched_clock, 16, clk_rate); - setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction); + setup_irq(jz4740_clockevent.irq, &timer_irqaction); ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index d3d2ff2..3f5cf8a 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -62,7 +62,6 @@ obj-$(CONFIG_MIPS_VPE_APSP_API_CMP) += rtlx-cmp.o obj-$(CONFIG_MIPS_VPE_APSP_API_MT) += rtlx-mt.o obj-$(CONFIG_I8259) += i8259.o -obj-$(CONFIG_IRQ_CPU) += irq_cpu.o obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o obj-$(CONFIG_MIPS_MSC) += irq-msc01.o obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o @@ -77,6 +76,7 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_PROC_FS) += proc.o +obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o obj-$(CONFIG_64BIT) += cpu-bugs64.o diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 209e5b7..dbe0792 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -945,7 +945,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST; c->tlbsize = 64; break; case PRID_IMP_R14000: @@ -960,7 +960,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST; c->tlbsize = 64; break; case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ @@ -1443,7 +1443,9 @@ void cpu_probe(void) case PRID_COMP_CAVIUM: cpu_probe_cavium(c, cpu); break; - case PRID_COMP_INGENIC: + case PRID_COMP_INGENIC_D0: + case PRID_COMP_INGENIC_D1: + case PRID_COMP_INGENIC_E1: cpu_probe_ingenic(c, cpu); break; case PRID_COMP_NETLOGIC: @@ -1478,6 +1480,10 @@ void cpu_probe(void) else cpu_set_nofpu_opts(c); + if (cpu_has_bp_ghist) + write_c0_r10k_diag(read_c0_r10k_diag() | + R10K_DIAG_E_GHIST); + if (cpu_has_mips_r2_r6) { c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; /* R2 has Performance Counter Interrupt indicator */ diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 95afd66..4e4cc5b 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -94,6 +94,22 @@ NESTED(kernel_entry, 16, sp) # kernel entry point jr t0 0: +#ifdef CONFIG_MIPS_RAW_APPENDED_DTB + PTR_LA t0, __appended_dtb + +#ifdef CONFIG_CPU_BIG_ENDIAN + li t1, 0xd00dfeed +#else + li t1, 0xedfe0dd0 +#endif + lw t2, (t0) + bne t1, t2, not_found + nop + + move a1, t0 + PTR_LI a0, -2 +not_found: +#endif PTR_LA t0, __bss_start # clear .bss LONG_S zero, (t0) PTR_LA t1, __bss_stop - LONGSIZE diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index a74ec3a..74f6752 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -14,6 +14,7 @@ #include <linux/interrupt.h> #include <linux/irqdomain.h> #include <linux/kernel.h> +#include <linux/of_irq.h> #include <linux/spinlock.h> #include <linux/syscore_ops.h> #include <linux/irq.h> @@ -21,6 +22,8 @@ #include <asm/i8259.h> #include <asm/io.h> +#include "../../drivers/irqchip/irqchip.h" + /* * This is the 'legacy' 8259A Programmable Interrupt Controller, * present in the majority of PC/AT boxes. @@ -327,7 +330,7 @@ static struct irq_domain_ops i8259A_ops = { * driver compatibility reasons interrupts 0 - 15 to be the i8259 * interrupts even if the hardware uses a different interrupt numbering. */ -void __init init_i8259_irqs(void) +struct irq_domain * __init __init_i8259_irqs(struct device_node *node) { struct irq_domain *domain; @@ -336,10 +339,46 @@ void __init init_i8259_irqs(void) init_8259A(0); - domain = irq_domain_add_legacy(NULL, 16, I8259A_IRQ_BASE, 0, + domain = irq_domain_add_legacy(node, 16, I8259A_IRQ_BASE, 0, &i8259A_ops, NULL); if (!domain) panic("Failed to add i8259 IRQ domain"); setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2); + return domain; +} + +void __init init_i8259_irqs(void) +{ + __init_i8259_irqs(NULL); +} + +static void i8259_irq_dispatch(unsigned int irq, struct irq_desc *desc) +{ + struct irq_domain *domain = irq_get_handler_data(irq); + int hwirq = i8259_irq(); + + if (hwirq < 0) + return; + + irq = irq_linear_revmap(domain, hwirq); + generic_handle_irq(irq); +} + +int __init i8259_of_init(struct device_node *node, struct device_node *parent) +{ + struct irq_domain *domain; + unsigned int parent_irq; + + parent_irq = irq_of_parse_and_map(node, 0); + if (!parent_irq) { + pr_err("Failed to map i8259 parent IRQ\n"); + return -ENODEV; + } + + domain = __init_i8259_irqs(node); + irq_set_handler_data(parent_irq, domain); + irq_set_chained_handler(parent_irq, i8259_irq_dispatch); + return 0; } +IRQCHIP_DECLARE(i8259, "intel,i8259", i8259_of_init); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 3c8a18a..8eb5af8 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -25,48 +25,6 @@ #include <linux/atomic.h> #include <asm/uaccess.h> -#ifdef CONFIG_KGDB -int kgdb_early_setup; -#endif - -static DECLARE_BITMAP(irq_map, NR_IRQS); - -int allocate_irqno(void) -{ - int irq; - -again: - irq = find_first_zero_bit(irq_map, NR_IRQS); - - if (irq >= NR_IRQS) - return -ENOSPC; - - if (test_and_set_bit(irq, irq_map)) - goto again; - - return irq; -} - -/* - * Allocate the 16 legacy interrupts for i8259 devices. This happens early - * in the kernel initialization so treating allocation failure as BUG() is - * ok. - */ -void __init alloc_legacy_irqno(void) -{ - int i; - - for (i = 0; i <= 16; i++) - BUG_ON(test_and_set_bit(i, irq_map)); -} - -void free_irqno(unsigned int irq) -{ - smp_mb__before_atomic(); - clear_bit(irq, irq_map); - smp_mb__after_atomic(); -} - /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. @@ -93,20 +51,10 @@ void __init init_IRQ(void) { int i; -#ifdef CONFIG_KGDB - if (kgdb_early_setup) - return; -#endif - for (i = 0; i < NR_IRQS; i++) irq_set_noprobe(i); arch_init_irq(); - -#ifdef CONFIG_KGDB - if (!kgdb_early_setup) - kgdb_early_setup = 1; -#endif } #ifdef CONFIG_DEBUG_STACKOVERFLOW diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 7afcc2f..de63d36 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -378,10 +378,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, struct kgdb_arch arch_kgdb_ops; -/* - * We use kgdb_early_setup so that functions we need to call now don't - * cause trouble when called again later. - */ int kgdb_arch_init(void) { union mips_instruction insn = { diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index e303cb1..b130033 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -18,6 +18,7 @@ #include <linux/of_fdt.h> #include <linux/of_platform.h> +#include <asm/bootinfo.h> #include <asm/page.h> #include <asm/prom.h> diff --git a/arch/mips/kernel/sysrq.c b/arch/mips/kernel/sysrq.c new file mode 100644 index 0000000..5b539f5 --- /dev/null +++ b/arch/mips/kernel/sysrq.c @@ -0,0 +1,77 @@ +/* + * MIPS specific sysrq operations. + * + * Copyright (C) 2015 Imagination Technologies Ltd. + */ +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/spinlock.h> +#include <linux/sysrq.h> +#include <linux/workqueue.h> + +#include <asm/cpu-features.h> +#include <asm/mipsregs.h> +#include <asm/tlbdebug.h> + +/* + * Dump TLB entries on all CPUs. + */ + +static DEFINE_SPINLOCK(show_lock); + +static void sysrq_tlbdump_single(void *dummy) +{ + const int field = 2 * sizeof(unsigned long); + unsigned long flags; + + spin_lock_irqsave(&show_lock, flags); + + pr_info("CPU%d:\n", smp_processor_id()); + pr_info("Index : %0x\n", read_c0_index()); + pr_info("Pagemask: %0x\n", read_c0_pagemask()); + pr_info("EntryHi : %0*lx\n", field, read_c0_entryhi()); + pr_info("EntryLo0: %0*lx\n", field, read_c0_entrylo0()); + pr_info("EntryLo1: %0*lx\n", field, read_c0_entrylo1()); + pr_info("Wired : %0x\n", read_c0_wired()); + pr_info("Pagegrain: %0x\n", read_c0_pagegrain()); + if (cpu_has_htw) { + pr_info("PWField : %0*lx\n", field, read_c0_pwfield()); + pr_info("PWSize : %0*lx\n", field, read_c0_pwsize()); + pr_info("PWCtl : %0x\n", read_c0_pwctl()); + } + pr_info("\n"); + dump_tlb_all(); + pr_info("\n"); + + spin_unlock_irqrestore(&show_lock, flags); +} + +#ifdef CONFIG_SMP +static void sysrq_tlbdump_othercpus(struct work_struct *dummy) +{ + smp_call_function(sysrq_tlbdump_single, NULL, 0); +} + +static DECLARE_WORK(sysrq_tlbdump, sysrq_tlbdump_othercpus); +#endif + +static void sysrq_handle_tlbdump(int key) +{ + sysrq_tlbdump_single(NULL); +#ifdef CONFIG_SMP + schedule_work(&sysrq_tlbdump); +#endif +} + +static struct sysrq_key_op sysrq_tlbdump_op = { + .handler = sysrq_handle_tlbdump, + .help_msg = "show-tlbs(x)", + .action_msg = "Show TLB entries", + .enable_mask = SYSRQ_ENABLE_DUMP, +}; + +static int __init mips_sysrq_init(void) +{ + return register_sysrq_key('x', &sysrq_tlbdump_op); +} +arch_initcall(mips_sysrq_init); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index d2d1c19..2a7b38e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -236,6 +236,7 @@ static void __show_regs(const struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); unsigned int cause = regs->cp0_cause; + unsigned int exccode; int i; show_regs_print_info(KERN_DEFAULT); @@ -317,10 +318,10 @@ static void __show_regs(const struct pt_regs *regs) } printk("\n"); - printk("Cause : %08x\n", cause); + exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; + printk("Cause : %08x (ExcCode %02x)\n", cause, exccode); - cause = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; - if (1 <= cause && cause <= 5) + if (1 <= exccode && exccode <= 5) printk("BadVA : %0*lx\n", field, regs->cp0_badvaddr); printk("PrId : %08x (%s)\n", read_c0_prid(), @@ -2184,11 +2185,6 @@ void __init trap_init(void) check_wait(); -#if defined(CONFIG_KGDB) - if (kgdb_early_setup) - return; /* Already done */ -#endif - if (cpu_has_veic || cpu_has_vint) { unsigned long size = 0x200 + VECTORSPACING*64; ebase = (unsigned long) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 3b46f7c..07d32a4 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -125,8 +125,14 @@ SECTIONS .exit.data : { EXIT_DATA } - +#ifdef CONFIG_SMP PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT) +#endif +#ifdef CONFIG_MIPS_RAW_APPENDED_DTB + __appended_dtb = .; + /* leave space for appended DTB */ + . += 0x100000; +#endif /* * Align to 64K in attempt to eliminate holes before the * .bss..swapper_pg_dir section at the start of .bss. This diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 32b9f21..167f3563 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -7,6 +7,7 @@ #include <linux/kernel.h> #include <linux/mm.h> +#include <asm/hazards.h> #include <asm/mipsregs.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -40,17 +41,20 @@ static inline const char *msk2str(unsigned int mask) return ""; } -#define BARRIER() \ - __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - "nop;nop;nop;nop;nop;nop;nop\n\t" \ - ".set\treorder"); - static void dump_tlb(int first, int last) { unsigned long s_entryhi, entryhi, asid; - unsigned long long entrylo0, entrylo1; + unsigned long long entrylo0, entrylo1, pa; unsigned int s_index, s_pagemask, pagemask, c0, c1, i; +#ifdef CONFIG_32BIT + bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA); + int pwidth = xpa ? 11 : 8; + int vwidth = 8; +#else + bool xpa = false; + int pwidth = 11; + int vwidth = 11; +#endif s_pagemask = read_c0_pagemask(); s_entryhi = read_c0_entryhi(); @@ -59,46 +63,74 @@ static void dump_tlb(int first, int last) for (i = first; i <= last; i++) { write_c0_index(i); - BARRIER(); + mtc0_tlbr_hazard(); tlb_read(); - BARRIER(); + tlb_read_hazard(); pagemask = read_c0_pagemask(); entryhi = read_c0_entryhi(); entrylo0 = read_c0_entrylo0(); entrylo1 = read_c0_entrylo1(); - /* Unused entries have a virtual address of CKSEG0. */ - if ((entryhi & ~0x1ffffUL) != CKSEG0 - && (entryhi & 0xff) == asid) { -#ifdef CONFIG_32BIT - int width = 8; -#else - int width = 11; -#endif - /* - * Only print entries in use - */ - printk("Index: %2d pgmask=%s ", i, msk2str(pagemask)); + /* EHINV bit marks entire entry as invalid */ + if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV) + continue; + /* + * Prior to tlbinv, unused entries have a virtual address of + * CKSEG0. + */ + if ((entryhi & ~0x1ffffUL) == CKSEG0) + continue; + /* + * ASID takes effect in absence of G (global) bit. + * We check both G bits, even though architecturally they should + * match one another, because some revisions of the SB1 core may + * leave only a single G bit set after a machine check exception + * due to duplicate TLB entry. + */ + if (!((entrylo0 | entrylo1) & MIPS_ENTRYLO_G) && + (entryhi & 0xff) != asid) + continue; + + /* + * Only print entries in use + */ + printk("Index: %2d pgmask=%s ", i, msk2str(pagemask)); - c0 = (entrylo0 >> 3) & 7; - c1 = (entrylo1 >> 3) & 7; + c0 = (entrylo0 & MIPS_ENTRYLO_C) >> MIPS_ENTRYLO_C_SHIFT; + c1 = (entrylo1 & MIPS_ENTRYLO_C) >> MIPS_ENTRYLO_C_SHIFT; - printk("va=%0*lx asid=%02lx\n", - width, (entryhi & ~0x1fffUL), - entryhi & 0xff); - printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ", - width, - (entrylo0 << 6) & PAGE_MASK, c0, - (entrylo0 & 4) ? 1 : 0, - (entrylo0 & 2) ? 1 : 0, - (entrylo0 & 1) ? 1 : 0); - printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n", - width, - (entrylo1 << 6) & PAGE_MASK, c1, - (entrylo1 & 4) ? 1 : 0, - (entrylo1 & 2) ? 1 : 0, - (entrylo1 & 1) ? 1 : 0); - } + printk("va=%0*lx asid=%02lx\n", + vwidth, (entryhi & ~0x1fffUL), + entryhi & 0xff); + /* RI/XI are in awkward places, so mask them off separately */ + pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); + if (xpa) + pa |= (unsigned long long)readx_c0_entrylo0() << 30; + pa = (pa << 6) & PAGE_MASK; + printk("\t["); + if (cpu_has_rixi) + printk("ri=%d xi=%d ", + (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0, + (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0); + printk("pa=%0*llx c=%d d=%d v=%d g=%d] [", + pwidth, pa, c0, + (entrylo0 & MIPS_ENTRYLO_D) ? 1 : 0, + (entrylo0 & MIPS_ENTRYLO_V) ? 1 : 0, + (entrylo0 & MIPS_ENTRYLO_G) ? 1 : 0); + /* RI/XI are in awkward places, so mask them off separately */ + pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI); + if (xpa) + pa |= (unsigned long long)readx_c0_entrylo1() << 30; + pa = (pa << 6) & PAGE_MASK; + if (cpu_has_rixi) + printk("ri=%d xi=%d ", + (entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0, + (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0); + printk("pa=%0*llx c=%d d=%d v=%d g=%d]\n", + pwidth, pa, c1, + (entrylo1 & MIPS_ENTRYLO_D) ? 1 : 0, + (entrylo1 & MIPS_ENTRYLO_V) ? 1 : 0, + (entrylo1 & MIPS_ENTRYLO_G) ? 1 : 0); } printk("\n"); diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c index 975a138..8e0d3cf 100644 --- a/arch/mips/lib/r3k_dump_tlb.c +++ b/arch/mips/lib/r3k_dump_tlb.c @@ -14,8 +14,6 @@ #include <asm/pgtable.h> #include <asm/tlbdebug.h> -extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */ - static void dump_tlb(int first, int last) { int i; @@ -35,8 +33,9 @@ static void dump_tlb(int first, int last) entrylo0 = read_c0_entrylo0(); /* Unused entries have a virtual address of KSEG0. */ - if ((entryhi & PAGE_MASK) != KSEG0 - && (entryhi & ASID_MASK) == asid) { + if ((entryhi & PAGE_MASK) != KSEG0 && + (entrylo0 & R3K_ENTRYLO_G || + (entryhi & ASID_MASK) == asid)) { /* * Only print entries in use */ @@ -47,10 +46,10 @@ static void dump_tlb(int first, int last) entryhi & PAGE_MASK, entryhi & ASID_MASK, entrylo0 & PAGE_MASK, - (entrylo0 & (1 << 11)) ? 1 : 0, - (entrylo0 & (1 << 10)) ? 1 : 0, - (entrylo0 & (1 << 9)) ? 1 : 0, - (entrylo0 & (1 << 8)) ? 1 : 0); + (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, + (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, + (entrylo0 & R3K_ENTRYLO_V) ? 1 : 0, + (entrylo0 & R3K_ENTRYLO_G) ? 1 : 0); } } printk("\n"); diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson32/Kconfig index a2b796e..7704f20 100644 --- a/arch/mips/loongson1/Kconfig +++ b/arch/mips/loongson32/Kconfig @@ -1,4 +1,4 @@ -if MACH_LOONGSON1 +if MACH_LOONGSON32 choice prompt "Machine Type" @@ -10,7 +10,7 @@ config LOONGSON1_LS1B select SYS_HAS_CPU_LOONGSON1B select DMA_NONCOHERENT select BOOT_ELF32 - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_HIGHMEM @@ -58,4 +58,4 @@ config TIMER_USE_PWM3 endchoice -endif # MACH_LOONGSON1 +endif # MACH_LOONGSON32 diff --git a/arch/mips/loongson1/Makefile b/arch/mips/loongson32/Makefile index 9719c75..5f4bd6e 100644 --- a/arch/mips/loongson1/Makefile +++ b/arch/mips/loongson32/Makefile @@ -2,7 +2,7 @@ # Common code for all Loongson 1 based systems # -obj-$(CONFIG_MACH_LOONGSON1) += common/ +obj-$(CONFIG_MACH_LOONGSON32) += common/ # # Loongson LS1B board diff --git a/arch/mips/loongson1/Platform b/arch/mips/loongson32/Platform index 1186344..ebb6dc2 100644 --- a/arch/mips/loongson1/Platform +++ b/arch/mips/loongson32/Platform @@ -2,6 +2,6 @@ cflags-$(CONFIG_CPU_LOONGSON1) += \ $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ -Wa,-mips32r2 -Wa,--trap -platform-$(CONFIG_MACH_LOONGSON1) += loongson1/ -cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1 +platform-$(CONFIG_MACH_LOONGSON32) += loongson32/ +cflags-$(CONFIG_MACH_LOONGSON32) += -I$(srctree)/arch/mips/include/asm/mach-loongson32 load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80100000 diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson32/common/Makefile index 723b4ce..723b4ce 100644 --- a/arch/mips/loongson1/common/Makefile +++ b/arch/mips/loongson32/common/Makefile diff --git a/arch/mips/loongson1/common/irq.c b/arch/mips/loongson32/common/irq.c index 455a770..455a770 100644 --- a/arch/mips/loongson1/common/irq.c +++ b/arch/mips/loongson32/common/irq.c diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson32/common/platform.c index ddf1d4c..ddf1d4c 100644 --- a/arch/mips/loongson1/common/platform.c +++ b/arch/mips/loongson32/common/platform.c diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson32/common/prom.c index 6860098..6860098 100644 --- a/arch/mips/loongson1/common/prom.c +++ b/arch/mips/loongson32/common/prom.c diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson32/common/reset.c index c41e4ca..c41e4ca 100644 --- a/arch/mips/loongson1/common/reset.c +++ b/arch/mips/loongson32/common/reset.c diff --git a/arch/mips/loongson1/common/setup.c b/arch/mips/loongson32/common/setup.c index 62f41af..62f41af 100644 --- a/arch/mips/loongson1/common/setup.c +++ b/arch/mips/loongson32/common/setup.c diff --git a/arch/mips/loongson1/common/time.c b/arch/mips/loongson32/common/time.c index df0f850..df0f850 100644 --- a/arch/mips/loongson1/common/time.c +++ b/arch/mips/loongson32/common/time.c diff --git a/arch/mips/loongson1/ls1b/Makefile b/arch/mips/loongson32/ls1b/Makefile index 891eac4..891eac4 100644 --- a/arch/mips/loongson1/ls1b/Makefile +++ b/arch/mips/loongson32/ls1b/Makefile diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson32/ls1b/board.c index 58daeea..58daeea 100644 --- a/arch/mips/loongson1/ls1b/board.c +++ b/arch/mips/loongson32/ls1b/board.c diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson64/Kconfig index 156de85..497912b 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson64/Kconfig @@ -1,4 +1,4 @@ -if MACH_LOONGSON +if MACH_LOONGSON64 choice prompt "Machine Type" @@ -15,7 +15,7 @@ config LEMOTE_FULOONG2E select HW_HAS_PCI select I8259 select ISA - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -44,7 +44,7 @@ config LEMOTE_MACH2F select HAVE_CLK select HW_HAS_PCI select I8259 - select IRQ_CPU + select IRQ_MIPS_CPU select ISA select SYS_HAS_CPU_LOONGSON2F select SYS_HAS_EARLY_PRINTK @@ -73,7 +73,7 @@ config LOONGSON_MACH3X select ISA select HT_PCI select I8259 - select IRQ_CPU + select IRQ_MIPS_CPU select NR_CPUS_DEFAULT_4 select SYS_HAS_CPU_LOONGSON3 select SYS_HAS_EARLY_PRINTK @@ -155,4 +155,4 @@ config LOONGSON_MC146818 config LEFI_FIRMWARE_INTERFACE bool -endif # MACH_LOONGSON +endif # MACH_LOONGSON64 diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson64/Makefile index 7429994..4fe3d88 100644 --- a/arch/mips/loongson/Makefile +++ b/arch/mips/loongson64/Makefile @@ -2,7 +2,7 @@ # Common code for all Loongson based systems # -obj-$(CONFIG_MACH_LOONGSON) += common/ +obj-$(CONFIG_MACH_LOONGSON64) += common/ # # Lemote Fuloong mini-PC (Loongson 2E-based) diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson64/Platform index 0ac20eb..2e48e83 100644 --- a/arch/mips/loongson/Platform +++ b/arch/mips/loongson64/Platform @@ -26,8 +26,8 @@ endif # Loongson Machines' Support # -platform-$(CONFIG_MACH_LOONGSON) += loongson/ -cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely +platform-$(CONFIG_MACH_LOONGSON64) += loongson64/ +cflags-$(CONFIG_MACH_LOONGSON64) += -I$(srctree)/arch/mips/include/asm/mach-loongson64 -mno-branch-likely load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000 load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000 load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000 diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson64/common/Makefile index f2e8153..f2e8153 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson64/common/Makefile diff --git a/arch/mips/loongson/common/bonito-irq.c b/arch/mips/loongson64/common/bonito-irq.c index cc0e4fd..cc0e4fd 100644 --- a/arch/mips/loongson/common/bonito-irq.c +++ b/arch/mips/loongson64/common/bonito-irq.c diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c index 72fed00..72fed00 100644 --- a/arch/mips/loongson/common/cmdline.c +++ b/arch/mips/loongson64/common/cmdline.c diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson64/common/cs5536/Makefile index f12e640..f12e640 100644 --- a/arch/mips/loongson/common/cs5536/Makefile +++ b/arch/mips/loongson64/common/cs5536/Makefile diff --git a/arch/mips/loongson/common/cs5536/cs5536_acc.c b/arch/mips/loongson64/common/cs5536/cs5536_acc.c index ab4d6cc..ab4d6cc 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_acc.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_acc.c diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson64/common/cs5536/cs5536_ehci.c index ec2e360..ec2e360 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_ehci.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_ehci.c diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson64/common/cs5536/cs5536_ide.c index a73414d..a73414d 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_ide.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_ide.c diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson64/common/cs5536/cs5536_isa.c index 924be39..924be39 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_isa.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_isa.c diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index 12c75db..12c75db 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson64/common/cs5536/cs5536_ohci.c index f7c905e..f7c905e 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_ohci.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_ohci.c diff --git a/arch/mips/loongson/common/cs5536/cs5536_pci.c b/arch/mips/loongson64/common/cs5536/cs5536_pci.c index b739723..b739723 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_pci.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_pci.c diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson64/common/dma-swiotlb.c index 2c6b989..2c6b989 100644 --- a/arch/mips/loongson/common/dma-swiotlb.c +++ b/arch/mips/loongson64/common/dma-swiotlb.c diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson64/common/early_printk.c index 6ca632e..6ca632e 100644 --- a/arch/mips/loongson/common/early_printk.c +++ b/arch/mips/loongson64/common/early_printk.c diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson64/common/env.c index 22f04ca..22f04ca 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson64/common/env.c diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson64/common/init.c index 9b987fe..9b987fe 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson64/common/init.c diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson64/common/irq.c index 687003b..687003b 100644 --- a/arch/mips/loongson/common/irq.c +++ b/arch/mips/loongson64/common/irq.c diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson64/common/machtype.c index f2807bc..f2807bc 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson64/common/machtype.c diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson64/common/mem.c index b01d524..b01d524 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson64/common/mem.c diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson64/common/pci.c index 4e25756..4e25756 100644 --- a/arch/mips/loongson/common/pci.c +++ b/arch/mips/loongson64/common/pci.c diff --git a/arch/mips/loongson/common/platform.c b/arch/mips/loongson64/common/platform.c index 0ed3832..0ed3832 100644 --- a/arch/mips/loongson/common/platform.c +++ b/arch/mips/loongson64/common/platform.c diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson64/common/pm.c index a6b67cc..a6b67cc 100644 --- a/arch/mips/loongson/common/pm.c +++ b/arch/mips/loongson64/common/pm.c diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson64/common/reset.c index a60715e..a60715e 100644 --- a/arch/mips/loongson/common/reset.c +++ b/arch/mips/loongson64/common/reset.c diff --git a/arch/mips/loongson/common/rtc.c b/arch/mips/loongson64/common/rtc.c index b5709af..b5709af 100644 --- a/arch/mips/loongson/common/rtc.c +++ b/arch/mips/loongson64/common/rtc.c diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson64/common/serial.c index c23fa13..ffefc1c 100644 --- a/arch/mips/loongson/common/serial.c +++ b/arch/mips/loongson64/common/serial.c @@ -11,7 +11,7 @@ */ #include <linux/io.h> -#include <linux/init.h> +#include <linux/module.h> #include <linux/serial_8250.h> #include <asm/bootinfo.h> @@ -108,5 +108,10 @@ static int __init serial_init(void) return platform_device_register(&uart8250_device); } +module_init(serial_init); -device_initcall(serial_init); +static void __init serial_exit(void) +{ + platform_device_unregister(&uart8250_device); +} +module_exit(serial_exit); diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson64/common/setup.c index d477dd6..d477dd6 100644 --- a/arch/mips/loongson/common/setup.c +++ b/arch/mips/loongson64/common/setup.c diff --git a/arch/mips/loongson/common/time.c b/arch/mips/loongson64/common/time.c index e1a5382a..e1a5382a 100644 --- a/arch/mips/loongson/common/time.c +++ b/arch/mips/loongson64/common/time.c diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson64/common/uart_base.c index 9de559d..9de559d 100644 --- a/arch/mips/loongson/common/uart_base.c +++ b/arch/mips/loongson64/common/uart_base.c diff --git a/arch/mips/loongson/fuloong-2e/Makefile b/arch/mips/loongson64/fuloong-2e/Makefile index b762272..b762272 100644 --- a/arch/mips/loongson/fuloong-2e/Makefile +++ b/arch/mips/loongson64/fuloong-2e/Makefile diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson64/fuloong-2e/irq.c index ef5ec8f..ef5ec8f 100644 --- a/arch/mips/loongson/fuloong-2e/irq.c +++ b/arch/mips/loongson64/fuloong-2e/irq.c diff --git a/arch/mips/loongson/fuloong-2e/reset.c b/arch/mips/loongson64/fuloong-2e/reset.c index da4d2ae..da4d2ae 100644 --- a/arch/mips/loongson/fuloong-2e/reset.c +++ b/arch/mips/loongson64/fuloong-2e/reset.c diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson64/lemote-2f/Makefile index 4f9eaa3..4f9eaa3 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson64/lemote-2f/Makefile diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson64/lemote-2f/clock.c index 462e34d..462e34d 100644 --- a/arch/mips/loongson/lemote-2f/clock.c +++ b/arch/mips/loongson64/lemote-2f/clock.c diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c index 2b666d3..2b666d3 100644 --- a/arch/mips/loongson/lemote-2f/ec_kb3310b.c +++ b/arch/mips/loongson64/lemote-2f/ec_kb3310b.c diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.h b/arch/mips/loongson64/lemote-2f/ec_kb3310b.h index 5a3f186..5a3f186 100644 --- a/arch/mips/loongson/lemote-2f/ec_kb3310b.h +++ b/arch/mips/loongson64/lemote-2f/ec_kb3310b.h diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson64/lemote-2f/irq.c index cab5f43..cab5f43 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson64/lemote-2f/irq.c diff --git a/arch/mips/loongson/lemote-2f/machtype.c b/arch/mips/loongson64/lemote-2f/machtype.c index b55e6ee..b55e6ee 100644 --- a/arch/mips/loongson/lemote-2f/machtype.c +++ b/arch/mips/loongson64/lemote-2f/machtype.c diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson64/lemote-2f/pm.c index cac4d38..cac4d38 100644 --- a/arch/mips/loongson/lemote-2f/pm.c +++ b/arch/mips/loongson64/lemote-2f/pm.c diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson64/lemote-2f/reset.c index a26ca7f..a26ca7f 100644 --- a/arch/mips/loongson/lemote-2f/reset.c +++ b/arch/mips/loongson64/lemote-2f/reset.c diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson64/loongson-3/Makefile index 622fead..622fead 100644 --- a/arch/mips/loongson/loongson-3/Makefile +++ b/arch/mips/loongson64/loongson-3/Makefile diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson64/loongson-3/cop2-ex.c index ea13764..ea13764 100644 --- a/arch/mips/loongson/loongson-3/cop2-ex.c +++ b/arch/mips/loongson64/loongson-3/cop2-ex.c diff --git a/arch/mips/loongson/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c index 5c21cd3..5c21cd3 100644 --- a/arch/mips/loongson/loongson-3/hpet.c +++ b/arch/mips/loongson64/loongson-3/hpet.c diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson64/loongson-3/irq.c index 0f75b6b..0f75b6b 100644 --- a/arch/mips/loongson/loongson-3/irq.c +++ b/arch/mips/loongson64/loongson-3/irq.c diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c index 12d14ed..12d14ed 100644 --- a/arch/mips/loongson/loongson-3/numa.c +++ b/arch/mips/loongson64/loongson-3/numa.c diff --git a/arch/mips/loongson/loongson-3/platform.c b/arch/mips/loongson64/loongson-3/platform.c index 25a97cc..25a97cc 100644 --- a/arch/mips/loongson/loongson-3/platform.c +++ b/arch/mips/loongson64/loongson-3/platform.c diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c index 509877c..509877c 100644 --- a/arch/mips/loongson/loongson-3/smp.c +++ b/arch/mips/loongson64/loongson-3/smp.c diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson64/loongson-3/smp.h index d98ff65..d98ff65 100644 --- a/arch/mips/loongson/loongson-3/smp.h +++ b/arch/mips/loongson64/loongson-3/smp.h diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 2e03ab1..7f660dc 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -295,7 +295,7 @@ static void r4k_blast_icache_page_setup(void) static void (*r4k_blast_icache_user_page)(unsigned long addr); -static void __cpuinit r4k_blast_icache_user_page_setup(void) +static void r4k_blast_icache_user_page_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 8d909db..596e184 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -28,8 +28,6 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ #include <asm/r4kcache.h> -extern int r3k_have_wired_reg; /* in r3k-tlb.c */ - /* This sequence is required to ensure icache is disabled immediately */ #define TX39_STOP_STREAMING() \ __asm__ __volatile__( \ @@ -383,8 +381,6 @@ void tx39_cache_init(void) case CPU_TX3927: default: /* TX39/H2,H3 core (writeback 2way-set-associative cache) */ - r3k_have_wired_reg = 1; - write_c0_wired(0); /* set 8 on reset... */ /* board-dependent init code may set WBON */ __flush_cache_vmap = tx39__flush_cache_vmap; diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 609d124..eeaf024 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -262,12 +262,13 @@ static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, plat_unmap_dma_mem(dev, dma_addr, size, direction); } -static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg, +static int mips_dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction, struct dma_attrs *attrs) { int i; + struct scatterlist *sg; - for (i = 0; i < nents; i++, sg++) { + for_each_sg(sglist, sg, nents, i) { if (!plat_device_is_coherent(dev)) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); @@ -291,13 +292,14 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page, return plat_map_dma_mem_page(dev, page) + offset; } -static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, +static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nhwentries, enum dma_data_direction direction, struct dma_attrs *attrs) { int i; + struct scatterlist *sg; - for (i = 0; i < nhwentries; i++, sg++) { + for_each_sg(sglist, sg, nhwentries, i) { if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) __dma_sync(sg_page(sg), sg->offset, sg->length, @@ -324,26 +326,34 @@ static void mips_dma_sync_single_for_device(struct device *dev, } static void mips_dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg, int nelems, enum dma_data_direction direction) + struct scatterlist *sglist, int nelems, + enum dma_data_direction direction) { int i; + struct scatterlist *sg; - if (cpu_needs_post_dma_flush(dev)) - for (i = 0; i < nelems; i++, sg++) + if (cpu_needs_post_dma_flush(dev)) { + for_each_sg(sglist, sg, nelems, i) { __dma_sync(sg_page(sg), sg->offset, sg->length, direction); + } + } plat_post_dma_flush(dev); } static void mips_dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, enum dma_data_direction direction) + struct scatterlist *sglist, int nelems, + enum dma_data_direction direction) { int i; + struct scatterlist *sg; - if (!plat_device_is_coherent(dev)) - for (i = 0; i < nelems; i++, sg++) + if (!plat_device_is_coherent(dev)) { + for_each_sg(sglist, sg, nelems, i) { __dma_sync(sg_page(sg), sg->offset, sg->length, direction); + } + } } int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 4094bbd..2b75b8f 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -36,30 +36,33 @@ extern void build_tlb_refill_handler(void); "nop\n\t" \ ".set pop\n\t") -int r3k_have_wired_reg; /* should be in cpu_data? */ +static int r3k_have_wired_reg; /* Should be in cpu_data? */ /* TLB operations. */ -void local_flush_tlb_all(void) +static void local_flush_tlb_from(int entry) { - unsigned long flags; unsigned long old_ctx; - int entry; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - local_irq_save(flags); old_ctx = read_c0_entryhi() & ASID_MASK; write_c0_entrylo0(0); - entry = r3k_have_wired_reg ? read_c0_wired() : 8; - for (; entry < current_cpu_data.tlbsize; entry++) { + while (entry < current_cpu_data.tlbsize) { write_c0_index(entry << 8); write_c0_entryhi((entry | 0x80000) << 12); - BARRIER; + entry++; /* BARRIER */ tlb_write_indexed(); } write_c0_entryhi(old_ctx); +} + +void local_flush_tlb_all(void) +{ + unsigned long flags; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + local_irq_save(flags); + local_flush_tlb_from(r3k_have_wired_reg ? read_c0_wired() : 8); local_irq_restore(flags); } @@ -277,7 +280,13 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, void tlb_init(void) { - local_flush_tlb_all(); - + switch (current_cpu_type()) { + case CPU_TX3922: + case CPU_TX3927: + r3k_have_wired_reg = 1; + write_c0_wired(0); /* Set to 8 on reset... */ + break; + } + local_flush_tlb_from(0); build_tlb_refill_handler(); } diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 08318ec..5037d58 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -423,7 +423,7 @@ int __init has_transparent_hugepage(void) * lifetime of the system */ -int temp_tlb_entry __cpuinitdata; +int temp_tlb_entry; __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 97c8702..323d1d3 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -35,7 +35,7 @@ #include <asm/uasm.h> #include <asm/setup.h> -static int __cpuinitdata mips_xpa_disabled; +static int mips_xpa_disabled; static int __init xpa_disable(char *s) { @@ -1608,23 +1608,32 @@ build_pte_present(u32 **p, struct uasm_reloc **r, int pte, int ptr, int scratch, enum label_id lid) { int t = scratch >= 0 ? scratch : pte; + int cur = pte; if (cpu_has_rixi) { if (use_bbit_insns()) { uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid); uasm_i_nop(p); } else { - uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 1); + if (_PAGE_PRESENT_SHIFT) { + uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT); + cur = t; + } + uasm_i_andi(p, t, cur, 1); uasm_il_beqz(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ iPTE_LW(p, pte, ptr); } } else { - uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 3); - uasm_i_xori(p, t, t, 3); + if (_PAGE_PRESENT_SHIFT) { + uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT); + cur = t; + } + uasm_i_andi(p, t, cur, + (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, + (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ @@ -1652,10 +1661,16 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, enum label_id lid) { int t = scratch >= 0 ? scratch : pte; + int cur = pte; - uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); - uasm_i_andi(p, t, t, 5); - uasm_i_xori(p, t, t, 5); + if (_PAGE_PRESENT_SHIFT) { + uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT); + cur = t; + } + uasm_i_andi(p, t, cur, + (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); + uasm_i_xori(p, t, t, + (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 6510ace..ea35587 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -5,7 +5,7 @@ # Copyright (C) 2008 Wind River Systems, Inc. # written by Ralf Baechle <ralf@linux-mips.org> # -obj-y := malta-display.o malta-init.o \ +obj-y := malta-display.o malta-dt.o malta-init.o \ malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o diff --git a/arch/mips/mti-malta/malta-dt.c b/arch/mips/mti-malta/malta-dt.c new file mode 100644 index 0000000..47a2288 --- /dev/null +++ b/arch/mips/mti-malta/malta-dt.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/clk-provider.h> +#include <linux/init.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> + +void __init device_tree_init(void) +{ + unflatten_and_copy_device_tree(); +} + +static const struct of_device_id bus_ids[] __initconst = { + { .compatible = "simple-bus", }, + { .compatible = "isa", }, + {}, +}; + +static int __init publish_devices(void) +{ + if (!of_have_populated_dt()) + return 0; + + return of_platform_bus_probe(NULL, bus_ids, NULL); +} +device_initcall(publish_devices); diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c index db7c9e5..9d1e7f5 100644 --- a/arch/mips/mti-malta/malta-setup.c +++ b/arch/mips/mti-malta/malta-setup.c @@ -21,6 +21,7 @@ #include <linux/sched.h> #include <linux/ioport.h> #include <linux/irq.h> +#include <linux/of_fdt.h> #include <linux/pci.h> #include <linux/screen_info.h> #include <linux/time.h> @@ -31,6 +32,7 @@ #include <asm/mips-boards/malta.h> #include <asm/mips-boards/maltaint.h> #include <asm/dma.h> +#include <asm/prom.h> #include <asm/traps.h> #ifdef CONFIG_VT #include <linux/console.h> @@ -249,6 +251,8 @@ void __init plat_mem_setup(void) { unsigned int i; + __dt_setup_arch(__dtb_start); + if (config_enabled(CONFIG_EVA)) /* EVA has already been configured in mach-malta/kernel-init.h */ pr_info("Enhanced Virtual Addressing (EVA) activated\n"); diff --git a/arch/mips/net/Makefile b/arch/mips/net/Makefile index ae74b3a..8c27714 100644 --- a/arch/mips/net/Makefile +++ b/arch/mips/net/Makefile @@ -1,3 +1,3 @@ # MIPS networking code -obj-$(CONFIG_BPF_JIT) += bpf_jit.o +obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_asm.o diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index e23fdf2..0c4a133 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -20,6 +20,7 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/types.h> +#include <asm/asm.h> #include <asm/bitops.h> #include <asm/cacheflush.h> #include <asm/cpu-features.h> @@ -28,14 +29,14 @@ #include "bpf_jit.h" /* ABI - * - * s0 1st scratch register - * s1 2nd scratch register - * s2 offset register - * s3 BPF register A - * s4 BPF register X - * s5 *skb - * s6 *scratch memory + * r_skb_hl SKB header length + * r_data SKB data pointer + * r_off Offset + * r_A BPF register A + * r_X BPF register X + * r_skb *skb + * r_M *scratch memory + * r_skb_len SKB length * * On entry (*bpf_func)(*skb, *filter) * a0 = MIPS_R_A0 = skb; @@ -63,44 +64,8 @@ * ---------------------------------------------------- */ -#define RSIZE (sizeof(unsigned long)) #define ptr typeof(unsigned long) -/* ABI specific return values */ -#ifdef CONFIG_32BIT /* O32 */ -#ifdef CONFIG_CPU_LITTLE_ENDIAN -#define r_err MIPS_R_V1 -#define r_val MIPS_R_V0 -#else /* CONFIG_CPU_LITTLE_ENDIAN */ -#define r_err MIPS_R_V0 -#define r_val MIPS_R_V1 -#endif -#else /* N64 */ -#define r_err MIPS_R_V0 -#define r_val MIPS_R_V0 -#endif - -#define r_ret MIPS_R_V0 - -/* - * Use 2 scratch registers to avoid pipeline interlocks. - * There is no overhead during epilogue and prologue since - * any of the $s0-$s6 registers will only be preserved if - * they are going to actually be used. - */ -#define r_s0 MIPS_R_S0 /* scratch reg 1 */ -#define r_s1 MIPS_R_S1 /* scratch reg 2 */ -#define r_off MIPS_R_S2 -#define r_A MIPS_R_S3 -#define r_X MIPS_R_S4 -#define r_skb MIPS_R_S5 -#define r_M MIPS_R_S6 -#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */ -#define r_tmp MIPS_R_T7 /* No need to preserve this */ -#define r_zero MIPS_R_ZERO -#define r_sp MIPS_R_SP -#define r_ra MIPS_R_RA - #define SCRATCH_OFF(k) (4 * (k)) /* JIT flags */ @@ -108,13 +73,13 @@ #define SEEN_SREG_SFT (BPF_MEMWORDS + 1) #define SEEN_SREG_BASE (1 << SEEN_SREG_SFT) #define SEEN_SREG(x) (SEEN_SREG_BASE << (x)) -#define SEEN_S0 SEEN_SREG(0) -#define SEEN_S1 SEEN_SREG(1) #define SEEN_OFF SEEN_SREG(2) #define SEEN_A SEEN_SREG(3) #define SEEN_X SEEN_SREG(4) #define SEEN_SKB SEEN_SREG(5) #define SEEN_MEM SEEN_SREG(6) +/* SEEN_SK_DATA also implies skb_hl an skb_len */ +#define SEEN_SKB_DATA (SEEN_SREG(7) | SEEN_SREG(1) | SEEN_SREG(0)) /* Arguments used by JIT */ #define ARGS_USED_BY_JIT 2 /* only applicable to 64-bit */ @@ -577,27 +542,13 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset) /* Adjust the stack pointer */ emit_stack_offset(-align_sp(offset), ctx); - if (ctx->flags & SEEN_CALL) { - /* Argument save area */ - if (config_enabled(CONFIG_64BIT)) - /* Bottom of current frame */ - real_off = align_sp(offset) - RSIZE; - else - /* Top of previous frame */ - real_off = align_sp(offset) + RSIZE; - emit_store_stack_reg(MIPS_R_A0, r_sp, real_off, ctx); - emit_store_stack_reg(MIPS_R_A1, r_sp, real_off + RSIZE, ctx); - - real_off = 0; - } - tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT; /* sflags is essentially a bitmap */ while (tmp_flags) { if ((sflags >> i) & 0x1) { emit_store_stack_reg(MIPS_R_S0 + i, r_sp, real_off, ctx); - real_off += RSIZE; + real_off += SZREG; } i++; tmp_flags >>= 1; @@ -606,13 +557,13 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset) /* save return address */ if (ctx->flags & SEEN_CALL) { emit_store_stack_reg(r_ra, r_sp, real_off, ctx); - real_off += RSIZE; + real_off += SZREG; } /* Setup r_M leaving the alignment gap if necessary */ if (ctx->flags & SEEN_MEM) { - if (real_off % (RSIZE * 2)) - real_off += RSIZE; + if (real_off % (SZREG * 2)) + real_off += SZREG; emit_long_instr(ctx, ADDIU, r_M, r_sp, real_off); } } @@ -623,19 +574,6 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx, int i, real_off = 0; u32 sflags, tmp_flags; - if (ctx->flags & SEEN_CALL) { - if (config_enabled(CONFIG_64BIT)) - /* Bottom of current frame */ - real_off = align_sp(offset) - RSIZE; - else - /* Top of previous frame */ - real_off = align_sp(offset) + RSIZE; - emit_load_stack_reg(MIPS_R_A0, r_sp, real_off, ctx); - emit_load_stack_reg(MIPS_R_A1, r_sp, real_off + RSIZE, ctx); - - real_off = 0; - } - tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT; /* sflags is a bitmap */ i = 0; @@ -643,7 +581,7 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx, if ((sflags >> i) & 0x1) { emit_load_stack_reg(MIPS_R_S0 + i, r_sp, real_off, ctx); - real_off += RSIZE; + real_off += SZREG; } i++; tmp_flags >>= 1; @@ -663,23 +601,13 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx) /* How may s* regs do we need to preserved? */ - sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * RSIZE; + sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * SZREG; if (ctx->flags & SEEN_MEM) sp_off += 4 * BPF_MEMWORDS; /* BPF_MEMWORDS are 32-bit */ if (ctx->flags & SEEN_CALL) - /* - * The JIT code make calls to external functions using 2 - * arguments. Therefore, for o32 we don't need to allocate - * space because we don't care if the argumetns are lost - * across calls. We do need however to preserve incoming - * arguments but the space is already allocated for us by - * the caller. On the other hand, for n64, we need to allocate - * this space ourselves. We need to preserve $ra as well. - */ - sp_off += config_enabled(CONFIG_64BIT) ? - (ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE; + sp_off += SZREG; /* Space for our ra register */ return sp_off; } @@ -696,6 +624,19 @@ static void build_prologue(struct jit_ctx *ctx) if (ctx->flags & SEEN_SKB) emit_reg_move(r_skb, MIPS_R_A0, ctx); + if (ctx->flags & SEEN_SKB_DATA) { + /* Load packet length */ + emit_load(r_skb_len, r_skb, offsetof(struct sk_buff, len), + ctx); + emit_load(r_tmp, r_skb, offsetof(struct sk_buff, data_len), + ctx); + /* Load the data pointer */ + emit_load_ptr(r_skb_data, r_skb, + offsetof(struct sk_buff, data), ctx); + /* Load the header length */ + emit_subu(r_skb_hl, r_skb_len, r_tmp, ctx); + } + if (ctx->flags & SEEN_X) emit_jit_reg_move(r_X, r_zero, ctx); @@ -718,43 +659,17 @@ static void build_epilogue(struct jit_ctx *ctx) emit_nop(ctx); } -static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) -{ - u8 ret; - int err; - - err = skb_copy_bits(skb, offset, &ret, 1); - - return (u64)err << 32 | ret; -} - -static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) -{ - u16 ret; - int err; - - err = skb_copy_bits(skb, offset, &ret, 2); - - return (u64)err << 32 | ntohs(ret); -} - -static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) -{ - u32 ret; - int err; - - err = skb_copy_bits(skb, offset, &ret, 4); - - return (u64)err << 32 | ntohl(ret); -} +#define CHOOSE_LOAD_FUNC(K, func) \ + ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative : func) : \ + func##_positive) static int build_body(struct jit_ctx *ctx) { - void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w}; const struct bpf_prog *prog = ctx->skf; const struct sock_filter *inst; - unsigned int i, off, load_order, condt; + unsigned int i, off, condt; u32 k, b_off __maybe_unused; + u8 (*sk_load_func)(unsigned long *skb, int offset); for (i = 0; i < prog->len; i++) { u16 code; @@ -788,71 +703,46 @@ static int build_body(struct jit_ctx *ctx) break; case BPF_LD | BPF_W | BPF_ABS: /* A <- P[k:4] */ - load_order = 2; + sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_word); goto load; case BPF_LD | BPF_H | BPF_ABS: /* A <- P[k:2] */ - load_order = 1; + sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_half); goto load; case BPF_LD | BPF_B | BPF_ABS: /* A <- P[k:1] */ - load_order = 0; + sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_byte); load: - /* the interpreter will deal with the negative K */ - if ((int)k < 0) - return -ENOTSUPP; - emit_load_imm(r_off, k, ctx); load_common: - /* - * We may got here from the indirect loads so - * return if offset is negative. - */ - emit_slt(r_s0, r_off, r_zero, ctx); - emit_bcond(MIPS_COND_NE, r_s0, r_zero, - b_imm(prog->len, ctx), ctx); - emit_reg_move(r_ret, r_zero, ctx); - - ctx->flags |= SEEN_CALL | SEEN_OFF | SEEN_S0 | - SEEN_SKB | SEEN_A; + ctx->flags |= SEEN_CALL | SEEN_OFF | + SEEN_SKB | SEEN_A | SEEN_SKB_DATA; - emit_load_func(r_s0, (ptr)load_func[load_order], - ctx); + emit_load_func(r_s0, (ptr)sk_load_func, ctx); emit_reg_move(MIPS_R_A0, r_skb, ctx); emit_jalr(MIPS_R_RA, r_s0, ctx); /* Load second argument to delay slot */ emit_reg_move(MIPS_R_A1, r_off, ctx); /* Check the error value */ - if (config_enabled(CONFIG_64BIT)) { - /* Get error code from the top 32-bits */ - emit_dsrl32(r_s0, r_val, 0, ctx); - /* Branch to 3 instructions ahead */ - emit_bcond(MIPS_COND_NE, r_s0, r_zero, 3 << 2, - ctx); - } else { - /* Branch to 3 instructions ahead */ - emit_bcond(MIPS_COND_NE, r_err, r_zero, 3 << 2, - ctx); - } - emit_nop(ctx); - /* We are good */ - emit_b(b_imm(i + 1, ctx), ctx); - emit_jit_reg_move(r_A, r_val, ctx); + emit_bcond(MIPS_COND_EQ, r_ret, 0, b_imm(i + 1, ctx), + ctx); + /* Load return register on DS for failures */ + emit_reg_move(r_ret, r_zero, ctx); /* Return with error */ emit_b(b_imm(prog->len, ctx), ctx); - emit_reg_move(r_ret, r_zero, ctx); + emit_nop(ctx); break; case BPF_LD | BPF_W | BPF_IND: /* A <- P[X + k:4] */ - load_order = 2; + sk_load_func = sk_load_word; goto load_ind; case BPF_LD | BPF_H | BPF_IND: /* A <- P[X + k:2] */ - load_order = 1; + sk_load_func = sk_load_half; goto load_ind; case BPF_LD | BPF_B | BPF_IND: /* A <- P[X + k:1] */ - load_order = 0; + sk_load_func = sk_load_byte; load_ind: ctx->flags |= SEEN_OFF | SEEN_X; emit_addiu(r_off, r_X, k, ctx); @@ -874,14 +764,10 @@ load_ind: emit_load(r_X, r_skb, off, ctx); break; case BPF_LDX | BPF_B | BPF_MSH: - /* the interpreter will deal with the negative K */ - if ((int)k < 0) - return -ENOTSUPP; - /* X <- 4 * (P[k:1] & 0xf) */ - ctx->flags |= SEEN_X | SEEN_CALL | SEEN_S0 | SEEN_SKB; + ctx->flags |= SEEN_X | SEEN_CALL | SEEN_SKB; /* Load offset to a1 */ - emit_load_func(r_s0, (ptr)jit_get_skb_b, ctx); + emit_load_func(r_s0, (ptr)sk_load_byte, ctx); /* * This may emit two instructions so it may not fit * in the delay slot. So use a0 in the delay slot. @@ -890,25 +776,15 @@ load_ind: emit_jalr(MIPS_R_RA, r_s0, ctx); emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */ /* Check the error value */ - if (config_enabled(CONFIG_64BIT)) { - /* Top 32-bits of $v0 on 64-bit */ - emit_dsrl32(r_s0, r_val, 0, ctx); - emit_bcond(MIPS_COND_NE, r_s0, r_zero, - 3 << 2, ctx); - } else { - emit_bcond(MIPS_COND_NE, r_err, r_zero, - 3 << 2, ctx); - } - /* No need for delay slot */ + emit_bcond(MIPS_COND_NE, r_ret, 0, + b_imm(prog->len, ctx), ctx); + emit_reg_move(r_ret, r_zero, ctx); /* We are good */ /* X <- P[1:K] & 0xf */ - emit_andi(r_X, r_val, 0xf, ctx); + emit_andi(r_X, r_A, 0xf, ctx); /* X << 2 */ emit_b(b_imm(i + 1, ctx), ctx); emit_sll(r_X, r_X, 2, ctx); /* delay slot */ - /* Return with error */ - emit_b(b_imm(prog->len, ctx), ctx); - emit_load_imm(r_ret, 0, ctx); /* delay slot */ break; case BPF_ST: /* M[k] <- A */ @@ -943,7 +819,7 @@ load_ind: case BPF_ALU | BPF_MUL | BPF_K: /* A *= K */ /* Load K to scratch register before MUL */ - ctx->flags |= SEEN_A | SEEN_S0; + ctx->flags |= SEEN_A; emit_load_imm(r_s0, k, ctx); emit_mul(r_A, r_A, r_s0, ctx); break; @@ -961,7 +837,7 @@ load_ind: emit_srl(r_A, r_A, k, ctx); break; } - ctx->flags |= SEEN_A | SEEN_S0; + ctx->flags |= SEEN_A; emit_load_imm(r_s0, k, ctx); emit_div(r_A, r_s0, ctx); break; @@ -971,7 +847,7 @@ load_ind: ctx->flags |= SEEN_A; emit_jit_reg_move(r_A, r_zero, ctx); } else { - ctx->flags |= SEEN_A | SEEN_S0; + ctx->flags |= SEEN_A; emit_load_imm(r_s0, k, ctx); emit_mod(r_A, r_s0, ctx); } @@ -982,7 +858,7 @@ load_ind: /* Check if r_X is zero */ emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_imm(prog->len, ctx), ctx); - emit_load_imm(r_val, 0, ctx); /* delay slot */ + emit_load_imm(r_ret, 0, ctx); /* delay slot */ emit_div(r_A, r_X, ctx); break; case BPF_ALU | BPF_MOD | BPF_X: @@ -991,7 +867,7 @@ load_ind: /* Check if r_X is zero */ emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_imm(prog->len, ctx), ctx); - emit_load_imm(r_val, 0, ctx); /* delay slot */ + emit_load_imm(r_ret, 0, ctx); /* delay slot */ emit_mod(r_A, r_X, ctx); break; case BPF_ALU | BPF_OR | BPF_K: @@ -1085,10 +961,10 @@ jmp_cmp: if ((condt & MIPS_COND_GE) || (condt & MIPS_COND_GT)) { if (condt & MIPS_COND_K) { /* K */ - ctx->flags |= SEEN_S0 | SEEN_A; + ctx->flags |= SEEN_A; emit_sltiu(r_s0, r_A, k, ctx); } else { /* X */ - ctx->flags |= SEEN_S0 | SEEN_A | + ctx->flags |= SEEN_A | SEEN_X; emit_sltu(r_s0, r_A, r_X, ctx); } @@ -1100,7 +976,7 @@ jmp_cmp: /* A > (K|X) ? scratch = 0 */ if (condt & MIPS_COND_GT) { /* Checking for equality */ - ctx->flags |= SEEN_S0 | SEEN_A | SEEN_X; + ctx->flags |= SEEN_A | SEEN_X; if (condt & MIPS_COND_K) emit_load_imm(r_s0, k, ctx); else @@ -1123,7 +999,7 @@ jmp_cmp: } else { /* A == K|X */ if (condt & MIPS_COND_K) { /* K */ - ctx->flags |= SEEN_S0 | SEEN_A; + ctx->flags |= SEEN_A; emit_load_imm(r_s0, k, ctx); /* jump true */ b_off = b_imm(i + inst->jt + 1, ctx); @@ -1153,7 +1029,7 @@ jmp_cmp: } break; case BPF_JMP | BPF_JSET | BPF_K: - ctx->flags |= SEEN_S0 | SEEN_S1 | SEEN_A; + ctx->flags |= SEEN_A; /* pc += (A & K) ? pc -> jt : pc -> jf */ emit_load_imm(r_s1, k, ctx); emit_and(r_s0, r_A, r_s1, ctx); @@ -1167,7 +1043,7 @@ jmp_cmp: emit_nop(ctx); break; case BPF_JMP | BPF_JSET | BPF_X: - ctx->flags |= SEEN_S0 | SEEN_X | SEEN_A; + ctx->flags |= SEEN_X | SEEN_A; /* pc += (A & X) ? pc -> jt : pc -> jf */ emit_and(r_s0, r_A, r_X, ctx); /* jump true */ @@ -1251,7 +1127,7 @@ jmp_cmp: break; case BPF_ANC | SKF_AD_IFINDEX: /* A = skb->dev->ifindex */ - ctx->flags |= SEEN_SKB | SEEN_A | SEEN_S0; + ctx->flags |= SEEN_SKB | SEEN_A; off = offsetof(struct sk_buff, dev); /* Load *dev pointer */ emit_load_ptr(r_s0, r_skb, off, ctx); @@ -1278,7 +1154,7 @@ jmp_cmp: break; case BPF_ANC | SKF_AD_VLAN_TAG: case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT: - ctx->flags |= SEEN_SKB | SEEN_S0 | SEEN_A; + ctx->flags |= SEEN_SKB | SEEN_A; BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2); off = offsetof(struct sk_buff, vlan_tci); diff --git a/arch/mips/net/bpf_jit.h b/arch/mips/net/bpf_jit.h index 3a5751b..8f9f548 100644 --- a/arch/mips/net/bpf_jit.h +++ b/arch/mips/net/bpf_jit.h @@ -15,9 +15,10 @@ /* Registers used by JIT */ #define MIPS_R_ZERO 0 #define MIPS_R_V0 2 -#define MIPS_R_V1 3 #define MIPS_R_A0 4 #define MIPS_R_A1 5 +#define MIPS_R_T4 12 +#define MIPS_R_T5 13 #define MIPS_R_T6 14 #define MIPS_R_T7 15 #define MIPS_R_S0 16 @@ -41,4 +42,43 @@ #define MIPS_COND_X (0x1 << 5) #define MIPS_COND_K (0x1 << 6) +#define r_ret MIPS_R_V0 + +/* + * Use 2 scratch registers to avoid pipeline interlocks. + * There is no overhead during epilogue and prologue since + * any of the $s0-$s6 registers will only be preserved if + * they are going to actually be used. + */ +#define r_skb_hl MIPS_R_S0 /* skb header length */ +#define r_skb_data MIPS_R_S1 /* skb actual data */ +#define r_off MIPS_R_S2 +#define r_A MIPS_R_S3 +#define r_X MIPS_R_S4 +#define r_skb MIPS_R_S5 +#define r_M MIPS_R_S6 +#define r_skb_len MIPS_R_S7 +#define r_s0 MIPS_R_T4 /* scratch reg 1 */ +#define r_s1 MIPS_R_T5 /* scratch reg 2 */ +#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */ +#define r_tmp MIPS_R_T7 /* No need to preserve this */ +#define r_zero MIPS_R_ZERO +#define r_sp MIPS_R_SP +#define r_ra MIPS_R_RA + +#ifndef __ASSEMBLY__ + +/* Declare ASM helpers */ + +#define DECLARE_LOAD_FUNC(func) \ + extern u8 func(unsigned long *skb, int offset); \ + extern u8 func##_negative(unsigned long *skb, int offset); \ + extern u8 func##_positive(unsigned long *skb, int offset) + +DECLARE_LOAD_FUNC(sk_load_word); +DECLARE_LOAD_FUNC(sk_load_half); +DECLARE_LOAD_FUNC(sk_load_byte); + +#endif + #endif /* BPF_JIT_MIPS_OP_H */ diff --git a/arch/mips/net/bpf_jit_asm.S b/arch/mips/net/bpf_jit_asm.S new file mode 100644 index 0000000..e927260 --- /dev/null +++ b/arch/mips/net/bpf_jit_asm.S @@ -0,0 +1,238 @@ +/* + * bpf_jib_asm.S: Packet/header access helper functions for MIPS/MIPS64 BPF + * compiler. + * + * Copyright (C) 2015 Imagination Technologies Ltd. + * Author: Markos Chandras <markos.chandras@imgtec.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + */ + +#include <asm/asm.h> +#include <asm/regdef.h> +#include "bpf_jit.h" + +/* ABI + * + * r_skb_hl skb header length + * r_skb_data skb data + * r_off(a1) offset register + * r_A BPF register A + * r_X PF register X + * r_skb(a0) *skb + * r_M *scratch memory + * r_skb_le skb length + * r_s0 Scratch register 0 + * r_s1 Scratch register 1 + * + * On entry: + * a0: *skb + * a1: offset (imm or imm + X) + * + * All non-BPF-ABI registers are free for use. On return, we only + * care about r_ret. The BPF-ABI registers are assumed to remain + * unmodified during the entire filter operation. + */ + +#define skb a0 +#define offset a1 +#define SKF_LL_OFF (-0x200000) /* Can't include linux/filter.h in assembly */ + + /* We know better :) so prevent assembler reordering etc */ + .set noreorder + +#define is_offset_negative(TYPE) \ + /* If offset is negative we have more work to do */ \ + slti t0, offset, 0; \ + bgtz t0, bpf_slow_path_##TYPE##_neg; \ + /* Be careful what follows in DS. */ + +#define is_offset_in_header(SIZE, TYPE) \ + /* Reading from header? */ \ + addiu $r_s0, $r_skb_hl, -SIZE; \ + slt t0, $r_s0, offset; \ + bgtz t0, bpf_slow_path_##TYPE; \ + +LEAF(sk_load_word) + is_offset_negative(word) + .globl sk_load_word_positive +sk_load_word_positive: + is_offset_in_header(4, word) + /* Offset within header boundaries */ + PTR_ADDU t1, $r_skb_data, offset + lw $r_A, 0(t1) +#ifdef CONFIG_CPU_LITTLE_ENDIAN + wsbh t0, $r_A + rotr $r_A, t0, 16 +#endif + jr $r_ra + move $r_ret, zero + END(sk_load_word) + +LEAF(sk_load_half) + is_offset_negative(half) + .globl sk_load_half_positive +sk_load_half_positive: + is_offset_in_header(2, half) + /* Offset within header boundaries */ + PTR_ADDU t1, $r_skb_data, offset + lh $r_A, 0(t1) +#ifdef CONFIG_CPU_LITTLE_ENDIAN + wsbh t0, $r_A + seh $r_A, t0 +#endif + jr $r_ra + move $r_ret, zero + END(sk_load_half) + +LEAF(sk_load_byte) + is_offset_negative(byte) + .globl sk_load_byte_positive +sk_load_byte_positive: + is_offset_in_header(1, byte) + /* Offset within header boundaries */ + PTR_ADDU t1, $r_skb_data, offset + lb $r_A, 0(t1) + jr $r_ra + move $r_ret, zero + END(sk_load_byte) + +/* + * call skb_copy_bits: + * (prototype in linux/skbuff.h) + * + * int skb_copy_bits(sk_buff *skb, int offset, void *to, int len) + * + * o32 mandates we leave 4 spaces for argument registers in case + * the callee needs to use them. Even though we don't care about + * the argument registers ourselves, we need to allocate that space + * to remain ABI compliant since the callee may want to use that space. + * We also allocate 2 more spaces for $r_ra and our return register (*to). + * + * n64 is a bit different. The *caller* will allocate the space to preserve + * the arguments. So in 64-bit kernels, we allocate the 4-arg space for no + * good reason but it does not matter that much really. + * + * (void *to) is returned in r_s0 + * + */ +#define bpf_slow_path_common(SIZE) \ + /* Quick check. Are we within reasonable boundaries? */ \ + LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \ + sltu $r_s0, offset, $r_s1; \ + beqz $r_s0, fault; \ + /* Load 4th argument in DS */ \ + LONG_ADDIU a3, zero, SIZE; \ + PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \ + PTR_LA t0, skb_copy_bits; \ + PTR_S $r_ra, (5 * SZREG)($r_sp); \ + /* Assign low slot to a2 */ \ + move a2, $r_sp; \ + jalr t0; \ + /* Reset our destination slot (DS but it's ok) */ \ + INT_S zero, (4 * SZREG)($r_sp); \ + /* \ + * skb_copy_bits returns 0 on success and -EFAULT \ + * on error. Our data live in a2. Do not bother with \ + * our data if an error has been returned. \ + */ \ + /* Restore our frame */ \ + PTR_L $r_ra, (5 * SZREG)($r_sp); \ + INT_L $r_s0, (4 * SZREG)($r_sp); \ + bltz v0, fault; \ + PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \ + move $r_ret, zero; \ + +NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp) + bpf_slow_path_common(4) +#ifdef CONFIG_CPU_LITTLE_ENDIAN + wsbh t0, $r_s0 + jr $r_ra + rotr $r_A, t0, 16 +#endif + jr $r_ra + move $r_A, $r_s0 + + END(bpf_slow_path_word) + +NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp) + bpf_slow_path_common(2) +#ifdef CONFIG_CPU_LITTLE_ENDIAN + jr $r_ra + wsbh $r_A, $r_s0 +#endif + jr $r_ra + move $r_A, $r_s0 + + END(bpf_slow_path_half) + +NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp) + bpf_slow_path_common(1) + jr $r_ra + move $r_A, $r_s0 + + END(bpf_slow_path_byte) + +/* + * Negative entry points + */ + .macro bpf_is_end_of_data + li t0, SKF_LL_OFF + /* Reading link layer data? */ + slt t1, offset, t0 + bgtz t1, fault + /* Be careful what follows in DS. */ + .endm +/* + * call skb_copy_bits: + * (prototype in linux/filter.h) + * + * void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, + * int k, unsigned int size) + * + * see above (bpf_slow_path_common) for ABI restrictions + */ +#define bpf_negative_common(SIZE) \ + PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \ + PTR_LA t0, bpf_internal_load_pointer_neg_helper; \ + PTR_S $r_ra, (5 * SZREG)($r_sp); \ + jalr t0; \ + li a2, SIZE; \ + PTR_L $r_ra, (5 * SZREG)($r_sp); \ + /* Check return pointer */ \ + beqz v0, fault; \ + PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \ + /* Preserve our pointer */ \ + move $r_s0, v0; \ + /* Set return value */ \ + move $r_ret, zero; \ + +bpf_slow_path_word_neg: + bpf_is_end_of_data +NESTED(sk_load_word_negative, (6 * SZREG), $r_sp) + bpf_negative_common(4) + jr $r_ra + lw $r_A, 0($r_s0) + END(sk_load_word_negative) + +bpf_slow_path_half_neg: + bpf_is_end_of_data +NESTED(sk_load_half_negative, (6 * SZREG), $r_sp) + bpf_negative_common(2) + jr $r_ra + lhu $r_A, 0($r_s0) + END(sk_load_half_negative) + +bpf_slow_path_byte_neg: + bpf_is_end_of_data +NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp) + bpf_negative_common(1) + jr $r_ra + lbu $r_A, 0($r_s0) + END(sk_load_byte_negative) + +fault: + jr $r_ra + addiu $r_ret, zero, 1 diff --git a/arch/mips/netlogic/xlr/platform-flash.c b/arch/mips/netlogic/xlr/platform-flash.c index 6d3c727..f03131f 100644 --- a/arch/mips/netlogic/xlr/platform-flash.c +++ b/arch/mips/netlogic/xlr/platform-flash.c @@ -78,8 +78,6 @@ static struct platform_device xlr_nor_dev = { .resource = xlr_nor_res, }; -const char *xlr_part_probes[] = { "cmdlinepart", NULL }; - /* * Use "gen_nand" driver for NAND flash * @@ -111,7 +109,6 @@ struct platform_nand_data xlr_nand_data = { .nr_partitions = ARRAY_SIZE(xlr_nand_parts), .chip_delay = 50, .partitions = xlr_nand_parts, - .part_probe_types = xlr_part_probes, }, .ctrl = { .cmd_ctrl = xlr_nand_ctrl, diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c index 07a1822..dadb303 100644 --- a/arch/mips/pci/pci-ar2315.c +++ b/arch/mips/pci/pci-ar2315.c @@ -320,7 +320,7 @@ static int ar2315_pci_host_setup(struct ar2315_pci_ctrl *apc) static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc) { - struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq); + struct ar2315_pci_ctrl *apc = irq_desc_get_handler_data(desc); u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) & ar2315_pci_reg_read(apc, AR2315_PCI_IMR); unsigned pci_irq = 0; diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index 9e62ad3..283157f 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c @@ -232,7 +232,7 @@ static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) void __iomem *base = ath79_reset_base; u32 pending; - apc = irq_get_handler_data(irq); + apc = irq_desc_get_handler_data(desc); pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); @@ -318,23 +318,13 @@ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) static void ar71xx_pci_reset(void) { - void __iomem *ddr_base = ath79_ddr_base; - ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); mdelay(100); ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); mdelay(100); - __raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0); - __raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1); - __raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2); - __raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3); - __raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4); - __raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5); - __raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6); - __raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7); - + ath79_ddr_set_pci_windows(); mdelay(100); } diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index a1b7d2a..0af362b 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -231,7 +231,7 @@ static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) void __iomem *base; u32 pending; - apc = irq_get_handler_data(irq); + apc = irq_desc_get_handler_data(desc); base = apc->ctrl_base; pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c index ec9be8c..80fafe6 100644 --- a/arch/mips/pci/pci-rt3883.c +++ b/arch/mips/pci/pci-rt3883.c @@ -134,7 +134,7 @@ static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) struct rt3883_pci_controller *rpc; u32 pending; - rpc = irq_get_handler_data(irq); + rpc = irq_desc_get_handler_data(desc); pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) & rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index 7cf91b9..da301e0 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c @@ -100,7 +100,7 @@ static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc) u32 pending = rt_intc_r32(INTC_REG_STATUS0); if (pending) { - struct irq_domain *domain = irq_get_handler_data(irq); + struct irq_domain *domain = irq_desc_get_handler_data(desc); generic_handle_irq(irq_find_mapping(domain, __ffs(pending))); } else { spurious_interrupt(); diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index da8f681..ab4affa 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -2,9 +2,9 @@ # Makefile for the IP27 specific kernel interface routines under Linux. # -obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \ - ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o ip27-hubio.o \ - ip27-xtalk.o +obj-y := ip27-berr.o ip27-irq.o ip27-irqno.o ip27-init.o ip27-klconfig.o \ + ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o \ + ip27-hubio.o ip27-xtalk.o obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o obj-$(CONFIG_PCI) += ip27-irq-pci.o diff --git a/arch/mips/sgi-ip27/ip27-irqno.c b/arch/mips/sgi-ip27/ip27-irqno.c new file mode 100644 index 0000000..957ab58 --- /dev/null +++ b/arch/mips/sgi-ip27/ip27-irqno.c @@ -0,0 +1,48 @@ +/* + * 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 <linux/init.h> +#include <linux/irq.h> +#include <linux/types.h> + +#include <asm/barrier.h> + +static DECLARE_BITMAP(irq_map, NR_IRQS); + +int allocate_irqno(void) +{ + int irq; + +again: + irq = find_first_zero_bit(irq_map, NR_IRQS); + + if (irq >= NR_IRQS) + return -ENOSPC; + + if (test_and_set_bit(irq, irq_map)) + goto again; + + return irq; +} + +/* + * Allocate the 16 legacy interrupts for i8259 devices. This happens early + * in the kernel initialization so treating allocation failure as BUG() is + * ok. + */ +void __init alloc_legacy_irqno(void) +{ + int i; + + for (i = 0; i <= 16; i++) + BUG_ON(test_and_set_bit(i, irq_map)); +} + +void free_irqno(unsigned int irq) +{ + smp_mb__before_atomic(); + clear_bit(irq, irq_map); + smp_mb__after_atomic(); +} diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig index 5fbd360..a8bb972 100644 --- a/arch/mips/sibyte/Kconfig +++ b/arch/mips/sibyte/Kconfig @@ -3,7 +3,7 @@ config SIBYTE_SB1250 select CEVT_SB1250 select CSRC_SB1250 select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_ENABLE_LDT_IF_PCI select SIBYTE_HAS_ZBUS_PROFILING select SIBYTE_SB1xxx_SOC @@ -13,7 +13,7 @@ config SIBYTE_BCM1120 bool select CEVT_SB1250 select CSRC_SB1250 - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_BCM112X select SIBYTE_HAS_ZBUS_PROFILING select SIBYTE_SB1xxx_SOC @@ -23,7 +23,7 @@ config SIBYTE_BCM1125 select CEVT_SB1250 select CSRC_SB1250 select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_BCM112X select SIBYTE_HAS_ZBUS_PROFILING select SIBYTE_SB1xxx_SOC @@ -33,7 +33,7 @@ config SIBYTE_BCM1125H select CEVT_SB1250 select CSRC_SB1250 select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_BCM112X select SIBYTE_ENABLE_LDT_IF_PCI select SIBYTE_HAS_ZBUS_PROFILING @@ -43,7 +43,7 @@ config SIBYTE_BCM112X bool select CEVT_SB1250 select CSRC_SB1250 - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_SB1xxx_SOC select SIBYTE_HAS_ZBUS_PROFILING @@ -52,7 +52,7 @@ config SIBYTE_BCM1x80 select CEVT_BCM1480 select CSRC_BCM1480 select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_HAS_ZBUS_PROFILING select SIBYTE_SB1xxx_SOC select SYS_SUPPORTS_SMP @@ -62,7 +62,7 @@ config SIBYTE_BCM1x55 select CEVT_BCM1480 select CSRC_BCM1480 select HW_HAS_PCI - select IRQ_CPU + select IRQ_MIPS_CPU select SIBYTE_SB1xxx_SOC select SIBYTE_HAS_ZBUS_PROFILING select SYS_SUPPORTS_SMP @@ -70,7 +70,7 @@ config SIBYTE_BCM1x55 config SIBYTE_SB1xxx_SOC bool select DMA_COHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select SWAP_IO_SPACE select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 6d40bc7..8c337d6 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -8,7 +8,7 @@ config MACH_TX49XX select MACH_TXX9 select CEVT_R4K select CSRC_R4K - select IRQ_CPU + select IRQ_MIPS_CPU select SYS_HAS_CPU_TX49XX select SYS_SUPPORTS_64BIT_KERNEL diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig index c1be6b3..74927b4 100644 --- a/arch/mips/vr41xx/Kconfig +++ b/arch/mips/vr41xx/Kconfig @@ -8,7 +8,7 @@ config CASIO_E55 select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select ISA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -18,7 +18,7 @@ config IBM_WORKPAD select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select ISA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -28,7 +28,7 @@ config TANBAC_TB022X select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select HW_HAS_PCI select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -44,7 +44,7 @@ config VICTOR_MPC30X select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select HW_HAS_PCI select PCI_VR41XX select SYS_SUPPORTS_32BIT_KERNEL @@ -55,7 +55,7 @@ config ZAO_CAPCELLA select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select IRQ_CPU + select IRQ_MIPS_CPU select HW_HAS_PCI select PCI_VR41XX select SYS_SUPPORTS_32BIT_KERNEL diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5b6af6a..8732e4c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o -obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o +obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o @@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ obj-$(CONFIG_ARCH_HIP04) += hisilicon/ obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ obj-$(CONFIG_ARCH_MXC) += imx/ +obj-$(CONFIG_MACH_INGENIC) += ingenic/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile new file mode 100644 index 0000000..cd47b06 --- /dev/null +++ b/drivers/clk/ingenic/Makefile @@ -0,0 +1,3 @@ +obj-y += cgu.o +obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o +obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c new file mode 100644 index 0000000..b936cdd --- /dev/null +++ b/drivers/clk/ingenic/cgu.c @@ -0,0 +1,711 @@ +/* + * Ingenic SoC CGU driver + * + * Copyright (c) 2013-2015 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/bitops.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/delay.h> +#include <linux/math64.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include "cgu.h" + +#define MHZ (1000 * 1000) + +/** + * ingenic_cgu_gate_get() - get the value of clock gate register bit + * @cgu: reference to the CGU whose registers should be read + * @info: info struct describing the gate bit + * + * Retrieves the state of the clock gate bit described by info. The + * caller must hold cgu->lock. + * + * Return: true if the gate bit is set, else false. + */ +static inline bool +ingenic_cgu_gate_get(struct ingenic_cgu *cgu, + const struct ingenic_cgu_gate_info *info) +{ + return readl(cgu->base + info->reg) & BIT(info->bit); +} + +/** + * ingenic_cgu_gate_set() - set the value of clock gate register bit + * @cgu: reference to the CGU whose registers should be modified + * @info: info struct describing the gate bit + * @val: non-zero to gate a clock, otherwise zero + * + * Sets the given gate bit in order to gate or ungate a clock. + * + * The caller must hold cgu->lock. + */ +static inline void +ingenic_cgu_gate_set(struct ingenic_cgu *cgu, + const struct ingenic_cgu_gate_info *info, bool val) +{ + u32 clkgr = readl(cgu->base + info->reg); + + if (val) + clkgr |= BIT(info->bit); + else + clkgr &= ~BIT(info->bit); + + writel(clkgr, cgu->base + info->reg); +} + +/* + * PLL operations + */ + +static unsigned long +ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + const struct ingenic_cgu_pll_info *pll_info; + unsigned m, n, od_enc, od; + bool bypass, enable; + unsigned long flags; + u32 ctl; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + BUG_ON(clk_info->type != CGU_CLK_PLL); + pll_info = &clk_info->pll; + + spin_lock_irqsave(&cgu->lock, flags); + ctl = readl(cgu->base + pll_info->reg); + spin_unlock_irqrestore(&cgu->lock, flags); + + m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0); + m += pll_info->m_offset; + n = (ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0); + n += pll_info->n_offset; + od_enc = ctl >> pll_info->od_shift; + od_enc &= GENMASK(pll_info->od_bits - 1, 0); + bypass = !!(ctl & BIT(pll_info->bypass_bit)); + enable = !!(ctl & BIT(pll_info->enable_bit)); + + if (bypass) + return parent_rate; + + if (!enable) + return 0; + + for (od = 0; od < pll_info->od_max; od++) { + if (pll_info->od_encoding[od] == od_enc) + break; + } + BUG_ON(od == pll_info->od_max); + od++; + + return div_u64((u64)parent_rate * m, n * od); +} + +static unsigned long +ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, + unsigned long rate, unsigned long parent_rate, + unsigned *pm, unsigned *pn, unsigned *pod) +{ + const struct ingenic_cgu_pll_info *pll_info; + unsigned m, n, od; + + pll_info = &clk_info->pll; + od = 1; + + /* + * The frequency after the input divider must be between 10 and 50 MHz. + * The highest divider yields the best resolution. + */ + n = parent_rate / (10 * MHZ); + n = min_t(unsigned, n, 1 << clk_info->pll.n_bits); + n = max_t(unsigned, n, pll_info->n_offset); + + m = (rate / MHZ) * od * n / (parent_rate / MHZ); + m = min_t(unsigned, m, 1 << clk_info->pll.m_bits); + m = max_t(unsigned, m, pll_info->m_offset); + + if (pm) + *pm = m; + if (pn) + *pn = n; + if (pod) + *pod = od; + + return div_u64((u64)parent_rate * m, n * od); +} + +static long +ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long *prate) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + BUG_ON(clk_info->type != CGU_CLK_PLL); + + return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL); +} + +static int +ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long parent_rate) +{ + const unsigned timeout = 100; + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + const struct ingenic_cgu_pll_info *pll_info; + unsigned long rate, flags; + unsigned m, n, od, i; + u32 ctl; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + BUG_ON(clk_info->type != CGU_CLK_PLL); + pll_info = &clk_info->pll; + + rate = ingenic_pll_calc(clk_info, req_rate, parent_rate, + &m, &n, &od); + if (rate != req_rate) + pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n", + clk_info->name, req_rate, rate); + + spin_lock_irqsave(&cgu->lock, flags); + ctl = readl(cgu->base + pll_info->reg); + + ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift); + ctl |= (m - pll_info->m_offset) << pll_info->m_shift; + + ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift); + ctl |= (n - pll_info->n_offset) << pll_info->n_shift; + + ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift); + ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift; + + ctl &= ~BIT(pll_info->bypass_bit); + ctl |= BIT(pll_info->enable_bit); + + writel(ctl, cgu->base + pll_info->reg); + + /* wait for the PLL to stabilise */ + for (i = 0; i < timeout; i++) { + ctl = readl(cgu->base + pll_info->reg); + if (ctl & BIT(pll_info->stable_bit)) + break; + mdelay(1); + } + + spin_unlock_irqrestore(&cgu->lock, flags); + + if (i == timeout) + return -EBUSY; + + return 0; +} + +static const struct clk_ops ingenic_pll_ops = { + .recalc_rate = ingenic_pll_recalc_rate, + .round_rate = ingenic_pll_round_rate, + .set_rate = ingenic_pll_set_rate, +}; + +/* + * Operations for all non-PLL clocks + */ + +static u8 ingenic_clk_get_parent(struct clk_hw *hw) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + u32 reg; + u8 i, hw_idx, idx = 0; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_MUX) { + reg = readl(cgu->base + clk_info->mux.reg); + hw_idx = (reg >> clk_info->mux.shift) & + GENMASK(clk_info->mux.bits - 1, 0); + + /* + * Convert the hardware index to the parent index by skipping + * over any -1's in the parents array. + */ + for (i = 0; i < hw_idx; i++) { + if (clk_info->parents[i] != -1) + idx++; + } + } + + return idx; +} + +static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + unsigned long flags; + u8 curr_idx, hw_idx, num_poss; + u32 reg, mask; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_MUX) { + /* + * Convert the parent index to the hardware index by adding + * 1 for any -1 in the parents array preceding the given + * index. That is, we want the index of idx'th entry in + * clk_info->parents which does not equal -1. + */ + hw_idx = curr_idx = 0; + num_poss = 1 << clk_info->mux.bits; + for (; hw_idx < num_poss; hw_idx++) { + if (clk_info->parents[hw_idx] == -1) + continue; + if (curr_idx == idx) + break; + curr_idx++; + } + + /* idx should always be a valid parent */ + BUG_ON(curr_idx != idx); + + mask = GENMASK(clk_info->mux.bits - 1, 0); + mask <<= clk_info->mux.shift; + + spin_lock_irqsave(&cgu->lock, flags); + + /* write the register */ + reg = readl(cgu->base + clk_info->mux.reg); + reg &= ~mask; + reg |= hw_idx << clk_info->mux.shift; + writel(reg, cgu->base + clk_info->mux.reg); + + spin_unlock_irqrestore(&cgu->lock, flags); + return 0; + } + + return idx ? -EINVAL : 0; +} + +static unsigned long +ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + unsigned long rate = parent_rate; + u32 div_reg, div; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_DIV) { + div_reg = readl(cgu->base + clk_info->div.reg); + div = (div_reg >> clk_info->div.shift) & + GENMASK(clk_info->div.bits - 1, 0); + div += 1; + + rate /= div; + } + + return rate; +} + +static unsigned +ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info, + unsigned long parent_rate, unsigned long req_rate) +{ + unsigned div; + + /* calculate the divide */ + div = DIV_ROUND_UP(parent_rate, req_rate); + + /* and impose hardware constraints */ + div = min_t(unsigned, div, 1 << clk_info->div.bits); + div = max_t(unsigned, div, 1); + + return div; +} + +static long +ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long *parent_rate) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + long rate = *parent_rate; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_DIV) + rate /= ingenic_clk_calc_div(clk_info, *parent_rate, req_rate); + else if (clk_info->type & CGU_CLK_FIXDIV) + rate /= clk_info->fixdiv.div; + + return rate; +} + +static int +ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long parent_rate) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + const unsigned timeout = 100; + unsigned long rate, flags; + unsigned div, i; + u32 reg, mask; + int ret = 0; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_DIV) { + div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate); + rate = parent_rate / div; + + if (rate != req_rate) + return -EINVAL; + + spin_lock_irqsave(&cgu->lock, flags); + reg = readl(cgu->base + clk_info->div.reg); + + /* update the divide */ + mask = GENMASK(clk_info->div.bits - 1, 0); + reg &= ~(mask << clk_info->div.shift); + reg |= (div - 1) << clk_info->div.shift; + + /* clear the stop bit */ + if (clk_info->div.stop_bit != -1) + reg &= ~BIT(clk_info->div.stop_bit); + + /* set the change enable bit */ + if (clk_info->div.ce_bit != -1) + reg |= BIT(clk_info->div.ce_bit); + + /* update the hardware */ + writel(reg, cgu->base + clk_info->div.reg); + + /* wait for the change to take effect */ + if (clk_info->div.busy_bit != -1) { + for (i = 0; i < timeout; i++) { + reg = readl(cgu->base + clk_info->div.reg); + if (!(reg & BIT(clk_info->div.busy_bit))) + break; + mdelay(1); + } + if (i == timeout) + ret = -EBUSY; + } + + spin_unlock_irqrestore(&cgu->lock, flags); + return ret; + } + + return -EINVAL; +} + +static int ingenic_clk_enable(struct clk_hw *hw) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + unsigned long flags; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_GATE) { + /* ungate the clock */ + spin_lock_irqsave(&cgu->lock, flags); + ingenic_cgu_gate_set(cgu, &clk_info->gate, false); + spin_unlock_irqrestore(&cgu->lock, flags); + } + + return 0; +} + +static void ingenic_clk_disable(struct clk_hw *hw) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + unsigned long flags; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_GATE) { + /* gate the clock */ + spin_lock_irqsave(&cgu->lock, flags); + ingenic_cgu_gate_set(cgu, &clk_info->gate, true); + spin_unlock_irqrestore(&cgu->lock, flags); + } +} + +static int ingenic_clk_is_enabled(struct clk_hw *hw) +{ + struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + struct ingenic_cgu *cgu = ingenic_clk->cgu; + const struct ingenic_cgu_clk_info *clk_info; + unsigned long flags; + int enabled = 1; + + clk_info = &cgu->clock_info[ingenic_clk->idx]; + + if (clk_info->type & CGU_CLK_GATE) { + spin_lock_irqsave(&cgu->lock, flags); + enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate); + spin_unlock_irqrestore(&cgu->lock, flags); + } + + return enabled; +} + +static const struct clk_ops ingenic_clk_ops = { + .get_parent = ingenic_clk_get_parent, + .set_parent = ingenic_clk_set_parent, + + .recalc_rate = ingenic_clk_recalc_rate, + .round_rate = ingenic_clk_round_rate, + .set_rate = ingenic_clk_set_rate, + + .enable = ingenic_clk_enable, + .disable = ingenic_clk_disable, + .is_enabled = ingenic_clk_is_enabled, +}; + +/* + * Setup functions. + */ + +static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx) +{ + const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx]; + struct clk_init_data clk_init; + struct ingenic_clk *ingenic_clk = NULL; + struct clk *clk, *parent; + const char *parent_names[4]; + unsigned caps, i, num_possible; + int err = -EINVAL; + + BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names)); + + if (clk_info->type == CGU_CLK_EXT) { + clk = of_clk_get_by_name(cgu->np, clk_info->name); + if (IS_ERR(clk)) { + pr_err("%s: no external clock '%s' provided\n", + __func__, clk_info->name); + err = -ENODEV; + goto out; + } + err = clk_register_clkdev(clk, clk_info->name, NULL); + if (err) { + clk_put(clk); + goto out; + } + cgu->clocks.clks[idx] = clk; + return 0; + } + + if (!clk_info->type) { + pr_err("%s: no clock type specified for '%s'\n", __func__, + clk_info->name); + goto out; + } + + ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL); + if (!ingenic_clk) { + err = -ENOMEM; + goto out; + } + + ingenic_clk->hw.init = &clk_init; + ingenic_clk->cgu = cgu; + ingenic_clk->idx = idx; + + clk_init.name = clk_info->name; + clk_init.flags = 0; + clk_init.parent_names = parent_names; + + caps = clk_info->type; + + if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) { + clk_init.num_parents = 0; + + if (caps & CGU_CLK_MUX) + num_possible = 1 << clk_info->mux.bits; + else + num_possible = ARRAY_SIZE(clk_info->parents); + + for (i = 0; i < num_possible; i++) { + if (clk_info->parents[i] == -1) + continue; + + parent = cgu->clocks.clks[clk_info->parents[i]]; + parent_names[clk_init.num_parents] = + __clk_get_name(parent); + clk_init.num_parents++; + } + + BUG_ON(!clk_init.num_parents); + BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names)); + } else { + BUG_ON(clk_info->parents[0] == -1); + clk_init.num_parents = 1; + parent = cgu->clocks.clks[clk_info->parents[0]]; + parent_names[0] = __clk_get_name(parent); + } + + if (caps & CGU_CLK_CUSTOM) { + clk_init.ops = clk_info->custom.clk_ops; + + caps &= ~CGU_CLK_CUSTOM; + + if (caps) { + pr_err("%s: custom clock may not be combined with type 0x%x\n", + __func__, caps); + goto out; + } + } else if (caps & CGU_CLK_PLL) { + clk_init.ops = &ingenic_pll_ops; + + caps &= ~CGU_CLK_PLL; + + if (caps) { + pr_err("%s: PLL may not be combined with type 0x%x\n", + __func__, caps); + goto out; + } + } else { + clk_init.ops = &ingenic_clk_ops; + } + + /* nothing to do for gates or fixed dividers */ + caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV); + + if (caps & CGU_CLK_MUX) { + if (!(caps & CGU_CLK_MUX_GLITCHFREE)) + clk_init.flags |= CLK_SET_PARENT_GATE; + + caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE); + } + + if (caps & CGU_CLK_DIV) { + caps &= ~CGU_CLK_DIV; + } else { + /* pass rate changes to the parent clock */ + clk_init.flags |= CLK_SET_RATE_PARENT; + } + + if (caps) { + pr_err("%s: unknown clock type 0x%x\n", __func__, caps); + goto out; + } + + clk = clk_register(NULL, &ingenic_clk->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock '%s'\n", __func__, + clk_info->name); + err = PTR_ERR(clk); + goto out; + } + + err = clk_register_clkdev(clk, clk_info->name, NULL); + if (err) + goto out; + + cgu->clocks.clks[idx] = clk; +out: + if (err) + kfree(ingenic_clk); + return err; +} + +struct ingenic_cgu * +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info, + unsigned num_clocks, struct device_node *np) +{ + struct ingenic_cgu *cgu; + + cgu = kzalloc(sizeof(*cgu), GFP_KERNEL); + if (!cgu) + goto err_out; + + cgu->base = of_iomap(np, 0); + if (!cgu->base) { + pr_err("%s: failed to map CGU registers\n", __func__); + goto err_out_free; + } + + cgu->np = np; + cgu->clock_info = clock_info; + cgu->clocks.clk_num = num_clocks; + + spin_lock_init(&cgu->lock); + + return cgu; + +err_out_free: + kfree(cgu); +err_out: + return NULL; +} + +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu) +{ + unsigned i; + int err; + + cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *), + GFP_KERNEL); + if (!cgu->clocks.clks) { + err = -ENOMEM; + goto err_out; + } + + for (i = 0; i < cgu->clocks.clk_num; i++) { + err = ingenic_register_clock(cgu, i); + if (err) + goto err_out_unregister; + } + + err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get, + &cgu->clocks); + if (err) + goto err_out_unregister; + + return 0; + +err_out_unregister: + for (i = 0; i < cgu->clocks.clk_num; i++) { + if (!cgu->clocks.clks[i]) + continue; + if (cgu->clock_info[i].type & CGU_CLK_EXT) + clk_put(cgu->clocks.clks[i]); + else + clk_unregister(cgu->clocks.clks[i]); + } + kfree(cgu->clocks.clks); +err_out: + return err; +} diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h new file mode 100644 index 0000000..99347e2 --- /dev/null +++ b/drivers/clk/ingenic/cgu.h @@ -0,0 +1,223 @@ +/* + * Ingenic SoC CGU driver + * + * Copyright (c) 2013-2015 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRIVERS_CLK_INGENIC_CGU_H__ +#define __DRIVERS_CLK_INGENIC_CGU_H__ + +#include <linux/bitops.h> +#include <linux/of.h> +#include <linux/spinlock.h> + +/** + * struct ingenic_cgu_pll_info - information about a PLL + * @reg: the offset of the PLL's control register within the CGU + * @m_shift: the number of bits to shift the multiplier value by (ie. the + * index of the lowest bit of the multiplier value in the PLL's + * control register) + * @m_bits: the size of the multiplier field in bits + * @m_offset: the multiplier value which encodes to 0 in the PLL's control + * register + * @n_shift: the number of bits to shift the divider value by (ie. the + * index of the lowest bit of the divider value in the PLL's + * control register) + * @n_bits: the size of the divider field in bits + * @n_offset: the divider value which encodes to 0 in the PLL's control + * register + * @od_shift: the number of bits to shift the post-VCO divider value by (ie. + * the index of the lowest bit of the post-VCO divider value in + * the PLL's control register) + * @od_bits: the size of the post-VCO divider field in bits + * @od_max: the maximum post-VCO divider value + * @od_encoding: a pointer to an array mapping post-VCO divider values to + * their encoded values in the PLL control register, or -1 for + * unsupported values + * @bypass_bit: the index of the bypass bit in the PLL control register + * @enable_bit: the index of the enable bit in the PLL control register + * @stable_bit: the index of the stable bit in the PLL control register + */ +struct ingenic_cgu_pll_info { + unsigned reg; + const s8 *od_encoding; + u8 m_shift, m_bits, m_offset; + u8 n_shift, n_bits, n_offset; + u8 od_shift, od_bits, od_max; + u8 bypass_bit; + u8 enable_bit; + u8 stable_bit; +}; + +/** + * struct ingenic_cgu_mux_info - information about a clock mux + * @reg: offset of the mux control register within the CGU + * @shift: number of bits to shift the mux value by (ie. the index of + * the lowest bit of the mux value within its control register) + * @bits: the size of the mux value in bits + */ +struct ingenic_cgu_mux_info { + unsigned reg; + u8 shift; + u8 bits; +}; + +/** + * struct ingenic_cgu_div_info - information about a divider + * @reg: offset of the divider control register within the CGU + * @shift: number of bits to shift the divide value by (ie. the index of + * the lowest bit of the divide value within its control register) + * @bits: the size of the divide value in bits + * @ce_bit: the index of the change enable bit within reg, or -1 if there + * isn't one + * @busy_bit: the index of the busy bit within reg, or -1 if there isn't one + * @stop_bit: the index of the stop bit within reg, or -1 if there isn't one + */ +struct ingenic_cgu_div_info { + unsigned reg; + u8 shift; + u8 bits; + s8 ce_bit; + s8 busy_bit; + s8 stop_bit; +}; + +/** + * struct ingenic_cgu_fixdiv_info - information about a fixed divider + * @div: the divider applied to the parent clock + */ +struct ingenic_cgu_fixdiv_info { + unsigned div; +}; + +/** + * struct ingenic_cgu_gate_info - information about a clock gate + * @reg: offset of the gate control register within the CGU + * @bit: offset of the bit in the register that controls the gate + */ +struct ingenic_cgu_gate_info { + unsigned reg; + u8 bit; +}; + +/** + * struct ingenic_cgu_custom_info - information about a custom (SoC) clock + * @clk_ops: custom clock operation callbacks + */ +struct ingenic_cgu_custom_info { + struct clk_ops *clk_ops; +}; + +/** + * struct ingenic_cgu_clk_info - information about a clock + * @name: name of the clock + * @type: a bitmask formed from CGU_CLK_* values + * @parents: an array of the indices of potential parents of this clock + * within the clock_info array of the CGU, or -1 in entries + * which correspond to no valid parent + * @pll: information valid if type includes CGU_CLK_PLL + * @gate: information valid if type includes CGU_CLK_GATE + * @mux: information valid if type includes CGU_CLK_MUX + * @div: information valid if type includes CGU_CLK_DIV + * @fixdiv: information valid if type includes CGU_CLK_FIXDIV + * @custom: information valid if type includes CGU_CLK_CUSTOM + */ +struct ingenic_cgu_clk_info { + const char *name; + + enum { + CGU_CLK_NONE = 0, + CGU_CLK_EXT = BIT(0), + CGU_CLK_PLL = BIT(1), + CGU_CLK_GATE = BIT(2), + CGU_CLK_MUX = BIT(3), + CGU_CLK_MUX_GLITCHFREE = BIT(4), + CGU_CLK_DIV = BIT(5), + CGU_CLK_FIXDIV = BIT(6), + CGU_CLK_CUSTOM = BIT(7), + } type; + + int parents[4]; + + union { + struct ingenic_cgu_pll_info pll; + + struct { + struct ingenic_cgu_gate_info gate; + struct ingenic_cgu_mux_info mux; + struct ingenic_cgu_div_info div; + struct ingenic_cgu_fixdiv_info fixdiv; + }; + + struct ingenic_cgu_custom_info custom; + }; +}; + +/** + * struct ingenic_cgu - data about the CGU + * @np: the device tree node that caused the CGU to be probed + * @base: the ioremap'ed base address of the CGU registers + * @clock_info: an array containing information about implemented clocks + * @clocks: used to provide clocks to DT, allows lookup of struct clk* + * @lock: lock to be held whilst manipulating CGU registers + */ +struct ingenic_cgu { + struct device_node *np; + void __iomem *base; + + const struct ingenic_cgu_clk_info *clock_info; + struct clk_onecell_data clocks; + + spinlock_t lock; +}; + +/** + * struct ingenic_clk - private data for a clock + * @hw: see Documentation/clk.txt + * @cgu: a pointer to the CGU data + * @idx: the index of this clock in cgu->clock_info + */ +struct ingenic_clk { + struct clk_hw hw; + struct ingenic_cgu *cgu; + unsigned idx; +}; + +#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw) + +/** + * ingenic_cgu_new() - create a new CGU instance + * @clock_info: an array of clock information structures describing the clocks + * which are implemented by the CGU + * @num_clocks: the number of entries in clock_info + * @np: the device tree node which causes this CGU to be probed + * + * Return: a pointer to the CGU instance if initialisation is successful, + * otherwise NULL. + */ +struct ingenic_cgu * +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info, + unsigned num_clocks, struct device_node *np); + +/** + * ingenic_cgu_register_clocks() - Registers the clocks + * @cgu: pointer to cgu data + * + * Register the clocks described by the CGU with the common clock framework. + * + * Return: 0 on success or -errno if unsuccesful. + */ +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu); + +#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */ diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c new file mode 100644 index 0000000..305a26c2 --- /dev/null +++ b/drivers/clk/ingenic/jz4740-cgu.c @@ -0,0 +1,303 @@ +/* + * Ingenic JZ4740 SoC CGU driver + * + * Copyright (c) 2015 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <dt-bindings/clock/jz4740-cgu.h> +#include <asm/mach-jz4740/clock.h> +#include "cgu.h" + +/* CGU register offsets */ +#define CGU_REG_CPCCR 0x00 +#define CGU_REG_LCR 0x04 +#define CGU_REG_CPPCR 0x10 +#define CGU_REG_CLKGR 0x20 +#define CGU_REG_SCR 0x24 +#define CGU_REG_I2SCDR 0x60 +#define CGU_REG_LPCDR 0x64 +#define CGU_REG_MSCCDR 0x68 +#define CGU_REG_UHCCDR 0x6c +#define CGU_REG_SSICDR 0x74 + +/* bits within a PLL control register */ +#define PLLCTL_M_SHIFT 23 +#define PLLCTL_M_MASK (0x1ff << PLLCTL_M_SHIFT) +#define PLLCTL_N_SHIFT 18 +#define PLLCTL_N_MASK (0x1f << PLLCTL_N_SHIFT) +#define PLLCTL_OD_SHIFT 16 +#define PLLCTL_OD_MASK (0x3 << PLLCTL_OD_SHIFT) +#define PLLCTL_STABLE (1 << 10) +#define PLLCTL_BYPASS (1 << 9) +#define PLLCTL_ENABLE (1 << 8) + +/* bits within the LCR register */ +#define LCR_SLEEP (1 << 0) + +/* bits within the CLKGR register */ +#define CLKGR_UDC (1 << 11) + +static struct ingenic_cgu *cgu; + +static const s8 pll_od_encoding[4] = { + 0x0, 0x1, -1, 0x3, +}; + +static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { + + /* External clocks */ + + [JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT }, + [JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT }, + + [JZ4740_CLK_PLL] = { + "pll", CGU_CLK_PLL, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .pll = { + .reg = CGU_REG_CPPCR, + .m_shift = 23, + .m_bits = 9, + .m_offset = 2, + .n_shift = 18, + .n_bits = 5, + .n_offset = 2, + .od_shift = 16, + .od_bits = 2, + .od_max = 4, + .od_encoding = pll_od_encoding, + .stable_bit = 10, + .bypass_bit = 9, + .enable_bit = 8, + }, + }, + + /* Muxes & dividers */ + + [JZ4740_CLK_PLL_HALF] = { + "pll half", CGU_CLK_DIV, + .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, + .div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 }, + }, + + [JZ4740_CLK_CCLK] = { + "cclk", CGU_CLK_DIV, + .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, + .div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 }, + }, + + [JZ4740_CLK_HCLK] = { + "hclk", CGU_CLK_DIV, + .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, + .div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 }, + }, + + [JZ4740_CLK_PCLK] = { + "pclk", CGU_CLK_DIV, + .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, + .div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 }, + }, + + [JZ4740_CLK_MCLK] = { + "mclk", CGU_CLK_DIV, + .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, + .div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 }, + }, + + [JZ4740_CLK_LCD] = { + "lcd", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, + .div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 }, + .gate = { CGU_REG_CLKGR, 10 }, + }, + + [JZ4740_CLK_LCD_PCLK] = { + "lcd_pclk", CGU_CLK_DIV, + .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, + .div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 }, + }, + + [JZ4740_CLK_I2S] = { + "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 }, + .mux = { CGU_REG_CPCCR, 31, 1 }, + .div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 6 }, + }, + + [JZ4740_CLK_SPI] = { + "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 }, + .mux = { CGU_REG_SSICDR, 31, 1 }, + .div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 4 }, + }, + + [JZ4740_CLK_MMC] = { + "mmc", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, + .div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 7 }, + }, + + [JZ4740_CLK_UHC] = { + "uhc", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, + .div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 14 }, + }, + + [JZ4740_CLK_UDC] = { + "udc", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 }, + .mux = { CGU_REG_CPCCR, 29, 1 }, + .div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 }, + .gate = { CGU_REG_SCR, 6 }, + }, + + /* Gate-only clocks */ + + [JZ4740_CLK_UART0] = { + "uart0", CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 0 }, + }, + + [JZ4740_CLK_UART1] = { + "uart1", CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 15 }, + }, + + [JZ4740_CLK_DMA] = { + "dma", CGU_CLK_GATE, + .parents = { JZ4740_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 12 }, + }, + + [JZ4740_CLK_IPU] = { + "ipu", CGU_CLK_GATE, + .parents = { JZ4740_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 13 }, + }, + + [JZ4740_CLK_ADC] = { + "adc", CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 8 }, + }, + + [JZ4740_CLK_I2C] = { + "i2c", CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 3 }, + }, + + [JZ4740_CLK_AIC] = { + "aic", CGU_CLK_GATE, + .parents = { JZ4740_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR, 5 }, + }, +}; + +static void __init jz4740_cgu_init(struct device_node *np) +{ + int retval; + + cgu = ingenic_cgu_new(jz4740_cgu_clocks, + ARRAY_SIZE(jz4740_cgu_clocks), np); + if (!cgu) { + pr_err("%s: failed to initialise CGU\n", __func__); + return; + } + + retval = ingenic_cgu_register_clocks(cgu); + if (retval) + pr_err("%s: failed to register CGU Clocks\n", __func__); +} +CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init); + +void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) +{ + uint32_t lcr = readl(cgu->base + CGU_REG_LCR); + + switch (mode) { + case JZ4740_WAIT_MODE_IDLE: + lcr &= ~LCR_SLEEP; + break; + + case JZ4740_WAIT_MODE_SLEEP: + lcr |= LCR_SLEEP; + break; + } + + writel(lcr, cgu->base + CGU_REG_LCR); +} + +void jz4740_clock_udc_disable_auto_suspend(void) +{ + uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR); + + clkgr &= ~CLKGR_UDC; + writel(clkgr, cgu->base + CGU_REG_CLKGR); +} +EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); + +void jz4740_clock_udc_enable_auto_suspend(void) +{ + uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR); + + clkgr |= CLKGR_UDC; + writel(clkgr, cgu->base + CGU_REG_CLKGR); +} +EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); + +#define JZ_CLOCK_GATE_UART0 BIT(0) +#define JZ_CLOCK_GATE_TCU BIT(1) +#define JZ_CLOCK_GATE_DMAC BIT(12) + +void jz4740_clock_suspend(void) +{ + uint32_t clkgr, cppcr; + + clkgr = readl(cgu->base + CGU_REG_CLKGR); + clkgr |= JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0; + writel(clkgr, cgu->base + CGU_REG_CLKGR); + + cppcr = readl(cgu->base + CGU_REG_CPPCR); + cppcr &= ~BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit); + writel(cppcr, cgu->base + CGU_REG_CPPCR); +} + +void jz4740_clock_resume(void) +{ + uint32_t clkgr, cppcr, stable; + + cppcr = readl(cgu->base + CGU_REG_CPPCR); + cppcr |= BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit); + writel(cppcr, cgu->base + CGU_REG_CPPCR); + + stable = BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.stable_bit); + do { + cppcr = readl(cgu->base + CGU_REG_CPPCR); + } while (!(cppcr & stable)); + + clkgr = readl(cgu->base + CGU_REG_CLKGR); + clkgr &= ~JZ_CLOCK_GATE_TCU; + clkgr &= ~JZ_CLOCK_GATE_DMAC; + clkgr &= ~JZ_CLOCK_GATE_UART0; + writel(clkgr, cgu->base + CGU_REG_CLKGR); +} diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c new file mode 100644 index 0000000..431f962 --- /dev/null +++ b/drivers/clk/ingenic/jz4780-cgu.c @@ -0,0 +1,733 @@ +/* + * Ingenic JZ4780 SoC CGU driver + * + * Copyright (c) 2013-2015 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <dt-bindings/clock/jz4780-cgu.h> +#include "cgu.h" + +/* CGU register offsets */ +#define CGU_REG_CLOCKCONTROL 0x00 +#define CGU_REG_PLLCONTROL 0x0c +#define CGU_REG_APLL 0x10 +#define CGU_REG_MPLL 0x14 +#define CGU_REG_EPLL 0x18 +#define CGU_REG_VPLL 0x1c +#define CGU_REG_CLKGR0 0x20 +#define CGU_REG_OPCR 0x24 +#define CGU_REG_CLKGR1 0x28 +#define CGU_REG_DDRCDR 0x2c +#define CGU_REG_VPUCDR 0x30 +#define CGU_REG_USBPCR 0x3c +#define CGU_REG_USBRDT 0x40 +#define CGU_REG_USBVBFIL 0x44 +#define CGU_REG_USBPCR1 0x48 +#define CGU_REG_LP0CDR 0x54 +#define CGU_REG_I2SCDR 0x60 +#define CGU_REG_LP1CDR 0x64 +#define CGU_REG_MSC0CDR 0x68 +#define CGU_REG_UHCCDR 0x6c +#define CGU_REG_SSICDR 0x74 +#define CGU_REG_CIMCDR 0x7c +#define CGU_REG_PCMCDR 0x84 +#define CGU_REG_GPUCDR 0x88 +#define CGU_REG_HDMICDR 0x8c +#define CGU_REG_MSC1CDR 0xa4 +#define CGU_REG_MSC2CDR 0xa8 +#define CGU_REG_BCHCDR 0xac +#define CGU_REG_CLOCKSTATUS 0xd4 + +/* bits within the OPCR register */ +#define OPCR_SPENDN0 (1 << 7) +#define OPCR_SPENDN1 (1 << 6) + +/* bits within the USBPCR register */ +#define USBPCR_USB_MODE BIT(31) +#define USBPCR_IDPULLUP_MASK (0x3 << 28) +#define USBPCR_COMMONONN BIT(25) +#define USBPCR_VBUSVLDEXT BIT(24) +#define USBPCR_VBUSVLDEXTSEL BIT(23) +#define USBPCR_POR BIT(22) +#define USBPCR_OTG_DISABLE BIT(20) +#define USBPCR_COMPDISTUNE_MASK (0x7 << 17) +#define USBPCR_OTGTUNE_MASK (0x7 << 14) +#define USBPCR_SQRXTUNE_MASK (0x7 << 11) +#define USBPCR_TXFSLSTUNE_MASK (0xf << 7) +#define USBPCR_TXPREEMPHTUNE BIT(6) +#define USBPCR_TXHSXVTUNE_MASK (0x3 << 4) +#define USBPCR_TXVREFTUNE_MASK 0xf + +/* bits within the USBPCR1 register */ +#define USBPCR1_REFCLKSEL_SHIFT 26 +#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT) +#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT) +#define USBPCR1_REFCLKDIV_SHIFT 24 +#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT) +#define USBPCR1_REFCLKDIV_19_2 (0x3 << USBPCR1_REFCLKDIV_SHIFT) +#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT) +#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT) +#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT) +#define USBPCR1_USB_SEL BIT(28) +#define USBPCR1_WORD_IF0 BIT(19) +#define USBPCR1_WORD_IF1 BIT(18) + +/* bits within the USBRDT register */ +#define USBRDT_VBFIL_LD_EN BIT(25) +#define USBRDT_USBRDT_MASK 0x7fffff + +/* bits within the USBVBFIL register */ +#define USBVBFIL_IDDIGFIL_SHIFT 16 +#define USBVBFIL_IDDIGFIL_MASK (0xffff << USBVBFIL_IDDIGFIL_SHIFT) +#define USBVBFIL_USBVBFIL_MASK (0xffff) + +static struct ingenic_cgu *cgu; + +static u8 jz4780_otg_phy_get_parent(struct clk_hw *hw) +{ + /* we only use CLKCORE, revisit if that ever changes */ + return 0; +} + +static int jz4780_otg_phy_set_parent(struct clk_hw *hw, u8 idx) +{ + unsigned long flags; + u32 usbpcr1; + + if (idx > 0) + return -EINVAL; + + spin_lock_irqsave(&cgu->lock, flags); + + usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); + usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK; + /* we only use CLKCORE */ + usbpcr1 |= USBPCR1_REFCLKSEL_CORE; + writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); + + spin_unlock_irqrestore(&cgu->lock, flags); + return 0; +} + +static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 usbpcr1; + unsigned refclk_div; + + usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); + refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK; + + switch (refclk_div) { + case USBPCR1_REFCLKDIV_12: + return 12000000; + + case USBPCR1_REFCLKDIV_24: + return 24000000; + + case USBPCR1_REFCLKDIV_48: + return 48000000; + + case USBPCR1_REFCLKDIV_19_2: + return 19200000; + } + + BUG(); + return parent_rate; +} + +static long jz4780_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long *parent_rate) +{ + if (req_rate < 15600000) + return 12000000; + + if (req_rate < 21600000) + return 19200000; + + if (req_rate < 36000000) + return 24000000; + + return 48000000; +} + +static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate, + unsigned long parent_rate) +{ + unsigned long flags; + u32 usbpcr1, div_bits; + + switch (req_rate) { + case 12000000: + div_bits = USBPCR1_REFCLKDIV_12; + break; + + case 19200000: + div_bits = USBPCR1_REFCLKDIV_19_2; + break; + + case 24000000: + div_bits = USBPCR1_REFCLKDIV_24; + break; + + case 48000000: + div_bits = USBPCR1_REFCLKDIV_48; + break; + + default: + return -EINVAL; + } + + spin_lock_irqsave(&cgu->lock, flags); + + usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); + usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK; + usbpcr1 |= div_bits; + writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); + + spin_unlock_irqrestore(&cgu->lock, flags); + return 0; +} + +static struct clk_ops jz4780_otg_phy_ops = { + .get_parent = jz4780_otg_phy_get_parent, + .set_parent = jz4780_otg_phy_set_parent, + + .recalc_rate = jz4780_otg_phy_recalc_rate, + .round_rate = jz4780_otg_phy_round_rate, + .set_rate = jz4780_otg_phy_set_rate, +}; + +static const s8 pll_od_encoding[16] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +}; + +static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { + + /* External clocks */ + + [JZ4780_CLK_EXCLK] = { "ext", CGU_CLK_EXT }, + [JZ4780_CLK_RTCLK] = { "rtc", CGU_CLK_EXT }, + + /* PLLs */ + +#define DEF_PLL(name) { \ + .reg = CGU_REG_ ## name, \ + .m_shift = 19, \ + .m_bits = 13, \ + .m_offset = 1, \ + .n_shift = 13, \ + .n_bits = 6, \ + .n_offset = 1, \ + .od_shift = 9, \ + .od_bits = 4, \ + .od_max = 16, \ + .od_encoding = pll_od_encoding, \ + .stable_bit = 6, \ + .bypass_bit = 1, \ + .enable_bit = 0, \ +} + + [JZ4780_CLK_APLL] = { + "apll", CGU_CLK_PLL, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .pll = DEF_PLL(APLL), + }, + + [JZ4780_CLK_MPLL] = { + "mpll", CGU_CLK_PLL, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .pll = DEF_PLL(MPLL), + }, + + [JZ4780_CLK_EPLL] = { + "epll", CGU_CLK_PLL, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .pll = DEF_PLL(EPLL), + }, + + [JZ4780_CLK_VPLL] = { + "vpll", CGU_CLK_PLL, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .pll = DEF_PLL(VPLL), + }, + +#undef DEF_PLL + + /* Custom (SoC-specific) OTG PHY */ + + [JZ4780_CLK_OTGPHY] = { + "otg_phy", CGU_CLK_CUSTOM, + .parents = { -1, -1, JZ4780_CLK_EXCLK, -1 }, + .custom = { &jz4780_otg_phy_ops }, + }, + + /* Muxes & dividers */ + + [JZ4780_CLK_SCLKA] = { + "sclk_a", CGU_CLK_MUX, + .parents = { -1, JZ4780_CLK_APLL, JZ4780_CLK_EXCLK, + JZ4780_CLK_RTCLK }, + .mux = { CGU_REG_CLOCKCONTROL, 30, 2 }, + }, + + [JZ4780_CLK_CPUMUX] = { + "cpumux", CGU_CLK_MUX, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL }, + .mux = { CGU_REG_CLOCKCONTROL, 28, 2 }, + }, + + [JZ4780_CLK_CPU] = { + "cpu", CGU_CLK_DIV, + .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, + .div = { CGU_REG_CLOCKCONTROL, 0, 4, 22, -1, -1 }, + }, + + [JZ4780_CLK_L2CACHE] = { + "l2cache", CGU_CLK_DIV, + .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, + .div = { CGU_REG_CLOCKCONTROL, 4, 4, -1, -1, -1 }, + }, + + [JZ4780_CLK_AHB0] = { + "ahb0", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL }, + .mux = { CGU_REG_CLOCKCONTROL, 26, 2 }, + .div = { CGU_REG_CLOCKCONTROL, 8, 4, 21, -1, -1 }, + }, + + [JZ4780_CLK_AHB2PMUX] = { + "ahb2_apb_mux", CGU_CLK_MUX, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_RTCLK }, + .mux = { CGU_REG_CLOCKCONTROL, 24, 2 }, + }, + + [JZ4780_CLK_AHB2] = { + "ahb2", CGU_CLK_DIV, + .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 }, + .div = { CGU_REG_CLOCKCONTROL, 12, 4, 20, -1, -1 }, + }, + + [JZ4780_CLK_PCLK] = { + "pclk", CGU_CLK_DIV, + .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 }, + .div = { CGU_REG_CLOCKCONTROL, 16, 4, 20, -1, -1 }, + }, + + [JZ4780_CLK_DDR] = { + "ddr", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 }, + .mux = { CGU_REG_DDRCDR, 30, 2 }, + .div = { CGU_REG_DDRCDR, 0, 4, 29, 28, 27 }, + }, + + [JZ4780_CLK_VPU] = { + "vpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL, -1 }, + .mux = { CGU_REG_VPUCDR, 30, 2 }, + .div = { CGU_REG_VPUCDR, 0, 4, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR1, 2 }, + }, + + [JZ4780_CLK_I2SPLL] = { + "i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1, -1 }, + .mux = { CGU_REG_I2SCDR, 30, 1 }, + .div = { CGU_REG_I2SCDR, 0, 8, 29, 28, 27 }, + }, + + [JZ4780_CLK_I2S] = { + "i2s", CGU_CLK_MUX, + .parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_I2SPLL, -1, -1 }, + .mux = { CGU_REG_I2SCDR, 31, 1 }, + }, + + [JZ4780_CLK_LCD0PIXCLK] = { + "lcd0pixclk", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_VPLL, -1 }, + .mux = { CGU_REG_LP0CDR, 30, 2 }, + .div = { CGU_REG_LP0CDR, 0, 8, 28, 27, 26 }, + }, + + [JZ4780_CLK_LCD1PIXCLK] = { + "lcd1pixclk", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_VPLL, -1 }, + .mux = { CGU_REG_LP1CDR, 30, 2 }, + .div = { CGU_REG_LP1CDR, 0, 8, 28, 27, 26 }, + }, + + [JZ4780_CLK_MSCMUX] = { + "msc_mux", CGU_CLK_MUX, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 }, + .mux = { CGU_REG_MSC0CDR, 30, 2 }, + }, + + [JZ4780_CLK_MSC0] = { + "msc0", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, + .div = { CGU_REG_MSC0CDR, 0, 8, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR0, 3 }, + }, + + [JZ4780_CLK_MSC1] = { + "msc1", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, + .div = { CGU_REG_MSC1CDR, 0, 8, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR0, 11 }, + }, + + [JZ4780_CLK_MSC2] = { + "msc2", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, + .div = { CGU_REG_MSC2CDR, 0, 8, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR0, 12 }, + }, + + [JZ4780_CLK_UHC] = { + "uhc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY }, + .mux = { CGU_REG_UHCCDR, 30, 2 }, + .div = { CGU_REG_UHCCDR, 0, 8, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR0, 24 }, + }, + + [JZ4780_CLK_SSIPLL] = { + "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 }, + .mux = { CGU_REG_SSICDR, 30, 1 }, + .div = { CGU_REG_SSICDR, 0, 8, 29, 28, 27 }, + }, + + [JZ4780_CLK_SSI] = { + "ssi", CGU_CLK_MUX, + .parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_SSIPLL, -1, -1 }, + .mux = { CGU_REG_SSICDR, 31, 1 }, + }, + + [JZ4780_CLK_CIMMCLK] = { + "cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 }, + .mux = { CGU_REG_CIMCDR, 31, 1 }, + .div = { CGU_REG_CIMCDR, 0, 8, 30, 29, 28 }, + }, + + [JZ4780_CLK_PCMPLL] = { + "pcm_pll", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL, JZ4780_CLK_VPLL }, + .mux = { CGU_REG_PCMCDR, 29, 2 }, + .div = { CGU_REG_PCMCDR, 0, 8, 28, 27, 26 }, + }, + + [JZ4780_CLK_PCM] = { + "pcm", CGU_CLK_MUX | CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_PCMPLL, -1, -1 }, + .mux = { CGU_REG_PCMCDR, 31, 1 }, + .gate = { CGU_REG_CLKGR1, 3 }, + }, + + [JZ4780_CLK_GPU] = { + "gpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL }, + .mux = { CGU_REG_GPUCDR, 30, 2 }, + .div = { CGU_REG_GPUCDR, 0, 4, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR1, 4 }, + }, + + [JZ4780_CLK_HDMI] = { + "hdmi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_VPLL, -1 }, + .mux = { CGU_REG_HDMICDR, 30, 2 }, + .div = { CGU_REG_HDMICDR, 0, 8, 29, 28, 26 }, + .gate = { CGU_REG_CLKGR1, 9 }, + }, + + [JZ4780_CLK_BCH] = { + "bch", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, + JZ4780_CLK_EPLL }, + .mux = { CGU_REG_BCHCDR, 30, 2 }, + .div = { CGU_REG_BCHCDR, 0, 4, 29, 28, 27 }, + .gate = { CGU_REG_CLKGR0, 1 }, + }, + + /* Gate-only clocks */ + + [JZ4780_CLK_NEMC] = { + "nemc", CGU_CLK_GATE, + .parents = { JZ4780_CLK_AHB2, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 0 }, + }, + + [JZ4780_CLK_OTG0] = { + "otg0", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 2 }, + }, + + [JZ4780_CLK_SSI0] = { + "ssi0", CGU_CLK_GATE, + .parents = { JZ4780_CLK_SSI, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 4 }, + }, + + [JZ4780_CLK_SMB0] = { + "smb0", CGU_CLK_GATE, + .parents = { JZ4780_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 5 }, + }, + + [JZ4780_CLK_SMB1] = { + "smb1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 6 }, + }, + + [JZ4780_CLK_SCC] = { + "scc", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 7 }, + }, + + [JZ4780_CLK_AIC] = { + "aic", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 8 }, + }, + + [JZ4780_CLK_TSSI0] = { + "tssi0", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 9 }, + }, + + [JZ4780_CLK_OWI] = { + "owi", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 10 }, + }, + + [JZ4780_CLK_KBC] = { + "kbc", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 13 }, + }, + + [JZ4780_CLK_SADC] = { + "sadc", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 14 }, + }, + + [JZ4780_CLK_UART0] = { + "uart0", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 15 }, + }, + + [JZ4780_CLK_UART1] = { + "uart1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 16 }, + }, + + [JZ4780_CLK_UART2] = { + "uart2", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 17 }, + }, + + [JZ4780_CLK_UART3] = { + "uart3", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 18 }, + }, + + [JZ4780_CLK_SSI1] = { + "ssi1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_SSI, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 19 }, + }, + + [JZ4780_CLK_SSI2] = { + "ssi2", CGU_CLK_GATE, + .parents = { JZ4780_CLK_SSI, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 20 }, + }, + + [JZ4780_CLK_PDMA] = { + "pdma", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 21 }, + }, + + [JZ4780_CLK_GPS] = { + "gps", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 22 }, + }, + + [JZ4780_CLK_MAC] = { + "mac", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 23 }, + }, + + [JZ4780_CLK_SMB2] = { + "smb2", CGU_CLK_GATE, + .parents = { JZ4780_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 24 }, + }, + + [JZ4780_CLK_CIM] = { + "cim", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 26 }, + }, + + [JZ4780_CLK_LCD] = { + "lcd", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 28 }, + }, + + [JZ4780_CLK_TVE] = { + "tve", CGU_CLK_GATE, + .parents = { JZ4780_CLK_LCD, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 27 }, + }, + + [JZ4780_CLK_IPU] = { + "ipu", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 29 }, + }, + + [JZ4780_CLK_DDR0] = { + "ddr0", CGU_CLK_GATE, + .parents = { JZ4780_CLK_DDR, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 30 }, + }, + + [JZ4780_CLK_DDR1] = { + "ddr1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_DDR, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 31 }, + }, + + [JZ4780_CLK_SMB3] = { + "smb3", CGU_CLK_GATE, + .parents = { JZ4780_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 0 }, + }, + + [JZ4780_CLK_TSSI1] = { + "tssi1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 1 }, + }, + + [JZ4780_CLK_COMPRESS] = { + "compress", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 5 }, + }, + + [JZ4780_CLK_AIC1] = { + "aic1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 6 }, + }, + + [JZ4780_CLK_GPVLC] = { + "gpvlc", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 7 }, + }, + + [JZ4780_CLK_OTG1] = { + "otg1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 8 }, + }, + + [JZ4780_CLK_UART4] = { + "uart4", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 10 }, + }, + + [JZ4780_CLK_AHBMON] = { + "ahb_mon", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 11 }, + }, + + [JZ4780_CLK_SMB4] = { + "smb4", CGU_CLK_GATE, + .parents = { JZ4780_CLK_PCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 12 }, + }, + + [JZ4780_CLK_DES] = { + "des", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 13 }, + }, + + [JZ4780_CLK_X2D] = { + "x2d", CGU_CLK_GATE, + .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 14 }, + }, + + [JZ4780_CLK_CORE1] = { + "core1", CGU_CLK_GATE, + .parents = { JZ4780_CLK_CPU, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 15 }, + }, + +}; + +static void __init jz4780_cgu_init(struct device_node *np) +{ + int retval; + + cgu = ingenic_cgu_new(jz4780_cgu_clocks, + ARRAY_SIZE(jz4780_cgu_clocks), np); + if (!cgu) { + pr_err("%s: failed to initialise CGU\n", __func__); + return; + } + + retval = ingenic_cgu_register_clocks(cgu); + if (retval) { + pr_err("%s: failed to register CGU Clocks\n", __func__); + return; + } +} +CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init); diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/ls1x-cpufreq.c index f0913ee..262581b 100644 --- a/drivers/cpufreq/ls1x-cpufreq.c +++ b/drivers/cpufreq/ls1x-cpufreq.c @@ -17,8 +17,8 @@ #include <linux/platform_device.h> #include <linux/slab.h> -#include <asm/mach-loongson1/cpufreq.h> -#include <asm/mach-loongson1/loongson1.h> +#include <cpufreq.h> +#include <loongson1.h> static struct { struct device *dev; diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 6517132..99c69a3 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -136,6 +136,7 @@ config QCOM_SCM bool depends on ARM || ARM64 +source "drivers/firmware/broadcom/Kconfig" source "drivers/firmware/google/Kconfig" source "drivers/firmware/efi/Kconfig" diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 3001f1a..4a4b897 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_QCOM_SCM) += qcom_scm.o obj-$(CONFIG_QCOM_SCM) += qcom_scm-32.o CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) +obj-y += broadcom/ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_UEFI_CPER) += efi/ diff --git a/drivers/firmware/broadcom/Kconfig b/drivers/firmware/broadcom/Kconfig new file mode 100644 index 0000000..6bed119 --- /dev/null +++ b/drivers/firmware/broadcom/Kconfig @@ -0,0 +1,11 @@ +config BCM47XX_NVRAM + bool "Broadcom NVRAM driver" + depends on BCM47XX || ARCH_BCM_5301X + help + Broadcom home routers contain flash partition called "nvram" with all + important hardware configuration as well as some minor user setup. + NVRAM partition contains a text-like data representing name=value + pairs. + This driver provides an easy way to get value of requested parameter. + It simply reads content of NVRAM and parses it. It doesn't control any + hardware part itself. diff --git a/drivers/firmware/broadcom/Makefile b/drivers/firmware/broadcom/Makefile new file mode 100644 index 0000000..d0e6835 --- /dev/null +++ b/drivers/firmware/broadcom/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o diff --git a/arch/mips/bcm47xx/nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index ba632ff..87add3f 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -35,6 +35,7 @@ struct nvram_header { }; static char nvram_buf[NVRAM_SPACE]; +static size_t nvram_len; static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; static u32 find_nvram_size(void __iomem *end) @@ -60,7 +61,7 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim) u32 *src, *dst; u32 size; - if (nvram_buf[0]) { + if (nvram_len) { pr_warn("nvram already initialized\n"); return -EEXIST; } @@ -94,18 +95,25 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim) return -ENXIO; found: - if (header->len > size) - pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n"); - if (header->len > NVRAM_SPACE) - pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", - header->len, NVRAM_SPACE); - src = (u32 *)header; dst = (u32 *)nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = __raw_readl(src++); - for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4) + header = (struct nvram_header *)nvram_buf; + nvram_len = header->len; + if (nvram_len > size) { + pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); + nvram_len = size; + } + if (nvram_len >= NVRAM_SPACE) { + pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", + header->len, NVRAM_SPACE - 1); + nvram_len = NVRAM_SPACE - 1; + } + /* proceed reading data after header */ + for (; i < nvram_len; i += 4) *dst++ = readl(src++); + nvram_buf[NVRAM_SPACE - 1] = '\0'; return 0; } @@ -146,21 +154,18 @@ static int nvram_init(void) return -ENODEV; err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header); - if (!err && header.magic == NVRAM_MAGIC) { - u8 *dst = (uint8_t *)nvram_buf; - size_t len = header.len; - - if (header.len > NVRAM_SPACE) { + if (!err && header.magic == NVRAM_MAGIC && + header.len > sizeof(header)) { + nvram_len = header.len; + if (nvram_len >= NVRAM_SPACE) { pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", header.len, NVRAM_SPACE); - len = NVRAM_SPACE; + nvram_len = NVRAM_SPACE - 1; } - err = mtd_read(mtd, 0, len, &bytes_read, dst); - if (err) - return err; - - return 0; + err = mtd_read(mtd, 0, nvram_len, &nvram_len, + (u8 *)nvram_buf); + return err; } #endif @@ -170,12 +175,12 @@ static int nvram_init(void) int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) { char *var, *value, *end, *eq; - int data_left, err; + int err; if (!name) return -EINVAL; - if (!nvram_buf[0]) { + if (!nvram_len) { err = nvram_init(); if (err) return err; @@ -183,19 +188,16 @@ int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) /* Look for name=value and return value */ var = &nvram_buf[sizeof(struct nvram_header)]; - end = nvram_buf + sizeof(nvram_buf) - 2; - end[0] = '\0'; - end[1] = '\0'; - for (; *var; var = value + strlen(value) + 1) { - data_left = end - var; - - eq = strnchr(var, data_left, '='); + end = nvram_buf + sizeof(nvram_buf); + while (var < end && *var) { + eq = strchr(var, '='); if (!eq) break; value = eq + 1; if (eq - var == strlen(name) && strncmp(var, name, eq - var) == 0) return snprintf(val, val_len, "%s", value); + var = value + strlen(value) + 1; } return -ENOENT; } @@ -221,3 +223,26 @@ int bcm47xx_nvram_gpio_pin(const char *name) return -ENOENT; } EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin); + +char *bcm47xx_nvram_get_contents(size_t *nvram_size) +{ + int err; + char *nvram; + + if (!nvram_len) { + err = nvram_init(); + if (err) + return NULL; + } + + *nvram_size = nvram_len - sizeof(struct nvram_header); + nvram = vmalloc(*nvram_size); + if (!nvram) + return NULL; + memcpy(nvram, &nvram_buf[sizeof(struct nvram_header)], *nvram_size); + + return nvram; +} +EXPORT_SYMBOL(bcm47xx_nvram_get_contents); + +MODULE_LICENSE("GPLv2"); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 8a7d780..120d815 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -86,6 +86,11 @@ config IMGPDC_IRQ select GENERIC_IRQ_CHIP select IRQ_DOMAIN +config IRQ_MIPS_CPU + bool + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + config CLPS711X_IRQCHIP bool depends on ARCH_CLPS711X @@ -160,10 +165,15 @@ config MIPS_GIC bool select MIPS_CM +config INGENIC_IRQ + bool + depends on MACH_INGENIC + default y + config RENESAS_H8300H_INTC bool select IRQ_DOMAIN config RENESAS_H8S_INTC bool - select IRQ_DOMAIN
\ No newline at end of file + select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 5c9adf1..b8d4e96 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_ARM_VIC) += irq-vic.o obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o +obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o @@ -50,3 +51,4 @@ obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o +obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c new file mode 100644 index 0000000..005de3f --- /dev/null +++ b/drivers/irqchip/irq-ingenic.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> + * JZ4740 platform IRQ support + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/irqchip/ingenic.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/delay.h> + +#include <asm/io.h> +#include <asm/mach-jz4740/irq.h> + +#include "irqchip.h" + +struct ingenic_intc_data { + void __iomem *base; + unsigned num_chips; +}; + +#define JZ_REG_INTC_STATUS 0x00 +#define JZ_REG_INTC_MASK 0x04 +#define JZ_REG_INTC_SET_MASK 0x08 +#define JZ_REG_INTC_CLEAR_MASK 0x0c +#define JZ_REG_INTC_PENDING 0x10 +#define CHIP_SIZE 0x20 + +static irqreturn_t intc_cascade(int irq, void *data) +{ + struct ingenic_intc_data *intc = irq_get_handler_data(irq); + uint32_t irq_reg; + unsigned i; + + for (i = 0; i < intc->num_chips; i++) { + irq_reg = readl(intc->base + (i * CHIP_SIZE) + + JZ_REG_INTC_PENDING); + if (!irq_reg) + continue; + + generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE); + } + + return IRQ_HANDLED; +} + +static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask) +{ + struct irq_chip_regs *regs = &gc->chip_types->regs; + + writel(mask, gc->reg_base + regs->enable); + writel(~mask, gc->reg_base + regs->disable); +} + +void ingenic_intc_irq_suspend(struct irq_data *data) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + intc_irq_set_mask(gc, gc->wake_active); +} + +void ingenic_intc_irq_resume(struct irq_data *data) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + intc_irq_set_mask(gc, gc->mask_cache); +} + +static struct irqaction intc_cascade_action = { + .handler = intc_cascade, + .name = "SoC intc cascade interrupt", +}; + +static int __init ingenic_intc_of_init(struct device_node *node, + unsigned num_chips) +{ + struct ingenic_intc_data *intc; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + struct irq_domain *domain; + int parent_irq, err = 0; + unsigned i; + + intc = kzalloc(sizeof(*intc), GFP_KERNEL); + if (!intc) { + err = -ENOMEM; + goto out_err; + } + + parent_irq = irq_of_parse_and_map(node, 0); + if (!parent_irq) { + err = -EINVAL; + goto out_free; + } + + err = irq_set_handler_data(parent_irq, intc); + if (err) + goto out_unmap_irq; + + intc->num_chips = num_chips; + intc->base = of_iomap(node, 0); + if (!intc->base) { + err = -ENODEV; + goto out_unmap_irq; + } + + for (i = 0; i < num_chips; i++) { + /* Mask all irqs */ + writel(0xffffffff, intc->base + (i * CHIP_SIZE) + + JZ_REG_INTC_SET_MASK); + + gc = irq_alloc_generic_chip("INTC", 1, + JZ4740_IRQ_BASE + (i * 32), + intc->base + (i * CHIP_SIZE), + handle_level_irq); + + gc->wake_enabled = IRQ_MSK(32); + + ct = gc->chip_types; + ct->regs.enable = JZ_REG_INTC_CLEAR_MASK; + ct->regs.disable = JZ_REG_INTC_SET_MASK; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; + ct->chip.irq_set_wake = irq_gc_set_wake; + ct->chip.irq_suspend = ingenic_intc_irq_suspend; + ct->chip.irq_resume = ingenic_intc_irq_resume; + + irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, + IRQ_NOPROBE | IRQ_LEVEL); + } + + domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0, + &irq_domain_simple_ops, NULL); + if (!domain) + pr_warn("unable to register IRQ domain\n"); + + setup_irq(parent_irq, &intc_cascade_action); + return 0; + +out_unmap_irq: + irq_dispose_mapping(parent_irq); +out_free: + kfree(intc); +out_err: + return err; +} + +static int __init intc_1chip_of_init(struct device_node *node, + struct device_node *parent) +{ + return ingenic_intc_of_init(node, 1); +} +IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init); + +static int __init intc_2chip_of_init(struct device_node *node, + struct device_node *parent) +{ + return ingenic_intc_of_init(node, 2); +} +IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init); +IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init); +IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init); diff --git a/arch/mips/kernel/irq_cpu.c b/drivers/irqchip/irq-mips-cpu.c index 6eb7a3f..a43c419 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/drivers/irqchip/irq-mips-cpu.c @@ -38,6 +38,8 @@ #include <asm/mipsmtregs.h> #include <asm/setup.h> +#include "irqchip.h" + static inline void unmask_mips_irq(struct irq_data *d) { set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); @@ -167,3 +169,4 @@ int __init mips_cpu_irq_of_init(struct device_node *of_node, __mips_cpu_irq_init(of_node); return 0; } +IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init); diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 487d057..c0e6ede 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -267,6 +267,13 @@ config PHY_EXYNOS5_USBDRD This driver provides PHY interface for USB 3.0 DRD controller present on Exynos5 SoC series. +config PHY_PISTACHIO_USB + tristate "IMG Pistachio USB2.0 PHY driver" + depends on MACH_PISTACHIO + select GENERIC_PHY + help + Enable this to support the USB2.0 PHY on the IMG Pistachio SoC. + config PHY_QCOM_APQ8064_SATA tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" depends on ARCH_QCOM diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 42f58e9..f344e1b 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o +obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o diff --git a/drivers/phy/phy-pistachio-usb.c b/drivers/phy/phy-pistachio-usb.c new file mode 100644 index 0000000..c6db35e --- /dev/null +++ b/drivers/phy/phy-pistachio-usb.c @@ -0,0 +1,206 @@ +/* + * IMG Pistachio USB PHY driver + * + * Copyright (C) 2015 Google, Inc. + * + * 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. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <dt-bindings/phy/phy-pistachio-usb.h> + +#define USB_PHY_CONTROL1 0x04 +#define USB_PHY_CONTROL1_FSEL_SHIFT 2 +#define USB_PHY_CONTROL1_FSEL_MASK 0x7 + +#define USB_PHY_STRAP_CONTROL 0x10 +#define USB_PHY_STRAP_CONTROL_REFCLK_SHIFT 4 +#define USB_PHY_STRAP_CONTROL_REFCLK_MASK 0x3 + +#define USB_PHY_STATUS 0x14 +#define USB_PHY_STATUS_RX_PHY_CLK BIT(9) +#define USB_PHY_STATUS_RX_UTMI_CLK BIT(8) +#define USB_PHY_STATUS_VBUS_FAULT BIT(7) + +struct pistachio_usb_phy { + struct device *dev; + struct regmap *cr_top; + struct clk *phy_clk; + unsigned int refclk; +}; + +static const unsigned long fsel_rate_map[] = { + 9600000, + 10000000, + 12000000, + 19200000, + 20000000, + 24000000, + 0, + 50000000, +}; + +static int pistachio_usb_phy_power_on(struct phy *phy) +{ + struct pistachio_usb_phy *p_phy = phy_get_drvdata(phy); + unsigned long timeout, rate; + unsigned int i; + int ret; + + ret = clk_prepare_enable(p_phy->phy_clk); + if (ret < 0) { + dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret); + return ret; + } + + regmap_update_bits(p_phy->cr_top, USB_PHY_STRAP_CONTROL, + USB_PHY_STRAP_CONTROL_REFCLK_MASK << + USB_PHY_STRAP_CONTROL_REFCLK_SHIFT, + p_phy->refclk << USB_PHY_STRAP_CONTROL_REFCLK_SHIFT); + + rate = clk_get_rate(p_phy->phy_clk); + if (p_phy->refclk == REFCLK_XO_CRYSTAL && rate != 12000000) { + dev_err(p_phy->dev, "Unsupported rate for XO crystal: %ld\n", + rate); + ret = -EINVAL; + goto disable_clk; + } + + for (i = 0; i < ARRAY_SIZE(fsel_rate_map); i++) { + if (rate == fsel_rate_map[i]) + break; + } + if (i == ARRAY_SIZE(fsel_rate_map)) { + dev_err(p_phy->dev, "Unsupported clock rate: %lu\n", rate); + ret = -EINVAL; + goto disable_clk; + } + + regmap_update_bits(p_phy->cr_top, USB_PHY_CONTROL1, + USB_PHY_CONTROL1_FSEL_MASK << + USB_PHY_CONTROL1_FSEL_SHIFT, + i << USB_PHY_CONTROL1_FSEL_SHIFT); + + timeout = jiffies + msecs_to_jiffies(200); + while (time_before(jiffies, timeout)) { + unsigned int val; + + regmap_read(p_phy->cr_top, USB_PHY_STATUS, &val); + if (val & USB_PHY_STATUS_VBUS_FAULT) { + dev_err(p_phy->dev, "VBUS fault detected\n"); + ret = -EIO; + goto disable_clk; + } + if ((val & USB_PHY_STATUS_RX_PHY_CLK) && + (val & USB_PHY_STATUS_RX_UTMI_CLK)) + return 0; + usleep_range(1000, 1500); + } + + dev_err(p_phy->dev, "Timed out waiting for PHY to power on\n"); + ret = -ETIMEDOUT; + +disable_clk: + clk_disable_unprepare(p_phy->phy_clk); + return ret; +} + +static int pistachio_usb_phy_power_off(struct phy *phy) +{ + struct pistachio_usb_phy *p_phy = phy_get_drvdata(phy); + + clk_disable_unprepare(p_phy->phy_clk); + + return 0; +} + +static const struct phy_ops pistachio_usb_phy_ops = { + .power_on = pistachio_usb_phy_power_on, + .power_off = pistachio_usb_phy_power_off, + .owner = THIS_MODULE, +}; + +static int pistachio_usb_phy_probe(struct platform_device *pdev) +{ + struct pistachio_usb_phy *p_phy; + struct phy_provider *provider; + struct phy *phy; + int ret; + + p_phy = devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL); + if (!p_phy) + return -ENOMEM; + p_phy->dev = &pdev->dev; + platform_set_drvdata(pdev, p_phy); + + p_phy->cr_top = syscon_regmap_lookup_by_phandle(p_phy->dev->of_node, + "img,cr-top"); + if (IS_ERR(p_phy->cr_top)) { + dev_err(p_phy->dev, "Failed to get CR_TOP registers: %ld\n", + PTR_ERR(p_phy->cr_top)); + return PTR_ERR(p_phy->cr_top); + } + + p_phy->phy_clk = devm_clk_get(p_phy->dev, "usb_phy"); + if (IS_ERR(p_phy->phy_clk)) { + dev_err(p_phy->dev, "Failed to get usb_phy clock: %ld\n", + PTR_ERR(p_phy->phy_clk)); + return PTR_ERR(p_phy->phy_clk); + } + + ret = of_property_read_u32(p_phy->dev->of_node, "img,refclk", + &p_phy->refclk); + if (ret < 0) { + dev_err(p_phy->dev, "No reference clock selector specified\n"); + return ret; + } + + phy = devm_phy_create(p_phy->dev, NULL, &pistachio_usb_phy_ops); + if (IS_ERR(phy)) { + dev_err(p_phy->dev, "Failed to create PHY: %ld\n", + PTR_ERR(phy)); + return PTR_ERR(phy); + } + phy_set_drvdata(phy, p_phy); + + provider = devm_of_phy_provider_register(p_phy->dev, + of_phy_simple_xlate); + if (IS_ERR(provider)) { + dev_err(p_phy->dev, "Failed to register PHY provider: %ld\n", + PTR_ERR(provider)); + return PTR_ERR(provider); + } + + return 0; +} + +static const struct of_device_id pistachio_usb_phy_of_match[] = { + { .compatible = "img,pistachio-usb-phy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, pistachio_usb_phy_of_match); + +static struct platform_driver pistachio_usb_phy_driver = { + .probe = pistachio_usb_phy_probe, + .driver = { + .name = "pistachio-usb-phy", + .of_match_table = pistachio_usb_phy_of_match, + }, +}; +module_platform_driver(pistachio_usb_phy_driver); + +MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>"); +MODULE_DESCRIPTION("IMG Pistachio USB2.0 PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index db2fe4a..83b4b89 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1503,7 +1503,7 @@ config RTC_DRV_PUV3 config RTC_DRV_LOONGSON1 tristate "loongson1 RTC support" - depends on MACH_LOONGSON1 + depends on MACH_LOONGSON32 help This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year counter) to be used as a RTC. diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index 8445e56..22a9ec4 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c @@ -17,7 +17,7 @@ #include <linux/delay.h> #include <linux/types.h> #include <linux/io.h> -#include <asm/mach-loongson1/loongson1.h> +#include <loongson1.h> #define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20) #define LS1X_RTC_REGS(x) \ diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c new file mode 100644 index 0000000..21bf81f --- /dev/null +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de> + * Copyright (C) 2015 Imagination Technologies + * + * Ingenic SoC UART support + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/io.h> +#include <linux/libfdt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_fdt.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> +#include <linux/serial_core.h> +#include <linux/serial_reg.h> + +struct ingenic_uart_data { + struct clk *clk_module; + struct clk *clk_baud; + int line; +}; + +#define UART_FCR_UME BIT(4) + +static struct earlycon_device *early_device; + +static uint8_t __init early_in(struct uart_port *port, int offset) +{ + return readl(port->membase + (offset << 2)); +} + +static void __init early_out(struct uart_port *port, int offset, uint8_t value) +{ + writel(value, port->membase + (offset << 2)); +} + +static void __init ingenic_early_console_putc(struct uart_port *port, int c) +{ + uint8_t lsr; + + do { + lsr = early_in(port, UART_LSR); + } while ((lsr & UART_LSR_TEMT) == 0); + + early_out(port, UART_TX, c); +} + +static void __init ingenic_early_console_write(struct console *console, + const char *s, unsigned int count) +{ + uart_console_write(&early_device->port, s, count, + ingenic_early_console_putc); +} + +static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev) +{ + void *fdt = initial_boot_params; + const __be32 *prop; + int offset; + + offset = fdt_path_offset(fdt, "/ext"); + if (offset < 0) + return; + + prop = fdt_getprop(fdt, offset, "clock-frequency", NULL); + if (!prop) + return; + + dev->port.uartclk = be32_to_cpup(prop); +} + +static int __init ingenic_early_console_setup(struct earlycon_device *dev, + const char *opt) +{ + struct uart_port *port = &dev->port; + unsigned int baud, divisor; + + if (!dev->port.membase) + return -ENODEV; + + ingenic_early_console_setup_clock(dev); + + baud = dev->baud ?: 115200; + divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); + + early_out(port, UART_IER, 0); + early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); + early_out(port, UART_DLL, 0); + early_out(port, UART_DLM, 0); + early_out(port, UART_LCR, UART_LCR_WLEN8); + early_out(port, UART_FCR, UART_FCR_UME | UART_FCR_CLEAR_XMIT | + UART_FCR_CLEAR_RCVR | UART_FCR_ENABLE_FIFO); + early_out(port, UART_MCR, UART_MCR_RTS | UART_MCR_DTR); + + early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); + early_out(port, UART_DLL, divisor & 0xff); + early_out(port, UART_DLM, (divisor >> 8) & 0xff); + early_out(port, UART_LCR, UART_LCR_WLEN8); + + early_device = dev; + dev->con->write = ingenic_early_console_write; + + return 0; +} + +EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart", + ingenic_early_console_setup); + +EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart", + ingenic_early_console_setup); + +EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup); +OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart", + ingenic_early_console_setup); + +static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) +{ + switch (offset) { + case UART_FCR: + /* UART module enable */ + value |= UART_FCR_UME; + break; + + case UART_IER: + value |= (value & 0x4) << 2; + break; + + default: + break; + } + + writeb(value, p->membase + (offset << p->regshift)); +} + +static int ingenic_uart_probe(struct platform_device *pdev) +{ + struct uart_8250_port uart = {}; + struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + struct ingenic_uart_data *data; + int err, line; + + if (!regs || !irq) { + dev_err(&pdev->dev, "no registers/irq defined\n"); + return -EINVAL; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&uart.port.lock); + uart.port.type = PORT_16550; + uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE; + uart.port.iotype = UPIO_MEM; + uart.port.mapbase = regs->start; + uart.port.regshift = 2; + uart.port.serial_out = ingenic_uart_serial_out; + uart.port.irq = irq->start; + uart.port.dev = &pdev->dev; + + /* Check for a fixed line number */ + line = of_alias_get_id(pdev->dev.of_node, "serial"); + if (line >= 0) + uart.port.line = line; + + uart.port.membase = devm_ioremap(&pdev->dev, regs->start, + resource_size(regs)); + if (!uart.port.membase) + return -ENOMEM; + + data->clk_module = devm_clk_get(&pdev->dev, "module"); + if (IS_ERR(data->clk_module)) { + err = PTR_ERR(data->clk_module); + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, + "unable to get module clock: %d\n", err); + return err; + } + + data->clk_baud = devm_clk_get(&pdev->dev, "baud"); + if (IS_ERR(data->clk_baud)) { + err = PTR_ERR(data->clk_baud); + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, + "unable to get baud clock: %d\n", err); + return err; + } + + err = clk_prepare_enable(data->clk_module); + if (err) { + dev_err(&pdev->dev, "could not enable module clock: %d\n", err); + goto out; + } + + err = clk_prepare_enable(data->clk_baud); + if (err) { + dev_err(&pdev->dev, "could not enable baud clock: %d\n", err); + goto out_disable_moduleclk; + } + uart.port.uartclk = clk_get_rate(data->clk_baud); + + data->line = serial8250_register_8250_port(&uart); + if (data->line < 0) { + err = data->line; + goto out_disable_baudclk; + } + + platform_set_drvdata(pdev, data); + return 0; + +out_disable_baudclk: + clk_disable_unprepare(data->clk_baud); +out_disable_moduleclk: + clk_disable_unprepare(data->clk_module); +out: + return err; +} + +static int ingenic_uart_remove(struct platform_device *pdev) +{ + struct ingenic_uart_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + clk_disable_unprepare(data->clk_module); + clk_disable_unprepare(data->clk_baud); + return 0; +} + +static const struct of_device_id of_match[] = { + { .compatible = "ingenic,jz4740-uart" }, + { .compatible = "ingenic,jz4775-uart" }, + { .compatible = "ingenic,jz4780-uart" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match); + +static struct platform_driver ingenic_uart_platform_driver = { + .driver = { + .name = "ingenic-uart", + .owner = THIS_MODULE, + .of_match_table = of_match, + }, + .probe = ingenic_uart_probe, + .remove = ingenic_uart_remove, +}; + +module_platform_driver(ingenic_uart_platform_driver); + +MODULE_AUTHOR("Paul Burton"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Ingenic SoC UART driver"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a74a8e4..e1de118 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -357,3 +357,12 @@ config SERIAL_8250_UNIPHIER help If you have a UniPhier based board and want to use the on-chip serial ports, say Y to this option. If unsure, say N. + +config SERIAL_8250_INGENIC + bool "Support for Ingenic SoC serial ports" + depends on SERIAL_8250_CONSOLE && OF_FLATTREE + select LIBFDT + select SERIAL_EARLYCON + help + If you have a system using an Ingenic SoC and wish to make use of + its UARTs, say Y to this option. If unsure, say N. diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 6fa22ff..7062959 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -25,3 +25,6 @@ obj-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o +obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o + +CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 1c479103..2847108 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -462,6 +462,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { /* v: May be registered for frame buffer console restore */ NULL, /* v */ &sysrq_showstate_blocked_op, /* w */ + /* x: May be registered on mips for TLB dump */ /* x: May be registered on ppc/powerpc for xmon */ /* x: May be registered on sparc64 for global PMU dump */ NULL, /* x */ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 547cee8..8afc3c1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -295,7 +295,7 @@ config USB_OCTEON_EHCI bool "Octeon on-chip EHCI support (DEPRECATED)" depends on CAVIUM_OCTEON_SOC default n - select USB_EHCI_BIG_ENDIAN_MMIO + select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN select USB_EHCI_HCD_PLATFORM help This option is deprecated now and the driver was removed, use @@ -568,7 +568,7 @@ config USB_OCTEON_OHCI bool "Octeon on-chip OHCI support (DEPRECATED)" depends on CAVIUM_OCTEON_SOC default USB_OCTEON_EHCI - select USB_OHCI_BIG_ENDIAN_MMIO + select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN select USB_OHCI_LITTLE_ENDIAN select USB_OHCI_HCD_PLATFORM help diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h new file mode 100644 index 0000000..43153d3 --- /dev/null +++ b/include/dt-bindings/clock/jz4740-cgu.h @@ -0,0 +1,37 @@ +/* + * This header provides clock numbers for the ingenic,jz4740-cgu DT binding. + * + * They are roughly ordered as: + * - external clocks + * - PLLs + * - muxes/dividers in the order they appear in the jz4740 programmers manual + * - gates in order of their bit in the CLKGR* registers + */ + +#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ +#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ + +#define JZ4740_CLK_EXT 0 +#define JZ4740_CLK_RTC 1 +#define JZ4740_CLK_PLL 2 +#define JZ4740_CLK_PLL_HALF 3 +#define JZ4740_CLK_CCLK 4 +#define JZ4740_CLK_HCLK 5 +#define JZ4740_CLK_PCLK 6 +#define JZ4740_CLK_MCLK 7 +#define JZ4740_CLK_LCD 8 +#define JZ4740_CLK_LCD_PCLK 9 +#define JZ4740_CLK_I2S 10 +#define JZ4740_CLK_SPI 11 +#define JZ4740_CLK_MMC 12 +#define JZ4740_CLK_UHC 13 +#define JZ4740_CLK_UDC 14 +#define JZ4740_CLK_UART0 15 +#define JZ4740_CLK_UART1 16 +#define JZ4740_CLK_DMA 17 +#define JZ4740_CLK_IPU 18 +#define JZ4740_CLK_ADC 19 +#define JZ4740_CLK_I2C 20 +#define JZ4740_CLK_AIC 21 + +#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */ diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h new file mode 100644 index 0000000..467165e --- /dev/null +++ b/include/dt-bindings/clock/jz4780-cgu.h @@ -0,0 +1,88 @@ +/* + * This header provides clock numbers for the ingenic,jz4780-cgu DT binding. + * + * They are roughly ordered as: + * - external clocks + * - PLLs + * - muxes/dividers in the order they appear in the jz4780 programmers manual + * - gates in order of their bit in the CLKGR* registers + */ + +#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ +#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ + +#define JZ4780_CLK_EXCLK 0 +#define JZ4780_CLK_RTCLK 1 +#define JZ4780_CLK_APLL 2 +#define JZ4780_CLK_MPLL 3 +#define JZ4780_CLK_EPLL 4 +#define JZ4780_CLK_VPLL 5 +#define JZ4780_CLK_OTGPHY 6 +#define JZ4780_CLK_SCLKA 7 +#define JZ4780_CLK_CPUMUX 8 +#define JZ4780_CLK_CPU 9 +#define JZ4780_CLK_L2CACHE 10 +#define JZ4780_CLK_AHB0 11 +#define JZ4780_CLK_AHB2PMUX 12 +#define JZ4780_CLK_AHB2 13 +#define JZ4780_CLK_PCLK 14 +#define JZ4780_CLK_DDR 15 +#define JZ4780_CLK_VPU 16 +#define JZ4780_CLK_I2SPLL 17 +#define JZ4780_CLK_I2S 18 +#define JZ4780_CLK_LCD0PIXCLK 19 +#define JZ4780_CLK_LCD1PIXCLK 20 +#define JZ4780_CLK_MSCMUX 21 +#define JZ4780_CLK_MSC0 22 +#define JZ4780_CLK_MSC1 23 +#define JZ4780_CLK_MSC2 24 +#define JZ4780_CLK_UHC 25 +#define JZ4780_CLK_SSIPLL 26 +#define JZ4780_CLK_SSI 27 +#define JZ4780_CLK_CIMMCLK 28 +#define JZ4780_CLK_PCMPLL 29 +#define JZ4780_CLK_PCM 30 +#define JZ4780_CLK_GPU 31 +#define JZ4780_CLK_HDMI 32 +#define JZ4780_CLK_BCH 33 +#define JZ4780_CLK_NEMC 34 +#define JZ4780_CLK_OTG0 35 +#define JZ4780_CLK_SSI0 36 +#define JZ4780_CLK_SMB0 37 +#define JZ4780_CLK_SMB1 38 +#define JZ4780_CLK_SCC 39 +#define JZ4780_CLK_AIC 40 +#define JZ4780_CLK_TSSI0 41 +#define JZ4780_CLK_OWI 42 +#define JZ4780_CLK_KBC 43 +#define JZ4780_CLK_SADC 44 +#define JZ4780_CLK_UART0 45 +#define JZ4780_CLK_UART1 46 +#define JZ4780_CLK_UART2 47 +#define JZ4780_CLK_UART3 48 +#define JZ4780_CLK_SSI1 49 +#define JZ4780_CLK_SSI2 50 +#define JZ4780_CLK_PDMA 51 +#define JZ4780_CLK_GPS 52 +#define JZ4780_CLK_MAC 53 +#define JZ4780_CLK_SMB2 54 +#define JZ4780_CLK_CIM 55 +#define JZ4780_CLK_LCD 56 +#define JZ4780_CLK_TVE 57 +#define JZ4780_CLK_IPU 58 +#define JZ4780_CLK_DDR0 59 +#define JZ4780_CLK_DDR1 60 +#define JZ4780_CLK_SMB3 61 +#define JZ4780_CLK_TSSI1 62 +#define JZ4780_CLK_COMPRESS 63 +#define JZ4780_CLK_AIC1 64 +#define JZ4780_CLK_GPVLC 65 +#define JZ4780_CLK_OTG1 66 +#define JZ4780_CLK_UART4 67 +#define JZ4780_CLK_AHBMON 68 +#define JZ4780_CLK_SMB4 69 +#define JZ4780_CLK_DES 70 +#define JZ4780_CLK_X2D 71 +#define JZ4780_CLK_CORE1 72 + +#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */ diff --git a/include/dt-bindings/phy/phy-pistachio-usb.h b/include/dt-bindings/phy/phy-pistachio-usb.h new file mode 100644 index 0000000..d1877aa --- /dev/null +++ b/include/dt-bindings/phy/phy-pistachio-usb.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2015 Google, Inc. + * + * 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. + */ + +#ifndef _DT_BINDINGS_PHY_PISTACHIO +#define _DT_BINDINGS_PHY_PISTACHIO + +#define REFCLK_XO_CRYSTAL 0x0 +#define REFCLK_X0_EXT_CLK 0x1 +#define REFCLK_CLK_CORE 0x2 + +#endif /* _DT_BINDINGS_PHY_PISTACHIO */ diff --git a/include/linux/bcm47xx_nvram.h b/include/linux/bcm47xx_nvram.h index b12b07e..2793652 100644 --- a/include/linux/bcm47xx_nvram.h +++ b/include/linux/bcm47xx_nvram.h @@ -10,11 +10,17 @@ #include <linux/types.h> #include <linux/kernel.h> +#include <linux/vmalloc.h> -#ifdef CONFIG_BCM47XX +#ifdef CONFIG_BCM47XX_NVRAM int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); int bcm47xx_nvram_gpio_pin(const char *name); +char *bcm47xx_nvram_get_contents(size_t *val_len); +static inline void bcm47xx_nvram_release_contents(char *nvram) +{ + vfree(nvram); +}; #else static inline int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) { @@ -29,6 +35,15 @@ static inline int bcm47xx_nvram_gpio_pin(const char *name) { return -ENOTSUPP; }; + +static inline char *bcm47xx_nvram_get_contents(size_t *val_len) +{ + return NULL; +}; + +static inline void bcm47xx_nvram_release_contents(char *nvram) +{ +}; #endif #endif /* __BCM47XX_NVRAM_H */ diff --git a/arch/mips/jz4740/irq.h b/include/linux/irqchip/ingenic.h index 0f48720..0ee319a 100644 --- a/arch/mips/jz4740/irq.h +++ b/include/linux/irqchip/ingenic.h @@ -12,12 +12,12 @@ * */ -#ifndef __MIPS_JZ4740_IRQ_H__ -#define __MIPS_JZ4740_IRQ_H__ +#ifndef __LINUX_IRQCHIP_INGENIC_H__ +#define __LINUX_IRQCHIP_INGENIC_H__ #include <linux/irq.h> -extern void jz4740_irq_suspend(struct irq_data *data); -extern void jz4740_irq_resume(struct irq_data *data); +extern void ingenic_intc_irq_suspend(struct irq_data *data); +extern void ingenic_intc_irq_resume(struct irq_data *data); #endif diff --git a/include/linux/platform_data/gpio-ath79.h b/include/linux/platform_data/gpio-ath79.h new file mode 100644 index 0000000..88b0db7 --- /dev/null +++ b/include/linux/platform_data/gpio-ath79.h @@ -0,0 +1,19 @@ +/* + * Atheros AR7XXX/AR9XXX GPIO controller platform data + * + * Copyright (C) 2015 Alban Bedel <albeu@free.fr> + * + * 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. + */ + +#ifndef __LINUX_PLATFORM_DATA_GPIO_ATH79_H +#define __LINUX_PLATFORM_DATA_GPIO_ATH79_H + +struct ath79_gpio_platform_data { + unsigned ngpios; + bool oe_inverted; +}; + +#endif diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 4568a5c..c3d1a52 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -29,10 +29,13 @@ struct ssb_sprom { u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */ u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */ u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */ + u8 et2mac[6] __aligned(sizeof(u16)); /* MAC address for extra Ethernet */ u8 et0phyaddr; /* MII address for enet0 */ u8 et1phyaddr; /* MII address for enet1 */ + u8 et2phyaddr; /* MII address for enet2 */ u8 et0mdcport; /* MDIO for enet0 */ u8 et1mdcport; /* MDIO for enet1 */ + u8 et2mdcport; /* MDIO for enet2 */ u16 dev_id; /* Device ID overriding e.g. PCI ID */ u16 board_rev; /* Board revision number from SPROM. */ u16 board_num; /* Board number from SPROM. */ @@ -88,11 +91,14 @@ struct ssb_sprom { u32 ofdm5glpo; /* 5.2GHz OFDM power offset */ u32 ofdm5gpo; /* 5.3GHz OFDM power offset */ u32 ofdm5ghpo; /* 5.8GHz OFDM power offset */ + u32 boardflags; + u32 boardflags2; + u32 boardflags3; + /* TODO: Switch all drivers to new u32 fields and drop below ones */ u16 boardflags_lo; /* Board flags (bits 0-15) */ u16 boardflags_hi; /* Board flags (bits 16-31) */ u16 boardflags2_lo; /* Board flags (bits 32-47) */ u16 boardflags2_hi; /* Board flags (bits 48-63) */ - /* TODO store board flags in a single u64 */ struct ssb_sprom_core_pwr_info core_pwr_info[4]; |