mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
ARM: SoC changes for 5.14
A few SoC (code) changes have queued up this cycle, mostly for minor changes and some refactoring and cleanup of legacy platforms. This branch also contains a few of the fixes that weren't sent in by the end of the release (all fairly minor). - Adding an additional maintainer for the TEE subsystem (Sumit Garg) - Quite a significant modernization of the IXP4xx platforms by Linus Walleij, revisiting with a new PCI host driver/binding, removing legacy mach/* include dependencies and moving platform detection/config to drivers/soc. Also some updates/cleanup of platform data. - Core power domain support for Tegra platforms, and some improvements in build test coverage by adding stubs for compile test targets. - A handful of updates to i.MX platforms, adding legacy (non-PSCI) SMP support on i.MX7D, SoC ID setup for i.MX50, removal of platform data and board fixups for iMX6/7. ... and a few smaller changes and fixes for Samsung, OMAP, Allwinner, Rockchip. -----BEGIN PGP SIGNATURE----- iQJDBAABCgAtFiEElf+HevZ4QCAJmMQ+jBrnPN6EHHcFAmDojiQPHG9sb2ZAbGl4 b20ubmV0AAoJEIwa5zzehBx3Z+kQAJofM2XXE3eHoIGINp+XuYZHCAdTxpIJfhsQ KPt4dzaxq0eBhrD8PICelJ2ymWz4c3sO2z+v79zQfOJdutnFKWTCRstqW8qdq9cE vzYh5pDJy0VmLkYSX/PzvfTLUQDM+Cx0sH/8e2gRwCC/F5tXolLA8lcqWQg9LnlC 5joLOm2WL2uHDgPFZLR6Y1m0KabvUMMpYx6ji9EUx4qtc0VgRMRTSZkRZK4E1PU+ ls175pPZxQfmTyFuHGc1L6KrfnHry8+YX/61sMlBfi96itMnBi05PcxljH8hMkQ8 IVfqPYVnI2vX37f8MhcX4Wec8pKQ9SZqT9mbADGEG23XfZppT5cp7pJUACoZ/wJ5 MMXn99hsEI0NO/gswKr2ZCCskydWrwOqhzubxZrYQtyFt38Sgs+mMLYxyQJKztbZ Laz+JBYKsvIlRctt+fArLp79EJx+CpSUpcha5Q0dQUmz3GWApPpS/6nMiNkq1Myv aByG9HXjOpRI5IiaOi7Fv/m/i+TsO43boNFerUIqPYi2AxmM9D8M2sJcyWHVwQRK glSAjISbp0GHAzVPM5JzhGIrCu4xC5Hf09Q+0OP6c3YVylwKNMurJCjCCql+ft8I Z41WVglS4xO5Y/qiWi+5pzg7/+VESBcsFn6PA5AJAAsDGgU5WHHXhI5kO7eUFAK9 nuIbtqUS =b6Jo -----END PGP SIGNATURE----- Merge tag 'arm-soc-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc Pull ARM SoC updates from Olof Johansson: "A few SoC (code) changes have queued up this cycle, mostly for minor changes and some refactoring and cleanup of legacy platforms. This branch also contains a few of the fixes that weren't sent in by the end of the release (all fairly minor). - Adding an additional maintainer for the TEE subsystem (Sumit Garg) - Quite a significant modernization of the IXP4xx platforms by Linus Walleij, revisiting with a new PCI host driver/binding, removing legacy mach/* include dependencies and moving platform detection/config to drivers/soc. Also some updates/cleanup of platform data. - Core power domain support for Tegra platforms, and some improvements in build test coverage by adding stubs for compile test targets. - A handful of updates to i.MX platforms, adding legacy (non-PSCI) SMP support on i.MX7D, SoC ID setup for i.MX50, removal of platform data and board fixups for iMX6/7. ... and a few smaller changes and fixes for Samsung, OMAP, Allwinner, Rockchip" * tag 'arm-soc-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (53 commits) MAINTAINERS: Add myself as TEE subsystem reviewer ixp4xx: fix spelling mistake in Kconfig "Devce" -> "Device" hw_random: ixp4xx: Add OF support hw_random: ixp4xx: Add DT bindings hw_random: ixp4xx: Turn into a module hw_random: ixp4xx: Use SPDX license tag hw_random: ixp4xx: enable compile-testing pata: ixp4xx: split platform data to its own header soc: ixp4xx: move cpu detection to linux/soc/ixp4xx/cpu.h PCI: ixp4xx: Add a new driver for IXP4xx PCI: ixp4xx: Add device tree bindings for IXP4xx ARM/ixp4xx: Make NEED_MACH_IO_H optional ARM/ixp4xx: Move the virtual IObases MAINTAINERS: ARM/MStar/Sigmastar SoCs: Add a link to the MStar tree ARM: debug: add UART early console support for MSTAR SoCs ARM: dts: ux500: Fix LED probing ARM: imx: add smp support for imx7d ARM: imx6q: drop of_platform_default_populate() from init_machine arm64: dts: rockchip: Update RK3399 PCI host bridge window to 32-bit address memory soc/tegra: fuse: Fix Tegra234-only builds ...
This commit is contained in:
commit
6e207b8821
100
Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
Normal file
100
Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
Normal file
@ -0,0 +1,100 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pci/intel,ixp4xx-pci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel IXP4xx PCI controller
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
description: PCI host controller found in the Intel IXP4xx SoC series.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/pci/pci-bus.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- intel,ixp42x-pci
|
||||
- intel,ixp43x-pci
|
||||
description: The two supported variants are ixp42x and ixp43x,
|
||||
though more variants may exist.
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: IXP4xx-specific registers
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Main PCI interrupt
|
||||
- description: PCI DMA interrupt 1
|
||||
- description: PCI DMA interrupt 2
|
||||
|
||||
ranges:
|
||||
maxItems: 2
|
||||
description: Typically one memory range of 64MB and one IO
|
||||
space range of 64KB.
|
||||
|
||||
dma-ranges:
|
||||
maxItems: 1
|
||||
description: The DMA range tells the PCI host which addresses
|
||||
the RAM is at. It can map only 64MB so if the RAM is bigger
|
||||
than 64MB the DMA access has to be restricted to these
|
||||
addresses.
|
||||
|
||||
"#interrupt-cells": true
|
||||
|
||||
interrupt-map: true
|
||||
|
||||
interrupt-map-mask:
|
||||
items:
|
||||
- const: 0xf800
|
||||
- const: 0
|
||||
- const: 0
|
||||
- const: 7
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- dma-ranges
|
||||
- "#interrupt-cells"
|
||||
- interrupt-map
|
||||
- interrupt-map-mask
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pci@c0000000 {
|
||||
compatible = "intel,ixp43x-pci";
|
||||
reg = <0xc0000000 0x1000>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
device_type = "pci";
|
||||
bus-range = <0x00 0xff>;
|
||||
|
||||
ranges =
|
||||
<0x02000000 0 0x48000000 0x48000000 0 0x04000000>,
|
||||
<0x01000000 0 0x00000000 0x4c000000 0 0x00010000>;
|
||||
dma-ranges =
|
||||
<0x02000000 0 0x00000000 0x00000000 0 0x04000000>;
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0xf800 0 0 7>;
|
||||
interrupt-map =
|
||||
<0x0800 0 0 1 &gpio0 11 3>, /* INT A on slot 1 is irq 11 */
|
||||
<0x0800 0 0 2 &gpio0 10 3>, /* INT B on slot 1 is irq 10 */
|
||||
<0x0800 0 0 3 &gpio0 9 3>, /* INT C on slot 1 is irq 9 */
|
||||
<0x0800 0 0 4 &gpio0 8 3>, /* INT D on slot 1 is irq 8 */
|
||||
<0x1000 0 0 1 &gpio0 10 3>, /* INT A on slot 2 is irq 10 */
|
||||
<0x1000 0 0 2 &gpio0 9 3>, /* INT B on slot 2 is irq 9 */
|
||||
<0x1000 0 0 3 &gpio0 8 3>, /* INT C on slot 2 is irq 8 */
|
||||
<0x1000 0 0 4 &gpio0 11 3>, /* INT D on slot 2 is irq 11 */
|
||||
<0x1800 0 0 1 &gpio0 9 3>, /* INT A on slot 3 is irq 9 */
|
||||
<0x1800 0 0 2 &gpio0 8 3>, /* INT B on slot 3 is irq 8 */
|
||||
<0x1800 0 0 3 &gpio0 11 3>, /* INT C on slot 3 is irq 11 */
|
||||
<0x1800 0 0 4 &gpio0 10 3>; /* INT D on slot 3 is irq 10 */
|
||||
};
|
36
Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
Normal file
36
Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rng/intel,ixp46x-rng.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel IXP46x RNG bindings
|
||||
|
||||
description: |
|
||||
The Intel IXP46x has a random number generator at a fixed physical
|
||||
location in memory. Each read is guaranteed to provide a unique
|
||||
32 bit random number.
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,ixp46x-rng
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
rng@70002100 {
|
||||
compatible = "intel,ixp46x-rng";
|
||||
reg = <0x70002100 4>;
|
||||
};
|
||||
|
18
MAINTAINERS
18
MAINTAINERS
@ -2210,6 +2210,7 @@ M: Daniel Palmer <daniel@thingy.jp>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
W: http://linux-chenxing.org/
|
||||
T: git git://github.com/linux-chenxing/linux.git
|
||||
F: Documentation/devicetree/bindings/arm/mstar/*
|
||||
F: Documentation/devicetree/bindings/clock/mstar,msc313-mpll.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/mstar,msc313-gpio.yaml
|
||||
@ -2479,9 +2480,12 @@ F: drivers/*/*/*s3c24*
|
||||
F: drivers/*/*s3c24*
|
||||
F: drivers/*/*s3c64xx*
|
||||
F: drivers/*/*s5pv210*
|
||||
F: drivers/clocksource/samsung_pwm_timer.c
|
||||
F: drivers/memory/samsung/
|
||||
F: drivers/pwm/pwm-samsung.c
|
||||
F: drivers/soc/samsung/
|
||||
F: drivers/tty/serial/samsung*
|
||||
F: include/clocksource/samsung_pwm.h
|
||||
F: include/linux/platform_data/*s3c*
|
||||
F: include/linux/serial_s3c.h
|
||||
F: include/linux/soc/samsung/
|
||||
@ -9381,6 +9385,7 @@ F: include/linux/soc/ixp4xx/qmgr.h
|
||||
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
|
||||
M: Deepak Saxena <dsaxena@plexity.net>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/intel,ixp46x-rng.yaml
|
||||
F: drivers/char/hw_random/ixp4xx-rng.c
|
||||
|
||||
INTEL KEEM BAY DRM DRIVER
|
||||
@ -13510,12 +13515,6 @@ L: linux-omap@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/arm/mach-omap2/omap_hwmod*data*
|
||||
|
||||
OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
|
||||
M: Benoît Cousson <bcousson@baylibre.com>
|
||||
L: linux-omap@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
|
||||
OMAP HWMOD SUPPORT
|
||||
M: Benoît Cousson <bcousson@baylibre.com>
|
||||
M: Paul Walmsley <paul@pwsan.com>
|
||||
@ -14179,6 +14178,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
|
||||
F: drivers/pci/controller/dwc/pcie-fu740.c
|
||||
|
||||
PCI DRIVER FOR INTEL IXP4XX
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
|
||||
F: drivers/pci/controller/pci-ixp4xx.c
|
||||
|
||||
PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
|
||||
M: Jonathan Derrick <jonathan.derrick@intel.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
@ -18126,6 +18131,7 @@ F: include/media/i2c/tw9910.h
|
||||
|
||||
TEE SUBSYSTEM
|
||||
M: Jens Wiklander <jens.wiklander@linaro.org>
|
||||
R: Sumit Garg <sumit.garg@linaro.org>
|
||||
L: op-tee@lists.trustedfirmware.org
|
||||
S: Maintained
|
||||
F: Documentation/staging/tee.rst
|
||||
|
@ -394,7 +394,8 @@ config ARCH_IXP4XX
|
||||
select HAVE_PCI
|
||||
select IXP4XX_IRQ
|
||||
select IXP4XX_TIMER
|
||||
select NEED_MACH_IO_H
|
||||
# With the new PCI driver this is not needed
|
||||
select NEED_MACH_IO_H if PCI_IXP4XX_LEGACY
|
||||
select USB_EHCI_BIG_ENDIAN_DESC
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
||||
help
|
||||
|
@ -609,6 +609,14 @@ choice
|
||||
when u-boot hands over to the kernel, the system
|
||||
silently crashes, with no serial output at all.
|
||||
|
||||
config DEBUG_MSTARV7_PMUART
|
||||
bool "Kernel low-level debugging messages via MSTARV7 PM UART"
|
||||
depends on ARCH_MSTARV7
|
||||
select DEBUG_UART_8250
|
||||
help
|
||||
Say Y here if you want kernel low-level debugging support
|
||||
for MSTAR ARMv7-based platforms on PM UART.
|
||||
|
||||
config DEBUG_MT6589_UART0
|
||||
bool "Mediatek mt6589 UART0"
|
||||
depends on ARCH_MEDIATEK
|
||||
@ -1607,6 +1615,7 @@ config DEBUG_UART_PHYS
|
||||
default 0x18000400 if DEBUG_BCM_HR2
|
||||
default 0x18023000 if DEBUG_BCM_IPROC_UART3
|
||||
default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
|
||||
default 0x1f221000 if DEBUG_MSTARV7_PMUART
|
||||
default 0x20001000 if DEBUG_HIP01_UART
|
||||
default 0x20060000 if DEBUG_RK29_UART0
|
||||
default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
|
||||
@ -1724,6 +1733,7 @@ config DEBUG_UART_VIRT
|
||||
default 0xf0100000 if DEBUG_DIGICOLOR_UA0
|
||||
default 0xf01fb000 if DEBUG_NOMADIK_UART
|
||||
default 0xf0201000 if DEBUG_BCM2835 || DEBUG_BCM2836
|
||||
default 0xf0221000 if DEBUG_MSTARV7_PMUART
|
||||
default 0xf1000300 if DEBUG_BCM_5301X
|
||||
default 0xf1000400 if DEBUG_BCM_HR2
|
||||
default 0xf1002000 if DEBUG_MT8127_UART0
|
||||
@ -1805,8 +1815,8 @@ config DEBUG_UART_VIRT
|
||||
default 0xfedc0000 if DEBUG_EP93XX
|
||||
default 0xfee003f8 if DEBUG_FOOTBRIDGE_COM1
|
||||
default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
|
||||
default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
|
||||
default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
|
||||
default 0xfec00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
|
||||
default 0xfec00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
|
||||
default 0xfef36000 if DEBUG_HIGHBANK_UART
|
||||
default 0xfefb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1
|
||||
default 0xfefb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2
|
||||
@ -1829,6 +1839,7 @@ config DEBUG_UART_8250_SHIFT
|
||||
default 0 if DEBUG_FOOTBRIDGE_COM1 || ARCH_IOP32X || DEBUG_BCM_5301X || \
|
||||
DEBUG_BCM_HR2 || DEBUG_OMAP7XXUART1 || DEBUG_OMAP7XXUART2 || \
|
||||
DEBUG_OMAP7XXUART3
|
||||
default 3 if DEBUG_MSTARV7_PMUART
|
||||
default 2
|
||||
|
||||
config DEBUG_UART_8250_WORD
|
||||
|
@ -17,17 +17,13 @@
|
||||
* VCP1, VCP2
|
||||
* MLB
|
||||
* ISS
|
||||
* USB3, USB4
|
||||
* USB3
|
||||
*/
|
||||
|
||||
&usb3_tm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usb4_tm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&atl_tm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -4129,28 +4129,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
usb4_tm: target-module@140000 { /* 0x48940000, ap 75 3c.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
reg = <0x140000 0x4>,
|
||||
<0x140010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
ti,sysc-mask = <SYSC_OMAP4_DMADISABLE>;
|
||||
ti,sysc-midle = <SYSC_IDLE_FORCE>,
|
||||
<SYSC_IDLE_NO>,
|
||||
<SYSC_IDLE_SMART>,
|
||||
<SYSC_IDLE_SMART_WKUP>;
|
||||
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
|
||||
<SYSC_IDLE_NO>,
|
||||
<SYSC_IDLE_SMART>,
|
||||
<SYSC_IDLE_SMART_WKUP>;
|
||||
/* Domains (P, C): l3init_pwrdm, l3init_clkdm */
|
||||
clocks = <&l3init_clkctrl DRA7_L3INIT_USB_OTG_SS4_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x140000 0x20000>;
|
||||
};
|
||||
|
||||
target-module@170000 { /* 0x48970000, ap 21 0a.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
reg = <0x170010 0x4>;
|
||||
|
@ -11,7 +11,3 @@
|
||||
&rtctarget {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usb4_tm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -108,7 +108,3 @@
|
||||
&pcie2_rc {
|
||||
compatible = "ti,dra726-pcie-rc", "ti,dra7-pcie";
|
||||
};
|
||||
|
||||
&usb4_tm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -49,49 +49,6 @@
|
||||
reg = <0x41500000 0x100>;
|
||||
};
|
||||
|
||||
target-module@48940000 {
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
reg = <0x48940000 0x4>,
|
||||
<0x48940010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
ti,sysc-mask = <SYSC_OMAP4_DMADISABLE>;
|
||||
ti,sysc-midle = <SYSC_IDLE_FORCE>,
|
||||
<SYSC_IDLE_NO>,
|
||||
<SYSC_IDLE_SMART>,
|
||||
<SYSC_IDLE_SMART_WKUP>;
|
||||
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
|
||||
<SYSC_IDLE_NO>,
|
||||
<SYSC_IDLE_SMART>,
|
||||
<SYSC_IDLE_SMART_WKUP>;
|
||||
clocks = <&l3init_clkctrl DRA7_L3INIT_USB_OTG_SS4_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x48940000 0x20000>;
|
||||
|
||||
omap_dwc3_4: omap_dwc3_4@0 {
|
||||
compatible = "ti,dwc3";
|
||||
reg = <0 0x10000>;
|
||||
interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
utmi-mode = <2>;
|
||||
ranges;
|
||||
status = "disabled";
|
||||
usb4: usb@10000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x10000 0x17000>;
|
||||
interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "peripheral",
|
||||
"host",
|
||||
"otg";
|
||||
maximum-speed = "high-speed";
|
||||
dr_mode = "otg";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
target-module@41501000 {
|
||||
compatible = "ti,sysc-omap2", "ti,sysc";
|
||||
@ -224,3 +181,52 @@
|
||||
&pcie2_rc {
|
||||
compatible = "ti,dra746-pcie-rc", "ti,dra7-pcie";
|
||||
};
|
||||
|
||||
&l4_per3 {
|
||||
segment@0 {
|
||||
usb4_tm: target-module@140000 { /* 0x48940000, ap 75 3c.0 */
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
reg = <0x140000 0x4>,
|
||||
<0x140010 0x4>;
|
||||
reg-names = "rev", "sysc";
|
||||
ti,sysc-mask = <SYSC_OMAP4_DMADISABLE>;
|
||||
ti,sysc-midle = <SYSC_IDLE_FORCE>,
|
||||
<SYSC_IDLE_NO>,
|
||||
<SYSC_IDLE_SMART>,
|
||||
<SYSC_IDLE_SMART_WKUP>;
|
||||
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
|
||||
<SYSC_IDLE_NO>,
|
||||
<SYSC_IDLE_SMART>,
|
||||
<SYSC_IDLE_SMART_WKUP>;
|
||||
/* Domains (P, C): l3init_pwrdm, l3init_clkdm */
|
||||
clocks = <&l3init_clkctrl DRA7_L3INIT_USB_OTG_SS4_CLKCTRL 0>;
|
||||
clock-names = "fck";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x140000 0x20000>;
|
||||
|
||||
omap_dwc3_4: omap_dwc3_4@0 {
|
||||
compatible = "ti,dwc3";
|
||||
reg = <0 0x10000>;
|
||||
interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
utmi-mode = <2>;
|
||||
ranges;
|
||||
status = "disabled";
|
||||
usb4: usb@10000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x10000 0x17000>;
|
||||
interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "peripheral",
|
||||
"host",
|
||||
"otg";
|
||||
maximum-speed = "high-speed";
|
||||
dr_mode = "otg";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -250,7 +250,7 @@
|
||||
nand-ecc-step-size = <512>;
|
||||
nand-bus-width = <8>;
|
||||
/* efs2 partition is secured */
|
||||
secure-regions = <0x500000 0xb00000>;
|
||||
secure-regions = /bits/ 64 <0x500000 0xb00000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -250,8 +250,8 @@
|
||||
nand-ecc-step-size = <512>;
|
||||
nand-bus-width = <8>;
|
||||
/* ico and efs2 partitions are secured */
|
||||
secure-regions = <0x500000 0x500000
|
||||
0xa00000 0xb00000>;
|
||||
secure-regions = /bits/ 64 <0x500000 0x500000
|
||||
0xa00000 0xb00000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include "ste-href-family-pinctrl.dtsi"
|
||||
|
||||
/ {
|
||||
@ -64,17 +65,20 @@
|
||||
reg = <0>;
|
||||
led-cur = /bits/ 8 <0x2f>;
|
||||
max-cur = /bits/ 8 <0x5f>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
chan@1 {
|
||||
reg = <1>;
|
||||
led-cur = /bits/ 8 <0x2f>;
|
||||
max-cur = /bits/ 8 <0x5f>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
chan@2 {
|
||||
reg = <2>;
|
||||
led-cur = /bits/ 8 <0x2f>;
|
||||
max-cur = /bits/ 8 <0x5f>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
lp5521@34 {
|
||||
@ -88,16 +92,19 @@
|
||||
reg = <0>;
|
||||
led-cur = /bits/ 8 <0x2f>;
|
||||
max-cur = /bits/ 8 <0x5f>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
chan@1 {
|
||||
reg = <1>;
|
||||
led-cur = /bits/ 8 <0x2f>;
|
||||
max-cur = /bits/ 8 <0x5f>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
chan@2 {
|
||||
reg = <2>;
|
||||
led-cur = /bits/ 8 <0x2f>;
|
||||
max-cur = /bits/ 8 <0x5f>;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
bh1780@29 {
|
||||
|
@ -85,7 +85,7 @@
|
||||
pinctrl-0 = <&emac_rgmii_pins>;
|
||||
phy-supply = <®_gmac_3v3>;
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -55,6 +55,7 @@ void __init exynos_sysram_init(void)
|
||||
sysram_base_addr = of_iomap(node, 0);
|
||||
sysram_base_phys = of_translate_address(node,
|
||||
of_get_address(node, 0, NULL, NULL));
|
||||
of_node_put(node);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -62,6 +63,7 @@ void __init exynos_sysram_init(void)
|
||||
if (!of_device_is_available(node))
|
||||
continue;
|
||||
sysram_ns_base_addr = of_iomap(node, 0);
|
||||
of_node_put(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
|
||||
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
|
||||
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
|
||||
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
|
||||
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
|
||||
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D_CA7)$(CONFIG_SOC_LS1021A),)
|
||||
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
|
||||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
|
@ -68,11 +68,13 @@ void imx_set_cpu_arg(int cpu, u32 arg);
|
||||
void v7_secondary_startup(void);
|
||||
void imx_scu_map_io(void);
|
||||
void imx_smp_prepare(void);
|
||||
void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
|
||||
#else
|
||||
static inline void imx_scu_map_io(void) {}
|
||||
static inline void imx_smp_prepare(void) {}
|
||||
#endif
|
||||
void imx_src_init(void);
|
||||
void imx7_src_init(void);
|
||||
void imx_gpc_pre_suspend(bool arm_power_off);
|
||||
void imx_gpc_post_resume(void);
|
||||
void imx_gpc_mask_all(void);
|
||||
@ -131,6 +133,7 @@ static inline void imx_init_l2cache(void) {}
|
||||
#endif
|
||||
|
||||
extern const struct smp_operations imx_smp_ops;
|
||||
extern const struct smp_operations imx7_smp_ops;
|
||||
extern const struct smp_operations ls1021a_smp_ops;
|
||||
|
||||
#endif
|
||||
|
@ -21,6 +21,15 @@ diag_reg_offset:
|
||||
|
||||
ENTRY(v7_secondary_startup)
|
||||
ARM_BE8(setend be) @ go BE8 if entered LE
|
||||
mrc p15, 0, r0, c0, c0, 0
|
||||
lsl r0, r0, #16
|
||||
lsr r0, r0, #20
|
||||
/* 0xc07 is cortex A7's ID */
|
||||
mov r1, #0xc00
|
||||
orr r1, #0x7
|
||||
cmp r0, r1
|
||||
beq secondary_startup
|
||||
|
||||
set_diag_reg
|
||||
b secondary_startup
|
||||
ENDPROC(v7_secondary_startup)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <asm/proc-fns.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "hardware.h"
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
@ -40,5 +41,7 @@ int imx_cpu_kill(unsigned int cpu)
|
||||
return 0;
|
||||
imx_enable_cpu(cpu, false);
|
||||
imx_set_cpu_arg(cpu, 0);
|
||||
if (cpu_is_imx7d())
|
||||
imx_gpcv2_set_core1_pdn_pup_by_software(true);
|
||||
return 1;
|
||||
}
|
||||
|
@ -9,6 +9,12 @@
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "hardware.h"
|
||||
|
||||
static void __init imx50_init_early(void)
|
||||
{
|
||||
mxc_set_cpu_type(MXC_CPU_MX50);
|
||||
}
|
||||
|
||||
static const char * const imx50_dt_board_compat[] __initconst = {
|
||||
"fsl,imx50",
|
||||
@ -16,5 +22,6 @@ static const char * const imx50_dt_board_compat[] __initconst = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
|
||||
.init_early = imx50_init_early,
|
||||
.dt_compat = imx50_dt_board_compat,
|
||||
MACHINE_END
|
||||
|
@ -40,27 +40,6 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
|
||||
{
|
||||
phy_write(dev, 0x0d, device);
|
||||
phy_write(dev, 0x0e, reg);
|
||||
phy_write(dev, 0x0d, (1 << 14) | device);
|
||||
phy_write(dev, 0x0e, val);
|
||||
}
|
||||
|
||||
static int ksz9031rn_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
/*
|
||||
* min rx data delay, max rx/tx clock delay,
|
||||
* min rx/tx control delay
|
||||
*/
|
||||
mmd_write_reg(dev, 2, 4, 0);
|
||||
mmd_write_reg(dev, 2, 5, 0);
|
||||
mmd_write_reg(dev, 2, 8, 0x003ff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
|
||||
* as they are used for slots1-7 PERST#
|
||||
@ -89,75 +68,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
|
||||
|
||||
static int ar8031_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
/* To enable AR8031 output a 125MHz clk from CLK_25M */
|
||||
phy_write(dev, 0xd, 0x7);
|
||||
phy_write(dev, 0xe, 0x8016);
|
||||
phy_write(dev, 0xd, 0x4007);
|
||||
|
||||
val = phy_read(dev, 0xe);
|
||||
val &= 0xffe3;
|
||||
val |= 0x18;
|
||||
phy_write(dev, 0xe, val);
|
||||
|
||||
/* introduce tx clock delay */
|
||||
phy_write(dev, 0x1d, 0x5);
|
||||
val = phy_read(dev, 0x1e);
|
||||
val |= 0x0100;
|
||||
phy_write(dev, 0x1e, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PHY_ID_AR8031 0x004dd074
|
||||
|
||||
static int ar8035_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
/* Ar803x phy SmartEEE feature cause link status generates glitch,
|
||||
* which cause ethernet link down/up issue, so disable SmartEEE
|
||||
*/
|
||||
phy_write(dev, 0xd, 0x3);
|
||||
phy_write(dev, 0xe, 0x805d);
|
||||
phy_write(dev, 0xd, 0x4003);
|
||||
|
||||
val = phy_read(dev, 0xe);
|
||||
phy_write(dev, 0xe, val & ~(1 << 8));
|
||||
|
||||
/*
|
||||
* Enable 125MHz clock from CLK_25M on the AR8031. This
|
||||
* is fed in to the IMX6 on the ENET_REF_CLK (V22) pad.
|
||||
* Also, introduce a tx clock delay.
|
||||
*
|
||||
* This is the same as is the AR8031 fixup.
|
||||
*/
|
||||
ar8031_phy_fixup(dev);
|
||||
|
||||
/*check phy power*/
|
||||
val = phy_read(dev, 0x0);
|
||||
if (val & BMCR_PDOWN)
|
||||
phy_write(dev, 0x0, val & ~BMCR_PDOWN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PHY_ID_AR8035 0x004dd072
|
||||
|
||||
static void __init imx6q_enet_phy_init(void)
|
||||
{
|
||||
if (IS_BUILTIN(CONFIG_PHYLIB)) {
|
||||
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
|
||||
ksz9021rn_phy_fixup);
|
||||
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
|
||||
ksz9031rn_phy_fixup);
|
||||
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
|
||||
ar8031_phy_fixup);
|
||||
phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef,
|
||||
ar8035_phy_fixup);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,9 +172,6 @@ static void __init imx6q_init_machine(void)
|
||||
imx_get_soc_revision());
|
||||
|
||||
imx6q_enet_phy_init();
|
||||
|
||||
of_platform_default_populate(NULL, NULL, NULL);
|
||||
|
||||
imx_anatop_init();
|
||||
cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
|
||||
imx6q_1588_init();
|
||||
|
@ -15,31 +15,6 @@
|
||||
#include "common.h"
|
||||
#include "cpuidle.h"
|
||||
|
||||
static int ar8031_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
/* Set RGMII IO voltage to 1.8V */
|
||||
phy_write(dev, 0x1d, 0x1f);
|
||||
phy_write(dev, 0x1e, 0x8);
|
||||
|
||||
/* introduce tx clock delay */
|
||||
phy_write(dev, 0x1d, 0x5);
|
||||
val = phy_read(dev, 0x1e);
|
||||
val |= 0x0100;
|
||||
phy_write(dev, 0x1e, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PHY_ID_AR8031 0x004dd074
|
||||
static void __init imx6sx_enet_phy_init(void)
|
||||
{
|
||||
if (IS_BUILTIN(CONFIG_PHYLIB))
|
||||
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
|
||||
ar8031_phy_fixup);
|
||||
}
|
||||
|
||||
static void __init imx6sx_enet_clk_sel(void)
|
||||
{
|
||||
struct regmap *gpr;
|
||||
@ -57,7 +32,6 @@ static void __init imx6sx_enet_clk_sel(void)
|
||||
|
||||
static inline void imx6sx_enet_init(void)
|
||||
{
|
||||
imx6sx_enet_phy_init();
|
||||
imx6sx_enet_clk_sel();
|
||||
}
|
||||
|
||||
|
@ -14,25 +14,6 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static int ar8031_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
/* Set RGMII IO voltage to 1.8V */
|
||||
phy_write(dev, 0x1d, 0x1f);
|
||||
phy_write(dev, 0x1e, 0x8);
|
||||
|
||||
/* disable phy AR8031 SmartEEE function. */
|
||||
phy_write(dev, 0xd, 0x3);
|
||||
phy_write(dev, 0xe, 0x805d);
|
||||
phy_write(dev, 0xd, 0x4003);
|
||||
val = phy_read(dev, 0xe);
|
||||
val &= ~(0x1 << 8);
|
||||
phy_write(dev, 0xe, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm54220_phy_fixup(struct phy_device *dev)
|
||||
{
|
||||
/* enable RXC skew select RGMII copper mode */
|
||||
@ -44,14 +25,11 @@ static int bcm54220_phy_fixup(struct phy_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PHY_ID_AR8031 0x004dd074
|
||||
#define PHY_ID_BCM54220 0x600d8589
|
||||
|
||||
static void __init imx7d_enet_phy_init(void)
|
||||
{
|
||||
if (IS_BUILTIN(CONFIG_PHYLIB)) {
|
||||
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
|
||||
ar8031_phy_fixup);
|
||||
phy_register_fixup_for_uid(PHY_ID_BCM54220, 0xffffffff,
|
||||
bcm54220_phy_fixup);
|
||||
}
|
||||
@ -91,7 +69,7 @@ static void __init imx7d_init_late(void)
|
||||
static void __init imx7d_init_irq(void)
|
||||
{
|
||||
imx_init_revision_from_anatop();
|
||||
imx_src_init();
|
||||
imx7_src_init();
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
@ -102,6 +80,7 @@ static const char *const imx7d_dt_compat[] __initconst = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
|
||||
.smp = smp_ops(imx7_smp_ops),
|
||||
.init_irq = imx7d_init_irq,
|
||||
.init_machine = imx7d_init_machine,
|
||||
.init_late = imx7d_init_late,
|
||||
|
@ -92,6 +92,32 @@ const struct smp_operations imx_smp_ops __initconst = {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system.
|
||||
*/
|
||||
static void __init imx7_smp_init_cpus(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int i, ncores = 0;
|
||||
|
||||
/* The iMX7D SCU does not report core count, get it from DT */
|
||||
for_each_of_cpu_node(np)
|
||||
ncores++;
|
||||
|
||||
for (i = ncores; i < NR_CPUS; i++)
|
||||
set_cpu_possible(i, false);
|
||||
}
|
||||
|
||||
const struct smp_operations imx7_smp_ops __initconst = {
|
||||
.smp_init_cpus = imx7_smp_init_cpus,
|
||||
.smp_boot_secondary = imx_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = imx_cpu_die,
|
||||
.cpu_kill = imx_cpu_kill,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DCFG_CCSR_SCRATCHRW1 0x200
|
||||
|
||||
static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
|
@ -6,15 +6,19 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include "common.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#define SRC_SCR 0x000
|
||||
#define SRC_GPR1 0x020
|
||||
#define SRC_GPR1_V1 0x020
|
||||
#define SRC_GPR1_V2 0x074
|
||||
#define SRC_GPR1(gpr_v2) ((gpr_v2) ? SRC_GPR1_V2 : SRC_GPR1_V1)
|
||||
#define BP_SRC_SCR_WARM_RESET_ENABLE 0
|
||||
#define BP_SRC_SCR_SW_GPU_RST 1
|
||||
#define BP_SRC_SCR_SW_VPU_RST 2
|
||||
@ -23,9 +27,18 @@
|
||||
#define BP_SRC_SCR_SW_IPU2_RST 12
|
||||
#define BP_SRC_SCR_CORE1_RST 14
|
||||
#define BP_SRC_SCR_CORE1_ENABLE 22
|
||||
/* below is for i.MX7D */
|
||||
#define SRC_A7RCR1 0x008
|
||||
#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
|
||||
#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
|
||||
#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
|
||||
#define GPC_PGC_C1 0x840
|
||||
#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
|
||||
|
||||
static void __iomem *src_base;
|
||||
static DEFINE_SPINLOCK(scr_lock);
|
||||
static bool gpr_v2;
|
||||
static void __iomem *gpc_base;
|
||||
|
||||
static const int sw_reset_bits[5] = {
|
||||
BP_SRC_SCR_SW_GPU_RST,
|
||||
@ -73,17 +86,64 @@ static struct reset_controller_dev imx_reset_controller = {
|
||||
.nr_resets = ARRAY_SIZE(sw_reset_bits),
|
||||
};
|
||||
|
||||
static void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
|
||||
{
|
||||
writel_relaxed(enable, gpc_base + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* The motivation for bringing up the second i.MX7D core inside the kernel
|
||||
* is that legacy vendor bootloaders usually do not implement PSCI support.
|
||||
* This is a significant blocker for systems in the field that are running old
|
||||
* bootloader versions to upgrade to a modern mainline kernel version, as only
|
||||
* one CPU of the i.MX7D would be brought up.
|
||||
* Bring up the second i.MX7D core inside the kernel to make the migration
|
||||
* path to mainline kernel easier for the existing iMX7D users.
|
||||
*/
|
||||
void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn)
|
||||
{
|
||||
u32 reg = pdn ? GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ;
|
||||
u32 val, pup;
|
||||
int ret;
|
||||
|
||||
imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
|
||||
val = readl_relaxed(gpc_base + reg);
|
||||
val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
|
||||
writel_relaxed(val, gpc_base + reg);
|
||||
|
||||
ret = readl_relaxed_poll_timeout_atomic(gpc_base + reg, pup,
|
||||
!(pup & BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7),
|
||||
5, 1000000);
|
||||
if (ret < 0) {
|
||||
pr_err("i.MX7D: CORE1_A7 power up timeout\n");
|
||||
val &= ~BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
|
||||
writel_relaxed(val, gpc_base + reg);
|
||||
}
|
||||
|
||||
imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
|
||||
}
|
||||
|
||||
void imx_enable_cpu(int cpu, bool enable)
|
||||
{
|
||||
u32 mask, val;
|
||||
|
||||
cpu = cpu_logical_map(cpu);
|
||||
mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
|
||||
spin_lock(&scr_lock);
|
||||
val = readl_relaxed(src_base + SRC_SCR);
|
||||
val = enable ? val | mask : val & ~mask;
|
||||
val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
|
||||
writel_relaxed(val, src_base + SRC_SCR);
|
||||
if (gpr_v2) {
|
||||
if (enable)
|
||||
imx_gpcv2_set_core1_pdn_pup_by_software(false);
|
||||
|
||||
mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
|
||||
val = readl_relaxed(src_base + SRC_A7RCR1);
|
||||
val = enable ? val | mask : val & ~mask;
|
||||
writel_relaxed(val, src_base + SRC_A7RCR1);
|
||||
} else {
|
||||
mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
|
||||
val = readl_relaxed(src_base + SRC_SCR);
|
||||
val = enable ? val | mask : val & ~mask;
|
||||
val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
|
||||
writel_relaxed(val, src_base + SRC_SCR);
|
||||
}
|
||||
spin_unlock(&scr_lock);
|
||||
}
|
||||
|
||||
@ -91,19 +151,19 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
|
||||
{
|
||||
cpu = cpu_logical_map(cpu);
|
||||
writel_relaxed(__pa_symbol(jump_addr),
|
||||
src_base + SRC_GPR1 + cpu * 8);
|
||||
src_base + SRC_GPR1(gpr_v2) + cpu * 8);
|
||||
}
|
||||
|
||||
u32 imx_get_cpu_arg(int cpu)
|
||||
{
|
||||
cpu = cpu_logical_map(cpu);
|
||||
return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
|
||||
return readl_relaxed(src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
|
||||
}
|
||||
|
||||
void imx_set_cpu_arg(int cpu, u32 arg)
|
||||
{
|
||||
cpu = cpu_logical_map(cpu);
|
||||
writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
|
||||
writel_relaxed(arg, src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4);
|
||||
}
|
||||
|
||||
void __init imx_src_init(void)
|
||||
@ -131,3 +191,26 @@ void __init imx_src_init(void)
|
||||
writel_relaxed(val, src_base + SRC_SCR);
|
||||
spin_unlock(&scr_lock);
|
||||
}
|
||||
|
||||
void __init imx7_src_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
gpr_v2 = true;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-src");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
src_base = of_iomap(np, 0);
|
||||
if (!src_base)
|
||||
return;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
gpc_base = of_iomap(np, 0);
|
||||
if (!gpc_base)
|
||||
return;
|
||||
}
|
||||
|
@ -28,11 +28,11 @@
|
||||
* ^
|
||||
* ^
|
||||
* imx53_suspend code
|
||||
* PM_INFO structure(imx53_suspend_info)
|
||||
* PM_INFO structure(imx5_cpu_suspend_info)
|
||||
* ======================== low address =======================
|
||||
*/
|
||||
|
||||
/* Offsets of members of struct imx53_suspend_info */
|
||||
/* Offsets of members of struct imx5_cpu_suspend_info */
|
||||
#define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0
|
||||
#define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4
|
||||
#define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8
|
||||
|
@ -7,7 +7,7 @@ comment "IXP4xx Platforms"
|
||||
|
||||
config MACH_IXP4XX_OF
|
||||
bool
|
||||
prompt "Devce Tree IXP4xx boards"
|
||||
prompt "Device Tree IXP4xx boards"
|
||||
default y
|
||||
select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
|
||||
select I2C
|
||||
@ -20,7 +20,7 @@ config MACH_IXP4XX_OF
|
||||
config MACH_NSLU2
|
||||
bool
|
||||
prompt "Linksys NSLU2"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Linksys's
|
||||
NSLU2 NAS device. For more information on this platform,
|
||||
@ -28,7 +28,7 @@ config MACH_NSLU2
|
||||
|
||||
config MACH_AVILA
|
||||
bool "Avila"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the Gateworks
|
||||
Avila Network Platform. For more information on this platform,
|
||||
@ -44,7 +44,7 @@ config MACH_LOFT
|
||||
|
||||
config ARCH_ADI_COYOTE
|
||||
bool "Coyote"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the ADI
|
||||
Engineering Coyote Gateway Reference Platform. For more
|
||||
@ -52,7 +52,7 @@ config ARCH_ADI_COYOTE
|
||||
|
||||
config MACH_GATEWAY7001
|
||||
bool "Gateway 7001"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Gateway's
|
||||
7001 Access Point. For more information on this platform,
|
||||
@ -60,7 +60,7 @@ config MACH_GATEWAY7001
|
||||
|
||||
config MACH_WG302V2
|
||||
bool "Netgear WG302 v2 / WAG302 v2"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Netgear's
|
||||
WG302 v2 or WAG302 v2 Access Points. For more information
|
||||
@ -68,6 +68,7 @@ config MACH_WG302V2
|
||||
|
||||
config ARCH_IXDP425
|
||||
bool "IXDP425"
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Intel's
|
||||
IXDP425 Development Platform (Also known as Richfield).
|
||||
@ -75,6 +76,7 @@ config ARCH_IXDP425
|
||||
|
||||
config MACH_IXDPG425
|
||||
bool "IXDPG425"
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Intel's
|
||||
IXDPG425 Development Platform (Also known as Montajade).
|
||||
@ -120,7 +122,7 @@ config ARCH_PRPMC1100
|
||||
config MACH_NAS100D
|
||||
bool
|
||||
prompt "NAS100D"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Iomega's
|
||||
NAS 100d device. For more information on this platform,
|
||||
@ -129,7 +131,7 @@ config MACH_NAS100D
|
||||
config MACH_DSMG600
|
||||
bool
|
||||
prompt "D-Link DSM-G600 RevA"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support D-Link's
|
||||
DSM-G600 RevA device. For more information on this platform,
|
||||
@ -143,7 +145,7 @@ config ARCH_IXDP4XX
|
||||
config MACH_FSG
|
||||
bool
|
||||
prompt "Freecom FSG-3"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Freecom's
|
||||
FSG-3 device. For more information on this platform,
|
||||
@ -152,7 +154,7 @@ config MACH_FSG
|
||||
config MACH_ARCOM_VULCAN
|
||||
bool
|
||||
prompt "Arcom/Eurotech Vulcan"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Arcom's
|
||||
Vulcan board.
|
||||
@ -173,7 +175,7 @@ config CPU_IXP43X
|
||||
config MACH_GTWX5715
|
||||
bool "Gemtek WX5715 (Linksys WRV54G)"
|
||||
depends on ARCH_IXP4XX
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
This board is currently inside the Linksys WRV54G Gateways.
|
||||
|
||||
@ -196,7 +198,7 @@ config MACH_DEVIXP
|
||||
|
||||
config MACH_MICCPT
|
||||
bool "Omicron MICCPT"
|
||||
select FORCE_PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the MICCPT
|
||||
board from OMICRON electronics GmbH.
|
||||
@ -209,9 +211,16 @@ config MACH_MIC256
|
||||
|
||||
comment "IXP4xx Options"
|
||||
|
||||
config IXP4XX_PCI_LEGACY
|
||||
bool "IXP4xx legacy PCI driver support"
|
||||
depends on PCI
|
||||
help
|
||||
Selects legacy PCI driver.
|
||||
Not recommended for new development.
|
||||
|
||||
config IXP4XX_INDIRECT_PCI
|
||||
bool "Use indirect PCI memory access"
|
||||
depends on PCI
|
||||
depends on IXP4XX_PCI_LEGACY
|
||||
help
|
||||
IXP4xx provides two methods of accessing PCI memory space:
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/platform_data/pata_ixp4xx_cf.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/memory.h>
|
||||
|
@ -27,12 +27,12 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sched_clock.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
#include <linux/irqchip/irq-ixp4xx.h>
|
||||
#include <linux/platform_data/timer-ixp4xx.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <mach/udc.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/exception.h>
|
||||
@ -44,6 +44,27 @@
|
||||
|
||||
#include "irqs.h"
|
||||
|
||||
u32 ixp4xx_read_feature_bits(void)
|
||||
{
|
||||
u32 val = ~__raw_readl(IXP4XX_EXP_CFG2);
|
||||
|
||||
if (cpu_is_ixp42x_rev_a0())
|
||||
return IXP42X_FEATURE_MASK & ~(IXP4XX_FEATURE_RCOMP |
|
||||
IXP4XX_FEATURE_AES);
|
||||
if (cpu_is_ixp42x())
|
||||
return val & IXP42X_FEATURE_MASK;
|
||||
if (cpu_is_ixp43x())
|
||||
return val & IXP43X_FEATURE_MASK;
|
||||
return val & IXP46X_FEATURE_MASK;
|
||||
}
|
||||
EXPORT_SYMBOL(ixp4xx_read_feature_bits);
|
||||
|
||||
void ixp4xx_write_feature_bits(u32 value)
|
||||
{
|
||||
__raw_writel(~value, IXP4XX_EXP_CFG2);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp4xx_write_feature_bits);
|
||||
|
||||
#define IXP4XX_TIMER_FREQ 66666000
|
||||
|
||||
/*************************************************************************
|
||||
@ -215,6 +236,27 @@ static struct resource ixp46x_i2c_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
/* A single 32-bit register on IXP46x */
|
||||
#define IXP4XX_HWRANDOM_BASE_PHYS 0x70002100
|
||||
|
||||
static struct resource ixp46x_hwrandom_resource[] = {
|
||||
{
|
||||
.start = IXP4XX_HWRANDOM_BASE_PHYS,
|
||||
.end = IXP4XX_HWRANDOM_BASE_PHYS + 0x3,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ixp46x_hwrandom_device = {
|
||||
.name = "ixp4xx-hwrandom",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.resource = ixp46x_hwrandom_resource,
|
||||
.num_resources = ARRAY_SIZE(ixp46x_hwrandom_resource),
|
||||
};
|
||||
|
||||
/*
|
||||
* I2C controller. The IXP46x uses the same block as the IOP3xx, so
|
||||
* we just use the same device name.
|
||||
@ -227,7 +269,8 @@ static struct platform_device ixp46x_i2c_controller = {
|
||||
};
|
||||
|
||||
static struct platform_device *ixp46x_devices[] __initdata = {
|
||||
&ixp46x_i2c_controller
|
||||
&ixp46x_hwrandom_device,
|
||||
&ixp46x_i2c_controller,
|
||||
};
|
||||
|
||||
unsigned long ixp4xx_exp_bus_size;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "irqs.h"
|
||||
|
||||
|
@ -1,54 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* arch/arm/mach-ixp4xx/include/mach/cpu.h
|
||||
*
|
||||
* IXP4XX cpu type detection
|
||||
*
|
||||
* Copyright (C) 2007 MontaVista Software, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_CPU_H__
|
||||
#define __ASM_ARCH_CPU_H__
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm/cputype.h>
|
||||
|
||||
/* Processor id value in CP15 Register 0 */
|
||||
#define IXP42X_PROCESSOR_ID_VALUE 0x690541c0 /* including unused 0x690541Ex */
|
||||
#define IXP42X_PROCESSOR_ID_MASK 0xffffffc0
|
||||
|
||||
#define IXP43X_PROCESSOR_ID_VALUE 0x69054040
|
||||
#define IXP43X_PROCESSOR_ID_MASK 0xfffffff0
|
||||
|
||||
#define IXP46X_PROCESSOR_ID_VALUE 0x69054200 /* including IXP455 */
|
||||
#define IXP46X_PROCESSOR_ID_MASK 0xfffffff0
|
||||
|
||||
#define cpu_is_ixp42x_rev_a0() ((read_cpuid_id() & (IXP42X_PROCESSOR_ID_MASK | 0xF)) == \
|
||||
IXP42X_PROCESSOR_ID_VALUE)
|
||||
#define cpu_is_ixp42x() ((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \
|
||||
IXP42X_PROCESSOR_ID_VALUE)
|
||||
#define cpu_is_ixp43x() ((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \
|
||||
IXP43X_PROCESSOR_ID_VALUE)
|
||||
#define cpu_is_ixp46x() ((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \
|
||||
IXP46X_PROCESSOR_ID_VALUE)
|
||||
|
||||
static inline u32 ixp4xx_read_feature_bits(void)
|
||||
{
|
||||
u32 val = ~__raw_readl(IXP4XX_EXP_CFG2);
|
||||
|
||||
if (cpu_is_ixp42x_rev_a0())
|
||||
return IXP42X_FEATURE_MASK & ~(IXP4XX_FEATURE_RCOMP |
|
||||
IXP4XX_FEATURE_AES);
|
||||
if (cpu_is_ixp42x())
|
||||
return val & IXP42X_FEATURE_MASK;
|
||||
if (cpu_is_ixp43x())
|
||||
return val & IXP43X_FEATURE_MASK;
|
||||
return val & IXP46X_FEATURE_MASK;
|
||||
}
|
||||
|
||||
static inline void ixp4xx_write_feature_bits(u32 value)
|
||||
{
|
||||
__raw_writel(~value, IXP4XX_EXP_CFG2);
|
||||
}
|
||||
|
||||
#endif /* _ASM_ARCH_CPU_H */
|
@ -23,7 +23,7 @@
|
||||
#include "ixp4xx-regs.h"
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <mach/cpu.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
#endif
|
||||
|
||||
/* Platform helper functions and definitions */
|
||||
|
@ -45,21 +45,21 @@
|
||||
* it can be used with the low-level debug code.
|
||||
*/
|
||||
#define IXP4XX_PERIPHERAL_BASE_PHYS 0xC8000000
|
||||
#define IXP4XX_PERIPHERAL_BASE_VIRT IOMEM(0xFEF00000)
|
||||
#define IXP4XX_PERIPHERAL_BASE_VIRT IOMEM(0xFEC00000)
|
||||
#define IXP4XX_PERIPHERAL_REGION_SIZE 0x00013000
|
||||
|
||||
/*
|
||||
* PCI Config registers
|
||||
*/
|
||||
#define IXP4XX_PCI_CFG_BASE_PHYS 0xC0000000
|
||||
#define IXP4XX_PCI_CFG_BASE_VIRT IOMEM(0xFEF13000)
|
||||
#define IXP4XX_PCI_CFG_BASE_VIRT IOMEM(0xFEC13000)
|
||||
#define IXP4XX_PCI_CFG_REGION_SIZE 0x00001000
|
||||
|
||||
/*
|
||||
* Expansion BUS Configuration registers
|
||||
*/
|
||||
#define IXP4XX_EXP_CFG_BASE_PHYS 0xC4000000
|
||||
#define IXP4XX_EXP_CFG_BASE_VIRT 0xFEF14000
|
||||
#define IXP4XX_EXP_CFG_BASE_VIRT 0xFEC14000
|
||||
#define IXP4XX_EXP_CFG_REGION_SIZE 0x00001000
|
||||
|
||||
#define IXP4XX_EXP_CS0_OFFSET 0x00
|
||||
@ -120,6 +120,7 @@
|
||||
#define IXP4XX_SSP_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x12000)
|
||||
|
||||
|
||||
/* The UART is explicitly put in the beginning of fixmap */
|
||||
#define IXP4XX_UART1_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x0000)
|
||||
#define IXP4XX_UART2_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000)
|
||||
#define IXP4XX_PMU_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000)
|
||||
@ -299,58 +300,4 @@
|
||||
|
||||
#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */
|
||||
|
||||
/* "fuse" bits of IXP_EXP_CFG2 */
|
||||
/* All IXP4xx CPUs */
|
||||
#define IXP4XX_FEATURE_RCOMP (1 << 0)
|
||||
#define IXP4XX_FEATURE_USB_DEVICE (1 << 1)
|
||||
#define IXP4XX_FEATURE_HASH (1 << 2)
|
||||
#define IXP4XX_FEATURE_AES (1 << 3)
|
||||
#define IXP4XX_FEATURE_DES (1 << 4)
|
||||
#define IXP4XX_FEATURE_HDLC (1 << 5)
|
||||
#define IXP4XX_FEATURE_AAL (1 << 6)
|
||||
#define IXP4XX_FEATURE_HSS (1 << 7)
|
||||
#define IXP4XX_FEATURE_UTOPIA (1 << 8)
|
||||
#define IXP4XX_FEATURE_NPEB_ETH0 (1 << 9)
|
||||
#define IXP4XX_FEATURE_NPEC_ETH (1 << 10)
|
||||
#define IXP4XX_FEATURE_RESET_NPEA (1 << 11)
|
||||
#define IXP4XX_FEATURE_RESET_NPEB (1 << 12)
|
||||
#define IXP4XX_FEATURE_RESET_NPEC (1 << 13)
|
||||
#define IXP4XX_FEATURE_PCI (1 << 14)
|
||||
#define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT (3 << 16)
|
||||
#define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22)
|
||||
#define IXP42X_FEATURE_MASK (IXP4XX_FEATURE_RCOMP | \
|
||||
IXP4XX_FEATURE_USB_DEVICE | \
|
||||
IXP4XX_FEATURE_HASH | \
|
||||
IXP4XX_FEATURE_AES | \
|
||||
IXP4XX_FEATURE_DES | \
|
||||
IXP4XX_FEATURE_HDLC | \
|
||||
IXP4XX_FEATURE_AAL | \
|
||||
IXP4XX_FEATURE_HSS | \
|
||||
IXP4XX_FEATURE_UTOPIA | \
|
||||
IXP4XX_FEATURE_NPEB_ETH0 | \
|
||||
IXP4XX_FEATURE_NPEC_ETH | \
|
||||
IXP4XX_FEATURE_RESET_NPEA | \
|
||||
IXP4XX_FEATURE_RESET_NPEB | \
|
||||
IXP4XX_FEATURE_RESET_NPEC | \
|
||||
IXP4XX_FEATURE_PCI | \
|
||||
IXP4XX_FEATURE_UTOPIA_PHY_LIMIT | \
|
||||
IXP4XX_FEATURE_XSCALE_MAX_FREQ)
|
||||
|
||||
|
||||
/* IXP43x/46x CPUs */
|
||||
#define IXP4XX_FEATURE_ECC_TIMESYNC (1 << 15)
|
||||
#define IXP4XX_FEATURE_USB_HOST (1 << 18)
|
||||
#define IXP4XX_FEATURE_NPEA_ETH (1 << 19)
|
||||
#define IXP43X_FEATURE_MASK (IXP42X_FEATURE_MASK | \
|
||||
IXP4XX_FEATURE_ECC_TIMESYNC | \
|
||||
IXP4XX_FEATURE_USB_HOST | \
|
||||
IXP4XX_FEATURE_NPEA_ETH)
|
||||
|
||||
/* IXP46x CPU (including IXP455) only */
|
||||
#define IXP4XX_FEATURE_NPEB_ETH_1_TO_3 (1 << 20)
|
||||
#define IXP4XX_FEATURE_RSA (1 << 21)
|
||||
#define IXP46X_FEATURE_MASK (IXP43X_FEATURE_MASK | \
|
||||
IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \
|
||||
IXP4XX_FEATURE_RSA)
|
||||
|
||||
#endif
|
||||
|
@ -79,20 +79,6 @@ extern unsigned long ixp4xx_exp_bus_size;
|
||||
#define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66MHzi APB BUS */
|
||||
#define IXP4XX_UART_XTAL 14745600
|
||||
|
||||
/*
|
||||
* This structure provide a means for the board setup code
|
||||
* to give information to th pata_ixp4xx driver. It is
|
||||
* passed as platform_data.
|
||||
*/
|
||||
struct ixp4xx_pata_data {
|
||||
volatile u32 *cs0_cfg;
|
||||
volatile u32 *cs1_cfg;
|
||||
unsigned long cs0_bits;
|
||||
unsigned long cs1_bits;
|
||||
void __iomem *cs0;
|
||||
void __iomem *cs1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Frequency of clock used for primary clocksource
|
||||
*/
|
||||
|
@ -9,8 +9,12 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/ixp4xx-regs.h>
|
||||
/*
|
||||
* These are the only fixed phys to virt mappings we ever need
|
||||
* we put it right after the UART mapping at 0xffc80000-0xffc81fff
|
||||
*/
|
||||
#define IXP4XX_EXP_CFG_BASE_PHYS 0xC4000000
|
||||
#define IXP4XX_EXP_CFG_BASE_VIRT 0xFEC14000
|
||||
|
||||
static struct map_desc ixp4xx_of_io_desc[] __initdata = {
|
||||
/*
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "irqs.h"
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "irqs.h"
|
||||
|
||||
|
@ -65,14 +65,14 @@ config MACH_OMAP_INNOVATOR
|
||||
config MACH_OMAP_H2
|
||||
bool "TI H2 Support"
|
||||
depends on ARCH_OMAP16XX
|
||||
help
|
||||
help
|
||||
TI OMAP 1610/1611B H2 board support. Say Y here if you have such
|
||||
a board.
|
||||
|
||||
config MACH_OMAP_H3
|
||||
bool "TI H3 Support"
|
||||
depends on ARCH_OMAP16XX
|
||||
help
|
||||
help
|
||||
TI OMAP 1710 H3 board support. Say Y here if you have such
|
||||
a board.
|
||||
|
||||
@ -85,14 +85,14 @@ config MACH_HERALD
|
||||
config MACH_OMAP_OSK
|
||||
bool "TI OSK Support"
|
||||
depends on ARCH_OMAP16XX
|
||||
help
|
||||
help
|
||||
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
|
||||
if you have such a board.
|
||||
|
||||
config OMAP_OSK_MISTRAL
|
||||
bool "Mistral QVGA board Support"
|
||||
depends on MACH_OMAP_OSK
|
||||
help
|
||||
help
|
||||
The OSK supports an optional add-on board with a Quarter-VGA
|
||||
touchscreen, PDA-ish buttons, a resume button, bicolor LED,
|
||||
and camera connector. Say Y here if you have this board.
|
||||
@ -100,14 +100,14 @@ config OMAP_OSK_MISTRAL
|
||||
config MACH_OMAP_PERSEUS2
|
||||
bool "TI Perseus2"
|
||||
depends on ARCH_OMAP730
|
||||
help
|
||||
help
|
||||
Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
|
||||
a board.
|
||||
|
||||
config MACH_OMAP_FSAMPLE
|
||||
bool "TI F-Sample"
|
||||
depends on ARCH_OMAP730
|
||||
help
|
||||
help
|
||||
Support for TI OMAP 850 F-Sample board. Say Y here if you have such
|
||||
a board.
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
extern struct omap_domain_base cm_base;
|
||||
extern struct omap_domain_base cm2_base;
|
||||
extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
|
||||
# endif
|
||||
|
||||
/*
|
||||
|
@ -37,19 +37,6 @@ struct omap_domain_base cm2_base;
|
||||
#define CM_NO_CLOCKS 0x1
|
||||
#define CM_SINGLE_INSTANCE 0x2
|
||||
|
||||
/**
|
||||
* omap2_set_globals_cm - set the CM/CM2 base addresses (for early use)
|
||||
* @cm: CM base virtual address
|
||||
* @cm2: CM2 base virtual address (if present on the booted SoC)
|
||||
*
|
||||
* XXX Will be replaced when the PRM/CM drivers are completed.
|
||||
*/
|
||||
void __init omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2)
|
||||
{
|
||||
cm_base.va = cm;
|
||||
cm2_base.va = cm2;
|
||||
}
|
||||
|
||||
/**
|
||||
* cm_split_idlest_reg - split CM_IDLEST reg addr into its components
|
||||
* @idlest_reg: CM_IDLEST* virtual address
|
||||
|
@ -130,7 +130,6 @@ void am33xx_init_early(void);
|
||||
void am35xx_init_early(void);
|
||||
void ti814x_init_early(void);
|
||||
void ti816x_init_early(void);
|
||||
void am33xx_init_early(void);
|
||||
void am43xx_init_early(void);
|
||||
void am43xx_init_late(void);
|
||||
void omap4430_init_early(void);
|
||||
|
@ -136,11 +136,6 @@ struct omap3_control_regs {
|
||||
static struct omap3_control_regs control_context;
|
||||
#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
|
||||
|
||||
void __init omap2_set_globals_control(void __iomem *ctrl)
|
||||
{
|
||||
omap2_ctrl_base = ctrl;
|
||||
}
|
||||
|
||||
u8 omap_ctrl_readb(u16 offset)
|
||||
{
|
||||
u32 val;
|
||||
|
@ -528,7 +528,6 @@ extern int omap3_ctrl_save_padconf(void);
|
||||
void omap3_ctrl_init(void);
|
||||
int omap2_control_base_init(void);
|
||||
int omap_control_init(void);
|
||||
void omap2_set_globals_control(void __iomem *ctrl);
|
||||
void __init omap3_control_legacy_iomap_init(void);
|
||||
#else
|
||||
#define omap_ctrl_readb(x) 0
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/platform_data/pm33xx.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/cpuidle.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/suspend.h>
|
||||
@ -324,6 +325,44 @@ static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
/*
|
||||
* Block system suspend initially. Later on pm33xx sets up it's own
|
||||
* platform_suspend_ops after probe. That depends also on loaded
|
||||
* wkup_m3_ipc and booted am335x-pm-firmware.elf.
|
||||
*/
|
||||
static int amx3_suspend_block(suspend_state_t state)
|
||||
{
|
||||
pr_warn("PM not initialized for pm33xx, wkup_m3_ipc, or am335x-pm-firmware.elf\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int amx3_pm_valid(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops amx3_blocked_pm_ops = {
|
||||
.begin = amx3_suspend_block,
|
||||
.valid = amx3_pm_valid,
|
||||
};
|
||||
|
||||
static void __init amx3_block_suspend(void)
|
||||
{
|
||||
suspend_set_ops(&amx3_blocked_pm_ops);
|
||||
}
|
||||
#else
|
||||
static inline void amx3_block_suspend(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
||||
int __init amx3_common_pm_init(void)
|
||||
{
|
||||
struct am33xx_pm_platform_data *pdata;
|
||||
@ -337,6 +376,7 @@ int __init amx3_common_pm_init(void)
|
||||
devinfo.size_data = sizeof(*pdata);
|
||||
devinfo.id = -1;
|
||||
platform_device_register_full(&devinfo);
|
||||
amx3_block_suspend();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -271,7 +271,6 @@ static int rx1950_led_blink_set(struct gpio_desc *desc, int state,
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (delay_on && delay_off && !*delay_on && !*delay_off)
|
||||
|
@ -16,6 +16,7 @@ config ARCH_SUNXI
|
||||
select IRQ_FASTEOI_HIERARCHY_HANDLERS
|
||||
select PINCTRL
|
||||
select RESET_CONTROLLER
|
||||
select SUN4I_TIMER
|
||||
help
|
||||
This enables support for Allwinner sunxi based SoCs like the A64.
|
||||
|
||||
|
@ -79,7 +79,7 @@
|
||||
&emac {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rgmii_pins>;
|
||||
phy-mode = "rgmii-id";
|
||||
phy-mode = "rgmii-txid";
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
phy-supply = <®_dc1sw>;
|
||||
status = "okay";
|
||||
|
@ -227,7 +227,7 @@
|
||||
<&pcie_phy 2>, <&pcie_phy 3>;
|
||||
phy-names = "pcie-phy-0", "pcie-phy-1",
|
||||
"pcie-phy-2", "pcie-phy-3";
|
||||
ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000>,
|
||||
ranges = <0x82000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000>,
|
||||
<0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>;
|
||||
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
|
||||
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>,
|
||||
|
@ -1058,7 +1058,7 @@ config PATA_ISAPNP
|
||||
|
||||
config PATA_IXP4XX_CF
|
||||
tristate "IXP4XX Compact Flash support"
|
||||
depends on ARCH_IXP4XX
|
||||
depends on ARCH_IXP4XX || COMPILE_TEST
|
||||
help
|
||||
This option enables support for a Compact Flash connected on
|
||||
the ixp4xx expansion bus. This driver had been written for
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/libata.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/pata_ixp4xx_cf.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#define DRV_NAME "pata_ixp4xx_cf"
|
||||
|
@ -152,7 +152,7 @@ config HW_RANDOM_VIA
|
||||
|
||||
config HW_RANDOM_IXP4XX
|
||||
tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
|
||||
depends on ARCH_IXP4XX
|
||||
depends on ARCH_IXP4XX || COMPILE_TEST
|
||||
default HW_RANDOM
|
||||
help
|
||||
This driver provides kernel-side support for the Pseudo-Random
|
||||
|
@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* drivers/char/hw_random/ixp4xx-rng.c
|
||||
*
|
||||
@ -8,23 +9,20 @@
|
||||
* Copyright 2005 (c) MontaVista Software, Inc.
|
||||
*
|
||||
* Fixes by Michael Buesch
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
|
||||
static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer)
|
||||
{
|
||||
@ -40,35 +38,40 @@ static struct hwrng ixp4xx_rng_ops = {
|
||||
.data_read = ixp4xx_rng_data_read,
|
||||
};
|
||||
|
||||
static int __init ixp4xx_rng_init(void)
|
||||
static int ixp4xx_rng_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem * rng_base;
|
||||
int err;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
|
||||
if (!cpu_is_ixp46x()) /* includes IXP455 */
|
||||
return -ENOSYS;
|
||||
|
||||
rng_base = ioremap(0x70002100, 4);
|
||||
if (!rng_base)
|
||||
return -ENOMEM;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rng_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(rng_base))
|
||||
return PTR_ERR(rng_base);
|
||||
|
||||
ixp4xx_rng_ops.priv = (unsigned long)rng_base;
|
||||
err = hwrng_register(&ixp4xx_rng_ops);
|
||||
if (err)
|
||||
iounmap(rng_base);
|
||||
|
||||
return err;
|
||||
return devm_hwrng_register(dev, &ixp4xx_rng_ops);
|
||||
}
|
||||
|
||||
static void __exit ixp4xx_rng_exit(void)
|
||||
{
|
||||
void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv;
|
||||
static const struct of_device_id ixp4xx_rng_of_match[] = {
|
||||
{
|
||||
.compatible = "intel,ixp46x-rng",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ixp4xx_rng_of_match);
|
||||
|
||||
hwrng_unregister(&ixp4xx_rng_ops);
|
||||
iounmap(rng_base);
|
||||
}
|
||||
|
||||
module_init(ixp4xx_rng_init);
|
||||
module_exit(ixp4xx_rng_exit);
|
||||
static struct platform_driver ixp4xx_rng_driver = {
|
||||
.driver = {
|
||||
.name = "ixp4xx-hwrandom",
|
||||
.of_match_table = ixp4xx_rng_of_match,
|
||||
},
|
||||
.probe = ixp4xx_rng_probe,
|
||||
};
|
||||
module_platform_driver(ixp4xx_rng_driver);
|
||||
|
||||
MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
|
||||
MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x");
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include <linux/soc/ixp4xx/npe.h>
|
||||
#include <linux/soc/ixp4xx/qmgr.h>
|
||||
|
||||
/* Intermittent includes, delete this after v5.14-rc1 */
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
#include <mach/ixp4xx-regs.h>
|
||||
|
||||
#define MAX_KEYLEN 32
|
||||
|
||||
/* hash: cfgword + 2 * digestlen; crypt: keylen + cfgword */
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/soc/ixp4xx/npe.h>
|
||||
#include <linux/soc/ixp4xx/qmgr.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
|
||||
#include "ixp46x_ts.h"
|
||||
|
||||
|
@ -12,9 +12,8 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
|
||||
#include "ixp46x_ts.h"
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/ixp4xx/npe.h>
|
||||
#include <linux/soc/ixp4xx/qmgr.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
|
||||
#define DEBUG_DESC 0
|
||||
#define DEBUG_RX 0
|
||||
|
@ -37,6 +37,14 @@ config PCI_FTPCI100
|
||||
depends on OF
|
||||
default ARCH_GEMINI
|
||||
|
||||
config PCI_IXP4XX
|
||||
bool "Intel IXP4xx PCI controller"
|
||||
depends on ARM && OF
|
||||
default ARCH_IXP4XX
|
||||
help
|
||||
Say Y here if you want support for the PCI host controller found
|
||||
in the Intel IXP4xx XScale-based network processor SoC.
|
||||
|
||||
config PCI_TEGRA
|
||||
bool "NVIDIA Tegra PCIe controller"
|
||||
depends on ARCH_TEGRA || COMPILE_TEST
|
||||
|
@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_PCIE_CADENCE) += cadence/
|
||||
obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o
|
||||
obj-$(CONFIG_PCI_IXP4XX) += pci-ixp4xx.o
|
||||
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
|
||||
obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o
|
||||
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
|
||||
|
671
drivers/pci/controller/pci-ixp4xx.c
Normal file
671
drivers/pci/controller/pci-ixp4xx.c
Normal file
@ -0,0 +1,671 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Support for Intel IXP4xx PCI host controller
|
||||
*
|
||||
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
|
||||
*
|
||||
* Based on the IXP4xx arch/arm/mach-ixp4xx/common-pci.c driver
|
||||
* Copyright (C) 2002 Intel Corporation
|
||||
* Copyright (C) 2003 Greg Ungerer <gerg@linux-m68k.org>
|
||||
* Copyright (C) 2003-2004 MontaVista Software, Inc.
|
||||
* Copyright (C) 2005 Deepak Saxena <dsaxena@plexity.net>
|
||||
* Copyright (C) 2005 Alessandro Zummo <a.zummo@towertech.it>
|
||||
*
|
||||
* TODO:
|
||||
* - Test IO-space access
|
||||
* - DMA support
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
/* Register offsets */
|
||||
#define IXP4XX_PCI_NP_AD 0x00
|
||||
#define IXP4XX_PCI_NP_CBE 0x04
|
||||
#define IXP4XX_PCI_NP_WDATA 0x08
|
||||
#define IXP4XX_PCI_NP_RDATA 0x0c
|
||||
#define IXP4XX_PCI_CRP_AD_CBE 0x10
|
||||
#define IXP4XX_PCI_CRP_WDATA 0x14
|
||||
#define IXP4XX_PCI_CRP_RDATA 0x18
|
||||
#define IXP4XX_PCI_CSR 0x1c
|
||||
#define IXP4XX_PCI_ISR 0x20
|
||||
#define IXP4XX_PCI_INTEN 0x24
|
||||
#define IXP4XX_PCI_DMACTRL 0x28
|
||||
#define IXP4XX_PCI_AHBMEMBASE 0x2c
|
||||
#define IXP4XX_PCI_AHBIOBASE 0x30
|
||||
#define IXP4XX_PCI_PCIMEMBASE 0x34
|
||||
#define IXP4XX_PCI_AHBDOORBELL 0x38
|
||||
#define IXP4XX_PCI_PCIDOORBELL 0x3c
|
||||
#define IXP4XX_PCI_ATPDMA0_AHBADDR 0x40
|
||||
#define IXP4XX_PCI_ATPDMA0_PCIADDR 0x44
|
||||
#define IXP4XX_PCI_ATPDMA0_LENADDR 0x48
|
||||
#define IXP4XX_PCI_ATPDMA1_AHBADDR 0x4c
|
||||
#define IXP4XX_PCI_ATPDMA1_PCIADDR 0x50
|
||||
#define IXP4XX_PCI_ATPDMA1_LENADDR 0x54
|
||||
|
||||
/* CSR bit definitions */
|
||||
#define IXP4XX_PCI_CSR_HOST BIT(0)
|
||||
#define IXP4XX_PCI_CSR_ARBEN BIT(1)
|
||||
#define IXP4XX_PCI_CSR_ADS BIT(2)
|
||||
#define IXP4XX_PCI_CSR_PDS BIT(3)
|
||||
#define IXP4XX_PCI_CSR_ABE BIT(4)
|
||||
#define IXP4XX_PCI_CSR_DBT BIT(5)
|
||||
#define IXP4XX_PCI_CSR_ASE BIT(8)
|
||||
#define IXP4XX_PCI_CSR_IC BIT(15)
|
||||
#define IXP4XX_PCI_CSR_PRST BIT(16)
|
||||
|
||||
/* ISR (Interrupt status) Register bit definitions */
|
||||
#define IXP4XX_PCI_ISR_PSE BIT(0)
|
||||
#define IXP4XX_PCI_ISR_PFE BIT(1)
|
||||
#define IXP4XX_PCI_ISR_PPE BIT(2)
|
||||
#define IXP4XX_PCI_ISR_AHBE BIT(3)
|
||||
#define IXP4XX_PCI_ISR_APDC BIT(4)
|
||||
#define IXP4XX_PCI_ISR_PADC BIT(5)
|
||||
#define IXP4XX_PCI_ISR_ADB BIT(6)
|
||||
#define IXP4XX_PCI_ISR_PDB BIT(7)
|
||||
|
||||
/* INTEN (Interrupt Enable) Register bit definitions */
|
||||
#define IXP4XX_PCI_INTEN_PSE BIT(0)
|
||||
#define IXP4XX_PCI_INTEN_PFE BIT(1)
|
||||
#define IXP4XX_PCI_INTEN_PPE BIT(2)
|
||||
#define IXP4XX_PCI_INTEN_AHBE BIT(3)
|
||||
#define IXP4XX_PCI_INTEN_APDC BIT(4)
|
||||
#define IXP4XX_PCI_INTEN_PADC BIT(5)
|
||||
#define IXP4XX_PCI_INTEN_ADB BIT(6)
|
||||
#define IXP4XX_PCI_INTEN_PDB BIT(7)
|
||||
|
||||
/* Shift value for byte enable on NP cmd/byte enable register */
|
||||
#define IXP4XX_PCI_NP_CBE_BESL 4
|
||||
|
||||
/* PCI commands supported by NP access unit */
|
||||
#define NP_CMD_IOREAD 0x2
|
||||
#define NP_CMD_IOWRITE 0x3
|
||||
#define NP_CMD_CONFIGREAD 0xa
|
||||
#define NP_CMD_CONFIGWRITE 0xb
|
||||
#define NP_CMD_MEMREAD 0x6
|
||||
#define NP_CMD_MEMWRITE 0x7
|
||||
|
||||
/* Constants for CRP access into local config space */
|
||||
#define CRP_AD_CBE_BESL 20
|
||||
#define CRP_AD_CBE_WRITE 0x00010000
|
||||
|
||||
/* Special PCI configuration space registers for this controller */
|
||||
#define IXP4XX_PCI_RTOTTO 0x40
|
||||
|
||||
struct ixp4xx_pci {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
bool errata_hammer;
|
||||
bool host_mode;
|
||||
};
|
||||
|
||||
/*
|
||||
* The IXP4xx has a peculiar address bus that will change the
|
||||
* byte order on SoC peripherals depending on whether the device
|
||||
* operates in big-endian or little-endian mode. That means that
|
||||
* readl() and writel() that always use little-endian access
|
||||
* will not work for SoC peripherals such as the PCI controller
|
||||
* when used in big-endian mode. The accesses to the individual
|
||||
* PCI devices on the other hand, are always little-endian and
|
||||
* can use readl() and writel().
|
||||
*
|
||||
* For local AHB bus access we need to use __raw_[readl|writel]()
|
||||
* to make sure that we access the SoC devices in the CPU native
|
||||
* endianness.
|
||||
*/
|
||||
static inline u32 ixp4xx_readl(struct ixp4xx_pci *p, u32 reg)
|
||||
{
|
||||
return __raw_readl(p->base + reg);
|
||||
}
|
||||
|
||||
static inline void ixp4xx_writel(struct ixp4xx_pci *p, u32 reg, u32 val)
|
||||
{
|
||||
__raw_writel(val, p->base + reg);
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_check_master_abort(struct ixp4xx_pci *p)
|
||||
{
|
||||
u32 isr = ixp4xx_readl(p, IXP4XX_PCI_ISR);
|
||||
|
||||
if (isr & IXP4XX_PCI_ISR_PFE) {
|
||||
/* Make sure the master abort bit is reset */
|
||||
ixp4xx_writel(p, IXP4XX_PCI_ISR, IXP4XX_PCI_ISR_PFE);
|
||||
dev_dbg(p->dev, "master abort detected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_read(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
|
||||
{
|
||||
ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
|
||||
|
||||
if (p->errata_hammer) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* PCI workaround - only works if NP PCI space reads have
|
||||
* no side effects. Hammer the register and read twice 8
|
||||
* times. last one will be good.
|
||||
*/
|
||||
for (i = 0; i < 8; i++) {
|
||||
ixp4xx_writel(p, IXP4XX_PCI_NP_CBE, cmd);
|
||||
*data = ixp4xx_readl(p, IXP4XX_PCI_NP_RDATA);
|
||||
*data = ixp4xx_readl(p, IXP4XX_PCI_NP_RDATA);
|
||||
}
|
||||
} else {
|
||||
ixp4xx_writel(p, IXP4XX_PCI_NP_CBE, cmd);
|
||||
*data = ixp4xx_readl(p, IXP4XX_PCI_NP_RDATA);
|
||||
}
|
||||
|
||||
return ixp4xx_pci_check_master_abort(p);
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_write(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 data)
|
||||
{
|
||||
ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
|
||||
|
||||
/* Set up the write */
|
||||
ixp4xx_writel(p, IXP4XX_PCI_NP_CBE, cmd);
|
||||
|
||||
/* Execute the write by writing to NP_WDATA */
|
||||
ixp4xx_writel(p, IXP4XX_PCI_NP_WDATA, data);
|
||||
|
||||
return ixp4xx_pci_check_master_abort(p);
|
||||
}
|
||||
|
||||
static u32 ixp4xx_config_addr(u8 bus_num, u16 devfn, int where)
|
||||
{
|
||||
/* Root bus is always 0 in this hardware */
|
||||
if (bus_num == 0) {
|
||||
/* type 0 */
|
||||
return BIT(32-PCI_SLOT(devfn)) | ((PCI_FUNC(devfn)) << 8) |
|
||||
(where & ~3);
|
||||
} else {
|
||||
/* type 1 */
|
||||
return (bus_num << 16) | ((PCI_SLOT(devfn)) << 11) |
|
||||
((PCI_FUNC(devfn)) << 8) | (where & ~3) | 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CRP functions are "Controller Configuration Port" accesses
|
||||
* initiated from within this driver itself to read/write PCI
|
||||
* control information in the config space.
|
||||
*/
|
||||
static u32 ixp4xx_crp_byte_lane_enable_bits(u32 n, int size)
|
||||
{
|
||||
if (size == 1)
|
||||
return (0xf & ~BIT(n)) << CRP_AD_CBE_BESL;
|
||||
if (size == 2)
|
||||
return (0xf & ~(BIT(n) | BIT(n+1))) << CRP_AD_CBE_BESL;
|
||||
if (size == 4)
|
||||
return 0;
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
static int ixp4xx_crp_read_config(struct ixp4xx_pci *p, int where, int size,
|
||||
u32 *value)
|
||||
{
|
||||
u32 n, cmd, val;
|
||||
|
||||
n = where % 4;
|
||||
cmd = where & ~3;
|
||||
|
||||
dev_dbg(p->dev, "%s from %d size %d cmd %08x\n",
|
||||
__func__, where, size, cmd);
|
||||
|
||||
ixp4xx_writel(p, IXP4XX_PCI_CRP_AD_CBE, cmd);
|
||||
val = ixp4xx_readl(p, IXP4XX_PCI_CRP_RDATA);
|
||||
|
||||
val >>= (8*n);
|
||||
switch (size) {
|
||||
case 1:
|
||||
val &= U8_MAX;
|
||||
dev_dbg(p->dev, "%s read byte %02x\n", __func__, val);
|
||||
break;
|
||||
case 2:
|
||||
val &= U16_MAX;
|
||||
dev_dbg(p->dev, "%s read word %04x\n", __func__, val);
|
||||
break;
|
||||
case 4:
|
||||
val &= U32_MAX;
|
||||
dev_dbg(p->dev, "%s read long %08x\n", __func__, val);
|
||||
break;
|
||||
default:
|
||||
/* Should not happen */
|
||||
dev_err(p->dev, "%s illegal size\n", __func__);
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
*value = val;
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int ixp4xx_crp_write_config(struct ixp4xx_pci *p, int where, int size,
|
||||
u32 value)
|
||||
{
|
||||
u32 n, cmd, val;
|
||||
|
||||
n = where % 4;
|
||||
cmd = ixp4xx_crp_byte_lane_enable_bits(n, size);
|
||||
if (cmd == 0xffffffff)
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
cmd |= where & ~3;
|
||||
cmd |= CRP_AD_CBE_WRITE;
|
||||
|
||||
val = value << (8*n);
|
||||
|
||||
dev_dbg(p->dev, "%s to %d size %d cmd %08x val %08x\n",
|
||||
__func__, where, size, cmd, val);
|
||||
|
||||
ixp4xx_writel(p, IXP4XX_PCI_CRP_AD_CBE, cmd);
|
||||
ixp4xx_writel(p, IXP4XX_PCI_CRP_WDATA, val);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Then follows the functions that read and write from the common PCI
|
||||
* configuration space.
|
||||
*/
|
||||
static u32 ixp4xx_byte_lane_enable_bits(u32 n, int size)
|
||||
{
|
||||
if (size == 1)
|
||||
return (0xf & ~BIT(n)) << 4;
|
||||
if (size == 2)
|
||||
return (0xf & ~(BIT(n) | BIT(n+1))) << 4;
|
||||
if (size == 4)
|
||||
return 0;
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 *value)
|
||||
{
|
||||
struct ixp4xx_pci *p = bus->sysdata;
|
||||
u32 n, addr, val, cmd;
|
||||
u8 bus_num = bus->number;
|
||||
int ret;
|
||||
|
||||
*value = 0xffffffff;
|
||||
n = where % 4;
|
||||
cmd = ixp4xx_byte_lane_enable_bits(n, size);
|
||||
if (cmd == 0xffffffff)
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
addr = ixp4xx_config_addr(bus_num, devfn, where);
|
||||
cmd |= NP_CMD_CONFIGREAD;
|
||||
dev_dbg(p->dev, "read_config from %d size %d dev %d:%d:%d address: %08x cmd: %08x\n",
|
||||
where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), addr, cmd);
|
||||
|
||||
ret = ixp4xx_pci_read(p, addr, cmd, &val);
|
||||
if (ret)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
val >>= (8*n);
|
||||
switch (size) {
|
||||
case 1:
|
||||
val &= U8_MAX;
|
||||
dev_dbg(p->dev, "%s read byte %02x\n", __func__, val);
|
||||
break;
|
||||
case 2:
|
||||
val &= U16_MAX;
|
||||
dev_dbg(p->dev, "%s read word %04x\n", __func__, val);
|
||||
break;
|
||||
case 4:
|
||||
val &= U32_MAX;
|
||||
dev_dbg(p->dev, "%s read long %08x\n", __func__, val);
|
||||
break;
|
||||
default:
|
||||
/* Should not happen */
|
||||
dev_err(p->dev, "%s illegal size\n", __func__);
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
*value = val;
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 value)
|
||||
{
|
||||
struct ixp4xx_pci *p = bus->sysdata;
|
||||
u32 n, addr, val, cmd;
|
||||
u8 bus_num = bus->number;
|
||||
int ret;
|
||||
|
||||
n = where % 4;
|
||||
cmd = ixp4xx_byte_lane_enable_bits(n, size);
|
||||
if (cmd == 0xffffffff)
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
addr = ixp4xx_config_addr(bus_num, devfn, where);
|
||||
cmd |= NP_CMD_CONFIGWRITE;
|
||||
val = value << (8*n);
|
||||
|
||||
dev_dbg(p->dev, "write_config_byte %#x to %d size %d dev %d:%d:%d addr: %08x cmd %08x\n",
|
||||
value, where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), addr, cmd);
|
||||
|
||||
ret = ixp4xx_pci_write(p, addr, cmd, val);
|
||||
if (ret)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops ixp4xx_pci_ops = {
|
||||
.read = ixp4xx_pci_read_config,
|
||||
.write = ixp4xx_pci_write_config,
|
||||
};
|
||||
|
||||
static u32 ixp4xx_pci_addr_to_64mconf(phys_addr_t addr)
|
||||
{
|
||||
u8 base;
|
||||
|
||||
base = ((addr & 0xff000000) >> 24);
|
||||
return (base << 24) | ((base + 1) << 16)
|
||||
| ((base + 2) << 8) | (base + 3);
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_parse_map_ranges(struct ixp4xx_pci *p)
|
||||
{
|
||||
struct device *dev = p->dev;
|
||||
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(p);
|
||||
struct resource_entry *win;
|
||||
struct resource *res;
|
||||
phys_addr_t addr;
|
||||
|
||||
win = resource_list_first_type(&bridge->windows, IORESOURCE_MEM);
|
||||
if (win) {
|
||||
u32 pcimembase;
|
||||
|
||||
res = win->res;
|
||||
addr = res->start - win->offset;
|
||||
|
||||
if (res->flags & IORESOURCE_PREFETCH)
|
||||
res->name = "IXP4xx PCI PRE-MEM";
|
||||
else
|
||||
res->name = "IXP4xx PCI NON-PRE-MEM";
|
||||
|
||||
dev_dbg(dev, "%s window %pR, bus addr %pa\n",
|
||||
res->name, res, &addr);
|
||||
if (resource_size(res) != SZ_64M) {
|
||||
dev_err(dev, "memory range is not 64MB\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pcimembase = ixp4xx_pci_addr_to_64mconf(addr);
|
||||
/* Commit configuration */
|
||||
ixp4xx_writel(p, IXP4XX_PCI_PCIMEMBASE, pcimembase);
|
||||
} else {
|
||||
dev_err(dev, "no AHB memory mapping defined\n");
|
||||
}
|
||||
|
||||
win = resource_list_first_type(&bridge->windows, IORESOURCE_IO);
|
||||
if (win) {
|
||||
res = win->res;
|
||||
|
||||
addr = pci_pio_to_address(res->start);
|
||||
if (addr & 0xff) {
|
||||
dev_err(dev, "IO mem at uneven address: %pa\n", &addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res->name = "IXP4xx PCI IO MEM";
|
||||
/*
|
||||
* Setup I/O space location for PCI->AHB access, the
|
||||
* upper 24 bits of the address goes into the lower
|
||||
* 24 bits of this register.
|
||||
*/
|
||||
ixp4xx_writel(p, IXP4XX_PCI_AHBIOBASE, (addr >> 8));
|
||||
} else {
|
||||
dev_info(dev, "no IO space AHB memory mapping defined\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ixp4xx_pci_parse_map_dma_ranges(struct ixp4xx_pci *p)
|
||||
{
|
||||
struct device *dev = p->dev;
|
||||
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(p);
|
||||
struct resource_entry *win;
|
||||
struct resource *res;
|
||||
phys_addr_t addr;
|
||||
u32 ahbmembase;
|
||||
|
||||
win = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
|
||||
if (win) {
|
||||
res = win->res;
|
||||
addr = res->start - win->offset;
|
||||
|
||||
if (resource_size(res) != SZ_64M) {
|
||||
dev_err(dev, "DMA memory range is not 64MB\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "DMA MEM BASE: %pa\n", &addr);
|
||||
/*
|
||||
* 4 PCI-to-AHB windows of 16 MB each, write the 8 high bits
|
||||
* into each byte of the PCI_AHBMEMBASE register.
|
||||
*/
|
||||
ahbmembase = ixp4xx_pci_addr_to_64mconf(addr);
|
||||
/* Commit AHB membase */
|
||||
ixp4xx_writel(p, IXP4XX_PCI_AHBMEMBASE, ahbmembase);
|
||||
} else {
|
||||
dev_err(dev, "no DMA memory range defined\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only used to get context for abort handling */
|
||||
static struct ixp4xx_pci *ixp4xx_pci_abort_singleton;
|
||||
|
||||
static int ixp4xx_pci_abort_handler(unsigned long addr, unsigned int fsr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct ixp4xx_pci *p = ixp4xx_pci_abort_singleton;
|
||||
u32 isr, status;
|
||||
int ret;
|
||||
|
||||
isr = ixp4xx_readl(p, IXP4XX_PCI_ISR);
|
||||
ret = ixp4xx_crp_read_config(p, PCI_STATUS, 2, &status);
|
||||
if (ret) {
|
||||
dev_err(p->dev, "unable to read abort status\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_err(p->dev,
|
||||
"PCI: abort_handler addr = %#lx, isr = %#x, status = %#x\n",
|
||||
addr, isr, status);
|
||||
|
||||
/* Make sure the Master Abort bit is reset */
|
||||
ixp4xx_writel(p, IXP4XX_PCI_ISR, IXP4XX_PCI_ISR_PFE);
|
||||
status |= PCI_STATUS_REC_MASTER_ABORT;
|
||||
ret = ixp4xx_crp_write_config(p, PCI_STATUS, 2, status);
|
||||
if (ret)
|
||||
dev_err(p->dev, "unable to clear abort status bit\n");
|
||||
|
||||
/*
|
||||
* If it was an imprecise abort, then we need to correct the
|
||||
* return address to be _after_ the instruction.
|
||||
*/
|
||||
if (fsr & (1 << 10)) {
|
||||
dev_err(p->dev, "imprecise abort\n");
|
||||
regs->ARM_pc += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ixp4xx_pci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct ixp4xx_pci *p;
|
||||
struct pci_host_bridge *host;
|
||||
int ret;
|
||||
u32 val;
|
||||
phys_addr_t addr;
|
||||
u32 basereg[4] = {
|
||||
PCI_BASE_ADDRESS_0,
|
||||
PCI_BASE_ADDRESS_1,
|
||||
PCI_BASE_ADDRESS_2,
|
||||
PCI_BASE_ADDRESS_3,
|
||||
};
|
||||
int i;
|
||||
|
||||
host = devm_pci_alloc_host_bridge(dev, sizeof(*p));
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
host->ops = &ixp4xx_pci_ops;
|
||||
p = pci_host_bridge_priv(host);
|
||||
host->sysdata = p;
|
||||
p->dev = dev;
|
||||
dev_set_drvdata(dev, p);
|
||||
|
||||
/*
|
||||
* Set up quirk for erratic behaviour in the 42x variant
|
||||
* when accessing config space.
|
||||
*/
|
||||
if (of_device_is_compatible(np, "intel,ixp42x-pci")) {
|
||||
p->errata_hammer = true;
|
||||
dev_info(dev, "activate hammering errata\n");
|
||||
}
|
||||
|
||||
p->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(p->base))
|
||||
return PTR_ERR(p->base);
|
||||
|
||||
val = ixp4xx_readl(p, IXP4XX_PCI_CSR);
|
||||
p->host_mode = !!(val & IXP4XX_PCI_CSR_HOST);
|
||||
dev_info(dev, "controller is in %s mode\n",
|
||||
p->host_mode ? "host" : "option");
|
||||
|
||||
/* Hook in our fault handler for PCI errors */
|
||||
ixp4xx_pci_abort_singleton = p;
|
||||
hook_fault_code(16+6, ixp4xx_pci_abort_handler, SIGBUS, 0,
|
||||
"imprecise external abort");
|
||||
|
||||
ret = ixp4xx_pci_parse_map_ranges(p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ixp4xx_pci_parse_map_dma_ranges(p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* This is only configured in host mode */
|
||||
if (p->host_mode) {
|
||||
addr = __pa(PAGE_OFFSET);
|
||||
/* This is a noop (0x00) but explains what is going on */
|
||||
addr |= PCI_BASE_ADDRESS_SPACE_MEMORY;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
/* Write this directly into the config space */
|
||||
ret = ixp4xx_crp_write_config(p, basereg[i], 4, addr);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to set up PCI_BASE_ADDRESS_%d\n", i);
|
||||
else
|
||||
dev_info(dev, "set PCI_BASE_ADDR_%d to %pa\n", i, &addr);
|
||||
addr += SZ_16M;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable CSR window at 64 MiB to allow PCI masters to continue
|
||||
* prefetching past the 64 MiB boundary, if all AHB to PCI
|
||||
* windows are consecutive.
|
||||
*/
|
||||
ret = ixp4xx_crp_write_config(p, PCI_BASE_ADDRESS_4, 4, addr);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to set up PCI_BASE_ADDRESS_4\n");
|
||||
else
|
||||
dev_info(dev, "set PCI_BASE_ADDR_4 to %pa\n", &addr);
|
||||
|
||||
/*
|
||||
* Put the IO memory window at the very end of physical memory
|
||||
* at 0xfffffc00. This is when the system is trying to access IO
|
||||
* memory over AHB.
|
||||
*/
|
||||
addr = 0xfffffc00;
|
||||
addr |= PCI_BASE_ADDRESS_SPACE_IO;
|
||||
ret = ixp4xx_crp_write_config(p, PCI_BASE_ADDRESS_5, 4, addr);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to set up PCI_BASE_ADDRESS_5\n");
|
||||
else
|
||||
dev_info(dev, "set PCI_BASE_ADDR_5 to %pa\n", &addr);
|
||||
|
||||
/*
|
||||
* Retry timeout to 0x80
|
||||
* Transfer ready timeout to 0xff
|
||||
*/
|
||||
ret = ixp4xx_crp_write_config(p, IXP4XX_PCI_RTOTTO, 4,
|
||||
0x000080ff);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to set up TRDY limit\n");
|
||||
else
|
||||
dev_info(dev, "set TRDY limit to 0x80ff\n");
|
||||
}
|
||||
|
||||
/* Clear interrupts */
|
||||
val = IXP4XX_PCI_ISR_PSE | IXP4XX_PCI_ISR_PFE | IXP4XX_PCI_ISR_PPE | IXP4XX_PCI_ISR_AHBE;
|
||||
ixp4xx_writel(p, IXP4XX_PCI_ISR, val);
|
||||
|
||||
/*
|
||||
* Set Initialize Complete in PCI Control Register: allow IXP4XX to
|
||||
* generate PCI configuration cycles. Specify that the AHB bus is
|
||||
* operating in big-endian mode. Set up byte lane swapping between
|
||||
* little-endian PCI and the big-endian AHB bus.
|
||||
*/
|
||||
val = IXP4XX_PCI_CSR_IC | IXP4XX_PCI_CSR_ABE;
|
||||
if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
|
||||
val |= (IXP4XX_PCI_CSR_PDS | IXP4XX_PCI_CSR_ADS);
|
||||
ixp4xx_writel(p, IXP4XX_PCI_CSR, val);
|
||||
|
||||
ret = ixp4xx_crp_write_config(p, PCI_COMMAND, 2, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
|
||||
if (ret)
|
||||
dev_err(dev, "unable to initialize master and command memory\n");
|
||||
else
|
||||
dev_info(dev, "initialized as master\n");
|
||||
|
||||
pci_host_probe(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ixp4xx_pci_of_match[] = {
|
||||
{
|
||||
.compatible = "intel,ixp42x-pci",
|
||||
},
|
||||
{
|
||||
.compatible = "intel,ixp43x-pci",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
/*
|
||||
* This driver needs to be a builtin module with suppressed bind
|
||||
* attributes since the probe() is initializing a hard exception
|
||||
* handler and this can only be done from __init-tagged code
|
||||
* sections. This module cannot be removed and inserted at all.
|
||||
*/
|
||||
static struct platform_driver ixp4xx_pci_driver = {
|
||||
.driver = {
|
||||
.name = "ixp4xx-pci",
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = ixp4xx_pci_of_match,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver_probe(ixp4xx_pci_driver, ixp4xx_pci_probe);
|
@ -70,6 +70,9 @@ static int __init imx_soc_device_init(void)
|
||||
case MXC_CPU_MX35:
|
||||
soc_id = "i.MX35";
|
||||
break;
|
||||
case MXC_CPU_MX50:
|
||||
soc_id = "i.MX50";
|
||||
break;
|
||||
case MXC_CPU_MX51:
|
||||
ocotp_compat = "fsl,imx51-iim";
|
||||
soc_id = "i.MX51";
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/ixp4xx/npe.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
|
||||
#define DEBUG_MSG 0
|
||||
#define DEBUG_FW 0
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/ixp4xx/qmgr.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/soc/ixp4xx/cpu.h>
|
||||
|
||||
static struct qmgr_regs __iomem *qmgr_regs;
|
||||
static int qmgr_irq_1;
|
||||
|
@ -144,6 +144,8 @@ config SOC_TEGRA_FLOWCTRL
|
||||
config SOC_TEGRA_PMC
|
||||
bool
|
||||
select GENERIC_PINCONF
|
||||
select PM_OPP
|
||||
select PM_GENERIC_DOMAINS
|
||||
|
||||
config SOC_TEGRA_POWERGATE_BPMP
|
||||
def_bool y
|
||||
|
@ -3,9 +3,16 @@
|
||||
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#define dev_fmt(fmt) "tegra-soc: " fmt
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_opp.h>
|
||||
|
||||
#include <soc/tegra/common.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
|
||||
static const struct of_device_id tegra_machine_match[] = {
|
||||
{ .compatible = "nvidia,tegra20", },
|
||||
@ -31,3 +38,93 @@ bool soc_is_tegra(void)
|
||||
|
||||
return match != NULL;
|
||||
}
|
||||
|
||||
static int tegra_core_dev_init_opp_state(struct device *dev)
|
||||
{
|
||||
unsigned long rate;
|
||||
struct clk *clk;
|
||||
int err;
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "failed to get clk: %pe\n", clk);
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
if (!rate) {
|
||||
dev_err(dev, "failed to get clk rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* first dummy rate-setting initializes voltage vote */
|
||||
err = dev_pm_opp_set_rate(dev, rate);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to initialize OPP clock: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_tegra_core_dev_init_opp_table() - initialize OPP table
|
||||
* @dev: device for which OPP table is initialized
|
||||
* @params: pointer to the OPP table configuration
|
||||
*
|
||||
* This function will initialize OPP table and sync OPP state of a Tegra SoC
|
||||
* core device.
|
||||
*
|
||||
* Return: 0 on success or errorno.
|
||||
*/
|
||||
int devm_tegra_core_dev_init_opp_table(struct device *dev,
|
||||
struct tegra_core_opp_params *params)
|
||||
{
|
||||
u32 hw_version;
|
||||
int err;
|
||||
|
||||
err = devm_pm_opp_set_clkname(dev, NULL);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to set OPP clk: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Tegra114+ doesn't support OPP yet */
|
||||
if (!of_machine_is_compatible("nvidia,tegra20") &&
|
||||
!of_machine_is_compatible("nvidia,tegra30"))
|
||||
return -ENODEV;
|
||||
|
||||
if (of_machine_is_compatible("nvidia,tegra20"))
|
||||
hw_version = BIT(tegra_sku_info.soc_process_id);
|
||||
else
|
||||
hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||
|
||||
err = devm_pm_opp_set_supported_hw(dev, &hw_version, 1);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to set OPP supported HW: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Older device-trees have an empty OPP table, we will get
|
||||
* -ENODEV from devm_pm_opp_of_add_table() in this case.
|
||||
*/
|
||||
err = devm_pm_opp_of_add_table(dev);
|
||||
if (err) {
|
||||
if (err == -ENODEV)
|
||||
dev_err_once(dev, "OPP table not found, please update device-tree\n");
|
||||
else
|
||||
dev_err(dev, "failed to add OPP table: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
if (params->init_state) {
|
||||
err = tegra_core_dev_init_opp_state(dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_tegra_core_dev_init_opp_table);
|
||||
|
@ -489,10 +489,8 @@ static int __init tegra_init_fuse(void)
|
||||
size_t size = sizeof(*fuse->lookups) * fuse->soc->num_lookups;
|
||||
|
||||
fuse->lookups = kmemdup(fuse->soc->lookups, size, GFP_KERNEL);
|
||||
if (!fuse->lookups)
|
||||
return -ENOMEM;
|
||||
|
||||
nvmem_add_cell_lookups(fuse->lookups, fuse->soc->num_lookups);
|
||||
if (fuse->lookups)
|
||||
nvmem_add_cell_lookups(fuse->lookups, fuse->soc->num_lookups);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -37,7 +37,8 @@
|
||||
defined(CONFIG_ARCH_TEGRA_132_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_210_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_186_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_194_SOC)
|
||||
defined(CONFIG_ARCH_TEGRA_194_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_234_SOC)
|
||||
static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
|
||||
{
|
||||
if (WARN_ON(!fuse->base))
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
@ -428,6 +429,9 @@ struct tegra_pmc {
|
||||
struct irq_chip irq;
|
||||
|
||||
struct notifier_block clk_nb;
|
||||
|
||||
bool core_domain_state_synced;
|
||||
bool core_domain_registered;
|
||||
};
|
||||
|
||||
static struct tegra_pmc *pmc = &(struct tegra_pmc) {
|
||||
@ -1297,12 +1301,107 @@ free_mem:
|
||||
return err;
|
||||
}
|
||||
|
||||
bool tegra_pmc_core_domain_state_synced(void)
|
||||
{
|
||||
return pmc->core_domain_state_synced;
|
||||
}
|
||||
|
||||
static int
|
||||
tegra_pmc_core_pd_set_performance_state(struct generic_pm_domain *genpd,
|
||||
unsigned int level)
|
||||
{
|
||||
struct dev_pm_opp *opp;
|
||||
int err;
|
||||
|
||||
opp = dev_pm_opp_find_level_ceil(&genpd->dev, &level);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(&genpd->dev, "failed to find OPP for level %u: %pe\n",
|
||||
level, opp);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
err = dev_pm_opp_set_opp(pmc->dev, opp);
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (err) {
|
||||
dev_err(&genpd->dev, "failed to set voltage to %duV: %d\n",
|
||||
level, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
tegra_pmc_core_pd_opp_to_performance_state(struct generic_pm_domain *genpd,
|
||||
struct dev_pm_opp *opp)
|
||||
{
|
||||
return dev_pm_opp_get_level(opp);
|
||||
}
|
||||
|
||||
static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, struct device_node *np)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
const char *rname = "core";
|
||||
int err;
|
||||
|
||||
genpd = devm_kzalloc(pmc->dev, sizeof(*genpd), GFP_KERNEL);
|
||||
if (!genpd)
|
||||
return -ENOMEM;
|
||||
|
||||
genpd->name = np->name;
|
||||
genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
|
||||
genpd->opp_to_performance_state = tegra_pmc_core_pd_opp_to_performance_state;
|
||||
|
||||
err = devm_pm_opp_set_regulators(pmc->dev, &rname, 1);
|
||||
if (err)
|
||||
return dev_err_probe(pmc->dev, err,
|
||||
"failed to set core OPP regulator\n");
|
||||
|
||||
err = pm_genpd_init(genpd, NULL, false);
|
||||
if (err) {
|
||||
dev_err(pmc->dev, "failed to init core genpd: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = of_genpd_add_provider_simple(np, genpd);
|
||||
if (err) {
|
||||
dev_err(pmc->dev, "failed to add core genpd: %d\n", err);
|
||||
goto remove_genpd;
|
||||
}
|
||||
|
||||
pmc->core_domain_registered = true;
|
||||
|
||||
return 0;
|
||||
|
||||
remove_genpd:
|
||||
pm_genpd_remove(genpd);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_powergate_init(struct tegra_pmc *pmc,
|
||||
struct device_node *parent)
|
||||
{
|
||||
struct of_phandle_args child_args, parent_args;
|
||||
struct device_node *np, *child;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Core power domain is the parent of powergate domains, hence it
|
||||
* should be registered first.
|
||||
*/
|
||||
np = of_get_child_by_name(parent, "core-domain");
|
||||
if (np) {
|
||||
err = tegra_pmc_core_pd_add(pmc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
np = of_get_child_by_name(parent, "powergates");
|
||||
if (!np)
|
||||
return 0;
|
||||
@ -1313,6 +1412,21 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
|
||||
of_node_put(child);
|
||||
break;
|
||||
}
|
||||
|
||||
if (of_parse_phandle_with_args(child, "power-domains",
|
||||
"#power-domain-cells",
|
||||
0, &parent_args))
|
||||
continue;
|
||||
|
||||
child_args.np = child;
|
||||
child_args.args_count = 0;
|
||||
|
||||
err = of_genpd_add_subdomain(&parent_args, &child_args);
|
||||
of_node_put(parent_args.np);
|
||||
if (err) {
|
||||
of_node_put(child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
@ -1356,6 +1470,12 @@ static void tegra_powergate_remove_all(struct device_node *parent)
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(parent, "core-domain");
|
||||
if (np) {
|
||||
of_genpd_del_provider(np);
|
||||
of_genpd_remove_last(np);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct tegra_io_pad_soc *
|
||||
@ -3667,6 +3787,29 @@ static const struct of_device_id tegra_pmc_match[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static void tegra_pmc_sync_state(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Older device-trees don't have core PD, and thus, there are
|
||||
* no dependencies that will block the state syncing. We shouldn't
|
||||
* mark the domain as synced in this case.
|
||||
*/
|
||||
if (!pmc->core_domain_registered)
|
||||
return;
|
||||
|
||||
pmc->core_domain_state_synced = true;
|
||||
|
||||
/* this is a no-op if core regulator isn't used */
|
||||
mutex_lock(&pmc->powergates_lock);
|
||||
err = dev_pm_opp_sync_regulators(dev);
|
||||
mutex_unlock(&pmc->powergates_lock);
|
||||
|
||||
if (err)
|
||||
dev_err(dev, "failed to sync regulators: %d\n", err);
|
||||
}
|
||||
|
||||
static struct platform_driver tegra_pmc_driver = {
|
||||
.driver = {
|
||||
.name = "tegra-pmc",
|
||||
@ -3675,6 +3818,7 @@ static struct platform_driver tegra_pmc_driver = {
|
||||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
|
||||
.pm = &tegra_pmc_pm_ops,
|
||||
#endif
|
||||
.sync_state = tegra_pmc_sync_state,
|
||||
},
|
||||
.probe = tegra_pmc_probe,
|
||||
};
|
||||
|
@ -12,16 +12,22 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/regulator/coupler.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
struct tegra_regulator_coupler {
|
||||
struct regulator_coupler coupler;
|
||||
struct regulator_dev *core_rdev;
|
||||
struct regulator_dev *cpu_rdev;
|
||||
struct regulator_dev *rtc_rdev;
|
||||
int core_min_uV;
|
||||
struct notifier_block reboot_notifier;
|
||||
int core_min_uV, cpu_min_uV;
|
||||
bool sys_reboot_mode_req;
|
||||
bool sys_reboot_mode;
|
||||
};
|
||||
|
||||
static inline struct tegra_regulator_coupler *
|
||||
@ -38,6 +44,21 @@ static int tegra20_core_limit(struct tegra_regulator_coupler *tegra,
|
||||
int core_cur_uV;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Tegra20 SoC has critical DVFS-capable devices that are
|
||||
* permanently-active or active at a boot time, like EMC
|
||||
* (DRAM controller) or Display controller for example.
|
||||
*
|
||||
* The voltage of a CORE SoC power domain shall not be dropped below
|
||||
* a minimum level, which is determined by device's clock rate.
|
||||
* This means that we can't fully allow CORE voltage scaling until
|
||||
* the state of all DVFS-critical CORE devices is synced.
|
||||
*/
|
||||
if (tegra_pmc_core_domain_state_synced() && !tegra->sys_reboot_mode) {
|
||||
pr_info_once("voltage state synced\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tegra->core_min_uV > 0)
|
||||
return tegra->core_min_uV;
|
||||
|
||||
@ -58,7 +79,7 @@ static int tegra20_core_limit(struct tegra_regulator_coupler *tegra,
|
||||
*/
|
||||
tegra->core_min_uV = core_max_uV;
|
||||
|
||||
pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV);
|
||||
pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);
|
||||
|
||||
return tegra->core_min_uV;
|
||||
}
|
||||
@ -242,6 +263,10 @@ static int tegra20_cpu_voltage_update(struct tegra_regulator_coupler *tegra,
|
||||
if (cpu_uV < 0)
|
||||
return cpu_uV;
|
||||
|
||||
/* store boot voltage level */
|
||||
if (!tegra->cpu_min_uV)
|
||||
tegra->cpu_min_uV = cpu_uV;
|
||||
|
||||
/*
|
||||
* CPU's regulator may not have any consumers, hence the voltage
|
||||
* must not be changed in that case because CPU simply won't
|
||||
@ -250,6 +275,10 @@ static int tegra20_cpu_voltage_update(struct tegra_regulator_coupler *tegra,
|
||||
if (!cpu_min_uV_consumers)
|
||||
cpu_min_uV = cpu_uV;
|
||||
|
||||
/* restore boot voltage level */
|
||||
if (tegra->sys_reboot_mode)
|
||||
cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
|
||||
|
||||
if (cpu_min_uV > cpu_uV) {
|
||||
err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
|
||||
cpu_uV, cpu_min_uV);
|
||||
@ -290,6 +319,8 @@ static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
|
||||
|
||||
if (rdev == cpu_rdev)
|
||||
return tegra20_cpu_voltage_update(tegra, cpu_rdev,
|
||||
core_rdev, rtc_rdev);
|
||||
@ -303,6 +334,51 @@ static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler,
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static int tegra20_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra,
|
||||
bool sys_reboot_mode)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev)
|
||||
return 0;
|
||||
|
||||
WRITE_ONCE(tegra->sys_reboot_mode_req, true);
|
||||
|
||||
/*
|
||||
* Some devices use CPU soft-reboot method and in this case we
|
||||
* should ensure that voltages are sane for the reboot by restoring
|
||||
* the minimum boot levels.
|
||||
*/
|
||||
err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = regulator_sync_voltage_rdev(tegra->core_rdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
WRITE_ONCE(tegra->sys_reboot_mode_req, sys_reboot_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra20_regulator_reboot(struct notifier_block *notifier,
|
||||
unsigned long event, void *cmd)
|
||||
{
|
||||
struct tegra_regulator_coupler *tegra;
|
||||
int ret;
|
||||
|
||||
if (event != SYS_RESTART)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
tegra = container_of(notifier, struct tegra_regulator_coupler,
|
||||
reboot_notifier);
|
||||
|
||||
ret = tegra20_regulator_prepare_reboot(tegra, true);
|
||||
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static int tegra20_regulator_attach(struct regulator_coupler *coupler,
|
||||
struct regulator_dev *rdev)
|
||||
{
|
||||
@ -335,6 +411,14 @@ static int tegra20_regulator_detach(struct regulator_coupler *coupler,
|
||||
{
|
||||
struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
|
||||
|
||||
/*
|
||||
* We don't expect regulators to be decoupled during reboot,
|
||||
* this may race with the reboot handler and shouldn't ever
|
||||
* happen in practice.
|
||||
*/
|
||||
if (WARN_ON_ONCE(system_state > SYSTEM_RUNNING))
|
||||
return -EPERM;
|
||||
|
||||
if (tegra->core_rdev == rdev) {
|
||||
tegra->core_rdev = NULL;
|
||||
return 0;
|
||||
@ -359,13 +443,19 @@ static struct tegra_regulator_coupler tegra20_coupler = {
|
||||
.detach_regulator = tegra20_regulator_detach,
|
||||
.balance_voltage = tegra20_regulator_balance_voltage,
|
||||
},
|
||||
.reboot_notifier.notifier_call = tegra20_regulator_reboot,
|
||||
};
|
||||
|
||||
static int __init tegra_regulator_coupler_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!of_machine_is_compatible("nvidia,tegra20"))
|
||||
return 0;
|
||||
|
||||
err = register_reboot_notifier(&tegra20_coupler.reboot_notifier);
|
||||
WARN_ON(err);
|
||||
|
||||
return regulator_coupler_register(&tegra20_coupler.coupler);
|
||||
}
|
||||
arch_initcall(tegra_regulator_coupler_init);
|
||||
|
@ -12,17 +12,22 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/regulator/coupler.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
struct tegra_regulator_coupler {
|
||||
struct regulator_coupler coupler;
|
||||
struct regulator_dev *core_rdev;
|
||||
struct regulator_dev *cpu_rdev;
|
||||
int core_min_uV;
|
||||
struct notifier_block reboot_notifier;
|
||||
int core_min_uV, cpu_min_uV;
|
||||
bool sys_reboot_mode_req;
|
||||
bool sys_reboot_mode;
|
||||
};
|
||||
|
||||
static inline struct tegra_regulator_coupler *
|
||||
@ -39,6 +44,21 @@ static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,
|
||||
int core_cur_uV;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Tegra30 SoC has critical DVFS-capable devices that are
|
||||
* permanently-active or active at a boot time, like EMC
|
||||
* (DRAM controller) or Display controller for example.
|
||||
*
|
||||
* The voltage of a CORE SoC power domain shall not be dropped below
|
||||
* a minimum level, which is determined by device's clock rate.
|
||||
* This means that we can't fully allow CORE voltage scaling until
|
||||
* the state of all DVFS-critical CORE devices is synced.
|
||||
*/
|
||||
if (tegra_pmc_core_domain_state_synced() && !tegra->sys_reboot_mode) {
|
||||
pr_info_once("voltage state synced\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tegra->core_min_uV > 0)
|
||||
return tegra->core_min_uV;
|
||||
|
||||
@ -59,7 +79,7 @@ static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,
|
||||
*/
|
||||
tegra->core_min_uV = core_max_uV;
|
||||
|
||||
pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV);
|
||||
pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);
|
||||
|
||||
return tegra->core_min_uV;
|
||||
}
|
||||
@ -172,6 +192,10 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
|
||||
if (cpu_uV < 0)
|
||||
return cpu_uV;
|
||||
|
||||
/* store boot voltage level */
|
||||
if (!tegra->cpu_min_uV)
|
||||
tegra->cpu_min_uV = cpu_uV;
|
||||
|
||||
/*
|
||||
* CPU's regulator may not have any consumers, hence the voltage
|
||||
* must not be changed in that case because CPU simply won't
|
||||
@ -195,6 +219,10 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* restore boot voltage level */
|
||||
if (tegra->sys_reboot_mode)
|
||||
cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
|
||||
|
||||
if (core_min_limited_uV > core_uV) {
|
||||
pr_err("core voltage constraint violated: %d %d %d\n",
|
||||
core_uV, core_min_limited_uV, cpu_uV);
|
||||
@ -263,9 +291,56 @@ static int tegra30_regulator_balance_voltage(struct regulator_coupler *coupler,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
|
||||
|
||||
return tegra30_voltage_update(tegra, cpu_rdev, core_rdev);
|
||||
}
|
||||
|
||||
static int tegra30_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra,
|
||||
bool sys_reboot_mode)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!tegra->core_rdev || !tegra->cpu_rdev)
|
||||
return 0;
|
||||
|
||||
WRITE_ONCE(tegra->sys_reboot_mode_req, true);
|
||||
|
||||
/*
|
||||
* Some devices use CPU soft-reboot method and in this case we
|
||||
* should ensure that voltages are sane for the reboot by restoring
|
||||
* the minimum boot levels.
|
||||
*/
|
||||
err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = regulator_sync_voltage_rdev(tegra->core_rdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
WRITE_ONCE(tegra->sys_reboot_mode_req, sys_reboot_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra30_regulator_reboot(struct notifier_block *notifier,
|
||||
unsigned long event, void *cmd)
|
||||
{
|
||||
struct tegra_regulator_coupler *tegra;
|
||||
int ret;
|
||||
|
||||
if (event != SYS_RESTART)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
tegra = container_of(notifier, struct tegra_regulator_coupler,
|
||||
reboot_notifier);
|
||||
|
||||
ret = tegra30_regulator_prepare_reboot(tegra, true);
|
||||
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static int tegra30_regulator_attach(struct regulator_coupler *coupler,
|
||||
struct regulator_dev *rdev)
|
||||
{
|
||||
@ -292,6 +367,14 @@ static int tegra30_regulator_detach(struct regulator_coupler *coupler,
|
||||
{
|
||||
struct tegra_regulator_coupler *tegra = to_tegra_coupler(coupler);
|
||||
|
||||
/*
|
||||
* We don't expect regulators to be decoupled during reboot,
|
||||
* this may race with the reboot handler and shouldn't ever
|
||||
* happen in practice.
|
||||
*/
|
||||
if (WARN_ON_ONCE(system_state > SYSTEM_RUNNING))
|
||||
return -EPERM;
|
||||
|
||||
if (tegra->core_rdev == rdev) {
|
||||
tegra->core_rdev = NULL;
|
||||
return 0;
|
||||
@ -311,13 +394,19 @@ static struct tegra_regulator_coupler tegra30_coupler = {
|
||||
.detach_regulator = tegra30_regulator_detach,
|
||||
.balance_voltage = tegra30_regulator_balance_voltage,
|
||||
},
|
||||
.reboot_notifier.notifier_call = tegra30_regulator_reboot,
|
||||
};
|
||||
|
||||
static int __init tegra_regulator_coupler_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!of_machine_is_compatible("nvidia,tegra30"))
|
||||
return 0;
|
||||
|
||||
err = register_reboot_notifier(&tegra30_coupler.reboot_notifier);
|
||||
WARN_ON(err);
|
||||
|
||||
return regulator_coupler_register(&tegra30_coupler.coupler);
|
||||
}
|
||||
arch_initcall(tegra_regulator_coupler_init);
|
||||
|
21
include/linux/platform_data/pata_ixp4xx_cf.h
Normal file
21
include/linux/platform_data/pata_ixp4xx_cf.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __PLATFORM_DATA_PATA_IXP4XX_H
|
||||
#define __PLATFORM_DATA_PATA_IXP4XX_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* This structure provide a means for the board setup code
|
||||
* to give information to th pata_ixp4xx driver. It is
|
||||
* passed as platform_data.
|
||||
*/
|
||||
struct ixp4xx_pata_data {
|
||||
volatile u32 *cs0_cfg;
|
||||
volatile u32 *cs1_cfg;
|
||||
unsigned long cs0_bits;
|
||||
unsigned long cs1_bits;
|
||||
void __iomem *cs0;
|
||||
void __iomem *cs1;
|
||||
};
|
||||
|
||||
#endif
|
106
include/linux/soc/ixp4xx/cpu.h
Normal file
106
include/linux/soc/ixp4xx/cpu.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* IXP4XX cpu type detection
|
||||
*
|
||||
* Copyright (C) 2007 MontaVista Software, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_IXP4XX_CPU_H__
|
||||
#define __SOC_IXP4XX_CPU_H__
|
||||
|
||||
#include <linux/io.h>
|
||||
#ifdef CONFIG_ARM
|
||||
#include <asm/cputype.h>
|
||||
#endif
|
||||
|
||||
/* Processor id value in CP15 Register 0 */
|
||||
#define IXP42X_PROCESSOR_ID_VALUE 0x690541c0 /* including unused 0x690541Ex */
|
||||
#define IXP42X_PROCESSOR_ID_MASK 0xffffffc0
|
||||
|
||||
#define IXP43X_PROCESSOR_ID_VALUE 0x69054040
|
||||
#define IXP43X_PROCESSOR_ID_MASK 0xfffffff0
|
||||
|
||||
#define IXP46X_PROCESSOR_ID_VALUE 0x69054200 /* including IXP455 */
|
||||
#define IXP46X_PROCESSOR_ID_MASK 0xfffffff0
|
||||
|
||||
/* "fuse" bits of IXP_EXP_CFG2 */
|
||||
/* All IXP4xx CPUs */
|
||||
#define IXP4XX_FEATURE_RCOMP (1 << 0)
|
||||
#define IXP4XX_FEATURE_USB_DEVICE (1 << 1)
|
||||
#define IXP4XX_FEATURE_HASH (1 << 2)
|
||||
#define IXP4XX_FEATURE_AES (1 << 3)
|
||||
#define IXP4XX_FEATURE_DES (1 << 4)
|
||||
#define IXP4XX_FEATURE_HDLC (1 << 5)
|
||||
#define IXP4XX_FEATURE_AAL (1 << 6)
|
||||
#define IXP4XX_FEATURE_HSS (1 << 7)
|
||||
#define IXP4XX_FEATURE_UTOPIA (1 << 8)
|
||||
#define IXP4XX_FEATURE_NPEB_ETH0 (1 << 9)
|
||||
#define IXP4XX_FEATURE_NPEC_ETH (1 << 10)
|
||||
#define IXP4XX_FEATURE_RESET_NPEA (1 << 11)
|
||||
#define IXP4XX_FEATURE_RESET_NPEB (1 << 12)
|
||||
#define IXP4XX_FEATURE_RESET_NPEC (1 << 13)
|
||||
#define IXP4XX_FEATURE_PCI (1 << 14)
|
||||
#define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT (3 << 16)
|
||||
#define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22)
|
||||
#define IXP42X_FEATURE_MASK (IXP4XX_FEATURE_RCOMP | \
|
||||
IXP4XX_FEATURE_USB_DEVICE | \
|
||||
IXP4XX_FEATURE_HASH | \
|
||||
IXP4XX_FEATURE_AES | \
|
||||
IXP4XX_FEATURE_DES | \
|
||||
IXP4XX_FEATURE_HDLC | \
|
||||
IXP4XX_FEATURE_AAL | \
|
||||
IXP4XX_FEATURE_HSS | \
|
||||
IXP4XX_FEATURE_UTOPIA | \
|
||||
IXP4XX_FEATURE_NPEB_ETH0 | \
|
||||
IXP4XX_FEATURE_NPEC_ETH | \
|
||||
IXP4XX_FEATURE_RESET_NPEA | \
|
||||
IXP4XX_FEATURE_RESET_NPEB | \
|
||||
IXP4XX_FEATURE_RESET_NPEC | \
|
||||
IXP4XX_FEATURE_PCI | \
|
||||
IXP4XX_FEATURE_UTOPIA_PHY_LIMIT | \
|
||||
IXP4XX_FEATURE_XSCALE_MAX_FREQ)
|
||||
|
||||
|
||||
/* IXP43x/46x CPUs */
|
||||
#define IXP4XX_FEATURE_ECC_TIMESYNC (1 << 15)
|
||||
#define IXP4XX_FEATURE_USB_HOST (1 << 18)
|
||||
#define IXP4XX_FEATURE_NPEA_ETH (1 << 19)
|
||||
#define IXP43X_FEATURE_MASK (IXP42X_FEATURE_MASK | \
|
||||
IXP4XX_FEATURE_ECC_TIMESYNC | \
|
||||
IXP4XX_FEATURE_USB_HOST | \
|
||||
IXP4XX_FEATURE_NPEA_ETH)
|
||||
|
||||
/* IXP46x CPU (including IXP455) only */
|
||||
#define IXP4XX_FEATURE_NPEB_ETH_1_TO_3 (1 << 20)
|
||||
#define IXP4XX_FEATURE_RSA (1 << 21)
|
||||
#define IXP46X_FEATURE_MASK (IXP43X_FEATURE_MASK | \
|
||||
IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \
|
||||
IXP4XX_FEATURE_RSA)
|
||||
|
||||
#ifdef CONFIG_ARCH_IXP4XX
|
||||
#define cpu_is_ixp42x_rev_a0() ((read_cpuid_id() & (IXP42X_PROCESSOR_ID_MASK | 0xF)) == \
|
||||
IXP42X_PROCESSOR_ID_VALUE)
|
||||
#define cpu_is_ixp42x() ((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \
|
||||
IXP42X_PROCESSOR_ID_VALUE)
|
||||
#define cpu_is_ixp43x() ((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \
|
||||
IXP43X_PROCESSOR_ID_VALUE)
|
||||
#define cpu_is_ixp46x() ((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \
|
||||
IXP46X_PROCESSOR_ID_VALUE)
|
||||
|
||||
u32 ixp4xx_read_feature_bits(void);
|
||||
void ixp4xx_write_feature_bits(u32 value);
|
||||
#else
|
||||
#define cpu_is_ixp42x_rev_a0() 0
|
||||
#define cpu_is_ixp42x() 0
|
||||
#define cpu_is_ixp43x() 0
|
||||
#define cpu_is_ixp46x() 0
|
||||
static inline u32 ixp4xx_read_feature_bits(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void ixp4xx_write_feature_bits(u32 value)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_ARCH_CPU_H */
|
@ -611,12 +611,6 @@
|
||||
#define EXYNOS5420_FSYS2_OPTION 0x4168
|
||||
#define EXYNOS5420_PSGEN_OPTION 0x4188
|
||||
|
||||
/* For EXYNOS_CENTRAL_SEQ_OPTION */
|
||||
#define EXYNOS5_USE_STANDBYWFI_ARM_CORE0 BIT(16)
|
||||
#define EXYNOS5_USE_STANDBYWFI_ARM_CORE1 BUT(17)
|
||||
#define EXYNOS5_USE_STANDBYWFE_ARM_CORE0 BIT(24)
|
||||
#define EXYNOS5_USE_STANDBYWFE_ARM_CORE1 BIT(25)
|
||||
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI0 BIT(4)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI1 BIT(5)
|
||||
#define EXYNOS5420_ARM_USE_STANDBY_WFI2 BIT(6)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define MXC_CPU_MX27 27
|
||||
#define MXC_CPU_MX31 31
|
||||
#define MXC_CPU_MX35 35
|
||||
#define MXC_CPU_MX50 50
|
||||
#define MXC_CPU_MX51 51
|
||||
#define MXC_CPU_MX53 53
|
||||
#define MXC_CPU_IMX6SL 0x60
|
||||
|
@ -6,6 +6,37 @@
|
||||
#ifndef __SOC_TEGRA_COMMON_H__
|
||||
#define __SOC_TEGRA_COMMON_H__
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
|
||||
/**
|
||||
* Tegra SoC core device OPP table configuration
|
||||
*
|
||||
* @init_state: pre-initialize OPP state of a device
|
||||
*/
|
||||
struct tegra_core_opp_params {
|
||||
bool init_state;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
bool soc_is_tegra(void);
|
||||
|
||||
int devm_tegra_core_dev_init_opp_table(struct device *dev,
|
||||
struct tegra_core_opp_params *params);
|
||||
#else
|
||||
static inline bool soc_is_tegra(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int
|
||||
devm_tegra_core_dev_init_opp_table(struct device *dev,
|
||||
struct tegra_core_opp_params *params)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SOC_TEGRA_COMMON_H__ */
|
||||
|
@ -52,14 +52,28 @@ struct tegra_sku_info {
|
||||
enum tegra_revision revision;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
extern struct tegra_sku_info tegra_sku_info;
|
||||
u32 tegra_read_straps(void);
|
||||
u32 tegra_read_ram_code(void);
|
||||
int tegra_fuse_readl(unsigned long offset, u32 *value);
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
extern struct tegra_sku_info tegra_sku_info;
|
||||
#else
|
||||
static struct tegra_sku_info tegra_sku_info __maybe_unused;
|
||||
|
||||
static inline u32 tegra_read_straps(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 tegra_read_ram_code(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int tegra_fuse_readl(unsigned long offset, u32 *value)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct device *tegra_soc_device_register(void);
|
||||
|
@ -171,6 +171,8 @@ int tegra_io_rail_power_off(unsigned int id);
|
||||
void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
|
||||
void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
|
||||
|
||||
bool tegra_pmc_core_domain_state_synced(void);
|
||||
|
||||
#else
|
||||
static inline int tegra_powergate_power_on(unsigned int id)
|
||||
{
|
||||
@ -227,6 +229,11 @@ static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool tegra_pmc_core_domain_state_synced(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SOC_TEGRA_PMC */
|
||||
|
||||
#if defined(CONFIG_SOC_TEGRA_PMC) && defined(CONFIG_PM_SLEEP)
|
||||
|
Loading…
Reference in New Issue
Block a user