* [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support
@ 2026-08-16 17:56 Sascha Hauer
2026-08-16 17:56 ` [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support Sascha Hauer
` (28 more replies)
0 siblings, 29 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
This series drops unused for longer remnants of the PXA2xx support and
adds device tree based PXA3xx support instead. The PXA2xx boards have
been removed already earlier leaving the remaining SoC code unused.
Should anybody have interest in PXA2xx it should be straight forward
adding back based on the new device tree code.
The board supported with this series is a Raumfeld Speaker which I had
lying under my desk catching dust, but now serves me as a music player
again. The PXA3xx support is fairly complete:
- NAND support including 1st stage load
- USB OHCI
- watchdog
- GPIO
- clk driver
- SD/MMC support (though untested, the speaker only has a SDIO WiFi card
which is detected by barebox, but ignored)
What's missing right now is pinctrl support, the pinmux is configured by
a register table in the PBL.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Sascha Hauer (27):
ARM: pxa: remove PXA25x and PXA27x support
video: remove the PXA framebuffer driver
ARM: cache: drive the XSC3 cache with the ARMv4 functions
mci: pxamci: get the clock from the clk API
pwm: pxa: get the clock from the clk API
serial: pxa: get the clock from the clk API
clk: pxa: add a device tree clock driver for PXA3xx
mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config
mtd: nand: nand_mrvl_nfc: support the nand-controller bindings
mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command
mtd: nand: mrvl_nfc: do not report a command timeout as an error
mci: pxamci: probe from the device tree
serial: pxa: add device tree support
serial: pxa: provide the Linux console name
gpio: pxa: add a driver and switch the architecture to GPIOLIB
ARM: pxa: add DEBUG_LL support
ARM: pxa: let the board select the SoC
ARM: pxa: enable device tree support
scripts: add pxa-image
ARM: pxa: add a NAND first stage loader
filetype: detect PXA3xx NTIM images
ARM: pxa: add a barebox update handler for NAND
clocksource: add a driver for the PXA OS timer and its watchdog
ARM: pxa: move over to MULTIARCH
ARM: pxa: reset straight away and without complaining
ARM: pxa: add Raumfeld Speaker board support
ARM: multi_v5_v6_defconfig: enable PXA support
Documentation/boards/pxa/Phytec-phyCORE-PXA270.rst | 6 -
Documentation/boards/pxa/raumfeld.rst | 78 ++
arch/arm/Kconfig | 13 +-
arch/arm/boards/Makefile | 1 +
arch/arm/boards/raumfeld-speaker/Makefile | 5 +
arch/arm/boards/raumfeld-speaker/board.c | 37 +
arch/arm/boards/raumfeld-speaker/lowlevel-obm.c | 206 +++
arch/arm/boards/raumfeld-speaker/lowlevel.c | 106 ++
arch/arm/configs/multi_v5_v6_defconfig | 18 +-
arch/arm/cpu/cache_32.c | 31 +
arch/arm/dts/Makefile | 1 +
arch/arm/dts/pxa300-raumfeld-speaker.dts | 108 ++
arch/arm/include/asm/debug_ll.h | 2 +
arch/arm/include/asm/system_info.h | 9 +
arch/arm/mach-pxa/Kconfig | 51 +-
arch/arm/mach-pxa/Makefile | 12 +-
arch/arm/mach-pxa/bbu.c | 96 ++
arch/arm/mach-pxa/clocksource.c | 41 -
arch/arm/mach-pxa/common.c | 29 +-
arch/arm/mach-pxa/devices.c | 6 -
arch/arm/mach-pxa/gpio.c | 101 --
arch/arm/mach-pxa/mfp-pxa2xx.c | 191 ---
arch/arm/mach-pxa/pxa2xx.c | 69 -
arch/arm/mach-pxa/pxa3xx.c | 6 +-
arch/arm/mach-pxa/sleep.S | 28 -
arch/arm/mach-pxa/speed-pxa25x.c | 54 -
arch/arm/mach-pxa/speed-pxa27x.c | 54 -
arch/arm/mach-pxa/speed-pxa3xx.c | 43 -
arch/arm/mach-pxa/xload-nand.c | 255 ++++
common/Kconfig.debug_ll | 17 +
common/filetype.c | 11 +
drivers/clk/Makefile | 1 +
drivers/clk/pxa/Makefile | 3 +
drivers/clk/pxa/clk-pxa.c | 122 ++
drivers/clk/pxa/clk-pxa.h | 118 ++
drivers/clk/pxa/clk-pxa3xx.c | 357 +++++
drivers/clocksource/Kconfig | 7 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-pxa.c | 151 ++
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-pxa.c | 146 ++
drivers/mci/Kconfig | 4 +-
drivers/mci/pxamci.c | 88 +-
drivers/mci/pxamci.h | 2 +-
drivers/mtd/nand/raw/nand_mrvl_nfc.c | 107 +-
drivers/pwm/Kconfig | 7 +-
drivers/pwm/pxa_pwm.c | 38 +-
drivers/serial/serial_pxa.c | 27 +-
drivers/usb/gadget/Kconfig | 7 -
drivers/usb/gadget/udc/Makefile | 1 -
drivers/usb/gadget/udc/pxa27x_udc.c | 1469 --------------------
drivers/usb/gadget/udc/pxa27x_udc.h | 380 -----
drivers/video/Kconfig | 7 -
drivers/video/Makefile | 1 -
drivers/video/pxa.c | 548 --------
images/Makefile | 1 +
images/Makefile.pxa | 32 +
include/filetype.h | 1 +
include/mach/pxa/bbu.h | 18 +
include/mach/pxa/clock.h | 19 -
include/mach/pxa/debug_ll.h | 74 +
include/mach/pxa/devices.h | 2 -
include/mach/pxa/gpio.h | 31 -
include/mach/pxa/hardware.h | 18 -
include/mach/pxa/mci_pxa2xx.h | 12 -
include/mach/pxa/mfp-pxa27x.h | 472 -------
include/mach/pxa/mfp-pxa2xx.h | 135 --
include/mach/pxa/pxa-regs.h | 12 -
include/mach/pxa/pxa25x-regs.h | 8 -
include/mach/pxa/pxa27x-regs.h | 8 -
include/mach/pxa/pxa2xx-regs.h | 273 ----
include/mach/pxa/pxafb.h | 81 --
include/mach/pxa/regs-lcd.h | 182 ---
include/mach/pxa/udc_pxa2xx.h | 28 -
include/mach/pxa/xload.h | 42 +
scripts/Kconfig | 7 +
scripts/Makefile | 1 +
scripts/pxa-image.c | 281 ++++
79 files changed, 2583 insertions(+), 4439 deletions(-)
---
base-commit: 23acc2f11182214ff655ed7c3b226160282c6a21
change-id: 20260816-pxa3xx-9d16ccfd1ca9
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 02/27] video: remove the PXA framebuffer driver Sascha Hauer
` (27 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
No board in tree selects ARCH_PXA25X or ARCH_PXA27X, so none of this code
is reachable, let alone tested. Remove it rather than carry it along
through the PXA cleanup.
Gone with it:
- The SoC support itself: mfp-pxa2xx.c, pxa2xx.c, the two speed-*.c and
the PXA25x/27x half of sleep.S, which was wrapped in a #if on the two
symbols and had no caller anywhere.
- pxa27x_udc, the only driver that depended on ARCH_PXA27X and could
therefore never be built either.
- The documentation for the Phytec phyCORE-PXA270, whose defconfig was
removed long ago and which points at it.
- __gpio_is_occupied(), which had no user at all, and the PXA26x variant
of __gpio_is_inverted(), which was guarded by a CONFIG_CPU_PXA26x that
does not exist.
Drivers that depend on ARCH_PXA2XX but are not inherently PXA2xx -- pwm
and mci -- are left alone here. They become unselectable, which is
honest: they do not build for PXA3xx yet. Both are fixed up in the course
of the clk conversion.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/boards/pxa/Phytec-phyCORE-PXA270.rst | 6 -
arch/arm/mach-pxa/Kconfig | 31 +-
arch/arm/mach-pxa/Makefile | 5 +-
arch/arm/mach-pxa/mfp-pxa2xx.c | 191 ---
arch/arm/mach-pxa/pxa2xx.c | 69 -
arch/arm/mach-pxa/sleep.S | 28 -
arch/arm/mach-pxa/speed-pxa25x.c | 54 -
arch/arm/mach-pxa/speed-pxa27x.c | 54 -
drivers/mci/pxamci.c | 16 +-
drivers/usb/gadget/Kconfig | 7 -
drivers/usb/gadget/udc/Makefile | 1 -
drivers/usb/gadget/udc/pxa27x_udc.c | 1469 --------------------
drivers/usb/gadget/udc/pxa27x_udc.h | 380 -----
include/mach/pxa/gpio.h | 30 -
include/mach/pxa/hardware.h | 18 -
include/mach/pxa/mfp-pxa27x.h | 472 -------
include/mach/pxa/mfp-pxa2xx.h | 135 --
include/mach/pxa/pxa-regs.h | 12 -
include/mach/pxa/pxa25x-regs.h | 8 -
include/mach/pxa/pxa27x-regs.h | 8 -
include/mach/pxa/pxa2xx-regs.h | 273 ----
include/mach/pxa/udc_pxa2xx.h | 28 -
22 files changed, 9 insertions(+), 3286 deletions(-)
diff --git a/Documentation/boards/pxa/Phytec-phyCORE-PXA270.rst b/Documentation/boards/pxa/Phytec-phyCORE-PXA270.rst
deleted file mode 100644
index 23b2829fa8..0000000000
--- a/Documentation/boards/pxa/Phytec-phyCORE-PXA270.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-Phytec phyCORE-PXA270
-=====================
-
-Building the bootloader image for this target is covered by the ``phytec-phycore-pxa270_defconfig``.
-
-Use the corresponding ``barebox.bin`` file for this target.
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 53becd51d4..3a58736d2d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,33 +4,14 @@ if ARCH_PXA
# ----------------------------------------------------------
-config ARCH_PXA2XX
- bool
- select CPU_XSCALE
-
config ARCH_PXA3XX
- bool
- select CPU_XSC3
- select HAVE_CLK
- select COMMON_CLK
+ bool
+ default y
+ select CPU_XSC3
+ select HAVE_CLK
+ select COMMON_CLK
config ARCH_PXA310
- bool
-
-choice
- prompt "Intel/Marvell PXA Processor"
-
-config ARCH_PXA25X
- bool "PXA25x"
- select ARCH_PXA2XX
-
-config ARCH_PXA27X
- bool "PXA27x"
- select ARCH_PXA2XX
-
-config ARCH_PXA3XX
- bool "PXA3xx"
-
-endchoice
+ bool
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 9249c8fe14..fbcc4b8859 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -1,12 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += clocksource.o
+obj-y += sleep.o
obj-y += common.o
obj-y += gpio.o
obj-y += devices.o
-obj-y += sleep.o
-obj-$(CONFIG_ARCH_PXA2XX) += mfp-pxa2xx.o pxa2xx.o
-obj-$(CONFIG_ARCH_PXA25X) += speed-pxa25x.o
-obj-$(CONFIG_ARCH_PXA27X) += speed-pxa27x.o
obj-$(CONFIG_ARCH_PXA3XX) += speed-pxa3xx.o mfp-pxa3xx.o pxa3xx.o
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
deleted file mode 100644
index aca46c45b3..0000000000
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/mfp-pxa2xx.c
- *
- * PXA2xx pin mux configuration support
- *
- * The GPIOs on PXA2xx can be configured as one of many alternate
- * functions, this is by concept samilar to the MFP configuration
- * on PXA3xx, what's more important, the low power pin state and
- * wakeup detection are also supported by the same framework.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <common.h>
-#include <errno.h>
-#include <init.h>
-
-#include <mach/pxa/gpio.h>
-#include <mach/pxa/hardware.h>
-#include <mach/pxa/mfp-pxa2xx.h>
-#include <mach/pxa/pxa-regs.h>
-
-#define PGSR(x) __REG2(0x40F00020, (x) << 2)
-#define __GAFR(u, x) __REG2((u) ? 0x40E00058 : 0x40E00054, (x) << 3)
-#define GAFR_L(x) __GAFR(0, x)
-#define GAFR_U(x) __GAFR(1, x)
-
-struct gpio_desc {
- unsigned valid:1;
- unsigned dir_inverted:1;
- unsigned long config;
-};
-
-static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
-
-static unsigned long gpdr_lpm[4];
-
-static int __mfp_config_gpio(unsigned gpio, unsigned long c)
-{
- unsigned long gafr, mask = GPIO_bit(gpio);
- int bank = gpio_to_bank(gpio);
- int uorl = !!(gpio & 0x10); /* GAFRx_U or GAFRx_L ? */
- int shft = (gpio & 0xf) << 1;
- int fn = MFP_AF(c);
- int is_out = (c & MFP_DIR_OUT) ? 1 : 0;
-
- if (fn > 3)
- return -EINVAL;
-
- /* alternate function and direction at run-time */
- gafr = (uorl == 0) ? GAFR_L(bank) : GAFR_U(bank);
- gafr = (gafr & ~(0x3 << shft)) | (fn << shft);
-
- if (uorl == 0)
- GAFR_L(bank) = gafr;
- else
- GAFR_U(bank) = gafr;
-
- if (is_out ^ gpio_desc[gpio].dir_inverted)
- GPDR(gpio) |= mask;
- else
- GPDR(gpio) &= ~mask;
-
- /* alternate function and direction at low power mode */
- switch (c & MFP_LPM_STATE_MASK) {
- case MFP_LPM_DRIVE_HIGH:
- PGSR(bank) |= mask;
- is_out = 1;
- break;
- case MFP_LPM_DRIVE_LOW:
- PGSR(bank) &= ~mask;
- is_out = 1;
- break;
- case MFP_LPM_DEFAULT:
- break;
- default:
- /* warning and fall through, treat as MFP_LPM_DEFAULT */
- pr_warning("%s: GPIO%d: unsupported low power mode\n",
- __func__, gpio);
- break;
- }
-
- if (is_out ^ gpio_desc[gpio].dir_inverted)
- gpdr_lpm[bank] |= mask;
- else
- gpdr_lpm[bank] &= ~mask;
-
- return 0;
-}
-
-static inline int __mfp_validate(int mfp)
-{
- int gpio = mfp_to_gpio(mfp);
-
- if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
- pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
- return -1;
- }
-
- return gpio;
-}
-
-void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
-{
- unsigned long *c;
- int i, gpio;
-
- for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
-
- gpio = __mfp_validate(MFP_PIN(*c));
- if (gpio < 0)
- continue;
-
- gpio_desc[gpio].config = *c;
- __mfp_config_gpio(gpio, *c);
- }
-}
-
-void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm)
-{
- unsigned long c;
- int gpio;
-
- gpio = __mfp_validate(mfp);
- if (gpio < 0)
- return;
-
- c = gpio_desc[gpio].config;
- c = (c & ~MFP_LPM_STATE_MASK) | lpm;
- __mfp_config_gpio(gpio, c);
-}
-
-static void __init pxa25x_mfp_init(void)
-{
- int i;
-
- for (i = 0; i <= pxa_last_gpio; i++)
- gpio_desc[i].valid = 1;
-
- /* PXA26x has additional 4 GPIOs (86/87/88/89) which has the
- * direction bit inverted in GPDR2. See PXA26x DM 4.1.1.
- */
- for (i = 86; i <= pxa_last_gpio; i++)
- gpio_desc[i].dir_inverted = 1;
-}
-
-static void __init pxa27x_mfp_init(void)
-{
- int i;
-
- for (i = 0; i <= pxa_last_gpio; i++) {
- /*
- * skip GPIO2, 5, 6, 7, 8, they are not
- * valid pins allow configuration
- */
- if (i == 2 || i == 5 || i == 6 || i == 7 || i == 8)
- continue;
-
- gpio_desc[i].valid = 1;
- }
-}
-
-static int __init pxa2xx_mfp_init(void)
-{
- int i;
-
- if (!cpu_is_pxa2xx())
- return 0;
-
- if (cpu_is_pxa25x()) {
- pxa_init_gpio(0, 84);
- pxa25x_mfp_init();
- }
-
- if (cpu_is_pxa27x()) {
- pxa_init_gpio(2, 120);
- pxa27x_mfp_init();
- }
-
- /* clear RDH bit to enable GPIO receivers after reset/sleep exit */
- PSSR = PSSR_RDH;
-
- /* initialize gafr_run[], pgsr_lpm[] from existing values */
- for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++)
- gpdr_lpm[i] = GPDR(i * 32);
-
- return 0;
-}
-postcore_initcall(pxa2xx_mfp_init);
diff --git a/arch/arm/mach-pxa/pxa2xx.c b/arch/arm/mach-pxa/pxa2xx.c
deleted file mode 100644
index ee50dca7a9..0000000000
--- a/arch/arm/mach-pxa/pxa2xx.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * (C) Copyright 2014 Robert Jarzmik <robert.jarzmik@free.fr>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <common.h>
-#include <init.h>
-#include <poweroff.h>
-#include <reset_source.h>
-#include <mach/pxa/hardware.h>
-#include <mach/pxa/pxa-regs.h>
-
-extern void pxa_suspend(int mode);
-
-static int pxa_detect_reset_source(void)
-{
- u32 reg = RCSR;
-
- /*
- * Order is important, as many bits can be set together
- */
- if (reg & RCSR_GPR)
- reset_source_set(RESET_RST);
- else if (reg & RCSR_WDR)
- reset_source_set(RESET_WDG);
- else if (reg & RCSR_HWR)
- reset_source_set(RESET_POR);
- else if (reg & RCSR_SMR)
- reset_source_set(RESET_WKE);
- else
- reset_source_set(RESET_UKWN);
-
- return 0;
-}
-
-void pxa_clear_reset_source(void)
-{
- RCSR = RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR;
-}
-
-static void __noreturn pxa2xx_poweroff(struct poweroff_handler *handler,
- unsigned long flags)
-{
- shutdown_barebox();
-
- /* Clear last reset source */
- pxa_clear_reset_source();
- pxa_suspend(PWRMODE_DEEPSLEEP);
- unreachable();
-}
-
-static int pxa2xx_init(void)
-{
- poweroff_handler_register_fn(pxa2xx_poweroff);
-
- pxa_detect_reset_source();
-
- return 0;
-}
-device_initcall(pxa2xx_init);
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 3d12dc54de..7bf08275ef 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -14,40 +14,12 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/pxa/hardware.h>
-#include <mach/pxa/pxa2xx-regs.h>
#define MDREFR_KDIV 0x200a4000 // all banks
#define CCCR_SLEEP 0x00000107 // L=7 2N=2 A=0 PPDIS=0 CPDIS=0
#define UNCACHED_PHYS_0 0
.text
-#if (defined CONFIG_ARCH_PXA27X || defined CONFIG_ARCH_PXA25X)
-/*
- * pxa27x_finish_suspend()
- *
- * Forces CPU into sleep state.
- *
- * r0 = value for PWRMODE M field for desired sleep state
- */
-ENTRY(pxa_suspend)
- @ Put the processor to sleep
- @ (also workaround for sighting 28071)
-
- @ prepare value for sleep mode
- mov r1, r0 @ sleep mode
-
- @ Intel PXA270 Specification Update notes problems sleeping
- @ with core operating above 91 MHz
- @ (see Errata 50, ...processor does not exit from sleep...)
- ldr r6, =CCCR
- ldr r8, [r6] @ keep original value for resume
-
- ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
- mov r0, #0x2 @ prepare value for CLKCFG
-
- @ align execution to a cache line
- b pxa_cpu_do_suspend
-#endif
.ltorg
diff --git a/arch/arm/mach-pxa/speed-pxa25x.c b/arch/arm/mach-pxa/speed-pxa25x.c
deleted file mode 100644
index de3d5c251c..0000000000
--- a/arch/arm/mach-pxa/speed-pxa25x.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * clock.h - implementation of the PXA clock functions
- *
- * Copyright (C) 2014 Robert Jarzmik <robert.jarzmik@free.fr>
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <common.h>
-#include <mach/pxa/clock.h>
-#include <mach/pxa/pxa-regs.h>
-
-/* Crystal clock: 13MHz */
-#define BASE_CLK 13000000
-
-unsigned long pxa_get_uartclk(void)
-{
- return 14857000;
-}
-
-unsigned long pxa_get_mmcclk(void)
-{
- return 19500000;
-}
-
-/*
- * Return the current LCD clock frequency in units of 10kHz as
- */
-static unsigned int pxa_get_lcdclk_10khz(void)
-{
- unsigned long ccsr;
- unsigned int l, L, k, K;
-
- ccsr = CCSR;
-
- l = ccsr & 0x1f;
- k = (l <= 7) ? 1 : (l <= 16) ? 2 : 4;
-
- L = l * BASE_CLK;
- K = L / k;
-
- return (K / 10000);
-}
-
-unsigned long pxa_get_lcdclk(void)
-{
- return pxa_get_lcdclk_10khz() * 10000;
-}
-
-unsigned long pxa_get_pwmclk(void)
-{
- return BASE_CLK;
-}
diff --git a/arch/arm/mach-pxa/speed-pxa27x.c b/arch/arm/mach-pxa/speed-pxa27x.c
deleted file mode 100644
index 5441dc3d70..0000000000
--- a/arch/arm/mach-pxa/speed-pxa27x.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * clock.h - implementation of the PXA clock functions
- *
- * Copyright (C) 2010 by Marc Kleine-Budde <mkl@pengutronix.de>
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <common.h>
-#include <mach/pxa/clock.h>
-#include <mach/pxa/pxa-regs.h>
-
-/* Crystal clock: 13MHz */
-#define BASE_CLK 13000000
-
-unsigned long pxa_get_uartclk(void)
-{
- return 14857000;
-}
-
-unsigned long pxa_get_mmcclk(void)
-{
- return 19500000;
-}
-
-/*
- * Return the current LCD clock frequency in units of 10kHz as
- */
-static unsigned int pxa_get_lcdclk_10khz(void)
-{
- unsigned long ccsr;
- unsigned int l, L, k, K;
-
- ccsr = CCSR;
-
- l = ccsr & 0x1f;
- k = (l <= 7) ? 1 : (l <= 16) ? 2 : 4;
-
- L = l * BASE_CLK;
- K = L / k;
-
- return (K / 10000);
-}
-
-unsigned long pxa_get_lcdclk(void)
-{
- return pxa_get_lcdclk_10khz() * 10000;
-}
-
-unsigned long pxa_get_pwmclk(void)
-{
- return BASE_CLK;
-}
diff --git a/drivers/mci/pxamci.c b/drivers/mci/pxamci.c
index f337ea48ef..1f2aaf2031 100644
--- a/drivers/mci/pxamci.c
+++ b/drivers/mci/pxamci.c
@@ -216,20 +216,8 @@ static int pxamci_cmd_response(struct pxamci_host *host, struct mci_cmd *cmd)
stat = mmc_readl(MMC_STAT);
if (stat & STAT_TIME_OUT_RESPONSE)
return -ETIMEDOUT;
- if (stat & STAT_RES_CRC_ERR && cmd->resp_type & MMC_RSP_CRC) {
- /*
- * workaround for erratum #42:
- * Intel PXA27x Family Processor Specification Update Rev 001
- * A bogus CRC error can appear if the msb of a 136 bit
- * response is a one.
- */
- if (cpu_is_pxa27x() && cmd->resp_type & MMC_RSP_136 &&
- cmd->response[0] & 0x80000000)
- pr_debug("ignoring CRC from command %d - *risky*\n",
- cmd->cmdidx);
- else
- return -EILSEQ;
- }
+ if (stat & STAT_RES_CRC_ERR && cmd->resp_type & MMC_RSP_CRC)
+ return -EILSEQ;
return 0;
}
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 517255f477..365238930c 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -24,13 +24,6 @@ config USB_GADGET_DRIVER_AT91
default y
select USB_GADGET_DUALSPEED
-config USB_GADGET_DRIVER_PXA27X
- bool
- prompt "PXA27x gadget driver"
- depends on ARCH_PXA27X
- default y
- select USB_GADGET_DUALSPEED
-
config USB_GADGET_AUTOSTART
bool
default y
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 6e79e80cfa..db5f5faaa7 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -4,4 +4,3 @@ obj-$(CONFIG_USB_GADGET) += core.o
obj-$(CONFIG_USB_GADGET_DRIVER_ARC) += fsl_udc.o
obj-$(CONFIG_USB_GADGET_DRIVER_AT91) += at91_udc.o
-obj-$(CONFIG_USB_GADGET_DRIVER_PXA27X) += pxa27x_udc.o
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
deleted file mode 100644
index 20148f4878..0000000000
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ /dev/null
@@ -1,1469 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Handles the Intel 27x USB Device Controller (UDC)
- *
- * Inspired by original driver by Frank Becker, David Brownell, and others.
- * Copyright (C) 2008 Robert Jarzmik
- *
- * Taken from linux-2.6 kernel and adapted to barebox.
- */
-#include <common.h>
-#include <errno.h>
-#include <clock.h>
-#include <io.h>
-#include <gpio.h>
-#include <init.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "pxa27x_udc.h"
-#include <mach/pxa/udc_pxa2xx.h>
-#include <mach/pxa/pxa-regs.h>
-
-#define DRIVER_VERSION "2008-04-18"
-#define DRIVER_DESC "PXA 27x USB Device Controller driver"
-
-static const char driver_name[] = "pxa27x_udc";
-static struct pxa_udc *the_controller;
-
-static void handle_ep(struct pxa_ep *ep);
-
-static int is_match_usb_pxa(struct udc_usb_ep *udc_usb_ep, struct pxa_ep *ep,
- int config, int interface, int altsetting)
-{
- if (usb_endpoint_num(&udc_usb_ep->desc) != ep->addr)
- return 0;
- if (usb_endpoint_dir_in(&udc_usb_ep->desc) != ep->dir_in)
- return 0;
- if (usb_endpoint_type(&udc_usb_ep->desc) != ep->type)
- return 0;
- if ((ep->config != config) || (ep->interface != interface)
- || (ep->alternate != altsetting))
- return 0;
- return 1;
-}
-
-static struct pxa_ep *find_pxa_ep(struct pxa_udc *udc,
- struct udc_usb_ep *udc_usb_ep)
-{
- int i;
- struct pxa_ep *ep;
- int cfg = udc->config;
- int iface = udc->last_interface;
- int alt = udc->last_alternate;
-
- if (udc_usb_ep == &udc->udc_usb_ep[0])
- return &udc->pxa_ep[0];
-
- for (i = 1; i < NR_PXA_ENDPOINTS; i++) {
- ep = &udc->pxa_ep[i];
- if (is_match_usb_pxa(udc_usb_ep, ep, cfg, iface, alt))
- return ep;
- }
- return NULL;
-}
-
-static void update_pxa_ep_matches(struct pxa_udc *udc)
-{
- int i;
- struct udc_usb_ep *udc_usb_ep;
-
- for (i = 1; i < NR_USB_ENDPOINTS; i++) {
- udc_usb_ep = &udc->udc_usb_ep[i];
- if (udc_usb_ep->pxa_ep)
- udc_usb_ep->pxa_ep = find_pxa_ep(udc, udc_usb_ep);
- }
-}
-
-static void pio_irq_enable(struct pxa_ep *ep)
-{
- struct pxa_udc *udc = ep->dev;
- int index = EPIDX(ep);
- u32 udcicr0 = udc_readl(udc, UDCICR0);
- u32 udcicr1 = udc_readl(udc, UDCICR1);
-
- if (index < 16)
- udc_writel(udc, UDCICR0, udcicr0 | (3 << (index * 2)));
- else
- udc_writel(udc, UDCICR1, udcicr1 | (3 << ((index - 16) * 2)));
-}
-
-static void pio_irq_disable(struct pxa_ep *ep)
-{
- struct pxa_udc *udc = ep->dev;
- int index = EPIDX(ep);
- u32 udcicr0 = udc_readl(udc, UDCICR0);
- u32 udcicr1 = udc_readl(udc, UDCICR1);
-
- if (index < 16)
- udc_writel(udc, UDCICR0, udcicr0 & ~(3 << (index * 2)));
- else
- udc_writel(udc, UDCICR1, udcicr1 & ~(3 << ((index - 16) * 2)));
-}
-
-static inline void udc_set_mask_UDCCR(struct pxa_udc *udc, int mask)
-{
- u32 udccr = udc_readl(udc, UDCCR);
- udc_writel(udc, UDCCR,
- (udccr & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS));
-}
-
-static inline void udc_clear_mask_UDCCR(struct pxa_udc *udc, int mask)
-{
- u32 udccr = udc_readl(udc, UDCCR);
- udc_writel(udc, UDCCR,
- (udccr & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS));
-}
-
-static inline void ep_write_UDCCSR(struct pxa_ep *ep, int mask)
-{
- if (is_ep0(ep))
- mask |= UDCCSR0_ACM;
- udc_ep_writel(ep, UDCCSR, mask);
-}
-
-static int ep_count_bytes_remain(struct pxa_ep *ep)
-{
- if (ep->dir_in)
- return -EOPNOTSUPP;
- return udc_ep_readl(ep, UDCBCR) & 0x3ff;
-}
-
-static int ep_is_empty(struct pxa_ep *ep)
-{
- int ret;
-
- if (!is_ep0(ep) && ep->dir_in)
- return -EOPNOTSUPP;
- if (is_ep0(ep))
- ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR0_RNE);
- else
- ret = !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNE);
- return ret;
-}
-
-static int ep_is_full(struct pxa_ep *ep)
-{
- if (is_ep0(ep))
- return udc_ep_readl(ep, UDCCSR) & UDCCSR0_IPR;
- if (!ep->dir_in)
- return -EOPNOTSUPP;
- return !(udc_ep_readl(ep, UDCCSR) & UDCCSR_BNF);
-}
-
-static int epout_has_pkt(struct pxa_ep *ep)
-{
- if (!is_ep0(ep) && ep->dir_in)
- return -EOPNOTSUPP;
- if (is_ep0(ep))
- return udc_ep_readl(ep, UDCCSR) & UDCCSR0_OPC;
- return udc_ep_readl(ep, UDCCSR) & UDCCSR_PC;
-}
-
-static void set_ep0state(struct pxa_udc *udc, int state)
-{
- struct pxa_ep *ep = &udc->pxa_ep[0];
- char *old_stname = EP0_STNAME(udc);
-
- udc->ep0state = state;
- ep_dbg(ep, "state=%s->%s, udccsr0=0x%03x, udcbcr=%d\n", old_stname,
- EP0_STNAME(udc), udc_ep_readl(ep, UDCCSR),
- udc_ep_readl(ep, UDCBCR));
-}
-
-static void ep0_idle(struct pxa_udc *dev)
-{
- set_ep0state(dev, WAIT_FOR_SETUP);
-}
-
-static __init void pxa_ep_setup(struct pxa_ep *ep)
-{
- u32 new_udccr;
-
- new_udccr = ((ep->config << UDCCONR_CN_S) & UDCCONR_CN)
- | ((ep->interface << UDCCONR_IN_S) & UDCCONR_IN)
- | ((ep->alternate << UDCCONR_AISN_S) & UDCCONR_AISN)
- | ((EPADDR(ep) << UDCCONR_EN_S) & UDCCONR_EN)
- | ((EPXFERTYPE(ep) << UDCCONR_ET_S) & UDCCONR_ET)
- | ((ep->dir_in) ? UDCCONR_ED : 0)
- | ((ep->fifo_size << UDCCONR_MPS_S) & UDCCONR_MPS)
- | UDCCONR_EE;
-
- udc_ep_writel(ep, UDCCR, new_udccr);
-}
-
-static __init void pxa_eps_setup(struct pxa_udc *dev)
-{
- unsigned int i;
-
- dev_dbg(dev->dev, "%s: dev=%p\n", __func__, dev);
-
- for (i = 1; i < NR_PXA_ENDPOINTS; i++)
- pxa_ep_setup(&dev->pxa_ep[i]);
-}
-
-static struct usb_request *pxa_ep_alloc_request(struct usb_ep *_ep)
-{
- struct pxa27x_request *req;
-
- req = xzalloc(sizeof *req);
-
- INIT_LIST_HEAD(&req->queue);
- req->in_use = 0;
- req->udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-
- return &req->req;
-}
-
-static void pxa_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
-{
- struct pxa27x_request *req;
-
- req = container_of(_req, struct pxa27x_request, req);
- WARN_ON(!list_empty(&req->queue));
- kfree(req);
-}
-
-static void ep_add_request(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- if (unlikely(!req))
- return;
- ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
- req->req.length, udc_ep_readl(ep, UDCCSR));
-
- req->in_use = 1;
- list_add_tail(&req->queue, &ep->queue);
- pio_irq_enable(ep);
-}
-
-static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- if (unlikely(!req))
- return;
- ep_vdbg(ep, "req:%p, lg=%d, udccsr=0x%03x\n", req,
- req->req.length, udc_ep_readl(ep, UDCCSR));
-
- list_del_init(&req->queue);
- req->in_use = 0;
- if (!is_ep0(ep) && list_empty(&ep->queue))
- pio_irq_disable(ep);
-}
-
-static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status)
-{
- ep_del_request(ep, req);
- if (likely(req->req.status == -EINPROGRESS))
- req->req.status = status;
- else
- status = req->req.status;
-
- if (status && status != -ESHUTDOWN)
- ep_dbg(ep, "complete req %p stat %d len %u/%u\n",
- &req->req, status,
- req->req.actual, req->req.length);
-
- req->req.complete(&req->udc_usb_ep->usb_ep, &req->req);
-}
-
-static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- req_done(ep, req, 0);
-}
-
-static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- set_ep0state(ep->dev, OUT_STATUS_STAGE);
- ep_end_out_req(ep, req);
- ep0_idle(ep->dev);
-}
-
-static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- req_done(ep, req, 0);
-}
-
-static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- set_ep0state(ep->dev, IN_STATUS_STAGE);
- ep_end_in_req(ep, req);
-}
-
-static void nuke(struct pxa_ep *ep, int status)
-{
- struct pxa27x_request *req;
-
- while (!list_empty(&ep->queue)) {
- req = list_entry(ep->queue.next, struct pxa27x_request, queue);
- req_done(ep, req, status);
- }
-}
-
-static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- u32 *buf;
- int bytes_ep, bufferspace, count, i;
-
- bytes_ep = ep_count_bytes_remain(ep);
- bufferspace = req->req.length - req->req.actual;
-
- buf = (u32 *)(req->req.buf + req->req.actual);
-
- if (likely(!ep_is_empty(ep)))
- count = min(bytes_ep, bufferspace);
- else /* zlp */
- count = 0;
-
- for (i = count; i > 0; i -= 4)
- *buf++ = udc_ep_readl(ep, UDCDR);
- req->req.actual += count;
-
- ep_write_UDCCSR(ep, UDCCSR_PC);
-
- return count;
-}
-
-static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req,
- unsigned int max)
-{
- int length, count, remain, i;
- u32 *buf;
- u8 *buf_8;
-
- buf = (u32 *)(req->req.buf + req->req.actual);
-
- length = min(req->req.length - req->req.actual, max);
- req->req.actual += length;
-
- remain = length & 0x3;
- count = length & ~(0x3);
- for (i = count; i > 0 ; i -= 4)
- udc_ep_writel(ep, UDCDR, *buf++);
-
- buf_8 = (u8 *)buf;
- for (i = remain; i > 0; i--)
- udc_ep_writeb(ep, UDCDR, *buf_8++);
-
- ep_vdbg(ep, "length=%d+%d, udccsr=0x%03x\n", count, remain,
- udc_ep_readl(ep, UDCCSR));
-
- return length;
-}
-
-static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- int count, is_short, completed = 0;
-
- while (epout_has_pkt(ep)) {
- count = read_packet(ep, req);
-
- is_short = (count < ep->fifo_size);
- ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
- udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
- &req->req, req->req.actual, req->req.length);
-
- /* completion */
- if (is_short || req->req.actual == req->req.length) {
- completed = 1;
- break;
- }
- /* finished that packet. the next one may be waiting... */
- }
- return completed;
-}
-
-static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- unsigned max;
- int count, is_short, is_last = 0, completed = 0, totcount = 0;
- u32 udccsr;
-
- max = ep->fifo_size;
- do {
- is_short = 0;
-
- udccsr = udc_ep_readl(ep, UDCCSR);
- if (udccsr & UDCCSR_PC) {
- ep_vdbg(ep, "Clearing Transmit Complete, udccsr=%x\n",
- udccsr);
- ep_write_UDCCSR(ep, UDCCSR_PC);
- }
- if (udccsr & UDCCSR_TRN) {
- ep_vdbg(ep, "Clearing Underrun on, udccsr=%x\n",
- udccsr);
- ep_write_UDCCSR(ep, UDCCSR_TRN);
- }
-
- count = write_packet(ep, req, max);
- totcount += count;
-
- /* last packet is usually short (or a zlp) */
- if (unlikely(count < max)) {
- is_last = 1;
- is_short = 1;
- } else {
- if (likely(req->req.length > req->req.actual)
- || req->req.zero)
- is_last = 0;
- else
- is_last = 1;
- /* interrupt/iso maxpacket may not fill the fifo */
- is_short = unlikely(max < ep->fifo_size);
- }
-
- if (is_short)
- ep_write_UDCCSR(ep, UDCCSR_SP);
-
- /* requests complete when all IN data is in the FIFO */
- if (is_last) {
- completed = 1;
- break;
- }
- } while (!ep_is_full(ep));
-
- ep_dbg(ep, "wrote count:%d bytes%s%s, left:%d req=%p\n",
- totcount, is_last ? "/L" : "", is_short ? "/S" : "",
- req->req.length - req->req.actual, &req->req);
-
- return completed;
-}
-
-static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- int count, is_short, completed = 0;
-
- while (epout_has_pkt(ep)) {
- count = read_packet(ep, req);
- ep_write_UDCCSR(ep, UDCCSR0_OPC);
-
- is_short = (count < ep->fifo_size);
- ep_dbg(ep, "read udccsr:%03x, count:%d bytes%s req %p %d/%d\n",
- udc_ep_readl(ep, UDCCSR), count, is_short ? "/S" : "",
- &req->req, req->req.actual, req->req.length);
-
- if (is_short || req->req.actual >= req->req.length) {
- completed = 1;
- break;
- }
- }
-
- return completed;
-}
-
-static int write_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req)
-{
- unsigned count;
- int is_last, is_short;
-
- count = write_packet(ep, req, EP0_FIFO_SIZE);
-
- is_short = (count < EP0_FIFO_SIZE);
- is_last = ((count == 0) || (count < EP0_FIFO_SIZE));
-
- /* Sends either a short packet or a 0 length packet */
- if (unlikely(is_short))
- ep_write_UDCCSR(ep, UDCCSR0_IPR);
-
- ep_dbg(ep, "in %d bytes%s%s, %d left, req=%p, udccsr0=0x%03x\n",
- count, is_short ? "/S" : "", is_last ? "/L" : "",
- req->req.length - req->req.actual,
- &req->req, udc_ep_readl(ep, UDCCSR));
-
- return is_last;
-}
-
-static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req)
-{
- struct udc_usb_ep *udc_usb_ep;
- struct pxa_ep *ep;
- struct pxa27x_request *req;
- struct pxa_udc *dev;
- int rc = 0;
- int is_first_req;
- unsigned length;
-
- req = container_of(_req, struct pxa27x_request, req);
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
-
- if (unlikely(!_req || !_req->complete || !_req->buf))
- return -EINVAL;
-
- if (unlikely(!_ep))
- return -EINVAL;
-
- dev = udc_usb_ep->dev;
- ep = udc_usb_ep->pxa_ep;
- if (unlikely(!ep))
- return -EINVAL;
-
- dev = ep->dev;
- if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
- ep_dbg(ep, "bogus device state\n");
- return -ESHUTDOWN;
- }
-
- /* iso is always one packet per request, that's the only way
- * we can report per-packet status. that also helps with dma.
- */
- if (unlikely(EPXFERTYPE_is_ISO(ep)
- && req->req.length > ep->fifo_size))
- return -EMSGSIZE;
-
- is_first_req = list_empty(&ep->queue);
- ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
- _req, is_first_req ? "yes" : "no",
- _req->length, _req->buf);
-
- if (!ep->enabled) {
- _req->status = -ESHUTDOWN;
- rc = -ESHUTDOWN;
- goto out_locked;
- }
-
- if (req->in_use) {
- ep_err(ep, "refusing to queue req %p (already queued)\n", req);
- goto out_locked;
- }
-
- length = _req->length;
- _req->status = -EINPROGRESS;
- _req->actual = 0;
-
- ep_add_request(ep, req);
-
- if (is_ep0(ep)) {
- switch (dev->ep0state) {
- case WAIT_ACK_SET_CONF_INTERF:
- if (length == 0) {
- ep_end_in_req(ep, req);
- } else {
- ep_err(ep, "got a request of %d bytes while"
- "in state WAIT_ACK_SET_CONF_INTERF\n",
- length);
- ep_del_request(ep, req);
- rc = -EL2HLT;
- }
- ep0_idle(ep->dev);
- break;
- case IN_DATA_STAGE:
- if (!ep_is_full(ep))
- if (write_ep0_fifo(ep, req))
- ep0_end_in_req(ep, req);
- break;
- case OUT_DATA_STAGE:
- if ((length == 0) || !epout_has_pkt(ep))
- if (read_ep0_fifo(ep, req))
- ep0_end_out_req(ep, req);
- break;
- default:
- ep_err(ep, "odd state %s to send me a request\n",
- EP0_STNAME(ep->dev));
- ep_del_request(ep, req);
- rc = -EL2HLT;
- break;
- }
- } else {
- handle_ep(ep);
- }
-
-out:
- return rc;
-out_locked:
- goto out;
-}
-
-static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
- struct pxa_ep *ep;
- struct udc_usb_ep *udc_usb_ep;
- struct pxa27x_request *req;
- int rc = -EINVAL;
-
- if (!_ep)
- return rc;
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
- ep = udc_usb_ep->pxa_ep;
- if (!ep || is_ep0(ep))
- return rc;
-
- /* make sure it's actually queued on this endpoint */
- list_for_each_entry(req, &ep->queue, queue) {
- if (&req->req == _req) {
- rc = 0;
- break;
- }
- }
-
- if (!rc)
- req_done(ep, req, -ECONNRESET);
- return rc;
-}
-
-static int pxa_ep_set_halt(struct usb_ep *_ep, int value)
-{
- struct pxa_ep *ep;
- struct udc_usb_ep *udc_usb_ep;
- int rc;
-
-
- if (!_ep)
- return -EINVAL;
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
- ep = udc_usb_ep->pxa_ep;
- if (!ep || is_ep0(ep))
- return -EINVAL;
-
- if (value == 0) {
- /*
- * This path (reset toggle+halt) is needed to implement
- * SET_INTERFACE on normal hardware. but it can't be
- * done from software on the PXA UDC, and the hardware
- * forgets to do it as part of SET_INTERFACE automagic.
- */
- ep_dbg(ep, "only host can clear halt\n");
- return -EROFS;
- }
-
- rc = -EAGAIN;
- if (ep->dir_in && (ep_is_full(ep) || !list_empty(&ep->queue)))
- goto out;
-
- /* FST, FEF bits are the same for control and non control endpoints */
- rc = 0;
- ep_write_UDCCSR(ep, UDCCSR_FST | UDCCSR_FEF);
- if (is_ep0(ep))
- set_ep0state(ep->dev, STALL);
-
-out:
- return rc;
-}
-
-static int pxa_ep_fifo_status(struct usb_ep *_ep)
-{
- struct pxa_ep *ep;
- struct udc_usb_ep *udc_usb_ep;
-
- if (!_ep)
- return -ENODEV;
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
- ep = udc_usb_ep->pxa_ep;
- if (!ep || is_ep0(ep))
- return -ENODEV;
-
- if (ep->dir_in)
- return -EOPNOTSUPP;
- if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN || ep_is_empty(ep))
- return 0;
- else
- return ep_count_bytes_remain(ep) + 1;
-}
-
-static void pxa_ep_fifo_flush(struct usb_ep *_ep)
-{
- struct pxa_ep *ep;
- struct udc_usb_ep *udc_usb_ep;
-
- if (!_ep)
- return;
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
- ep = udc_usb_ep->pxa_ep;
- if (!ep || is_ep0(ep))
- return;
-
- if (unlikely(!list_empty(&ep->queue)))
- ep_dbg(ep, "called while queue list not empty\n");
- ep_dbg(ep, "called\n");
-
- /* for OUT, just read and discard the FIFO contents. */
- if (!ep->dir_in) {
- while (!ep_is_empty(ep))
- udc_ep_readl(ep, UDCDR);
- } else {
- /* most IN status is the same, but ISO can't stall */
- ep_write_UDCCSR(ep,
- UDCCSR_PC | UDCCSR_FEF | UDCCSR_TRN
- | (EPXFERTYPE_is_ISO(ep) ? 0 : UDCCSR_SST));
- }
-}
-
-static int pxa_ep_enable(struct usb_ep *_ep,
- const struct usb_endpoint_descriptor *desc)
-{
- struct pxa_ep *ep;
- struct udc_usb_ep *udc_usb_ep;
- struct pxa_udc *udc;
-
- if (!_ep || !desc)
- return -EINVAL;
-
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
- if (udc_usb_ep->pxa_ep) {
- ep = udc_usb_ep->pxa_ep;
- ep_warn(ep, "usb_ep %s already enabled, doing nothing\n",
- _ep->name);
- } else {
- ep = find_pxa_ep(udc_usb_ep->dev, udc_usb_ep);
- }
-
- if (!ep || is_ep0(ep)) {
- dev_err(udc_usb_ep->dev->dev,
- "unable to match pxa_ep for ep %s\n",
- _ep->name);
- return -EINVAL;
- }
-
- if ((desc->bDescriptorType != USB_DT_ENDPOINT)
- || (ep->type != usb_endpoint_type(desc))) {
- ep_err(ep, "type mismatch\n");
- return -EINVAL;
- }
-
- if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) {
- ep_err(ep, "bad maxpacket\n");
- return -ERANGE;
- }
-
- udc_usb_ep->pxa_ep = ep;
- udc = ep->dev;
-
- if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
- ep_err(ep, "bogus device state\n");
- return -ESHUTDOWN;
- }
-
- ep->enabled = 1;
-
- /* flush fifo (mostly for OUT buffers) */
- pxa_ep_fifo_flush(_ep);
-
- ep_dbg(ep, "enabled\n");
- return 0;
-}
-
-static int pxa_ep_disable(struct usb_ep *_ep)
-{
- struct pxa_ep *ep;
- struct udc_usb_ep *udc_usb_ep;
-
- if (!_ep)
- return -EINVAL;
-
- udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
- ep = udc_usb_ep->pxa_ep;
- if (!ep || is_ep0(ep) || !list_empty(&ep->queue))
- return -EINVAL;
-
- ep->enabled = 0;
- nuke(ep, -ESHUTDOWN);
-
- pxa_ep_fifo_flush(_ep);
- udc_usb_ep->pxa_ep = NULL;
-
- ep_dbg(ep, "disabled\n");
- return 0;
-}
-
-static struct usb_ep_ops pxa_ep_ops = {
- .enable = pxa_ep_enable,
- .disable = pxa_ep_disable,
-
- .alloc_request = pxa_ep_alloc_request,
- .free_request = pxa_ep_free_request,
-
- .queue = pxa_ep_queue,
- .dequeue = pxa_ep_dequeue,
-
- .set_halt = pxa_ep_set_halt,
- .fifo_status = pxa_ep_fifo_status,
- .fifo_flush = pxa_ep_fifo_flush,
-};
-
-static void dplus_pullup(struct pxa_udc *udc, int on)
-{
- if (on) {
- if (udc->mach->gpio_pullup > 0)
- gpio_set_value(udc->mach->gpio_pullup,
- !udc->mach->gpio_pullup_inverted);
- if (udc->mach->udc_command)
- udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
- } else {
- if (udc->mach->gpio_pullup > 0)
- gpio_set_value(udc->mach->gpio_pullup,
- udc->mach->gpio_pullup_inverted);
- if (udc->mach->udc_command)
- udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
- }
- udc->pullup_on = on;
-}
-
-/**
- * pxa_udc_get_frame - Returns usb frame number
- * @_gadget: usb gadget
- */
-static int pxa_udc_get_frame(struct usb_gadget *_gadget)
-{
- struct pxa_udc *udc = to_gadget_udc(_gadget);
-
- return udc_readl(udc, UDCFNR) & 0x7ff;
-}
-
-static int pxa_udc_wakeup(struct usb_gadget *_gadget)
-{
- struct pxa_udc *udc = to_gadget_udc(_gadget);
-
- /* host may not have enabled remote wakeup */
- if ((udc_readl(udc, UDCCR) & UDCCR_DWRE) == 0)
- return -EHOSTUNREACH;
- udc_set_mask_UDCCR(udc, UDCCR_UDR);
- return 0;
-}
-
-static void udc_enable(struct pxa_udc *udc);
-static void udc_disable(struct pxa_udc *udc);
-
-static int should_enable_udc(struct pxa_udc *udc)
-{
- int put_on;
-
- put_on = ((udc->pullup_on) && (udc->driver));
- put_on &= udc->vbus_sensed;
- return put_on;
-}
-
-static int should_disable_udc(struct pxa_udc *udc)
-{
- int put_off;
-
- put_off = ((!udc->pullup_on) || (!udc->driver));
- put_off |= !udc->vbus_sensed;
- return put_off;
-}
-
-static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
-{
- struct pxa_udc *udc = to_gadget_udc(_gadget);
-
- if ((udc->mach->gpio_pullup < 0) && !udc->mach->udc_command)
- return -EOPNOTSUPP;
-
- dplus_pullup(udc, is_active);
-
- if (should_enable_udc(udc))
- udc_enable(udc);
- if (should_disable_udc(udc))
- udc_disable(udc);
- return 0;
-}
-
-static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
-{
- struct pxa_udc *udc = to_gadget_udc(_gadget);
-
- udc->vbus_sensed = is_active;
- if (should_enable_udc(udc))
- udc_enable(udc);
- if (should_disable_udc(udc))
- udc_disable(udc);
-
- return 0;
-}
-
-static int pxa_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver);
-static int pxa_udc_stop(struct usb_gadget *gadget);
-static void pxa_udc_gadget_poll(struct usb_gadget *gadget);
-
-static const struct usb_gadget_ops pxa_udc_ops = {
- .get_frame = pxa_udc_get_frame,
- .wakeup = pxa_udc_wakeup,
- .pullup = pxa_udc_pullup,
- .vbus_session = pxa_udc_vbus_session,
- .udc_start = pxa_udc_start,
- .udc_stop = pxa_udc_stop,
- .udc_poll = pxa_udc_gadget_poll,
-};
-
-static void usb_clk_enable(void)
-{
- CKEN |= CKEN_USB;
-}
-
-static void usb_clk_disable(void)
-{
- CKEN &= ~CKEN_USB;
-}
-
-static void udc_disable(struct pxa_udc *udc)
-{
- if (!udc->enabled)
- return;
-
- udc_writel(udc, UDCICR0, 0);
- udc_writel(udc, UDCICR1, 0);
-
- udc_clear_mask_UDCCR(udc, UDCCR_UDE);
- usb_clk_disable();
-
- ep0_idle(udc);
- udc->gadget.speed = USB_SPEED_UNKNOWN;
-
- udc->enabled = 0;
-}
-
-static __init void udc_init_data(struct pxa_udc *dev)
-{
- int i;
- struct pxa_ep *ep;
-
- /* device/ep0 records init */
- INIT_LIST_HEAD(&dev->gadget.ep_list);
- INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
- dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
- ep0_idle(dev);
-
- /* PXA endpoints init */
- for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
- ep = &dev->pxa_ep[i];
-
- ep->enabled = is_ep0(ep);
- INIT_LIST_HEAD(&ep->queue);
- }
-
- /* USB endpoints init */
- for (i = 1; i < NR_USB_ENDPOINTS; i++) {
- list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
- &dev->gadget.ep_list);
- usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep,
- dev->udc_usb_ep[i].usb_ep.maxpacket);
- }
-}
-
-static void udc_enable(struct pxa_udc *udc)
-{
- if (udc->enabled)
- return;
-
- udc_writel(udc, UDCICR0, 0);
- udc_writel(udc, UDCICR1, 0);
- udc_clear_mask_UDCCR(udc, UDCCR_UDE);
-
- usb_clk_enable();
-
- ep0_idle(udc);
- udc->gadget.speed = USB_SPEED_FULL;
- memset(&udc->stats, 0, sizeof(udc->stats));
-
- udc_set_mask_UDCCR(udc, UDCCR_UDE);
- ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_ACM);
- udelay(2);
- if (udc_readl(udc, UDCCR) & UDCCR_EMCE)
- dev_err(udc->dev, "Configuration errors, udc disabled\n");
-
- /*
- * Caller must be able to sleep in order to cope with startup transients
- */
- mdelay(100);
-
- /* enable suspend/resume and reset irqs */
- udc_writel(udc, UDCICR1,
- UDCICR1_IECC | UDCICR1_IERU
- | UDCICR1_IESU | UDCICR1_IERS);
-
- pio_irq_enable(&udc->pxa_ep[0]);
- udc->enabled = 1;
-}
-
-static int pxa_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver)
-{
- struct pxa_udc *udc = the_controller;
-
- /* first hook up the driver ... */
- udc->driver = driver;
-
- dev_dbg(udc->dev, "registered gadget function '%s'\n",
- driver->function);
-
- if (should_enable_udc(udc))
- udc_enable(udc);
- return 0;
-}
-
-static void stop_activity(struct pxa_udc *udc)
-{
- int i;
-
- udc->gadget.speed = USB_SPEED_UNKNOWN;
-
- for (i = 0; i < NR_USB_ENDPOINTS; i++)
- pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
-}
-
-static int pxa_udc_stop(struct usb_gadget *gadget)
-{
- struct pxa_udc *udc = the_controller;
-
- if (!udc)
- return -ENODEV;
-
- stop_activity(udc);
- udc_disable(udc);
-
- udc->driver = NULL;
-
- /*
- dev_info(udc->dev, "unregistered gadget driver '%s'\n",
- driver->driver.name);
- */
- return 0;
-}
-
-static void handle_ep0_ctrl_req(struct pxa_udc *udc,
- struct pxa27x_request *req)
-{
- struct pxa_ep *ep = &udc->pxa_ep[0];
- union {
- struct usb_ctrlrequest r;
- u32 word[2];
- } u;
- int i;
- int have_extrabytes = 0;
-
- nuke(ep, -EPROTO);
-
- /*
- * In the PXA320 manual, in the section about Back-to-Back setup
- * packets, it describes this situation. The solution is to set OPC to
- * get rid of the status packet, and then continue with the setup
- * packet. Generalize to pxa27x CPUs.
- */
- if (epout_has_pkt(ep) && (ep_count_bytes_remain(ep) == 0))
- ep_write_UDCCSR(ep, UDCCSR0_OPC);
-
- /* read SETUP packet */
- for (i = 0; i < 2; i++) {
- if (unlikely(ep_is_empty(ep)))
- goto stall;
- u.word[i] = udc_ep_readl(ep, UDCDR);
- }
-
- have_extrabytes = !ep_is_empty(ep);
- while (!ep_is_empty(ep)) {
- i = udc_ep_readl(ep, UDCDR);
- ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
- }
-
- ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n",
- u.r.bRequestType, u.r.bRequest,
- le16_to_cpu(u.r.wValue), le16_to_cpu(u.r.wIndex),
- le16_to_cpu(u.r.wLength));
- if (unlikely(have_extrabytes))
- goto stall;
-
- if (u.r.bRequestType & USB_DIR_IN)
- set_ep0state(udc, IN_DATA_STAGE);
- else
- set_ep0state(udc, OUT_DATA_STAGE);
-
- /* Tell UDC to enter Data Stage */
- ep_write_UDCCSR(ep, UDCCSR0_SA | UDCCSR0_OPC);
-
- i = udc->driver->setup(&udc->gadget, &u.r);
- if (i < 0)
- goto stall;
-out:
- return;
-stall:
- ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n",
- udc_ep_readl(ep, UDCCSR), i);
- ep_write_UDCCSR(ep, UDCCSR0_FST | UDCCSR0_FTF);
- set_ep0state(udc, STALL);
- goto out;
-}
-
-static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
-{
- u32 udccsr0;
- struct pxa_ep *ep = &udc->pxa_ep[0];
- struct pxa27x_request *req = NULL;
- int completed = 0;
-
- if (!list_empty(&ep->queue))
- req = list_entry(ep->queue.next, struct pxa27x_request, queue);
-
- udccsr0 = udc_ep_readl(ep, UDCCSR);
- ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
- EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
- (fifo_irq << 1 | opc_irq));
-
- if (udccsr0 & UDCCSR0_SST) {
- ep_dbg(ep, "clearing stall status\n");
- nuke(ep, -EPIPE);
- ep_write_UDCCSR(ep, UDCCSR0_SST);
- ep0_idle(udc);
- }
-
- if (udccsr0 & UDCCSR0_SA) {
- nuke(ep, 0);
- set_ep0state(udc, SETUP_STAGE);
- }
-
- switch (udc->ep0state) {
- case WAIT_FOR_SETUP:
- /*
- * Hardware bug : beware, we cannot clear OPC, since we would
- * miss a potential OPC irq for a setup packet.
- * So, we only do ... nothing, and hope for a next irq with
- * UDCCSR0_SA set.
- */
- break;
- case SETUP_STAGE:
- udccsr0 &= UDCCSR0_CTRL_REQ_MASK;
- if (likely(udccsr0 == UDCCSR0_CTRL_REQ_MASK))
- handle_ep0_ctrl_req(udc, req);
- break;
- case IN_DATA_STAGE: /* GET_DESCRIPTOR */
- if (epout_has_pkt(ep))
- ep_write_UDCCSR(ep, UDCCSR0_OPC);
- if (req && !ep_is_full(ep))
- completed = write_ep0_fifo(ep, req);
- if (completed)
- ep0_end_in_req(ep, req);
- break;
- case OUT_DATA_STAGE: /* SET_DESCRIPTOR */
- if (epout_has_pkt(ep) && req)
- completed = read_ep0_fifo(ep, req);
- if (completed)
- ep0_end_out_req(ep, req);
- break;
- case STALL:
- ep_write_UDCCSR(ep, UDCCSR0_FST);
- break;
- case IN_STATUS_STAGE:
- /*
- * Hardware bug : beware, we cannot clear OPC, since we would
- * miss a potential PC irq for a setup packet.
- * So, we only put the ep0 into WAIT_FOR_SETUP state.
- */
- if (opc_irq)
- ep0_idle(udc);
- break;
- case OUT_STATUS_STAGE:
- case WAIT_ACK_SET_CONF_INTERF:
- ep_warn(ep, "should never get in %s state here!!!\n",
- EP0_STNAME(ep->dev));
- ep0_idle(udc);
- break;
- }
-}
-
-static void handle_ep(struct pxa_ep *ep)
-{
- struct pxa27x_request *req;
- int completed;
- u32 udccsr;
- int is_in = ep->dir_in;
- int loop = 0;
-
- do {
- completed = 0;
- udccsr = udc_ep_readl(ep, UDCCSR);
-
- if (likely(!list_empty(&ep->queue)))
- req = list_entry(ep->queue.next,
- struct pxa27x_request, queue);
- else
- req = NULL;
-
- ep_dbg(ep, "req:%p, udccsr 0x%03x loop=%d\n",
- req, udccsr, loop++);
-
- if (unlikely(udccsr & (UDCCSR_SST | UDCCSR_TRN)))
- udc_ep_writel(ep, UDCCSR,
- udccsr & (UDCCSR_SST | UDCCSR_TRN));
- if (!req)
- break;
-
- if (unlikely(is_in)) {
- if (likely(!ep_is_full(ep)))
- completed = write_fifo(ep, req);
- } else {
- if (likely(epout_has_pkt(ep)))
- completed = read_fifo(ep, req);
- }
-
- if (completed) {
- if (is_in)
- ep_end_in_req(ep, req);
- else
- ep_end_out_req(ep, req);
- }
- } while (completed);
-
- return;
-}
-
-static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
-{
- struct usb_ctrlrequest req ;
-
- dev_dbg(udc->dev, "config=%d\n", config);
-
- udc->config = config;
- udc->last_interface = 0;
- udc->last_alternate = 0;
-
- req.bRequestType = 0;
- req.bRequest = USB_REQ_SET_CONFIGURATION;
- req.wValue = config;
- req.wIndex = 0;
- req.wLength = 0;
-
- set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
- udc->driver->setup(&udc->gadget, &req);
-}
-
-static void __maybe_unused pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
-{
- struct usb_ctrlrequest req;
-
- dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt);
-
- udc->last_interface = iface;
- udc->last_alternate = alt;
-
- req.bRequestType = USB_RECIP_INTERFACE;
- req.bRequest = USB_REQ_SET_INTERFACE;
- req.wValue = alt;
- req.wIndex = iface;
- req.wLength = 0;
-
- set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
- ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
- udc->driver->setup(&udc->gadget, &req);
-}
-
-static void irq_handle_data(struct pxa_udc *udc)
-{
- int i;
- struct pxa_ep *ep;
- u32 udcisr0 = udc_readl(udc, UDCISR0) & UDCCISR0_EP_MASK;
- u32 udcisr1 = udc_readl(udc, UDCISR1) & UDCCISR1_EP_MASK;
-
- if (udcisr0 & UDCISR_INT_MASK) {
- udc_writel(udc, UDCISR0, UDCISR_INT(0, UDCISR_INT_MASK));
- handle_ep0(udc, !!(udcisr0 & UDCICR_FIFOERR),
- !!(udcisr0 & UDCICR_PKTCOMPL));
- }
-
- udcisr0 >>= 2;
- for (i = 1; udcisr0 != 0 && i < 16; udcisr0 >>= 2, i++) {
- if (!(udcisr0 & UDCISR_INT_MASK))
- continue;
-
- udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK));
-
- WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
- if (i < ARRAY_SIZE(udc->pxa_ep)) {
- ep = &udc->pxa_ep[i];
- if (ep->enabled)
- handle_ep(ep);
- }
- }
-
- for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) {
- udc_writel(udc, UDCISR1, UDCISR_INT(i - 16, UDCISR_INT_MASK));
- if (!(udcisr1 & UDCISR_INT_MASK))
- continue;
-
- WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
- if (i < ARRAY_SIZE(udc->pxa_ep)) {
- ep = &udc->pxa_ep[i];
- if (ep->enabled)
- handle_ep(ep);
- }
- }
-
-}
-
-static void irq_udc_suspend(struct pxa_udc *udc)
-{
- udc_writel(udc, UDCISR1, UDCISR1_IRSU);
-
- if (udc->gadget.speed != USB_SPEED_UNKNOWN
- && udc->driver && udc->driver->suspend)
- udc->driver->suspend(&udc->gadget);
- ep0_idle(udc);
-}
-
-static void irq_udc_resume(struct pxa_udc *udc)
-{
- udc_writel(udc, UDCISR1, UDCISR1_IRRU);
-
- if (udc->gadget.speed != USB_SPEED_UNKNOWN
- && udc->driver && udc->driver->resume)
- udc->driver->resume(&udc->gadget);
-}
-
-static void irq_udc_reconfig(struct pxa_udc *udc)
-{
- unsigned config, interface, alternate, config_change;
- u32 udccr = udc_readl(udc, UDCCR);
-
- udc_writel(udc, UDCISR1, UDCISR1_IRCC);
-
- config = (udccr & UDCCR_ACN) >> UDCCR_ACN_S;
- config_change = (config != udc->config);
- if (config_change)
- update_pxa_ep_matches(udc);
- udc_set_mask_UDCCR(udc, UDCCR_SMAC);
- ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
-
- pxa27x_change_configuration(udc, config);
- interface = (udccr & UDCCR_AIN) >> UDCCR_AIN_S;
- alternate = (udccr & UDCCR_AAISN) >> UDCCR_AAISN_S;
-
- /*
- * barebox specific: do not call change interface, as change_config has
- * already setup the gadget.
- * pxa27x_change_interface(udc, interface, alternate);
- */
-}
-
-static void irq_udc_reset(struct pxa_udc *udc)
-{
- u32 udccr = udc_readl(udc, UDCCR);
- struct pxa_ep *ep = &udc->pxa_ep[0];
-
- dev_info(udc->dev, "USB reset\n");
- udc_writel(udc, UDCISR1, UDCISR1_IRRS);
-
- if ((udccr & UDCCR_UDA) == 0) {
- dev_dbg(udc->dev, "USB reset start\n");
- stop_activity(udc);
- }
- udc->gadget.speed = USB_SPEED_FULL;
-
- nuke(ep, -EPROTO);
- ep_write_UDCCSR(ep, UDCCSR0_FTF | UDCCSR0_OPC);
- ep0_idle(udc);
-}
-
-static void pxa_udc_gadget_poll(struct usb_gadget *gadget)
-{
- struct pxa_udc *udc = to_gadget_udc(gadget);
- u32 udcisr0 = udc_readl(udc, UDCISR0);
- u32 udcisr1 = udc_readl(udc, UDCISR1);
- u32 udccr = udc_readl(udc, UDCCR);
- u32 udcisr1_spec;
-
- udc->vbus_sensed = udc->mach->udc_is_connected();
- if (should_enable_udc(udc))
- udc_enable(udc);
- if (should_disable_udc(udc)) {
- stop_activity(udc);
- udc_disable(udc);
- }
-
- if (!udc->enabled)
- return;
-
- dev_dbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, "
- "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr);
-
- udcisr1_spec = udcisr1 & 0xf8000000;
- if (unlikely(udcisr1_spec & UDCISR1_IRSU))
- irq_udc_suspend(udc);
- if (unlikely(udcisr1_spec & UDCISR1_IRRU))
- irq_udc_resume(udc);
- if (unlikely(udcisr1_spec & UDCISR1_IRCC))
- irq_udc_reconfig(udc);
- if (unlikely(udcisr1_spec & UDCISR1_IRRS))
- irq_udc_reset(udc);
-
- if ((udcisr0 & UDCCISR0_EP_MASK) | (udcisr1 & UDCCISR1_EP_MASK))
- irq_handle_data(udc);
-}
-
-static struct pxa_udc memory = {
- .gadget = {
- .ops = &pxa_udc_ops,
- .ep0 = &memory.udc_usb_ep[0].usb_ep,
- .name = driver_name,
- },
-
- .udc_usb_ep = {
- USB_EP_CTRL,
- USB_EP_OUT_BULK(1),
- USB_EP_IN_BULK(2),
- USB_EP_IN_ISO(3),
- USB_EP_OUT_ISO(4),
- USB_EP_IN_INT(5),
- },
-
- .pxa_ep = {
- PXA_EP_CTRL,
- /* Endpoints for gadget zero */
- PXA_EP_OUT_BULK(1, 1, 3, 0, 0),
- PXA_EP_IN_BULK(2, 2, 3, 0, 0),
- /* Endpoints for ether gadget, file storage gadget */
- PXA_EP_OUT_BULK(3, 1, 1, 0, 0),
- PXA_EP_IN_BULK(4, 2, 1, 0, 0),
- PXA_EP_IN_ISO(5, 3, 1, 0, 0),
- PXA_EP_OUT_ISO(6, 4, 1, 0, 0),
- PXA_EP_IN_INT(7, 5, 1, 0, 0),
- /* Endpoints for RNDIS, serial */
- PXA_EP_OUT_BULK(8, 1, 2, 0, 0),
- PXA_EP_IN_BULK(9, 2, 2, 0, 0),
- PXA_EP_IN_INT(10, 5, 2, 0, 0),
- /*
- * All the following endpoints are only for completion. They
- * won't never work, as multiple interfaces are really broken on
- * the pxa.
- */
- PXA_EP_OUT_BULK(11, 1, 2, 1, 0),
- PXA_EP_IN_BULK(12, 2, 2, 1, 0),
- /* Endpoint for CDC Ether */
- PXA_EP_OUT_BULK(13, 1, 1, 1, 1),
- PXA_EP_IN_BULK(14, 2, 1, 1, 1),
- }
-};
-
-static int __init pxa_udc_probe(struct device *dev)
-{
- struct resource *iores;
- struct pxa_udc *udc = &memory;
- int gpio, ret;
-
- iores = dev_request_mem_resource(dev, 0);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
- udc->regs = IOMEM(iores->start);
-
- udc->dev = dev;
- udc->mach = dev->platform_data;
-
- gpio = udc->mach->gpio_pullup;
- if (gpio >= 0) {
- gpio_direction_output(gpio,
- udc->mach->gpio_pullup_inverted);
- }
-
- udc->vbus_sensed = 0;
-
- the_controller = udc;
- udc_init_data(udc);
- pxa_eps_setup(udc);
-
- ret = usb_add_gadget_udc_release(dev, &udc->gadget, NULL);
- if (ret)
- return ret;
-
- return 0;
-}
-
-#define pxa27x_clear_otgph() do {} while (0)
-
-static struct driver udc_driver = {
- .name = "pxa27x-udc",
- .probe = pxa_udc_probe,
-};
-device_platform_driver(udc_driver);
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h
deleted file mode 100644
index 80a93cdcf9..0000000000
--- a/drivers/usb/gadget/udc/pxa27x_udc.h
+++ /dev/null
@@ -1,380 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/usb/gadget/pxa27x_udc.h
- * Intel PXA27x on-chip full speed USB device controller
- *
- * Inspired by original driver by Frank Becker, David Brownell, and others.
- * Copyright (C) 2008 Robert Jarzmik
- *
- * Taken from linux-2.6 kernel and adapted to barebox.
- */
-
-#ifndef __LINUX_USB_GADGET_PXA27X_H
-#define __LINUX_USB_GADGET_PXA27X_H
-
-/*
- * Register definitions
- */
-/* Offsets */
-#define UDCCR 0x0000 /* UDC Control Register */
-#define UDCICR0 0x0004 /* UDC Interrupt Control Register0 */
-#define UDCICR1 0x0008 /* UDC Interrupt Control Register1 */
-#define UDCISR0 0x000C /* UDC Interrupt Status Register 0 */
-#define UDCISR1 0x0010 /* UDC Interrupt Status Register 1 */
-#define UDCFNR 0x0014 /* UDC Frame Number Register */
-#define UDCOTGICR 0x0018 /* UDC On-The-Go interrupt control */
-#define UP2OCR 0x0020 /* USB Port 2 Output Control register */
-#define UP3OCR 0x0024 /* USB Port 3 Output Control register */
-#define UDCCSRn(x) (0x0100 + ((x)<<2)) /* UDC Control/Status register */
-#define UDCBCRn(x) (0x0200 + ((x)<<2)) /* UDC Byte Count Register */
-#define UDCDRn(x) (0x0300 + ((x)<<2)) /* UDC Data Register */
-#define UDCCRn(x) (0x0400 + ((x)<<2)) /* UDC Control Register */
-
-#define UDCCR_OEN (1 << 31) /* On-the-Go Enable */
-#define UDCCR_AALTHNP (1 << 30) /* A-device Alternate Host Negotiation
- Protocol Port Support */
-#define UDCCR_AHNP (1 << 29) /* A-device Host Negotiation Protocol
- Support */
-#define UDCCR_BHNP (1 << 28) /* B-device Host Negotiation Protocol
- Enable */
-#define UDCCR_DWRE (1 << 16) /* Device Remote Wake-up Enable */
-#define UDCCR_ACN (0x03 << 11) /* Active UDC configuration Number */
-#define UDCCR_ACN_S 11
-#define UDCCR_AIN (0x07 << 8) /* Active UDC interface Number */
-#define UDCCR_AIN_S 8
-#define UDCCR_AAISN (0x07 << 5) /* Active UDC Alternate Interface
- Setting Number */
-#define UDCCR_AAISN_S 5
-#define UDCCR_SMAC (1 << 4) /* Switch Endpoint Memory to Active
- Configuration */
-#define UDCCR_EMCE (1 << 3) /* Endpoint Memory Configuration
- Error */
-#define UDCCR_UDR (1 << 2) /* UDC Resume */
-#define UDCCR_UDA (1 << 1) /* UDC Active */
-#define UDCCR_UDE (1 << 0) /* UDC Enable */
-
-#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
-#define UDCICR1_IECC (1 << 31) /* IntEn - Configuration Change */
-#define UDCICR1_IESOF (1 << 30) /* IntEn - Start of Frame */
-#define UDCICR1_IERU (1 << 29) /* IntEn - Resume */
-#define UDCICR1_IESU (1 << 28) /* IntEn - Suspend */
-#define UDCICR1_IERS (1 << 27) /* IntEn - Reset */
-#define UDCICR_FIFOERR (1 << 1) /* FIFO Error interrupt for EP */
-#define UDCICR_PKTCOMPL (1 << 0) /* Packet Complete interrupt for EP */
-#define UDCICR_INT_MASK (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
-
-#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
-#define UDCISR1_IRCC (1 << 31) /* IntReq - Configuration Change */
-#define UDCISR1_IRSOF (1 << 30) /* IntReq - Start of Frame */
-#define UDCISR1_IRRU (1 << 29) /* IntReq - Resume */
-#define UDCISR1_IRSU (1 << 28) /* IntReq - Suspend */
-#define UDCISR1_IRRS (1 << 27) /* IntReq - Reset */
-#define UDCISR_INT_MASK (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
-
-#define UDCOTGICR_IESF (1 << 24) /* OTG SET_FEATURE command recvd */
-#define UDCOTGICR_IEXR (1 << 17) /* Extra Transceiver Interrupt
- Rising Edge Interrupt Enable */
-#define UDCOTGICR_IEXF (1 << 16) /* Extra Transceiver Interrupt
- Falling Edge Interrupt Enable */
-#define UDCOTGICR_IEVV40R (1 << 9) /* OTG Vbus Valid 4.0V Rising Edge
- Interrupt Enable */
-#define UDCOTGICR_IEVV40F (1 << 8) /* OTG Vbus Valid 4.0V Falling Edge
- Interrupt Enable */
-#define UDCOTGICR_IEVV44R (1 << 7) /* OTG Vbus Valid 4.4V Rising Edge
- Interrupt Enable */
-#define UDCOTGICR_IEVV44F (1 << 6) /* OTG Vbus Valid 4.4V Falling Edge
- Interrupt Enable */
-#define UDCOTGICR_IESVR (1 << 5) /* OTG Session Valid Rising Edge
- Interrupt Enable */
-#define UDCOTGICR_IESVF (1 << 4) /* OTG Session Valid Falling Edge
- Interrupt Enable */
-#define UDCOTGICR_IESDR (1 << 3) /* OTG A-Device SRP Detect Rising
- Edge Interrupt Enable */
-#define UDCOTGICR_IESDF (1 << 2) /* OTG A-Device SRP Detect Falling
- Edge Interrupt Enable */
-#define UDCOTGICR_IEIDR (1 << 1) /* OTG ID Change Rising Edge
- Interrupt Enable */
-#define UDCOTGICR_IEIDF (1 << 0) /* OTG ID Change Falling Edge
- Interrupt Enable */
-
-/* Host Port 2 field bits */
-#define UP2OCR_CPVEN (1 << 0) /* Charge Pump Vbus Enable */
-#define UP2OCR_CPVPE (1 << 1) /* Charge Pump Vbus Pulse Enable */
- /* Transceiver enablers */
-#define UP2OCR_DPPDE (1 << 2) /* D+ Pull Down Enable */
-#define UP2OCR_DMPDE (1 << 3) /* D- Pull Down Enable */
-#define UP2OCR_DPPUE (1 << 4) /* D+ Pull Up Enable */
-#define UP2OCR_DMPUE (1 << 5) /* D- Pull Up Enable */
-#define UP2OCR_DPPUBE (1 << 6) /* D+ Pull Up Bypass Enable */
-#define UP2OCR_DMPUBE (1 << 7) /* D- Pull Up Bypass Enable */
-#define UP2OCR_EXSP (1 << 8) /* External Transceiver Speed Control */
-#define UP2OCR_EXSUS (1 << 9) /* External Transceiver Speed Enable */
-#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */
-#define UP2OCR_HXS (1 << 16) /* Transceiver Output Select */
-#define UP2OCR_HXOE (1 << 17) /* Transceiver Output Enable */
-#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */
-
-#define UDCCSR0_ACM (1 << 9) /* Ack Control Mode */
-#define UDCCSR0_AREN (1 << 8) /* Ack Response Enable */
-#define UDCCSR0_SA (1 << 7) /* Setup Active */
-#define UDCCSR0_RNE (1 << 6) /* Receive FIFO Not Empty */
-#define UDCCSR0_FST (1 << 5) /* Force Stall */
-#define UDCCSR0_SST (1 << 4) /* Sent Stall */
-#define UDCCSR0_DME (1 << 3) /* DMA Enable */
-#define UDCCSR0_FTF (1 << 2) /* Flush Transmit FIFO */
-#define UDCCSR0_IPR (1 << 1) /* IN Packet Ready */
-#define UDCCSR0_OPC (1 << 0) /* OUT Packet Complete */
-
-#define UDCCSR_DPE (1 << 9) /* Data Packet Error */
-#define UDCCSR_FEF (1 << 8) /* Flush Endpoint FIFO */
-#define UDCCSR_SP (1 << 7) /* Short Packet Control/Status */
-#define UDCCSR_BNE (1 << 6) /* Buffer Not Empty (IN endpoints) */
-#define UDCCSR_BNF (1 << 6) /* Buffer Not Full (OUT endpoints) */
-#define UDCCSR_FST (1 << 5) /* Force STALL */
-#define UDCCSR_SST (1 << 4) /* Sent STALL */
-#define UDCCSR_DME (1 << 3) /* DMA Enable */
-#define UDCCSR_TRN (1 << 2) /* Tx/Rx NAK */
-#define UDCCSR_PC (1 << 1) /* Packet Complete */
-#define UDCCSR_FS (1 << 0) /* FIFO needs service */
-
-#define UDCCONR_CN (0x03 << 25) /* Configuration Number */
-#define UDCCONR_CN_S 25
-#define UDCCONR_IN (0x07 << 22) /* Interface Number */
-#define UDCCONR_IN_S 22
-#define UDCCONR_AISN (0x07 << 19) /* Alternate Interface Number */
-#define UDCCONR_AISN_S 19
-#define UDCCONR_EN (0x0f << 15) /* Endpoint Number */
-#define UDCCONR_EN_S 15
-#define UDCCONR_ET (0x03 << 13) /* Endpoint Type: */
-#define UDCCONR_ET_S 13
-#define UDCCONR_ET_INT (0x03 << 13) /* Interrupt */
-#define UDCCONR_ET_BULK (0x02 << 13) /* Bulk */
-#define UDCCONR_ET_ISO (0x01 << 13) /* Isochronous */
-#define UDCCONR_ET_NU (0x00 << 13) /* Not used */
-#define UDCCONR_ED (1 << 12) /* Endpoint Direction */
-#define UDCCONR_MPS (0x3ff << 2) /* Maximum Packet Size */
-#define UDCCONR_MPS_S 2
-#define UDCCONR_DE (1 << 1) /* Double Buffering Enable */
-#define UDCCONR_EE (1 << 0) /* Endpoint Enable */
-
-#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE)
-#define UDCCSR_WR_MASK (UDCCSR_DME | UDCCSR_FST)
-#define UDC_FNR_MASK (0x7ff)
-#define UDC_BCR_MASK (0x3ff)
-
-/*
- * UDCCR = UDC Endpoint Configuration Registers
- * UDCCSR = UDC Control/Status Register for this EP
- * UDCBCR = UDC Byte Count Remaining (contents of OUT fifo)
- * UDCDR = UDC Endpoint Data Register (the fifo)
- */
-#define ofs_UDCCR(ep) (UDCCRn(ep->idx))
-#define ofs_UDCCSR(ep) (UDCCSRn(ep->idx))
-#define ofs_UDCBCR(ep) (UDCBCRn(ep->idx))
-#define ofs_UDCDR(ep) (UDCDRn(ep->idx))
-
-/* Register access macros */
-#define udc_ep_readl(ep, reg) \
- readl((ep)->dev->regs + ofs_##reg(ep))
-#define udc_ep_writel(ep, reg, value) \
- writel((value), ep->dev->regs + ofs_##reg(ep))
-#define udc_ep_readb(ep, reg) \
- readb((ep)->dev->regs + ofs_##reg(ep))
-#define udc_ep_writeb(ep, reg, value) \
- writeb((value), ep->dev->regs + ofs_##reg(ep))
-#define udc_readl(dev, reg) \
- readl((dev)->regs + (reg))
-#define udc_writel(udc, reg, value) \
- writel((value), (udc)->regs + (reg))
-
-#define UDCCSR_MASK (UDCCSR_FST | UDCCSR_DME)
-#define UDCCISR0_EP_MASK (~0)
-#define UDCCISR1_EP_MASK 0xffff
-#define UDCCSR0_CTRL_REQ_MASK (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)
-
-#define EPIDX(ep) (ep->idx)
-#define EPADDR(ep) (ep->addr)
-#define EPXFERTYPE(ep) (ep->type)
-#define EPNAME(ep) (ep->name)
-#define is_ep0(ep) (!ep->idx)
-#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC)
-
-/*
- * Endpoint definition helpers
- */
-#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
-{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
- .desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
- .bmAttributes = type, \
- .wMaxPacketSize = maxpkt, }, \
- .dev = &memory \
-}
-#define USB_EP_BULK(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
-#define USB_EP_ISO(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
-#define USB_EP_INT(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
-#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1)
-#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0)
-#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1)
-#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0)
-#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1)
-#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE)
-
-#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
-{ \
- .dev = &memory, \
- .name = "ep" #_idx, \
- .idx = _idx, .enabled = 0, \
- .dir_in = dir, .addr = _addr, \
- .config = _config, .interface = iface, .alternate = altset, \
- .type = _type, .fifo_size = maxpkt, \
-}
-#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \
- PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \
- config, iface, alt)
-#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \
- PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \
- config, iface, alt)
-#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \
- PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \
- config, iface, alt)
-#define PXA_EP_IN_BULK(i, adr, c, f, a) PXA_EP_BULK(i, adr, 1, c, f, a)
-#define PXA_EP_OUT_BULK(i, adr, c, f, a) PXA_EP_BULK(i, adr, 0, c, f, a)
-#define PXA_EP_IN_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 1, c, f, a)
-#define PXA_EP_OUT_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 0, c, f, a)
-#define PXA_EP_IN_INT(i, adr, c, f, a) PXA_EP_INT(i, adr, 1, c, f, a)
-#define PXA_EP_CTRL PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0)
-
-struct pxa27x_udc;
-
-struct stats {
- unsigned long in_ops;
- unsigned long out_ops;
- unsigned long in_bytes;
- unsigned long out_bytes;
- unsigned long irqs;
-};
-
-/**
- * struct udc_usb_ep - container of each usb_ep structure
- * @usb_ep: usb endpoint
- * @desc: usb descriptor, especially type and address
- * @dev: udc managing this endpoint
- * @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call)
- */
-struct udc_usb_ep {
- struct usb_ep usb_ep;
- struct usb_endpoint_descriptor desc;
- struct pxa_udc *dev;
- struct pxa_ep *pxa_ep;
-};
-
-struct pxa_ep {
- struct pxa_udc *dev;
-
- struct list_head queue;
- unsigned enabled:1;
-
- unsigned idx:5;
- char *name;
-
- /*
- * Specific pxa endpoint data, needed for hardware initialization
- */
- unsigned dir_in:1;
- unsigned addr:4;
- unsigned config:2;
- unsigned interface:3;
- unsigned alternate:3;
- unsigned fifo_size;
- unsigned type;
-};
-
-struct pxa27x_request {
- struct usb_request req;
- struct udc_usb_ep *udc_usb_ep;
- unsigned in_use:1;
- struct list_head queue;
-};
-
-enum ep0_state {
- WAIT_FOR_SETUP,
- SETUP_STAGE,
- IN_DATA_STAGE,
- OUT_DATA_STAGE,
- IN_STATUS_STAGE,
- OUT_STATUS_STAGE,
- STALL,
- WAIT_ACK_SET_CONF_INTERF
-};
-
-static char *ep0_state_name[] = {
- "WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE",
- "IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL",
- "WAIT_ACK_SET_CONF_INTERF"
-};
-#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state]
-
-#define EP0_FIFO_SIZE 16U
-#define BULK_FIFO_SIZE 64U
-#define ISO_FIFO_SIZE 256U
-#define INT_FIFO_SIZE 16U
-
-struct udc_stats {
- unsigned long irqs_reset;
- unsigned long irqs_suspend;
- unsigned long irqs_resume;
- unsigned long irqs_reconfig;
-};
-
-#define NR_USB_ENDPOINTS (1 + 5) /* ep0 + ep1in-bulk + .. + ep3in-iso */
-#define NR_PXA_ENDPOINTS (1 + 14) /* ep0 + epA + epB + .. + epX */
-
-struct pxa_udc {
- void __iomem *regs;
- int irq;
- struct clk *clk;
- struct device *dev;
-
- struct usb_gadget gadget;
- struct usb_gadget_driver *driver;
- struct pxa2xx_udc_mach_info *mach;
-
- enum ep0_state ep0state;
- struct udc_stats stats;
-
- struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS];
- struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS];
-
- unsigned enabled:1;
- unsigned pullup_on:1;
- unsigned pullup_resume:1;
- unsigned vbus_sensed:1;
- unsigned config:2;
- unsigned last_interface:3;
- unsigned last_alternate:3;
-
-};
-
-static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
-{
- return container_of(gadget, struct pxa_udc, gadget);
-}
-
-/*
- * Debugging/message support
- */
-#define ep_dbg(ep, fmt, arg...) \
- dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_vdbg(ep, fmt, arg...) \
- dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_err(ep, fmt, arg...) \
- dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_info(ep, fmt, arg...) \
- dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
-#define ep_warn(ep, fmt, arg...) \
- dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
-
-#endif /* __LINUX_USB_GADGET_PXA27X_H */
diff --git a/include/mach/pxa/gpio.h b/include/mach/pxa/gpio.h
index 06e6f3e42b..2d169608d8 100644
--- a/include/mach/pxa/gpio.h
+++ b/include/mach/pxa/gpio.h
@@ -97,37 +97,7 @@
#define gpio_to_bank(gpio) ((gpio) >> 5)
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static inline int __gpio_is_inverted(unsigned gpio)
-{
- return cpu_is_pxa25x() && gpio > 85;
-}
-#else
static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
-#endif
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static inline int __gpio_is_occupied(unsigned gpio)
-{
- if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
- int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
- int dir = GPDR(gpio) & GPIO_bit(gpio);
-
- if (__gpio_is_inverted(gpio))
- return af != 1 || dir == 0;
- else
- return af != 0 || dir != 0;
- } else
- return GPDR(gpio) & GPIO_bit(gpio);
-}
/*
* We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
diff --git a/include/mach/pxa/hardware.h b/include/mach/pxa/hardware.h
index d968a11880..f2ac155166 100644
--- a/include/mach/pxa/hardware.h
+++ b/include/mach/pxa/hardware.h
@@ -10,24 +10,6 @@
#ifndef __MACH_HARDWARE_H
#define __MACH_HARDWARE_H
-#ifdef CONFIG_ARCH_PXA2XX
-#define cpu_is_pxa2xx() (1)
-#else
-#define cpu_is_pxa2xx() (0)
-#endif
-
-#ifdef CONFIG_ARCH_PXA25X
-#define cpu_is_pxa25x() (1)
-#else
-#define cpu_is_pxa25x() (0)
-#endif
-
-#ifdef CONFIG_ARCH_PXA27X
-#define cpu_is_pxa27x() (1)
-#else
-#define cpu_is_pxa27x() (0)
-#endif
-
#ifdef CONFIG_ARCH_PXA3XX
#define cpu_is_pxa3xx() (1)
# ifdef CONFIG_ARCH_PXA320
diff --git a/include/mach/pxa/mfp-pxa27x.h b/include/mach/pxa/mfp-pxa27x.h
deleted file mode 100644
index 6193a440cb..0000000000
--- a/include/mach/pxa/mfp-pxa27x.h
+++ /dev/null
@@ -1,472 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_ARCH_MFP_PXA27X_H
-#define __ASM_ARCH_MFP_PXA27X_H
-
-/*
- * NOTE: for those special-function bidirectional GPIOs, as described
- * in the "PXA27x Developer's Manual" Section 24.4.2.1, only its input
- * alternative is preserved, the direction is actually selected by the
- * specific controller, and this should work in most cases.
- */
-
-#include <mach/pxa/mfp-pxa2xx.h>
-
-/* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN
- * bit is set, regardless of the GPIO configuration
- */
-#define GPIO3_GPIO MFP_CFG_IN(GPIO3, AF0)
-#define GPIO4_GPIO MFP_CFG_IN(GPIO4, AF0)
-
-/* GPIO */
-#define GPIO85_GPIO MFP_CFG_IN(GPIO85, AF0)
-#define GPIO86_GPIO MFP_CFG_IN(GPIO86, AF0)
-#define GPIO87_GPIO MFP_CFG_IN(GPIO87, AF0)
-#define GPIO88_GPIO MFP_CFG_IN(GPIO88, AF0)
-#define GPIO89_GPIO MFP_CFG_IN(GPIO89, AF0)
-#define GPIO90_GPIO MFP_CFG_IN(GPIO90, AF0)
-#define GPIO91_GPIO MFP_CFG_IN(GPIO91, AF0)
-#define GPIO92_GPIO MFP_CFG_IN(GPIO92, AF0)
-#define GPIO93_GPIO MFP_CFG_IN(GPIO93, AF0)
-#define GPIO94_GPIO MFP_CFG_IN(GPIO94, AF0)
-#define GPIO95_GPIO MFP_CFG_IN(GPIO95, AF0)
-#define GPIO96_GPIO MFP_CFG_IN(GPIO96, AF0)
-#define GPIO97_GPIO MFP_CFG_IN(GPIO97, AF0)
-#define GPIO98_GPIO MFP_CFG_IN(GPIO98, AF0)
-#define GPIO99_GPIO MFP_CFG_IN(GPIO99, AF0)
-#define GPIO100_GPIO MFP_CFG_IN(GPIO100, AF0)
-#define GPIO101_GPIO MFP_CFG_IN(GPIO101, AF0)
-#define GPIO102_GPIO MFP_CFG_IN(GPIO102, AF0)
-#define GPIO103_GPIO MFP_CFG_IN(GPIO103, AF0)
-#define GPIO104_GPIO MFP_CFG_IN(GPIO104, AF0)
-#define GPIO105_GPIO MFP_CFG_IN(GPIO105, AF0)
-#define GPIO106_GPIO MFP_CFG_IN(GPIO106, AF0)
-#define GPIO107_GPIO MFP_CFG_IN(GPIO107, AF0)
-#define GPIO108_GPIO MFP_CFG_IN(GPIO108, AF0)
-#define GPIO109_GPIO MFP_CFG_IN(GPIO109, AF0)
-#define GPIO110_GPIO MFP_CFG_IN(GPIO110, AF0)
-#define GPIO111_GPIO MFP_CFG_IN(GPIO111, AF0)
-#define GPIO112_GPIO MFP_CFG_IN(GPIO112, AF0)
-#define GPIO113_GPIO MFP_CFG_IN(GPIO113, AF0)
-#define GPIO114_GPIO MFP_CFG_IN(GPIO114, AF0)
-#define GPIO115_GPIO MFP_CFG_IN(GPIO115, AF0)
-#define GPIO116_GPIO MFP_CFG_IN(GPIO116, AF0)
-#define GPIO117_GPIO MFP_CFG_IN(GPIO117, AF0)
-#define GPIO118_GPIO MFP_CFG_IN(GPIO118, AF0)
-#define GPIO119_GPIO MFP_CFG_IN(GPIO119, AF0)
-#define GPIO120_GPIO MFP_CFG_IN(GPIO120, AF0)
-
-/* Crystal and Clock Signals */
-#define GPIO9_HZ_CLK MFP_CFG_OUT(GPIO9, AF1, DRIVE_LOW)
-#define GPIO10_HZ_CLK MFP_CFG_OUT(GPIO10, AF1, DRIVE_LOW)
-#define GPIO11_48_MHz MFP_CFG_OUT(GPIO11, AF3, DRIVE_LOW)
-#define GPIO12_48_MHz MFP_CFG_OUT(GPIO12, AF3, DRIVE_LOW)
-#define GPIO13_CLK_EXT MFP_CFG_IN(GPIO13, AF1)
-
-/* OS Timer Signals */
-#define GPIO11_EXT_SYNC_0 MFP_CFG_IN(GPIO11, AF1)
-#define GPIO12_EXT_SYNC_1 MFP_CFG_IN(GPIO12, AF1)
-#define GPIO9_CHOUT_0 MFP_CFG_OUT(GPIO9, AF3, DRIVE_LOW)
-#define GPIO10_CHOUT_1 MFP_CFG_OUT(GPIO10, AF3, DRIVE_LOW)
-#define GPIO11_CHOUT_0 MFP_CFG_OUT(GPIO11, AF1, DRIVE_LOW)
-#define GPIO12_CHOUT_1 MFP_CFG_OUT(GPIO12, AF1, DRIVE_LOW)
-
-/* SDRAM and Static Memory I/O Signals */
-#define GPIO20_nSDCS_2 MFP_CFG_OUT(GPIO20, AF1, DRIVE_HIGH)
-#define GPIO21_nSDCS_3 MFP_CFG_OUT(GPIO21, AF1, DRIVE_HIGH)
-#define GPIO15_nCS_1 MFP_CFG_OUT(GPIO15, AF2, DRIVE_HIGH)
-#define GPIO78_nCS_2 MFP_CFG_OUT(GPIO78, AF2, DRIVE_HIGH)
-#define GPIO79_nCS_3 MFP_CFG_OUT(GPIO79, AF2, DRIVE_HIGH)
-#define GPIO80_nCS_4 MFP_CFG_OUT(GPIO80, AF2, DRIVE_HIGH)
-#define GPIO33_nCS_5 MFP_CFG_OUT(GPIO33, AF2, DRIVE_HIGH)
-
-/* Miscellaneous I/O and DMA Signals */
-#define GPIO21_DVAL_0 MFP_CFG_OUT(GPIO21, AF2, DRIVE_HIGH)
-#define GPIO116_DVAL_0 MFP_CFG_OUT(GPIO116, AF1, DRIVE_HIGH)
-#define GPIO33_DVAL_1 MFP_CFG_OUT(GPIO33, AF1, DRIVE_HIGH)
-#define GPIO96_DVAL_1 MFP_CFG_OUT(GPIO96, AF2, DRIVE_HIGH)
-#define GPIO18_RDY MFP_CFG_IN(GPIO18, AF1)
-#define GPIO20_DREQ_0 MFP_CFG_IN(GPIO20, AF1)
-#define GPIO115_DREQ_0 MFP_CFG_IN(GPIO115, AF1)
-#define GPIO80_DREQ_1 MFP_CFG_IN(GPIO80, AF1)
-#define GPIO97_DREQ_1 MFP_CFG_IN(GPIO97, AF2)
-#define GPIO85_DREQ_2 MFP_CFG_IN(GPIO85, AF2)
-#define GPIO100_DREQ_2 MFP_CFG_IN(GPIO100, AF2)
-
-/* Alternate Bus Master Mode I/O Signals */
-#define GPIO20_MBREQ MFP_CFG_IN(GPIO20, AF2)
-#define GPIO80_MBREQ MFP_CFG_IN(GPIO80, AF2)
-#define GPIO96_MBREQ MFP_CFG_IN(GPIO96, AF2)
-#define GPIO115_MBREQ MFP_CFG_IN(GPIO115, AF3)
-#define GPIO21_MBGNT MFP_CFG_OUT(GPIO21, AF3, DRIVE_LOW)
-#define GPIO33_MBGNT MFP_CFG_OUT(GPIO33, AF3, DRIVE_LOW)
-#define GPIO97_MBGNT MFP_CFG_OUT(GPIO97, AF2, DRIVE_LOW)
-#define GPIO116_MBGNT MFP_CFG_OUT(GPIO116, AF3, DRIVE_LOW)
-
-/* PC CARD */
-#define GPIO15_nPCE_1 MFP_CFG_OUT(GPIO15, AF1, DRIVE_HIGH)
-#define GPIO85_nPCE_1 MFP_CFG_OUT(GPIO85, AF1, DRIVE_HIGH)
-#define GPIO86_nPCE_1 MFP_CFG_OUT(GPIO86, AF1, DRIVE_HIGH)
-#define GPIO102_nPCE_1 MFP_CFG_OUT(GPIO102, AF1, DRIVE_HIGH)
-#define GPIO54_nPCE_2 MFP_CFG_OUT(GPIO54, AF2, DRIVE_HIGH)
-#define GPIO78_nPCE_2 MFP_CFG_OUT(GPIO78, AF1, DRIVE_HIGH)
-#define GPIO87_nPCE_2 MFP_CFG_IN(GPIO87, AF1)
-#define GPIO55_nPREG MFP_CFG_OUT(GPIO55, AF2, DRIVE_HIGH)
-#define GPIO50_nPIOR MFP_CFG_OUT(GPIO50, AF2, DRIVE_HIGH)
-#define GPIO51_nPIOW MFP_CFG_OUT(GPIO51, AF2, DRIVE_HIGH)
-#define GPIO49_nPWE MFP_CFG_OUT(GPIO49, AF2, DRIVE_HIGH)
-#define GPIO48_nPOE MFP_CFG_OUT(GPIO48, AF2, DRIVE_HIGH)
-#define GPIO57_nIOIS16 MFP_CFG_IN(GPIO57, AF1)
-#define GPIO56_nPWAIT MFP_CFG_IN(GPIO56, AF1)
-#define GPIO79_PSKTSEL MFP_CFG_OUT(GPIO79, AF1, DRIVE_HIGH)
-#define GPIO104_PSKTSEL MFP_CFG_OUT(GPIO104, AF1, DRIVE_HIGH)
-
-/* I2C */
-#define GPIO117_I2C_SCL MFP_CFG_IN(GPIO117, AF1)
-#define GPIO118_I2C_SDA MFP_CFG_IN(GPIO118, AF1)
-
-/* FFUART */
-#define GPIO9_FFUART_CTS MFP_CFG_IN(GPIO9, AF3)
-#define GPIO26_FFUART_CTS MFP_CFG_IN(GPIO26, AF3)
-#define GPIO35_FFUART_CTS MFP_CFG_IN(GPIO35, AF1)
-#define GPIO100_FFUART_CTS MFP_CFG_IN(GPIO100, AF3)
-#define GPIO10_FFUART_DCD MFP_CFG_IN(GPIO10, AF1)
-#define GPIO36_FFUART_DCD MFP_CFG_IN(GPIO36, AF1)
-#define GPIO33_FFUART_DSR MFP_CFG_IN(GPIO33, AF2)
-#define GPIO37_FFUART_DSR MFP_CFG_IN(GPIO37, AF1)
-#define GPIO38_FFUART_RI MFP_CFG_IN(GPIO38, AF1)
-#define GPIO89_FFUART_RI MFP_CFG_IN(GPIO89, AF3)
-#define GPIO19_FFUART_RXD MFP_CFG_IN(GPIO19, AF3)
-#define GPIO33_FFUART_RXD MFP_CFG_IN(GPIO33, AF1)
-#define GPIO34_FFUART_RXD MFP_CFG_IN(GPIO34, AF1)
-#define GPIO41_FFUART_RXD MFP_CFG_IN(GPIO41, AF1)
-#define GPIO53_FFUART_RXD MFP_CFG_IN(GPIO53, AF1)
-#define GPIO85_FFUART_RXD MFP_CFG_IN(GPIO85, AF1)
-#define GPIO96_FFUART_RXD MFP_CFG_IN(GPIO96, AF3)
-#define GPIO102_FFUART_RXD MFP_CFG_IN(GPIO102, AF3)
-#define GPIO16_FFUART_TXD MFP_CFG_OUT(GPIO16, AF3, DRIVE_HIGH)
-#define GPIO37_FFUART_TXD MFP_CFG_OUT(GPIO37, AF3, DRIVE_HIGH)
-#define GPIO39_FFUART_TXD MFP_CFG_OUT(GPIO39, AF2, DRIVE_HIGH)
-#define GPIO83_FFUART_TXD MFP_CFG_OUT(GPIO83, AF2, DRIVE_HIGH)
-#define GPIO99_FFUART_TXD MFP_CFG_OUT(GPIO99, AF3, DRIVE_HIGH)
-#define GPIO27_FFUART_RTS MFP_CFG_OUT(GPIO27, AF3, DRIVE_HIGH)
-#define GPIO41_FFUART_RTS MFP_CFG_OUT(GPIO41, AF2, DRIVE_HIGH)
-#define GPIO83_FFUART_RTS MFP_CFG_OUT(GPIO83, AF3, DRIVE_HIGH)
-#define GPIO98_FFUART_RTS MFP_CFG_OUT(GPIO98, AF3, DRIVE_HIGH)
-#define GPIO40_FFUART_DTR MFP_CFG_OUT(GPIO40, AF2, DRIVE_HIGH)
-#define GPIO82_FFUART_DTR MFP_CFG_OUT(GPIO82, AF3, DRIVE_HIGH)
-
-/* BTUART */
-#define GPIO44_BTUART_CTS MFP_CFG_IN(GPIO44, AF1)
-#define GPIO42_BTUART_RXD MFP_CFG_IN(GPIO42, AF1)
-#define GPIO45_BTUART_RTS MFP_CFG_OUT(GPIO45, AF2, DRIVE_HIGH)
-#define GPIO43_BTUART_TXD MFP_CFG_OUT(GPIO43, AF2, DRIVE_HIGH)
-
-/* STUART */
-#define GPIO46_STUART_RXD MFP_CFG_IN(GPIO46, AF2)
-#define GPIO47_STUART_TXD MFP_CFG_OUT(GPIO47, AF1, DRIVE_HIGH)
-
-/* FICP */
-#define GPIO42_FICP_RXD MFP_CFG_IN(GPIO42, AF2)
-#define GPIO46_FICP_RXD MFP_CFG_IN(GPIO46, AF1)
-#define GPIO43_FICP_TXD MFP_CFG_OUT(GPIO43, AF1, DRIVE_HIGH)
-#define GPIO47_FICP_TXD MFP_CFG_OUT(GPIO47, AF2, DRIVE_HIGH)
-
-/* PWM 0/1/2/3 */
-#define GPIO11_PWM2_OUT MFP_CFG_OUT(GPIO11, AF2, DRIVE_LOW)
-#define GPIO12_PWM3_OUT MFP_CFG_OUT(GPIO12, AF2, DRIVE_LOW)
-#define GPIO16_PWM0_OUT MFP_CFG_OUT(GPIO16, AF2, DRIVE_LOW)
-#define GPIO17_PWM1_OUT MFP_CFG_OUT(GPIO17, AF2, DRIVE_LOW)
-#define GPIO38_PWM1_OUT MFP_CFG_OUT(GPIO38, AF3, DRIVE_LOW)
-#define GPIO46_PWM2_OUT MFP_CFG_OUT(GPIO46, AF2, DRIVE_LOW)
-#define GPIO47_PWM3_OUT MFP_CFG_OUT(GPIO47, AF3, DRIVE_LOW)
-#define GPIO79_PWM2_OUT MFP_CFG_OUT(GPIO79, AF3, DRIVE_LOW)
-#define GPIO80_PWM3_OUT MFP_CFG_OUT(GPIO80, AF3, DRIVE_LOW)
-#define GPIO115_PWM1_OUT MFP_CFG_OUT(GPIO115, AF3, DRIVE_LOW)
-
-/* AC97 */
-#define GPIO31_AC97_SYNC MFP_CFG_OUT(GPIO31, AF2, DRIVE_LOW)
-#define GPIO94_AC97_SYNC MFP_CFG_OUT(GPIO94, AF1, DRIVE_LOW)
-#define GPIO30_AC97_SDATA_OUT MFP_CFG_OUT(GPIO30, AF2, DRIVE_LOW)
-#define GPIO93_AC97_SDATA_OUT MFP_CFG_OUT(GPIO93, AF1, DRIVE_LOW)
-#define GPIO45_AC97_SYSCLK MFP_CFG_OUT(GPIO45, AF1, DRIVE_LOW)
-#define GPIO89_AC97_SYSCLK MFP_CFG_OUT(GPIO89, AF1, DRIVE_LOW)
-#define GPIO98_AC97_SYSCLK MFP_CFG_OUT(GPIO98, AF1, DRIVE_LOW)
-#define GPIO95_AC97_nRESET MFP_CFG_OUT(GPIO95, AF1, DRIVE_LOW)
-#define GPIO113_AC97_nRESET MFP_CFG_OUT(GPIO113, AF2, DRIVE_LOW)
-#define GPIO28_AC97_BITCLK MFP_CFG_IN(GPIO28, AF1)
-#define GPIO29_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO29, AF1)
-#define GPIO116_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO116, AF2)
-#define GPIO99_AC97_SDATA_IN_1 MFP_CFG_IN(GPIO99, AF2)
-
-/* I2S */
-#define GPIO28_I2S_BITCLK_IN MFP_CFG_IN(GPIO28, AF2)
-#define GPIO28_I2S_BITCLK_OUT MFP_CFG_OUT(GPIO28, AF1, DRIVE_LOW)
-#define GPIO29_I2S_SDATA_IN MFP_CFG_IN(GPIO29, AF2)
-#define GPIO30_I2S_SDATA_OUT MFP_CFG_OUT(GPIO30, AF1, DRIVE_LOW)
-#define GPIO31_I2S_SYNC MFP_CFG_OUT(GPIO31, AF1, DRIVE_LOW)
-#define GPIO113_I2S_SYSCLK MFP_CFG_OUT(GPIO113, AF1, DRIVE_LOW)
-
-/* SSP 1 */
-#define GPIO23_SSP1_SCLK MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW)
-#define GPIO29_SSP1_SCLK MFP_CFG_IN(GPIO29, AF3)
-#define GPIO27_SSP1_SYSCLK MFP_CFG_OUT(GPIO27, AF1, DRIVE_LOW)
-#define GPIO53_SSP1_SYSCLK MFP_CFG_OUT(GPIO53, AF3, DRIVE_LOW)
-#define GPIO24_SSP1_SFRM MFP_CFG_IN(GPIO24, AF2)
-#define GPIO28_SSP1_SFRM MFP_CFG_IN(GPIO28, AF3)
-#define GPIO25_SSP1_TXD MFP_CFG_OUT(GPIO25, AF2, DRIVE_LOW)
-#define GPIO57_SSP1_TXD MFP_CFG_OUT(GPIO57, AF3, DRIVE_LOW)
-#define GPIO26_SSP1_RXD MFP_CFG_IN(GPIO26, AF1)
-#define GPIO27_SSP1_SCLKEN MFP_CFG_IN(GPIO27, AF2)
-
-/* SSP 2 */
-#define GPIO19_SSP2_SCLK MFP_CFG_IN(GPIO19, AF1)
-#define GPIO22_SSP2_SCLK MFP_CFG_IN(GPIO22, AF3)
-#define GPIO29_SSP2_SCLK MFP_CFG_OUT(GPIO29, AF3, DRIVE_LOW)
-#define GPIO36_SSP2_SCLK MFP_CFG_IN(GPIO36, AF2)
-#define GPIO50_SSP2_SCLK MFP_CFG_IN(GPIO50, AF3)
-#define GPIO22_SSP2_SYSCLK MFP_CFG_OUT(GPIO22, AF2, DRIVE_LOW)
-#define GPIO14_SSP2_SFRM MFP_CFG_IN(GPIO14, AF2)
-#define GPIO37_SSP2_SFRM MFP_CFG_IN(GPIO37, AF2)
-#define GPIO87_SSP2_SFRM MFP_CFG_OUT(GPIO87, AF3, DRIVE_LOW)
-#define GPIO88_SSP2_SFRM MFP_CFG_IN(GPIO88, AF3)
-#define GPIO13_SSP2_TXD MFP_CFG_OUT(GPIO13, AF1, DRIVE_LOW)
-#define GPIO38_SSP2_TXD MFP_CFG_OUT(GPIO38, AF2, DRIVE_LOW)
-#define GPIO87_SSP2_TXD MFP_CFG_OUT(GPIO87, AF1, DRIVE_LOW)
-#define GPIO89_SSP2_TXD MFP_CFG_OUT(GPIO89, AF3, DRIVE_LOW)
-#define GPIO11_SSP2_RXD MFP_CFG_IN(GPIO11, AF2)
-#define GPIO29_SSP2_RXD MFP_CFG_OUT(GPIO29, AF1, DRIVE_LOW)
-#define GPIO40_SSP2_RXD MFP_CFG_IN(GPIO40, AF1)
-#define GPIO86_SSP2_RXD MFP_CFG_IN(GPIO86, AF1)
-#define GPIO88_SSP2_RXD MFP_CFG_IN(GPIO88, AF2)
-#define GPIO22_SSP2_EXTCLK MFP_CFG_IN(GPIO22, AF1)
-#define GPIO27_SSP2_EXTCLK MFP_CFG_IN(GPIO27, AF1)
-#define GPIO22_SSP2_SCLKEN MFP_CFG_IN(GPIO22, AF2)
-#define GPIO23_SSP2_SCLKEN MFP_CFG_IN(GPIO23, AF2)
-
-/* SSP 3 */
-#define GPIO34_SSP3_SCLK MFP_CFG_IN(GPIO34, AF3)
-#define GPIO40_SSP3_SCLK MFP_CFG_OUT(GPIO40, AF3, DRIVE_LOW)
-#define GPIO52_SSP3_SCLK MFP_CFG_IN(GPIO52, AF2)
-#define GPIO84_SSP3_SCLK MFP_CFG_IN(GPIO84, AF1)
-#define GPIO45_SSP3_SYSCLK MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
-#define GPIO35_SSP3_SFRM MFP_CFG_IN(GPIO35, AF3)
-#define GPIO39_SSP3_SFRM MFP_CFG_IN(GPIO39, AF3)
-#define GPIO83_SSP3_SFRM MFP_CFG_IN(GPIO83, AF1)
-#define GPIO35_SSP3_TXD MFP_CFG_OUT(GPIO35, AF3, DRIVE_LOW)
-#define GPIO38_SSP3_TXD MFP_CFG_OUT(GPIO38, AF1, DRIVE_LOW)
-#define GPIO81_SSP3_TXD MFP_CFG_OUT(GPIO81, AF1, DRIVE_LOW)
-#define GPIO41_SSP3_RXD MFP_CFG_IN(GPIO41, AF3)
-#define GPIO82_SSP3_RXD MFP_CFG_IN(GPIO82, AF1)
-#define GPIO89_SSP3_RXD MFP_CFG_IN(GPIO89, AF1)
-
-/* MMC */
-#define GPIO32_MMC_CLK MFP_CFG_OUT(GPIO32, AF2, DRIVE_LOW)
-#define GPIO92_MMC_DAT_0 MFP_CFG_IN(GPIO92, AF1)
-#define GPIO109_MMC_DAT_1 MFP_CFG_IN(GPIO109, AF1)
-#define GPIO110_MMC_DAT_2 MFP_CFG_IN(GPIO110, AF1)
-#define GPIO111_MMC_DAT_3 MFP_CFG_IN(GPIO111, AF1)
-#define GPIO112_MMC_CMD MFP_CFG_IN(GPIO112, AF1)
-
-/* LCD */
-#define GPIO58_LCD_LDD_0 MFP_CFG_OUT(GPIO58, AF2, DRIVE_LOW)
-#define GPIO59_LCD_LDD_1 MFP_CFG_OUT(GPIO59, AF2, DRIVE_LOW)
-#define GPIO60_LCD_LDD_2 MFP_CFG_OUT(GPIO60, AF2, DRIVE_LOW)
-#define GPIO61_LCD_LDD_3 MFP_CFG_OUT(GPIO61, AF2, DRIVE_LOW)
-#define GPIO62_LCD_LDD_4 MFP_CFG_OUT(GPIO62, AF2, DRIVE_LOW)
-#define GPIO63_LCD_LDD_5 MFP_CFG_OUT(GPIO63, AF2, DRIVE_LOW)
-#define GPIO64_LCD_LDD_6 MFP_CFG_OUT(GPIO64, AF2, DRIVE_LOW)
-#define GPIO65_LCD_LDD_7 MFP_CFG_OUT(GPIO65, AF2, DRIVE_LOW)
-#define GPIO66_LCD_LDD_8 MFP_CFG_OUT(GPIO66, AF2, DRIVE_LOW)
-#define GPIO67_LCD_LDD_9 MFP_CFG_OUT(GPIO67, AF2, DRIVE_LOW)
-#define GPIO68_LCD_LDD_10 MFP_CFG_OUT(GPIO68, AF2, DRIVE_LOW)
-#define GPIO69_LCD_LDD_11 MFP_CFG_OUT(GPIO69, AF2, DRIVE_LOW)
-#define GPIO70_LCD_LDD_12 MFP_CFG_OUT(GPIO70, AF2, DRIVE_LOW)
-#define GPIO71_LCD_LDD_13 MFP_CFG_OUT(GPIO71, AF2, DRIVE_LOW)
-#define GPIO72_LCD_LDD_14 MFP_CFG_OUT(GPIO72, AF2, DRIVE_LOW)
-#define GPIO73_LCD_LDD_15 MFP_CFG_OUT(GPIO73, AF2, DRIVE_LOW)
-#define GPIO86_LCD_LDD_16 MFP_CFG_OUT(GPIO86, AF2, DRIVE_LOW)
-#define GPIO87_LCD_LDD_17 MFP_CFG_OUT(GPIO87, AF2, DRIVE_LOW)
-#define GPIO74_LCD_FCLK MFP_CFG_OUT(GPIO74, AF2, DRIVE_LOW)
-#define GPIO75_LCD_LCLK MFP_CFG_OUT(GPIO75, AF2, DRIVE_LOW)
-#define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW)
-#define GPIO77_LCD_BIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW)
-#define GPIO14_LCD_VSYNC MFP_CFG_IN(GPIO14, AF1)
-#define GPIO19_LCD_CS MFP_CFG_OUT(GPIO19, AF2, DRIVE_LOW)
-
-/* Keypad */
-#define GPIO93_KP_DKIN_0 MFP_CFG_IN(GPIO93, AF1)
-#define GPIO94_KP_DKIN_1 MFP_CFG_IN(GPIO94, AF1)
-#define GPIO95_KP_DKIN_2 MFP_CFG_IN(GPIO95, AF1)
-#define GPIO96_KP_DKIN_3 MFP_CFG_IN(GPIO96, AF1)
-#define GPIO97_KP_DKIN_4 MFP_CFG_IN(GPIO97, AF1)
-#define GPIO98_KP_DKIN_5 MFP_CFG_IN(GPIO98, AF1)
-#define GPIO99_KP_DKIN_6 MFP_CFG_IN(GPIO99, AF1)
-#define GPIO13_KP_KDIN_7 MFP_CFG_IN(GPIO13, AF2)
-#define GPIO100_KP_MKIN_0 MFP_CFG_IN(GPIO100, AF1)
-#define GPIO101_KP_MKIN_1 MFP_CFG_IN(GPIO101, AF1)
-#define GPIO102_KP_MKIN_2 MFP_CFG_IN(GPIO102, AF1)
-#define GPIO34_KP_MKIN_3 MFP_CFG_IN(GPIO34, AF2)
-#define GPIO37_KP_MKIN_3 MFP_CFG_IN(GPIO37, AF3)
-#define GPIO97_KP_MKIN_3 MFP_CFG_IN(GPIO97, AF3)
-#define GPIO98_KP_MKIN_4 MFP_CFG_IN(GPIO98, AF3)
-#define GPIO38_KP_MKIN_4 MFP_CFG_IN(GPIO38, AF2)
-#define GPIO39_KP_MKIN_4 MFP_CFG_IN(GPIO39, AF1)
-#define GPIO16_KP_MKIN_5 MFP_CFG_IN(GPIO16, AF1)
-#define GPIO90_KP_MKIN_5 MFP_CFG_IN(GPIO90, AF1)
-#define GPIO99_KP_MKIN_5 MFP_CFG_IN(GPIO99, AF3)
-#define GPIO17_KP_MKIN_6 MFP_CFG_IN(GPIO17, AF1)
-#define GPIO91_KP_MKIN_6 MFP_CFG_IN(GPIO91, AF1)
-#define GPIO95_KP_MKIN_6 MFP_CFG_IN(GPIO95, AF3)
-#define GPIO13_KP_MKIN_7 MFP_CFG_IN(GPIO13, AF3)
-#define GPIO36_KP_MKIN_7 MFP_CFG_IN(GPIO36, AF3)
-#define GPIO103_KP_MKOUT_0 MFP_CFG_OUT(GPIO103, AF2, DRIVE_HIGH)
-#define GPIO104_KP_MKOUT_1 MFP_CFG_OUT(GPIO104, AF2, DRIVE_HIGH)
-#define GPIO105_KP_MKOUT_2 MFP_CFG_OUT(GPIO105, AF2, DRIVE_HIGH)
-#define GPIO106_KP_MKOUT_3 MFP_CFG_OUT(GPIO106, AF2, DRIVE_HIGH)
-#define GPIO107_KP_MKOUT_4 MFP_CFG_OUT(GPIO107, AF2, DRIVE_HIGH)
-#define GPIO108_KP_MKOUT_5 MFP_CFG_OUT(GPIO108, AF2, DRIVE_HIGH)
-#define GPIO35_KP_MKOUT_6 MFP_CFG_OUT(GPIO35, AF2, DRIVE_HIGH)
-#define GPIO22_KP_MKOUT_7 MFP_CFG_OUT(GPIO22, AF1, DRIVE_HIGH)
-#define GPIO40_KP_MKOUT_6 MFP_CFG_OUT(GPIO40, AF1, DRIVE_HIGH)
-#define GPIO41_KP_MKOUT_7 MFP_CFG_OUT(GPIO41, AF1, DRIVE_HIGH)
-#define GPIO96_KP_MKOUT_6 MFP_CFG_OUT(GPIO96, AF3, DRIVE_HIGH)
-
-/* USB P3 */
-#define GPIO10_USB_P3_5 MFP_CFG_IN(GPIO10, AF3)
-#define GPIO11_USB_P3_1 MFP_CFG_IN(GPIO11, AF3)
-#define GPIO30_USB_P3_2 MFP_CFG_OUT(GPIO30, AF3, DRIVE_LOW)
-#define GPIO31_USB_P3_6 MFP_CFG_OUT(GPIO31, AF3, DRIVE_LOW)
-#define GPIO56_USB_P3_4 MFP_CFG_OUT(GPIO56, AF1, DRIVE_LOW)
-#define GPIO86_USB_P3_5 MFP_CFG_IN(GPIO86, AF3)
-#define GPIO87_USB_P3_1 MFP_CFG_IN(GPIO87, AF3)
-#define GPIO90_USB_P3_5 MFP_CFG_IN(GPIO90, AF2)
-#define GPIO91_USB_P3_1 MFP_CFG_IN(GPIO91, AF2)
-#define GPIO113_USB_P3_3 MFP_CFG_IN(GPIO113, AF3)
-
-/* USB P2 */
-#define GPIO34_USB_P2_2 MFP_CFG_OUT(GPIO34, AF1, DRIVE_LOW)
-#define GPIO35_USB_P2_1 MFP_CFG_IN(GPIO35, AF2)
-#define GPIO36_USB_P2_4 MFP_CFG_OUT(GPIO36, AF1, DRIVE_LOW)
-#define GPIO37_USB_P2_8 MFP_CFG_OUT(GPIO37, AF1, DRIVE_LOW)
-#define GPIO38_USB_P2_3 MFP_CFG_IN(GPIO38, AF3)
-#define GPIO39_USB_P2_6 MFP_CFG_OUT(GPIO39, AF1, DRIVE_LOW)
-#define GPIO40_USB_P2_5 MFP_CFG_IN(GPIO40, AF3)
-#define GPIO41_USB_P2_7 MFP_CFG_IN(GPIO41, AF2)
-#define GPIO53_USB_P2_3 MFP_CFG_IN(GPIO53, AF2)
-
-/* USB Host Port 1/2 */
-#define GPIO88_USBH1_PWR MFP_CFG_IN(GPIO88, AF1)
-#define GPIO89_USBH1_PEN MFP_CFG_OUT(GPIO89, AF2, DRIVE_LOW)
-#define GPIO119_USBH2_PWR MFP_CFG_IN(GPIO119, AF1)
-#define GPIO120_USBH2_PEN MFP_CFG_OUT(GPIO120, AF2, DRIVE_LOW)
-
-/* QCI - default to Master Mode: CIF_FV/CIF_LV Direction In */
-#define GPIO115_CIF_DD_3 MFP_CFG_IN(GPIO115, AF2)
-#define GPIO116_CIF_DD_2 MFP_CFG_IN(GPIO116, AF1)
-#define GPIO12_CIF_DD_7 MFP_CFG_IN(GPIO12, AF2)
-#define GPIO17_CIF_DD_6 MFP_CFG_IN(GPIO17, AF2)
-#define GPIO23_CIF_MCLK MFP_CFG_OUT(GPIO23, AF1, DRIVE_LOW)
-#define GPIO24_CIF_FV MFP_CFG_IN(GPIO24, AF1)
-#define GPIO25_CIF_LV MFP_CFG_IN(GPIO25, AF1)
-#define GPIO26_CIF_PCLK MFP_CFG_IN(GPIO26, AF2)
-#define GPIO27_CIF_DD_0 MFP_CFG_IN(GPIO27, AF3)
-#define GPIO42_CIF_MCLK MFP_CFG_OUT(GPIO42, AF3, DRIVE_LOW)
-#define GPIO43_CIF_FV MFP_CFG_IN(GPIO43, AF3)
-#define GPIO44_CIF_LV MFP_CFG_IN(GPIO44, AF3)
-#define GPIO45_CIF_PCLK MFP_CFG_IN(GPIO45, AF3)
-#define GPIO47_CIF_DD_0 MFP_CFG_IN(GPIO47, AF1)
-#define GPIO48_CIF_DD_5 MFP_CFG_IN(GPIO48, AF1)
-#define GPIO50_CIF_DD_3 MFP_CFG_IN(GPIO50, AF1)
-#define GPIO51_CIF_DD_2 MFP_CFG_IN(GPIO51, AF1)
-#define GPIO52_CIF_DD_4 MFP_CFG_IN(GPIO52, AF1)
-#define GPIO53_CIF_MCLK MFP_CFG_OUT(GPIO53, AF2, DRIVE_LOW)
-#define GPIO54_CIF_PCLK MFP_CFG_IN(GPIO54, AF3)
-#define GPIO55_CIF_DD_1 MFP_CFG_IN(GPIO55, AF1)
-#define GPIO81_CIF_DD_0 MFP_CFG_IN(GPIO81, AF2)
-#define GPIO82_CIF_DD_5 MFP_CFG_IN(GPIO82, AF3)
-#define GPIO83_CIF_DD_4 MFP_CFG_IN(GPIO83, AF3)
-#define GPIO84_CIF_FV MFP_CFG_IN(GPIO84, AF3)
-#define GPIO85_CIF_LV MFP_CFG_IN(GPIO85, AF3)
-#define GPIO90_CIF_DD_4 MFP_CFG_IN(GPIO90, AF3)
-#define GPIO91_CIF_DD_5 MFP_CFG_IN(GPIO91, AF3)
-#define GPIO93_CIF_DD_6 MFP_CFG_IN(GPIO93, AF2)
-#define GPIO94_CIF_DD_5 MFP_CFG_IN(GPIO94, AF2)
-#define GPIO95_CIF_DD_4 MFP_CFG_IN(GPIO95, AF2)
-#define GPIO98_CIF_DD_0 MFP_CFG_IN(GPIO98, AF2)
-#define GPIO103_CIF_DD_3 MFP_CFG_IN(GPIO103, AF1)
-#define GPIO104_CIF_DD_2 MFP_CFG_IN(GPIO104, AF1)
-#define GPIO105_CIF_DD_1 MFP_CFG_IN(GPIO105, AF1)
-#define GPIO106_CIF_DD_9 MFP_CFG_IN(GPIO106, AF1)
-#define GPIO107_CIF_DD_8 MFP_CFG_IN(GPIO107, AF1)
-#define GPIO108_CIF_DD_7 MFP_CFG_IN(GPIO108, AF1)
-#define GPIO114_CIF_DD_1 MFP_CFG_IN(GPIO114, AF1)
-
-/* Universal Subscriber ID Interface */
-#define GPIO114_UVS0 MFP_CFG_OUT(GPIO114, AF2, DRIVE_LOW)
-#define GPIO115_nUVS1 MFP_CFG_OUT(GPIO115, AF2, DRIVE_LOW)
-#define GPIO116_nUVS2 MFP_CFG_OUT(GPIO116, AF2, DRIVE_LOW)
-#define GPIO14_UCLK MFP_CFG_OUT(GPIO14, AF3, DRIVE_LOW)
-#define GPIO91_UCLK MFP_CFG_OUT(GPIO91, AF2, DRIVE_LOW)
-#define GPIO19_nURST MFP_CFG_OUT(GPIO19, AF3, DRIVE_LOW)
-#define GPIO90_nURST MFP_CFG_OUT(GPIO90, AF2, DRIVE_LOW)
-#define GPIO116_UDET MFP_CFG_IN(GPIO116, AF3)
-#define GPIO114_UEN MFP_CFG_OUT(GPIO114, AF1, DRIVE_LOW)
-#define GPIO115_UEN MFP_CFG_OUT(GPIO115, AF1, DRIVE_LOW)
-
-/* Mobile Scalable Link (MSL) Interface */
-#define GPIO81_BB_OB_DAT_0 MFP_CFG_OUT(GPIO81, AF2, DRIVE_LOW)
-#define GPIO48_BB_OB_DAT_1 MFP_CFG_OUT(GPIO48, AF1, DRIVE_LOW)
-#define GPIO50_BB_OB_DAT_2 MFP_CFG_OUT(GPIO50, AF1, DRIVE_LOW)
-#define GPIO51_BB_OB_DAT_3 MFP_CFG_OUT(GPIO51, AF1, DRIVE_LOW)
-#define GPIO52_BB_OB_CLK MFP_CFG_OUT(GPIO52, AF1, DRIVE_LOW)
-#define GPIO53_BB_OB_STB MFP_CFG_OUT(GPIO53, AF1, DRIVE_LOW)
-#define GPIO54_BB_OB_WAIT MFP_CFG_IN(GPIO54, AF2)
-#define GPIO82_BB_IB_DAT_0 MFP_CFG_IN(GPIO82, AF2)
-#define GPIO55_BB_IB_DAT_1 MFP_CFG_IN(GPIO55, AF2)
-#define GPIO56_BB_IB_DAT_2 MFP_CFG_IN(GPIO56, AF2)
-#define GPIO57_BB_IB_DAT_3 MFP_CFG_IN(GPIO57, AF2)
-#define GPIO83_BB_IB_CLK MFP_CFG_IN(GPIO83, AF2)
-#define GPIO84_BB_IB_STB MFP_CFG_IN(GPIO84, AF2)
-#define GPIO85_BB_IB_WAIT MFP_CFG_OUT(GPIO85, AF2, DRIVE_LOW)
-
-/* Memory Stick Host Controller */
-#define GPIO92_MSBS MFP_CFG_OUT(GPIO92, AF2, DRIVE_LOW)
-#define GPIO109_MSSDIO MFP_CFG_IN(GPIO109, AF2)
-#define GPIO112_nMSINS MFP_CFG_IN(GPIO112, AF2)
-#define GPIO32_MSSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
-
-/* commonly used pin configurations */
-#define GPIOxx_LCD_16BPP \
- GPIO58_LCD_LDD_0, \
- GPIO59_LCD_LDD_1, \
- GPIO60_LCD_LDD_2, \
- GPIO61_LCD_LDD_3, \
- GPIO62_LCD_LDD_4, \
- GPIO63_LCD_LDD_5, \
- GPIO64_LCD_LDD_6, \
- GPIO65_LCD_LDD_7, \
- GPIO66_LCD_LDD_8, \
- GPIO67_LCD_LDD_9, \
- GPIO68_LCD_LDD_10, \
- GPIO69_LCD_LDD_11, \
- GPIO70_LCD_LDD_12, \
- GPIO71_LCD_LDD_13, \
- GPIO72_LCD_LDD_14, \
- GPIO73_LCD_LDD_15
-
-#define GPIOxx_LCD_DSTN_16BPP \
- GPIOxx_LCD_16BPP, \
- GPIO74_LCD_FCLK, \
- GPIO75_LCD_LCLK, \
- GPIO76_LCD_PCLK
-
-#define GPIOxx_LCD_TFT_16BPP \
- GPIOxx_LCD_16BPP, \
- GPIO74_LCD_FCLK, \
- GPIO75_LCD_LCLK, \
- GPIO76_LCD_PCLK, \
- GPIO77_LCD_BIAS
-
-extern int keypad_set_wake(unsigned int on);
-#endif /* __ASM_ARCH_MFP_PXA27X_H */
diff --git a/include/mach/pxa/mfp-pxa2xx.h b/include/mach/pxa/mfp-pxa2xx.h
deleted file mode 100644
index 00bae5e063..0000000000
--- a/include/mach/pxa/mfp-pxa2xx.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_ARCH_MFP_PXA2XX_H
-#define __ASM_ARCH_MFP_PXA2XX_H
-
-#include <mach/pxa/mfp.h>
-
-/*
- * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx:
- *
- * MFP_PIN(x)
- * MFP_AFx
- * MFP_LPM_DRIVE_{LOW, HIGH}
- * MFP_LPM_EDGE_x
- *
- * other MFP_x bit definitions will be ignored
- *
- * and adds the below two bits specifically for pxa2xx:
- *
- * bit 23 - Input/Output (PXA2xx specific)
- * bit 24 - Wakeup Enable(PXA2xx specific)
- */
-
-#define MFP_DIR_IN (0x0 << 23)
-#define MFP_DIR_OUT (0x1 << 23)
-#define MFP_DIR_MASK (0x1 << 23)
-#define MFP_DIR(x) (((x) >> 23) & 0x1)
-
-#define MFP_LPM_CAN_WAKEUP (0x1 << 24)
-#define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE)
-#define WAKEUP_ON_EDGE_FALL (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_FALL)
-#define WAKEUP_ON_EDGE_BOTH (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_BOTH)
-
-/* specifically for enabling wakeup on keypad GPIOs */
-#define WAKEUP_ON_LEVEL_HIGH (MFP_LPM_CAN_WAKEUP)
-
-#define MFP_CFG_IN(pin, af) \
- ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK)) |\
- (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_IN))
-
-/* NOTE: pins configured as output _must_ provide a low power state,
- * and this state should help to minimize the power dissipation.
- */
-#define MFP_CFG_OUT(pin, af, state) \
- ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK | MFP_LPM_STATE_MASK)) |\
- (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_OUT | MFP_LPM_##state))
-
-/* Common configurations for pxa25x and pxa27x
- *
- * Note: pins configured as GPIO are always initialized to input
- * so not to cause any side effect
- */
-#define GPIO0_GPIO MFP_CFG_IN(GPIO0, AF0)
-#define GPIO1_GPIO MFP_CFG_IN(GPIO1, AF0)
-#define GPIO9_GPIO MFP_CFG_IN(GPIO9, AF0)
-#define GPIO10_GPIO MFP_CFG_IN(GPIO10, AF0)
-#define GPIO11_GPIO MFP_CFG_IN(GPIO11, AF0)
-#define GPIO12_GPIO MFP_CFG_IN(GPIO12, AF0)
-#define GPIO13_GPIO MFP_CFG_IN(GPIO13, AF0)
-#define GPIO14_GPIO MFP_CFG_IN(GPIO14, AF0)
-#define GPIO15_GPIO MFP_CFG_IN(GPIO15, AF0)
-#define GPIO16_GPIO MFP_CFG_IN(GPIO16, AF0)
-#define GPIO17_GPIO MFP_CFG_IN(GPIO17, AF0)
-#define GPIO18_GPIO MFP_CFG_IN(GPIO18, AF0)
-#define GPIO19_GPIO MFP_CFG_IN(GPIO19, AF0)
-#define GPIO20_GPIO MFP_CFG_IN(GPIO20, AF0)
-#define GPIO21_GPIO MFP_CFG_IN(GPIO21, AF0)
-#define GPIO22_GPIO MFP_CFG_IN(GPIO22, AF0)
-#define GPIO23_GPIO MFP_CFG_IN(GPIO23, AF0)
-#define GPIO24_GPIO MFP_CFG_IN(GPIO24, AF0)
-#define GPIO25_GPIO MFP_CFG_IN(GPIO25, AF0)
-#define GPIO26_GPIO MFP_CFG_IN(GPIO26, AF0)
-#define GPIO27_GPIO MFP_CFG_IN(GPIO27, AF0)
-#define GPIO28_GPIO MFP_CFG_IN(GPIO28, AF0)
-#define GPIO29_GPIO MFP_CFG_IN(GPIO29, AF0)
-#define GPIO30_GPIO MFP_CFG_IN(GPIO30, AF0)
-#define GPIO31_GPIO MFP_CFG_IN(GPIO31, AF0)
-#define GPIO32_GPIO MFP_CFG_IN(GPIO32, AF0)
-#define GPIO33_GPIO MFP_CFG_IN(GPIO33, AF0)
-#define GPIO34_GPIO MFP_CFG_IN(GPIO34, AF0)
-#define GPIO35_GPIO MFP_CFG_IN(GPIO35, AF0)
-#define GPIO36_GPIO MFP_CFG_IN(GPIO36, AF0)
-#define GPIO37_GPIO MFP_CFG_IN(GPIO37, AF0)
-#define GPIO38_GPIO MFP_CFG_IN(GPIO38, AF0)
-#define GPIO39_GPIO MFP_CFG_IN(GPIO39, AF0)
-#define GPIO40_GPIO MFP_CFG_IN(GPIO40, AF0)
-#define GPIO41_GPIO MFP_CFG_IN(GPIO41, AF0)
-#define GPIO42_GPIO MFP_CFG_IN(GPIO42, AF0)
-#define GPIO43_GPIO MFP_CFG_IN(GPIO43, AF0)
-#define GPIO44_GPIO MFP_CFG_IN(GPIO44, AF0)
-#define GPIO45_GPIO MFP_CFG_IN(GPIO45, AF0)
-#define GPIO46_GPIO MFP_CFG_IN(GPIO46, AF0)
-#define GPIO47_GPIO MFP_CFG_IN(GPIO47, AF0)
-#define GPIO48_GPIO MFP_CFG_IN(GPIO48, AF0)
-#define GPIO49_GPIO MFP_CFG_IN(GPIO49, AF0)
-#define GPIO50_GPIO MFP_CFG_IN(GPIO50, AF0)
-#define GPIO51_GPIO MFP_CFG_IN(GPIO51, AF0)
-#define GPIO52_GPIO MFP_CFG_IN(GPIO52, AF0)
-#define GPIO53_GPIO MFP_CFG_IN(GPIO53, AF0)
-#define GPIO54_GPIO MFP_CFG_IN(GPIO54, AF0)
-#define GPIO55_GPIO MFP_CFG_IN(GPIO55, AF0)
-#define GPIO56_GPIO MFP_CFG_IN(GPIO56, AF0)
-#define GPIO57_GPIO MFP_CFG_IN(GPIO57, AF0)
-#define GPIO58_GPIO MFP_CFG_IN(GPIO58, AF0)
-#define GPIO59_GPIO MFP_CFG_IN(GPIO59, AF0)
-#define GPIO60_GPIO MFP_CFG_IN(GPIO60, AF0)
-#define GPIO61_GPIO MFP_CFG_IN(GPIO61, AF0)
-#define GPIO62_GPIO MFP_CFG_IN(GPIO62, AF0)
-#define GPIO63_GPIO MFP_CFG_IN(GPIO63, AF0)
-#define GPIO64_GPIO MFP_CFG_IN(GPIO64, AF0)
-#define GPIO65_GPIO MFP_CFG_IN(GPIO65, AF0)
-#define GPIO66_GPIO MFP_CFG_IN(GPIO66, AF0)
-#define GPIO67_GPIO MFP_CFG_IN(GPIO67, AF0)
-#define GPIO68_GPIO MFP_CFG_IN(GPIO68, AF0)
-#define GPIO69_GPIO MFP_CFG_IN(GPIO69, AF0)
-#define GPIO70_GPIO MFP_CFG_IN(GPIO70, AF0)
-#define GPIO71_GPIO MFP_CFG_IN(GPIO71, AF0)
-#define GPIO72_GPIO MFP_CFG_IN(GPIO72, AF0)
-#define GPIO73_GPIO MFP_CFG_IN(GPIO73, AF0)
-#define GPIO74_GPIO MFP_CFG_IN(GPIO74, AF0)
-#define GPIO75_GPIO MFP_CFG_IN(GPIO75, AF0)
-#define GPIO76_GPIO MFP_CFG_IN(GPIO76, AF0)
-#define GPIO77_GPIO MFP_CFG_IN(GPIO77, AF0)
-#define GPIO78_GPIO MFP_CFG_IN(GPIO78, AF0)
-#define GPIO79_GPIO MFP_CFG_IN(GPIO79, AF0)
-#define GPIO80_GPIO MFP_CFG_IN(GPIO80, AF0)
-#define GPIO81_GPIO MFP_CFG_IN(GPIO81, AF0)
-#define GPIO82_GPIO MFP_CFG_IN(GPIO82, AF0)
-#define GPIO83_GPIO MFP_CFG_IN(GPIO83, AF0)
-#define GPIO84_GPIO MFP_CFG_IN(GPIO84, AF0)
-
-extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num);
-extern void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm);
-extern int gpio_set_wake(unsigned int gpio, unsigned int on);
-#endif /* __ASM_ARCH_MFP_PXA2XX_H */
diff --git a/include/mach/pxa/pxa-regs.h b/include/mach/pxa/pxa-regs.h
index 55bfae67be..24b39f5e60 100644
--- a/include/mach/pxa/pxa-regs.h
+++ b/include/mach/pxa/pxa-regs.h
@@ -20,18 +20,6 @@
# define __REG2(x, y) ((x) + (y))
#endif
-#ifdef CONFIG_ARCH_PXA2XX
-#include <mach/pxa/pxa2xx-regs.h>
-#endif
-
-#if defined(CONFIG_ARCH_PXA27X)
-#include <mach/pxa/pxa27x-regs.h>
-#elif defined(CONFIG_ARCH_PXA3XX)
#include <mach/pxa/pxa3xx-regs.h>
-#elif defined(CONFIG_ARCH_PXA25X)
-#include <mach/pxa/pxa25x-regs.h>
-#else
-#error "unknown PXA soc type"
-#endif
#endif /* !__MACH_PXA_REGS_H */
diff --git a/include/mach/pxa/pxa25x-regs.h b/include/mach/pxa/pxa25x-regs.h
deleted file mode 100644
index f9cbe50007..0000000000
--- a/include/mach/pxa/pxa25x-regs.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __MACH_PXA25X_REGS
-#define __MACH_PXA25X_REGS
-
-/* this file intentionally left blank */
-
-#endif /* !__MACH_PXA25X_REGS */
diff --git a/include/mach/pxa/pxa27x-regs.h b/include/mach/pxa/pxa27x-regs.h
deleted file mode 100644
index a97538d012..0000000000
--- a/include/mach/pxa/pxa27x-regs.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __MACH_PXA27X_REGS
-#define __MACH_PXA27X_REGS
-
-/* this file intentionally left blank */
-
-#endif /* !__MACH_PXA27X_REGS */
diff --git a/include/mach/pxa/pxa2xx-regs.h b/include/mach/pxa/pxa2xx-regs.h
deleted file mode 100644
index 9e5aeb467d..0000000000
--- a/include/mach/pxa/pxa2xx-regs.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
- *
- * Taken from pxa-regs.h by Russell King
- *
- * Author: Nicolas Pitre
- * Copyright: MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PXA2XX_REGS_H
-#define __PXA2XX_REGS_H
-
-#include <mach/pxa/hardware.h>
-
-/*
- * PXA Chip selects
- */
-#define PXA_CS0_PHYS 0x00000000
-#define PXA_CS1_PHYS 0x04000000
-#define PXA_CS2_PHYS 0x08000000
-#define PXA_CS3_PHYS 0x0C000000
-#define PXA_CS4_PHYS 0x10000000
-#define PXA_CS5_PHYS 0x14000000
-
-/*
- * Memory controller
- */
-#define MDCNFG_OFFSET 0x00000000
-#define MDREFR_OFFSET 0x00000004
-#define MSC0_OFFSET 0x00000008
-#define MSC1_OFFSET 0x0000000C
-#define MSC2_OFFSET 0x00000010
-#define MECR_OFFSET 0x00000014
-#define SXCNFG_OFFSET 0x0000001C
-#define FLYCNFG_OFFSET 0x00000020
-#define MCMEM0_OFFSET 0x00000028
-#define MCMEM1_OFFSET 0x0000002C
-#define MCATT0_OFFSET 0x00000030
-#define MCATT1_OFFSET 0x00000034
-#define MCIO0_OFFSET 0x00000038
-#define MCIO1_OFFSET 0x0000003C
-#define MDMRS_OFFSET 0x00000040
-
-#define MDCNFG __REG(0x48000000) /* SDRAM Configuration Register 0 */
-#define MDREFR __REG(0x48000004) /* SDRAM Refresh Control Register */
-#define MSC0 __REG(0x48000008) /* Static Memory Control Register 0 */
-#define MSC1 __REG(0x4800000C) /* Static Memory Control Register 1 */
-#define MSC2 __REG(0x48000010) /* Static Memory Control Register 2 */
-#define MECR __REG(0x48000014) /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
-#define SXLCR __REG(0x48000018) /* LCR value to be written to SDRAM-Timing Synchronous Flash */
-#define SXCNFG __REG(0x4800001C) /* Synchronous Static Memory Control Register */
-#define FLYCNFG __REG(0x48000020) /* Flycnfg Register */
-#define SXMRS __REG(0x48000024) /* MRS value to be written to Synchronous Flash or SMROM */
-#define MCMEM0 __REG(0x48000028) /* Card interface Common Memory Space Socket 0 Timing */
-#define MCMEM1 __REG(0x4800002C) /* Card interface Common Memory Space Socket 1 Timing */
-#define MCATT0 __REG(0x48000030) /* Card interface Attribute Space Socket 0 Timing Configuration */
-#define MCATT1 __REG(0x48000034) /* Card interface Attribute Space Socket 1 Timing Configuration */
-#define MCIO0 __REG(0x48000038) /* Card interface I/O Space Socket 0 Timing Configuration */
-#define MCIO1 __REG(0x4800003C) /* Card interface I/O Space Socket 1 Timing Configuration */
-#define MDMRS __REG(0x48000040) /* MRS value to be written to SDRAM */
-#define BOOT_DEF __REG(0x48000044) /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
-
-/*
- * More handy macros for PCMCIA
- *
- * Arg is socket number
- */
-#define MCMEM(s) __REG2(0x48000028, (s)<<2 ) /* Card interface Common Memory Space Socket s Timing */
-#define MCATT(s) __REG2(0x48000030, (s)<<2 ) /* Card interface Attribute Space Socket s Timing Configuration */
-#define MCIO(s) __REG2(0x48000038, (s)<<2 ) /* Card interface I/O Space Socket s Timing Configuration */
-
-/* MECR register defines */
-#define MECR_NOS (1 << 0) /* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */
-#define MECR_CIT (1 << 1) /* Card Is There: 0 -> no card, 1 -> card inserted */
-
-#define MDCNFG_DE0 (1 << 0) /* SDRAM Bank 0 Enable */
-#define MDCNFG_DE1 (1 << 1) /* SDRAM Bank 1 Enable */
-#define MDCNFG_DE2 (1 << 16) /* SDRAM Bank 2 Enable */
-#define MDCNFG_DE3 (1 << 17) /* SDRAM Bank 3 Enable */
-
-#define MDREFR_K0DB4 (1 << 29) /* SDCLK0 Divide by 4 Control/Status */
-#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */
-#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */
-#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */
-#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */
-#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */
-#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */
-#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */
-#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */
-#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */
-#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */
-#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */
-#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */
-#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */
-
-/*
- * Power Manager
- */
-
-#define PMCR __REG(0x40F00000) /* Power Manager Control Register */
-#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status Register */
-#define PSPR __REG(0x40F00008) /* Power Manager Scratch Pad Register */
-#define PWER __REG(0x40F0000C) /* Power Manager Wake-up Enable Register */
-#define PRER __REG(0x40F00010) /* Power Manager GPIO Rising-Edge Detect Enable Register */
-#define PFER __REG(0x40F00014) /* Power Manager GPIO Falling-Edge Detect Enable Register */
-#define PEDR __REG(0x40F00018) /* Power Manager GPIO Edge Detect Status Register */
-#define PCFR __REG(0x40F0001C) /* Power Manager General Configuration Register */
-#define PGSR0 __REG(0x40F00020) /* Power Manager GPIO Sleep State Register for GP[31-0] */
-#define PGSR1 __REG(0x40F00024) /* Power Manager GPIO Sleep State Register for GP[63-32] */
-#define PGSR2 __REG(0x40F00028) /* Power Manager GPIO Sleep State Register for GP[84-64] */
-#define PGSR3 __REG(0x40F0002C) /* Power Manager GPIO Sleep State Register for GP[118-96] */
-#define RCSR __REG(0x40F00030) /* Reset Controller Status Register */
-
-#define PSLR __REG(0x40F00034) /* Power Manager Sleep Config Register */
-#define PSTR __REG(0x40F00038) /* Power Manager Standby Config Register */
-#define PSNR __REG(0x40F0003C) /* Power Manager Sense Config Register */
-#define PVCR __REG(0x40F00040) /* Power Manager VoltageControl Register */
-#define PKWR __REG(0x40F00050) /* Power Manager KB Wake-up Enable Reg */
-#define PKSR __REG(0x40F00054) /* Power Manager KB Level-Detect Register */
-#define PCMD(x) __REG2(0x40F00080, (x)<<2)
-#define PCMD0 __REG(0x40F00080 + 0 * 4)
-#define PCMD1 __REG(0x40F00080 + 1 * 4)
-#define PCMD2 __REG(0x40F00080 + 2 * 4)
-#define PCMD3 __REG(0x40F00080 + 3 * 4)
-#define PCMD4 __REG(0x40F00080 + 4 * 4)
-#define PCMD5 __REG(0x40F00080 + 5 * 4)
-#define PCMD6 __REG(0x40F00080 + 6 * 4)
-#define PCMD7 __REG(0x40F00080 + 7 * 4)
-#define PCMD8 __REG(0x40F00080 + 8 * 4)
-#define PCMD9 __REG(0x40F00080 + 9 * 4)
-#define PCMD10 __REG(0x40F00080 + 10 * 4)
-#define PCMD11 __REG(0x40F00080 + 11 * 4)
-#define PCMD12 __REG(0x40F00080 + 12 * 4)
-#define PCMD13 __REG(0x40F00080 + 13 * 4)
-#define PCMD14 __REG(0x40F00080 + 14 * 4)
-#define PCMD15 __REG(0x40F00080 + 15 * 4)
-#define PCMD16 __REG(0x40F00080 + 16 * 4)
-#define PCMD17 __REG(0x40F00080 + 17 * 4)
-#define PCMD18 __REG(0x40F00080 + 18 * 4)
-#define PCMD19 __REG(0x40F00080 + 19 * 4)
-#define PCMD20 __REG(0x40F00080 + 20 * 4)
-#define PCMD21 __REG(0x40F00080 + 21 * 4)
-#define PCMD22 __REG(0x40F00080 + 22 * 4)
-#define PCMD23 __REG(0x40F00080 + 23 * 4)
-#define PCMD24 __REG(0x40F00080 + 24 * 4)
-#define PCMD25 __REG(0x40F00080 + 25 * 4)
-#define PCMD26 __REG(0x40F00080 + 26 * 4)
-#define PCMD27 __REG(0x40F00080 + 27 * 4)
-#define PCMD28 __REG(0x40F00080 + 28 * 4)
-#define PCMD29 __REG(0x40F00080 + 29 * 4)
-#define PCMD30 __REG(0x40F00080 + 30 * 4)
-#define PCMD31 __REG(0x40F00080 + 31 * 4)
-
-#define PCMD_MBC (1<<12)
-#define PCMD_DCE (1<<11)
-#define PCMD_LC (1<<10)
-/* FIXME: PCMD_SQC need be checked. */
-#define PCMD_SQC (3<<8) /* currently only bit 8 is changeable,
- bit 9 should be 0 all day. */
-#define PVCR_VCSA (0x1<<14)
-#define PVCR_CommandDelay (0xf80)
-#define PCFR_PI2C_EN (0x1 << 6)
-
-#define PSSR_OTGPH (1 << 6) /* OTG Peripheral control Hold */
-#define PSSR_RDH (1 << 5) /* Read Disable Hold */
-#define PSSR_PH (1 << 4) /* Peripheral Control Hold */
-#define PSSR_STS (1 << 3) /* Standby Mode Status */
-#define PSSR_VFS (1 << 2) /* VDD Fault Status */
-#define PSSR_BFS (1 << 1) /* Battery Fault Status */
-#define PSSR_SSS (1 << 0) /* Software Sleep Status */
-
-#define PSLR_SL_ROD (1 << 20) /* Sleep-Mode/Depp-Sleep Mode nRESET_OUT Disable */
-
-#define PCFR_RO (1 << 15) /* RDH Override */
-#define PCFR_PO (1 << 14) /* PH Override */
-#define PCFR_GPROD (1 << 12) /* GPIO nRESET_OUT Disable */
-#define PCFR_L1_EN (1 << 11) /* Sleep Mode L1 converter Enable */
-#define PCFR_FVC (1 << 10) /* Frequency/Voltage Change */
-#define PCFR_DC_EN (1 << 7) /* Sleep/deep-sleep DC-DC Converter Enable */
-#define PCFR_PI2CEN (1 << 6) /* Enable PI2C controller */
-#define PCFR_GPR_EN (1 << 4) /* nRESET_GPIO Pin Enable */
-#define PCFR_DS (1 << 3) /* Deep Sleep Mode */
-#define PCFR_FS (1 << 2) /* Float Static Chip Selects */
-#define PCFR_FP (1 << 1) /* Float PCMCIA controls */
-#define PCFR_OPDE (1 << 0) /* 3.6864 MHz oscillator power-down enable */
-
-#define RCSR_GPR (1 << 3) /* GPIO Reset */
-#define RCSR_SMR (1 << 2) /* Sleep Mode */
-#define RCSR_WDR (1 << 1) /* Watchdog Reset */
-#define RCSR_HWR (1 << 0) /* Hardware Reset */
-
-#define PWER_GPIO(Nb) (1 << Nb) /* GPIO [0..15] wake-up enable */
-#define PWER_GPIO0 PWER_GPIO(0) /* GPIO [0] wake-up enable */
-#define PWER_GPIO1 PWER_GPIO(1) /* GPIO [1] wake-up enable */
-#define PWER_GPIO2 PWER_GPIO(2) /* GPIO [2] wake-up enable */
-#define PWER_GPIO3 PWER_GPIO(3) /* GPIO [3] wake-up enable */
-#define PWER_GPIO4 PWER_GPIO(4) /* GPIO [4] wake-up enable */
-#define PWER_GPIO5 PWER_GPIO(5) /* GPIO [5] wake-up enable */
-#define PWER_GPIO6 PWER_GPIO(6) /* GPIO [6] wake-up enable */
-#define PWER_GPIO7 PWER_GPIO(7) /* GPIO [7] wake-up enable */
-#define PWER_GPIO8 PWER_GPIO(8) /* GPIO [8] wake-up enable */
-#define PWER_GPIO9 PWER_GPIO(9) /* GPIO [9] wake-up enable */
-#define PWER_GPIO10 PWER_GPIO(10) /* GPIO [10] wake-up enable */
-#define PWER_GPIO11 PWER_GPIO(11) /* GPIO [11] wake-up enable */
-#define PWER_GPIO12 PWER_GPIO(12) /* GPIO [12] wake-up enable */
-#define PWER_GPIO13 PWER_GPIO(13) /* GPIO [13] wake-up enable */
-#define PWER_GPIO14 PWER_GPIO(14) /* GPIO [14] wake-up enable */
-#define PWER_GPIO15 PWER_GPIO(15) /* GPIO [15] wake-up enable */
-#define PWER_RTC 0x80000000 /* RTC alarm wake-up enable */
-
-/*
- * PXA2xx specific Core clock definitions
- */
-#define CCCR __REG(0x41300000) /* Core Clock Configuration Register */
-#define CCSR __REG(0x4130000C) /* Core Clock Status Register */
-#define CKEN __REG(0x41300004) /* Clock Enable Register */
-#define OSCC __REG(0x41300008) /* Oscillator Configuration Register */
-
-#define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */
-#define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */
-#define CCCR_L_MASK 0x001f /* Crystal Frequency to Memory Frequency Multiplier */
-#define CCCR_CPDIS (1 << 31)
-#define CCCR_PPDIS (1 << 30)
-#define CCCR_LCD26 (1 << 27)
-#define CCCR_PLL_EARLY (1 << 26)
-#define CCCR_A (1 << 25)
-
-#define CKEN_AC97CONF (1 << 31) /* AC97 Controller Configuration */
-#define CKEN_CAMERA (1 << 24) /* Camera Interface Clock Enable */
-#define CKEN_SSP1 (1 << 23) /* SSP1 Unit Clock Enable */
-#define CKEN_MEMC (1 << 22) /* Memory Controller Clock Enable */
-#define CKEN_MEMSTK (1 << 21) /* Memory Stick Host Controller */
-#define CKEN_IM (1 << 20) /* Internal Memory Clock Enable */
-#define CKEN_KEYPAD (1 << 19) /* Keypad Interface Clock Enable */
-#define CKEN_USIM (1 << 18) /* USIM Unit Clock Enable */
-#define CKEN_MSL (1 << 17) /* MSL Unit Clock Enable */
-#define CKEN_LCD (1 << 16) /* LCD Unit Clock Enable */
-#define CKEN_PWRI2C (1 << 15) /* PWR I2C Unit Clock Enable */
-#define CKEN_I2C (1 << 14) /* I2C Unit Clock Enable */
-#define CKEN_FICP (1 << 13) /* FICP Unit Clock Enable */
-#define CKEN_MMC (1 << 12) /* MMC Unit Clock Enable */
-#define CKEN_USB (1 << 11) /* USB Unit Clock Enable */
-#define CKEN_ASSP (1 << 10) /* ASSP (1 << SSP3) Clock Enable */
-#define CKEN_USBHOST (1 << 10) /* USB Host Unit Clock Enable */
-#define CKEN_OSTIMER (1 << 9) /* OS Timer Unit Clock Enable */
-#define CKEN_NSSP (1 << 9) /* NSSP (1 << SSP2) Clock Enable */
-#define CKEN_I2S (1 << 8) /* I2S Unit Clock Enable */
-#define CKEN_BTUART (1 << 7) /* BTUART Unit Clock Enable */
-#define CKEN_FFUART (1 << 6) /* FFUART Unit Clock Enable */
-#define CKEN_STUART (1 << 5) /* STUART Unit Clock Enable */
-#define CKEN_HWUART (1 << 4) /* HWUART Unit Clock Enable */
-#define CKEN_SSP3 (1 << 4) /* SSP3 Unit Clock Enable */
-#define CKEN_SSP (1 << 3) /* SSP Unit Clock Enable */
-#define CKEN_SSP2 (1 << 3) /* SSP2 Unit Clock Enable */
-#define CKEN_AC97 (1 << 2) /* AC97 Unit Clock Enable */
-#define CKEN_PWM1 (1 << 1) /* PWM1 Clock Enable */
-#define CKEN_PWM0 (1 << 0) /* PWM0 Clock Enable */
-
-#define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */
-#define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */
-
-/* PWRMODE register M field values */
-
-#define PWRMODE_IDLE 0x1
-#define PWRMODE_STANDBY 0x2
-#define PWRMODE_SLEEP 0x3
-#define PWRMODE_DEEPSLEEP 0x7
-
-#endif
diff --git a/include/mach/pxa/udc_pxa2xx.h b/include/mach/pxa/udc_pxa2xx.h
deleted file mode 100644
index 1ddfa7b797..0000000000
--- a/include/mach/pxa/udc_pxa2xx.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-/*
- * arch/arm/mach-pxa/include/mach/udc_pxa2xx.h
- *
- * This supports machine-specific differences in how the PXA2xx
- * USB Device Controller (UDC) is wired.
- *
- * It is set in linux/arch/arm/mach-pxa/<machine>.c or in
- * linux/arch/mach-ixp4xx/<machine>.c and used in
- * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c
- */
-
-struct pxa2xx_udc_mach_info {
- int (*udc_is_connected)(void); /* do we see host? */
- void (*udc_command)(int cmd);
-#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */
-#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */
-
- /* Boards following the design guidelines in the developer's manual,
- * with on-chip GPIOs not Lubbock's weird hardware, can have a sane
- * VBUS IRQ and omit the methods above. Store the GPIO number
- * here. Note that sometimes the signals go through inverters...
- */
- bool gpio_pullup_inverted;
- int gpio_pullup; /* high == pullup activated */
-};
-
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 02/27] video: remove the PXA framebuffer driver
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
2026-08-16 17:56 ` [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions Sascha Hauer
` (26 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The driver only ever worked on PXA27x, which is gone now, so it cannot be
enabled by anything. Remove it together with the register definitions and
the platform device helper that existed solely for it.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/devices.c | 6 -
drivers/video/Kconfig | 7 -
drivers/video/Makefile | 1 -
drivers/video/pxa.c | 548 --------------------------------------------
include/mach/pxa/devices.h | 2 -
include/mach/pxa/pxafb.h | 81 -------
include/mach/pxa/regs-lcd.h | 182 ---------------
7 files changed, 827 deletions(-)
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index b5d098bd91..2f05573708 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -15,7 +15,6 @@
#include <common.h>
#include <driver.h>
#include <mach/pxa/devices.h>
-#include <mach/pxa/pxafb.h>
static inline struct device *pxa_add_device(char *name, int id, void *base,
int size, void *pdata)
@@ -35,11 +34,6 @@ struct device *pxa_add_uart(void *base, int id)
return pxa_add_device("pxa_serial", id, base, 0x1000, NULL);
}
-struct device *pxa_add_fb(void *base, struct pxafb_platform_data *pdata)
-{
- return pxa_add_device("pxafb", -1, base, 0x1000, pdata);
-}
-
struct device *pxa_add_mmc(void *base, int id, void *pdata)
{
return pxa_add_device("pxa-mmc", id, base, 0x1000, pdata);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 2faad19a99..c9dc765894 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -102,13 +102,6 @@ config DRIVER_VIDEO_SDL
depends on HAVE_LIBSDL2
select SDL
-config DRIVER_VIDEO_PXA
- bool "PXA27x framebuffer driver"
- depends on ARCH_PXA27X
- help
- Add support for the frame buffer device found on the PXA270
- CPU.
-
config DRIVER_VIDEO_BCM283X
bool "BCM283X framebuffer driver"
depends on ARCH_BCM283X
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 7b10eda0d8..ff03c63fa2 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -27,7 +27,6 @@ obj-$(CONFIG_DRIVER_VIDEO_STM32_DSI) += stm32_dsi.o
obj-$(CONFIG_DRIVER_VIDEO_IMX) += imx.o
obj-$(CONFIG_DRIVER_VIDEO_IMX_IPU) += imx-ipu-fb.o
obj-$(CONFIG_DRIVER_VIDEO_LCDIF) += lcdif_drv.o lcdif_kms.o
-obj-$(CONFIG_DRIVER_VIDEO_PXA) += pxa.o
obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
obj-$(CONFIG_DRIVER_VIDEO_BCM283X) += bcm2835.o
obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB_CLIENT) += simplefb-client.o
diff --git a/drivers/video/pxa.c b/drivers/video/pxa.c
deleted file mode 100644
index f4078b229a..0000000000
--- a/drivers/video/pxa.c
+++ /dev/null
@@ -1,548 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
- *
- * Derived from the linux-2.6 pxa framebuffer driver:
- *
- * Copyright (C) 1999 Eric A. Thomas.
- * Copyright (C) 2004 Jean-Frederic Clere.
- * Copyright (C) 2004 Ian Campbell.
- * Copyright (C) 2004 Jeff Lackey.
- * Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas
- * which in turn is:
- * Based on acornfb.c Copyright (C) Russell King.
- *
- */
-
-#include <common.h>
-#include <dma.h>
-#include <driver.h>
-#include <errno.h>
-#include <fb.h>
-#include <init.h>
-#include <malloc.h>
-#include <linux/err.h>
-
-#include <mach/pxa/clock.h>
-#include <mach/pxa/pxa-regs.h>
-#include <mach/pxa/regs-lcd.h>
-#include <mach/pxa/pxafb.h>
-
-#include <asm/io.h>
-#include <linux/math64.h>
-
-/* PXA LCD DMA descriptor */
-struct pxafb_dma_descriptor {
- unsigned int fdadr;
- unsigned int fsadr;
- unsigned int fidr;
- unsigned int ldcmd;
-};
-
-enum {
- PAL_NONE = -1,
- PAL_BASE = 0,
- PAL_MAX,
-};
-
-enum {
- DMA_BASE = 0,
- DMA_UPPER = 0,
- DMA_LOWER = 1,
- DMA_MAX,
-};
-
-struct pxafb_dma_buff {
- struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2];
-};
-
-struct pxafb_info {
- void __iomem *regs;
-
- struct pxafb_dma_buff *dma_buff;
- dma_addr_t fdadr[DMA_MAX * 2];
-
- u32 lccr0;
- u32 lccr3;
- u32 lccr4;
-
- u32 reg_lccr0;
- u32 reg_lccr1;
- u32 reg_lccr2;
- u32 reg_lccr3;
- u32 reg_lccr4;
-
- struct pxafb_videomode *mode;
- struct fb_info info;
- struct device *dev;
-
- void (*lcd_power)(int);
- void (*backlight_power)(int);
-};
-
-#define info_to_pxafb_info(_info) container_of(_info, struct pxafb_info, info)
-
-static inline unsigned long
-lcd_readl(struct pxafb_info *fbi, unsigned int off)
-{
- return __raw_readl(fbi->regs + off);
-}
-
-static inline void
-lcd_writel(struct pxafb_info *fbi, unsigned int off, unsigned long val)
-{
- __raw_writel(val, fbi->regs + off);
-}
-
-static inline void pxafb_backlight_power(struct pxafb_info *fbi, int on)
-{
- pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
-
- if (fbi->backlight_power)
- fbi->backlight_power(on);
-}
-
-static inline void pxafb_lcd_power(struct pxafb_info *fbi, int on)
-{
- pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
-
- if (fbi->lcd_power)
- fbi->lcd_power(on);
-}
-
-static void pxafb_enable_controller(struct fb_info *info)
-{
- struct pxafb_info *fbi = info_to_pxafb_info(info);
-
- pr_debug("pxafb: Enabling LCD controller\n");
- pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr[0]);
- pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr[1]);
- pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
- pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
- pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
- pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
- pr_debug("dma_desc 0x%08x\n", (unsigned int) &fbi->dma_buff->dma_desc[DMA_BASE]);
-
- /* enable LCD controller clock */
- CKEN |= CKEN_LCD;
-
- if (fbi->lccr0 & LCCR0_LCDT)
- return;
-
- /* Sequence from 11.7.10 */
- lcd_writel(fbi, LCCR4, fbi->reg_lccr4);
- lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
- lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
- lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
- lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
-
- lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
- lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
- lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
-
- pxafb_lcd_power(fbi, 1);
- pxafb_backlight_power(fbi, 1);
-}
-
-static void pxafb_disable_controller(struct fb_info *info)
-{
- struct pxafb_info *fbi = info_to_pxafb_info(info);
- u32 lccr0;
-
- pxafb_backlight_power(fbi, 0);
- pxafb_lcd_power(fbi, 0);
-
- /* Clear LCD Status Register */
- lcd_writel(fbi, LCSR, 0xffffffff);
-
- lccr0 = lcd_readl(fbi, LCCR0) & ~LCCR0_LDM;
- lcd_writel(fbi, LCCR0, lccr0);
- lcd_writel(fbi, LCCR0, lccr0 | LCCR0_DIS);
-
- /* disable LCD controller clock */
- CKEN &= ~CKEN_LCD;
-}
-
-static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
- unsigned long start, size_t size)
-{
- struct pxafb_dma_descriptor *dma_desc;
-
- if (dma < 0 || dma >= DMA_MAX * 2)
- return -EINVAL;
-
- dma_desc = &fbi->dma_buff->dma_desc[dma];
-
- dma_desc->fsadr = start;
- dma_desc->fidr = 0;
- dma_desc->ldcmd = size;
-
- if (pal < 0 || pal >= PAL_MAX * 2) {
- dma_desc->fdadr = virt_to_phys(dma_desc);
- fbi->fdadr[dma] = virt_to_phys(dma_desc);
- } else {
-#if 0
- struct pxafb_dma_descriptor *pal_desc;
-
- pal_desc = &fbi->dma_buff->pal_desc[pal];
-
- pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
- pal_desc->fidr = 0;
-
- if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
- pal_desc->ldcmd = fbi->palette_size * sizeof(u16);
- else
- pal_desc->ldcmd = fbi->palette_size * sizeof(u32);
-
- pal_desc->ldcmd |= LDCMD_PAL;
-
- /* flip back and forth between palette and frame buffer */
- pal_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
- dma_desc->fdadr = fbi->dma_buff_phys + pal_desc_off;
- fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
-#endif
- }
-
- return 0;
-}
-
-static void setup_base_frame(struct pxafb_info *fbi)
-{
- struct pxafb_videomode *mode = fbi->mode;
- struct fb_info *info = &fbi->info;
- int nbytes, dma, pal, bpp = info->bits_per_pixel;
- unsigned long line_length, offset;
-
- dma = DMA_BASE;
- pal = (bpp >= 16) ? PAL_NONE : PAL_BASE;
-
- line_length = info->xres * info->bits_per_pixel / 8;
-
- nbytes = line_length * mode->mode.yres;
- offset = virt_to_phys(info->screen_base);
-
- if (fbi->lccr0 & LCCR0_SDS) {
- nbytes = nbytes / 2;
- setup_frame_dma(fbi, dma + 1, PAL_NONE, offset + nbytes, nbytes);
- }
-
- setup_frame_dma(fbi, dma, pal, offset, nbytes);
-}
-
-/*
- * Calculate the PCD value from the clock rate (in picoseconds).
- * We take account of the PPCR clock setting.
- * From PXA Developer's Manual:
- *
- * PixelClock = LCLK
- * -------------
- * 2 ( PCD + 1 )
- *
- * PCD = LCLK
- * ------------- - 1
- * 2(PixelClock)
- *
- * Where:
- * LCLK = LCD/Memory Clock
- * PCD = LCCR3[7:0]
- *
- * PixelClock here is in Hz while the pixclock argument given is the
- * period in picoseconds. Hence PixelClock = 1 / ( pixclock * 10^-12 )
- *
- * The function get_lclk_frequency_10khz returns LCLK in units of
- * 10khz. Calling the result of this function lclk gives us the
- * following
- *
- * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 )
- * -------------------------------------- - 1
- * 2
- *
- * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
- */
-static inline unsigned int get_pcd(struct pxafb_info *fbi,
- unsigned int pixclock)
-{
- unsigned long long pcd;
-
- /*
- * FIXME: Need to take into account Double Pixel Clock mode
- * (DPC) bit? or perhaps set it based on the various clock
- * speeds
- */
- pcd = (unsigned long long)(pxa_get_lcdclk() / 10000);
- pcd *= pixclock;
- do_div(pcd, 100000000 * 2);
- /* no need for this, since we should subtract 1 anyway. they cancel */
- /* pcd += 1; */ /* make up for integer math truncations */
- return (unsigned int)pcd;
-}
-
-static void setup_parallel_timing(struct pxafb_info *fbi)
-{
- struct fb_info *info = &fbi->info;
- struct fb_videomode *mode = info->mode;
-
- unsigned int lines_per_panel, pcd = get_pcd(fbi, mode->pixclock.ps);
-
- fbi->reg_lccr1 =
- LCCR1_DisWdth(mode->xres) +
- LCCR1_HorSnchWdth(mode->hsync_len) +
- LCCR1_BegLnDel(mode->left_margin) +
- LCCR1_EndLnDel(mode->right_margin);
-
- /*
- * If we have a dual scan LCD, we need to halve
- * the YRES parameter.
- */
- lines_per_panel = mode->yres;
- if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
- lines_per_panel /= 2;
-
- fbi->reg_lccr2 =
- LCCR2_DisHght(lines_per_panel) +
- LCCR2_VrtSnchWdth(mode->vsync_len) +
- LCCR2_BegFrmDel(mode->upper_margin) +
- LCCR2_EndFrmDel(mode->lower_margin);
-
- fbi->reg_lccr3 = fbi->lccr3 |
- (mode->sync & FB_SYNC_HOR_HIGH_ACT ?
- LCCR3_HorSnchH : LCCR3_HorSnchL) |
- (mode->sync & FB_SYNC_VERT_HIGH_ACT ?
- LCCR3_VrtSnchH : LCCR3_VrtSnchL);
-
- if (pcd)
- fbi->reg_lccr3 |= LCCR3_PixClkDiv(pcd);
-}
-
-/* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */
-static inline int var_to_depth(struct fb_info *info)
-{
- return info->red.length + info->green.length +
- info->blue.length + info->transp.length;
-}
-
-/* calculate 4-bit BPP value for LCCR3 and OVLxC1 */
-static int pxafb_var_to_bpp(struct fb_info *info)
-{
- int bpp = -EINVAL;
-
- switch (info->bits_per_pixel) {
- case 1: bpp = 0; break;
- case 2: bpp = 1; break;
- case 4: bpp = 2; break;
- case 8: bpp = 3; break;
- case 16: bpp = 4; break;
- case 24:
- switch (var_to_depth(info)) {
- case 18: bpp = 6; break; /* 18-bits/pixel packed */
- case 19: bpp = 8; break; /* 19-bits/pixel packed */
- case 24: bpp = 9; break;
- }
- break;
- case 32:
- switch (var_to_depth(info)) {
- case 18: bpp = 5; break; /* 18-bits/pixel unpacked */
- case 19: bpp = 7; break; /* 19-bits/pixel unpacked */
- case 25: bpp = 10; break;
- }
- break;
- }
- return bpp;
-}
-
-/*
- * pxafb_var_to_lccr3():
- * Convert a bits per pixel value to the correct bit pattern for LCCR3
- *
- * NOTE: for PXA27x with overlays support, the LCCR3_PDFOR_x bits have an
- * implication of the acutal use of transparency bit, which we handle it
- * here separatedly. See PXA27x Developer's Manual, Section <<7.4.6 Pixel
- * Formats>> for the valid combination of PDFOR, PAL_FOR for various BPP.
- *
- * Transparency for palette pixel formats is not supported at the moment.
- */
-static uint32_t pxafb_var_to_lccr3(struct fb_info *info)
-{
- int bpp = pxafb_var_to_bpp(info);
- uint32_t lccr3;
-
- if (bpp < 0)
- return 0;
-
- lccr3 = LCCR3_BPP(bpp);
-
- switch (var_to_depth(info)) {
- case 16: lccr3 |= info->transp.length ? LCCR3_PDFOR_3 : 0; break;
- case 18: lccr3 |= LCCR3_PDFOR_3; break;
- case 24: lccr3 |= info->transp.length ? LCCR3_PDFOR_2 : LCCR3_PDFOR_3;
- break;
- case 19:
- case 25: lccr3 |= LCCR3_PDFOR_0; break;
- }
- return lccr3;
-}
-
-/*
- * Configures LCD Controller based on entries in fbi parameter.
- */
-static int pxafb_activate_var(struct pxafb_info *fbi)
-{
- struct fb_info *info = &fbi->info;
-
- setup_parallel_timing(fbi);
-
- setup_base_frame(fbi);
-
- fbi->reg_lccr0 = fbi->lccr0 |
- (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
- LCCR0_QDM | LCCR0_BM | LCCR0_OUM);
-
- fbi->reg_lccr3 |= pxafb_var_to_lccr3(info);
-
- fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK;
- fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
-
- return 0;
-}
-
-#define SET_PIXFMT(v, r, g, b) \
-({ \
- (v)->blue.length = (b); (v)->blue.offset = 0; \
- (v)->green.length = (g); (v)->green.offset = (b); \
- (v)->red.length = (r); (v)->red.offset = (b) + (g); \
-})
-
-/*
- * set the RGBT bitfields of fb_var_screeninf according to
- * var->bits_per_pixel and given depth
- */
-static void pxafb_set_pixfmt(struct fb_info *info)
-{
- if (info->bits_per_pixel < 16) {
- /* indexed pixel formats */
- info->red.offset = 0; info->red.length = 8;
- info->green.offset = 0; info->green.length = 8;
- info->blue.offset = 0; info->blue.length = 8;
- info->transp.offset = 0; info->transp.length = 8;
- }
-
- switch (info->bits_per_pixel) {
- case 16: SET_PIXFMT(info, 5, 6, 5); break; /* RGB565 */
- case 18: SET_PIXFMT(info, 6, 6, 6); break; /* RGB666 */
- case 24: SET_PIXFMT(info, 8, 8, 8); break; /* RGB888 */
- }
-}
-
-static void pxafb_decode_mach_info(struct pxafb_info *fbi,
- struct pxafb_platform_data *inf)
-{
- unsigned int lcd_conn = inf->lcd_conn;
-
- switch (lcd_conn & LCD_TYPE_MASK) {
- case LCD_TYPE_MONO_STN:
- fbi->lccr0 = LCCR0_CMS;
- break;
- case LCD_TYPE_MONO_DSTN:
- fbi->lccr0 = LCCR0_CMS | LCCR0_SDS;
- break;
- case LCD_TYPE_COLOR_STN:
- fbi->lccr0 = 0;
- break;
- case LCD_TYPE_COLOR_DSTN:
- fbi->lccr0 = LCCR0_SDS;
- break;
- case LCD_TYPE_COLOR_TFT:
- fbi->lccr0 = LCCR0_PAS;
- break;
- case LCD_TYPE_SMART_PANEL:
- fbi->lccr0 = LCCR0_LCDT | LCCR0_PAS;
- break;
- }
-
- if (lcd_conn == LCD_MONO_STN_8BPP)
- fbi->lccr0 |= LCCR0_DPD;
-
- fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
-
- fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff) |
- (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0 |
- (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0;
-
- pxafb_set_pixfmt(&fbi->info);
-}
-
-static struct fb_ops pxafb_ops = {
- .fb_enable = pxafb_enable_controller,
- .fb_disable = pxafb_disable_controller,
-};
-
-static int pxafb_probe(struct device *dev)
-{
- struct resource *iores;
- struct pxafb_platform_data *pdata = dev->platform_data;
- struct pxafb_info *fbi;
- struct fb_info *info;
- int ret;
-
- if (!pdata)
- return -ENODEV;
-
- fbi = xzalloc(sizeof(*fbi));
- info = &fbi->info;
-
- fbi->mode = pdata->mode;
- iores = dev_request_mem_resource(dev, 0);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
- fbi->regs = IOMEM(iores->start);
-
- fbi->dev = dev;
- fbi->lcd_power = pdata->lcd_power;
- fbi->backlight_power = pdata->backlight_power;
- info->mode = &pdata->mode->mode;
- info->fbops = &pxafb_ops;
-
- info->xres = pdata->mode->mode.xres;
- info->yres = pdata->mode->mode.yres;
- info->bits_per_pixel = pdata->mode->bpp;
-
- pxafb_decode_mach_info(fbi, pdata);
-
- dev_info(dev, "PXA Framebuffer driver\n");
-
- if (pdata->framebuffer)
- fbi->info.screen_base = pdata->framebuffer;
- else
- fbi->info.screen_base =
- PTR_ALIGN(dma_alloc_coherent(DMA_DEVICE_BROKEN,
- info->xres * info->yres *
- (info->bits_per_pixel >> 3) + PAGE_SIZE,
- DMA_ADDRESS_BROKEN),
- PAGE_SIZE);
-
- if (!fbi->info.screen_base)
- return -ENOMEM;
-
- fbi->dma_buff = PTR_ALIGN(dma_alloc_coherent(DMA_DEVICE_BROKEN,
- sizeof(struct pxafb_dma_buff) + 16,
- DMA_ADDRESS_BROKEN), 16);
- if (!fbi->dma_buff)
- return -ENOMEM;
-
- pxafb_activate_var(fbi);
-
- fbi->info.dev.parent = dev;
- ret = register_framebuffer(&fbi->info);
- if (ret < 0) {
- dev_err(dev, "failed to register framebuffer\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct driver pxafb_driver = {
- .name = "pxafb",
- .probe = pxafb_probe,
-};
-device_platform_driver(pxafb_driver);
diff --git a/include/mach/pxa/devices.h b/include/mach/pxa/devices.h
index e4d1d07091..e7aeeb35c6 100644
--- a/include/mach/pxa/devices.h
+++ b/include/mach/pxa/devices.h
@@ -13,11 +13,9 @@
*
*/
#include <i2c/i2c.h>
-#include <mach/pxa/pxafb.h>
struct device *pxa_add_i2c(void *base, int id,
struct i2c_platform_data *pdata);
struct device *pxa_add_uart(void *base, int id);
-struct device *pxa_add_fb(void *base, struct pxafb_platform_data *pdata);
struct device *pxa_add_mmc(void *base, int id, void *pdata);
struct device *pxa_add_pwm(void *base, int id);
diff --git a/include/mach/pxa/pxafb.h b/include/mach/pxa/pxafb.h
deleted file mode 100644
index 44ac3237a3..0000000000
--- a/include/mach/pxa/pxafb.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-/*
- * This structure describes the machine which we are running on.
- */
-#ifndef _PXAFB_
-#define _PXAFB_
-
-#include <fb.h>
-
-/*
- * Supported LCD connections
- *
- * bits 0 - 3: for LCD panel type:
- *
- * STN - for passive matrix
- * DSTN - for dual scan passive matrix
- * TFT - for active matrix
- *
- * bits 4 - 9 : for bus width
- * bits 10-17 : for AC Bias Pin Frequency
- * bit 18 : for output enable polarity
- * bit 19 : for pixel clock edge
- * bit 20 : for output pixel format when base is RGBT16
- */
-#define LCD_CONN_TYPE(_x) ((_x) & 0x0f)
-#define LCD_CONN_WIDTH(_x) (((_x) >> 4) & 0x1f)
-
-#define LCD_TYPE_MASK 0xf
-#define LCD_TYPE_UNKNOWN 0
-#define LCD_TYPE_MONO_STN 1
-#define LCD_TYPE_MONO_DSTN 2
-#define LCD_TYPE_COLOR_STN 3
-#define LCD_TYPE_COLOR_DSTN 4
-#define LCD_TYPE_COLOR_TFT 5
-#define LCD_TYPE_SMART_PANEL 6
-#define LCD_TYPE_MAX 7
-
-#define LCD_MONO_STN_4BPP ((4 << 4) | LCD_TYPE_MONO_STN)
-#define LCD_MONO_STN_8BPP ((8 << 4) | LCD_TYPE_MONO_STN)
-#define LCD_MONO_DSTN_8BPP ((8 << 4) | LCD_TYPE_MONO_DSTN)
-#define LCD_COLOR_STN_8BPP ((8 << 4) | LCD_TYPE_COLOR_STN)
-#define LCD_COLOR_DSTN_16BPP ((16 << 4) | LCD_TYPE_COLOR_DSTN)
-#define LCD_COLOR_TFT_8BPP ((8 << 4) | LCD_TYPE_COLOR_TFT)
-#define LCD_COLOR_TFT_16BPP ((16 << 4) | LCD_TYPE_COLOR_TFT)
-#define LCD_COLOR_TFT_18BPP ((18 << 4) | LCD_TYPE_COLOR_TFT)
-#define LCD_SMART_PANEL_8BPP ((8 << 4) | LCD_TYPE_SMART_PANEL)
-#define LCD_SMART_PANEL_16BPP ((16 << 4) | LCD_TYPE_SMART_PANEL)
-#define LCD_SMART_PANEL_18BPP ((18 << 4) | LCD_TYPE_SMART_PANEL)
-
-#define LCD_AC_BIAS_FREQ(x) (((x) & 0xff) << 10)
-#define LCD_BIAS_ACTIVE_HIGH (0 << 18)
-#define LCD_BIAS_ACTIVE_LOW (1 << 18)
-#define LCD_PCLK_EDGE_RISE (0 << 19)
-#define LCD_PCLK_EDGE_FALL (1 << 19)
-#define LCD_ALTERNATE_MAPPING (1 << 20)
-
-struct pxafb_videomode {
- struct fb_videomode mode;
- u8 bpp;
-};
-
-/**
- * Define relevant framebuffer information
- */
-struct pxafb_platform_data {
- struct pxafb_videomode *mode;
- unsigned int lcd_conn;
-
- /** force a memory area to be used, else NULL for dynamic allocation */
- void *framebuffer;
-
- void (*lcd_power)(int);
- void (*backlight_power)(int);
-};
-
-/**
- * @file
- * @brief PXA related framebuffer declarations
- */
-#endif
diff --git a/include/mach/pxa/regs-lcd.h b/include/mach/pxa/regs-lcd.h
deleted file mode 100644
index 4d473f23ae..0000000000
--- a/include/mach/pxa/regs-lcd.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_ARCH_REGS_LCD_H
-#define __ASM_ARCH_REGS_LCD_H
-
-/*
- * LCD Controller Registers and Bits Definitions
- */
-#define LCCR0 (0x000) /* LCD Controller Control Register 0 */
-#define LCCR1 (0x004) /* LCD Controller Control Register 1 */
-#define LCCR2 (0x008) /* LCD Controller Control Register 2 */
-#define LCCR3 (0x00C) /* LCD Controller Control Register 3 */
-#define LCCR4 (0x010) /* LCD Controller Control Register 4 */
-#define LCCR5 (0x014) /* LCD Controller Control Register 5 */
-#define LCSR (0x038) /* LCD Controller Status Register 0 */
-#define LCSR1 (0x034) /* LCD Controller Status Register 1 */
-#define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */
-#define TMEDRGBR (0x040) /* TMED RGB Seed Register */
-#define TMEDCR (0x044) /* TMED Control Register */
-
-#define FBR0 (0x020) /* DMA Channel 0 Frame Branch Register */
-#define FBR1 (0x024) /* DMA Channel 1 Frame Branch Register */
-#define FBR2 (0x028) /* DMA Channel 2 Frame Branch Register */
-#define FBR3 (0x02C) /* DMA Channel 2 Frame Branch Register */
-#define FBR4 (0x030) /* DMA Channel 2 Frame Branch Register */
-#define FBR5 (0x110) /* DMA Channel 2 Frame Branch Register */
-#define FBR6 (0x114) /* DMA Channel 2 Frame Branch Register */
-
-#define OVL1C1 (0x050) /* Overlay 1 Control Register 1 */
-#define OVL1C2 (0x060) /* Overlay 1 Control Register 2 */
-#define OVL2C1 (0x070) /* Overlay 2 Control Register 1 */
-#define OVL2C2 (0x080) /* Overlay 2 Control Register 2 */
-
-#define CMDCR (0x100) /* Command Control Register */
-#define PRSR (0x104) /* Panel Read Status Register */
-
-#define LCCR3_BPP(x) ((((x) & 0x7) << 24) | (((x) & 0x8) ? (1 << 29) : 0))
-
-#define LCCR3_PDFOR_0 (0 << 30)
-#define LCCR3_PDFOR_1 (1 << 30)
-#define LCCR3_PDFOR_2 (2 << 30)
-#define LCCR3_PDFOR_3 (3 << 30)
-
-#define LCCR4_PAL_FOR_0 (0 << 15)
-#define LCCR4_PAL_FOR_1 (1 << 15)
-#define LCCR4_PAL_FOR_2 (2 << 15)
-#define LCCR4_PAL_FOR_3 (3 << 15)
-#define LCCR4_PAL_FOR_MASK (3 << 15)
-
-#define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */
-#define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */
-#define FDADR2 (0x220) /* DMA Channel 2 Frame Descriptor Address Register */
-#define FDADR3 (0x230) /* DMA Channel 3 Frame Descriptor Address Register */
-#define FDADR4 (0x240) /* DMA Channel 4 Frame Descriptor Address Register */
-#define FDADR5 (0x250) /* DMA Channel 5 Frame Descriptor Address Register */
-#define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */
-
-#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
-#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */
-#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
-#define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */
-#define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display Select */
-#define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */
-#define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */
-
-#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */
-#define LCCR0_SFM (1 << 4) /* Start of frame mask */
-#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */
-#define LCCR0_EFM (1 << 6) /* End of Frame mask */
-#define LCCR0_PAS (1 << 7) /* Passive/Active display Select */
-#define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */
-#define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */
-#define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome) */
-#define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome display */
-#define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome display */
-#define LCCR0_DIS (1 << 10) /* LCD Disable */
-#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */
-#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */
-#define LCCR0_PDD_S 12
-#define LCCR0_BM (1 << 20) /* Branch mask */
-#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
-#define LCCR0_LCDT (1 << 22) /* LCD panel type */
-#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */
-#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */
-#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */
-#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */
-
-#define LCCR1_DisWdth(Pixel) (((Pixel) - 1) << 0) /* Pixels Per Line - 1 */
-#define LCCR1_HorSnchWdth(Tpix) (((Tpix) - 1) << 10) /* Horizontal Synchronization */
-#define LCCR1_EndLnDel(Tpix) (((Tpix) - 1) << 16) /* End-of-Line pixel clock Wait - 1 */
-#define LCCR1_BegLnDel(Tpix) (((Tpix) - 1) << 24) /* Beginning-of-Line pixel clock */
-
-#define LCCR2_DisHght(Line) (((Line) - 1) << 0) /* Line Per Panel - 1 */
-#define LCCR2_VrtSnchWdth(Tln) (((Tln) - 1) << 10) /* Vertical Synchronization pulse - 1 */
-#define LCCR2_EndFrmDel(Tln) ((Tln) << 16) /* End-of-Frame line clock Wait */
-#define LCCR2_BegFrmDel(Tln) ((Tln) << 24) /* Beginning-of-Frame line clock */
-
-#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */
-#define LCCR3_API_S 16
-#define LCCR3_VSP (1 << 20) /* vertical sync polarity */
-#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */
-#define LCCR3_PCP (1 << 22) /* Pixel Clock Polarity (L_PCLK) */
-#define LCCR3_PixRsEdg (LCCR3_PCP*0) /* Pixel clock Rising-Edge */
-#define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */
-
-#define LCCR3_OEP (1 << 23) /* Output Enable Polarity */
-#define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */
-#define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */
-
-#define LCCR3_DPC (1 << 27) /* double pixel clock mode */
-#define LCCR3_PixClkDiv(Div) ((Div) << 0) /* Pixel Clock Divisor */
-
-#define LCCR3_Acb(Acb) ((Acb) << 8) /* AC Bias */
-
-#define LCCR3_HorSnchH (LCCR3_HSP*0) /* HSP Active High */
-#define LCCR3_HorSnchL (LCCR3_HSP*1) /* HSP Active Low */
-
-#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* VSP Active High */
-#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* VSP Active Low */
-
-#define LCCR5_IUM(x) (1 << ((x) + 23)) /* input underrun mask */
-#define LCCR5_BSM(x) (1 << ((x) + 15)) /* branch mask */
-#define LCCR5_EOFM(x) (1 << ((x) + 7)) /* end of frame mask */
-#define LCCR5_SOFM(x) (1 << ((x) + 0)) /* start of frame mask */
-
-#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-#define LCSR_SOF (1 << 1) /* Start of frame */
-#define LCSR_BER (1 << 2) /* Bus error */
-#define LCSR_ABC (1 << 3) /* AC Bias count */
-#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-#define LCSR_OU (1 << 6) /* output FIFO underrun */
-#define LCSR_QD (1 << 7) /* quick disable */
-#define LCSR_EOF (1 << 8) /* end of frame */
-#define LCSR_BS (1 << 9) /* branch status */
-#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-#define LCSR_RD_ST (1 << 11) /* read status */
-#define LCSR_CMD_INT (1 << 12) /* command interrupt */
-
-#define LCSR1_IU(x) (1 << ((x) + 23)) /* Input FIFO underrun */
-#define LCSR1_BS(x) (1 << ((x) + 15)) /* Branch Status */
-#define LCSR1_EOF(x) (1 << ((x) + 7)) /* End of Frame Status */
-#define LCSR1_SOF(x) (1 << ((x) - 1)) /* Start of Frame Status */
-
-#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-#define LDCMD_EOFINT (1 << 21) /* End of Frame Interrupt */
-
-/* overlay control registers */
-#define OVLxC1_PPL(x) ((((x) - 1) & 0x3ff) << 0) /* Pixels Per Line */
-#define OVLxC1_LPO(x) ((((x) - 1) & 0x3ff) << 10) /* Number of Lines */
-#define OVLxC1_BPP(x) (((x) & 0xf) << 20) /* Bits Per Pixel */
-#define OVLxC1_OEN (1 << 31) /* Enable bit for Overlay */
-#define OVLxC2_XPOS(x) (((x) & 0x3ff) << 0) /* Horizontal Position */
-#define OVLxC2_YPOS(x) (((x) & 0x3ff) << 10) /* Vertical Position */
-#define OVL2C2_PFOR(x) (((x) & 0x7) << 20) /* Pixel Format */
-
-/* smartpanel related */
-#define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */
-#define PRSR_A0 (1 << 8) /* Read Data Source */
-#define PRSR_ST_OK (1 << 9) /* Status OK */
-#define PRSR_CON_NT (1 << 10) /* Continue to Next Command */
-
-#define SMART_CMD_A0 (0x1 << 8)
-#define SMART_CMD_READ_STATUS_REG (0x0 << 9)
-#define SMART_CMD_READ_FRAME_BUFFER ((0x0 << 9) | SMART_CMD_A0)
-#define SMART_CMD_WRITE_COMMAND (0x1 << 9)
-#define SMART_CMD_WRITE_DATA ((0x1 << 9) | SMART_CMD_A0)
-#define SMART_CMD_WRITE_FRAME ((0x2 << 9) | SMART_CMD_A0)
-#define SMART_CMD_WAIT_FOR_VSYNC (0x3 << 9)
-#define SMART_CMD_NOOP (0x4 << 9)
-#define SMART_CMD_INTERRUPT (0x5 << 9)
-
-#define SMART_CMD(x) (SMART_CMD_WRITE_COMMAND | ((x) & 0xff))
-#define SMART_DAT(x) (SMART_CMD_WRITE_DATA | ((x) & 0xff))
-
-/* SMART_DELAY() is introduced for software controlled delay primitive which
- * can be inserted between command sequences, unused command 0x6 is used here
- * and delay ranges from 0ms ~ 255ms
- */
-#define SMART_CMD_DELAY (0x6 << 9)
-#define SMART_DELAY(ms) (SMART_CMD_DELAY | ((ms) & 0xff))
-#endif /* __ASM_ARCH_REGS_LCD_H */
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
2026-08-16 17:56 ` [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support Sascha Hauer
2026-08-16 17:56 ` [PATCH 02/27] video: remove the PXA framebuffer driver Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 04/27] mci: pxamci: get the clock from the clk API Sascha Hauer
` (25 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
XSC3 reports ARMv5TE and is dispatched to the ARMv5 cache functions
accordingly, where v5_mmu_cache_flush() cleans the D-cache with
1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
bne 1b
XSC3 does not implement that operation - Linux' xsc3_flush_kern_cache_all()
uses a set/way loop instead - so the condition flags never come back with
the cache reported clean and the loop does not end. The board hangs in
sync_caches_for_execution(), between the PBL and barebox proper, before
anything has been printed.
The ARMv4 functions flush by reading through the cache and use nothing
XScale is missing, so send XSC3 there.
This only shows up in a build that has another ARMv5 core in it, which is
why the PXA board defconfigs are unaffected and multi_v5_v6_defconfig
hangs. On its own CONFIG_CPU_XSC3 selects CPU_32v4T and no other CPU_32v*,
so ARM_MULTIARCH is never defined, cpu_architecture() is the compile time
constant CPU_ARCH_ARMv4T, and the same functions are reached by accident.
Add an ARM926 or an ARM1176 to the config and the runtime detection takes
over, correctly returns ARMv5TE, and picks code the core cannot run.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/cpu/cache_32.c | 31 +++++++++++++++++++++++++++++++
arch/arm/include/asm/system_info.h | 9 +++++++++
2 files changed, 40 insertions(+)
diff --git a/arch/arm/cpu/cache_32.c b/arch/arm/cpu/cache_32.c
index 0ac50c4d9a..e82cd212d2 100644
--- a/arch/arm/cpu/cache_32.c
+++ b/arch/arm/cpu/cache_32.c
@@ -39,10 +39,35 @@ DEFINE_CPU_FNS(v5)
DEFINE_CPU_FNS(v6)
DEFINE_CPU_FNS(v7)
+/*
+ * XSC3 reports ARMv5TE, and it is - but its cache is not the one the ARMv5
+ * code drives. v5_mmu_cache_flush() cleans the D-cache with the ARM926
+ * test-and-clean operation (c7, c14, 3), which XSC3 does not implement, so
+ * the loop waiting for it to report the cache clean never ends. The ARMv4
+ * code flushes by reading through the cache instead and uses nothing XScale
+ * is missing, so send these cores there.
+ *
+ * This only ever comes up in a build that has another ARMv5 core in it. On
+ * its own CPU_XSC3 selects CPU_32v4T and no other CPU_32v*, which leaves
+ * cpu_architecture() a compile time ARMv4T and lands on the same functions
+ * by accident.
+ */
+static struct cache_fns *cache_fns_by_core(void)
+{
+ if (IS_ENABLED(CONFIG_CPU_32v4T) && cpu_is_xsc3())
+ return &cache_fns_armv4;
+
+ return NULL;
+}
+
static struct cache_fns *cache_functions(void)
{
static struct cache_fns *cache_fns;
+ if (cache_fns)
+ return cache_fns;
+
+ cache_fns = cache_fns_by_core();
if (cache_fns)
return cache_fns;
@@ -119,6 +144,12 @@ void __mmu_cache_flush(void)
*/
void arm_early_mmu_cache_flush(void)
{
+ /* see cache_fns_by_core() */
+ if (IS_ENABLED(CONFIG_CPU_32v4T) && cpu_is_xsc3()) {
+ v4_mmu_cache_flush();
+ return;
+ }
+
switch (arm_early_get_cpu_architecture()) {
#ifdef CONFIG_CPU_32v4T
case CPU_ARCH_ARMv4T:
diff --git a/arch/arm/include/asm/system_info.h b/arch/arm/include/asm/system_info.h
index 5a84fde75b..1fde203063 100644
--- a/arch/arm/include/asm/system_info.h
+++ b/arch/arm/include/asm/system_info.h
@@ -59,6 +59,9 @@
#define CPU_IS_PXA270 0x69054110
#define CPU_IS_PXA270_MASK 0xfffff7f0
+#define CPU_IS_XSC3 0x69056000
+#define CPU_IS_XSC3_MASK 0xffffe000
+
#define cpu_is_arm(core) ((read_cpuid_id() & CPU_IS_##core##_MASK) == CPU_IS_##core)
#ifdef CONFIG_CPU_32v4T
@@ -80,6 +83,12 @@
#define cpu_is_pxa270() (0)
#endif
+#ifdef CONFIG_CPU_XSC3
+#define cpu_is_xsc3() cpu_is_arm(XSC3)
+#else
+#define cpu_is_xsc3() (0)
+#endif
+
#ifdef CONFIG_CPU_32v5
#ifdef ARM_ARCH
#define ARM_MULTIARCH
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 04/27] mci: pxamci: get the clock from the clk API
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (2 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 05/27] pwm: pxa: " Sascha Hauer
` (24 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The driver enabled its clock by poking CKEN directly and asked
pxa_get_mmcclk() for the rate. Use the clk api to handle the clocks.
A clk driver for PXA is not yet present in the tree, but PXA has
no board support currently, so we can safely break bisectability
here.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mci/Kconfig | 4 ++--
drivers/mci/pxamci.c | 25 +++++++++++++++----------
drivers/mci/pxamci.h | 1 +
3 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 55e63aad92..2c3365e723 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -192,10 +192,10 @@ config MCI_OMAP_HSMMC
config MCI_PXA
bool "PXA"
- depends on ARCH_PXA2XX
+ depends on ARCH_PXA
help
Enable this entry to add support to read and write SD cards on a
- XScale PXA25x / PXA27x based system.
+ XScale PXA3xx based system.
config MCI_ATMEL
bool "ATMEL (AT91)"
diff --git a/drivers/mci/pxamci.c b/drivers/mci/pxamci.c
index 1f2aaf2031..5e26022729 100644
--- a/drivers/mci/pxamci.c
+++ b/drivers/mci/pxamci.c
@@ -14,8 +14,8 @@
#include <init.h>
#include <mci.h>
#include <linux/err.h>
+#include <linux/clk.h>
-#include <mach/pxa/clock.h>
#include <mach/pxa/mci_pxa2xx.h>
#include <mach/pxa/pxa-regs.h>
#include "pxamci.h"
@@ -26,11 +26,6 @@
#define TX_TIMEOUT (250 * MSECOND)
#define CMD_TIMEOUT (100 * MSECOND)
-static void mmc_clk_enable(void)
-{
- CKEN |= CKEN_MMC;
-}
-
static int pxamci_set_power(struct pxamci_host *host, int on)
{
mci_dbg("on=%d\n", on);
@@ -272,7 +267,7 @@ static int pxamci_request(struct mci_host *mci, struct mci_cmd *cmd)
static void pxamci_set_ios(struct mci_host *mci, struct mci_ios *ios)
{
struct pxamci_host *host = to_pxamci(mci);
- unsigned int clk_in = pxa_get_mmcclk();
+ unsigned int clk_in = clk_get_rate(host->clk);
int fact;
mci_dbg("bus_width=%d, clock=%u\n", ios->bus_width, ios->clock);
@@ -326,15 +321,24 @@ static int pxamci_probe(struct device *dev)
{
struct resource *iores;
struct pxamci_host *host;
+ unsigned long rate;
int gpio_power = -1;
+ int ret;
- mmc_clk_enable();
host = xzalloc(sizeof(*host));
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
return PTR_ERR(iores);
host->base = IOMEM(iores->start);
+ host->clk = clk_get(dev, NULL);
+ if (IS_ERR(host->clk))
+ return PTR_ERR(host->clk);
+
+ ret = clk_enable(host->clk);
+ if (ret)
+ return ret;
+
host->mci.ops = pxamci_ops;
host->mci.host_caps = MMC_CAP_4_BIT_DATA;
host->mci.hw_dev = dev;
@@ -343,8 +347,9 @@ static int pxamci_probe(struct device *dev)
/*
* Calculate minimum clock rate, rounding up.
*/
- host->mci.f_min = pxa_get_mmcclk() >> 6;
- host->mci.f_max = pxa_get_mmcclk();
+ rate = clk_get_rate(host->clk);
+ host->mci.f_min = rate >> 6;
+ host->mci.f_max = rate;
/*
* Ensure that the host controller is shut down, and setup
diff --git a/drivers/mci/pxamci.h b/drivers/mci/pxamci.h
index 3dd93cb267..30119a5607 100644
--- a/drivers/mci/pxamci.h
+++ b/drivers/mci/pxamci.h
@@ -78,6 +78,7 @@ struct pxamci_host {
struct mci_host mci;
void __iomem *base;
struct pxamci_platform_data *pdata;
+ struct clk *clk;
unsigned int cmdat;
int clkrt;
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 05/27] pwm: pxa: get the clock from the clk API
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (3 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 04/27] mci: pxamci: get the clock from the clk API Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 06/27] serial: " Sascha Hauer
` (23 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The driver enabled and disabled its clock by poking CKEN and asked
pxa_get_pwmclk() for the rate. Use the clk api to handle the clocks.
A clk driver for PXA is not yet present in the tree, but PXA has
no board support currently, so we can safely break bisectability
here.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pwm/Kconfig | 7 +++----
drivers/pwm/pxa_pwm.c | 38 ++++++++++----------------------------
2 files changed, 13 insertions(+), 32 deletions(-)
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 85cde63bf6..33e1da8aef 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -11,11 +11,10 @@ menuconfig PWM
if PWM
config PWM_PXA
bool "PXA PWM Support"
- default y if ARCH_PXA2XX
- depends on ARCH_PXA2XX
+ default y if ARCH_PXA
+ depends on ARCH_PXA
help
- This enables PWM support for Intel/Marvell PXA chips, such
- as the PXA25x, PXA27x.
+ This enables PWM support for Intel/Marvell PXA chips.
config PWM_ATMEL
bool "Atmel PWM Support"
diff --git a/drivers/pwm/pxa_pwm.c b/drivers/pwm/pxa_pwm.c
index 42ccb37b9a..a70661d164 100644
--- a/drivers/pwm/pxa_pwm.c
+++ b/drivers/pwm/pxa_pwm.c
@@ -14,11 +14,11 @@
#include <pwm.h>
#include <mach/pxa/hardware.h>
-#include <mach/pxa/clock.h>
#include <mach/pxa/pxa-regs.h>
#include <mach/pxa/regs-pwm.h>
#include <linux/math64.h>
#include <linux/compiler.h>
+#include <linux/clk.h>
/* PWM registers and bits definitions */
#define PWMCR (0x00)
@@ -31,6 +31,7 @@
struct pxa_pwm_chip {
struct pwm_chip chip;
void __iomem *iobase;
+ struct clk *clk;
int id;
};
@@ -41,35 +42,12 @@ static struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
static int pxa_pwm_enable(struct pxa_pwm_chip *pxa_pwm)
{
- switch (pxa_pwm->id) {
- case 0:
- case 2:
- CKEN |= CKEN_PWM0;
- break;
- case 1:
- case 3:
- CKEN |= CKEN_PWM1;
- break;
- default:
- return -EINVAL;
- }
- return 0;
+ return clk_enable(pxa_pwm->clk);
}
static void pxa_pwm_disable(struct pxa_pwm_chip *pxa_pwm)
{
- switch (pxa_pwm->id) {
- case 0:
- case 2:
- CKEN &= ~CKEN_PWM0;
- break;
- case 1:
- case 3:
- CKEN &= ~CKEN_PWM1;
- break;
- default:
- break;
- }
+ clk_disable(pxa_pwm->clk);
}
/*
@@ -93,7 +71,7 @@ static int pxa_pwm_apply(struct pwm_chip *chip,
return 0;
}
- c = pxa_get_pwmclk();
+ c = clk_get_rate(pxa_pwm->clk);
c = c * state->period;
do_div(c, 1000000000);
period_cycles = c;
@@ -142,6 +120,11 @@ static int pxa_pwm_probe(struct device *dev)
if (IS_ERR(iores))
return PTR_ERR(iores);
chip->iobase = IOMEM(iores->start);
+
+ chip->clk = clk_get(dev, NULL);
+ if (IS_ERR(chip->clk))
+ return PTR_ERR(chip->clk);
+
chip->id = dev->id;
chip->chip.dev = dev;
dev->priv = chip;
@@ -156,7 +139,6 @@ static struct driver pxa_pwm_driver = {
static int __init pxa_pwm_init_driver(void)
{
- CKEN &= ~CKEN_PWM0 & ~CKEN_PWM1;
platform_driver_register(&pxa_pwm_driver);
return 0;
}
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 06/27] serial: pxa: get the clock from the clk API
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (4 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 05/27] pwm: pxa: " Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 07/27] clk: pxa: add a device tree clock driver for PXA3xx Sascha Hauer
` (22 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
pxa_get_uartclk() was a per SoC constant, and the PXA25x and PXA27x
versions of it are gone. Use the clk api to handle clocks.
A clk driver for PXA is not yet present in the tree, but PXA has
no board support currently, so we can safely break bisectability
here.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/serial/serial_pxa.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index 97342f923e..a0bebef811 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -9,7 +9,7 @@
#include <init.h>
#include <malloc.h>
-#include <mach/pxa/clock.h>
+#include <linux/clk.h>
#include <asm/io.h>
#define RBR 0x00 /* Receive Buffer Register (read only) */
@@ -90,6 +90,7 @@
struct pxa_serial_priv {
void __iomem *regs;
struct console_device cdev;
+ struct clk *clk;
};
static void __iomem *to_regs(struct console_device *cdev)
@@ -124,6 +125,8 @@ static void pxa_serial_flush(struct console_device *cdev)
static int pxa_serial_setbaudrate(struct console_device *cdev, int baudrate)
{
+ struct pxa_serial_priv *priv =
+ container_of(cdev, struct pxa_serial_priv, cdev);
unsigned char cval = LCR_WLEN8; /* 8N1 */
unsigned int quot;
@@ -131,7 +134,7 @@ static int pxa_serial_setbaudrate(struct console_device *cdev, int baudrate)
writel(IER_UUE, to_regs(cdev) + IER);
/* write divisor */
- quot = (pxa_get_uartclk() + (8 * baudrate)) / (16 * baudrate);
+ quot = (clk_get_rate(priv->clk) + (8 * baudrate)) / (16 * baudrate);
writel(cval | LCR_DLAB, to_regs(cdev) + LCR); /* set DLAB */
writel(quot & 0xff, to_regs(cdev) + DLL);
@@ -154,6 +157,7 @@ static int pxa_serial_probe(struct device *dev)
struct resource *iores;
struct console_device *cdev;
struct pxa_serial_priv *priv;
+ int ret;
priv = xzalloc(sizeof(*priv));
cdev = &priv->cdev;
@@ -162,6 +166,14 @@ static int pxa_serial_probe(struct device *dev)
return PTR_ERR(iores);
priv->regs = IOMEM(iores->start);
+ priv->clk = clk_get(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ ret = clk_enable(priv->clk);
+ if (ret)
+ return ret;
+
dev->priv = priv;
cdev->dev = dev;
cdev->tstc = pxa_serial_tstc;
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 07/27] clk: pxa: add a device tree clock driver for PXA3xx
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (5 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 06/27] serial: " Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config Sascha Hauer
` (21 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
barebox had no clock driver for the "marvell,pxa300-clocks" node the
device tree points every PXA3xx peripheral at. arch/arm/mach-pxa/speed-*
instead hardcoded a few rates and handed them out through non-device-tree
means: pxa_get_uartclk() and friends, plus a fixed "nand" clock that had
to be registered by physical base address to be found at all.
Port the clock driver from Linux, so the clocks come from the device tree
like on every other architecture. With the drivers converted to the clk
API in the previous commits, speed-pxa3xx.c and mach/pxa/clock.h have no
users left and go away with it.
Two things had to be adapted from the kernel:
- barebox's clk_hw embeds the struct clk itself and
clk_hw_register_composite() writes the ops into it, so the mux and the
rate half of a CKEN clock cannot share one clk_hw the way they do in
Linux -- the second assignment overwrites the ops of the first. Give
them one each.
- barebox has no .determine_rate, so the read-only muxes only implement
.get_parent. .set_parent still has to be there because the core will
not register a mux without one.
Everything the bootloader has no use for -- frequency changing, the
cpufreq helpers and pxa3xx_get_clk_frequency_khz() -- has been left out.
The clock ids come from dt-bindings/clock/pxa-clock.h, which the dts
directory already carries.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/Kconfig | 1 +
arch/arm/mach-pxa/Makefile | 2 +-
arch/arm/mach-pxa/speed-pxa3xx.c | 43 -----
drivers/clk/Makefile | 1 +
drivers/clk/pxa/Makefile | 3 +
drivers/clk/pxa/clk-pxa.c | 122 +++++++++++++
drivers/clk/pxa/clk-pxa.h | 118 +++++++++++++
drivers/clk/pxa/clk-pxa3xx.c | 357 +++++++++++++++++++++++++++++++++++++++
include/mach/pxa/clock.h | 19 ---
9 files changed, 603 insertions(+), 63 deletions(-)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 3a58736d2d..738fa7d9bb 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -10,6 +10,7 @@ config ARCH_PXA3XX
select CPU_XSC3
select HAVE_CLK
select COMMON_CLK
+ select COMMON_CLK_OF_PROVIDER
config ARCH_PXA310
bool
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index fbcc4b8859..b4f3a51046 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -6,4 +6,4 @@ obj-y += common.o
obj-y += gpio.o
obj-y += devices.o
-obj-$(CONFIG_ARCH_PXA3XX) += speed-pxa3xx.o mfp-pxa3xx.o pxa3xx.o
+obj-$(CONFIG_ARCH_PXA3XX) += mfp-pxa3xx.o pxa3xx.o
diff --git a/arch/arm/mach-pxa/speed-pxa3xx.c b/arch/arm/mach-pxa/speed-pxa3xx.c
deleted file mode 100644
index 2579966f41..0000000000
--- a/arch/arm/mach-pxa/speed-pxa3xx.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * clock.h - implementation of the PXA clock functions
- *
- * Copyright (C) 2014 by Robert Jarzmik <robert.jarzmik@free.fr>
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <common.h>
-#include <init.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <mach/pxa/clock.h>
-#include <mach/pxa/pxa-regs.h>
-
-/* Crystal clock: 13MHz */
-#define BASE_CLK 13000000
-
-unsigned long pxa_get_uartclk(void)
-{
- return 14857000;
-}
-
-unsigned long pxa_get_pwmclk(void)
-{
- return BASE_CLK;
-}
-
-static int pxa3xx_clock_init(void)
-{
- unsigned long nand_rate = (cpu_is_pxa320()) ? 104000000 : 156000000;
- struct clk *clk;
- int ret;
-
- clk = clk_fixed("nand", nand_rate);
- ret = clk_register_clkdev(clk, NULL, "nand");
- if (ret)
- return ret;
-
- return 0;
-}
-postcore_initcall(pxa3xx_clock_init);
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 4fda2c1e0d..3653bb63be 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -33,3 +33,4 @@ obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
obj-$(CONFIG_COMMON_CLK_GPIO) += clk-gpio.o
obj-$(CONFIG_TI_SCI_CLK) += ti-sci-clk.o
obj-$(CONFIG_ARCH_K3) += k3/
+obj-$(CONFIG_ARCH_PXA) += pxa/
diff --git a/drivers/clk/pxa/Makefile b/drivers/clk/pxa/Makefile
new file mode 100644
index 0000000000..60ecde7aaf
--- /dev/null
+++ b/drivers/clk/pxa/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += clk-pxa.o
+obj-$(CONFIG_ARCH_PXA3XX) += clk-pxa3xx.o
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c
new file mode 100644
index 0000000000..b5b6c88231
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Marvell PXA family clocks
+ *
+ * Copyright (C) 2014 Robert Jarzmik
+ *
+ * Common clock code for PXA clocks ("CKEN" type clocks + DT)
+ *
+ * Ported from the Linux kernel.
+ */
+#include <common.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <of.h>
+
+#include <dt-bindings/clock/pxa-clock.h>
+#include "clk-pxa.h"
+
+static struct clk *pxa_clocks[CLK_MAX];
+static struct clk_onecell_data onecell_data = {
+ .clks = pxa_clocks,
+ .clk_num = CLK_MAX,
+};
+
+/*
+ * Unlike Linux, barebox's clk_hw embeds the struct clk itself and
+ * clk_hw_register_composite() stores the ops in it, so the mux and the rate
+ * part cannot share one clk_hw: the second assignment would overwrite the
+ * ops of the first.
+ */
+struct pxa_clk {
+ struct clk_hw mux_hw;
+ struct clk_hw rate_hw;
+ struct clk_fixed_factor lp;
+ struct clk_fixed_factor hp;
+ struct clk_gate gate;
+ bool (*is_in_low_power)(void);
+};
+
+#define mux_to_pxa_clk(_hw) container_of(_hw, struct pxa_clk, mux_hw)
+#define rate_to_pxa_clk(_hw) container_of(_hw, struct pxa_clk, rate_hw)
+
+static unsigned long cken_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct pxa_clk *pclk = rate_to_pxa_clk(hw);
+ struct clk_fixed_factor *fix;
+
+ if (!pclk->is_in_low_power || pclk->is_in_low_power())
+ fix = &pclk->lp;
+ else
+ fix = &pclk->hp;
+
+ /*
+ * barebox's fixed factor only looks at mult and div, so unlike in
+ * Linux there is no need to point the embedded clk_hw at our parent
+ * first.
+ */
+ return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate);
+}
+
+static const struct clk_ops cken_rate_ops = {
+ .recalc_rate = cken_recalc_rate,
+};
+
+static int cken_get_parent(struct clk_hw *hw)
+{
+ struct pxa_clk *pclk = mux_to_pxa_clk(hw);
+
+ if (!pclk->is_in_low_power)
+ return 0;
+ return pclk->is_in_low_power() ? 0 : 1;
+}
+
+static const struct clk_ops cken_mux_ops = {
+ .get_parent = cken_get_parent,
+ .set_parent = dummy_clk_set_parent,
+};
+
+void clkdev_pxa_register(int ckid, const char *con_id, const char *dev_id,
+ struct clk *clk)
+{
+ if (!IS_ERR(clk) && (ckid != CLK_NONE))
+ pxa_clocks[ckid] = clk;
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, con_id, dev_id);
+}
+
+int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks,
+ void __iomem *clk_regs)
+{
+ struct pxa_clk *pxa_clk;
+ struct clk_hw *hw;
+ int i;
+
+ for (i = 0; i < nb_clks; i++) {
+ pxa_clk = xzalloc(sizeof(*pxa_clk));
+ pxa_clk->is_in_low_power = clks[i].is_in_low_power;
+ pxa_clk->lp = clks[i].lp;
+ pxa_clk->hp = clks[i].hp;
+ pxa_clk->gate = clks[i].gate;
+ pxa_clk->gate.reg = clk_regs + clks[i].cken_reg;
+
+ hw = clk_hw_register_composite(NULL, clks[i].name,
+ clks[i].parent_names, 2,
+ &pxa_clk->mux_hw, &cken_mux_ops,
+ &pxa_clk->rate_hw, &cken_rate_ops,
+ &pxa_clk->gate.hw, &clk_gate_ops,
+ clks[i].flags);
+ clkdev_pxa_register(clks[i].ckid, clks[i].con_id,
+ clks[i].dev_id, clk_hw_to_clk(hw));
+ }
+
+ return 0;
+}
+
+int clk_pxa_dt_common_init(struct device_node *np)
+{
+ return of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
+}
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
new file mode 100644
index 0000000000..f0fef5245c
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Marvell PXA family clocks
+ *
+ * Copyright (C) 2014 Robert Jarzmik
+ *
+ * Common clock code for PXA clocks ("CKEN" type clocks + DT)
+ *
+ * Ported from the Linux kernel.
+ */
+#ifndef _CLK_PXA_
+#define _CLK_PXA_
+
+#define PARENTS(name) \
+ static const char *const name ## _parents[]
+
+/*
+ * Unlike Linux, barebox's clk core has no .determine_rate, and it never
+ * changes a parent behind the driver's back, so the read-only muxes below
+ * only need .get_parent. .set_parent still has to exist because the core
+ * refuses to register a mux without one.
+ */
+#define MUX_RO_RATE_RO_OPS(name, clk_name) \
+ static struct clk_hw name ## _mux_hw; \
+ static struct clk_hw name ## _rate_hw; \
+ static const struct clk_ops name ## _mux_ops = { \
+ .get_parent = name ## _get_parent, \
+ .set_parent = dummy_clk_set_parent, \
+ }; \
+ static const struct clk_ops name ## _rate_ops = { \
+ .recalc_rate = name ## _get_rate, \
+ }; \
+ static struct clk *clk_register_ ## name(void) \
+ { \
+ return clk_hw_to_clk(clk_hw_register_composite(NULL, \
+ clk_name, \
+ name ## _parents, \
+ ARRAY_SIZE(name ## _parents), \
+ &name ## _mux_hw, &name ## _mux_ops, \
+ &name ## _rate_hw, &name ## _rate_ops, \
+ NULL, NULL, CLK_GET_RATE_NOCACHE)); \
+ }
+
+#define RATE_RO_OPS(name, clk_name) \
+ static struct clk_hw name ## _rate_hw; \
+ static const struct clk_ops name ## _rate_ops = { \
+ .recalc_rate = name ## _get_rate, \
+ }; \
+ static struct clk *clk_register_ ## name(void) \
+ { \
+ return clk_hw_to_clk(clk_hw_register_composite(NULL, \
+ clk_name, \
+ name ## _parents, \
+ ARRAY_SIZE(name ## _parents), \
+ NULL, NULL, \
+ &name ## _rate_hw, &name ## _rate_ops, \
+ NULL, NULL, CLK_GET_RATE_NOCACHE)); \
+ }
+
+/*
+ * CKEN clock type
+ * This clock takes it source from 2 possible parents :
+ * - a low power parent
+ * - a normal parent
+ *
+ * +------------+ +-----------+
+ * | Low Power | --- | x mult_lp |
+ * | Clock | | / div_lp |\
+ * +------------+ +-----------+ \+-----+ +-----------+
+ * | Mux |---| CKEN gate |
+ * +------------+ +-----------+ /+-----+ +-----------+
+ * | High Power | | x mult_hp |/
+ * | Clock | --- | / div_hp |
+ * +------------+ +-----------+
+ */
+struct desc_clk_cken {
+ struct clk_hw hw;
+ int ckid;
+ int cken_reg;
+ const char *name;
+ const char *dev_id;
+ const char *con_id;
+ const char * const *parent_names;
+ struct clk_fixed_factor lp;
+ struct clk_fixed_factor hp;
+ struct clk_gate gate;
+ bool (*is_in_low_power)(void);
+ const unsigned long flags;
+};
+
+#define PXA_CKEN(_dev_id, _con_id, _name, parents, _mult_lp, _div_lp, \
+ _mult_hp, _div_hp, is_lp, _cken_reg, _cken_bit, flag) \
+ { .ckid = CLK_ ## _name, .name = #_name, \
+ .cken_reg = _cken_reg, \
+ .dev_id = _dev_id, .con_id = _con_id, .parent_names = parents,\
+ .lp = { .mult = _mult_lp, .div = _div_lp }, \
+ .hp = { .mult = _mult_hp, .div = _div_hp }, \
+ .is_in_low_power = is_lp, \
+ .gate = { .bit_idx = _cken_bit }, \
+ .flags = flag, \
+ }
+#define PXA_CKEN_1RATE(dev_id, con_id, name, parents, cken_reg, \
+ cken_bit, flag) \
+ PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \
+ NULL, cken_reg, cken_bit, flag)
+
+static inline int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ return 0;
+}
+
+void clkdev_pxa_register(int ckid, const char *con_id, const char *dev_id,
+ struct clk *clk);
+int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks,
+ void __iomem *clk_regs);
+int clk_pxa_dt_common_init(struct device_node *np);
+
+#endif
diff --git a/drivers/clk/pxa/clk-pxa3xx.c b/drivers/clk/pxa/clk-pxa3xx.c
new file mode 100644
index 0000000000..1ef72120ac
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa3xx.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Marvell PXA3xxx family clocks
+ *
+ * Copyright (C) 2014 Robert Jarzmik
+ *
+ * Heavily inspired from former arch/arm/mach-pxa/pxa3xx.c
+ *
+ * Ported from the Linux kernel. Everything the bootloader cannot make use
+ * of -- frequency changing, the cpufreq helpers and the clocks feeding
+ * peripherals barebox has no driver for -- has been left out.
+ */
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <of.h>
+#include <mach/pxa/hardware.h>
+
+#include <dt-bindings/clock/pxa-clock.h>
+#include "clk-pxa.h"
+
+#define KHz 1000
+#define MHz (1000 * 1000)
+
+#define ACCR (0x0000) /* Application Subsystem Clock Configuration */
+#define ACSR (0x0004) /* Application Subsystem Clock Status */
+#define CKENA (0x000C) /* A Clock Enable Register */
+#define CKENB (0x0010) /* B Clock Enable Register */
+#define AC97_DIV (0x0014) /* AC97 clock divisor value register */
+
+/*
+ * Static memory controller. pxa3xx-regs.h has this, but it also has
+ * ACCR/ACSR/CKENA/CKENB as absolute addresses, which collide with the
+ * offsets above, so take just the one register we need.
+ */
+#define MEMCLKCFG 0x4a000068
+
+#define ACCR_D0CS (1 << 26) /* D0 Mode Clock Select */
+#define ACCR_XN_MASK (0x7 << 8) /* Core PLL Turbo-to-Run Ratio */
+#define ACCR_XL_MASK (0x1f) /* Core PLL Run-to-Oscillator Ratio */
+
+/*
+ * Clock Enable Bit
+ */
+#define CKEN_LCD 1 /* < LCD Clock Enable */
+#define CKEN_USBH 2 /* < USB host clock enable */
+#define CKEN_CAMERA 3 /* < Camera interface clock enable */
+#define CKEN_NAND 4 /* < NAND Flash Controller Clock Enable */
+#define CKEN_USB2 6 /* < USB 2.0 client clock enable. */
+#define CKEN_SMC 9 /* < Static Memory Controller clock enable */
+#define CKEN_MMC1 12 /* < MMC1 Clock enable */
+#define CKEN_MMC2 13 /* < MMC2 clock enable */
+#define CKEN_KEYPAD 14 /* < Keypand Controller Clock Enable */
+#define CKEN_UDC 20 /* < UDC clock enable */
+#define CKEN_BTUART 21 /* < BTUART clock enable */
+#define CKEN_FFUART 22 /* < FFUART clock enable */
+#define CKEN_STUART 23 /* < STUART clock enable */
+#define CKEN_AC97 24 /* < AC97 clock enable */
+#define CKEN_SSP1 26 /* < SSP1 clock enable */
+#define CKEN_SSP2 27 /* < SSP2 clock enable */
+#define CKEN_SSP3 28 /* < SSP3 clock enable */
+#define CKEN_SSP4 29 /* < SSP4 clock enable */
+#define CKEN_PWM0 32 /* < PWM[0] clock enable */
+#define CKEN_PWM1 33 /* < PWM[1] clock enable */
+#define CKEN_I2C 36 /* < I2C clock enable */
+#define CKEN_GPIO 39 /* < GPIO clock enable */
+#define CKEN_MMC3 5 /* < MMC3 Clock Enable */
+#define CKEN_PXA300_GCU 42 /* Graphics controller clock enable */
+#define CKEN_PXA320_GCU 7 /* Graphics controller clock enable */
+
+enum {
+ PXA_CORE_60Mhz = 0,
+ PXA_CORE_RUN,
+ PXA_CORE_TURBO,
+};
+
+enum {
+ PXA_BUS_60Mhz = 0,
+ PXA_BUS_HSS,
+};
+
+/* crystal frequency to HSIO bus frequency multiplier (HSS) */
+static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
+
+/* crystal frequency to static memory controller multiplier (SMCFS) */
+static unsigned int smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
+static const unsigned int df_clkdiv[4] = { 1, 2, 4, 1 };
+
+static void __iomem *clk_regs;
+
+static unsigned int pxa3xx_smemc_get_memclkdiv(void)
+{
+ return df_clkdiv[(readl(IOMEM(MEMCLKCFG)) >> 16) & 0x3];
+}
+
+static unsigned long clk_pxa3xx_ac97_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long ac97_div, rate;
+
+ ac97_div = readl(clk_regs + AC97_DIV);
+
+ /*
+ * This may loose precision for some rates but won't for the
+ * standard 24.576MHz.
+ */
+ rate = parent_rate / 2;
+ rate /= ((ac97_div >> 12) & 0x7fff);
+ rate *= (ac97_div & 0xfff);
+
+ return rate;
+}
+PARENTS(clk_pxa3xx_ac97) = { "spll_624mhz" };
+RATE_RO_OPS(clk_pxa3xx_ac97, "ac97");
+
+static unsigned long clk_pxa3xx_smemc_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = readl(clk_regs + ACSR);
+
+ return (parent_rate / 48) * smcfs_mult[(acsr >> 23) & 0x7] /
+ pxa3xx_smemc_get_memclkdiv();
+}
+PARENTS(clk_pxa3xx_smemc) = { "spll_624mhz" };
+RATE_RO_OPS(clk_pxa3xx_smemc, "smemc");
+
+static bool pxa3xx_is_ring_osc_forced(void)
+{
+ unsigned long acsr = readl(clk_regs + ACSR);
+
+ return acsr & ACCR_D0CS;
+}
+
+PARENTS(pxa3xx_pbus) = { "ring_osc_60mhz", "spll_624mhz" };
+PARENTS(pxa3xx_32Khz_bus) = { "osc_32_768khz", "osc_32_768khz" };
+PARENTS(pxa3xx_13MHz_bus) = { "osc_13mhz", "osc_13mhz" };
+PARENTS(pxa3xx_ac97_bus) = { "ring_osc_60mhz", "ac97" };
+PARENTS(pxa3xx_sbus) = { "ring_osc_60mhz", "system_bus" };
+PARENTS(pxa3xx_smemcbus) = { "ring_osc_60mhz", "smemc" };
+
+#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? CKENB : CKENA)
+#define PXA3XX_CKEN(dev_id, con_id, parents, mult_lp, div_lp, mult_hp, \
+ div_hp, bit, is_lp, flags) \
+ PXA_CKEN(dev_id, con_id, bit, parents, mult_lp, div_lp, \
+ mult_hp, div_hp, is_lp, CKEN_AB(bit), \
+ (CKEN_ ## bit % 32), flags)
+#define PXA3XX_PBUS_CKEN(dev_id, con_id, bit, mult_lp, div_lp, \
+ mult_hp, div_hp, delay) \
+ PXA3XX_CKEN(dev_id, con_id, pxa3xx_pbus_parents, mult_lp, \
+ div_lp, mult_hp, div_hp, bit, pxa3xx_is_ring_osc_forced, 0)
+#define PXA3XX_CKEN_1RATE(dev_id, con_id, bit, parents) \
+ PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
+ CKEN_AB(bit), (CKEN_ ## bit % 32), 0)
+
+static struct desc_clk_cken pxa3xx_clocks[] = {
+ PXA3XX_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 1, 4, 1, 42, 1),
+ PXA3XX_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 1, 4, 1, 42, 1),
+ PXA3XX_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 1, 4, 1, 42, 1),
+ PXA3XX_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 5, 1, 19, 0),
+ PXA3XX_PBUS_CKEN("pxa27x-udc", NULL, UDC, 1, 4, 1, 13, 5),
+ PXA3XX_PBUS_CKEN("pxa27x-ohci", NULL, USBH, 1, 4, 1, 13, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-u2d", NULL, USB2, 1, 4, 1, 13, 0),
+ PXA3XX_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 6, 1, 48, 0),
+ PXA3XX_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 6, 1, 48, 0),
+ PXA3XX_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC1, 1, 4, 1, 24, 0),
+ PXA3XX_PBUS_CKEN("pxa2xx-mci.1", NULL, MMC2, 1, 4, 1, 24, 0),
+ PXA3XX_PBUS_CKEN("pxa2xx-mci.2", NULL, MMC3, 1, 4, 1, 24, 0),
+
+ PXA3XX_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
+ pxa3xx_32Khz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.0", NULL, SSP1, pxa3xx_13MHz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.1", NULL, SSP2, pxa3xx_13MHz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.2", NULL, SSP3, pxa3xx_13MHz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.3", NULL, SSP4, pxa3xx_13MHz_bus_parents),
+
+ PXA3XX_CKEN(NULL, "AC97CLK", pxa3xx_ac97_bus_parents, 1, 4, 1, 1, AC97,
+ pxa3xx_is_ring_osc_forced, 0),
+ PXA3XX_CKEN(NULL, "CAMCLK", pxa3xx_sbus_parents, 1, 2, 1, 1, CAMERA,
+ pxa3xx_is_ring_osc_forced, 0),
+ PXA3XX_CKEN("pxa2xx-fb", NULL, pxa3xx_sbus_parents, 1, 1, 1, 1, LCD,
+ pxa3xx_is_ring_osc_forced, 0),
+ PXA3XX_CKEN("pxa2xx-pcmcia", NULL, pxa3xx_smemcbus_parents, 1, 4,
+ 1, 1, SMC, pxa3xx_is_ring_osc_forced, CLK_IGNORE_UNUSED),
+};
+
+static struct desc_clk_cken pxa300_310_clocks[] = {
+ PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA300_GCU, 1, 1, 1, 1, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 4, 0),
+ PXA3XX_CKEN_1RATE("pxa3xx-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
+};
+
+static struct desc_clk_cken pxa320_clocks[] = {
+ PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 6, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA320_GCU, 1, 1, 1, 1, 0),
+ PXA3XX_CKEN_1RATE("pxa3xx-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
+};
+
+static unsigned long clk_pxa3xx_system_bus_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = readl(clk_regs + ACSR);
+ unsigned int hss = (acsr >> 14) & 0x3;
+
+ if (pxa3xx_is_ring_osc_forced())
+ return parent_rate;
+ return parent_rate / 48 * hss_mult[hss];
+}
+
+static int clk_pxa3xx_system_bus_get_parent(struct clk_hw *hw)
+{
+ if (pxa3xx_is_ring_osc_forced())
+ return PXA_BUS_60Mhz;
+ else
+ return PXA_BUS_HSS;
+}
+
+PARENTS(clk_pxa3xx_system_bus) = { "ring_osc_60mhz", "spll_624mhz" };
+MUX_RO_RATE_RO_OPS(clk_pxa3xx_system_bus, "system_bus");
+
+static unsigned long clk_pxa3xx_core_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate;
+}
+
+static int clk_pxa3xx_core_get_parent(struct clk_hw *hw)
+{
+ unsigned long xclkcfg;
+ unsigned int t;
+
+ if (pxa3xx_is_ring_osc_forced())
+ return PXA_CORE_60Mhz;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ if (t)
+ return PXA_CORE_TURBO;
+ return PXA_CORE_RUN;
+}
+PARENTS(clk_pxa3xx_core) = { "ring_osc_60mhz", "run", "cpll" };
+MUX_RO_RATE_RO_OPS(clk_pxa3xx_core, "core");
+
+static unsigned long clk_pxa3xx_run_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = readl(clk_regs + ACSR);
+ unsigned int xn = (acsr & ACCR_XN_MASK) >> 8;
+ unsigned int t, xclkcfg;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ return t ? (parent_rate / xn) * 2 : parent_rate;
+}
+PARENTS(clk_pxa3xx_run) = { "cpll" };
+RATE_RO_OPS(clk_pxa3xx_run, "run");
+
+static unsigned long clk_pxa3xx_cpll_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = readl(clk_regs + ACSR);
+ unsigned int xn = (acsr & ACCR_XN_MASK) >> 8;
+ unsigned int xl = acsr & ACCR_XL_MASK;
+ unsigned int t, xclkcfg;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ return t ? parent_rate * xl * xn : parent_rate * xl;
+}
+PARENTS(clk_pxa3xx_cpll) = { "osc_13mhz" };
+RATE_RO_OPS(clk_pxa3xx_cpll, "cpll");
+
+static void pxa3xx_register_core(void)
+{
+ clk_register_clk_pxa3xx_cpll();
+ clk_register_clk_pxa3xx_run();
+
+ clkdev_pxa_register(CLK_CORE, "core", NULL,
+ clk_register_clk_pxa3xx_core());
+}
+
+static void pxa3xx_register_plls(void)
+{
+ clk_register_fixed_rate("osc_13mhz", NULL, CLK_GET_RATE_NOCACHE,
+ 13 * MHz);
+ clkdev_pxa_register(CLK_OSC32k768, "osc_32_768khz", NULL,
+ clk_register_fixed_rate("osc_32_768khz", NULL,
+ CLK_GET_RATE_NOCACHE,
+ 32768));
+ clk_register_fixed_rate("ring_osc_120mhz", NULL, CLK_GET_RATE_NOCACHE,
+ 120 * MHz);
+ clk_register_fixed_rate("clk_dummy", NULL, 0, 0);
+ clk_register_fixed_factor(NULL, "spll_624mhz", "osc_13mhz", 0, 48, 1);
+ clk_register_fixed_factor(NULL, "ring_osc_60mhz", "ring_osc_120mhz",
+ 0, 1, 2);
+}
+
+static void pxa3xx_base_clocks_init(void __iomem *oscc_reg)
+{
+ struct clk *clk;
+
+ pxa3xx_register_plls();
+ pxa3xx_register_core();
+ clk_register_clk_pxa3xx_system_bus();
+ clk_register_clk_pxa3xx_ac97();
+ clk_register_clk_pxa3xx_smemc();
+
+ clk = clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0, oscc_reg,
+ 11, 0, NULL);
+ clk_register_clkdev(clk, "CLK_POUT", NULL);
+ clkdev_pxa_register(CLK_OSTIMER, "OSTIMER0", NULL,
+ clk_register_fixed_factor(NULL, "os-timer0",
+ "osc_13mhz", 0, 1, 4));
+}
+
+static int pxa3xx_clocks_init(void __iomem *regs, void __iomem *oscc_reg)
+{
+ int ret;
+
+ clk_regs = regs;
+ pxa3xx_base_clocks_init(oscc_reg);
+
+ ret = clk_pxa_cken_init(pxa3xx_clocks, ARRAY_SIZE(pxa3xx_clocks), regs);
+ if (ret)
+ return ret;
+
+ if (cpu_is_pxa320())
+ return clk_pxa_cken_init(pxa320_clocks,
+ ARRAY_SIZE(pxa320_clocks), regs);
+
+ return clk_pxa_cken_init(pxa300_310_clocks,
+ ARRAY_SIZE(pxa300_310_clocks), regs);
+}
+
+static int pxa3xx_dt_clocks_init(struct device_node *np)
+{
+ int ret;
+
+ /*
+ * The clock unit has no reg property of its own in the binding, the
+ * addresses are implied by the compatible.
+ */
+ ret = pxa3xx_clocks_init(IOMEM(0x41340000), IOMEM(0x41350000));
+ if (ret)
+ return ret;
+
+ return clk_pxa_dt_common_init(np);
+}
+CLK_OF_DECLARE(pxa_clks, "marvell,pxa300-clocks", pxa3xx_dt_clocks_init);
diff --git a/include/mach/pxa/clock.h b/include/mach/pxa/clock.h
deleted file mode 100644
index f86152f7af..0000000000
--- a/include/mach/pxa/clock.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-/*
- * clock.h - definitions of the PXA clock functions
- *
- * Copyright (C) 2010 by Marc Kleine-Budde <mkl@pengutronix.de>
- *
- * This file is released under the GPLv2
- *
- */
-
-#ifndef __MACH_CLOCK_H
-#define __MACH_CLOCK_H
-
-unsigned long pxa_get_uartclk(void);
-unsigned long pxa_get_mmcclk(void);
-unsigned long pxa_get_lcdclk(void);
-unsigned long pxa_get_pwmclk(void);
-
-#endif /* !__MACH_CLOCK_H */
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (6 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 07/27] clk: pxa: add a device tree clock driver for PXA3xx Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings Sascha Hauer
` (20 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The property was parsed into host->keep_config and then never looked at,
so the driver always recalculated the timings from the core clock rate,
even where the device tree explicitly says not to.
Honour it. Where it is set, the timings the previous stage left behind
are known to work, and the driver no longer depends on clk_get_rate()
returning anything accurate for the NAND controller clock.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/raw/nand_mrvl_nfc.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/nand_mrvl_nfc.c b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
index 0e2a2b639a..6f3fb57062 100644
--- a/drivers/mtd/nand/raw/nand_mrvl_nfc.c
+++ b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
@@ -343,11 +343,20 @@ static struct mrvl_nand_timing timings[] = {
static void mrvl_nand_set_timing(struct mrvl_nand_host *host, bool use_default)
{
struct nand_chip *chip = &host->chip;
- unsigned long nand_clk = clk_get_rate(host->core_clk);
struct mrvl_nand_timing *t;
+ unsigned long nand_clk;
uint32_t ndtr0, ndtr1;
u16 id;
+ /*
+ * The previous stage has set up timings that are known to work,
+ * keep them instead of calculating our own.
+ */
+ if (host->keep_config)
+ return;
+
+ nand_clk = clk_get_rate(host->core_clk);
+
if (use_default) {
id = 0;
} else {
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (7 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command Sascha Hauer
` (19 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The driver only knows the deprecated "marvell,pxa3xx-nand" and
"marvell,armada370-nand" compatibles, where the chip properties are in
the controller node. The upstream device trees use the newer
"...-nand-controller" bindings, where the chip lives in a child node
along with its partitions.
Add the new compatibles and read the chip properties from the child
node. Handing that node to the NAND core via nand_set_flash_node() is
what makes the generic properties and the partitions below it work at
all: mtd_get_of_node() otherwise falls back to the parent, which is the
controller node.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/raw/nand_mrvl_nfc.c | 69 ++++++++++++++++++++++++++++++------
1 file changed, 58 insertions(+), 11 deletions(-)
diff --git a/drivers/mtd/nand/raw/nand_mrvl_nfc.c b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
index 6f3fb57062..ebb1fd81fb 100644
--- a/drivers/mtd/nand/raw/nand_mrvl_nfc.c
+++ b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
@@ -132,6 +132,12 @@
struct mrvl_nand_variant {
unsigned int hwflags;
+ /*
+ * True for the "nand-controller" bindings, where the chip properties
+ * live in per chip select child nodes instead of in the controller
+ * node itself.
+ */
+ bool chip_subnodes;
};
struct mrvl_nand_host {
@@ -288,7 +294,26 @@ static const struct mrvl_nand_variant armada370_variant = {
.hwflags = HWFLAGS_ECC_BCH | HWFLAGS_HAS_NDCB3,
};
+static const struct mrvl_nand_variant pxa3xx_controller_variant = {
+ .hwflags = 0,
+ .chip_subnodes = true,
+};
+
+static const struct mrvl_nand_variant armada370_controller_variant = {
+ .hwflags = HWFLAGS_ECC_BCH | HWFLAGS_HAS_NDCB3,
+ .chip_subnodes = true,
+};
+
static struct of_device_id mrvl_nand_dt_ids[] = {
+ {
+ .compatible = "marvell,pxa3xx-nand-controller",
+ .data = &pxa3xx_controller_variant,
+ },
+ {
+ .compatible = "marvell,armada370-nand-controller",
+ .data = &armada370_controller_variant,
+ },
+ /* Deprecated bindings, the chip properties are in the controller node */
{
.compatible = "marvell,pxa3xx-nand",
.data = &pxa3xx_variant,
@@ -1199,33 +1224,55 @@ static struct mrvl_nand_host *alloc_nand_resource(struct device *dev)
static int mrvl_nand_probe_dt(struct mrvl_nand_host *host)
{
struct device_node *np = host->dev->of_node;
- const struct of_device_id *match;
const struct mrvl_nand_variant *variant;
+ struct device_node *chip_np;
if (!IS_ENABLED(CONFIG_OFTREE) || host->dev->platform_data)
return 0;
- match = of_match_node(mrvl_nand_dt_ids, np);
- if (!match)
+ variant = device_get_match_data(host->dev);
+ if (!variant)
return -EINVAL;
- variant = match->data;
- if (of_get_property(np, "marvell,nand-keep-config", NULL))
- host->keep_config = 1;
+ host->hwflags = variant->hwflags;
+
of_property_read_u32(np, "num-cs", &host->num_cs);
- if (of_get_nand_on_flash_bbt(np))
+
+ /*
+ * With the "nand-controller" bindings the chip lives in a child node
+ * of the controller. Only a single chip is supported, so take the
+ * first one. The deprecated bindings have the chip properties in the
+ * controller node itself.
+ */
+ if (variant->chip_subnodes) {
+ chip_np = of_get_next_available_child(np, NULL);
+ if (!chip_np) {
+ dev_err(host->dev, "no chip node found\n");
+ return -ENODEV;
+ }
+ } else {
+ chip_np = np;
+ }
+
+ /*
+ * Hand the chip node to the NAND core so that the generic properties
+ * and the partitions below it are evaluated.
+ */
+ nand_set_flash_node(&host->chip, chip_np);
+
+ if (of_get_property(chip_np, "marvell,nand-keep-config", NULL))
+ host->keep_config = 1;
+ if (of_get_nand_on_flash_bbt(chip_np))
host->flash_bbt = 1;
- host->ecc_strength = of_get_nand_ecc_strength(np);
+ host->ecc_strength = of_get_nand_ecc_strength(chip_np);
if (host->ecc_strength < 0)
host->ecc_strength = 0;
- host->ecc_step = of_get_nand_ecc_step_size(np);
+ host->ecc_step = of_get_nand_ecc_step_size(chip_np);
if (host->ecc_step < 0)
host->ecc_step = 0;
- host->hwflags = variant->hwflags;
-
return 0;
}
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (8 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error Sascha Hauer
` (18 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
Every block erase and every page program took 400ms, so writing a
bootloader image to NAND took minutes. That 400ms is nand_wait()'s
timeout, hit in full every single time.
NDSR's per-chipselect ready bits latch the flash's busy-to-ready
transition rather than reporting its current level, and nand_wait()
polls them through mrvl_nand_ready() to find out when an erase or a
program has finished. It issues a STATUS command before it starts
polling, though, and every command clears NDSR on its way through
mrvl_nand_start() - so the transition it was about to wait for was gone
before it ever looked. It never saw a ready chip, ran its timeout out,
and only then fell through to read the status byte. That last read is
correct, which is why this showed up as NAND writes being unusably slow
rather than as an error.
Keep the ready bits across a STATUS command, and go on clearing them for
the commands that make the flash busy in the first place, so what
nand_wait() observes is that command's own completion.
Measured on a Raumfeld speaker (PXA303, 128KiB erase blocks): a block
erase goes from 400ms to under a millisecond and a 128KiB write from
25.6s to 28ms. Reads were never affected.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/raw/nand_mrvl_nfc.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/raw/nand_mrvl_nfc.c b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
index ebb1fd81fb..b1532dbf1b 100644
--- a/drivers/mtd/nand/raw/nand_mrvl_nfc.c
+++ b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
@@ -472,8 +472,9 @@ static unsigned int mrvl_datasize(struct mrvl_nand_host *host)
* We enable all the interrupt at the same time, and
* let mrvl_nand_irq to handle all logic.
*/
-static void mrvl_nand_start(struct mrvl_nand_host *host)
+static void mrvl_nand_start(struct mrvl_nand_host *host, unsigned command)
{
+ uint32_t ndsr_clear = NDSR_MASK;
uint32_t ndcr;
if (host->hwflags & HWFLAGS_ECC_BCH) {
@@ -503,9 +504,27 @@ static void mrvl_nand_start(struct mrvl_nand_host *host)
ndcr &= ~NDCR_ND_RUN;
ndcr |= NDCR_INT_MASK;
+ /*
+ * NDSR's per-chipselect ready bits latch the flash's busy-to-ready
+ * transition, they do not report its current level. nand_wait() polls
+ * them through mrvl_nand_ready() to find out when an erase or a page
+ * program has finished - but it issues a STATUS command first, and
+ * clearing the latch here would wipe the very transition it is about
+ * to wait for. It would then never see a ready chip and spend its
+ * full 400ms timeout on every block erase and every page program
+ * before falling through to read the status byte, which is why this
+ * only ever showed up as NAND writes being unusably slow rather than
+ * as an error.
+ *
+ * So leave the latch alone for STATUS, and keep clearing it for the
+ * commands that make the flash busy in the first place.
+ */
+ if (command == NAND_CMD_STATUS)
+ ndsr_clear &= ~(NDSR_RDY | NDSR_FLASH_RDY);
+
/* clear status bits and run */
nand_writel(host, NDCR, ndcr);
- nand_writel(host, NDSR, NDSR_MASK);
+ nand_writel(host, NDSR, ndsr_clear);
nand_writel(host, NDCR, ndcr | NDCR_ND_RUN);
if (wait_on_timeout(host->chip.legacy.chip_delay * USECOND,
@@ -817,7 +836,7 @@ static void mrvl_nand_cmdfunc(struct nand_chip *chip, unsigned command,
prepare_start_command(host, command);
if (prepare_set_command(host, command, 0, column, page_addr)) {
- mrvl_nand_start(host);
+ mrvl_nand_start(host, command);
mrvl_data_stage(host);
mrvl_nand_wait_cmd_done(host, command);
}
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (9 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 12/27] mci: pxamci: probe from the device tree Sascha Hauer
` (17 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
Identifying the chip prints
mrvl_nand ...: Waiting end of command 0th 236 timeout, \
ndsr=0x00000800 ndcr=0x10041fff
once on every boot. Command 236 is 0xEC, NAND_CMD_PARAM: the nand layer
asks for the ONFI parameter page to find out whether the chip is ONFI at
all, the controller never raises CS0_CMDD for it - NDSR reads back
FLASH_RDY alone - and the wait times out. The layer above then finds no
parameter page, falls back to identifying the chip from its id bytes,
and everything from there on works.
So this is a capability probe coming back negative, not a failure.
Nothing acts on it either: mrvl_nand_wait_cmd_done() has no return
value. Print it as a debug message.
Whether NAND_CMD_PARAM can be made to complete on this controller is a
separate question; this only stops the answer from looking like a fault.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/raw/nand_mrvl_nfc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/nand_mrvl_nfc.c b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
index b1532dbf1b..a5e30db669 100644
--- a/drivers/mtd/nand/raw/nand_mrvl_nfc.c
+++ b/drivers/mtd/nand/raw/nand_mrvl_nfc.c
@@ -813,7 +813,7 @@ static void mrvl_nand_wait_cmd_done(struct mrvl_nand_host *host,
wait_on_timeout(host->chip.legacy.chip_delay * USECOND,
(nand_readl(host, NDSR) & mask) == mask);
if ((nand_readl(host, NDSR) & mask) != mask) {
- dev_err(host->dev, "Waiting end of command %dth %d timeout, ndsr=0x%08x ndcr=0x%08x\n",
+ dev_dbg(host->dev, "Waiting end of command %dth %d timeout, ndsr=0x%08x ndcr=0x%08x\n",
nb_done++, command, nand_readl(host, NDSR),
nand_readl(host, NDCR));
}
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 12/27] mci: pxamci: probe from the device tree
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (10 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 13/27] serial: pxa: add device tree support Sascha Hauer
` (16 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The driver was probed by name only and took its configuration from
platform data. Nothing in tree ever registered that platform data, so the
gpio_power / setpower / init hooks were dead code, and the driver could
not be used from a device tree at all.
Match "marvell,pxa-mmc" and let mci_of_parse() pick up bus-width and the
other generic properties. The power switching goes away with the platform
data: the MCI core already gets a "vmmc" regulator from the device tree,
which is how the supply is described upstream.
mci_ops.init() stays, now as a stub: mci_card_probe() calls it without
checking it for NULL.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mci/pxamci.c | 47 +++++++++++++++++--------------------------
drivers/mci/pxamci.h | 1 -
include/mach/pxa/mci_pxa2xx.h | 12 -----------
3 files changed, 18 insertions(+), 42 deletions(-)
diff --git a/drivers/mci/pxamci.c b/drivers/mci/pxamci.c
index 5e26022729..236d4d97b4 100644
--- a/drivers/mci/pxamci.c
+++ b/drivers/mci/pxamci.c
@@ -13,10 +13,10 @@
#include <clock.h>
#include <init.h>
#include <mci.h>
+#include <of.h>
#include <linux/err.h>
#include <linux/clk.h>
-#include <mach/pxa/mci_pxa2xx.h>
#include <mach/pxa/pxa-regs.h>
#include "pxamci.h"
@@ -26,18 +26,6 @@
#define TX_TIMEOUT (250 * MSECOND)
#define CMD_TIMEOUT (100 * MSECOND)
-static int pxamci_set_power(struct pxamci_host *host, int on)
-{
- mci_dbg("on=%d\n", on);
- if (host->pdata && host->pdata->gpio_power > 0)
- gpio_set_value(host->pdata->gpio_power,
- !!on ^ host->pdata->gpio_power_invert);
- else if (host->pdata && host->pdata->setpower)
- host->pdata->setpower(&host->mci, on);
- mdelay(250);
- return 0;
-}
-
static void pxamci_start_clock(struct pxamci_host *host)
{
mmc_writel(START_CLOCK, MMC_STRPCL);
@@ -297,17 +285,16 @@ static void pxamci_set_ios(struct mci_host *mci, struct mci_ios *ios)
host->cmdat |= CMDAT_INIT;
- pxamci_set_power(host, 1);
pxamci_stop_clock(host);
mmc_writel(host->clkrt, MMC_CLKRT);
}
+/*
+ * The MCI core calls this unconditionally, so it has to exist even though
+ * there is nothing left to do here since the platform data went away.
+ */
static int pxamci_init(struct mci_host *mci, struct device *dev)
{
- struct pxamci_host *host = to_pxamci(mci);
-
- if (host->pdata && host->pdata->init)
- return host->pdata->init(mci, dev);
return 0;
}
@@ -322,7 +309,6 @@ static int pxamci_probe(struct device *dev)
struct resource *iores;
struct pxamci_host *host;
unsigned long rate;
- int gpio_power = -1;
int ret;
host = xzalloc(sizeof(*host));
@@ -344,6 +330,8 @@ static int pxamci_probe(struct device *dev)
host->mci.hw_dev = dev;
host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+ mci_of_parse(&host->mci);
+
/*
* Calculate minimum clock rate, rounding up.
*/
@@ -360,20 +348,21 @@ static int pxamci_probe(struct device *dev)
mmc_writel(64, MMC_RESTO);
mmc_writel(0, MMC_I_MASK);
- host->pdata = dev->platform_data;
- if (host->pdata)
- gpio_power = host->pdata->gpio_power;
-
- if (gpio_power > 0)
- gpio_direction_output(gpio_power,
- host->pdata->gpio_power_invert);
-
- mci_register(&host->mci);
- return 0;
+ return mci_register(&host->mci);
}
+static __maybe_unused struct of_device_id pxamci_dt_ids[] = {
+ {
+ .compatible = "marvell,pxa-mmc",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, pxamci_dt_ids);
+
static struct driver pxamci_driver = {
.name = DRIVER_NAME,
.probe = pxamci_probe,
+ .of_compatible = DRV_OF_COMPAT(pxamci_dt_ids),
};
device_platform_driver(pxamci_driver);
diff --git a/drivers/mci/pxamci.h b/drivers/mci/pxamci.h
index 30119a5607..1879d9603b 100644
--- a/drivers/mci/pxamci.h
+++ b/drivers/mci/pxamci.h
@@ -77,7 +77,6 @@
struct pxamci_host {
struct mci_host mci;
void __iomem *base;
- struct pxamci_platform_data *pdata;
struct clk *clk;
unsigned int cmdat;
diff --git a/include/mach/pxa/mci_pxa2xx.h b/include/mach/pxa/mci_pxa2xx.h
deleted file mode 100644
index 299e543479..0000000000
--- a/include/mach/pxa/mci_pxa2xx.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-
-struct mci_host;
-struct device;
-
-struct pxamci_platform_data {
- int gpio_power;
- int gpio_power_invert;
- int (*init)(struct mci_host*, struct device*);
- int (*setpower)(struct mci_host*, int on);
-};
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 13/27] serial: pxa: add device tree support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (11 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 12/27] mci: pxamci: probe from the device tree Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 14/27] serial: pxa: provide the Linux console name Sascha Hauer
` (15 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The driver has only been probed from platform devices so far. Add the
"mrvl,pxa-uart" compatible used by the upstream device trees.
The UART clock is still taken from pxa_get_uartclk() rather than from
the clocks phandle as barebox has no clock driver for the PXA3xx clock
controller the device trees point to.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/serial/serial_pxa.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index a0bebef811..bc792d62a5 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -187,8 +187,18 @@ static int pxa_serial_probe(struct device *dev)
return 0;
}
+static __maybe_unused struct of_device_id pxa_serial_dt_ids[] = {
+ {
+ .compatible = "mrvl,pxa-uart",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, pxa_serial_dt_ids);
+
static struct driver pxa_serial_driver = {
.name = "pxa_serial",
.probe = pxa_serial_probe,
+ .of_compatible = DRV_OF_COMPAT(pxa_serial_dt_ids),
};
console_platform_driver(pxa_serial_driver);
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 14/27] serial: pxa: provide the Linux console name
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (12 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 13/27] serial: pxa: add device tree support Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB Sascha Hauer
` (14 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
Without linux_console_name console_set_stdoutpath() returns early and
never creates global.linux.bootargs.console, so the console= option has
to be passed to Linux manually. The PXA UARTs are ttyS in Linux.
No linux_earlycon_name is set as the Linux PXA UART driver does not
register an earlycon.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/serial/serial_pxa.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index bc792d62a5..f2926bcd7a 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -181,6 +181,7 @@ static int pxa_serial_probe(struct device *dev)
cdev->getc = pxa_serial_getc;
cdev->flush = pxa_serial_flush;
cdev->setbrg = pxa_serial_setbaudrate;
+ cdev->linux_console_name = "ttyS";
console_register(cdev);
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (13 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 14/27] serial: pxa: provide the Linux console name Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 16/27] ARM: pxa: add DEBUG_LL support Sascha Hauer
` (13 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
PXA had no GPIO driver at all. ARCH_PXA selected GENERIC_GPIO, which on
PXA means arch/arm/mach-pxa/gpio.c: a handful of gpio_get_value() and
friends operating directly on the registers, but no gpio chip. So none
of the GPIOs described in the device tree could be used and every
consumer of them silently did nothing, be it the leds, the gpio keys,
the poweroff or the reset of the ethernet chip.
Add a proper driver for the device tree described controller and switch
the architecture over to GPIOLIB. The register layout is simple: banks
of 32 GPIOs, the first three interleaved one 32bit register per bank and
every further group of three starting at the next 0x100 boundary.
The old implementation has to go in the same step, its gpio_set_value()
and friends collide with the ones from gpiolib. Its only users were the
pxa_init_gpio() calls in the PXA2xx MFP code, which set up the gpio
range for that implementation and have no equivalent here: the range
comes from the device tree now.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/Kconfig | 2 +-
arch/arm/mach-pxa/Makefile | 1 -
arch/arm/mach-pxa/gpio.c | 101 -------------------------------
drivers/gpio/Kconfig | 6 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-pxa.c | 146 +++++++++++++++++++++++++++++++++++++++++++++
include/mach/pxa/gpio.h | 1 -
7 files changed, 154 insertions(+), 104 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index fe4fd3f471..2f2ab5d76d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -121,7 +121,7 @@ config ARCH_MXS
config ARCH_PXA
bool "Intel/Marvell PXA based"
depends on 32BIT
- select GENERIC_GPIO
+ select GPIOLIB
config ARCH_SOCFPGA
bool "Altera SOCFPGA"
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index b4f3a51046..fa0793d8a9 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,6 @@
obj-y += clocksource.o
obj-y += sleep.o
obj-y += common.o
-obj-y += gpio.o
obj-y += devices.o
obj-$(CONFIG_ARCH_PXA3XX) += mfp-pxa3xx.o pxa3xx.o
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
deleted file mode 100644
index 130faa404b..0000000000
--- a/arch/arm/mach-pxa/gpio.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Generic PXA GPIO handling
- *
- * Author: Nicolas Pitre
- * Created: Jun 15, 2001
- * Copyright: MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <common.h>
-#include <errno.h>
-#include <gpio.h>
-
-#include <mach/pxa/gpio.h>
-#include <asm/io.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
- void __iomem *regbase;
-};
-
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c) \
- for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
- int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
- struct pxa_gpio_chip *chips;
-
- chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
- if (chips == NULL) {
- pr_err("%s: failed to allocate GPIO chips\n", __func__);
- return -ENOMEM;
- }
-
- for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32)
- chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
- pxa_gpio_chips = chips;
- return 0;
-}
-
-int __init pxa_init_gpio(int start, int end)
-{
- struct pxa_gpio_chip *c;
- int err, gpio;
-
- pxa_last_gpio = end;
-
- /* Initialize GPIO chips */
- err = pxa_init_gpio_chip(end);
- if (err)
- return err;
-
- for_each_gpio_chip(gpio, c) {
- /* clear all GPIO edge detects */
- __raw_writel(0, c->regbase + GFER_OFFSET);
- __raw_writel(0, c->regbase + GRER_OFFSET);
- __raw_writel(~0, c->regbase + GEDR_OFFSET);
- }
-
- return 0;
-}
-
-int gpio_get_value(unsigned gpio)
-{
- return GPLR(gpio) & GPIO_bit(gpio);
-}
-
-void gpio_set_value(unsigned gpio, int value)
-{
- if (value)
- GPSR(gpio) = GPIO_bit(gpio);
- else
- GPCR(gpio) = GPIO_bit(gpio);
-}
-
-int gpio_direction_input(unsigned gpio)
-{
- if (__gpio_is_inverted(gpio))
- GPDR(gpio) |= GPIO_bit(gpio);
- else
- GPDR(gpio) &= ~GPIO_bit(gpio);
- return 0;
-}
-
-int gpio_direction_output(unsigned gpio, int value)
-{
- gpio_set_value(gpio, value);
- if (__gpio_is_inverted(gpio))
- GPDR(gpio) &= ~GPIO_bit(gpio);
- else
- GPDR(gpio) |= GPIO_bit(gpio);
- return 0;
-}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 988d08cf14..923d424e62 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -163,6 +163,12 @@ config GPIO_PL061
help
Say yes here to support the PrimeCell PL061 GPIO device
+config GPIO_PXA
+ bool "GPIO support for Intel/Marvell PXA"
+ depends on ARCH_PXA || COMPILE_TEST
+ help
+ Say yes here to enable the GPIO driver for the PXA SoCs
+
config GPIO_RASPBERRYPI_EXP
bool "Raspberry Pi 3 GPIO Expander"
depends on ARCH_BCM283X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8560e1f059..38059a47f7 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_JZ4740) += gpio-jz4740.o
obj-$(CONFIG_GPIO_MALTA_FPGA_I2C) += gpio-malta-fpga-i2c.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_ORION) += gpio-orion.o
+obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
new file mode 100644
index 0000000000..04b547a141
--- /dev/null
+++ b/drivers/gpio/gpio-pxa.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * GPIO driver for the Intel/Marvell PXA SoCs
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <malloc.h>
+#include <of_device.h>
+
+/*
+ * The registers are grouped in banks of 32 GPIOs. The first three banks
+ * are interleaved, one 32bit register per bank, and every further group
+ * of three banks starts at the next 0x100 boundary.
+ */
+#define GPLR 0x00 /* pin level, read only */
+#define GPDR 0x0c /* direction, 1 = output */
+#define GPSR 0x18 /* set output, write 1 to set */
+#define GPCR 0x24 /* clear output, write 1 to clear */
+
+#define BANK_OFF(bank) ((((bank) / 3) << 8) + (((bank) % 3) << 2))
+
+struct pxa_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *base;
+};
+
+static inline struct pxa_gpio_chip *to_pxa_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct pxa_gpio_chip, chip);
+}
+
+static inline void __iomem *pxa_gpio_reg(struct gpio_chip *chip,
+ unsigned off, unsigned reg)
+{
+ return to_pxa_gpio(chip)->base + BANK_OFF(off / 32) + reg;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned off)
+{
+ return !!(readl(pxa_gpio_reg(chip, off, GPLR)) & BIT(off % 32));
+}
+
+static int pxa_gpio_set(struct gpio_chip *chip, unsigned off, int value)
+{
+ writel(BIT(off % 32), pxa_gpio_reg(chip, off, value ? GPSR : GPCR));
+
+ return 0;
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+ void __iomem *gpdr = pxa_gpio_reg(chip, off, GPDR);
+
+ writel(readl(gpdr) & ~BIT(off % 32), gpdr);
+
+ return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip, unsigned off,
+ int value)
+{
+ void __iomem *gpdr = pxa_gpio_reg(chip, off, GPDR);
+
+ /* drive the requested level before switching the pin to output */
+ pxa_gpio_set(chip, off, value);
+ writel(readl(gpdr) | BIT(off % 32), gpdr);
+
+ return 0;
+}
+
+static int pxa_gpio_get_direction(struct gpio_chip *chip, unsigned off)
+{
+ if (readl(pxa_gpio_reg(chip, off, GPDR)) & BIT(off % 32))
+ return GPIOF_DIR_OUT;
+
+ return GPIOF_DIR_IN;
+}
+
+static struct gpio_ops pxa_gpio_ops = {
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get_direction = pxa_gpio_get_direction,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+};
+
+static int pxa_gpio_probe(struct device *dev)
+{
+ struct pxa_gpio_chip *pxa;
+ struct resource *iores;
+ int ret;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ pxa = xzalloc(sizeof(*pxa));
+ pxa->base = IOMEM(iores->start);
+
+ pxa->chip.dev = dev;
+ pxa->chip.ops = &pxa_gpio_ops;
+ pxa->chip.base = 0;
+ pxa->chip.ngpio = (uintptr_t)device_get_match_data(dev);
+
+ ret = gpiochip_add(&pxa->chip);
+ if (ret) {
+ dev_err(dev, "couldn't add gpiochip: %pe\n", ERR_PTR(ret));
+ free(pxa);
+ return ret;
+ }
+
+ dev_dbg(dev, "probed %u gpios\n", pxa->chip.ngpio);
+
+ return 0;
+}
+
+static struct of_device_id pxa_gpio_dt_ids[] = {
+ {
+ .compatible = "intel,pxa25x-gpio",
+ .data = (void *)85,
+ }, {
+ .compatible = "intel,pxa26x-gpio",
+ .data = (void *)90,
+ }, {
+ .compatible = "intel,pxa27x-gpio",
+ .data = (void *)121,
+ }, {
+ .compatible = "intel,pxa3xx-gpio",
+ .data = (void *)128,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, pxa_gpio_dt_ids);
+
+static struct driver pxa_gpio_driver = {
+ .name = "pxa-gpio",
+ .probe = pxa_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(pxa_gpio_dt_ids),
+};
+core_platform_driver(pxa_gpio_driver);
diff --git a/include/mach/pxa/gpio.h b/include/mach/pxa/gpio.h
index 2d169608d8..84331f6b5c 100644
--- a/include/mach/pxa/gpio.h
+++ b/include/mach/pxa/gpio.h
@@ -133,6 +133,5 @@ static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
*/
extern int pxa_last_gpio;
-extern int pxa_init_gpio(int start, int end);
#endif
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 16/27] ARM: pxa: add DEBUG_LL support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (14 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 17/27] ARM: pxa: let the board select the SoC Sascha Hauer
` (12 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA UARTs are NS16550 compatible, so the generic ns16550 debug_ll
helpers can be reused. Two things differ from a plain ns16550: the
registers are 32bit wide and thus spaced four bytes apart, and the unit
has to be enabled explicitly with the UUE bit in the IER register.
The latter needs care as debug_ll_ns16550_init() clears IER to disable
the interrupts, which on PXA disables the unit as well, so UUE has to be
set again afterwards.
The UART clock is a fixed 14.857MHz on all PXA variants, so the divisor
can be calculated without any clock support.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/Kconfig | 1 +
arch/arm/include/asm/debug_ll.h | 2 ++
common/Kconfig.debug_ll | 17 ++++++++++
include/mach/pxa/debug_ll.h | 74 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 94 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2f2ab5d76d..292b9cfe66 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -122,6 +122,7 @@ config ARCH_PXA
bool "Intel/Marvell PXA based"
depends on 32BIT
select GPIOLIB
+ select HAS_DEBUG_LL
config ARCH_SOCFPGA
bool "Altera SOCFPGA"
diff --git a/arch/arm/include/asm/debug_ll.h b/arch/arm/include/asm/debug_ll.h
index a645a6e910..e7e98ced0a 100644
--- a/arch/arm/include/asm/debug_ll.h
+++ b/arch/arm/include/asm/debug_ll.h
@@ -42,6 +42,8 @@
#include <mach/zynq/debug_ll.h>
#elif defined CONFIG_DEBUG_SOCFPGA_UART
#include <mach/socfpga/debug_ll.h>
+#elif defined CONFIG_DEBUG_PXA_UART
+#include <mach/pxa/debug_ll.h>
#endif
#endif
diff --git a/common/Kconfig.debug_ll b/common/Kconfig.debug_ll
index 8445b4be08..8ae3bbb172 100644
--- a/common/Kconfig.debug_ll
+++ b/common/Kconfig.debug_ll
@@ -393,6 +393,14 @@ config DEBUG_TEGRA_UART
bool "Tegra debug UART"
depends on ARCH_TEGRA
+config DEBUG_SOCFPGA_UART
+ bool "SoCFPGA debug UART"
+ depends on ARCH_SOCFPGA
+
+config DEBUG_PXA_UART
+ bool "PXA debug UART"
+ depends on ARCH_PXA
+
endchoice
config DEBUG_LL_NS16550
@@ -400,6 +408,15 @@ config DEBUG_LL_NS16550
help
Selected by RISC-V and PowerPC platforms that use ns16550 for debug_ll
+config DEBUG_PXA_UART_PORT
+ int "PXA Debug UART Port Selection" if DEBUG_PXA_UART
+ default 0
+ depends on ARCH_PXA
+ help
+ Choose UART port on which barebox low-level debug messages
+ should be output. Possible values are:
+ 0 - FFUART, 1 - BTUART, 2 - STUART
+
config DEBUG_IMX_UART_PORT
int "i.MX Debug UART Port Selection" if DEBUG_IMX1_UART || \
DEBUG_IMX21_UART || \
diff --git a/include/mach/pxa/debug_ll.h b/include/mach/pxa/debug_ll.h
new file mode 100644
index 0000000000..3a9ec3b6b6
--- /dev/null
+++ b/include/mach/pxa/debug_ll.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __MACH_PXA_DEBUG_LL_H__
+#define __MACH_PXA_DEBUG_LL_H__
+
+#include <io.h>
+#include <linux/bits.h>
+
+/*
+ * The PXA UARTs are NS16550 compatible, but the registers are 32bit
+ * wide and thus spaced four bytes apart. In addition to that the unit
+ * has to be enabled explicitly with the UUE bit in the IER register.
+ */
+#define PXA_UART_IER_UUE BIT(6)
+
+#define PXA_FFUART_BASE 0x40100000
+#define PXA_BTUART_BASE 0x40200000
+#define PXA_STUART_BASE 0x40700000
+
+#ifdef CONFIG_DEBUG_PXA_UART
+
+#if CONFIG_DEBUG_PXA_UART_PORT == 0
+#define PXA_DEBUG_UART_BASE PXA_FFUART_BASE
+#elif CONFIG_DEBUG_PXA_UART_PORT == 1
+#define PXA_DEBUG_UART_BASE PXA_BTUART_BASE
+#elif CONFIG_DEBUG_PXA_UART_PORT == 2
+#define PXA_DEBUG_UART_BASE PXA_STUART_BASE
+#else
+#error "Invalid CONFIG_DEBUG_PXA_UART_PORT"
+#endif
+
+static inline uint8_t debug_ll_read_reg(void __iomem *base, int reg)
+{
+ return readl(base + (reg << 2));
+}
+
+static inline void debug_ll_write_reg(void __iomem *base, int reg, uint8_t val)
+{
+ writel(val, base + (reg << 2));
+}
+
+#include <debug_ll/ns16550.h>
+
+static inline void pxa_debug_ll_init(void)
+{
+ void __iomem *base = IOMEM(PXA_DEBUG_UART_BASE);
+ uint16_t divisor;
+
+ /* The UART clock is a fixed 14.857MHz on all PXA variants */
+ divisor = debug_ll_ns16550_calc_divisor(14857000);
+ debug_ll_ns16550_init(base, divisor);
+
+ /*
+ * debug_ll_ns16550_init() has cleared IER to disable the
+ * interrupts, which on PXA also disabled the unit. Enable it
+ * again, interrupts stay disabled.
+ */
+ debug_ll_write_reg(base, NS16550_IER, PXA_UART_IER_UUE);
+}
+
+static inline void PUTC_LL(char c)
+{
+ debug_ll_ns16550_putc(IOMEM(PXA_DEBUG_UART_BASE), c);
+}
+
+#else
+
+static inline void pxa_debug_ll_init(void)
+{
+}
+
+#endif /* CONFIG_DEBUG_PXA_UART */
+
+#endif /* __MACH_PXA_DEBUG_LL_H__ */
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 17/27] ARM: pxa: let the board select the SoC
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (15 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 16/27] ARM: pxa: add DEBUG_LL support Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 18/27] ARM: pxa: enable device tree support Sascha Hauer
` (11 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA port had a user visible "PXA Processor" choice to pick the SoC,
independently of the board being built. That is the last remnant of the
one-SoC-per-build era and does not scale to multiple boards.
Make the SoC symbols invisible and have the board select them instead,
like all other ARM architectures do. Also add the PXA300 and PXA310
symbols, which had no equivalent in the choice.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/Kconfig | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 738fa7d9bb..5bc99f1f83 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -6,13 +6,17 @@ if ARCH_PXA
config ARCH_PXA3XX
bool
- default y
select CPU_XSC3
select HAVE_CLK
select COMMON_CLK
select COMMON_CLK_OF_PROVIDER
+config ARCH_PXA300
+ bool
+ select ARCH_PXA3XX
+
config ARCH_PXA310
bool
+ select ARCH_PXA3XX
endif
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 18/27] ARM: pxa: enable device tree support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (16 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 17/27] ARM: pxa: let the board select the SoC Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 19/27] scripts: add pxa-image Sascha Hauer
` (10 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA port has been platform data only so far. Select OFTREE and
OFDEVICE so PXA boards can be described by a device tree.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/Kconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 292b9cfe66..106f3d559e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -123,6 +123,8 @@ config ARCH_PXA
depends on 32BIT
select GPIOLIB
select HAS_DEBUG_LL
+ select OFTREE
+ select OFDEVICE
config ARCH_SOCFPGA
bool "Altera SOCFPGA"
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 19/27] scripts: add pxa-image
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (17 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 18/27] ARM: pxa: enable device tree support Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 20/27] ARM: pxa: add a NAND first stage loader Sascha Hauer
` (9 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA3xx Boot ROM does not boot a plain binary. It reads a Non-Trusted
Image Module header from the start of the boot device, copies the OBM
image listed in it into internal SRAM and jumps there; the OBM has to
load whatever comes next itself, because the Boot ROM unmaps itself
before handing over and never returns.
Add a tool that builds such an image out of an OBM and a payload. The
layout is configurable and defaults to keeping the header and the OBM in
the first erase block, which NAND chips guarantee to be good as shipped,
so that the Boot ROM never has to read a block that might be bad. The
gaps between the images are filled with 0xff
so the result can be written to erased NAND as is, and the payload's real
size is recorded in its image entry so that the OBM knows how much to
copy rather than having to assume a fixed amount.
The header format was recovered from the vendor image of a Raumfeld
speaker. Fed that device's own OBM and bootloader, this tool reproduces
55 of the 59 header words exactly; the rest are the issue date, which is
left zero for reproducibility, and the two sizes, which is the point.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
scripts/Kconfig | 7 ++
scripts/Makefile | 1 +
scripts/pxa-image.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 289 insertions(+)
diff --git a/scripts/Kconfig b/scripts/Kconfig
index 2972d5dbc7..8fff940946 100644
--- a/scripts/Kconfig
+++ b/scripts/Kconfig
@@ -21,6 +21,13 @@ config SOCFPGA_MKIMAGE
help
This enables building the image creation tool for SoCFPGA
+config PXA_IMAGE
+ bool "PXA image" if COMPILE_HOST_TOOLS
+ depends on ARCH_PXA || COMPILE_HOST_TOOLS
+ default y if ARCH_PXA
+ help
+ This enables building the image creation tool for PXA3xx
+
config ZYNQ_MKIMAGE
bool "Zynq mkimage" if COMPILE_HOST_TOOLS
depends on ARCH_ZYNQ || COMPILE_HOST_TOOLS
diff --git a/scripts/Makefile b/scripts/Makefile
index fc685f14dd..022e04ddec 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -19,6 +19,7 @@ hostprogs-always-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-always-$(CONFIG_MIPS) += mips-relocs
hostprogs-always-$(CONFIG_MVEBU_HOSTTOOLS) += kwbimage kwboot mvebuimg
hostprogs-always-$(CONFIG_OMAP_IMAGE) += omap_signGP mk-omap-image
+hostprogs-always-$(CONFIG_PXA_IMAGE) += pxa-image
HOSTCFLAGS_zynq_mkimage.o = -I$(srctree) -I$(srctree)/include/mach
hostprogs-always-$(CONFIG_ZYNQ_MKIMAGE) += zynq_mkimage
hostprogs-always-$(CONFIG_SOCFPGA_MKIMAGE) += socfpga_mkimage
diff --git a/scripts/pxa-image.c b/scripts/pxa-image.c
new file mode 100644
index 0000000000..6016752c9a
--- /dev/null
+++ b/scripts/pxa-image.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * pxa-image - build a bootable PXA3xx NAND image
+ *
+ * The PXA3xx Boot ROM reads a Non-Trusted Image Module (NTIM) header from the
+ * start of NAND, copies the OBM image listed in it into internal SRAM and
+ * jumps there. It does not return: the OBM has to set up DRAM and load the
+ * next image itself.
+ *
+ * This tool builds such an image out of the OBM (a barebox PBL built for
+ * internal SRAM) and barebox proper:
+ *
+ * offset 0 NTIM header
+ * offset <obm-offset> OBM, loaded to internal SRAM by the Boot ROM
+ * offset <boot-offset> barebox, loaded to DRAM by the OBM
+ *
+ * The default offsets keep the first two in the first erase block, which NAND
+ * chips guarantee to be good as shipped, so that the Boot ROM never has to
+ * read a block that might be bad. Only barebox lives beyond it, and that one
+ * is read by the OBM, which is ours.
+ *
+ * The size of the barebox image is stored in its NTIM entry so that the OBM
+ * knows how much to copy; see pxa_nand_load_image() in mach-pxa.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define NTIM_VERSION 0x00030102
+#define NTIM_ID_TIMH 0x54494d48 /* 'TIMH' */
+#define NTIM_ID_OBMI 0x4f424d49 /* 'OBMI' */
+#define NTIM_ID_BOOT 0x424f4f54 /* 'BOOT' */
+#define NTIM_ID_LAST 0xffffffff
+#define NTIM_OEM_UNIQUE_ID 0xcafeaffe
+#define NTIM_FLASH_INFO_NAND 0x4e414e06
+
+/* Where the Boot ROM puts the header itself. Fixed, see the Boot ROM manual. */
+#define NTIM_LOAD_ADDR 0x5c008000
+
+/*
+ * The vendor image declares 0xff for the header itself and rounds the OBM up
+ * to a NAND page. Stay byte compatible with it: this is the one configuration
+ * known to boot.
+ */
+#define NTIM_HEADER_CRC_SIZE 0xff
+#define NAND_PAGE_SIZE 2048
+
+struct ntim_header {
+ uint32_t version;
+ uint32_t identifier;
+ uint32_t trusted;
+ uint32_t issue_date;
+ uint32_t oem_unique_id;
+ uint32_t reserved[5];
+ uint32_t flash_info;
+ uint32_t num_images;
+ uint32_t num_keys;
+ uint32_t size_of_reserved;
+};
+
+struct ntim_image {
+ uint32_t image_id;
+ uint32_t next_image_id;
+ uint32_t flash_entry_addr;
+ uint32_t load_addr;
+ uint32_t image_size;
+ uint32_t reserved[10];
+};
+
+static void put32(void *buf, uint32_t v)
+{
+ unsigned char *p = buf;
+
+ p[0] = v; p[1] = v >> 8; p[2] = v >> 16; p[3] = v >> 24;
+}
+
+static void *read_file(const char *name, size_t *size)
+{
+ struct stat st;
+ void *buf;
+ FILE *f;
+
+ f = fopen(name, "rb");
+ if (!f) {
+ fprintf(stderr, "cannot open %s: %s\n", name, strerror(errno));
+ return NULL;
+ }
+ if (fstat(fileno(f), &st) < 0) {
+ fprintf(stderr, "cannot stat %s: %s\n", name, strerror(errno));
+ fclose(f);
+ return NULL;
+ }
+
+ buf = malloc(st.st_size);
+ if (!buf) {
+ fclose(f);
+ return NULL;
+ }
+
+ if (fread(buf, 1, st.st_size, f) != (size_t)st.st_size) {
+ fprintf(stderr, "short read on %s\n", name);
+ free(buf);
+ fclose(f);
+ return NULL;
+ }
+
+ fclose(f);
+ *size = st.st_size;
+
+ return buf;
+}
+
+/*
+ * The header and both images are written at their flash offsets, the gaps are
+ * filled with 0xff so that the result can be written to erased NAND as is.
+ */
+static int pad_to(FILE *out, size_t *pos, size_t target, const char *what)
+{
+ if (*pos > target) {
+ fprintf(stderr, "%s does not fit below 0x%zx (ends at 0x%zx)\n",
+ what, target, *pos);
+ return -1;
+ }
+
+ while (*pos < target) {
+ if (fputc(0xff, out) == EOF)
+ return -1;
+ (*pos)++;
+ }
+
+ return 0;
+}
+
+static void usage(const char *argv0)
+{
+ fprintf(stderr,
+"usage: %s -o OUT -b OBM -f BAREBOX [options]\n"
+" -o FILE output image\n"
+" -b FILE OBM image (barebox PBL for internal SRAM)\n"
+" -f FILE barebox image\n"
+" -O OFFSET flash offset of the OBM (default 0x800)\n"
+" -L ADDR load address of the OBM (default 0x5c020000)\n"
+" -F OFFSET flash offset of barebox (default 0x20000)\n"
+" -A ADDR load address of barebox (default 0x81000000)\n"
+" -M SIZE maximum total image size, 0 to disable (default 0x200000)\n",
+ argv0);
+}
+
+int main(int argc, char *argv[])
+{
+ const char *outfile = NULL, *obmfile = NULL, *bootfile = NULL;
+ unsigned long obm_offset = 0x800, obm_load = 0x5c020000;
+ unsigned long boot_offset = 0x20000, boot_load = 0x81000000;
+ unsigned long max_size = 0x200000;
+ size_t obm_size, boot_size, pos = 0;
+ void *obm, *boot;
+ struct ntim_header hdr;
+ struct ntim_image img[3];
+ FILE *out;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "o:b:f:O:L:F:A:M:h")) != -1) {
+ switch (opt) {
+ case 'o': outfile = optarg; break;
+ case 'b': obmfile = optarg; break;
+ case 'f': bootfile = optarg; break;
+ case 'O': obm_offset = strtoul(optarg, NULL, 0); break;
+ case 'L': obm_load = strtoul(optarg, NULL, 0); break;
+ case 'F': boot_offset = strtoul(optarg, NULL, 0); break;
+ case 'A': boot_load = strtoul(optarg, NULL, 0); break;
+ case 'M': max_size = strtoul(optarg, NULL, 0); break;
+ default:
+ usage(argv[0]);
+ return opt == 'h' ? 0 : 1;
+ }
+ }
+
+ if (!outfile || !obmfile || !bootfile) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ obm = read_file(obmfile, &obm_size);
+ if (!obm)
+ return 1;
+ boot = read_file(bootfile, &boot_size);
+ if (!boot)
+ return 1;
+
+ memset(&hdr, 0, sizeof(hdr));
+ put32(&hdr.version, NTIM_VERSION);
+ put32(&hdr.identifier, NTIM_ID_TIMH);
+ put32(&hdr.trusted, 0);
+ put32(&hdr.issue_date, 0);
+ put32(&hdr.oem_unique_id, NTIM_OEM_UNIQUE_ID);
+ memset(hdr.reserved, 0xff, sizeof(hdr.reserved));
+ put32(&hdr.flash_info, NTIM_FLASH_INFO_NAND);
+ put32(&hdr.num_images, 3);
+ put32(&hdr.num_keys, 0);
+ put32(&hdr.size_of_reserved, 0);
+
+ memset(img, 0, sizeof(img));
+
+ /* The header describes itself first. */
+ put32(&img[0].image_id, NTIM_ID_TIMH);
+ put32(&img[0].next_image_id, NTIM_ID_OBMI);
+ put32(&img[0].flash_entry_addr, 0);
+ put32(&img[0].load_addr, NTIM_LOAD_ADDR);
+ put32(&img[0].image_size, NTIM_HEADER_CRC_SIZE);
+
+ put32(&img[1].image_id, NTIM_ID_OBMI);
+ put32(&img[1].next_image_id, NTIM_ID_BOOT);
+ put32(&img[1].flash_entry_addr, obm_offset);
+ put32(&img[1].load_addr, obm_load);
+ put32(&img[1].image_size,
+ (obm_size + NAND_PAGE_SIZE - 1) & ~(NAND_PAGE_SIZE - 1));
+
+ /*
+ * image_size is what the OBM copies out of NAND, so it has to be the
+ * real size of the barebox image rather than the CRC'd part.
+ */
+ put32(&img[2].image_id, NTIM_ID_BOOT);
+ put32(&img[2].next_image_id, NTIM_ID_LAST);
+ put32(&img[2].flash_entry_addr, boot_offset);
+ put32(&img[2].load_addr, boot_load);
+ put32(&img[2].image_size, boot_size);
+
+ out = fopen(outfile, "wb");
+ if (!out) {
+ fprintf(stderr, "cannot create %s: %s\n", outfile,
+ strerror(errno));
+ return 1;
+ }
+
+ if (fwrite(&hdr, 1, sizeof(hdr), out) != sizeof(hdr))
+ goto write_error;
+ pos += sizeof(hdr);
+ if (fwrite(img, 1, sizeof(img), out) != sizeof(img))
+ goto write_error;
+ pos += sizeof(img);
+
+ if (pad_to(out, &pos, obm_offset, "NTIM header"))
+ goto error;
+ if (fwrite(obm, 1, obm_size, out) != obm_size)
+ goto write_error;
+ pos += obm_size;
+
+ if (pad_to(out, &pos, boot_offset, "OBM"))
+ goto error;
+ if (fwrite(boot, 1, boot_size, out) != boot_size)
+ goto write_error;
+ pos += boot_size;
+
+ if (max_size && pos > max_size) {
+ fprintf(stderr,
+ "image is 0x%zx bytes, exceeds the maximum of 0x%lx\n",
+ pos, max_size);
+ goto error;
+ }
+
+ fclose(out);
+
+ printf("pxa-image: NTIM + OBM (0x%zx @ 0x%lx) + barebox (0x%zx @ 0x%lx)"
+ " = 0x%zx bytes\n", obm_size, obm_offset, boot_size, boot_offset,
+ pos);
+
+ return 0;
+
+write_error:
+ fprintf(stderr, "write error on %s: %s\n", outfile, strerror(errno));
+error:
+ fclose(out);
+ remove(outfile);
+
+ return 1;
+}
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 20/27] ARM: pxa: add a NAND first stage loader
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (18 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 19/27] scripts: add pxa-image Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 21/27] filetype: detect PXA3xx NTIM images Sascha Hauer
` (8 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA3xx Boot ROM reads a NTIM header from the start of the boot
device, copies the OBM listed in it into internal SRAM and jumps to it.
It does not come back, so the OBM has to fetch the next image itself.
Add the pieces a PXA3xx board needs to be that OBM: pxa_nand_load_image()
reads the NTIM from flash rather than relying on the copy the Boot ROM
left in its scratch area, looks up an image by id and copies exactly as
many bytes as the header says.
Bad blocks are skipped, so the flash offsets in the NTIM count good
blocks only rather than addressing the device directly. That is what
mtd_peb_write_file() produces when a board writes such an image, so the
two ends agree on where an image is without either of them having to
record where the bad blocks are. Getting at the marker needs SPARE_EN in
NDCR, which makes the controller hand the spare area out along with the
page; with ECC_EN clear that is all 64 bytes of it, and the first is the
marker on a large page device. Only the first page of a block is checked:
vendors put the marker in the first page, the second or the last
depending on the part, and reading the first is what a first stage can
afford.
The NTIM itself is not covered by any of that, and does not need to be:
scripts/pxa-image puts it and the OBM in the first erase block, which the
chip guarantees to be good.
Everything here runs from internal SRAM before DRAM is usable for
anything but the destination, so it uses no global data and no stack
beyond what the entry function set up.
Alongside it goes the image rule that turns a PBL image into the layout
the Boot ROM expects, driven by scripts/pxa-image.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/Makefile | 2 +
arch/arm/mach-pxa/xload-nand.c | 255 +++++++++++++++++++++++++++++++++++++++++
images/Makefile | 1 +
images/Makefile.pxa | 18 +++
include/mach/pxa/xload.h | 42 +++++++
5 files changed, 318 insertions(+)
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index fa0793d8a9..4069a47251 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -6,3 +6,5 @@ obj-y += common.o
obj-y += devices.o
obj-$(CONFIG_ARCH_PXA3XX) += mfp-pxa3xx.o pxa3xx.o
+
+pbl-$(CONFIG_ARCH_PXA3XX) += xload-nand.o
diff --git a/arch/arm/mach-pxa/xload-nand.c b/arch/arm/mach-pxa/xload-nand.c
new file mode 100644
index 0000000000..c03f0e52cd
--- /dev/null
+++ b/arch/arm/mach-pxa/xload-nand.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Load barebox from NAND in the PXA3xx first stage.
+ *
+ * The Boot ROM reads the NTIM header from the start of NAND, copies the OBM
+ * listed in it into internal SRAM and jumps there. It does not come back, so
+ * the OBM has to fetch the next image itself.
+ *
+ * Everything here runs from internal SRAM before DRAM is usable for anything
+ * but the destination, so it uses no global data and no stack beyond what the
+ * entry function set up.
+ *
+ * The NTIM itself is in the first erase block, which the chip guarantees to be
+ * good, so it is always where the Boot ROM and this code expect it. Everything
+ * behind it is read past bad blocks.
+ */
+
+#include <common.h>
+#include <linux/sizes.h>
+#include <asm/io.h>
+#include <mach/pxa/xload.h>
+
+#define NAND_BASE 0x43100000
+
+#define NDCR 0x00
+#define NDTR0CS0 0x04
+#define NDTR1CS0 0x0c
+#define NDSR 0x14
+#define NDDB 0x40
+#define NDCB0 0x48
+
+#define NDCR_SPARE_EN (1 << 31)
+#define NDCR_ND_RUN (1 << 28)
+
+#define NDSR_WRCMDREQ (1 << 0)
+#define NDSR_RDDREQ (1 << 1)
+
+/*
+ * Values taken from the vendor OBM. NDCR configures a x8 device with 2K
+ * pages; the timings are the ones the previous stage is known to work with.
+ *
+ * SPARE_EN is ours: it makes the controller hand out the spare area along
+ * with the data, which is where the bad block marker is. With ECC_EN clear
+ * that is all 64 bytes of it.
+ */
+#define NDCR_INIT (0x01045fff | NDCR_SPARE_EN)
+#define NDTR0CS0_INIT 0x00161c1c
+#define NDTR1CS0_INIT 0x0f3d00f2
+
+/*
+ * Read command for a 2K page device: 0x00 followed by 0x30, five address
+ * cycles, double byte command.
+ */
+#define NDCB0_READ_PAGE 0x000d3000
+
+#define NAND_PAGE_SIZE 2048
+#define NAND_OOB_SIZE 64
+#define NAND_BLOCK_SIZE SZ_128K
+
+/* A device with more bad blocks than this in front of the image is broken. */
+#define NAND_MAX_BAD_BLOCKS 16
+
+static void pxa_nand_init(void __iomem *base)
+{
+ int i;
+
+ writel(0, base + NDCR);
+ writel(NDTR0CS0_INIT, base + NDTR0CS0);
+ writel(NDTR1CS0_INIT, base + NDTR1CS0);
+ writel(0x00000fff, base + NDSR);
+ writel(NDCR_INIT, base + NDCR);
+
+ /* Drain whatever the controller has left in the data buffer. */
+ for (i = 0; i < 16; i++)
+ readl(base + NDDB);
+}
+
+/*
+ * Read one page. 'offset' is a physical byte offset into the device and has to
+ * be page aligned. @buf takes the data and @oob the spare area; either may be
+ * NULL to read past that part of the page without keeping it. The controller
+ * hands out both whatever we do with them, so they have to be read either way.
+ */
+static void pxa_nand_read_page(void __iomem *base, u32 offset, void *buf,
+ void *oob)
+{
+ u32 *dest;
+ u32 addr;
+ int i;
+
+ writel(readl(base + NDCR) | NDCR_ND_RUN, base + NDCR);
+
+ while (!(readl(base + NDSR) & NDSR_WRCMDREQ))
+ ;
+
+ readl(base + NDDB);
+ readl(base + NDDB);
+
+ /* column in the low bits, page number from bit 16 upwards */
+ addr = (offset & 0x7ff) | ((offset << 5) & 0xffff0000);
+
+ writel(NDCB0_READ_PAGE, base + NDCB0);
+ writel(addr, base + NDCB0);
+ writel(0, base + NDCB0);
+
+ while (!(readl(base + NDSR) & NDSR_RDDREQ))
+ ;
+ writel(NDSR_RDDREQ, base + NDSR);
+
+ dest = buf;
+ for (i = 0; i < NAND_PAGE_SIZE / 4; i++) {
+ u32 val = readl(base + NDDB);
+
+ if (dest)
+ *dest++ = val;
+ }
+
+ /* The spare area follows the data. */
+ dest = oob;
+ for (i = 0; i < NAND_OOB_SIZE / 4; i++) {
+ u32 val = readl(base + NDDB);
+
+ if (dest)
+ *dest++ = val;
+ }
+}
+
+static bool pxa_nand_block_is_bad(void __iomem *base, u32 offset)
+{
+ /* pxa_nand_read_page() fills this a word at a time */
+ u8 oob[NAND_OOB_SIZE] __aligned(4);
+
+ pxa_nand_read_page(base, offset, NULL, oob);
+
+ /*
+ * The bad block marker is the first byte of the spare area on a large
+ * page device.
+ */
+ return oob[0] != 0xff;
+}
+
+/*
+ * Read @size bytes from @offset, which is an offset into the good blocks of
+ * the device rather than into the device itself: bad blocks are skipped and do
+ * not count towards it. That is the same thing mtd_peb_write_file() does when
+ * the update handler writes the image, so the two agree on where an image is
+ * without either of them having to record where the bad blocks are.
+ *
+ * Returns false if the image could not be read.
+ */
+static bool pxa_nand_read(void __iomem *base, u32 offset, void *buf, u32 size)
+{
+ unsigned int skipped = 0;
+ u32 phys = 0, log = 0;
+
+ while (size) {
+ /*
+ * Only the first page of a block carries the marker, so this
+ * is the one point where a block can be rejected.
+ */
+ if (!(phys & (NAND_BLOCK_SIZE - 1)) &&
+ pxa_nand_block_is_bad(base, phys)) {
+ if (++skipped > NAND_MAX_BAD_BLOCKS)
+ return false;
+ phys += NAND_BLOCK_SIZE;
+ continue;
+ }
+
+ /* Not at the image yet, so there is nothing to keep. */
+ if (log < offset) {
+ phys += NAND_PAGE_SIZE;
+ log += NAND_PAGE_SIZE;
+ continue;
+ }
+
+ pxa_nand_read_page(base, phys, buf, NULL);
+ buf += NAND_PAGE_SIZE;
+ phys += NAND_PAGE_SIZE;
+ log += NAND_PAGE_SIZE;
+ size -= min_t(u32, size, NAND_PAGE_SIZE);
+ }
+
+ return true;
+}
+
+/**
+ * pxa_nand_load_image - load the next image out of NAND
+ * @image_id: NTIM id of the image to load, eg NTIM_ID_BOOT
+ *
+ * Reads the NTIM header from the start of the device, looks up the entry for
+ * @image_id and copies that image to the load address the header gives. The
+ * flash offset in that entry counts good blocks only; see pxa_nand_read().
+ *
+ * The header is read from flash rather than taken from the address the Boot
+ * ROM loaded it to, so that this does not depend on the ROM's scratch area
+ * still being intact.
+ *
+ * What this expects of the flash. None of it is discovered: the register
+ * values at the top of this file are one board's, recovered from its vendor
+ * OBM, and the geometry is hardcoded to match them, so a device that differs
+ * in any of these needs more than new timings.
+ *
+ * - 2048 byte pages. That is NDCR PAGE_SZ, the five address cycles and the
+ * double byte command in NDCB0_READ_PAGE, and the 11 column bits in the
+ * address. A 512 byte page device needs all four changed.
+ *
+ * - An 8 bit bus, ie NDCR DWIDTH_M and DWIDTH_C clear.
+ *
+ * - 64 pages to an erase block, ie NDCR PG_PER_BLK set. NAND_BLOCK_SIZE has
+ * to say the same thing and nothing checks that it does.
+ *
+ * - 64 bytes of spare area, which is what the controller hands out for a 2K
+ * page with SPARE_EN set and ECC_EN clear.
+ *
+ * - The bad block marker in the first byte of the spare area of a block's
+ * first page. Parts that mark the second or the last page instead are not
+ * noticed.
+ *
+ * Return: the load address of the image, or NULL if it could not be loaded
+ */
+void *pxa_nand_load_image(u32 image_id)
+{
+ void __iomem *base = IOMEM(NAND_BASE);
+ u8 page[NAND_PAGE_SIZE] __aligned(4);
+ struct ntim_header *hdr;
+ struct ntim_image *img;
+ u32 i, num_images;
+
+ pxa_nand_init(base);
+ pxa_nand_read_page(base, 0, page, NULL);
+
+ hdr = (void *)page;
+ if (hdr->identifier != NTIM_ID_TIMH ||
+ hdr->oem_unique_id != NTIM_OEM_UNIQUE_ID)
+ return NULL;
+
+ num_images = hdr->num_images;
+ if (!num_images || num_images > NTIM_MAX_IMAGES)
+ return NULL;
+
+ img = (void *)(hdr + 1);
+
+ for (i = 0; i < num_images; i++) {
+ if (img[i].image_id != image_id)
+ continue;
+
+ if (!pxa_nand_read(base, img[i].flash_entry_addr,
+ (void *)img[i].load_addr, img[i].image_size))
+ return NULL;
+
+ return (void *)img[i].load_addr;
+ }
+
+ return NULL;
+}
diff --git a/images/Makefile b/images/Makefile
index 91425dd3a0..f8e853418d 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -183,6 +183,7 @@ include $(srctree)/images/Makefile.malta
include $(srctree)/images/Makefile.mvebu
include $(srctree)/images/Makefile.mxs
include $(srctree)/images/Makefile.omap3
+include $(srctree)/images/Makefile.pxa
include $(srctree)/images/Makefile.rockchip
include $(srctree)/images/Makefile.exynos
include $(srctree)/images/Makefile.sandbox
diff --git a/images/Makefile.pxa b/images/Makefile.pxa
new file mode 100644
index 0000000000..023aec428d
--- /dev/null
+++ b/images/Makefile.pxa
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# barebox image generation Makefile for PXA images
+#
+
+# A first stage image: the NTIM header the Boot ROM reads from NAND, the OBM
+# it loads into internal SRAM, and barebox for the OBM to load into DRAM.
+quiet_cmd_pxa_image = PXAIMG $@
+ cmd_pxa_image = $(objtree)/scripts/pxa-image \
+ -b $< -f $(obj)/$(PXA_PAYLOAD_$(@F)) -o $@ \
+ $(if $(PXA_OBM_OFFSET_$(@F)),-O $(PXA_OBM_OFFSET_$(@F))) \
+ $(if $(PXA_OBM_LOAD_$(@F)),-L $(PXA_OBM_LOAD_$(@F))) \
+ $(if $(PXA_BOOT_OFFSET_$(@F)),-F $(PXA_BOOT_OFFSET_$(@F))) \
+ $(if $(PXA_BOOT_LOAD_$(@F)),-A $(PXA_BOOT_LOAD_$(@F))) \
+ $(if $(PXA_MAX_SIZE_$(@F)),-M $(PXA_MAX_SIZE_$(@F)))
+
+$(obj)/%.pxaimg: $(obj)/% $(obj)/$$(PXA_PAYLOAD_$$(@F)) FORCE
+ $(call if_changed,pxa_image)
diff --git a/include/mach/pxa/xload.h b/include/mach/pxa/xload.h
new file mode 100644
index 0000000000..d24b180cbf
--- /dev/null
+++ b/include/mach/pxa/xload.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __MACH_PXA_XLOAD_H
+#define __MACH_PXA_XLOAD_H
+
+#include <linux/types.h>
+
+#define NTIM_ID_TIMH 0x54494d48 /* 'TIMH' */
+#define NTIM_ID_OBMI 0x4f424d49 /* 'OBMI' */
+#define NTIM_ID_BOOT 0x424f4f54 /* 'BOOT' */
+#define NTIM_OEM_UNIQUE_ID 0xcafeaffe
+
+#define NTIM_MAX_IMAGES 8
+
+/*
+ * Non-Trusted Image Module, the header the PXA3xx Boot ROM reads from the
+ * start of the boot device. Written by scripts/pxa-image.
+ */
+struct ntim_header {
+ u32 version;
+ u32 identifier;
+ u32 trusted;
+ u32 issue_date;
+ u32 oem_unique_id;
+ u32 reserved[5];
+ u32 flash_info;
+ u32 num_images;
+ u32 num_keys;
+ u32 size_of_reserved;
+};
+
+struct ntim_image {
+ u32 image_id;
+ u32 next_image_id;
+ u32 flash_entry_addr;
+ u32 load_addr;
+ u32 image_size;
+ u32 reserved[10];
+};
+
+void *pxa_nand_load_image(u32 image_id);
+
+#endif /* __MACH_PXA_XLOAD_H */
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 21/27] filetype: detect PXA3xx NTIM images
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (19 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 20/27] ARM: pxa: add a NAND first stage loader Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 22/27] ARM: pxa: add a barebox update handler for NAND Sascha Hauer
` (7 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The image scripts/pxa-image builds - the NTIM header the PXA3xx Boot ROM
reads from the start of the boot device, the OBM and barebox - has no
filetype, so the one thing that cares has to recognise it by hand.
The header carries no magic. Match the version field, which is the one
the Boot ROM in these parts expects and the only one the tool emits,
together with the 'TIMH' identifier that follows it.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/filetype.c | 11 +++++++++++
include/filetype.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/common/filetype.c b/common/filetype.c
index 01cef7f1fb..5f65b8a4f6 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -91,6 +91,7 @@ static const struct filetype_str filetype_str[] = {
"rk-image" },
[filetype_x86_linux_image] = { "x86 Linux image", "x86-linux" },
[filetype_x86_efi_linux_image] = { "x86 Linux/EFI image", "x86-efi-linux" },
+ [filetype_pxa_ntim] = { "Marvell PXA3xx NTIM image", "pxa-ntim" },
};
static const char *file_type_to_nr_string(enum filetype f)
@@ -386,6 +387,16 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
if (buf[0] == be32_to_cpu(0x534F4659))
return filetype_bpk;
+ /*
+ * The NTIM header the PXA3xx Boot ROM reads from the start of the boot
+ * device. It has no magic of its own, so match the version the images
+ * barebox builds carry along with the identifier of the header itself,
+ * which is the first of the image entries behind it.
+ */
+ if (le32_to_cpu(buf[0]) == 0x00030102 &&
+ le32_to_cpu(buf[1]) == 0x54494d48) /* 'TIMH' */
+ return filetype_pxa_ntim;
+
if (strncmp(buf8, "RKNS", 4) == 0)
return filetype_rockchip_rkns_image;
if (strncmp(buf8, "RKSS", 4) == 0)
diff --git a/include/filetype.h b/include/filetype.h
index 2fd0e22177..5b0bd9d399 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -72,6 +72,7 @@ enum filetype {
filetype_rockchip_rkss_image,
filetype_x86_linux_image,
filetype_x86_efi_linux_image,
+ filetype_pxa_ntim,
filetype_max,
};
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 22/27] ARM: pxa: add a barebox update handler for NAND
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (20 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 21/27] filetype: detect PXA3xx NTIM images Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 23/27] clocksource: add a driver for the PXA OS timer and its watchdog Sascha Hauer
` (6 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA3xx Boot ROM boots from the start of the flash: an NTIM header,
the OBM it copies into internal SRAM and the image the OBM loads into
DRAM, all in one blob built by scripts/pxa-image. Add an update handler
that writes such a blob to the mtd partition covering it, so a board can
replace its own bootloader with barebox_update.
bbu_register_std_file_update() would do the copy, but it goes through
the cdev and writes straight over a bad block. Use mtd_peb_write_file()
instead, which skips them, so what lands in flash is the image with the
bad blocks taken out of it. That is what the other end expects:
pxa_nand_load_image() reads the flash offsets in the NTIM as offsets into
the good blocks and skips the bad ones the same way. The NTIM and the OBM
are in the first erase block, which cannot be bad, so the Boot ROM -
which knows nothing of any of this - always finds them where it looks.
The image is checked for filetype_pxa_ntim before anything is erased.
Writing something else to this partition leaves a board that only JTAG
can talk to.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/Kconfig | 9 +++++
arch/arm/mach-pxa/Makefile | 1 +
arch/arm/mach-pxa/bbu.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
include/mach/pxa/bbu.h | 18 +++++++++
4 files changed, 124 insertions(+)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5bc99f1f83..b159cee0cc 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -19,4 +19,13 @@ config ARCH_PXA310
bool
select ARCH_PXA3XX
+config BAREBOX_UPDATE_PXA_NAND
+ prompt "barebox update NAND handler"
+ bool
+ depends on ARCH_PXA3XX && BAREBOX_UPDATE && MTD
+ help
+ Say Y here for an update handler that writes the image built by
+ scripts/pxa-image - the NTIM header, the OBM and barebox - to the
+ mtd partition the Boot ROM boots from.
+
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 4069a47251..86d9c4ca95 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -6,5 +6,6 @@ obj-y += common.o
obj-y += devices.o
obj-$(CONFIG_ARCH_PXA3XX) += mfp-pxa3xx.o pxa3xx.o
+obj-$(CONFIG_BAREBOX_UPDATE_PXA_NAND) += bbu.o
pbl-$(CONFIG_ARCH_PXA3XX) += xload-nand.o
diff --git a/arch/arm/mach-pxa/bbu.c b/arch/arm/mach-pxa/bbu.c
new file mode 100644
index 0000000000..981069a016
--- /dev/null
+++ b/arch/arm/mach-pxa/bbu.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * barebox update handler for the PXA3xx NAND boot partition.
+ */
+
+#include <common.h>
+#include <bbu.h>
+#include <filetype.h>
+#include <fs.h>
+#include <malloc.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <mtd/mtd-peb.h>
+#include <mach/pxa/bbu.h>
+
+static int pxa_bbu_nand_handler(struct bbu_handler *handler,
+ struct bbu_data *data)
+{
+ struct mtd_info *mtd;
+ struct cdev *cdev;
+ int ret;
+
+ /*
+ * The Boot ROM expects an NTIM header at the start of the boot
+ * device. Writing anything else here leaves a board that only JTAG
+ * can talk to.
+ */
+ if (file_detect_type(data->image, data->len) != filetype_pxa_ntim) {
+ if (!bbu_force(data, "%s is not a PXA3xx NTIM image",
+ data->imagefile))
+ return -EINVAL;
+ }
+
+ cdev = cdev_by_name(devpath_to_name(data->devicefile));
+ if (!cdev) {
+ pr_err("%s: no such device\n", data->devicefile);
+ return -ENODEV;
+ }
+
+ mtd = cdev->mtd;
+ if (!mtd) {
+ pr_err("%s is not a mtd device\n", data->devicefile);
+ return -EINVAL;
+ }
+
+ /* last chance before erasing the flash */
+ ret = bbu_confirm(data);
+ if (ret)
+ return ret;
+
+ ret = mtd_peb_write_file(mtd, 0, mtd_num_pebs(mtd), data->image,
+ data->len);
+ if (ret == -ENOSPC)
+ pr_err("%s holds %llu bytes, the image needs %zu\n",
+ data->devicefile, mtd->size, data->len);
+
+ return ret;
+}
+
+/**
+ * pxa_bbu_nand_register_handler - register a NAND update handler
+ * @name: Name of the handler
+ * @devicefile: the mtd partition the Boot ROM boots from
+ *
+ * Registers an update handler for the image built by scripts/pxa-image: the
+ * NTIM header the Boot ROM reads, the OBM it copies into internal SRAM, and
+ * the barebox image the OBM loads into DRAM.
+ *
+ * Unlike bbu_register_std_file_update() this goes through
+ * mtd_peb_write_file(), so a factory bad block in the boot partition is
+ * skipped rather than written to, and what lands in flash is the image with
+ * the bad blocks taken out of it. That is what the other side expects:
+ * pxa_nand_load_image() reads the flash offsets in the NTIM as offsets into
+ * the good blocks and skips the bad ones the same way. The NTIM and the OBM
+ * are in the first erase block, which cannot be bad, so the Boot ROM - which
+ * has no idea about any of this - always finds them where it looks.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int pxa_bbu_nand_register_handler(const char *name, const char *devicefile)
+{
+ struct bbu_handler *handler;
+ int ret;
+
+ handler = xzalloc(sizeof(*handler));
+ handler->devicefile = devicefile;
+ handler->name = name;
+ handler->handler = pxa_bbu_nand_handler;
+ handler->flags = BBU_HANDLER_FLAG_DEFAULT;
+
+ ret = bbu_register_handler(handler);
+ if (ret)
+ free(handler);
+
+ return ret;
+}
diff --git a/include/mach/pxa/bbu.h b/include/mach/pxa/bbu.h
new file mode 100644
index 0000000000..7b13009cf4
--- /dev/null
+++ b/include/mach/pxa/bbu.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __MACH_PXA_BBU_H
+#define __MACH_PXA_BBU_H
+
+#include <bbu.h>
+
+#ifdef CONFIG_BAREBOX_UPDATE_PXA_NAND
+int pxa_bbu_nand_register_handler(const char *name, const char *devicefile);
+#else
+static inline int pxa_bbu_nand_register_handler(const char *name,
+ const char *devicefile)
+{
+ return 0;
+}
+#endif
+
+#endif /* __MACH_PXA_BBU_H */
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 23/27] clocksource: add a driver for the PXA OS timer and its watchdog
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (21 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 22/27] ARM: pxa: add a barebox update handler for NAND Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 24/27] ARM: pxa: move over to MULTIARCH Sascha Hauer
` (5 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The PXA clocksource was registered from a core_initcall in mach-pxa which
is not suitable for multiarch. Move it over to a platform driver which probes
from device tree.
Match register 3 of the same timer doubles as a watchdog: arm it by writing
a match value ahead of the counter and setting OWER_WME, and the match
resets the machine. That is the same block the clocksource uses and there
is one device tree node for it, so register the watchdog from the same
driver rather than inventing a second node for the same registers.
OWER_WME cannot be cleared again - the watchdog runs until it resets the
machine - so refuse a timeout of zero once it is armed instead of
pretending to stop it. Verified on a PXA303: the board resets on schedule
whether or not something asked for it to be disabled in between.
The counter is 32 bit and the match has to fit in it, which puts the
maximum timeout at 1321s at this part's 3.25MHz.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/Makefile | 1 -
arch/arm/mach-pxa/clocksource.c | 41 -----------
drivers/clocksource/Kconfig | 7 ++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-pxa.c | 151 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 159 insertions(+), 42 deletions(-)
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 86d9c4ca95..7a9ca83199 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += clocksource.o
obj-y += sleep.o
obj-y += common.o
obj-y += devices.o
diff --git a/arch/arm/mach-pxa/clocksource.c b/arch/arm/mach-pxa/clocksource.c
deleted file mode 100644
index 3bc95827d8..0000000000
--- a/arch/arm/mach-pxa/clocksource.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * (C) Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <common.h>
-#include <init.h>
-#include <clock.h>
-#include <asm/io.h>
-
-#define OSCR 0x40A00010
-
-static uint64_t pxa_clocksource_read(void)
-{
- return readl(OSCR);
-}
-
-static struct clocksource cs = {
- .read = pxa_clocksource_read,
- .mask = 0xffffffff,
- .shift = 20,
- .priority = 80,
-};
-
-static int clocksource_init(void)
-{
- cs.mult = clocksource_hz2mult(3250000, cs.shift);
-
- return init_clock(&cs);
-}
-
-core_initcall(clocksource_init);
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 5ee83d2b38..89e0be7894 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -120,6 +120,13 @@ config ARMV7M_SYSTICK
help
This option enables support for the ARMv7M system timer unit.
+config CLOCKSOURCE_PXA
+ bool "Clocksource for PXA SoCs"
+ depends on OFDEVICE && (ARCH_PXA || COMPILE_TEST)
+ default ARCH_PXA
+ help
+ This option enables support for the OS timer found on PXA SoCs.
+
config CLKSRC_STM32
bool "Clocksource for STM32 SoCs"
depends on OFDEVICE && (ARCH_STM32 || COMPILE_TEST)
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index dff8255650..0f8a54d819 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_CLINT_TIMER) += timer-clint.o
obj-$(CONFIG_RISCV_TIMER) += timer-riscv.o
obj-$(CONFIG_ARMV7M_SYSTICK) += armv7m_systick.o
obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o
+obj-$(CONFIG_CLOCKSOURCE_PXA) += timer-pxa.o
diff --git a/drivers/clocksource/timer-pxa.c b/drivers/clocksource/timer-pxa.c
new file mode 100644
index 0000000000..8834bbec0c
--- /dev/null
+++ b/drivers/clocksource/timer-pxa.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Clocksource and watchdog for the PXA OS timer.
+ *
+ * The two are one block: match register 3 doubles as the watchdog, so both
+ * live in the same driver rather than fighting over the device tree node.
+ *
+ * (C) Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <driver.h>
+#include <init.h>
+#include <io.h>
+#include <watchdog.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#define OSMR3 0x0c /* match register 3, the watchdog match */
+#define OSCR 0x10 /* counter, free running and running out of reset */
+#define OSSR 0x14 /* status */
+#define OWER 0x18 /* watchdog enable */
+
+#define OSSR_M3 (1 << 3) /* match status channel 3 */
+#define OWER_WME (1 << 0) /* watchdog match enable */
+
+struct pxa_timer {
+ void __iomem *base;
+ unsigned long rate;
+ struct watchdog wd;
+};
+
+static inline struct pxa_timer *to_pxa_timer(struct watchdog *wd)
+{
+ return container_of(wd, struct pxa_timer, wd);
+}
+
+static void __iomem *pxa_timer_base;
+
+static uint64_t pxa_clocksource_read(void)
+{
+ return readl(pxa_timer_base + OSCR);
+}
+
+static struct clocksource pxa_cs = {
+ .read = pxa_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .priority = 80,
+};
+
+static int pxa_wdt_set_timeout(struct watchdog *wd, unsigned timeout)
+{
+ struct pxa_timer *timer = to_pxa_timer(wd);
+
+ if (!timeout) {
+ /*
+ * OWER_WME only ever reads back the way it was written once:
+ * the watchdog cannot be stopped again short of the reset it
+ * is about to cause. Refuse rather than pretend.
+ */
+ if (wd->running == WDOG_HW_RUNNING)
+ return -ENOSYS;
+
+ return 0;
+ }
+
+ writel(readl(timer->base + OSCR) + (u64)timeout * timer->rate,
+ timer->base + OSMR3);
+ writel(OSSR_M3, timer->base + OSSR);
+ writel(OWER_WME, timer->base + OWER);
+
+ wd->running = WDOG_HW_RUNNING;
+
+ return 0;
+}
+
+static int pxa_timer_probe(struct device *dev)
+{
+ struct resource *iores;
+ struct pxa_timer *timer;
+ struct clk *clk;
+ int ret;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ clk = clk_get(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk), "cannot get clock\n");
+
+ ret = clk_enable(clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "cannot enable clock\n");
+
+ timer = xzalloc(sizeof(*timer));
+ timer->base = IOMEM(iores->start);
+ timer->rate = clk_get_rate(clk);
+ if (!timer->rate)
+ return dev_err_probe(dev, -EINVAL, "clock has no rate\n");
+
+ pxa_timer_base = timer->base;
+ pxa_cs.mult = clocksource_hz2mult(timer->rate, pxa_cs.shift);
+
+ ret = init_clock(&pxa_cs);
+ if (ret)
+ return ret;
+
+ timer->wd.set_timeout = pxa_wdt_set_timeout;
+ timer->wd.hwdev = dev;
+ timer->wd.name = "pxa-wdt";
+ /* the counter is 32 bit, so that is as far ahead as a match reaches */
+ timer->wd.timeout_max = U32_MAX / timer->rate;
+ timer->wd.running = readl(timer->base + OWER) & OWER_WME ?
+ WDOG_HW_RUNNING : WDOG_HW_NOT_RUNNING;
+
+ ret = watchdog_register(&timer->wd);
+ if (ret)
+ dev_warn(dev, "failed to register watchdog: %pe\n",
+ ERR_PTR(ret));
+
+ return 0;
+}
+
+static const struct of_device_id pxa_timer_dt_ids[] = {
+ { .compatible = "marvell,pxa-timer" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pxa_timer_dt_ids);
+
+static struct driver pxa_timer_driver = {
+ .name = "pxa-timer",
+ .probe = pxa_timer_probe,
+ .of_compatible = pxa_timer_dt_ids,
+};
+postcore_platform_driver(pxa_timer_driver);
+
+/*
+ * Under deep probe nothing refers to the timer by phandle, so it is not probed
+ * until the device tree walk reaches it - and that walk is in device tree
+ * order, which on PXA3xx puts the NAND controller a long way ahead of the
+ * timer. Everything in between would run its timeouts against the dummy
+ * clocksource.
+ */
+static int pxa_timer_of_init(void)
+{
+ return of_devices_ensure_probed_by_dev_id(pxa_timer_dt_ids);
+}
+coredevice_initcall(pxa_timer_of_init);
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 24/27] ARM: pxa: move over to MULTIARCH
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (22 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 23/27] clocksource: add a driver for the PXA OS timer and its watchdog Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 25/27] ARM: pxa: reset straight away and without complaining Sascha Hauer
` (4 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
PXA was one of the architectures left in the "ARM system type" choice,
so a build could contain it or another architecture, never both.
Nothing about the SoC support requires that anymore, but its initcalls
did: the restart handler and the poweroff handler were registered
unconditionally and go straight at PXA registers, which on a multiarch
build would run on whatever else is in the image. Guard both with
of_machine_is_compatible() and move the architecture out of the choice.
For that to work the board has to identify as a PXA3xx. The SoC device
tree include says so, but a board that overrides the root compatible has
to keep it in its list.
While at it, drop the separate device_initcall() for
pxa_detect_reset_source(): pxa3xx_init() already calls it, so the reset
source was detected twice.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/Kconfig | 16 ++++++++--------
arch/arm/mach-pxa/common.c | 4 ++++
arch/arm/mach-pxa/pxa3xx.c | 6 ++++--
3 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 106f3d559e..6a4825fe33 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -118,14 +118,6 @@ config ARCH_MXS
select COMMON_CLK
select HAS_DEBUG_LL
-config ARCH_PXA
- bool "Intel/Marvell PXA based"
- depends on 32BIT
- select GPIOLIB
- select HAS_DEBUG_LL
- select OFTREE
- select OFDEVICE
-
config ARCH_SOCFPGA
bool "Altera SOCFPGA"
select HAS_DEBUG_LL
@@ -188,6 +180,14 @@ config ARCH_K3
select COMMON_CLK_OF_PROVIDER
select PM_GENERIC_DOMAINS
+config ARCH_PXA
+ bool "Intel/Marvell PXA based"
+ depends on 32BIT
+ select GPIOLIB
+ select HAS_DEBUG_LL
+ select OFTREE
+ select OFDEVICE
+
config ARCH_SUNXI
bool "Allwinner (sunxi) SoCs"
depends on ARCH_MULTIARCH
diff --git a/arch/arm/mach-pxa/common.c b/arch/arm/mach-pxa/common.c
index 1da1b58054..fea570c5fa 100644
--- a/arch/arm/mach-pxa/common.c
+++ b/arch/arm/mach-pxa/common.c
@@ -13,6 +13,7 @@
*/
#include <common.h>
+#include <of.h>
#include <init.h>
#include <restart.h>
#include <mach/pxa/pxa-regs.h>
@@ -42,6 +43,9 @@ static void __noreturn pxa_restart_soc(struct restart_handler *rst,
static int restart_register_feature(void)
{
+ if (!of_machine_is_compatible("marvell,pxa3xx"))
+ return 0;
+
restart_handler_register_fn("soc-wdt", pxa_restart_soc);
return 0;
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index ea84efc8b0..6edc55481e 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -13,6 +13,7 @@
*/
#include <common.h>
+#include <of.h>
#include <init.h>
#include <poweroff.h>
#include <reset_source.h>
@@ -47,8 +48,6 @@ void pxa_clear_reset_source(void)
ARSR = ARSR_GPR | ARSR_LPMR | ARSR_WDT | ARSR_HWR;
}
-device_initcall(pxa_detect_reset_source);
-
static void __noreturn pxa3xx_poweroff(struct poweroff_handler *handler,
unsigned long flags)
{
@@ -62,6 +61,9 @@ static void __noreturn pxa3xx_poweroff(struct poweroff_handler *handler,
static int pxa3xx_init(void)
{
+ if (!of_machine_is_compatible("marvell,pxa3xx"))
+ return 0;
+
poweroff_handler_register_fn(pxa3xx_poweroff);
pxa_detect_reset_source();
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 25/27] ARM: pxa: reset straight away and without complaining
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (23 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 24/27] ARM: pxa: move over to MULTIARCH Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 26/27] ARM: pxa: add Raumfeld Speaker board support Sascha Hauer
` (3 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
Two things made a working reset look like a failure. It waited 113ms for
the watchdog match, and it spent them inside hang(), which prints
"### ERROR ### Please RESET the board ###" - so a reset announced itself
as a board that needs one.
There is no reason to wait. Park the counter just below the match instead
of computing the match from the counter: both writes are absolute, so the
match is still ahead whenever the second one lands, and the margin no
longer has to cover the store that sets it up. 16 ticks is about 5us at
this part's 3.25MHz. Computing it the other way round has to guess that
margin, and losing the race costs a full 32bit wrap of the counter rather
than a retry.
Then spin quietly rather than calling hang().
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-pxa/common.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-pxa/common.c b/arch/arm/mach-pxa/common.c
index fea570c5fa..d76167438a 100644
--- a/arch/arm/mach-pxa/common.c
+++ b/arch/arm/mach-pxa/common.c
@@ -27,6 +27,13 @@
#define OWER_WME (1 << 0) /* Watch-dog Match Enable */
#define OSSR_M3 (1 << 3) /* Match status channel 3 */
+/*
+ * Where to park the counter, and how far below the match to park it. The
+ * counter runs at 3.25MHz on PXA3xx, so 16 ticks is around 5us.
+ */
+#define RESET_MATCH 0x1000
+#define RESET_MARGIN 16
+
static void __noreturn pxa_restart_soc(struct restart_handler *rst,
unsigned long flags)
{
@@ -36,9 +43,23 @@ static void __noreturn pxa_restart_soc(struct restart_handler *rst,
/* Initialize the watchdog and let it fire */
writel(OWER_WME, OWER);
writel(OSSR_M3, OSSR);
- writel(readl(OSCR) + 368640, OSMR3); /* ... in 100 ms */
- hang();
+ /*
+ * Set the match, then put the counter just below it. Both writes are
+ * absolute, so the match is still ahead of the counter whenever the
+ * second one lands - unlike computing the match from the counter,
+ * which has to leave enough margin for its own store to get there and
+ * misses a whole 32bit wrap of the counter if it does not.
+ */
+ writel(RESET_MATCH, OSMR3);
+ writel(RESET_MATCH - RESET_MARGIN, OSCR);
+
+ /*
+ * A few microseconds out. Deliberately not hang(), which complains
+ * about a board needing a reset while it is being reset.
+ */
+ for (;;)
+ ;
}
static int restart_register_feature(void)
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 26/27] ARM: pxa: add Raumfeld Speaker board support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (24 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 25/27] ARM: pxa: reset straight away and without complaining Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-16 17:56 ` [PATCH 27/27] ARM: multi_v5_v6_defconfig: enable PXA support Sascha Hauer
` (2 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
The Raumfeld speakers are PXA303 based WLAN speakers. The Boot ROM reads
the NTIM header from the start of NAND, loads the OBM into internal SRAM
and jumps to it, so barebox has to be the whole boot chain: a first stage
entry point brings up the hardware and loads the ordinary second stage
image into DRAM.
Nothing here is specific to one model: they differ in enclosure and
speaker assembly, while the CPU board, the NAND layout, the ethernet and
the leds are the same. The device tree therefore includes the common
device tree include rather than any single model's, and carries the
compatible of every model, because barebox boots whichever kernel device
tree sits next to it and blspec_have_entry() refuses an entry whose
device tree is not compatible with the running board.
The first stage replays the register values the vendor OBM and the U-Boot
it loaded use, recovered from the copy in the device's NAND: the pin
multiplexing, the clock configuration written twice, and the DRAM
sequence including the delays on the OS timer and the readbacks that
flush the writes. They have not been decoded against the documentation,
which only matters if the memory or clock configuration is ever to be
changed. The FFUART pins are muxed there too - the vendor OBM is silent
and never needed to, and pxa_debug_ll_init() only programs the UART
registers - and so is the static memory controller, without which the
SMSC ethernet on nCS2 does not answer.
The core comes out of reset at 104MHz. ACCR asks for XL=24 and XN=2, but
the PLL only picks the ratio up once software writes XCLKCFG, and nothing
in the original boot chain ever did. The first stage does the frequency
change, straight to 624MHz and without touching the rails: that operating
point wants 1.375V on VCC_CORE and 1.4V on VCC_SRAM, and the MAX8660 that
supplies both powers up at 1.4V. It is write-only over I2C, so this cannot
be checked - but it does not have to be, because Linux has never done
anything else. pxa3xx-cpufreq carries those voltages and applies none of
them, and with the performance governor it takes this board to 624MHz at
boot, which is what the vendor firmware did too. Programming the rails
properly would drop them to 1.0V at the low operating points; that needs
the PMIC on the power I2C and therefore the driver model, and it buys
power rather than anything this board notices.
The NAND layout is barebox's own, not the one the vendor U-Boot used:
2M for the bootloader - the image is 713K, the old partition was 640K -
1M for the environment in a partition of its own rather than the splash
screen partition it used to squat in, 16M at the end for everything the
box remembers, and the rest UBI. Keeping the settings in a partition
rather than a volume inside the UBI leaves updating the root filesystem
what it is, a write to a whole MTD partition with nothing inside it that
has to survive; the size is driven by wear rather than by the data, which
is well under 100KiB, since a read-only root filesystem never erases a
block and UBI only levels within its own partition. barebox rewrites the
partition nodes in the kernel device tree from these, so this is the
layout on both sides.
The bootloader partition is not marked read-only: barebox lives there and
replaces itself with barebox_update, for which the PXA NAND handler is
registered on it.
Two device tree properties are barebox specific: the environment
partition, which the kernel has no use for, and the heartbeat trigger on
the first led so it is visible that barebox is alive.
The console is driven by the ns16550 driver rather than the PXA one,
which is what the UARTs are. The defconfig enables UBI and UBIFS so the
rootfs in NAND can be read,
the update infrastructure and command, and the MMC driver, which finds
the SD8686 SDIO wifi. Its vmmc-supply is dropped from the device tree: it
points into a PMIC barebox has no driver for, and a declared supply is
mandatory, so pxamci would wait for a regulator that never arrives.
Documentation/boards/pxa/raumfeld.rst describes the two images, the
internal connectors and the partitioning, along with the warning that
comes with the latter.
Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/boards/pxa/raumfeld.rst | 78 +++++++++
arch/arm/boards/Makefile | 1 +
arch/arm/boards/raumfeld-speaker/Makefile | 5 +
arch/arm/boards/raumfeld-speaker/board.c | 37 +++++
arch/arm/boards/raumfeld-speaker/lowlevel-obm.c | 206 ++++++++++++++++++++++++
arch/arm/boards/raumfeld-speaker/lowlevel.c | 106 ++++++++++++
arch/arm/dts/Makefile | 1 +
arch/arm/dts/pxa300-raumfeld-speaker.dts | 108 +++++++++++++
arch/arm/mach-pxa/Kconfig | 10 ++
images/Makefile.pxa | 14 ++
10 files changed, 566 insertions(+)
diff --git a/Documentation/boards/pxa/raumfeld.rst b/Documentation/boards/pxa/raumfeld.rst
new file mode 100644
index 0000000000..ed9aaccde4
--- /dev/null
+++ b/Documentation/boards/pxa/raumfeld.rst
@@ -0,0 +1,78 @@
+Raumfeld Speaker
+================
+
+The Raumfeld speakers are PXA303 based WLAN speakers, sold by Teufel as the
+Speaker M, L, S and One: https://teufel.de/raumfeld-speaker-m-102181000
+
+They differ in enclosure and speaker assembly only, so ``raumfeld_speaker_defconfig``
+and one device tree cover all of them.
+
+Images
+------
+
+``barebox-raumfeld-speaker.img``
+ barebox proper, entered at 0xa0008000 with the hardware already up. This is
+ what the first stage loads, and what to chainload with ``go`` when testing a
+ new build over TFTP.
+
+``barebox-raumfeld-speaker-nand.img``
+ The image the Boot ROM boots: an NTIM header, the OBM that brings up
+ pinmuxing, clocks and DRAM, and a copy of the image above for it to load.
+ Write it to the ``barebox`` partition with ``barebox_update -t nand``.
+
+Internal connectors
+-------------------
+
+CON2, serial console, 3.3V:
+
+=== ==============
+Pin Signal
+=== ==============
+1 not identified
+2 UART RXD
+3 UART TXD
+4 GPIO79
+5 GPIO84
+6 GPIO81
+7 GPIO83
+8 GND
+=== ==============
+
+CON3, JTAG:
+
+=== ==========
+Pin Signal
+=== ==========
+1 GND
+2 nSRST
+3 TDO
+4 TCK
+5 TMS
+6 TDI
+7 nTRST
+8 reset status
+=== ==========
+
+Pin 8 is an output and cannot be used to reset the board; nSRST is pin 2.
+
+NAND partitioning
+-----------------
+
+.. warning:: barebox does not use the vendor partitioning and overwrites it.
+
+The vendor bootloader lives in 640KiB at the start of NAND, followed by its
+environment and a splash screen partition, with the rest UBI. barebox does not
+fit in 640KiB, so it takes 2MiB, 1MiB for an environment of its own, and 16MiB
+at the end of the device for everything the running system writes:
+
+========= ====== ===================
+Offset Size Name
+========= ====== ===================
+0x0000000 2MiB barebox
+0x0200000 1MiB barebox-environment
+0x0300000 109MiB UBI
+0x7000000 16MiB Data
+========= ====== ===================
+
+barebox fixes these into the kernel device tree, so the partitioning in the
+kernel's own device tree does not take effect.
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index fbcf14748a..1057413e52 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -202,3 +202,4 @@ obj-$(CONFIG_MACH_RADXA_CM3) += radxa-cm3/
obj-$(CONFIG_MACH_TQMA93XX) += tqma93xx/
obj-$(CONFIG_MACH_WOLFVISION_PF5) += wolfvision-pf5/
obj-$(CONFIG_MACH_XUNLONG_ORANGEPI_5_PLUS) += xunlong-orangepi-5-plus/
+obj-$(CONFIG_MACH_RAUMFELD_SPEAKER) += raumfeld-speaker/
diff --git a/arch/arm/boards/raumfeld-speaker/Makefile b/arch/arm/boards/raumfeld-speaker/Makefile
new file mode 100644
index 0000000000..55fd2822a0
--- /dev/null
+++ b/arch/arm/boards/raumfeld-speaker/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += board.o
+lwl-y += lowlevel.o
+lwl-y += lowlevel-obm.o
diff --git a/arch/arm/boards/raumfeld-speaker/board.c b/arch/arm/boards/raumfeld-speaker/board.c
new file mode 100644
index 0000000000..3682af3232
--- /dev/null
+++ b/arch/arm/boards/raumfeld-speaker/board.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <of.h>
+#include <mach/pxa/bbu.h>
+
+static int raumfeld_speaker_probe(struct device *dev)
+{
+ barebox_set_model("Raumfeld Speaker");
+ barebox_set_hostname("speaker");
+
+ /*
+ * The Boot ROM boots from the start of NAND, so this is the partition
+ * holding the NTIM header, the OBM and barebox itself.
+ */
+ pxa_bbu_nand_register_handler("nand", "/dev/nand0.barebox");
+
+ return 0;
+}
+
+static const struct of_device_id raumfeld_speaker_of_match[] = {
+ { .compatible = "raumfeld,raumfeld-speaker-m-pxa303" },
+ { .compatible = "raumfeld,raumfeld-speaker-l-pxa303" },
+ { .compatible = "raumfeld,raumfeld-speaker-s-pxa303" },
+ { .compatible = "raumfeld,raumfeld-speaker-one-pxa303" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, raumfeld_speaker_of_match);
+
+static struct driver raumfeld_speaker_driver = {
+ .name = "board-raumfeld-speaker",
+ .probe = raumfeld_speaker_probe,
+ .of_compatible = raumfeld_speaker_of_match,
+};
+coredevice_platform_driver(raumfeld_speaker_driver);
diff --git a/arch/arm/boards/raumfeld-speaker/lowlevel-obm.c b/arch/arm/boards/raumfeld-speaker/lowlevel-obm.c
new file mode 100644
index 0000000000..8e25670352
--- /dev/null
+++ b/arch/arm/boards/raumfeld-speaker/lowlevel-obm.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * First stage entry for the Raumfeld speakers.
+ *
+ * Unlike the second stage entry in lowlevel.c, nothing has run before this:
+ * the Boot ROM has copied us from NAND into internal SRAM and jumped here, so
+ * pinmuxing, clocks, the UART and DRAM all have to be set up before barebox
+ * can be loaded into DRAM and started.
+ *
+ * The register values are the ones the vendor OBM in the device's NAND uses.
+ */
+
+#include <common.h>
+#include <debug_ll.h>
+#include <mach/pxa/debug_ll.h>
+#include <asm/barebox-arm.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/io.h>
+#include <mach/pxa/xload.h>
+
+/*
+ * We run from internal SRAM, which ends at 0x5c040000 on this part. The Boot
+ * ROM's own scratch area is well below the OBM load address of 0x5c020000.
+ */
+#define RAUMFELD_OBM_STACK_TOP 0x5c040000
+
+/* OS timer, used as the time base for the delays during DRAM setup */
+#define OSCR 0x40a00010
+
+/* Application subsystem clock configuration */
+#define ACCR 0x41340000
+#define ACCR_INIT 0x028cf298
+
+/* Dynamic memory controller */
+#define DMC_MDCNFG 0x48100000
+#define DMC_MDREFR 0x48100004
+#define DMC_DDR_HCAL 0x48100060
+#define DMC_DDR_SCAL 0x48100040
+#define DMC_DDR_WCAL 0x48100100
+
+#define MDCNFG_INIT 0x8000044d
+#define MDCNFG_DMCEN 0x40000000
+#define MDREFR_INIT 0x00000006
+
+struct reg_value {
+ u32 reg;
+ u32 val;
+};
+
+/*
+ * Pin multiplexing. The 0x1c01 block is the DDR address and data bus, the
+ * rest is the static memory controller and the NAND interface.
+ */
+static const struct reg_value mfp_init[] = {
+ { 0x40e1020c, 0x00001501 }, { 0x40e10240, 0x00001500 },
+ { 0x40e100cc, 0x0000d481 }, { 0x40e10200, 0x0000d481 },
+ { 0x40e10248, 0x00000001 }, { 0x40e100c8, 0x0000d5c0 },
+ { 0x40e10220, 0x00001c01 }, { 0x40e10228, 0x00001c01 },
+ { 0x40e10230, 0x00001c01 }, { 0x40e10238, 0x00001c01 },
+ { 0x40e10258, 0x00001c01 }, { 0x40e10260, 0x00001c01 },
+ { 0x40e10268, 0x00001c01 }, { 0x40e10270, 0x00001c01 },
+ { 0x40e10224, 0x00001c01 }, { 0x40e1022c, 0x00001c01 },
+ { 0x40e10234, 0x00001c01 }, { 0x40e1023c, 0x00001c01 },
+ { 0x40e1025c, 0x00001c01 }, { 0x40e10264, 0x00001c01 },
+ { 0x40e1026c, 0x00001c01 }, { 0x40e10274, 0x00001c01 },
+ { 0x40e100b8, 0x00001401 },
+};
+
+/*
+ * FFUART, the console: GPIO77 RXD, 78 TXD, 79 CTS, 81 DSR, 83 DTR, 84 RTS,
+ * all alternate function 1.
+ *
+ * This is not part of the vendor OBM's table. It did not need it - the U-Boot
+ * it loaded muxed these pins before using them, and the OBM itself is silent.
+ * Nothing does it in this boot path: pxa_debug_ll_init() only programs the
+ * UART registers, and no pinctrl driver binds to the pinconf-single node
+ * further along either. Without this everything from here to the barebox
+ * shell runs correctly and says nothing at all.
+ *
+ * Values as written by that U-Boot.
+ */
+static const struct reg_value uart_mfp_init[] = {
+ { 0x40e104c8, 0x0000c801 }, { 0x40e104cc, 0x00000801 },
+ { 0x40e104d0, 0x0000a801 }, { 0x40e104d8, 0x00000801 },
+ { 0x40e104e0, 0x00000801 }, { 0x40e104e4, 0x00000801 },
+};
+
+/*
+ * Static memory controller. The SMSC ethernet sits on nCS2, and nothing has
+ * configured the controller for it: the vendor OBM does not touch it either,
+ * because the U-Boot it loaded did so itself before probing the chip. Without
+ * this the chip select is dead and the driver gives up with "Device not READY
+ * in 100ms aborting".
+ *
+ * Values read out of that U-Boot (mtd0, literal pool at 0x40744).
+ */
+static const struct reg_value smc_init[] = {
+ { 0x4a000088, 0x00320809 }, /* CSADRCFG2, the ethernet chip select */
+ { 0x4a000008, 0x00000779 }, /* MSC0 */
+ { 0x4a00000c, 0x7ff07ff0 }, /* MSC1 */
+ { 0x4a00001c, 0x00880008 }, /* SXCNFG */
+};
+
+/* Pins and GPIO state the vendor OBM sets up after DRAM is running. */
+static const struct reg_value late_init[] = {
+ { 0x40e10524, 0x00000000 }, { 0x40e10528, 0x00000000 },
+ { 0x40e0010c, 0x00000006 }, { 0x40e00118, 0x00000004 },
+ { 0x40e00124, 0x00000004 }, { 0x40e10000, 0x00001901 },
+};
+
+static void write_regs(const struct reg_value *r, unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ writel(r[i].val, IOMEM(r[i].reg));
+}
+
+/* Busy wait on the OS timer, which is running out of reset. */
+static void obm_delay(u32 ticks)
+{
+ writel(0, IOMEM(OSCR));
+
+ while (readl(IOMEM(OSCR)) <= ticks)
+ ;
+}
+
+/*
+ * DRAM setup. The readbacks after the stores are the vendor's write flushes,
+ * the delays are what the DDR device needs between the steps; both are kept
+ * as they are.
+ */
+static void obm_ddr_init(void)
+{
+ writel(MDCNFG_INIT, IOMEM(DMC_MDCNFG));
+ readl(IOMEM(DMC_MDCNFG));
+ obm_delay(300);
+
+ writel(0x80000000, IOMEM(DMC_DDR_WCAL));
+ readl(IOMEM(DMC_DDR_WCAL));
+
+ writel(0x88000000, IOMEM(DMC_DDR_HCAL));
+ obm_delay(5);
+ readl(IOMEM(DMC_DDR_HCAL));
+
+ writel(0x60000033, IOMEM(DMC_DDR_SCAL));
+ obm_delay(300);
+
+ writel(0x60010000, IOMEM(DMC_DDR_SCAL));
+ obm_delay(300);
+
+ writel(MDREFR_INIT, IOMEM(DMC_MDREFR));
+ readl(IOMEM(DMC_MDREFR));
+
+ writel(readl(IOMEM(DMC_MDCNFG)) | MDCNFG_DMCEN, IOMEM(DMC_MDCNFG));
+}
+
+static noinline void __noreturn raumfeld_obm_start(void)
+{
+ void *barebox;
+
+ write_regs(mfp_init, ARRAY_SIZE(mfp_init));
+ write_regs(uart_mfp_init, ARRAY_SIZE(uart_mfp_init));
+
+ /* Written twice, as the vendor OBM does. */
+ writel(ACCR_INIT, IOMEM(ACCR));
+ writel(ACCR_INIT, IOMEM(ACCR));
+
+ pxa_debug_ll_init();
+ putc_ll('>');
+
+ obm_ddr_init();
+ write_regs(late_init, ARRAY_SIZE(late_init));
+ write_regs(smc_init, ARRAY_SIZE(smc_init));
+
+ /*
+ * The NTIM in NAND says where barebox lives and how big it is, so
+ * unlike the vendor OBM this does not copy a fixed amount.
+ */
+ barebox = pxa_nand_load_image(NTIM_ID_BOOT);
+ if (!barebox) {
+ putc_ll('!');
+ while (1)
+ ;
+ }
+
+ putc_ll('>');
+
+ /*
+ * barebox is a separate image with its own entry point, loaded to the
+ * address its NTIM entry gives, so enter it rather than continuing
+ * into a barebox linked into this one.
+ */
+ ((void (*)(void))barebox)();
+
+ while (1)
+ ;
+}
+
+ENTRY_FUNCTION_WITHSTACK(start_raumfeld_speaker_obm, RAUMFELD_OBM_STACK_TOP,
+ r0, r1, r2)
+{
+ arm_cpu_lowlevel_init();
+
+ raumfeld_obm_start();
+}
diff --git a/arch/arm/boards/raumfeld-speaker/lowlevel.c b/arch/arm/boards/raumfeld-speaker/lowlevel.c
new file mode 100644
index 0000000000..50243efc37
--- /dev/null
+++ b/arch/arm/boards/raumfeld-speaker/lowlevel.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <debug_ll.h>
+#include <linux/sizes.h>
+#include <asm/barebox-arm.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/io.h>
+#include <mach/pxa/debug_ll.h>
+
+#define RAUMFELD_SDRAM_BASE 0xa0000000
+#define RAUMFELD_SDRAM_SIZE SZ_128M
+
+/* Application subsystem clock configuration and its status counterpart */
+#define ACCR 0x41340000
+#define ACSR 0x41340004
+
+#define ACCR_XSPCLK(x) (((x) & 0x3) << 16) /* core clock during the change */
+#define ACCR_XSPCLK_MASK ACCR_XSPCLK(~0)
+#define ACCR_XN(x) (((x) & 0x7) << 8) /* turbo-mode-to-run-mode ratio */
+#define ACCR_XN_MASK ACCR_XN(~0)
+#define ACCR_XL(x) ((x) & 0x1f) /* run-mode-to-oscillator ratio */
+#define ACCR_XL_MASK ACCR_XL(~0)
+
+#define XSPCLK_NONE 3 /* no core clock while the PLL relocks */
+#define XCLKCFG_F (1 << 1) /* start a frequency change */
+#define XCLKCFG_T (1 << 0) /* turbo mode */
+
+extern char __dtb_pxa300_raumfeld_speaker_start[];
+
+/*
+ * Switch the core to the 624MHz operating point.
+ *
+ * The vendor OBM writes ACCR asking for XL=24 and XN=2, i.e. 312MHz run and
+ * 624MHz turbo, but writing ACCR does not change the core PLL by itself: the
+ * ratio only takes effect once software starts a frequency change by writing
+ * XCLKCFG. Nothing in the original boot chain ever did - the U-Boot in NAND
+ * contains no such write either - so the core has always run at its 104MHz
+ * reset default. Everything else in that ACCR value does apply immediately,
+ * which is why ACSR reads back the OBM's HSS, SMCFS, SFLFS and DMCFS next to
+ * XL=8 and XN=1.
+ *
+ * This is done blind, without touching the rails. 624MHz wants 1.375V on
+ * VCC_CORE and 1.4V on VCC_SRAM (pxa300_freqs[] in Linux'
+ * drivers/cpufreq/pxa3xx-cpufreq.c), and both come from a MAX8660 that is
+ * write-only over I2C, so what it supplies cannot be read back. It does not
+ * have to be: V3 and V4 power up at 1.4V, which covers every operating point
+ * the part has. Linux has always relied on the same thing - pxa3xx-cpufreq
+ * carries those voltages and applies none of them, and with the performance
+ * governor it takes this board to 624MHz at boot - so this is what the
+ * hardware has been doing since the factory, not a new assumption.
+ *
+ * The cost is that the rails stay at 1.4V at every frequency instead of
+ * dropping to 1.0V at the low ones. That needs the PMIC driver and the driver
+ * model, which is a long way past lowlevel, and it buys power rather than
+ * anything this board notices.
+ *
+ * FFUART is clocked from the system PLL rather than from the core, so the
+ * console baud rate is unaffected.
+ */
+static void raumfeld_speaker_core_624mhz(void)
+{
+ u32 want = ACCR_XN(2) | ACCR_XL(24);
+ int timeout = 100000;
+ u32 accr;
+
+ accr = readl(IOMEM(ACCR));
+ accr &= ~(ACCR_XN_MASK | ACCR_XL_MASK | ACCR_XSPCLK_MASK);
+ accr |= want | ACCR_XSPCLK(XSPCLK_NONE);
+ writel(accr, IOMEM(ACCR));
+
+ /*
+ * XN > 1 is the turbo-mode-to-run-mode ratio, so the turbo bit has to
+ * go out with the frequency change or the core stops at the 312MHz
+ * run frequency.
+ */
+ asm volatile("mcr p14, 0, %0, c6, c0, 0"
+ : : "r" (XCLKCFG_F | XCLKCFG_T));
+
+ /* ACSR follows ACCR once the PLL has relocked */
+ while (--timeout &&
+ (readl(IOMEM(ACSR)) & (ACCR_XN_MASK | ACCR_XL_MASK)) != want)
+ ;
+}
+
+ENTRY_FUNCTION_WITHSTACK(start_raumfeld_speaker, 0, r0, r1, r2)
+{
+ void *fdt;
+
+ arm_cpu_lowlevel_init();
+
+ /*
+ * We are the second stage: SDRAM, clocks and pinmuxing are already
+ * set up by the OBM. The stack the previous stage left us is used
+ * until barebox_arm_entry() installs its own.
+ */
+ pxa_debug_ll_init();
+
+ putc_ll('>');
+
+ raumfeld_speaker_core_624mhz();
+
+ fdt = __dtb_pxa300_raumfeld_speaker_start + get_runtime_offset();
+
+ barebox_arm_entry(RAUMFELD_SDRAM_BASE, RAUMFELD_SDRAM_SIZE, fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index b82f6c96fc..b418ac2dec 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -267,3 +267,4 @@ obj-$(CONFIG_MACH_WOLFVISION_PF5) += rk3568-wolfvision-pf5-io-expander.dtbo.o \
rk3568-wolfvision-pf5-display-vz.dtbo.o
clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.z
clean-files += *.dtbo *.dtbo.S .*.dtso
+lwl-$(CONFIG_MACH_RAUMFELD_SPEAKER) += pxa300-raumfeld-speaker.dtb.o
diff --git a/arch/arm/dts/pxa300-raumfeld-speaker.dts b/arch/arm/dts/pxa300-raumfeld-speaker.dts
new file mode 100644
index 0000000000..fbb93f9694
--- /dev/null
+++ b/arch/arm/dts/pxa300-raumfeld-speaker.dts
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include <arm/intel/pxa/pxa300-raumfeld-common.dtsi>
+
+/ {
+ /*
+ * The Raumfeld speakers differ in their enclosure and speaker
+ * assembly, not in anything barebox cares about, so one image
+ * covers all of them. Only the parts shared by all models are
+ * included here; the audio clock generator is left to the kernel.
+ */
+ model = "Raumfeld Speaker";
+ /*
+ * All models are listed, because barebox boots whichever kernel
+ * device tree sits next to it: the bootloader spec code refuses an
+ * entry whose device tree is not compatible with the running board,
+ * and upstream has one compatible per model.
+ */
+ compatible = "raumfeld,raumfeld-speaker-m-pxa303",
+ "raumfeld,raumfeld-speaker-l-pxa303",
+ "raumfeld,raumfeld-speaker-s-pxa303",
+ "raumfeld,raumfeld-speaker-one-pxa303",
+ "marvell,pxa300",
+ "marvell,pxa3xx";
+
+ barebox,deep-probe;
+
+ leds {
+ left {
+ barebox,default-trigger = "heartbeat";
+ };
+ };
+
+ chosen {
+ environment {
+ compatible = "barebox,environment";
+ device-path = &{/pxabus/nand-controller@43100000/nand@0},
+ "partname:barebox-environment";
+ };
+ };
+};
+
+/*
+ * vmmc-supply points at V6 of the MAX8660, for which there is no driver here.
+ * A supply that a node declares is mandatory, so pxamci would be left waiting
+ * for a regulator that is never going to appear. Nothing in barebox uses the
+ * SDIO wifi behind it anyway, and V6 comes up disabled, so it is Linux' PMIC
+ * driver that has to turn it on either way.
+ */
+&mmc0 {
+ /delete-property/ vmmc-supply;
+};
+
+/*
+ * The Raumfeld layout was built around the U-Boot in NAND: 640K for it, an
+ * environment and a splash screen partition, then UBI. barebox replaces that
+ * U-Boot, does not fit in 640K and keeps its environment in flash of its own,
+ * so lay the device out for barebox instead.
+ *
+ * This is what the kernel sees as well. barebox rewrites the partition nodes
+ * in the kernel device tree from the ones it uses itself, so these are the
+ * only ones there are.
+ */
+&{/pxabus/nand-controller@43100000/nand@0} {
+ /delete-node/ partitions;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@200000 {
+ label = "barebox-environment";
+ reg = <0x200000 0x100000>;
+ };
+
+ partition@300000 {
+ label = "UBI";
+ reg = <0x300000 0x6d00000>;
+ };
+
+ /*
+ * Everything the running system writes: WLAN credentials, radio
+ * stations, the mixer state. A partition rather than a second
+ * volume in the UBI above, so that updating the root filesystem
+ * is a write to a whole MTD partition and cannot take the
+ * settings with it.
+ *
+ * The size is not driven by the data, which is well under
+ * 100KiB. A read-only root never erases a block, so all of the
+ * wear lands here, and UBI only levels within its own
+ * partition; 128 erase blocks are also what keeps UBI's fixed
+ * overhead - layout volume, wear levelling and bad block
+ * reserve, then UBIFS' own - from dominating the partition.
+ */
+ partition@7000000 {
+ label = "Data";
+ reg = <0x7000000 0x1000000>;
+ };
+ };
+};
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index b159cee0cc..74a5e39df9 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -28,4 +28,14 @@ config BAREBOX_UPDATE_PXA_NAND
scripts/pxa-image - the NTIM header, the OBM and barebox - to the
mtd partition the Boot ROM boots from.
+comment "Intel/Marvell PXA boards"
+
+config MACH_RAUMFELD_SPEAKER
+ bool "Raumfeld Speaker"
+ select ARCH_PXA300
+ help
+ Say Y here if you are using the Raumfeld Speaker, a PXA303
+ based WLAN speaker. The Boot ROM loads barebox from NAND, so
+ it does the pinmuxing, clock and DRAM setup itself.
+
endif
diff --git a/images/Makefile.pxa b/images/Makefile.pxa
index 023aec428d..1f369223a2 100644
--- a/images/Makefile.pxa
+++ b/images/Makefile.pxa
@@ -3,6 +3,20 @@
# barebox image generation Makefile for PXA images
#
+pblb-$(CONFIG_MACH_RAUMFELD_SPEAKER) += start_raumfeld_speaker
+FILE_barebox-raumfeld-speaker.img = start_raumfeld_speaker.pblb
+image-$(CONFIG_MACH_RAUMFELD_SPEAKER) += barebox-raumfeld-speaker.img
+
+# First stage: runs from internal SRAM, so keep it well inside the 128K the
+# Boot ROM leaves us above the OBM load address.
+pblb-$(CONFIG_MACH_RAUMFELD_SPEAKER) += start_raumfeld_speaker_obm
+MAX_PBL_MEMORY_SIZE_start_raumfeld_speaker_obm = 0x10000
+# the OBM loads the ordinary second stage image into DRAM and enters it
+PXA_PAYLOAD_start_raumfeld_speaker_obm.pblb.pxaimg = start_raumfeld_speaker.pblb
+PXA_BOOT_LOAD_start_raumfeld_speaker_obm.pblb.pxaimg = 0xa0008000
+FILE_barebox-raumfeld-speaker-nand.img = start_raumfeld_speaker_obm.pblb.pxaimg
+image-$(CONFIG_MACH_RAUMFELD_SPEAKER) += barebox-raumfeld-speaker-nand.img
+
# A first stage image: the NTIM header the Boot ROM reads from NAND, the OBM
# it loads into internal SRAM, and barebox for the OBM to load into DRAM.
quiet_cmd_pxa_image = PXAIMG $@
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 27/27] ARM: multi_v5_v6_defconfig: enable PXA support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (25 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 26/27] ARM: pxa: add Raumfeld Speaker board support Sascha Hauer
@ 2026-08-16 17:56 ` Sascha Hauer
2026-08-17 7:35 ` [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Ahmad Fatoum
2026-08-19 9:26 ` Sascha Hauer
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-16 17:56 UTC (permalink / raw)
To: BAREBOX
Enable PXA support along with the Raumfeld Speaker board and PXA peripherals.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/configs/multi_v5_v6_defconfig | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/arm/configs/multi_v5_v6_defconfig b/arch/arm/configs/multi_v5_v6_defconfig
index bc6645b3ce..5f71ec0fd8 100644
--- a/arch/arm/configs/multi_v5_v6_defconfig
+++ b/arch/arm/configs/multi_v5_v6_defconfig
@@ -1,5 +1,6 @@
CONFIG_ARCH_BCM283X=y
CONFIG_ARCH_IMX=y
+CONFIG_ARCH_PXA=y
CONFIG_ARCH_VERSATILE=y
CONFIG_MACH_RPI=y
CONFIG_MACH_SCB9328=y
@@ -8,15 +9,15 @@ CONFIG_MACH_PCA100=y
CONFIG_MACH_PCM038=y
CONFIG_IMX_IIM=y
CONFIG_IMX_IIM_FUSE_BLOW=y
-CONFIG_BOARD_GENERIC_DT=y
+CONFIG_BAREBOX_UPDATE_PXA_NAND=y
+CONFIG_MACH_RAUMFELD_SPEAKER=y
CONFIG_AEABI=y
-CONFIG_BOOT_ATAGS=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
+CONFIG_BOOT_ATAGS=y
CONFIG_NAME="multi_v5_v6_defconfig"
CONFIG_MMU=y
CONFIG_MALLOC_SIZE=0x0
-CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_PANIC_HANG=y
CONFIG_HUSH_FANCY_PROMPT=y
@@ -26,10 +27,9 @@ CONFIG_MENU=y
CONFIG_BOOTM_SHOW_TYPE=y
CONFIG_BOOTM_VERBOSE=y
CONFIG_BOOTM_INITRD=y
-CONFIG_BOOTM_OFTREE=y
CONFIG_BLSPEC=y
-CONFIG_CONSOLE_ACTIVATE_ALL_FALLBACK=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+# CONFIG_BOOT_DEFAULTS is not set
CONFIG_RESET_SOURCE=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -81,7 +81,9 @@ CONFIG_NET=y
CONFIG_NET_NETCONSOLE=y
CONFIG_OF_BAREBOX_DRIVERS=y
CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_DRIVER_SERIAL_PXA=y
CONFIG_DRIVER_NET_FEC_IMX=y
+CONFIG_DRIVER_NET_SMC911X=y
CONFIG_DRIVER_NET_SMC91111=y
CONFIG_NET_USB=y
CONFIG_NET_USB_ASIX=y
@@ -94,6 +96,7 @@ CONFIG_CFI_BUFFER_WRITE=y
CONFIG_NAND=y
CONFIG_NAND_ALLOW_ERASE_BAD=y
CONFIG_NAND_IMX=y
+CONFIG_NAND_MRVL_NFC=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_FASTMAP=y
CONFIG_USB_HOST=y
@@ -110,6 +113,8 @@ CONFIG_EEPROM_AT25=y
CONFIG_EEPROM_AT24=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_IMX=y
+CONFIG_GPIO_PXA=y
+# CONFIG_PINCTRL is not set
CONFIG_IMX_WEIM=y
CONFIG_GENERIC_PHY=y
CONFIG_USB_NOP_XCEIV=y
@@ -120,7 +125,6 @@ CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_UBIFS=y
CONFIG_FS_UBIFS_COMPRESSION_LZO=y
+CONFIG_FS_QEMU_FW_CFG=y
CONFIG_DIGEST_SHA1_ARM=y
CONFIG_DIGEST_SHA256_ARM=y
-CONFIG_QEMU_FW_CFG=y
-CONFIG_FS_QEMU_FW_CFG=y
--
2.47.3
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (26 preceding siblings ...)
2026-08-16 17:56 ` [PATCH 27/27] ARM: multi_v5_v6_defconfig: enable PXA support Sascha Hauer
@ 2026-08-17 7:35 ` Ahmad Fatoum
2026-08-19 9:26 ` Sascha Hauer
28 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2026-08-17 7:35 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
Hi,
On 8/16/26 7:56 PM, Sascha Hauer wrote:
> This series drops unused for longer remnants of the PXA2xx support and
> adds device tree based PXA3xx support instead. The PXA2xx boards have
> been removed already earlier leaving the remaining SoC code unused.
> Should anybody have interest in PXA2xx it should be straight forward
> adding back based on the new device tree code.
>
> The board supported with this series is a Raumfeld Speaker which I had
> lying under my desk catching dust, but now serves me as a music player
> again. The PXA3xx support is fairly complete:
>
> - NAND support including 1st stage load
> - USB OHCI
> - watchdog
> - GPIO
> - clk driver
> - SD/MMC support (though untested, the speaker only has a SDIO WiFi card
> which is detected by barebox, but ignored)
>
> What's missing right now is pinctrl support, the pinmux is configured by
> a register table in the PBL.
Can we have some screenshot here for a future Mastodon release
announcement? :-)
Something printed by barebox to the device's screen or some serial
console output, perhaps from bfetch or hostnamectl.
Cheers,
Ahmad
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> Sascha Hauer (27):
> ARM: pxa: remove PXA25x and PXA27x support
> video: remove the PXA framebuffer driver
> ARM: cache: drive the XSC3 cache with the ARMv4 functions
> mci: pxamci: get the clock from the clk API
> pwm: pxa: get the clock from the clk API
> serial: pxa: get the clock from the clk API
> clk: pxa: add a device tree clock driver for PXA3xx
> mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config
> mtd: nand: nand_mrvl_nfc: support the nand-controller bindings
> mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command
> mtd: nand: mrvl_nfc: do not report a command timeout as an error
> mci: pxamci: probe from the device tree
> serial: pxa: add device tree support
> serial: pxa: provide the Linux console name
> gpio: pxa: add a driver and switch the architecture to GPIOLIB
> ARM: pxa: add DEBUG_LL support
> ARM: pxa: let the board select the SoC
> ARM: pxa: enable device tree support
> scripts: add pxa-image
> ARM: pxa: add a NAND first stage loader
> filetype: detect PXA3xx NTIM images
> ARM: pxa: add a barebox update handler for NAND
> clocksource: add a driver for the PXA OS timer and its watchdog
> ARM: pxa: move over to MULTIARCH
> ARM: pxa: reset straight away and without complaining
> ARM: pxa: add Raumfeld Speaker board support
> ARM: multi_v5_v6_defconfig: enable PXA support
>
> Documentation/boards/pxa/Phytec-phyCORE-PXA270.rst | 6 -
> Documentation/boards/pxa/raumfeld.rst | 78 ++
> arch/arm/Kconfig | 13 +-
> arch/arm/boards/Makefile | 1 +
> arch/arm/boards/raumfeld-speaker/Makefile | 5 +
> arch/arm/boards/raumfeld-speaker/board.c | 37 +
> arch/arm/boards/raumfeld-speaker/lowlevel-obm.c | 206 +++
> arch/arm/boards/raumfeld-speaker/lowlevel.c | 106 ++
> arch/arm/configs/multi_v5_v6_defconfig | 18 +-
> arch/arm/cpu/cache_32.c | 31 +
> arch/arm/dts/Makefile | 1 +
> arch/arm/dts/pxa300-raumfeld-speaker.dts | 108 ++
> arch/arm/include/asm/debug_ll.h | 2 +
> arch/arm/include/asm/system_info.h | 9 +
> arch/arm/mach-pxa/Kconfig | 51 +-
> arch/arm/mach-pxa/Makefile | 12 +-
> arch/arm/mach-pxa/bbu.c | 96 ++
> arch/arm/mach-pxa/clocksource.c | 41 -
> arch/arm/mach-pxa/common.c | 29 +-
> arch/arm/mach-pxa/devices.c | 6 -
> arch/arm/mach-pxa/gpio.c | 101 --
> arch/arm/mach-pxa/mfp-pxa2xx.c | 191 ---
> arch/arm/mach-pxa/pxa2xx.c | 69 -
> arch/arm/mach-pxa/pxa3xx.c | 6 +-
> arch/arm/mach-pxa/sleep.S | 28 -
> arch/arm/mach-pxa/speed-pxa25x.c | 54 -
> arch/arm/mach-pxa/speed-pxa27x.c | 54 -
> arch/arm/mach-pxa/speed-pxa3xx.c | 43 -
> arch/arm/mach-pxa/xload-nand.c | 255 ++++
> common/Kconfig.debug_ll | 17 +
> common/filetype.c | 11 +
> drivers/clk/Makefile | 1 +
> drivers/clk/pxa/Makefile | 3 +
> drivers/clk/pxa/clk-pxa.c | 122 ++
> drivers/clk/pxa/clk-pxa.h | 118 ++
> drivers/clk/pxa/clk-pxa3xx.c | 357 +++++
> drivers/clocksource/Kconfig | 7 +
> drivers/clocksource/Makefile | 1 +
> drivers/clocksource/timer-pxa.c | 151 ++
> drivers/gpio/Kconfig | 6 +
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-pxa.c | 146 ++
> drivers/mci/Kconfig | 4 +-
> drivers/mci/pxamci.c | 88 +-
> drivers/mci/pxamci.h | 2 +-
> drivers/mtd/nand/raw/nand_mrvl_nfc.c | 107 +-
> drivers/pwm/Kconfig | 7 +-
> drivers/pwm/pxa_pwm.c | 38 +-
> drivers/serial/serial_pxa.c | 27 +-
> drivers/usb/gadget/Kconfig | 7 -
> drivers/usb/gadget/udc/Makefile | 1 -
> drivers/usb/gadget/udc/pxa27x_udc.c | 1469 --------------------
> drivers/usb/gadget/udc/pxa27x_udc.h | 380 -----
> drivers/video/Kconfig | 7 -
> drivers/video/Makefile | 1 -
> drivers/video/pxa.c | 548 --------
> images/Makefile | 1 +
> images/Makefile.pxa | 32 +
> include/filetype.h | 1 +
> include/mach/pxa/bbu.h | 18 +
> include/mach/pxa/clock.h | 19 -
> include/mach/pxa/debug_ll.h | 74 +
> include/mach/pxa/devices.h | 2 -
> include/mach/pxa/gpio.h | 31 -
> include/mach/pxa/hardware.h | 18 -
> include/mach/pxa/mci_pxa2xx.h | 12 -
> include/mach/pxa/mfp-pxa27x.h | 472 -------
> include/mach/pxa/mfp-pxa2xx.h | 135 --
> include/mach/pxa/pxa-regs.h | 12 -
> include/mach/pxa/pxa25x-regs.h | 8 -
> include/mach/pxa/pxa27x-regs.h | 8 -
> include/mach/pxa/pxa2xx-regs.h | 273 ----
> include/mach/pxa/pxafb.h | 81 --
> include/mach/pxa/regs-lcd.h | 182 ---
> include/mach/pxa/udc_pxa2xx.h | 28 -
> include/mach/pxa/xload.h | 42 +
> scripts/Kconfig | 7 +
> scripts/Makefile | 1 +
> scripts/pxa-image.c | 281 ++++
> 79 files changed, 2583 insertions(+), 4439 deletions(-)
> ---
> base-commit: 23acc2f11182214ff655ed7c3b226160282c6a21
> change-id: 20260816-pxa3xx-9d16ccfd1ca9
>
> Best regards,
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
` (27 preceding siblings ...)
2026-08-17 7:35 ` [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Ahmad Fatoum
@ 2026-08-19 9:26 ` Sascha Hauer
28 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2026-08-19 9:26 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer
On Sun, 16 Aug 2026 19:56:20 +0200, Sascha Hauer wrote:
> This series drops unused for longer remnants of the PXA2xx support and
> adds device tree based PXA3xx support instead. The PXA2xx boards have
> been removed already earlier leaving the remaining SoC code unused.
> Should anybody have interest in PXA2xx it should be straight forward
> adding back based on the new device tree code.
>
> The board supported with this series is a Raumfeld Speaker which I had
> lying under my desk catching dust, but now serves me as a music player
> again. The PXA3xx support is fairly complete:
>
> [...]
Applied, thanks!
[01/27] ARM: pxa: remove PXA25x and PXA27x support
https://git.pengutronix.de/cgit/barebox/commit/?id=fbf83af6624a (link may not be stable)
[02/27] video: remove the PXA framebuffer driver
https://git.pengutronix.de/cgit/barebox/commit/?id=a2f81413c1b8 (link may not be stable)
[03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions
https://git.pengutronix.de/cgit/barebox/commit/?id=81946d495a4b (link may not be stable)
[04/27] mci: pxamci: get the clock from the clk API
https://git.pengutronix.de/cgit/barebox/commit/?id=b092d5603fb1 (link may not be stable)
[05/27] pwm: pxa: get the clock from the clk API
https://git.pengutronix.de/cgit/barebox/commit/?id=ac8fbcec25d5 (link may not be stable)
[06/27] serial: pxa: get the clock from the clk API
https://git.pengutronix.de/cgit/barebox/commit/?id=bea10f91081d (link may not be stable)
[07/27] clk: pxa: add a device tree clock driver for PXA3xx
https://git.pengutronix.de/cgit/barebox/commit/?id=67746dc67853 (link may not be stable)
[08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config
https://git.pengutronix.de/cgit/barebox/commit/?id=6d6c443a4fbb (link may not be stable)
[09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings
https://git.pengutronix.de/cgit/barebox/commit/?id=4e8b7516de1f (link may not be stable)
[10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command
https://git.pengutronix.de/cgit/barebox/commit/?id=c16739526aed (link may not be stable)
[11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error
https://git.pengutronix.de/cgit/barebox/commit/?id=97505ef63828 (link may not be stable)
[12/27] mci: pxamci: probe from the device tree
https://git.pengutronix.de/cgit/barebox/commit/?id=58ad9e48dbf8 (link may not be stable)
[13/27] serial: pxa: add device tree support
https://git.pengutronix.de/cgit/barebox/commit/?id=b4ad4bc4203e (link may not be stable)
[14/27] serial: pxa: provide the Linux console name
https://git.pengutronix.de/cgit/barebox/commit/?id=ecb4cebe15d6 (link may not be stable)
[15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB
https://git.pengutronix.de/cgit/barebox/commit/?id=4d01bdd2023b (link may not be stable)
[16/27] ARM: pxa: add DEBUG_LL support
https://git.pengutronix.de/cgit/barebox/commit/?id=7c984e8ae930 (link may not be stable)
[17/27] ARM: pxa: let the board select the SoC
https://git.pengutronix.de/cgit/barebox/commit/?id=b7a78c72b332 (link may not be stable)
[18/27] ARM: pxa: enable device tree support
https://git.pengutronix.de/cgit/barebox/commit/?id=642f2cc3b1cc (link may not be stable)
[19/27] scripts: add pxa-image
https://git.pengutronix.de/cgit/barebox/commit/?id=bcfcce3499ed (link may not be stable)
[20/27] ARM: pxa: add a NAND first stage loader
https://git.pengutronix.de/cgit/barebox/commit/?id=2e81de15f9c6 (link may not be stable)
[21/27] filetype: detect PXA3xx NTIM images
https://git.pengutronix.de/cgit/barebox/commit/?id=7a1f2a4e787c (link may not be stable)
[22/27] ARM: pxa: add a barebox update handler for NAND
https://git.pengutronix.de/cgit/barebox/commit/?id=772b16118429 (link may not be stable)
[23/27] clocksource: add a driver for the PXA OS timer and its watchdog
https://git.pengutronix.de/cgit/barebox/commit/?id=f593d9fadebb (link may not be stable)
[24/27] ARM: pxa: move over to MULTIARCH
https://git.pengutronix.de/cgit/barebox/commit/?id=27292387963d (link may not be stable)
[25/27] ARM: pxa: reset straight away and without complaining
https://git.pengutronix.de/cgit/barebox/commit/?id=4c21b99c838f (link may not be stable)
[26/27] ARM: pxa: add Raumfeld Speaker board support
https://git.pengutronix.de/cgit/barebox/commit/?id=74b245df5e0e (link may not be stable)
[27/27] ARM: multi_v5_v6_defconfig: enable PXA support
https://git.pengutronix.de/cgit/barebox/commit/?id=f5e40b66cd3b (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2026-08-19 9:27 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
2026-08-16 17:56 ` [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support Sascha Hauer
2026-08-16 17:56 ` [PATCH 02/27] video: remove the PXA framebuffer driver Sascha Hauer
2026-08-16 17:56 ` [PATCH 03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions Sascha Hauer
2026-08-16 17:56 ` [PATCH 04/27] mci: pxamci: get the clock from the clk API Sascha Hauer
2026-08-16 17:56 ` [PATCH 05/27] pwm: pxa: " Sascha Hauer
2026-08-16 17:56 ` [PATCH 06/27] serial: " Sascha Hauer
2026-08-16 17:56 ` [PATCH 07/27] clk: pxa: add a device tree clock driver for PXA3xx Sascha Hauer
2026-08-16 17:56 ` [PATCH 08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config Sascha Hauer
2026-08-16 17:56 ` [PATCH 09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings Sascha Hauer
2026-08-16 17:56 ` [PATCH 10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command Sascha Hauer
2026-08-16 17:56 ` [PATCH 11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error Sascha Hauer
2026-08-16 17:56 ` [PATCH 12/27] mci: pxamci: probe from the device tree Sascha Hauer
2026-08-16 17:56 ` [PATCH 13/27] serial: pxa: add device tree support Sascha Hauer
2026-08-16 17:56 ` [PATCH 14/27] serial: pxa: provide the Linux console name Sascha Hauer
2026-08-16 17:56 ` [PATCH 15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB Sascha Hauer
2026-08-16 17:56 ` [PATCH 16/27] ARM: pxa: add DEBUG_LL support Sascha Hauer
2026-08-16 17:56 ` [PATCH 17/27] ARM: pxa: let the board select the SoC Sascha Hauer
2026-08-16 17:56 ` [PATCH 18/27] ARM: pxa: enable device tree support Sascha Hauer
2026-08-16 17:56 ` [PATCH 19/27] scripts: add pxa-image Sascha Hauer
2026-08-16 17:56 ` [PATCH 20/27] ARM: pxa: add a NAND first stage loader Sascha Hauer
2026-08-16 17:56 ` [PATCH 21/27] filetype: detect PXA3xx NTIM images Sascha Hauer
2026-08-16 17:56 ` [PATCH 22/27] ARM: pxa: add a barebox update handler for NAND Sascha Hauer
2026-08-16 17:56 ` [PATCH 23/27] clocksource: add a driver for the PXA OS timer and its watchdog Sascha Hauer
2026-08-16 17:56 ` [PATCH 24/27] ARM: pxa: move over to MULTIARCH Sascha Hauer
2026-08-16 17:56 ` [PATCH 25/27] ARM: pxa: reset straight away and without complaining Sascha Hauer
2026-08-16 17:56 ` [PATCH 26/27] ARM: pxa: add Raumfeld Speaker board support Sascha Hauer
2026-08-16 17:56 ` [PATCH 27/27] ARM: multi_v5_v6_defconfig: enable PXA support Sascha Hauer
2026-08-17 7:35 ` [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Ahmad Fatoum
2026-08-19 9:26 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox