mirror of https://gitee.com/openkylin/linux.git
This is a major chunk of IXP4xx modernization:
- Fist we move some registers around to make room for the predetermined PCI I/O space. - Then we add some Kconfig options to make it possible to use the old PCI driver in parallell with the new shiny one. - Then we add the new PCI driver and some bindings for it. - On top of this we add an (ages old) patch from Arnd that centralize the CPU/SoC detection in drivers/soc and make the header a standard Linux header to avoid the <mach/*> business in drivers. - Then we split out and modernize some platform data headers for pata, and hwrandom, and top it up with DT bindings and support for hwrandom. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmDMWhIACgkQQRCzN7AZ XXMCeA/8C3EquNZgRZkzrEUvX2Einr0djZvu/vQZkn1cybusNQxeRTupyZH2eQYG DzvDq+lGe/1gK72fnBSlaNRr4RunBCGDEt7pmbYPnSIuQk9YckhCtvWX6ZVjzEe/ lY/H+zW7vWO+kajNffjRs8/Ovhlku+1VgN4+EpkHiW1UfYzdWAVRBn2s3JY5O4ht 1ONMJu7/myy5yE+fyNfGt5iBCE4Tj2VNuOVFdyijv07GwupndZ+xbnDqTlFmdbw0 qLaoumWSvSAhOlJHDINqfdeNJ3NXVrHejcrLERvDSn+UbqNV6+NYhAncDb+JV5Nn oZS5masrAOTbZHv9MGfVt3baQukDixYCvx7f/Qg3BUODkOJcUZWT8+ShRuLMrFfL d4uC/QKWkTbO1XOGzn3I/6Co25jC0FjLPk87AZ25i7q410gralHQwad9BmJWE1ZH vvQVvbE5ZELyFF13nGkk/m4cY3u07BGnLV24MbByZpUCyEE5M1X2jujBFtofacPC MxcJDVgewrlsgAeZVjrMW2XCFhYgU6fKLQyc80L2BHWMBI/6t7BcaaK3g+s9thOI 19X2smU4QRXLmC8fa7IkiQv0q8J288xTBbP+N9RgZF/9FUT4BPXQNTgRueMZjfm3 HcbKh+lsG1wtGqxHlK+7L4VCx+MjyQAFUVLHSKt0uu2q6vElFSQ= =k/Rp -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQJDBAABCgAtFiEElf+HevZ4QCAJmMQ+jBrnPN6EHHcFAmDT5DwPHG9sb2ZAbGl4 b20ubmV0AAoJEIwa5zzehBx3fJ0P/3R3Eyxo7W+sUZzDDkVuHIGQ+D2Yj2SLsNF+ hCoXlADnD37Zgjw4hEp3nW3ZuoRDH2MqhU//oMFfUScXh0giHbjaSsQRQextoo3u kqReKRrhU7r9KSuAloml8YXTCiBCYkHEQQ7BtMuInyJRYmIlBSUV9GpiMXGY4MOO Z4orN5OGio4S9VZ3hvN5efKJnqjbKvKzgXDGaHuXqEHFXpXX9gH8g/eulxOcUZ8f tfTdW026isqBpW1pGpEqKcyyT4TJmCs1JDx19DHjbaeVAV9vOvS2UF7xC+6nYGEA 7PQwRMxZGMdSP/YZ8HsbHKoAHh3/3rwc0BpjlnQcnW/2l52sQM4hrbsd0vjL7zap S7qTIlPWEK0glbFQccXVtwmfDauE7G6GxuuAe4+zO4zNeiJyxH9UwXiNvKsRGzSi E1sWSAEy8h8HOvxg4D0am7n/57QYdJLtfvOxgBtmmyx5FnVj64LYtKXSb4k345cn qAbYb/vKJauze046Hll8dxK6JsRuzpjUy/10Q3UnXw580GeNFcHRRGBzDNFKZynZ YlTfd/njEr+qjQA2hE9LxshA/R6M+OyskHuNvGCZ9bPFhbJzTBxfdAPwVqjs6G0h BEL90S6KiURnyEsnYzmHV6nVn5reggIXCdcmPtcCHan+jw4pJ5e/op/dZPytf2Uf Z0iZ4QiN =NWGE -----END PGP SIGNATURE----- Merge tag 'ixp4xx-arm-soc-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik into arm/soc This is a major chunk of IXP4xx modernization: - Fist we move some registers around to make room for the predetermined PCI I/O space. - Then we add some Kconfig options to make it possible to use the old PCI driver in parallell with the new shiny one. - Then we add the new PCI driver and some bindings for it. - On top of this we add an (ages old) patch from Arnd that centralize the CPU/SoC detection in drivers/soc and make the header a standard Linux header to avoid the <mach/*> business in drivers. - Then we split out and modernize some platform data headers for pata, and hwrandom, and top it up with DT bindings and support for hwrandom. * tag 'ixp4xx-arm-soc-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik: 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 Link: https://lore.kernel.org/r/CACRpkdbw6HSpp7k6q1FYGmtafLmdAu8bFnpHQOdfBDYYsdLbkw@mail.gmail.com Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
95ef715236
|
@ -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 */
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -9252,6 +9252,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
|
||||
|
@ -14015,6 +14016,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
|
||||
|
|
|
@ -398,7 +398,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
|
||||
|
|
|
@ -1813,8 +1813,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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -30,6 +30,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
|
||||
|
|
|
@ -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);
|
|
@ -20,6 +20,8 @@
|
|||
#include <linux/of.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;
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
Loading…
Reference in New Issue