Commit 95ef7152 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'ixp4xx-arm-soc-v5.14' of...

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.comSigned-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 6b4670af 0da518da
# 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 */
};
# 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 ...@@ -9252,6 +9252,7 @@ F: include/linux/soc/ixp4xx/qmgr.h
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
M: Deepak Saxena <dsaxena@plexity.net> M: Deepak Saxena <dsaxena@plexity.net>
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/display/intel,ixp46x-rng.yaml
F: drivers/char/hw_random/ixp4xx-rng.c F: drivers/char/hw_random/ixp4xx-rng.c
INTEL KEEM BAY DRM DRIVER INTEL KEEM BAY DRM DRIVER
...@@ -14015,6 +14016,12 @@ S: Maintained ...@@ -14015,6 +14016,12 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml F: Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
F: drivers/pci/controller/dwc/pcie-fu740.c 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) PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
M: Jonathan Derrick <jonathan.derrick@intel.com> M: Jonathan Derrick <jonathan.derrick@intel.com>
L: linux-pci@vger.kernel.org L: linux-pci@vger.kernel.org
......
...@@ -398,7 +398,8 @@ config ARCH_IXP4XX ...@@ -398,7 +398,8 @@ config ARCH_IXP4XX
select HAVE_PCI select HAVE_PCI
select IXP4XX_IRQ select IXP4XX_IRQ
select IXP4XX_TIMER 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_DESC
select USB_EHCI_BIG_ENDIAN_MMIO select USB_EHCI_BIG_ENDIAN_MMIO
help help
......
...@@ -1813,8 +1813,8 @@ config DEBUG_UART_VIRT ...@@ -1813,8 +1813,8 @@ config DEBUG_UART_VIRT
default 0xfedc0000 if DEBUG_EP93XX default 0xfedc0000 if DEBUG_EP93XX
default 0xfee003f8 if DEBUG_FOOTBRIDGE_COM1 default 0xfee003f8 if DEBUG_FOOTBRIDGE_COM1
default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN default 0xfec00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN default 0xfec00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
default 0xfef36000 if DEBUG_HIGHBANK_UART default 0xfef36000 if DEBUG_HIGHBANK_UART
default 0xfefb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1 default 0xfefb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1
default 0xfefb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2 default 0xfefb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2
......
...@@ -7,7 +7,7 @@ comment "IXP4xx Platforms" ...@@ -7,7 +7,7 @@ comment "IXP4xx Platforms"
config MACH_IXP4XX_OF config MACH_IXP4XX_OF
bool bool
prompt "Devce Tree IXP4xx boards" prompt "Device Tree IXP4xx boards"
default y default y
select ARM_APPENDED_DTB # Old Redboot bootloaders deployed select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
select I2C select I2C
...@@ -20,7 +20,7 @@ config MACH_IXP4XX_OF ...@@ -20,7 +20,7 @@ config MACH_IXP4XX_OF
config MACH_NSLU2 config MACH_NSLU2
bool bool
prompt "Linksys NSLU2" prompt "Linksys NSLU2"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Linksys's Say 'Y' here if you want your kernel to support Linksys's
NSLU2 NAS device. For more information on this platform, NSLU2 NAS device. For more information on this platform,
...@@ -28,7 +28,7 @@ config MACH_NSLU2 ...@@ -28,7 +28,7 @@ config MACH_NSLU2
config MACH_AVILA config MACH_AVILA
bool "Avila" bool "Avila"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support the Gateworks Say 'Y' here if you want your kernel to support the Gateworks
Avila Network Platform. For more information on this platform, Avila Network Platform. For more information on this platform,
...@@ -44,7 +44,7 @@ config MACH_LOFT ...@@ -44,7 +44,7 @@ config MACH_LOFT
config ARCH_ADI_COYOTE config ARCH_ADI_COYOTE
bool "Coyote" bool "Coyote"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support the ADI Say 'Y' here if you want your kernel to support the ADI
Engineering Coyote Gateway Reference Platform. For more Engineering Coyote Gateway Reference Platform. For more
...@@ -52,7 +52,7 @@ config ARCH_ADI_COYOTE ...@@ -52,7 +52,7 @@ config ARCH_ADI_COYOTE
config MACH_GATEWAY7001 config MACH_GATEWAY7001
bool "Gateway 7001" bool "Gateway 7001"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Gateway's Say 'Y' here if you want your kernel to support Gateway's
7001 Access Point. For more information on this platform, 7001 Access Point. For more information on this platform,
...@@ -60,7 +60,7 @@ config MACH_GATEWAY7001 ...@@ -60,7 +60,7 @@ config MACH_GATEWAY7001
config MACH_WG302V2 config MACH_WG302V2
bool "Netgear WG302 v2 / WAG302 v2" bool "Netgear WG302 v2 / WAG302 v2"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Netgear's Say 'Y' here if you want your kernel to support Netgear's
WG302 v2 or WAG302 v2 Access Points. For more information WG302 v2 or WAG302 v2 Access Points. For more information
...@@ -68,6 +68,7 @@ config MACH_WG302V2 ...@@ -68,6 +68,7 @@ config MACH_WG302V2
config ARCH_IXDP425 config ARCH_IXDP425
bool "IXDP425" bool "IXDP425"
depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Intel's Say 'Y' here if you want your kernel to support Intel's
IXDP425 Development Platform (Also known as Richfield). IXDP425 Development Platform (Also known as Richfield).
...@@ -75,6 +76,7 @@ config ARCH_IXDP425 ...@@ -75,6 +76,7 @@ config ARCH_IXDP425
config MACH_IXDPG425 config MACH_IXDPG425
bool "IXDPG425" bool "IXDPG425"
depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Intel's Say 'Y' here if you want your kernel to support Intel's
IXDPG425 Development Platform (Also known as Montajade). IXDPG425 Development Platform (Also known as Montajade).
...@@ -120,7 +122,7 @@ config ARCH_PRPMC1100 ...@@ -120,7 +122,7 @@ config ARCH_PRPMC1100
config MACH_NAS100D config MACH_NAS100D
bool bool
prompt "NAS100D" prompt "NAS100D"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Iomega's Say 'Y' here if you want your kernel to support Iomega's
NAS 100d device. For more information on this platform, NAS 100d device. For more information on this platform,
...@@ -129,7 +131,7 @@ config MACH_NAS100D ...@@ -129,7 +131,7 @@ config MACH_NAS100D
config MACH_DSMG600 config MACH_DSMG600
bool bool
prompt "D-Link DSM-G600 RevA" prompt "D-Link DSM-G600 RevA"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support D-Link's Say 'Y' here if you want your kernel to support D-Link's
DSM-G600 RevA device. For more information on this platform, DSM-G600 RevA device. For more information on this platform,
...@@ -143,7 +145,7 @@ config ARCH_IXDP4XX ...@@ -143,7 +145,7 @@ config ARCH_IXDP4XX
config MACH_FSG config MACH_FSG
bool bool
prompt "Freecom FSG-3" prompt "Freecom FSG-3"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Freecom's Say 'Y' here if you want your kernel to support Freecom's
FSG-3 device. For more information on this platform, FSG-3 device. For more information on this platform,
...@@ -152,7 +154,7 @@ config MACH_FSG ...@@ -152,7 +154,7 @@ config MACH_FSG
config MACH_ARCOM_VULCAN config MACH_ARCOM_VULCAN
bool bool
prompt "Arcom/Eurotech Vulcan" prompt "Arcom/Eurotech Vulcan"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support Arcom's Say 'Y' here if you want your kernel to support Arcom's
Vulcan board. Vulcan board.
...@@ -173,7 +175,7 @@ config CPU_IXP43X ...@@ -173,7 +175,7 @@ config CPU_IXP43X
config MACH_GTWX5715 config MACH_GTWX5715
bool "Gemtek WX5715 (Linksys WRV54G)" bool "Gemtek WX5715 (Linksys WRV54G)"
depends on ARCH_IXP4XX depends on ARCH_IXP4XX
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
This board is currently inside the Linksys WRV54G Gateways. This board is currently inside the Linksys WRV54G Gateways.
...@@ -196,7 +198,7 @@ config MACH_DEVIXP ...@@ -196,7 +198,7 @@ config MACH_DEVIXP
config MACH_MICCPT config MACH_MICCPT
bool "Omicron MICCPT" bool "Omicron MICCPT"
select FORCE_PCI depends on IXP4XX_PCI_LEGACY
help help
Say 'Y' here if you want your kernel to support the MICCPT Say 'Y' here if you want your kernel to support the MICCPT
board from OMICRON electronics GmbH. board from OMICRON electronics GmbH.
...@@ -209,9 +211,16 @@ config MACH_MIC256 ...@@ -209,9 +211,16 @@ config MACH_MIC256
comment "IXP4xx Options" 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 config IXP4XX_INDIRECT_PCI
bool "Use indirect PCI memory access" bool "Use indirect PCI memory access"
depends on PCI depends on IXP4XX_PCI_LEGACY
help help
IXP4xx provides two methods of accessing PCI memory space: IXP4xx provides two methods of accessing PCI memory space:
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/gpio/machine.h> #include <linux/gpio/machine.h>
#include <linux/platform_data/pata_ixp4xx_cf.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/memory.h> #include <asm/memory.h>
......
...@@ -27,12 +27,12 @@ ...@@ -27,12 +27,12 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/sched_clock.h> #include <linux/sched_clock.h>
#include <linux/soc/ixp4xx/cpu.h>
#include <linux/irqchip/irq-ixp4xx.h> #include <linux/irqchip/irq-ixp4xx.h>
#include <linux/platform_data/timer-ixp4xx.h> #include <linux/platform_data/timer-ixp4xx.h>
#include <linux/dma-map-ops.h> #include <linux/dma-map-ops.h>
#include <mach/udc.h> #include <mach/udc.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/io.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/exception.h> #include <asm/exception.h>
...@@ -44,6 +44,27 @@ ...@@ -44,6 +44,27 @@
#include "irqs.h" #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 #define IXP4XX_TIMER_FREQ 66666000
/************************************************************************* /*************************************************************************
...@@ -215,6 +236,27 @@ static struct resource ixp46x_i2c_resources[] = { ...@@ -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 * I2C controller. The IXP46x uses the same block as the IOP3xx, so
* we just use the same device name. * we just use the same device name.
...@@ -227,7 +269,8 @@ static struct platform_device ixp46x_i2c_controller = { ...@@ -227,7 +269,8 @@ static struct platform_device ixp46x_i2c_controller = {
}; };
static struct platform_device *ixp46x_devices[] __initdata = { static struct platform_device *ixp46x_devices[] __initdata = {
&ixp46x_i2c_controller &ixp46x_hwrandom_device,
&ixp46x_i2c_controller,
}; };
unsigned long ixp4xx_exp_bus_size; unsigned long ixp4xx_exp_bus_size;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <mach/hardware.h>
#include "irqs.h" #include "irqs.h"
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "ixp4xx-regs.h" #include "ixp4xx-regs.h"
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#include <mach/cpu.h> #include <linux/soc/ixp4xx/cpu.h>
#endif #endif
/* Platform helper functions and definitions */ /* Platform helper functions and definitions */
......
...@@ -45,21 +45,21 @@ ...@@ -45,21 +45,21 @@
* it can be used with the low-level debug code. * it can be used with the low-level debug code.
*/ */
#define IXP4XX_PERIPHERAL_BASE_PHYS 0xC8000000 #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 #define IXP4XX_PERIPHERAL_REGION_SIZE 0x00013000
/* /*
* PCI Config registers * PCI Config registers
*/ */
#define IXP4XX_PCI_CFG_BASE_PHYS 0xC0000000 #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 #define IXP4XX_PCI_CFG_REGION_SIZE 0x00001000
/* /*
* Expansion BUS Configuration registers * Expansion BUS Configuration registers
*/ */
#define IXP4XX_EXP_CFG_BASE_PHYS 0xC4000000 #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_CFG_REGION_SIZE 0x00001000
#define IXP4XX_EXP_CS0_OFFSET 0x00 #define IXP4XX_EXP_CS0_OFFSET 0x00
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
#define IXP4XX_SSP_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x12000) #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_UART1_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x0000)
#define IXP4XX_UART2_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000) #define IXP4XX_UART2_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000)
#define IXP4XX_PMU_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000) #define IXP4XX_PMU_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000)
...@@ -299,58 +300,4 @@ ...@@ -299,58 +300,4 @@
#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ #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 #endif
...@@ -79,20 +79,6 @@ extern unsigned long ixp4xx_exp_bus_size; ...@@ -79,20 +79,6 @@ extern unsigned long ixp4xx_exp_bus_size;
#define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66MHzi APB BUS */ #define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66MHzi APB BUS */
#define IXP4XX_UART_XTAL 14745600 #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 * Frequency of clock used for primary clocksource
*/ */
......
...@@ -9,8 +9,12 @@ ...@@ -9,8 +9,12 @@
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.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 = { static struct map_desc ixp4xx_of_io_desc[] __initdata = {
/* /*
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <mach/hardware.h>
#include "irqs.h" #include "irqs.h"
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <mach/hardware.h>
#include "irqs.h" #include "irqs.h"
......
...@@ -1058,7 +1058,7 @@ config PATA_ISAPNP ...@@ -1058,7 +1058,7 @@ config PATA_ISAPNP
config PATA_IXP4XX_CF config PATA_IXP4XX_CF
tristate "IXP4XX Compact Flash support" tristate "IXP4XX Compact Flash support"
depends on ARCH_IXP4XX depends on ARCH_IXP4XX || COMPILE_TEST
help help
This option enables support for a Compact Flash connected on This option enables support for a Compact Flash connected on
the ixp4xx expansion bus. This driver had been written for the ixp4xx expansion bus. This driver had been written for
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/pata_ixp4xx_cf.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#define DRV_NAME "pata_ixp4xx_cf" #define DRV_NAME "pata_ixp4xx_cf"
......
...@@ -152,7 +152,7 @@ config HW_RANDOM_VIA ...@@ -152,7 +152,7 @@ config HW_RANDOM_VIA
config HW_RANDOM_IXP4XX config HW_RANDOM_IXP4XX
tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support" tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
depends on ARCH_IXP4XX depends on ARCH_IXP4XX || COMPILE_TEST
default HW_RANDOM default HW_RANDOM
help help
This driver provides kernel-side support for the Pseudo-Random This driver provides kernel-side support for the Pseudo-Random
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* drivers/char/hw_random/ixp4xx-rng.c * drivers/char/hw_random/ixp4xx-rng.c
* *
...@@ -8,23 +9,20 @@ ...@@ -8,23 +9,20 @@
* Copyright 2005 (c) MontaVista Software, Inc. * Copyright 2005 (c) MontaVista Software, Inc.
* *
* Fixes by Michael Buesch * 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/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/hw_random.h> #include <linux/hw_random.h>
#include <linux/of.h>
#include <linux/soc/ixp4xx/cpu.h>
#include <asm/io.h> #include <asm/io.h>
#include <mach/hardware.h>
static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer) static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer)
{ {
...@@ -40,35 +38,40 @@ static struct hwrng ixp4xx_rng_ops = { ...@@ -40,35 +38,40 @@ static struct hwrng ixp4xx_rng_ops = {
.data_read = ixp4xx_rng_data_read, .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; void __iomem * rng_base;
int err; struct device *dev = &pdev->dev;
struct resource *res;
if (!cpu_is_ixp46x()) /* includes IXP455 */ if (!cpu_is_ixp46x()) /* includes IXP455 */
return -ENOSYS; return -ENOSYS;
rng_base = ioremap(0x70002100, 4); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!rng_base) rng_base = devm_ioremap_resource(dev, res);
return -ENOMEM; if (IS_ERR(rng_base))
ixp4xx_rng_ops.priv = (unsigned long)rng_base; return PTR_ERR(rng_base);
err = hwrng_register(&ixp4xx_rng_ops);
if (err)
iounmap(rng_base);
return err; ixp4xx_rng_ops.priv = (unsigned long)rng_base;
return devm_hwrng_register(dev, &ixp4xx_rng_ops);
} }
static void __exit ixp4xx_rng_exit(void) static const struct of_device_id ixp4xx_rng_of_match[] = {
{ {
void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv; .compatible = "intel,ixp46x-rng",
},
hwrng_unregister(&ixp4xx_rng_ops); {},
iounmap(rng_base); };
} MODULE_DEVICE_TABLE(of, ixp4xx_rng_of_match);
module_init(ixp4xx_rng_init); static struct platform_driver ixp4xx_rng_driver = {
module_exit(ixp4xx_rng_exit); .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_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x"); MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x");
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <linux/soc/ixp4xx/npe.h> #include <linux/soc/ixp4xx/npe.h>
#include <linux/soc/ixp4xx/qmgr.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 #define MAX_KEYLEN 32
/* hash: cfgword + 2 * digestlen; crypt: keylen + cfgword */ /* hash: cfgword + 2 * digestlen; crypt: keylen + cfgword */
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/soc/ixp4xx/npe.h> #include <linux/soc/ixp4xx/npe.h>
#include <linux/soc/ixp4xx/qmgr.h> #include <linux/soc/ixp4xx/qmgr.h>
#include <mach/hardware.h>
#include <linux/soc/ixp4xx/cpu.h>
#include "ixp46x_ts.h" #include "ixp46x_ts.h"
......
...@@ -12,9 +12,8 @@ ...@@ -12,9 +12,8 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#include <linux/soc/ixp4xx/cpu.h>
#include "ixp46x_ts.h" #include "ixp46x_ts.h"
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/soc/ixp4xx/npe.h> #include <linux/soc/ixp4xx/npe.h>
#include <linux/soc/ixp4xx/qmgr.h> #include <linux/soc/ixp4xx/qmgr.h>
#include <linux/soc/ixp4xx/cpu.h>
#define DEBUG_DESC 0 #define DEBUG_DESC 0
#define DEBUG_RX 0 #define DEBUG_RX 0
......
...@@ -37,6 +37,14 @@ config PCI_FTPCI100 ...@@ -37,6 +37,14 @@ config PCI_FTPCI100
depends on OF depends on OF
default ARCH_GEMINI 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 config PCI_TEGRA
bool "NVIDIA Tegra PCIe controller" bool "NVIDIA Tegra PCIe controller"
depends on ARCH_TEGRA || COMPILE_TEST depends on ARCH_TEGRA || COMPILE_TEST
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PCIE_CADENCE) += cadence/ obj-$(CONFIG_PCIE_CADENCE) += cadence/
obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o 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) += pci-hyperv.o
obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
......
// 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 @@ ...@@ -20,6 +20,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/soc/ixp4xx/npe.h> #include <linux/soc/ixp4xx/npe.h>
#include <mach/hardware.h>
#include <linux/soc/ixp4xx/cpu.h>
#define DEBUG_MSG 0 #define DEBUG_MSG 0
#define DEBUG_FW 0 #define DEBUG_FW 0
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/soc/ixp4xx/qmgr.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 struct qmgr_regs __iomem *qmgr_regs;
static int qmgr_irq_1; static int qmgr_irq_1;
......
/* 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
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* arch/arm/mach-ixp4xx/include/mach/cpu.h
*
* IXP4XX cpu type detection * IXP4XX cpu type detection
* *
* Copyright (C) 2007 MontaVista Software, Inc. * Copyright (C) 2007 MontaVista Software, Inc.
*/ */
#ifndef __ASM_ARCH_CPU_H__ #ifndef __SOC_IXP4XX_CPU_H__
#define __ASM_ARCH_CPU_H__ #define __SOC_IXP4XX_CPU_H__
#include <linux/io.h> #include <linux/io.h>
#ifdef CONFIG_ARM
#include <asm/cputype.h> #include <asm/cputype.h>
#endif
/* Processor id value in CP15 Register 0 */ /* Processor id value in CP15 Register 0 */
#define IXP42X_PROCESSOR_ID_VALUE 0x690541c0 /* including unused 0x690541Ex */ #define IXP42X_PROCESSOR_ID_VALUE 0x690541c0 /* including unused 0x690541Ex */
...@@ -23,6 +23,61 @@ ...@@ -23,6 +23,61 @@
#define IXP46X_PROCESSOR_ID_VALUE 0x69054200 /* including IXP455 */ #define IXP46X_PROCESSOR_ID_VALUE 0x69054200 /* including IXP455 */
#define IXP46X_PROCESSOR_ID_MASK 0xfffffff0 #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)) == \ #define cpu_is_ixp42x_rev_a0() ((read_cpuid_id() & (IXP42X_PROCESSOR_ID_MASK | 0xF)) == \
IXP42X_PROCESSOR_ID_VALUE) IXP42X_PROCESSOR_ID_VALUE)
#define cpu_is_ixp42x() ((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \ #define cpu_is_ixp42x() ((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \
...@@ -32,23 +87,20 @@ ...@@ -32,23 +87,20 @@
#define cpu_is_ixp46x() ((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \ #define cpu_is_ixp46x() ((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \
IXP46X_PROCESSOR_ID_VALUE) 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) static inline u32 ixp4xx_read_feature_bits(void)
{ {
u32 val = ~__raw_readl(IXP4XX_EXP_CFG2); return 0;
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) static inline void ixp4xx_write_feature_bits(u32 value)
{ {
__raw_writel(~value, IXP4XX_EXP_CFG2);
} }
#endif
#endif /* _ASM_ARCH_CPU_H */ #endif /* _ASM_ARCH_CPU_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment