Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
Igor Opaniuk <igor.opaniuk@gmail.com> <igor.opaniuk@linaro.org>
Igor Opaniuk <igor.opaniuk@gmail.com> <igor.opaniuk@toradex.com>
+Marek Behún <kabel@kernel.org> <marek.behun@nic.cz>
+Marek Behún <kabel@kernel.org> Marek Behun <marek.behun@nic.cz>
Marek Vasut <marex@denx.de> <marek.vasut+renesas@gmail.com>
Marek Vasut <marex@denx.de> <marek.vasut@gmail.com>
Marek Vasut <marex@denx.de> <marex at denx.de>
F: drivers/pinctrl/meson/
F: drivers/power/domain/meson-gx-pwrc-vpu.c
F: drivers/video/meson/
+F: drivers/watchdog/meson_gxbb_wdt.c
F: include/configs/meson64.h
F: include/configs/meson64_android.h
F: doc/board/amlogic/
F: drivers/net/phy/ca_phy.c
F: configs/cortina_presidio-asic-pnand_defconfig
-ARM/CZ.NIC TURRIS MOX SUPPORT
-M: Marek Behun <marek.behun@nic.cz>
-S: Maintained
-F: arch/arm/dts/armada-3720-turris-mox.dts
-F: board/CZ.NIC/
-F: configs/turris_*_defconfig
-F: include/configs/turris_*.h
-
ARM FREESCALE IMX
M: Stefano Babic <sbabic@denx.de>
M: Fabio Estevam <festevam@gmail.com>
F: tools/mtk_image.h
N: mediatek
+ARM METHODE SUPPORT
+M: Robert Marko <robert.marko@sartura.hr>
+S: Maintained
+F: arch/arm/dts/armada-3720-eDPU*
+F: arch/arm/dts/armada-3720-uDPU*
+F: configs/eDPU_defconfig
+F: configs/uDPU_defconfig
+
ARM MICROCHIP/ATMEL AT91
M: Eugen Hristev <eugen.hristev@microchip.com>
S: Maintained
F: test/boot/
BTRFS
-M: Marek Behun <marek.behun@nic.cz>
+M: Marek Behún <kabel@kernel.org>
R: Qu Wenruo <wqu@suse.com>
L: linux-btrfs@vger.kernel.org
S: Maintained
KWBIMAGE / KWBOOT TOOLS
M: Pali Rohár <pali@kernel.org>
-M: Marek Behún <marek.behun@nic.cz>
+M: Marek Behún <kabel@kernel.org>
M: Stefan Roese <sr@denx.de>
S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git
armada-3720-db.dtb \
armada-3720-espressobin.dtb \
armada-3720-turris-mox.dtb \
+ armada-3720-eDPU.dtb \
armada-3720-uDPU.dtb \
armada-375-db.dtb \
armada-385-atl-x530.dtb \
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+
+/ {
+ smbios {
+ compatible = "u-boot,sysinfo-smbios";
+
+ smbios {
+ system {
+ product = "eDPU";
+ };
+
+ baseboard {
+ product = "eDPU";
+ };
+
+ chassis {
+ product = "eDPU";
+ };
+ };
+ };
+};
+
+&spi0 {
+ u-boot,dm-pre-reloc;
+
+ spi-flash@0 {
+ u-boot,dm-pre-reloc;
+ };
+};
+
+&sdhci0 {
+ u-boot,dm-pre-reloc;
+};
+
+ð0 {
+ /* G.hn does not work without additional configuration */
+ status = "disabled";
+};
+
+ð1 {
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+};
--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "armada-3720-uDPU.dtsi"
+
+/ {
+ model = "Methode eDPU Board";
+ compatible = "methode,edpu", "marvell,armada3720", "marvell,armada3710";
+};
+
+ð0 {
+ phy-mode = "2500base-x";
+};
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device tree for the uDPU board.
- * Based on Marvell Armada 3720 development board (DB-88F3720-DDR3)
- * Copyright (C) 2016 Marvell
- * Copyright (C) 2019 Methode Electronics
- * Copyright (C) 2019 Telus
- *
- * Vladimir Vid <vladimir.vid@sartura.hr>
- */
/dts-v1/;
-#include <dt-bindings/gpio/gpio.h>
-#include "armada-372x.dtsi"
+#include "armada-3720-uDPU.dtsi"
/ {
model = "Methode uDPU Board";
- compatible = "methode,udpu", "marvell,armada3720";
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- memory@0 {
- device_type = "memory";
- reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
- };
-
- leds {
- pinctrl-names = "default";
- compatible = "gpio-leds";
-
- power1 {
- label = "udpu:green:power";
- gpios = <&gpionb 11 GPIO_ACTIVE_LOW>;
- };
-
- power2 {
- label = "udpu:red:power";
- gpios = <&gpionb 12 GPIO_ACTIVE_LOW>;
- };
-
- network1 {
- label = "udpu:green:network";
- gpios = <&gpionb 13 GPIO_ACTIVE_LOW>;
- };
-
- network2 {
- label = "udpu:red:network";
- gpios = <&gpionb 14 GPIO_ACTIVE_LOW>;
- };
-
- alarm1 {
- label = "udpu:green:alarm";
- gpios = <&gpionb 15 GPIO_ACTIVE_LOW>;
- };
-
- alarm2 {
- label = "udpu:red:alarm";
- gpios = <&gpionb 16 GPIO_ACTIVE_LOW>;
- };
- };
+ compatible = "methode,udpu", "marvell,armada3720", "marvell,armada3710";
sfp_eth0: sfp-eth0 {
compatible = "sff,sfp";
tx-fault-gpio = <&gpiosb 5 GPIO_ACTIVE_HIGH>;
maximum-power-milliwatt = <3000>;
};
-
- sfp_eth1: sfp-eth1 {
- compatible = "sff,sfp";
- i2c-bus = <&i2c1>;
- los-gpio = <&gpiosb 7 GPIO_ACTIVE_HIGH>;
- mod-def0-gpio = <&gpiosb 8 GPIO_ACTIVE_LOW>;
- tx-disable-gpio = <&gpiosb 9 GPIO_ACTIVE_HIGH>;
- tx-fault-gpio = <&gpiosb 10 GPIO_ACTIVE_HIGH>;
- maximum-power-milliwatt = <3000>;
- };
-};
-
-&sdhci0 {
- status = "okay";
- bus-width = <8>;
- mmc-ddr-1_8v;
- mmc-hs400-1_8v;
- marvell,pad-type = "fixed-1-8v";
- non-removable;
- no-sd;
- no-sdio;
-};
-
-&spi0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&spi_quad_pins>;
-
- spi-flash@0 {
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <54000000>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "firmware";
- reg = <0x0 0x180000>;
- };
-
- partition@180000 {
- label = "u-boot-env";
- reg = <0x180000 0x10000>;
- };
- };
- };
};
&pinctrl_nb {
groups = "i2c1";
function = "gpio";
};
-
- i2c2_recovery_pins: i2c2-recovery-pins {
- groups = "i2c2";
- function = "gpio";
- };
};
&i2c0 {
sda-gpios = <&gpionb 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
};
-&i2c1 {
- status = "okay";
- pinctrl-names = "default", "recovery";
- pinctrl-0 = <&i2c2_pins>;
- pinctrl-1 = <&i2c2_recovery_pins>;
- /delete-property/mrvl,i2c-fast-mode;
- scl-gpios = <&gpionb 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
- sda-gpios = <&gpionb 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
-
- nct375@48 {
- status = "okay";
- compatible = "ti,tmp75c";
- reg = <0x48>;
- };
-
- nct375@49 {
- status = "okay";
- compatible = "ti,tmp75c";
- reg = <0x49>;
- };
-};
-
ð0 {
phy-mode = "sgmii";
- status = "okay";
- managed = "in-band-status";
- phys = <&comphy1 0>;
sfp = <&sfp_eth0>;
};
-
-ð1 {
- phy-mode = "sgmii";
- status = "okay";
- managed = "in-band-status";
- phys = <&comphy0 1>;
- sfp = <&sfp_eth1>;
-};
-
-&usb3 {
- status = "okay";
- phys = <&usb2_utmi_otg_phy>;
- phy-names = "usb2-utmi-otg-phy";
-};
-
-&uart0 {
- status = "okay";
-};
--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device tree for the uDPU board.
+ * Based on Marvell Armada 3720 development board (DB-88F3720-DDR3)
+ * Copyright (C) 2016 Marvell
+ * Copyright (C) 2019 Methode Electronics
+ * Copyright (C) 2019 Telus
+ *
+ * Vladimir Vid <vladimir.vid@sartura.hr>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-372x.dtsi"
+
+/ {
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-power1 {
+ label = "udpu:green:power";
+ gpios = <&gpionb 11 GPIO_ACTIVE_LOW>;
+ };
+
+ led-power2 {
+ label = "udpu:red:power";
+ gpios = <&gpionb 12 GPIO_ACTIVE_LOW>;
+ };
+
+ led-network1 {
+ label = "udpu:green:network";
+ gpios = <&gpionb 13 GPIO_ACTIVE_LOW>;
+ };
+
+ led-network2 {
+ label = "udpu:red:network";
+ gpios = <&gpionb 14 GPIO_ACTIVE_LOW>;
+ };
+
+ led-alarm1 {
+ label = "udpu:green:alarm";
+ gpios = <&gpionb 15 GPIO_ACTIVE_LOW>;
+ };
+
+ led-alarm2 {
+ label = "udpu:red:alarm";
+ gpios = <&gpionb 16 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ sfp_eth1: sfp-eth1 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c1>;
+ los-gpio = <&gpiosb 7 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&gpiosb 8 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&gpiosb 9 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&gpiosb 10 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <3000>;
+ };
+};
+
+&sdhci0 {
+ status = "okay";
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ mmc-hs400-1_8v;
+ marvell,pad-type = "fixed-1-8v";
+ non-removable;
+ no-sd;
+ no-sdio;
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_quad_pins>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <54000000>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "firmware";
+ reg = <0x0 0x180000>;
+ };
+
+ partition@180000 {
+ label = "u-boot-env";
+ reg = <0x180000 0x10000>;
+ };
+ };
+ };
+};
+
+&pinctrl_nb {
+ i2c2_recovery_pins: i2c2-recovery-pins {
+ groups = "i2c2";
+ function = "gpio";
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ pinctrl-names = "default", "recovery";
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-1 = <&i2c2_recovery_pins>;
+ /delete-property/mrvl,i2c-fast-mode;
+ scl-gpios = <&gpionb 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpionb 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
+ temp-sensor@48 {
+ compatible = "ti,tmp75c";
+ reg = <0x48>;
+ };
+
+ temp-sensor@49 {
+ compatible = "ti,tmp75c";
+ reg = <0x49>;
+ };
+};
+
+ð0 {
+ status = "okay";
+ managed = "in-band-status";
+ phys = <&comphy1 0>;
+};
+
+ð1 {
+ phy-mode = "sgmii";
+ status = "okay";
+ managed = "in-band-status";
+ phys = <&comphy0 1>;
+ sfp = <&sfp_eth1>;
+};
+
+&usb3 {
+ status = "okay";
+ phys = <&usb2_utmi_otg_phy>;
+ phy-names = "usb2-utmi-otg-phy";
+};
+
+&uart0 {
+ status = "okay";
+};
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
*/
/ {
stdout-path = &uart0;
};
+ aliases {
+ ethernet0 = ð0;
+ ethernet1 = ð1;
+ ethernet2 = ð2;
+ };
+
memory {
device_type = "memory";
reg = <0x00000000 0x40000000>; /* 1024 MB */
* Currently only 2GiB are mapped for system memory. This is what
* we pass to the U-Boot subsystem here.
*/
-#define USABLE_RAM_SIZE 0x80000000
+#define USABLE_RAM_SIZE 0x80000000ULL
ulong board_get_usable_ram_top(ulong total_size)
{
- if (gd->ram_size > USABLE_RAM_SIZE)
- return USABLE_RAM_SIZE;
+ unsigned long top = CONFIG_SYS_SDRAM_BASE + min(gd->ram_size, USABLE_RAM_SIZE);
- return gd->ram_size;
+ return (gd->ram_top > top) ? top : gd->ram_top;
}
/*
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
- * Copyright (C) 2020 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2020 Marek Behún <kabel@kernel.org>
*/
#include <common.h>
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2018 Marek Behún <kabel@kernel.org>
* Copyright (C) 2021 Pali Rohár <pali@kernel.org>
*/
;
}
-int mvebu_soc_family(void)
-{
- u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff;
-
- switch (devid) {
- case SOC_MV78230_ID:
- case SOC_MV78260_ID:
- case SOC_MV78460_ID:
- return MVEBU_SOC_AXP;
-
- case SOC_88F6720_ID:
- return MVEBU_SOC_A375;
-
- case SOC_88F6810_ID:
- case SOC_88F6820_ID:
- case SOC_88F6828_ID:
- return MVEBU_SOC_A38X;
-
- case SOC_98DX3236_ID:
- case SOC_98DX3336_ID:
- case SOC_98DX4251_ID:
- return MVEBU_SOC_MSYS;
- }
-
- return MVEBU_SOC_UNKNOWN;
-}
-
u32 get_boot_device(void)
{
u32 val;
break;
}
- if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+ switch (devid) {
+ case SOC_MV78230_ID:
+ case SOC_MV78260_ID:
+ case SOC_MV78460_ID:
switch (revid) {
case 1:
puts("A0");
printf("?? (%x)", revid);
break;
}
- }
+ break;
- if (mvebu_soc_family() == MVEBU_SOC_A375) {
+ case SOC_88F6720_ID:
switch (revid) {
case MV_88F67XX_A0_ID:
puts("A0");
printf("?? (%x)", revid);
break;
}
- }
+ break;
- if (mvebu_soc_family() == MVEBU_SOC_A38X) {
+ case SOC_88F6810_ID:
+ case SOC_88F6820_ID:
+ case SOC_88F6828_ID:
switch (revid) {
case MV_88F68XX_Z1_ID:
puts("Z1");
printf("?? (%x)", revid);
break;
}
- }
+ break;
- if (mvebu_soc_family() == MVEBU_SOC_MSYS) {
+ case SOC_98DX3236_ID:
+ case SOC_98DX3336_ID:
+ case SOC_98DX4251_ID:
switch (revid) {
case 3:
puts("A0");
printf("?? (%x)", revid);
break;
}
+ break;
+
+ default:
+ printf("?? (%x)", revid);
+ break;
}
get_sar_freq(&sar_freq);
struct pl310_regs *const pl310 =
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
- if (mvebu_soc_family() == MVEBU_SOC_A38X) {
+ if (IS_ENABLED(CONFIG_ARMADA_38X)) {
/*
* To fully release / unlock this area from cache, we need
* to flush all caches and disable the L2 cache.
*/
mvebu_mbus_probe(NULL, 0);
- if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+ if (IS_ENABLED(CONFIG_ARMADA_XP)) {
/*
* Now the SDRAM access windows can be reconfigured using
* the information in the SDRAM scratch pad registers
*/
mvebu_mbus_probe(windows, ARRAY_SIZE(windows));
- if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+ if (IS_ENABLED(CONFIG_ARMADA_XP)) {
/* Enable GBE0, GBE1, LCD and NFC PUP */
clrsetbits_le32(ARMADA_XP_PUP_ENABLE, 0,
GE0_PUP_EN | GE1_PUP_EN | LCD_PUP_EN |
{
u32 reg;
- if (mvebu_soc_family() == MVEBU_SOC_A38X)
+ if (IS_ENABLED(CONFIG_ARMADA_38X))
reg = MVEBU_DFX_DIV_CLK_CTRL(1);
- else if (mvebu_soc_family() == MVEBU_SOC_MSYS)
+ else if (IS_ENABLED(CONFIG_ARMADA_MSYS))
reg = MVEBU_DFX_DIV_CLK_CTRL(8);
else
reg = MVEBU_CORE_DIV_CLK_CTRL(1);
* ethernet driver (mvpp2). So lets keep the d-cache disabled
* until this is solved.
*/
- if (mvebu_soc_family() != MVEBU_SOC_A375) {
+ if (IS_ENABLED(CONFIG_ARMADA_375)) {
/* Enable D-cache. I-cache is already enabled in start.S */
dcache_enable();
}
void v7_outer_cache_enable(void)
{
- if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+ if (IS_ENABLED(CONFIG_ARMADA_XP)) {
struct pl310_regs *const pl310 =
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
u32 u;
return 0;
}
-/* Return the width of the DRAM bus, or 0 for unknown. */
+/* Return the width of the DRAM bus. */
static int bus_width(void)
{
int full_width = 0;
if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_WIDTH_OFFS))
full_width = 1;
- switch (mvebu_soc_family()) {
- case MVEBU_SOC_AXP:
- return full_width ? 64 : 32;
- break;
- case MVEBU_SOC_A375:
- case MVEBU_SOC_A38X:
- case MVEBU_SOC_MSYS:
- return full_width ? 32 : 16;
- default:
- return 0;
- }
+#ifdef CONFIG_ARMADA_XP
+ return full_width ? 64 : 32;
+#else
+ return full_width ? 32 : 16;
+#endif
}
static int cycle_mode(void)
CPU_ATTR_DEV_CS3 = 0x37,
};
-enum {
- MVEBU_SOC_AXP,
- MVEBU_SOC_A375,
- MVEBU_SOC_A38X,
- MVEBU_SOC_MSYS,
- MVEBU_SOC_UNKNOWN,
-};
-
#define MVEBU_SDRAM_SIZE_MAX 0xc0000000
/*
unsigned int mvebu_sdram_bs(enum memory_bank bank);
void mvebu_sdram_size_adjust(enum memory_bank bank);
int mvebu_mbus_probe(struct mbus_win windows[], int count);
-int mvebu_soc_family(void);
u32 mvebu_get_nand_clock(void);
void __noreturn return_to_bootrom(void);
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2018 Marek Behún <kabel@kernel.org>
* Copyright (C) 2021 Pali Rohár <pali@kernel.org>
*/
slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable
support for this.
-config INITIAL_USB_SCAN_DELAY
- int "delay initial usb scan by x ms to allow builtin devices to init"
- default 0
- ---help---
- Some boards have on board usb devices which need longer than the
- USB spec's 1 second to connect from board powerup. Set this config
- option to a non 0 value to add an extra delay before the first usb
- bus scan.
-
config USB0_VBUS_PIN
string "Vbus enable pin for usb0 (otg)"
default ""
int "LCD panel display clock phase"
depends on VIDEO_SUNXI || DM_VIDEO
default 1
+ range 0 3
---help---
- Select LCD panel display clock phase shift, range 0-3.
+ Select LCD panel display clock phase shift
config VIDEO_LCD_POWER
string "LCD panel power enable pin"
};
};
- gpio-wdt {
+ wdt-gpio-toggle {
gpios = <&gpio_a 7 0>;
compatible = "linux,wdt-gpio";
hw_margin_ms = <100>;
+ hw_algo = "toggle";
+ always-running;
+ };
+
+ wdt-gpio-level {
+ gpios = <&gpio_a 7 0>;
+ compatible = "linux,wdt-gpio";
+ hw_margin_ms = <100>;
+ hw_algo = "level";
always-running;
};
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
* Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
*/
#include <env.h>
#include <net.h>
+#include <dm/device.h>
#include <dm/uclass.h>
#include <atsha204a-i2c.h>
#define TURRIS_ATSHA_OTP_MAC0 3
#define TURRIS_ATSHA_OTP_MAC1 4
+extern U_BOOT_DRIVER(atsha204);
+
static struct udevice *get_atsha204a_dev(void)
{
/* Cannot be static because BSS does not have to be ready at this early stage */
struct udevice *dev;
- if (uclass_get_device_by_name(UCLASS_MISC, "crypto@64", &dev)) {
+ if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(atsha204), &dev)) {
puts("Cannot find ATSHA204A on I2C bus!\n");
dev = NULL;
}
-TURRIS OMNIA BOARD
-M: Marek Behún <marek.behun@nic.cz>
+TURRIS MOX BOARD
+M: Marek Behún <kabel@kernel.org>
+M: Pali Rohár <pali@kernel.org>
S: Maintained
+F: arch/arm/dts/armada-3720-turris-mox*.dts*
F: board/CZ.NIC/turris_mox/
F: include/configs/turris_mox.h
F: configs/turris_mox_defconfig
# SPDX-License-Identifier: GPL-2.0+
#
-# Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+# Copyright (C) 2018 Marek Behún <kabel@kernel.org>
obj-y := turris_mox.o mox_sp.o
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2018 Marek Behún <kabel@kernel.org>
*/
#include <common.h>
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2018 Marek Behún <kabel@kernel.org>
*/
#ifndef _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2018 Marek Behún <kabel@kernel.org>
*/
#include <common.h>
TURRIS OMNIA BOARD
-M: Marek Behún <marek.behun@nic.cz>
+M: Marek Behún <kabel@kernel.org>
+M: Pali Rohár <pali@kernel.org>
S: Maintained
+F: arch/arm/dts/armada-385-turris-omnia*.dts*
+F: board/CZ.NIC/turris_atsha_otp.*
F: board/CZ.NIC/turris_omnia/
-F: include/configs/turris_omnia.h
F: configs/turris_omnia_defconfig
+F: include/configs/turris_omnia.h
# SPDX-License-Identifier: GPL-2.0+
#
-# Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+# Copyright (C) 2017 Marek Behún <kabel@kernel.org>
obj-y := turris_omnia.o ../turris_atsha_otp.o
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
* Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
*
* Derived from the code for
M: Konstantin Porotchkin <kostap@marvell.com>
S: Maintained
F: configs/mvebu_espressobin-88f3720_defconfig
-
-uDPU BOARD
-M: Vladimir Vid <vladimir.vid@sartura.hr>
-S: Maintained
-F: configs/uDPU_defconfig
config CMD_TLV_EEPROM
bool "tlv_eeprom"
depends on I2C_EEPROM
+ select CRC32
help
Display and program the system EEPROM data block in ONIE Tlvinfo
format. TLV stands for Type-Length-Value.
bool "tlv_eeprom for SPL"
depends on SPL_I2C_EEPROM
select SPL_DRIVERS_MISC
+ select SPL_CRC32
help
Read system EEPROM data block in ONIE Tlvinfo format from SPL.
// SPDX-License-Identifier: GPL-2.0+
/*
- * 2017 by Marek Behun <marek.behun@nic.cz>
+ * 2017 by Marek Behún <kabel@kernel.org>
*/
#include <common.h>
return 1;
}
+ if (strncmp(argv[0], "read", 4) != 0 && flash->flash_is_unlocked &&
+ !flash->flash_is_unlocked(flash, offset, len)) {
+ printf("ERROR: flash area is locked\n");
+ return 1;
+ }
+
buf = map_physmem(addr, len, MAP_WRBACK);
if (!buf && addr) {
puts("Failed to map physical memory\n");
return 1;
}
+ if (flash->flash_is_unlocked &&
+ !flash->flash_is_unlocked(flash, offset, len)) {
+ printf("ERROR: flash area is locked\n");
+ return 1;
+ }
+
ret = spi_flash_erase(flash, offset, size);
printf("SF: %zu bytes @ %#x Erased: ", (size_t)size, (u32)offset);
if (ret)
config SPL_RAW_IMAGE_SUPPORT
bool "Support SPL loading and booting of RAW images"
+ default n if ARCH_MVEBU
default n if (ARCH_MX6 && (SPL_MMC || SPL_SATA))
default y
depends on !TI_SECURE_DEVICE
config SPL_LEGACY_IMAGE_FORMAT
bool "Support SPL loading and booting of Legacy images"
+ default n if ARCH_MVEBU
default y if !SPL_LOAD_FIT
depends on !TI_SECURE_DEVICE
help
spl_image->size,
(void *)spl_image->load_addr);
}
+ if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) {
+ err = spi_nor_remove(flash);
+ if (err)
+ return err;
+ }
}
return err;
CONFIG_DFU_RAM=y
CONFIG_DFU_SF=y
CONFIG_MISC=y
+CONFIG_SPL_MISC=y
CONFIG_SYS_I2C_EEPROM_ADDR=0x50
CONFIG_MMC_OMAP_HS=y
CONFIG_MTD=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_OMAP=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_DWC3_PHY_OMAP=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
CONFIG_AM43XX=y
CONFIG_SPL=y
+CONFIG_SPL_MISC=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x4033ff00
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_OMAP=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_DWC3_PHY_OMAP=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000
CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL=y
+CONFIG_SPL_MISC=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x4033ff00
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_OMAP=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_DWC3_PHY_OMAP=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000
CONFIG_TARGET_AM57XX_EVM=y
CONFIG_SPL=y
+CONFIG_SPL_MISC=y
CONFIG_ENV_OFFSET_REDUND=0x280000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y
CONFIG_USB_XHCI_OMAP=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
CONFIG_ENV_OFFSET=0x680000
CONFIG_DM_GPIO=y
CONFIG_SPL_DM_SPI=y
+CONFIG_SPL_MISC=y
CONFIG_DEFAULT_DEVICE_TREE="k3-am654-base-board"
CONFIG_SPL_TEXT_BASE=0x80080000
CONFIG_SPL_MMC=y
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_KEYBOARD=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_SYS_MALLOC_LEN=0x2000000
CONFIG_SYS_MALLOC_F_LEN=0x55000
CONFIG_SPL_GPIO=y
+CONFIG_SPL_MISC=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_NR_DRAM_BANKS=2
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_OMAP54XX=y
CONFIG_TARGET_DRA7XX_EVM=y
CONFIG_SPL=y
+CONFIG_SPL_MISC=y
CONFIG_ENV_OFFSET_REDUND=0x280000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_OMAP=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_DWC3_PHY_OMAP=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000
CONFIG_TARGET_DRA7XX_EVM=y
CONFIG_SPL=y
+CONFIG_SPL_MISC=y
CONFIG_ENV_OFFSET_REDUND=0x280000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_OMAP=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_DWC3_PHY_OMAP=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000
CONFIG_TARGET_DRA7XX_EVM=y
CONFIG_SPL=y
+CONFIG_SPL_MISC=y
CONFIG_ENV_OFFSET_REDUND=0x280000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y
CONFIG_USB_XHCI_OMAP=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_SPL_USB_DWC3_GENERIC=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
--- /dev/null
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_TEXT_BASE=0x00000000
+CONFIG_TARGET_MVEBU_ARMADA_37XX=y
+CONFIG_MVEBU_EFUSE=y
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x180000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-3720-eDPU"
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_SYS_LOAD_ADDR=0x6000000
+CONFIG_DEBUG_UART=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_USE_PREBOOT=y
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_ARCH_EARLY_INIT_R=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="eDPU>> "
+CONFIG_SYS_MAXARGS=32
+CONFIG_SYS_PBSIZE=1048
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_FUSE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_MVEBU_BUBT=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_MAC_PARTITION=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ARP_TIMEOUT=200
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_LBA48=y
+CONFIG_SYS_64BIT_LBA=y
+CONFIG_CLK=y
+CONFIG_CLK_MVEBU=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_MV=y
+CONFIG_MISC=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_XENON=y
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHYLIB_10G=y
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_FIXED=y
+CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
+CONFIG_MVMDIO=y
+CONFIG_PHY=y
+CONFIG_MVEBU_COMPHY_SUPPORT=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_37XX=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+# CONFIG_SCSI is not set
+CONFIG_MVEBU_A3700_UART=y
+CONFIG_MVEBU_A3700_SPI=y
+CONFIG_SYSINFO=y
+CONFIG_SYSINFO_SMBIOS=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_LZO=y
CONFIG_SPL_STACK=0x8000
CONFIG_SYS_PBSIZE=1024
# CONFIG_SYSRESET is not set
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XTX=y
+CONFIG_SPI=y
CONFIG_CMD_PART=y
CONFIG_CMD_PCI=y
CONFIG_CMD_USB=y
+CONFIG_CMD_WDT=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_USB_ETHER_MCS7830=y
CONFIG_USB_ETHER_RTL8152=y
CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_WDT=y
CONFIG_HEXDUMP=y
CONFIG_CONSOLE_MUX=y
CONFIG_SPL_STACK=0x8000
CONFIG_SYS_PBSIZE=1024
+CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SUN8I_EMAC=y
CONFIG_SPI=y
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_USE_ETHPRIME=y
-CONFIG_ETHPRIME="ethernet@34000"
+CONFIG_ETHPRIME="eth2"
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NETCONSOLE=y
CONFIG_DEBUG_UART_BASE=0xd0012000
CONFIG_SYS_LOAD_ADDR=0x6000000
CONFIG_DEBUG_UART=y
-CONFIG_AHCI=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_MTD=y
-CONFIG_CMD_PCI=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_AHCI_MVEBU=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_CLK=y
CONFIG_PHY_MARVELL=y
CONFIG_PHY_FIXED=y
CONFIG_PHY_GIGE=y
-CONFIG_E1000=y
CONFIG_MVNETA=y
CONFIG_MVMDIO=y
-CONFIG_PCI=y
-CONFIG_PCI_AARDVARK=y
CONFIG_PHY=y
CONFIG_MVEBU_COMPHY_SUPPORT=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_ARMADA_37XX=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_GPIO=y
+# CONFIG_SCSI is not set
CONFIG_MVEBU_A3700_UART=y
CONFIG_MVEBU_A3700_SPI=y
CONFIG_SYSINFO=y
config SPL_DOS_PARTITION
bool "Enable MS Dos partition table for SPL"
depends on SPL
+ default n if ARCH_MVEBU
default n if ARCH_SUNXI
default y if DOS_PARTITION
select SPL_PARTITIONS
config SPL_EFI_PARTITION
bool "Enable EFI GPT partition table for SPL"
depends on SPL
+ default n if ARCH_MVEBU
default n if ARCH_SUNXI
default y if EFI_PARTITION
select SPL_PARTITIONS
+-------------------------------+-----------+-----------------+--------------+-------------+------------+-------------+--------------+
| PCIe (+NVMe) | *N/A* | *N/A* | *N/A* | **Yes** | **Yes** | **Yes** | **Yes** |
+-------------------------------+-----------+-----------------+--------------+-------------+------------+-------------+--------------+
+| Watchdog | *N/A* | **Yes** | *N/A* | *N/A* | *N/A* | *N/A* | *N/A* |
++-------------------------------+-----------+-----------------+--------------+-------------+------------+-------------+--------------+
Boot Documentation
------------------
Required properties:
- compatible: Must be "linux,wdt-gpio".
-- gpios: gpio to toggle when wdt driver reset method is called.
+- gpios: From common gpio binding; gpio connection to WDT reset pin.
+- hw_algo: The algorithm used by the driver. Should be one of the
+ following values:
+ - toggle: Toggle from high-to-low or low-to-high when resetting the watchdog.
+ - level: Maintain a constant high/low level, and trigger a short pulse when
+ resetting the watchdog. Active level is determined by the GPIO flags.
- always-running: Boolean property indicating that the watchdog cannot
be disabled. At present, U-Boot only supports this kind of GPIO
watchdog.
gpio-wdt {
gpios = <&gpio0 1 0>;
compatible = "linux,wdt-gpio";
+ hw_algo = "toggle";
always-running;
};
.br
Pali Rohár <pali@kernel.org>
.br
-Marek Behún <marek.behun@nic.cz>
+Marek Behún <kabel@kernel.org>
/*
* Marvell Armada 37xx SoC Peripheral clocks
*
- * Marek Behun <marek.behun@nic.cz>
+ * Marek Behún <kabel@kernel.org>
*
* Based on Linux driver by:
* Gregory CLEMENT <gregory.clement@free-electrons.com>
/*
* Marvell Armada 37xx SoC Time Base Generator clocks
*
- * Marek Behun <marek.behun@nic.cz>
+ * Marek Behún <kabel@kernel.org>
*
* Based on Linux driver by:
* Gregory CLEMENT <gregory.clement@free-electrons.com>
[RST_USB_PHY2] = RESET(0x0cc, BIT(2)),
};
-static const struct ccu_desc a10_ccu_desc = {
+const struct ccu_desc a10_ccu_desc = {
.gates = a10_gates,
.resets = a10_resets,
-};
-
-static int a10_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a10_resets));
-}
-
-static const struct udevice_id a10_ccu_ids[] = {
- { .compatible = "allwinner,sun4i-a10-ccu",
- .data = (ulong)&a10_ccu_desc },
- { .compatible = "allwinner,sun7i-a20-ccu",
- .data = (ulong)&a10_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun4i_a10) = {
- .name = "sun4i_a10_ccu",
- .id = UCLASS_CLK,
- .of_match = a10_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a10_clk_bind,
+ .num_gates = ARRAY_SIZE(a10_gates),
+ .num_resets = ARRAY_SIZE(a10_resets),
};
[RST_USB_PHY1] = RESET(0x0cc, BIT(1)),
};
-static const struct ccu_desc a10s_ccu_desc = {
+const struct ccu_desc a10s_ccu_desc = {
.gates = a10s_gates,
.resets = a10s_resets,
-};
-
-static int a10s_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a10s_resets));
-}
-
-static const struct udevice_id a10s_ccu_ids[] = {
- { .compatible = "allwinner,sun5i-a10s-ccu",
- .data = (ulong)&a10s_ccu_desc },
- { .compatible = "allwinner,sun5i-a13-ccu",
- .data = (ulong)&a10s_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun5i_a10s) = {
- .name = "sun5i_a10s_ccu",
- .id = UCLASS_CLK,
- .of_match = a10s_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a10s_clk_bind,
+ .num_gates = ARRAY_SIZE(a10s_gates),
+ .num_resets = ARRAY_SIZE(a10s_resets),
};
[RST_BUS_UART4] = RESET(0x2d8, BIT(20)),
};
-static const struct ccu_desc a23_ccu_desc = {
+const struct ccu_desc a23_ccu_desc = {
.gates = a23_gates,
.resets = a23_resets,
-};
-
-static int a23_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a23_resets));
-}
-
-static const struct udevice_id a23_clk_ids[] = {
- { .compatible = "allwinner,sun8i-a23-ccu",
- .data = (ulong)&a23_ccu_desc },
- { .compatible = "allwinner,sun8i-a33-ccu",
- .data = (ulong)&a23_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun8i_a23) = {
- .name = "sun8i_a23_ccu",
- .id = UCLASS_CLK,
- .of_match = a23_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a23_clk_bind,
+ .num_gates = ARRAY_SIZE(a23_gates),
+ .num_resets = ARRAY_SIZE(a23_resets),
};
[RST_APB2_UART5] = RESET(0x2d8, BIT(21)),
};
-static const struct ccu_desc a31_ccu_desc = {
+const struct ccu_desc a31_ccu_desc = {
.gates = a31_gates,
.resets = a31_resets,
-};
-
-static int a31_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a31_resets));
-}
-
-static const struct udevice_id a31_clk_ids[] = {
- { .compatible = "allwinner,sun6i-a31-ccu",
- .data = (ulong)&a31_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun6i_a31) = {
- .name = "sun6i_a31_ccu",
- .id = UCLASS_CLK,
- .of_match = a31_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a31_clk_bind,
+ .num_gates = ARRAY_SIZE(a31_gates),
+ .num_resets = ARRAY_SIZE(a31_resets),
};
[RST_APB0_I2C] = RESET(0x0b0, BIT(6)),
};
-static const struct ccu_desc a31_r_ccu_desc = {
+const struct ccu_desc a31_r_ccu_desc = {
.gates = a31_r_gates,
.resets = a31_r_resets,
-};
-
-static int a31_r_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a31_r_resets));
-}
-
-static const struct udevice_id a31_r_clk_ids[] = {
- { .compatible = "allwinner,sun8i-a83t-r-ccu",
- .data = (ulong)&a31_r_ccu_desc },
- { .compatible = "allwinner,sun8i-h3-r-ccu",
- .data = (ulong)&a31_r_ccu_desc },
- { .compatible = "allwinner,sun50i-a64-r-ccu",
- .data = (ulong)&a31_r_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun6i_a31_r) = {
- .name = "sun6i_a31_r_ccu",
- .id = UCLASS_CLK,
- .of_match = a31_r_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a31_r_clk_bind,
+ .num_gates = ARRAY_SIZE(a31_r_gates),
+ .num_resets = ARRAY_SIZE(a31_r_resets),
};
[RST_BUS_UART4] = RESET(0x2d8, BIT(20)),
};
-static const struct ccu_desc a64_ccu_desc = {
+const struct ccu_desc a64_ccu_desc = {
.gates = a64_gates,
.resets = a64_resets,
-};
-
-static int a64_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a64_resets));
-}
-
-static const struct udevice_id a64_ccu_ids[] = {
- { .compatible = "allwinner,sun50i-a64-ccu",
- .data = (ulong)&a64_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun50i_a64) = {
- .name = "sun50i_a64_ccu",
- .id = UCLASS_CLK,
- .of_match = a64_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a64_clk_bind,
+ .num_gates = ARRAY_SIZE(a64_gates),
+ .num_resets = ARRAY_SIZE(a64_resets),
};
[3] = GATE(0xc, BIT(18)),
};
-static const struct ccu_desc a80_ccu_desc = {
+const struct ccu_desc a80_ccu_desc = {
.gates = a80_gates,
.resets = a80_resets,
+ .num_gates = ARRAY_SIZE(a80_gates),
+ .num_resets = ARRAY_SIZE(a80_resets),
};
-static const struct ccu_desc a80_mmc_clk_desc = {
+const struct ccu_desc a80_mmc_clk_desc = {
.gates = a80_mmc_gates,
.resets = a80_mmc_resets,
-};
-
-static int a80_clk_bind(struct udevice *dev)
-{
- ulong count = ARRAY_SIZE(a80_resets);
-
- if (device_is_compatible(dev, "allwinner,sun9i-a80-mmc-config-clk"))
- count = ARRAY_SIZE(a80_mmc_resets);
-
- return sunxi_reset_bind(dev, count);
-}
-
-static const struct udevice_id a80_ccu_ids[] = {
- { .compatible = "allwinner,sun9i-a80-ccu",
- .data = (ulong)&a80_ccu_desc },
- { .compatible = "allwinner,sun9i-a80-mmc-config-clk",
- .data = (ulong)&a80_mmc_clk_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun9i_a80) = {
- .name = "sun9i_a80_ccu",
- .id = UCLASS_CLK,
- .of_match = a80_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a80_clk_bind,
+ .num_gates = ARRAY_SIZE(a80_mmc_gates),
+ .num_resets = ARRAY_SIZE(a80_mmc_resets),
};
[RST_BUS_UART4] = RESET(0x2d8, BIT(20)),
};
-static const struct ccu_desc a83t_ccu_desc = {
+const struct ccu_desc a83t_ccu_desc = {
.gates = a83t_gates,
.resets = a83t_resets,
-};
-
-static int a83t_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(a83t_resets));
-}
-
-static const struct udevice_id a83t_clk_ids[] = {
- { .compatible = "allwinner,sun8i-a83t-ccu",
- .data = (ulong)&a83t_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun8i_a83t) = {
- .name = "sun8i_a83t_ccu",
- .id = UCLASS_CLK,
- .of_match = a83t_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = a83t_clk_bind,
+ .num_gates = ARRAY_SIZE(a83t_gates),
+ .num_resets = ARRAY_SIZE(a83t_resets),
};
[RST_BUS_UART2] = RESET(0x2d0, BIT(22)),
};
-static const struct ccu_desc f1c100s_ccu_desc = {
+const struct ccu_desc f1c100s_ccu_desc = {
.gates = f1c100s_gates,
.resets = f1c100s_resets,
-};
-
-static int f1c100s_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(f1c100s_resets));
-}
-
-static const struct udevice_id f1c100s_clk_ids[] = {
- { .compatible = "allwinner,suniv-f1c100s-ccu",
- .data = (ulong)&f1c100s_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_suniv_f1c100s) = {
- .name = "suniv_f1c100s_ccu",
- .id = UCLASS_CLK,
- .of_match = f1c100s_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = f1c100s_clk_bind,
+ .num_gates = ARRAY_SIZE(f1c100s_gates),
+ .num_resets = ARRAY_SIZE(f1c100s_resets),
};
[RST_BUS_UART3] = RESET(0x2d8, BIT(19)),
};
-static const struct ccu_desc h3_ccu_desc = {
+const struct ccu_desc h3_ccu_desc = {
.gates = h3_gates,
.resets = h3_resets,
-};
-
-static int h3_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(h3_resets));
-}
-
-static const struct udevice_id h3_ccu_ids[] = {
- { .compatible = "allwinner,sun8i-h3-ccu",
- .data = (ulong)&h3_ccu_desc },
- { .compatible = "allwinner,sun50i-h5-ccu",
- .data = (ulong)&h3_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun8i_h3) = {
- .name = "sun8i_h3_ccu",
- .id = UCLASS_CLK,
- .of_match = h3_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = h3_clk_bind,
+ .num_gates = ARRAY_SIZE(h3_gates),
+ .num_resets = ARRAY_SIZE(h3_resets),
};
[RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
};
-static const struct ccu_desc h6_ccu_desc = {
+const struct ccu_desc h6_ccu_desc = {
.gates = h6_gates,
.resets = h6_resets,
-};
-
-static int h6_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(h6_resets));
-}
-
-static const struct udevice_id h6_ccu_ids[] = {
- { .compatible = "allwinner,sun50i-h6-ccu",
- .data = (ulong)&h6_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun50i_h6) = {
- .name = "sun50i_h6_ccu",
- .id = UCLASS_CLK,
- .of_match = h6_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = h6_clk_bind,
+ .num_gates = ARRAY_SIZE(h6_gates),
+ .num_resets = ARRAY_SIZE(h6_resets),
};
[RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
};
-static const struct ccu_desc h616_ccu_desc = {
+const struct ccu_desc h616_ccu_desc = {
.gates = h616_gates,
.resets = h616_resets,
-};
-
-static int h616_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(h616_resets));
-}
-
-static const struct udevice_id h616_ccu_ids[] = {
- { .compatible = "allwinner,sun50i-h616-ccu",
- .data = (ulong)&h616_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun50i_h616) = {
- .name = "sun50i_h616_ccu",
- .id = UCLASS_CLK,
- .of_match = h616_ccu_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = h616_clk_bind,
+ .num_gates = ARRAY_SIZE(h616_gates),
+ .num_resets = ARRAY_SIZE(h616_resets),
};
[RST_R_APB1_W1] = RESET(0x1ec, BIT(16)),
};
-static const struct ccu_desc h6_r_ccu_desc = {
+const struct ccu_desc h6_r_ccu_desc = {
.gates = h6_r_gates,
.resets = h6_r_resets,
-};
-
-static int h6_r_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(h6_r_resets));
-}
-
-static const struct udevice_id h6_r_clk_ids[] = {
- { .compatible = "allwinner,sun50i-h6-r-ccu",
- .data = (ulong)&h6_r_ccu_desc },
- { .compatible = "allwinner,sun50i-h616-r-ccu",
- .data = (ulong)&h6_r_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun50i_h6_r) = {
- .name = "sun50i_h6_r_ccu",
- .id = UCLASS_CLK,
- .of_match = h6_r_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = h6_r_clk_bind,
+ .num_gates = ARRAY_SIZE(h6_r_gates),
+ .num_resets = ARRAY_SIZE(h6_r_resets),
};
[RST_BUS_UART7] = RESET(0x2d8, BIT(23)),
};
-static const struct ccu_desc r40_ccu_desc = {
+const struct ccu_desc r40_ccu_desc = {
.gates = r40_gates,
.resets = r40_resets,
-};
-
-static int r40_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(r40_resets));
-}
-
-static const struct udevice_id r40_clk_ids[] = {
- { .compatible = "allwinner,sun8i-r40-ccu",
- .data = (ulong)&r40_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun8i_r40) = {
- .name = "sun8i_r40_ccu",
- .id = UCLASS_CLK,
- .of_match = r40_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = r40_clk_bind,
+ .num_gates = ARRAY_SIZE(r40_gates),
+ .num_resets = ARRAY_SIZE(r40_resets),
};
#include <reset.h>
#include <asm/io.h>
#include <clk/sunxi.h>
+#include <dm/device-internal.h>
#include <linux/bitops.h>
#include <linux/log2.h>
-static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
+extern U_BOOT_DRIVER(sunxi_reset);
+
+static const struct ccu_clk_gate *plat_to_gate(struct ccu_plat *plat,
unsigned long id)
{
- return &priv->desc->gates[id];
+ if (id >= plat->desc->num_gates)
+ return NULL;
+
+ return &plat->desc->gates[id];
}
static int sunxi_set_gate(struct clk *clk, bool on)
{
- struct ccu_priv *priv = dev_get_priv(clk->dev);
- const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
+ struct ccu_plat *plat = dev_get_plat(clk->dev);
+ const struct ccu_clk_gate *gate = plat_to_gate(plat, clk->id);
u32 reg;
- if ((gate->flags & CCU_CLK_F_DUMMY_GATE))
+ if (gate && (gate->flags & CCU_CLK_F_DUMMY_GATE))
return 0;
- if (!(gate->flags & CCU_CLK_F_IS_VALID)) {
+ if (!gate || !(gate->flags & CCU_CLK_F_IS_VALID)) {
printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
return 0;
}
debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
clk->id, gate->off, ilog2(gate->bit));
- reg = readl(priv->base + gate->off);
+ reg = readl(plat->base + gate->off);
if (on)
reg |= gate->bit;
else
reg &= ~gate->bit;
- writel(reg, priv->base + gate->off);
+ writel(reg, plat->base + gate->off);
return 0;
}
.disable = sunxi_clk_disable,
};
-int sunxi_clk_probe(struct udevice *dev)
+static int sunxi_clk_bind(struct udevice *dev)
+{
+ /* Reuse the platform data for the reset driver. */
+ return device_bind(dev, DM_DRIVER_REF(sunxi_reset), "reset",
+ dev_get_plat(dev), dev_ofnode(dev), NULL);
+}
+
+static int sunxi_clk_probe(struct udevice *dev)
{
- struct ccu_priv *priv = dev_get_priv(dev);
struct clk_bulk clk_bulk;
struct reset_ctl_bulk rst_bulk;
int ret;
- priv->base = dev_read_addr_ptr(dev);
- if (!priv->base)
- return -ENOMEM;
-
- priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
- if (!priv->desc)
- return -EINVAL;
-
ret = clk_get_bulk(dev, &clk_bulk);
if (!ret)
clk_enable_bulk(&clk_bulk);
return 0;
}
+
+static int sunxi_clk_of_to_plat(struct udevice *dev)
+{
+ struct ccu_plat *plat = dev_get_plat(dev);
+
+ plat->base = dev_read_addr_ptr(dev);
+ if (!plat->base)
+ return -ENOMEM;
+
+ plat->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
+ if (!plat->desc)
+ return -EINVAL;
+
+ return 0;
+}
+
+extern const struct ccu_desc a10_ccu_desc;
+extern const struct ccu_desc a10s_ccu_desc;
+extern const struct ccu_desc a23_ccu_desc;
+extern const struct ccu_desc a31_ccu_desc;
+extern const struct ccu_desc a31_r_ccu_desc;
+extern const struct ccu_desc a64_ccu_desc;
+extern const struct ccu_desc a80_ccu_desc;
+extern const struct ccu_desc a80_mmc_clk_desc;
+extern const struct ccu_desc a83t_ccu_desc;
+extern const struct ccu_desc f1c100s_ccu_desc;
+extern const struct ccu_desc h3_ccu_desc;
+extern const struct ccu_desc h6_ccu_desc;
+extern const struct ccu_desc h616_ccu_desc;
+extern const struct ccu_desc h6_r_ccu_desc;
+extern const struct ccu_desc r40_ccu_desc;
+extern const struct ccu_desc v3s_ccu_desc;
+
+static const struct udevice_id sunxi_clk_ids[] = {
+#ifdef CONFIG_CLK_SUN4I_A10
+ { .compatible = "allwinner,sun4i-a10-ccu",
+ .data = (ulong)&a10_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN5I_A10S
+ { .compatible = "allwinner,sun5i-a10s-ccu",
+ .data = (ulong)&a10s_ccu_desc },
+ { .compatible = "allwinner,sun5i-a13-ccu",
+ .data = (ulong)&a10s_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN6I_A31
+ { .compatible = "allwinner,sun6i-a31-ccu",
+ .data = (ulong)&a31_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN4I_A10
+ { .compatible = "allwinner,sun7i-a20-ccu",
+ .data = (ulong)&a10_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN8I_A23
+ { .compatible = "allwinner,sun8i-a23-ccu",
+ .data = (ulong)&a23_ccu_desc },
+ { .compatible = "allwinner,sun8i-a33-ccu",
+ .data = (ulong)&a23_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN8I_A83T
+ { .compatible = "allwinner,sun8i-a83t-ccu",
+ .data = (ulong)&a83t_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN6I_A31_R
+ { .compatible = "allwinner,sun8i-a83t-r-ccu",
+ .data = (ulong)&a31_r_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN8I_H3
+ { .compatible = "allwinner,sun8i-h3-ccu",
+ .data = (ulong)&h3_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN6I_A31_R
+ { .compatible = "allwinner,sun8i-h3-r-ccu",
+ .data = (ulong)&a31_r_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN8I_R40
+ { .compatible = "allwinner,sun8i-r40-ccu",
+ .data = (ulong)&r40_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN8I_V3S
+ { .compatible = "allwinner,sun8i-v3-ccu",
+ .data = (ulong)&v3s_ccu_desc },
+ { .compatible = "allwinner,sun8i-v3s-ccu",
+ .data = (ulong)&v3s_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN9I_A80
+ { .compatible = "allwinner,sun9i-a80-ccu",
+ .data = (ulong)&a80_ccu_desc },
+ { .compatible = "allwinner,sun9i-a80-mmc-config-clk",
+ .data = (ulong)&a80_mmc_clk_desc },
+#endif
+#ifdef CONFIG_CLK_SUN50I_A64
+ { .compatible = "allwinner,sun50i-a64-ccu",
+ .data = (ulong)&a64_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN6I_A31_R
+ { .compatible = "allwinner,sun50i-a64-r-ccu",
+ .data = (ulong)&a31_r_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN8I_H3
+ { .compatible = "allwinner,sun50i-h5-ccu",
+ .data = (ulong)&h3_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN50I_H6
+ { .compatible = "allwinner,sun50i-h6-ccu",
+ .data = (ulong)&h6_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN50I_H6_R
+ { .compatible = "allwinner,sun50i-h6-r-ccu",
+ .data = (ulong)&h6_r_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN50I_H616
+ { .compatible = "allwinner,sun50i-h616-ccu",
+ .data = (ulong)&h616_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUN50I_H6_R
+ { .compatible = "allwinner,sun50i-h616-r-ccu",
+ .data = (ulong)&h6_r_ccu_desc },
+#endif
+#ifdef CONFIG_CLK_SUNIV_F1C100S
+ { .compatible = "allwinner,suniv-f1c100s-ccu",
+ .data = (ulong)&f1c100s_ccu_desc },
+#endif
+ { }
+};
+
+U_BOOT_DRIVER(sunxi_clk) = {
+ .name = "sunxi_clk",
+ .id = UCLASS_CLK,
+ .of_match = sunxi_clk_ids,
+ .bind = sunxi_clk_bind,
+ .probe = sunxi_clk_probe,
+ .of_to_plat = sunxi_clk_of_to_plat,
+ .plat_auto = sizeof(struct ccu_plat),
+ .ops = &sunxi_clk_ops,
+};
[RST_BUS_UART2] = RESET(0x2d8, BIT(18)),
};
-static const struct ccu_desc v3s_ccu_desc = {
+const struct ccu_desc v3s_ccu_desc = {
.gates = v3s_gates,
.resets = v3s_resets,
-};
-
-static int v3s_clk_bind(struct udevice *dev)
-{
- return sunxi_reset_bind(dev, ARRAY_SIZE(v3s_resets));
-}
-
-static const struct udevice_id v3s_clk_ids[] = {
- { .compatible = "allwinner,sun8i-v3s-ccu",
- .data = (ulong)&v3s_ccu_desc },
- { .compatible = "allwinner,sun8i-v3-ccu",
- .data = (ulong)&v3s_ccu_desc },
- { }
-};
-
-U_BOOT_DRIVER(clk_sun8i_v3s) = {
- .name = "sun8i_v3s_ccu",
- .id = UCLASS_CLK,
- .of_match = v3s_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = v3s_clk_bind,
+ .num_gates = ARRAY_SIZE(v3s_gates),
+ .num_resets = ARRAY_SIZE(v3s_resets),
};
have several I2C ports and all are provided, controlled by the
device tree.
+config SYS_I2C_NPCM
+ bool "Nuvoton NPCM I2C driver"
+ help
+ Support for Nuvoton I2C controller driver.
+
config SYS_I2C_OCORES
bool "ocores I2C driver"
depends on DM_I2C
obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
obj-$(CONFIG_SYS_I2C_NEXELL) += nx_i2c.o
+obj-$(CONFIG_SYS_I2C_NPCM) += npcm_i2c.o
obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o
obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
/* Enable Master Mode. Assuming single-master */
writel(I2CD_MASTER_EN
| I2CD_M_SDA_LOCK_EN
- | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
+ | I2CD_MULTI_MASTER_DIS,
&priv->regs->fcr);
/* Enable Interrupts */
writel(I2CD_INTR_TX_ACK
struct udevice *bus = dev_get_parent(dev);
struct dm_i2c_ops *ops = i2c_get_ops(bus);
struct i2c_msg msg[1];
+ uint8_t _buf[I2C_MAX_OFFSET_LEN + 64];
+ uint8_t *buf = _buf;
+ int ret;
if (!ops->xfer)
return -ENOSYS;
* need to allow space for the offset (up to 4 bytes) and the message
* itself.
*/
- if (len < 64) {
- uint8_t buf[I2C_MAX_OFFSET_LEN + len];
-
- i2c_setup_offset(chip, offset, buf, msg);
- msg->len += len;
- memcpy(buf + chip->offset_len, buffer, len);
-
- return ops->xfer(bus, msg, 1);
- } else {
- uint8_t *buf;
- int ret;
-
+ if (len > sizeof(_buf) - I2C_MAX_OFFSET_LEN) {
buf = malloc(I2C_MAX_OFFSET_LEN + len);
if (!buf)
return -ENOMEM;
- i2c_setup_offset(chip, offset, buf, msg);
- msg->len += len;
- memcpy(buf + chip->offset_len, buffer, len);
+ }
- ret = ops->xfer(bus, msg, 1);
+ i2c_setup_offset(chip, offset, buf, msg);
+ msg->len += len;
+ memcpy(buf + chip->offset_len, buffer, len);
+
+ ret = ops->xfer(bus, msg, 1);
+ if (buf != _buf)
free(buf);
- return ret;
- }
+ return ret;
}
int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Nuvoton Technology Corp.
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include <asm/arch/gcr.h>
+
+#define I2C_FREQ_100K 100000
+#define NPCM_I2C_TIMEOUT_MS 10
+#define NPCM7XX_I2CSEGCTL_INIT_VAL 0x0333F000
+#define NPCM8XX_I2CSEGCTL_INIT_VAL 0x9333F000
+
+/* SCLFRQ min/max field values */
+#define SCLFRQ_MIN 10
+#define SCLFRQ_MAX 511
+
+/* SMBCTL1 */
+#define SMBCTL1_START BIT(0)
+#define SMBCTL1_STOP BIT(1)
+#define SMBCTL1_INTEN BIT(2)
+#define SMBCTL1_ACK BIT(4)
+#define SMBCTL1_STASTRE BIT(7)
+
+/* SMBCTL2 */
+#define SMBCTL2_ENABLE BIT(0)
+
+/* SMBCTL3 */
+#define SMBCTL3_SCL_LVL BIT(7)
+#define SMBCTL3_SDA_LVL BIT(6)
+
+/* SMBCST */
+#define SMBCST_BB BIT(1)
+#define SMBCST_TGSCL BIT(5)
+
+/* SMBST */
+#define SMBST_XMIT BIT(0)
+#define SMBST_MASTER BIT(1)
+#define SMBST_STASTR BIT(3)
+#define SMBST_NEGACK BIT(4)
+#define SMBST_BER BIT(5)
+#define SMBST_SDAST BIT(6)
+
+/* SMBCST3 in bank0 */
+#define SMBCST3_EO_BUSY BIT(7)
+
+/* SMBFIF_CTS in bank1 */
+#define SMBFIF_CTS_CLR_FIFO BIT(6)
+
+#define SMBFIF_CTL_FIFO_EN BIT(4)
+#define SMBCTL3_BNK_SEL BIT(5)
+
+enum {
+ I2C_ERR_NACK = 1,
+ I2C_ERR_BER,
+ I2C_ERR_TIMEOUT,
+};
+
+struct smb_bank0_regs {
+ u8 addr3;
+ u8 addr7;
+ u8 addr4;
+ u8 addr8;
+ u16 addr5;
+ u16 addr6;
+ u8 cst2;
+ u8 cst3;
+ u8 ctl4;
+ u8 ctl5;
+ u8 scllt;
+ u8 fif_ctl;
+ u8 sclht;
+};
+
+struct smb_bank1_regs {
+ u8 fif_cts;
+ u8 fair_per;
+ u16 txf_ctl;
+ u32 t_out;
+ u8 cst2;
+ u8 cst3;
+ u16 txf_sts;
+ u16 rxf_sts;
+ u8 rxf_ctl;
+};
+
+struct npcm_i2c_regs {
+ u16 sda;
+ u16 st;
+ u16 cst;
+ u16 ctl1;
+ u16 addr;
+ u16 ctl2;
+ u16 addr2;
+ u16 ctl3;
+ union {
+ struct smb_bank0_regs bank0;
+ struct smb_bank1_regs bank1;
+ };
+
+};
+
+struct npcm_i2c_bus {
+ struct npcm_i2c_regs *reg;
+ int num;
+ u32 apb_clk;
+ u32 freq;
+ bool started;
+};
+
+static void npcm_dump_regs(struct npcm_i2c_bus *bus)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+
+ printf("\n");
+ printf("SMBST=0x%x\n", readb(®->st));
+ printf("SMBCST=0x%x\n", readb(®->cst));
+ printf("SMBCTL1=0x%x\n", readb(®->ctl1));
+ printf("\n");
+}
+
+static int npcm_i2c_check_sda(struct npcm_i2c_bus *bus)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ ulong start_time;
+ int err = I2C_ERR_TIMEOUT;
+ u8 val;
+
+ start_time = get_timer(0);
+ /* wait SDAST to be 1 */
+ while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) {
+ val = readb(®->st);
+ if (val & SMBST_NEGACK) {
+ err = I2C_ERR_NACK;
+ break;
+ }
+ if (val & SMBST_BER) {
+ err = I2C_ERR_BER;
+ break;
+ }
+ if (val & SMBST_SDAST) {
+ err = 0;
+ break;
+ }
+ }
+
+ if (err)
+ printf("%s: err %d\n", __func__, err);
+
+ return err;
+}
+
+static int npcm_i2c_send_start(struct npcm_i2c_bus *bus)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ ulong start_time;
+ int err = I2C_ERR_TIMEOUT;
+
+ /* Generate START condition */
+ setbits_8(®->ctl1, SMBCTL1_START);
+
+ start_time = get_timer(0);
+ while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) {
+ if (readb(®->st) & SMBST_BER)
+ return I2C_ERR_BER;
+ if (readb(®->st) & SMBST_MASTER) {
+ err = 0;
+ break;
+ }
+ }
+ bus->started = true;
+
+ return err;
+}
+
+static int npcm_i2c_send_stop(struct npcm_i2c_bus *bus, bool wait)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ ulong start_time;
+ int err = I2C_ERR_TIMEOUT;
+
+ setbits_8(®->ctl1, SMBCTL1_STOP);
+
+ /* Clear NEGACK, STASTR and BER bits */
+ writeb(SMBST_STASTR | SMBST_NEGACK | SMBST_BER, ®->st);
+
+ bus->started = false;
+
+ if (!wait)
+ return 0;
+
+ start_time = get_timer(0);
+ while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) {
+ if ((readb(®->ctl1) & SMBCTL1_STOP) == 0) {
+ err = 0;
+ break;
+ }
+ }
+ if (err) {
+ printf("%s: err %d\n", __func__, err);
+ npcm_dump_regs(bus);
+ }
+
+ return err;
+}
+
+static void npcm_i2c_reset(struct npcm_i2c_bus *bus)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+
+ debug("%s: module %d\n", __func__, bus->num);
+ /* disable & enable SMB moudle */
+ clrbits_8(®->ctl2, SMBCTL2_ENABLE);
+ setbits_8(®->ctl2, SMBCTL2_ENABLE);
+
+ /* clear BB and status */
+ writeb(SMBCST_BB, ®->cst);
+ writeb(0xff, ®->st);
+
+ /* select bank 1 */
+ setbits_8(®->ctl3, SMBCTL3_BNK_SEL);
+ /* Clear all fifo bits */
+ writeb(SMBFIF_CTS_CLR_FIFO, ®->bank1.fif_cts);
+
+ /* select bank 0 */
+ clrbits_8(®->ctl3, SMBCTL3_BNK_SEL);
+ /* clear EOB bit */
+ writeb(SMBCST3_EO_BUSY, ®->bank0.cst3);
+ /* single byte mode */
+ clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN);
+
+ /* set POLL mode */
+ writeb(0, ®->ctl1);
+}
+
+static void npcm_i2c_recovery(struct npcm_i2c_bus *bus, u32 addr)
+{
+ u8 val;
+ int iter = 27;
+ struct npcm_i2c_regs *reg = bus->reg;
+ int err;
+
+ val = readb(®->ctl3);
+ /* Skip recovery, bus not stucked */
+ if ((val & SMBCTL3_SCL_LVL) && (val & SMBCTL3_SDA_LVL))
+ return;
+
+ printf("Performing I2C bus %d recovery...\n", bus->num);
+ /* SCL/SDA are not releaed, perform recovery */
+ while (1) {
+ /* toggle SCL line */
+ writeb(SMBCST_TGSCL, ®->cst);
+
+ udelay(20);
+ val = readb(®->ctl3);
+ if (val & SMBCTL3_SDA_LVL)
+ break;
+ if (iter-- == 0)
+ break;
+ }
+
+ if (val & SMBCTL3_SDA_LVL) {
+ writeb((u8)((addr << 1) & 0xff), ®->sda);
+ err = npcm_i2c_send_start(bus);
+ if (!err) {
+ udelay(20);
+ npcm_i2c_send_stop(bus, false);
+ udelay(200);
+ printf("I2C bus %d recovery completed\n",
+ bus->num);
+ } else {
+ printf("%s: send START err %d\n", __func__, err);
+ }
+ } else {
+ printf("Fail to recover I2C bus %d\n", bus->num);
+ }
+ npcm_i2c_reset(bus);
+}
+
+static int npcm_i2c_send_address(struct npcm_i2c_bus *bus, u8 addr,
+ bool stall)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ ulong start_time;
+ u8 val;
+
+ /* Stall After Start Enable */
+ if (stall)
+ setbits_8(®->ctl1, SMBCTL1_STASTRE);
+
+ writeb(addr, ®->sda);
+ if (stall) {
+ start_time = get_timer(0);
+ while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) {
+ if (readb(®->st) & SMBST_STASTR)
+ break;
+
+ if (readb(®->st) & SMBST_BER) {
+ clrbits_8(®->ctl1, SMBCTL1_STASTRE);
+ return I2C_ERR_BER;
+ }
+ }
+ }
+
+ /* check ACK */
+ val = readb(®->st);
+ if (val & SMBST_NEGACK) {
+ debug("NACK on addr 0x%x\n", addr >> 1);
+ /* After a Stop condition, writing 1 to NEGACK clears it */
+ return I2C_ERR_NACK;
+ }
+ if (val & SMBST_BER)
+ return I2C_ERR_BER;
+
+ return 0;
+}
+
+static int npcm_i2c_read_bytes(struct npcm_i2c_bus *bus, u8 *data, int len)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ u8 val;
+ int i;
+ int err = 0;
+
+ if (len == 1) {
+ /* bus should be stalled before receiving last byte */
+ setbits_8(®->ctl1, SMBCTL1_ACK);
+
+ /* clear STASTRE if it is set */
+ if (readb(®->ctl1) & SMBCTL1_STASTRE) {
+ writeb(SMBST_STASTR, ®->st);
+ clrbits_8(®->ctl1, SMBCTL1_STASTRE);
+ }
+ npcm_i2c_check_sda(bus);
+ npcm_i2c_send_stop(bus, false);
+ *data = readb(®->sda);
+ /* this must be done to generate STOP condition */
+ writeb(SMBST_NEGACK, ®->st);
+ } else {
+ for (i = 0; i < len; i++) {
+ /*
+ * When NEGACK bit is set to 1 after the transmission of a byte,
+ * SDAST is not set to 1.
+ */
+ if (i != (len - 1)) {
+ err = npcm_i2c_check_sda(bus);
+ } else {
+ err = readb_poll_timeout(®->ctl1, val,
+ !(val & SMBCTL1_ACK), 100000);
+ if (err) {
+ printf("wait nack timeout\n");
+ err = I2C_ERR_TIMEOUT;
+ npcm_dump_regs(bus);
+ }
+ }
+ if (err && err != I2C_ERR_TIMEOUT)
+ break;
+ if (i == (len - 2)) {
+ /* set NACK before last byte */
+ setbits_8(®->ctl1, SMBCTL1_ACK);
+ }
+ if (i == (len - 1)) {
+ /* last byte, send STOP condition */
+ npcm_i2c_send_stop(bus, false);
+ *data = readb(®->sda);
+ writeb(SMBST_NEGACK, ®->st);
+ break;
+ }
+ *data = readb(®->sda);
+ data++;
+ }
+ }
+
+ return err;
+}
+
+static int npcm_i2c_send_bytes(struct npcm_i2c_bus *bus, u8 *data, int len)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ u8 val;
+ int i;
+ int err = 0;
+
+ val = readb(®->st);
+ if (val & SMBST_NEGACK)
+ return I2C_ERR_NACK;
+ else if (val & SMBST_BER)
+ return I2C_ERR_BER;
+
+ /* clear STASTRE if it is set */
+ if (readb(®->ctl1) & SMBCTL1_STASTRE)
+ clrbits_8(®->ctl1, SMBCTL1_STASTRE);
+
+ for (i = 0; i < len; i++) {
+ err = npcm_i2c_check_sda(bus);
+ if (err)
+ break;
+ writeb(*data, ®->sda);
+ data++;
+ }
+ npcm_i2c_check_sda(bus);
+
+ return err;
+}
+
+static int npcm_i2c_read(struct npcm_i2c_bus *bus, u32 addr, u8 *data,
+ u32 len)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ int err;
+ bool stall;
+
+ if (len <= 0)
+ return -EINVAL;
+
+ /* send START condition */
+ err = npcm_i2c_send_start(bus);
+ if (err) {
+ debug("%s: send START err %d\n", __func__, err);
+ return err;
+ }
+
+ stall = (len == 1) ? true : false;
+ /* send address byte */
+ err = npcm_i2c_send_address(bus, (u8)(addr << 1) | 0x1, stall);
+
+ if (!err && len)
+ npcm_i2c_read_bytes(bus, data, len);
+
+ if (err == I2C_ERR_NACK) {
+ /* clear NACK */
+ writeb(SMBST_NEGACK, ®->st);
+ }
+
+ if (err)
+ debug("%s: err %d\n", __func__, err);
+
+ return err;
+}
+
+static int npcm_i2c_write(struct npcm_i2c_bus *bus, u32 addr, u8 *data,
+ u32 len)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ int err;
+ bool stall;
+
+ /* send START condition */
+ err = npcm_i2c_send_start(bus);
+ if (err) {
+ debug("%s: send START err %d\n", __func__, err);
+ return err;
+ }
+
+ stall = (len == 0) ? true : false;
+ /* send address byte */
+ err = npcm_i2c_send_address(bus, (u8)(addr << 1), stall);
+
+ if (!err && len)
+ err = npcm_i2c_send_bytes(bus, data, len);
+
+ /* clear STASTRE if it is set */
+ if (stall)
+ clrbits_8(®->ctl1, SMBCTL1_STASTRE);
+
+ if (err)
+ debug("%s: err %d\n", __func__, err);
+
+ return err;
+}
+
+static int npcm_i2c_xfer(struct udevice *dev,
+ struct i2c_msg *msg, int nmsgs)
+{
+ struct npcm_i2c_bus *bus = dev_get_priv(dev);
+ struct npcm_i2c_regs *reg = bus->reg;
+ int ret = 0, err = 0;
+
+ if (nmsgs < 1 || nmsgs > 2) {
+ printf("%s: commands not support\n", __func__);
+ return -EREMOTEIO;
+ }
+ /* clear ST register */
+ writeb(0xFF, ®->st);
+
+ for ( ; nmsgs > 0; nmsgs--, msg++) {
+ if (msg->flags & I2C_M_RD)
+ err = npcm_i2c_read(bus, msg->addr, msg->buf,
+ msg->len);
+ else
+ err = npcm_i2c_write(bus, msg->addr, msg->buf,
+ msg->len);
+ if (err) {
+ debug("i2c_xfer: error %d\n", err);
+ ret = -EREMOTEIO;
+ break;
+ }
+ }
+
+ if (bus->started)
+ npcm_i2c_send_stop(bus, true);
+
+ if (err)
+ npcm_i2c_recovery(bus, msg->addr);
+
+ return ret;
+}
+
+static int npcm_i2c_init_clk(struct npcm_i2c_bus *bus, u32 bus_freq)
+{
+ struct npcm_i2c_regs *reg = bus->reg;
+ u32 freq = bus->apb_clk;
+ u32 sclfrq;
+ u8 hldt, val;
+
+ if (bus_freq > I2C_FREQ_100K) {
+ printf("Support standard mode only\n");
+ return -EINVAL;
+ }
+
+ /* SCLFRQ = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) */
+ sclfrq = freq / (bus_freq * 4);
+ if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX)
+ return -EINVAL;
+
+ if (freq >= 40000000)
+ hldt = 17;
+ else if (freq >= 12500000)
+ hldt = 15;
+ else
+ hldt = 7;
+
+ val = readb(®->ctl2) & 0x1;
+ val |= (sclfrq & 0x7F) << 1;
+ writeb(val, ®->ctl2);
+
+ /* clear 400K_MODE bit */
+ val = readb(®->ctl3) & 0xc;
+ val |= (sclfrq >> 7) & 0x3;
+ writeb(val, ®->ctl3);
+
+ writeb(hldt, ®->bank0.ctl4);
+
+ return 0;
+}
+
+static int npcm_i2c_set_bus_speed(struct udevice *dev,
+ unsigned int speed)
+{
+ struct npcm_i2c_bus *bus = dev_get_priv(dev);
+
+ return npcm_i2c_init_clk(bus, speed);
+}
+
+static int npcm_i2c_probe(struct udevice *dev)
+{
+ struct npcm_i2c_bus *bus = dev_get_priv(dev);
+ struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA;
+ struct npcm_i2c_regs *reg;
+ u32 i2csegctl_val = dev_get_driver_data(dev);
+ struct clk clk;
+ int ret;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret) {
+ printf("%s: ret %d\n", __func__, ret);
+ return ret;
+ }
+ bus->apb_clk = clk_get_rate(&clk);
+ if (bus->apb_clk <= 0) {
+ printf("%s: fail to get rate\n", __func__);
+ return -EINVAL;
+ }
+ clk_free(&clk);
+
+ bus->num = dev->seq_;
+ bus->reg = dev_read_addr_ptr(dev);
+ bus->freq = dev_read_u32_default(dev, "clock-frequency", 100000);
+ bus->started = false;
+ reg = bus->reg;
+
+ if (npcm_i2c_init_clk(bus, bus->freq)) {
+ printf("%s: init_clk failed\n", __func__);
+ return -EINVAL;
+ }
+
+ /* set initial i2csegctl value */
+ writel(i2csegctl_val, &gcr->i2csegctl);
+
+ /* enable SMB module */
+ setbits_8(®->ctl2, SMBCTL2_ENABLE);
+
+ /* select register bank 0 */
+ clrbits_8(®->ctl3, SMBCTL3_BNK_SEL);
+
+ /* single byte mode */
+ clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN);
+
+ /* set POLL mode */
+ writeb(0, ®->ctl1);
+
+ printf("I2C bus %d ready. speed=%d, base=0x%x, apb=%u\n",
+ bus->num, bus->freq, (u32)(uintptr_t)bus->reg, bus->apb_clk);
+
+ return 0;
+}
+
+static const struct dm_i2c_ops nuvoton_i2c_ops = {
+ .xfer = npcm_i2c_xfer,
+ .set_bus_speed = npcm_i2c_set_bus_speed,
+};
+
+static const struct udevice_id nuvoton_i2c_of_match[] = {
+ { .compatible = "nuvoton,npcm845-i2c", .data = NPCM8XX_I2CSEGCTL_INIT_VAL},
+ { .compatible = "nuvoton,npcm750-i2c", .data = NPCM7XX_I2CSEGCTL_INIT_VAL},
+ {}
+};
+
+U_BOOT_DRIVER(npcm_i2c_bus) = {
+ .name = "npcm-i2c",
+ .id = UCLASS_I2C,
+ .of_match = nuvoton_i2c_of_match,
+ .probe = npcm_i2c_probe,
+ .priv_auto = sizeof(struct npcm_i2c_bus),
+ .ops = &nuvoton_i2c_ops,
+};
*
* Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com
* 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*
* 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
config SPL_DM_MMC
bool "Enable MMC controllers using Driver Model in SPL"
depends on SPL_DM && DM_MMC
+ default n if ARCH_MVEBU && !MVEBU_SPL_BOOT_DEVICE_MMC
default y
help
This enables the MultiMediaCard (MMC) uclass which supports MMC and
val = readl(SUNXI_NFC_BASE + NFC_CTL);
val &= ~NFC_CTL_PAGE_SIZE_MASK;
- writel(val | NFC_CTL_RAM_METHOD | NFC_CTL_PAGE_SIZE(conf->page_size),
+ writel(val | NFC_CTL_PAGE_SIZE(conf->page_size),
SUNXI_NFC_BASE + NFC_CTL);
writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA);
can support a type of operation in a much more refined way compared
to using flags like SPI_RX_DUAL, SPI_TX_QUAD, etc.
+config SPI_NOR_BOOT_SOFT_RESET_EXT_INVERT
+ bool "Command extension type is INVERT for Software Reset on boot"
+ default n
+ help
+ Because of SFDP information can not be get before boot.
+ So define command extension type is INVERT when Software Reset on boot only.
+
config SPI_FLASH_SOFT_RESET
bool "Software Reset support for SPI NOR flashes"
help
#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */
#define SFDP_SST_ID 0x01bf /* Manufacturer specific Table */
#define SFDP_PROFILE1_ID 0xff05 /* xSPI Profile 1.0 Table */
+#define SFDP_SCCR_MAP_ID 0xff87 /*
+ * Status, Control and Configuration
+ * Register Map.
+ */
#define SFDP_SIGNATURE 0x50444653U
#define SFDP_JESD216_MAJOR 1
#define PROFILE1_DWORD5_DUMMY_100MHZ GENMASK(11, 7)
#define PROFILE1_DUMMY_DEFAULT 20
+/* Status, Control and Configuration Register Map(SCCR) */
+#define SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE BIT(31)
+
struct sfdp_bfpt {
u32 dwords[BFPT_DWORD_MAX];
};
}
/*
- * Check if a region of the flash is (completely) locked. See stm_lock() for
+ * Check if a region of the flash is (completely) unlocked. See stm_lock() for
* more info.
*
- * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
+ * Returns 1 if entire region is unlocked, 0 if any portion is locked, and
* negative on errors.
*/
-static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
+static int stm_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
int status;
if (status < 0)
return status;
- return stm_is_locked_sr(nor, ofs, len, status);
+ return stm_is_unlocked_sr(nor, ofs, len, status);
}
#endif /* CONFIG_SPI_FLASH_STMICRO */
}
/*
- * Returns EACCES (positive value) if region is locked, 0 if region is unlocked,
- * and negative on errors.
+ * Returns EACCES (positive value) if region is (partially) locked, 0 if region
+ * is completely unlocked, and negative on errors.
*/
-static int sst26_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
+static int sst26_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
/*
- * is_locked function is used for check before reading or erasing flash
- * region, so offset and length might be not 64k allighned, so adjust
- * them to be 64k allighned as sst26_lock_ctl works only with 64k
- * allighned regions.
+ * is_unlocked function is used for check before reading or erasing
+ * flash region, so offset and length might be not 64k aligned, so
+ * adjust them to be 64k aligned as sst26_lock_ctl works only with 64k
+ * aligned regions.
*/
ofs -= ofs & (SZ_64K - 1);
len = len & (SZ_64K - 1) ? (len & ~(SZ_64K - 1)) + SZ_64K : len;
}
/**
+ * spi_nor_parse_sccr() - Parse the Status, Control and Configuration Register
+ * Map.
+ * @nor: pointer to a 'struct spi_nor'
+ * @sccr_header: pointer to the 'struct sfdp_parameter_header' describing
+ * the SCCR Map table length and version.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_sccr(struct spi_nor *nor,
+ const struct sfdp_parameter_header *sccr_header)
+{
+ u32 *table, addr;
+ size_t len;
+ int ret, i;
+
+ len = sccr_header->length * sizeof(*table);
+ table = kmalloc(len, GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ addr = SFDP_PARAM_HEADER_PTP(sccr_header);
+ ret = spi_nor_read_sfdp(nor, addr, len, table);
+ if (ret)
+ goto out;
+
+ /* Fix endianness of the table DWORDs. */
+ for (i = 0; i < sccr_header->length; i++)
+ table[i] = le32_to_cpu(table[i]);
+
+ if (FIELD_GET(SCCR_DWORD22_OCTAL_DTR_EN_VOLATILE, table[22]))
+ nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
+
+out:
+ kfree(table);
+ return ret;
+}
+
+/**
* spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
* @nor: pointer to a 'struct spi_nor'
* @params: pointer to the 'struct spi_nor_flash_parameter' to be
err = spi_nor_parse_profile1(nor, param_header, params);
break;
+ case SFDP_SCCR_MAP_ID:
+ err = spi_nor_parse_sccr(nor, param_header);
+ break;
+
default:
break;
}
};
#endif /* CONFIG_SPI_FLASH_MT35XU */
+#if CONFIG_IS_ENABLED(SPI_FLASH_MACRONIX)
+/**
+ * spi_nor_macronix_octal_dtr_enable() - Enable octal DTR on Macronix flashes.
+ * @nor: pointer to a 'struct spi_nor'
+ *
+ * Set Macronix max dummy cycles 20 to allow the flash to run at fastest frequency.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor)
+{
+ struct spi_mem_op op;
+ int ret;
+ u8 buf;
+
+ ret = write_enable(nor);
+ if (ret)
+ return ret;
+
+ buf = SPINOR_REG_MXIC_DC_20;
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
+ SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+
+ ret = spi_mem_exec_op(nor->spi, &op);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ return ret;
+
+ nor->read_dummy = MXIC_MAX_DC;
+ ret = write_enable(nor);
+ if (ret)
+ return ret;
+
+ buf = SPINOR_REG_MXIC_OPI_DTR_EN;
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
+ SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_MODE, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+
+ ret = spi_mem_exec_op(nor->spi, &op);
+ if (ret) {
+ dev_err(nor->dev, "Failed to enable octal DTR mode\n");
+ return ret;
+ }
+ nor->reg_proto = SNOR_PROTO_8_8_8_DTR;
+
+ return 0;
+}
+
+static void macronix_octal_default_init(struct spi_nor *nor)
+{
+ nor->octal_dtr_enable = spi_nor_macronix_octal_dtr_enable;
+}
+
+static void macronix_octal_post_sfdp_fixup(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
+{
+ /*
+ * Adding SNOR_HWCAPS_PP_8_8_8_DTR in hwcaps.mask when
+ * SPI_NOR_OCTAL_DTR_READ flag exists.
+ */
+ if (params->hwcaps.mask & SNOR_HWCAPS_READ_8_8_8_DTR)
+ params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+}
+
+static struct spi_nor_fixups macronix_octal_fixups = {
+ .default_init = macronix_octal_default_init,
+ .post_sfdp = macronix_octal_post_sfdp_fixup,
+};
+#endif /* CONFIG_SPI_FLASH_MACRONIX */
+
/** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed
* @nor: pointer to a 'struct spi_nor'
*
nor->write_proto == SNOR_PROTO_8_8_8_DTR))
return 0;
+ if (!(nor->flags & SNOR_F_IO_MODE_EN_VOLATILE))
+ return 0;
+
ret = nor->octal_dtr_enable(nor);
if (ret)
return ret;
enum spi_nor_cmd_ext ext;
ext = nor->cmd_ext_type;
- nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+ if (nor->cmd_ext_type == SPI_NOR_EXT_NONE) {
+ nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+#if CONFIG_IS_ENABLED(SPI_NOR_BOOT_SOFT_RESET_EXT_INVERT)
+ nor->cmd_ext_type = SPI_NOR_EXT_INVERT;
+#endif /* SPI_NOR_BOOT_SOFT_RESET_EXT_INVERT */
+ }
op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),
SPI_MEM_OP_NO_DUMMY,
if (!strcmp(nor->info->name, "mt35xu512aba"))
nor->fixups = &mt35xu512aba_fixups;
#endif
+
+#if CONFIG_IS_ENABLED(SPI_FLASH_MACRONIX)
+ nor->fixups = ¯onix_octal_fixups;
+#endif /* SPI_FLASH_MACRONIX */
}
int spi_nor_scan(struct spi_nor *nor)
info->flags & SPI_NOR_HAS_LOCK) {
nor->flash_lock = stm_lock;
nor->flash_unlock = stm_unlock;
- nor->flash_is_locked = stm_is_locked;
+ nor->flash_is_unlocked = stm_is_unlocked;
}
#endif
if (info->flags & SPI_NOR_HAS_SST26LOCK) {
nor->flash_lock = sst26_lock;
nor->flash_unlock = sst26_unlock;
- nor->flash_is_locked = sst26_is_locked;
+ nor->flash_is_unlocked = sst26_is_unlocked;
}
#endif
{ INFO("mx66l2g45g", 0xc2201c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) },
{ INFO("mx25r6435f", 0xc22817, 0, 64 * 1024, 128, SECT_4K) },
- { INFO("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx66uw2g345gx0", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx66lm1g45g", 0xc2853b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25lm51245g", 0xc2853a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25lw51245g", 0xc2863a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25lm25645g", 0xc28539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx66uw2g345g", 0xc2843c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx66um1g45g", 0xc2803b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx66uw1g45g", 0xc2813b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw51245g", 0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw51345g", 0xc2843a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25um25645g", 0xc28039, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw25645g", 0xc28139, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25um25345g", 0xc28339, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw25345g", 0xc28439, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw12845g", 0xc28138, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw12345g", 0xc28438, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw6445g", 0xc28137, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("mx25uw6345g", 0xc28437, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
#endif
#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{
+ INFO("w25q512nwq", 0xef6020, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
+ {
+ INFO("w25q512nwm", 0xef8020, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
+ {
INFO("w25q01jv", 0xef4021, 0, 64 * 1024, 2048,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
} \
} while (0)
#else
-#define ubi_assert(expr) do { \
- if (unlikely(!(expr))) { \
- pr_debug("UBI assert failed in %s at %u\n", \
- __func__, __LINE__); \
- dump_stack(); \
- } \
-} while (0)
+#include <log.h>
+#define ubi_assert(expr) assert(expr)
#endif
#define ubi_dbg_print_hex_dump(ps, pt, r, g, b, len, a) \
#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/io.h>
-#include <asm/arch/clock.h>
#include <common.h>
#include <clk.h>
#include <dm.h>
priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
pdata->phy_interface = dev_read_phy_mode(dev);
- printf("phy interface%d\n", pdata->phy_interface);
+ debug("phy interface %d\n", pdata->phy_interface);
if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
return -EINVAL;
This driver controls the entire USB PHY block, both the USB OTG
parts, as well as the 2 regular USB 2 host PHYs.
+config INITIAL_USB_SCAN_DELAY
+ int "Delay initial USB scan by x ms to allow builtin devices to init"
+ depends on PHY_SUN4I_USB
+ default 0
+ help
+ Some boards have on board usb devices which need longer than
+ the USB spec's 1 second to connect from board powerup. Set
+ this option to a nonzero value to add an extra delay before
+ the first USB bus scan.
+
config PHY_SUN50I_USB3
bool "Allwinner sun50i USB3 PHY driver"
depends on ARCH_SUNXI
#include <reset.h>
#include <asm/gpio.h>
#include <asm/io.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/cpu.h>
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#define REG_PHYTUNE 0x0c
#define REG_PHYCTL_A33 0x10
#define REG_PHY_OTGCTL 0x20
-#define REG_PMU_UNK1 0x10
+
+#define REG_HCI_PHY_CTL 0x10
/* Common Control Bits for Both PHYs */
#define PHY_PLL_BW 0x03
/* A83T specific control bits for PHY0 */
#define PHY_CTL_VBUSVLDEXT BIT(5)
#define PHY_CTL_SIDDQ BIT(3)
+#define PHY_CTL_H3_SIDDQ BIT(1)
/* A83T specific control bits for PHY2 HSIC */
#define SUNXI_EHCI_HS_FORCE BIT(20)
int num_phys;
enum sun4i_usb_phy_type type;
u32 disc_thresh;
+ u32 hci_phy_ctl_clear;
u8 phyctl_offset;
bool dedicated_clocks;
- bool enable_pmu_unk1;
bool phy0_dual_route;
int missing_phys;
};
return ret;
}
+ if (usb_phy->pmu && data->cfg->hci_phy_ctl_clear) {
+ val = readl(usb_phy->pmu + REG_HCI_PHY_CTL);
+ val &= ~data->cfg->hci_phy_ctl_clear;
+ writel(val, usb_phy->pmu + REG_HCI_PHY_CTL);
+ }
+
if (data->cfg->type == sun8i_a83t_phy ||
data->cfg->type == sun50i_h6_phy) {
if (phy->id == 0) {
writel(val, data->base + data->cfg->phyctl_offset);
}
} else {
- if (usb_phy->pmu && data->cfg->enable_pmu_unk1) {
- val = readl(usb_phy->pmu + REG_PMU_UNK1);
- writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1);
- }
-
if (usb_phy->id == 0)
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN,
PHY_RES45_CAL_DATA,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
- .enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
.disc_thresh = 2,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
- .enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
- .enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
.disc_thresh = 2,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
- .enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
- .enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = false,
};
static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
+ .phy0_dual_route = true,
+};
+
+static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = {
+ .num_phys = 2,
+ .type = sun50i_h6_phy,
+ .phyctl_offset = REG_PHYCTL_A33,
+ .dedicated_clocks = true,
+ .hci_phy_ctl_clear = PHY_CTL_SIDDQ,
.phy0_dual_route = true,
};
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
.phy0_dual_route = true,
.missing_phys = BIT(1) | BIT(2),
};
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg },
{ .compatible = "allwinner,sun8i-r40-usb-phy", .data = (ulong)&sun8i_r40_cfg },
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg },
+ { .compatible = "allwinner,sun20i-d1-usb-phy", .data = (ulong)&sun20i_d1_cfg },
{ .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg},
{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = (ulong)&sun50i_h6_cfg},
{ }
#include <reset-uclass.h>
#include <asm/io.h>
#include <clk/sunxi.h>
-#include <dm/device-internal.h>
-#include <dm/lists.h>
#include <linux/bitops.h>
#include <linux/log2.h>
-struct sunxi_reset_priv {
- void *base;
- ulong count;
- const struct ccu_desc *desc;
-};
-
-static const struct ccu_reset *priv_to_reset(struct sunxi_reset_priv *priv,
+static const struct ccu_reset *plat_to_reset(struct ccu_plat *plat,
unsigned long id)
{
- return &priv->desc->resets[id];
+ return &plat->desc->resets[id];
}
static int sunxi_reset_request(struct reset_ctl *reset_ctl)
{
- struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ struct ccu_plat *plat = dev_get_plat(reset_ctl->dev);
debug("%s: (RST#%ld)\n", __func__, reset_ctl->id);
- if (reset_ctl->id >= priv->count)
+ if (reset_ctl->id >= plat->desc->num_resets)
return -EINVAL;
return 0;
static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on)
{
- struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev);
- const struct ccu_reset *reset = priv_to_reset(priv, reset_ctl->id);
+ struct ccu_plat *plat = dev_get_plat(reset_ctl->dev);
+ const struct ccu_reset *reset = plat_to_reset(plat, reset_ctl->id);
u32 reg;
if (!(reset->flags & CCU_RST_F_IS_VALID)) {
debug("%s: (RST#%ld) off#0x%x, BIT(%d)\n", __func__,
reset_ctl->id, reset->off, ilog2(reset->bit));
- reg = readl(priv->base + reset->off);
+ reg = readl(plat->base + reset->off);
if (on)
reg |= reset->bit;
else
reg &= ~reset->bit;
- writel(reg, priv->base + reset->off);
+ writel(reg, plat->base + reset->off);
return 0;
}
.rst_deassert = sunxi_reset_deassert,
};
-static int sunxi_reset_probe(struct udevice *dev)
-{
- struct sunxi_reset_priv *priv = dev_get_priv(dev);
-
- priv->base = dev_read_addr_ptr(dev);
-
- return 0;
-}
-
-int sunxi_reset_bind(struct udevice *dev, ulong count)
-{
- struct udevice *rst_dev;
- struct sunxi_reset_priv *priv;
- int ret;
-
- ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset",
- dev_ofnode(dev), &rst_dev);
- if (ret) {
- debug("failed to bind sunxi_reset driver (ret=%d)\n", ret);
- return ret;
- }
- priv = malloc(sizeof(struct sunxi_reset_priv));
- priv->count = count;
- priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
- dev_set_priv(rst_dev, priv);
-
- return 0;
-}
-
U_BOOT_DRIVER(sunxi_reset) = {
.name = "sunxi_reset",
.id = UCLASS_RESET,
.ops = &sunxi_reset_ops,
- .probe = sunxi_reset_probe,
- .priv_auto = sizeof(struct sunxi_reset_priv),
};
/*
* RTC driver for the Armada 38x Marvell SoCs
*
- * Copyright (C) 2021 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2021 Marek Behún <kabel@kernel.org>
*
* Based on Linux' driver by Gregory Clement and Marvell
*/
#define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE)
#define SUN4I_FIFO_STA_RF_CNT_BITS 0
-#define SUN4I_SPI_MAX_RATE 24000000
+#ifdef CONFIG_MACH_SUNIV
+/* the AHB clock, which we programmed to be 1/3 of PLL_PERIPH@600MHz */
+#define SUNXI_INPUT_CLOCK 200000000 /* 200 MHz */
+#define SUN4I_SPI_MAX_RATE (SUNXI_INPUT_CLOCK / 2)
+#else
+/* the SPI mod clock, defaulting to be 1/1 of the HOSC@24MHz */
+#define SUNXI_INPUT_CLOCK 24000000 /* 24 MHz */
+#define SUN4I_SPI_MAX_RATE SUNXI_INPUT_CLOCK
+#endif
#define SUN4I_SPI_MIN_RATE 3000
#define SUN4I_SPI_DEFAULT_RATE 1000000
-#define SUN4I_SPI_TIMEOUT_US 1000000
+#define SUN4I_SPI_TIMEOUT_MS 1000
#define SPI_REG(priv, reg) ((priv)->base + \
(priv)->variant->regs[reg])
return ret;
}
+static void sun4i_spi_set_speed_mode(struct udevice *dev)
+{
+ struct sun4i_spi_priv *priv = dev_get_priv(dev);
+ unsigned int div;
+ u32 reg;
+
+ /*
+ * Setup clock divider.
+ *
+ * We have two choices there. Either we can use the clock
+ * divide rate 1, which is calculated thanks to this formula:
+ * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
+ * Or we can use CDR2, which is calculated with the formula:
+ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+ * Whether we use the former or the latter is set through the
+ * DRS bit.
+ *
+ * First try CDR2, and if we can't reach the expected
+ * frequency, fall back to CDR1.
+ */
+
+ div = DIV_ROUND_UP(SUNXI_INPUT_CLOCK, priv->freq);
+ reg = readl(SPI_REG(priv, SPI_CCR));
+
+ if ((div / 2) <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
+ div /= 2;
+ if (div > 0)
+ div--;
+
+ reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
+ reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
+ } else {
+ div = fls(div - 1);
+ /* The F1C100s encodes the divider as 2^(n+1) */
+ if (IS_ENABLED(CONFIG_MACH_SUNIV))
+ div--;
+ reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
+ reg |= SUN4I_CLK_CTL_CDR1(div);
+ }
+
+ writel(reg, SPI_REG(priv, SPI_CCR));
+
+ reg = readl(SPI_REG(priv, SPI_TCR));
+ reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA));
+
+ if (priv->mode & SPI_CPOL)
+ reg |= SPI_BIT(priv, SPI_TCR_CPOL);
+
+ if (priv->mode & SPI_CPHA)
+ reg |= SPI_BIT(priv, SPI_TCR_CPHA);
+
+ writel(reg, SPI_REG(priv, SPI_TCR));
+}
+
static int sun4i_spi_claim_bus(struct udevice *dev)
{
struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
+ sun4i_spi_set_speed_mode(dev->parent);
+
return 0;
}
struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
u32 len = bitlen / 8;
- u32 rx_fifocnt;
u8 nbytes;
int ret;
setbits_le32(SPI_REG(priv, SPI_TCR),
SPI_BIT(priv, SPI_TCR_XCH));
- /* Wait till RX FIFO to be empty */
- ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR),
- rx_fifocnt,
- (((rx_fifocnt &
- SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >>
- SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes),
- SUN4I_SPI_TIMEOUT_US);
+ /* Wait for the transfer to be done */
+ ret = wait_for_bit_le32((const void *)SPI_REG(priv, SPI_TCR),
+ SPI_BIT(priv, SPI_TCR_XCH),
+ false, SUN4I_SPI_TIMEOUT_MS, false);
if (ret < 0) {
printf("ERROR: sun4i_spi: Timeout transferring data\n");
sun4i_spi_set_cs(bus, slave_plat->cs, false);
{
struct sun4i_spi_plat *plat = dev_get_plat(dev);
struct sun4i_spi_priv *priv = dev_get_priv(dev);
- unsigned int div;
- u32 reg;
if (speed > plat->max_hz)
speed = plat->max_hz;
if (speed < SUN4I_SPI_MIN_RATE)
speed = SUN4I_SPI_MIN_RATE;
- /*
- * Setup clock divider.
- *
- * We have two choices there. Either we can use the clock
- * divide rate 1, which is calculated thanks to this formula:
- * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
- * Or we can use CDR2, which is calculated with the formula:
- * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
- * Whether we use the former or the latter is set through the
- * DRS bit.
- *
- * First try CDR2, and if we can't reach the expected
- * frequency, fall back to CDR1.
- */
-
- div = SUN4I_SPI_MAX_RATE / (2 * speed);
- reg = readl(SPI_REG(priv, SPI_CCR));
-
- if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
- if (div > 0)
- div--;
-
- reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
- reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
- } else {
- div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed);
- reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
- reg |= SUN4I_CLK_CTL_CDR1(div);
- }
priv->freq = speed;
- writel(reg, SPI_REG(priv, SPI_CCR));
return 0;
}
static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
{
struct sun4i_spi_priv *priv = dev_get_priv(dev);
- u32 reg;
-
- reg = readl(SPI_REG(priv, SPI_TCR));
- reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA));
-
- if (mode & SPI_CPOL)
- reg |= SPI_BIT(priv, SPI_TCR_CPOL);
-
- if (mode & SPI_CPHA)
- reg |= SPI_BIT(priv, SPI_TCR_CPHA);
priv->mode = mode;
- writel(reg, SPI_REG(priv, SPI_TCR));
return 0;
}
config SPL_DM_USB
bool "Enable driver model for USB host most in SPL"
depends on SPL_DM && DM_USB
+ default n if ARCH_MVEBU
default y
config DM_USB_GADGET
Select this for Xilinx ZynqMP and similar Platforms.
This wrapper supports Host and Peripheral operation modes.
+config SPL_USB_DWC3_GENERIC
+ bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue) for the SPL"
+ depends on SPL_DM_USB && USB_DWC3 && SPL_MISC
+ help
+ Select this for Xilinx ZynqMP and similar Platforms.
+ This wrapper supports Host and Peripheral operation modes.
+
config USB_DWC3_MESON_G12A
bool "Amlogic Meson G12A USB wrapper"
depends on DM_USB && USB_DWC3 && ARCH_MESON
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o
obj-$(CONFIG_USB_DWC3_MESON_GXL) += dwc3-meson-gxl.o
-obj-$(CONFIG_USB_DWC3_GENERIC) += dwc3-generic.o
+obj-$(CONFIG_$(SPL_)USB_DWC3_GENERIC) += dwc3-generic.o
obj-$(CONFIG_USB_DWC3_UNIPHIER) += dwc3-uniphier.o
obj-$(CONFIG_USB_DWC3_LAYERSCAPE) += dwc3-layerscape.o
obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o
musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
if (is_host_enabled(musb)) {
- ret = sun4i_usb_phy_vbus_detect(&glue->phy);
- if (ret == 1) {
- printf("A charger is plugged into the OTG: ");
- return -ENODEV;
- }
-
ret = sun4i_usb_phy_id_detect(&glue->phy);
if (ret == 1) {
printf("No host cable detected: ");
help
Select this to enable max6370 watchdog timer.
+config WDT_MESON_GXBB
+ bool "Amlogic watchdog timer support"
+ depends on WDT
+ help
+ Select this to enable Meson watchdog timer,
+ which can be found on some Amlogic platforms.
+
config WDT_MPC8xx
bool "MPC8xx watchdog timer support"
depends on WDT && MPC8xx
It performs full SoC reset.
config WDT_OCTEONTX
- bool "OcteonTX core watchdog support"
- depends on WDT && (ARCH_OCTEONTX || ARCH_OCTEONTX2)
+ bool "Octeon core watchdog support"
+ depends on WDT && (ARCH_OCTEON || ARCH_OCTEONTX || ARCH_OCTEONTX2)
default y
imply WATCHDOG
help
- This enables OcteonTX watchdog driver, which can be
- found on OcteonTX/TX2 chipsets and inline with driver model.
- Only supports watchdog reset.
+ This enables the Octeon watchdog driver, which can be found on
+ various Octeon parts such as Octeon II/III and OcteonTX/TX2.
config WDT_OMAP3
bool "TI OMAP watchdog timer support"
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
+obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o
obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
/*
* Marvell Armada 37xx SoC Watchdog Driver
*
- * Marek Behun <marek.behun@nic.cz>
+ * Marek Behún <kabel@kernel.org>
*/
#include <common.h>
#include <dm/device_compat.h>
#include <wdt.h>
#include <asm/gpio.h>
+#include <linux/delay.h>
+
+enum {
+ HW_ALGO_TOGGLE,
+ HW_ALGO_LEVEL,
+};
struct gpio_wdt_priv {
- struct gpio_desc gpio;
- bool always_running;
- int state;
+ struct gpio_desc gpio;
+ unsigned int hw_algo;
+ bool always_running;
+ int state;
};
static int gpio_wdt_reset(struct udevice *dev)
{
struct gpio_wdt_priv *priv = dev_get_priv(dev);
- priv->state = !priv->state;
-
- return dm_gpio_set_value(&priv->gpio, priv->state);
+ switch (priv->hw_algo) {
+ case HW_ALGO_TOGGLE:
+ /* Toggle output pin */
+ priv->state = !priv->state;
+ dm_gpio_set_value(&priv->gpio, priv->state);
+ break;
+ case HW_ALGO_LEVEL:
+ /* Pulse */
+ dm_gpio_set_value(&priv->gpio, 1);
+ udelay(1);
+ dm_gpio_set_value(&priv->gpio, 0);
+ break;
+ }
+ return 0;
}
static int gpio_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
{
struct gpio_wdt_priv *priv = dev_get_priv(dev);
int ret;
+ const char *algo = dev_read_string(dev, "hw_algo");
+
+ if (!algo)
+ return -EINVAL;
+ if (!strcmp(algo, "toggle"))
+ priv->hw_algo = HW_ALGO_TOGGLE;
+ else if (!strcmp(algo, "level"))
+ priv->hw_algo = HW_ALGO_LEVEL;
+ else
+ return -EINVAL;
priv->always_running = dev_read_bool(dev, "always-running");
ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 BayLibre, SAS.
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <reset.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+#define GXBB_WDT_CTRL_REG 0x0
+#define GXBB_WDT_TCNT_REG 0x8
+#define GXBB_WDT_RSET_REG 0xc
+
+#define GXBB_WDT_CTRL_SYS_RESET_NOW BIT(26)
+#define GXBB_WDT_CTRL_CLKDIV_EN BIT(25)
+#define GXBB_WDT_CTRL_CLK_EN BIT(24)
+#define GXBB_WDT_CTRL_EE_RESET BIT(21)
+#define GXBB_WDT_CTRL_EN BIT(18)
+
+#define GXBB_WDT_CTRL_DIV_MASK GENMASK(17, 0)
+#define GXBB_WDT_TCNT_SETUP_MASK GENMASK(15, 0)
+
+
+struct amlogic_wdt_priv {
+ void __iomem *reg_base;
+};
+
+static int amlogic_wdt_set_timeout(struct udevice *dev, u64 timeout_ms)
+{
+ struct amlogic_wdt_priv *data = dev_get_priv(dev);
+
+ if (timeout_ms > GXBB_WDT_TCNT_SETUP_MASK) {
+ dev_warn(dev, "%s: timeout_ms=%llu: maximum watchdog timeout exceeded\n",
+ __func__, timeout_ms);
+ timeout_ms = GXBB_WDT_TCNT_SETUP_MASK;
+ }
+
+ writel(timeout_ms, data->reg_base + GXBB_WDT_TCNT_REG);
+
+ return 0;
+}
+
+static int amlogic_wdt_stop(struct udevice *dev)
+{
+ struct amlogic_wdt_priv *data = dev_get_priv(dev);
+
+ writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
+ data->reg_base + GXBB_WDT_CTRL_REG);
+
+ return 0;
+}
+
+static int amlogic_wdt_start(struct udevice *dev, u64 time_ms, ulong flags)
+{
+ struct amlogic_wdt_priv *data = dev_get_priv(dev);
+
+ writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
+ data->reg_base + GXBB_WDT_CTRL_REG);
+
+ return amlogic_wdt_set_timeout(dev, time_ms);
+}
+
+static int amlogic_wdt_reset(struct udevice *dev)
+{
+ struct amlogic_wdt_priv *data = dev_get_priv(dev);
+
+ writel(0, data->reg_base + GXBB_WDT_RSET_REG);
+
+ return 0;
+}
+
+static int amlogic_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ struct amlogic_wdt_priv *data = dev_get_priv(dev);
+
+ writel(0, data->reg_base + GXBB_WDT_CTRL_SYS_RESET_NOW);
+
+ return 0;
+}
+
+static int amlogic_wdt_probe(struct udevice *dev)
+{
+ struct amlogic_wdt_priv *data = dev_get_priv(dev);
+ int ret;
+
+ data->reg_base = dev_remap_addr(dev);
+ if (!data->reg_base)
+ return -EINVAL;
+
+ struct clk clk;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(&clk);
+ if (ret) {
+ clk_free(&clk);
+ return ret;
+ }
+
+ /* Setup with 1ms timebase */
+ writel(((clk_get_rate(&clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
+ GXBB_WDT_CTRL_EE_RESET |
+ GXBB_WDT_CTRL_CLK_EN |
+ GXBB_WDT_CTRL_CLKDIV_EN,
+ data->reg_base + GXBB_WDT_CTRL_REG);
+
+ return 0;
+}
+
+static const struct wdt_ops amlogic_wdt_ops = {
+ .start = amlogic_wdt_start,
+ .reset = amlogic_wdt_reset,
+ .stop = amlogic_wdt_stop,
+ .expire_now = amlogic_wdt_expire_now,
+};
+
+static const struct udevice_id amlogic_wdt_ids[] = {
+ { .compatible = "amlogic,meson-gxbb-wdt" },
+ {}
+};
+
+U_BOOT_DRIVER(amlogic_wdt) = {
+ .name = "amlogic_wdt",
+ .id = UCLASS_WDT,
+ .of_match = amlogic_wdt_ids,
+ .priv_auto = sizeof(struct amlogic_wdt_priv),
+ .probe = amlogic_wdt_probe,
+ .ops = &amlogic_wdt_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
DECLARE_GLOBAL_DATA_PTR;
-#define CORE0_WDOG_OFFSET 0x40000
-#define CORE0_POKE_OFFSET 0x50000
#define CORE0_POKE_OFFSET_MASK 0xfffffULL
#define WDOG_MODE GENMASK_ULL(1, 0)
#define WDOG_LEN GENMASK_ULL(19, 4)
#define WDOG_CNT GENMASK_ULL(43, 20)
+struct octeontx_wdt_data {
+ u32 wdog_offset;
+ u32 poke_offset;
+ int timer_shift;
+ bool has_clk;
+};
+
struct octeontx_wdt {
void __iomem *reg;
+ const struct octeontx_wdt_data *data;
struct clk clk;
};
u64 clk_rate, val;
u64 tout_wdog;
- clk_rate = clk_get_rate(&priv->clk);
- if (IS_ERR_VALUE(clk_rate))
- return -EINVAL;
+ if (priv->data->has_clk) {
+ clk_rate = clk_get_rate(&priv->clk);
+ if (IS_ERR_VALUE(clk_rate))
+ return -EINVAL;
+ } else {
+ clk_rate = gd->bus_clk;
+ }
- /* Watchdog counts in 1024 cycle steps */
- tout_wdog = (clk_rate * timeout_ms / 1000) >> 10;
+ /* Watchdog counts in configured cycle steps */
+ tout_wdog = (clk_rate * timeout_ms / 1000) >> priv->data->timer_shift;
/*
* We can only specify the upper 16 bits of a 24 bit value.
val = FIELD_PREP(WDOG_MODE, 0x3) |
FIELD_PREP(WDOG_LEN, tout_wdog) |
FIELD_PREP(WDOG_CNT, tout_wdog << 8);
- writeq(val, priv->reg + CORE0_WDOG_OFFSET);
+ writeq(val, priv->reg + priv->data->wdog_offset);
return 0;
}
{
struct octeontx_wdt *priv = dev_get_priv(dev);
- writeq(0, priv->reg + CORE0_WDOG_OFFSET);
+ writeq(0, priv->reg + priv->data->wdog_offset);
return 0;
}
{
struct octeontx_wdt *priv = dev_get_priv(dev);
- writeq(~0ULL, priv->reg + CORE0_POKE_OFFSET);
+ writeq(~0ULL, priv->reg + priv->data->poke_offset);
return 0;
}
if (!priv->reg)
return -EINVAL;
+ priv->data = (void *)dev_get_driver_data(dev);
+ if (!priv->data)
+ return -EINVAL;
+
/*
* Save base register address in reg masking lower 20 bits
* as 0xa0000 appears when extracted from the DT
priv->reg = (void __iomem *)(((u64)priv->reg &
~CORE0_POKE_OFFSET_MASK));
- ret = clk_get_by_index(dev, 0, &priv->clk);
- if (ret < 0)
- return ret;
+ if (priv->data->has_clk) {
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret < 0)
+ return ret;
- ret = clk_enable(&priv->clk);
- if (ret)
- return ret;
+ ret = clk_enable(&priv->clk);
+ if (ret)
+ return ret;
+ }
return 0;
}
.expire_now = octeontx_wdt_expire_now,
};
+static const struct octeontx_wdt_data octeontx_data = {
+ .wdog_offset = 0x40000,
+ .poke_offset = 0x50000,
+ .timer_shift = 10,
+ .has_clk = true,
+};
+
+static const struct octeontx_wdt_data octeon_data = {
+ .wdog_offset = 0x20000,
+ .poke_offset = 0x30000,
+ .timer_shift = 10,
+ .has_clk = false,
+};
+
static const struct udevice_id octeontx_wdt_ids[] = {
- { .compatible = "arm,sbsa-gwdt" },
+ { .compatible = "arm,sbsa-gwdt", .data = (ulong)&octeontx_data },
+ { .compatible = "cavium,octeon-7890-ciu3", .data = (ulong)&octeon_data },
{}
};
.id = UCLASS_WDT,
.of_match = octeontx_wdt_ids,
.ops = &octeontx_wdt_ops,
- .priv_auto = sizeof(struct octeontx_wdt),
+ .priv_auto = sizeof(struct octeontx_wdt),
.probe = octeontx_wdt_probe,
.remove = octeontx_wdt_remove,
.flags = DM_FLAG_OS_PREPARE,
*
* Authors: Tomas Hlavacek <tmshlvck@gmail.com>
* Sylver Bruneau <sylver.bruneau@googlemail.com>
- * Marek Behun <marek.behun@nic.cz>
+ * Marek Behún <kabel@kernel.org>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
# SPDX-License-Identifier: GPL-2.0+
#
-# 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+# 2017 Marek Behún, CZ.NIC, kabel@kernel.org
obj-y := btrfs.o compression.o ctree.o dev.o dir-item.o \
extent-io.o inode.o subvolume.o crypto/hash.o disk-io.o \
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include <config.h>
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#ifndef __BTRFS_BTRFS_H__
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include "btrfs.h"
/*
* Functions to convert BTRFS structures from disk to CPU endianness and back.
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#ifndef __BTRFS_CONV_FUNCS_H__
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include <linux/kernel.h>
* From linux/fs/btrfs/ctree.h
* Copyright (C) 2007,2008 Oracle. All rights reserved.
*
- * Modified in 2017 by Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * Modified in 2017 by Marek Behún, CZ.NIC, kabel@kernel.org
*/
#ifndef __BTRFS_CTREE_H__
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include <common.h>
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include "btrfs.h"
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include <linux/kernel.h>
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include <linux/kernel.h>
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#include <malloc.h>
// SPDX-License-Identifier: GPL-2.0
/*
- * 2017 by Marek Behun <marek.behun@nic.cz>
+ * 2017 by Marek Behún <kabel@kernel.org>
*
* Derived from code in ext4/dev.c, which was based on reiserfs/dev.c
*/
dbg_snprintf_key(c, key, __tmp_key_buf, DBG_KEY_BUF_LEN)); \
} while (0)
#else
-#define ubifs_assert(expr) do { \
- if (unlikely(!(expr))) { \
- pr_debug("UBIFS assert failed in %s at %u\n", \
- __func__, __LINE__); \
- dump_stack(); \
- } \
-} while (0)
-#define ubifs_assert_cmt_locked(c) do { \
- if (unlikely(down_write_trylock(&(c)->commit_sem))) { \
- up_write(&(c)->commit_sem); \
- pr_debug("commit lock is not locked!\n"); \
- ubifs_assert(0); \
- } \
-} while (0)
+#include <log.h>
+#define ubifs_assert(expr) assert(expr)
+#define ubifs_assert_cmt_locked(c) do { } while (0)
#define ubifs_dbg_msg(type, fmt, ...) \
pr_debug("UBIFS DBG " type ": " fmt "\n", \
*
* Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com
* 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*
* 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
/*
* BTRFS filesystem implementation for U-Boot
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#ifndef __U_BOOT_BTRFS_H__
struct ccu_desc {
const struct ccu_clk_gate *gates;
const struct ccu_reset *resets;
+ u8 num_gates;
+ u8 num_resets;
};
/**
- * struct ccu_priv - sunxi clock control unit
+ * struct ccu_plat - sunxi clock control unit platform data
*
* @base: base address
* @desc: ccu descriptor
*/
-struct ccu_priv {
+struct ccu_plat {
void *base;
const struct ccu_desc *desc;
};
-/**
- * sunxi_clk_probe - common sunxi clock probe
- * @dev: clock device
- */
-int sunxi_clk_probe(struct udevice *dev);
-
extern struct clk_ops sunxi_clk_ops;
-/**
- * sunxi_reset_bind() - reset binding
- *
- * @dev: reset device
- * @count: reset count
- * Return: 0 success, or error value
- */
-int sunxi_reset_bind(struct udevice *dev, ulong count);
-
#endif /* _CLK_SUNXI_H */
*/
#define DEFAULT_ENV_IS_RW /* required for configuring default fdtfile= */
+#ifdef CONFIG_MMC
+#define BOOT_TARGET_DEVICES_MMC(func, i) func(MMC, mmc, i)
+#else
+#define BOOT_TARGET_DEVICES_MMC(func, i)
+#endif
+
+#ifdef CONFIG_USB_STORAGE
+#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
+#else
+#define BOOT_TARGET_DEVICES_USB(func)
+#endif
+
+#ifdef CONFIG_SCSI
+#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0)
+#else
+#define BOOT_TARGET_DEVICES_SCSI(func)
+#endif
+
+#ifdef CONFIG_NVME
+#define BOOT_TARGET_DEVICES_NVME(func) func(NVME, nvme, 0)
+#else
+#define BOOT_TARGET_DEVICES_NVME(func)
+#endif
+
+#if defined(CONFIG_CMD_DHCP) && defined(CONFIG_CMD_PXE)
+#define BOOT_TARGET_DEVICES_PXE(func) func(PXE, pxe, na)
+#else
+#define BOOT_TARGET_DEVICES_PXE(func)
+#endif
+
+#ifdef CONFIG_CMD_DHCP
+#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na)
+#else
+#define BOOT_TARGET_DEVICES_DHCP(func)
+#endif
+
#define BOOT_TARGET_DEVICES(func) \
- func(MMC, mmc, 1) \
- func(MMC, mmc, 0) \
- func(USB, usb, 0) \
- func(SCSI, scsi, 0) \
- func(PXE, pxe, na) \
- func(DHCP, dhcp, na)
+ BOOT_TARGET_DEVICES_MMC(func, 1) \
+ BOOT_TARGET_DEVICES_MMC(func, 0) \
+ BOOT_TARGET_DEVICES_USB(func) \
+ BOOT_TARGET_DEVICES_NVME(func) \
+ BOOT_TARGET_DEVICES_SCSI(func) \
+ BOOT_TARGET_DEVICES_PXE(func) \
+ BOOT_TARGET_DEVICES_DHCP(func)
#include <config_distro_bootcmd.h>
/*
* (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
*
- * Configuration settings for the Allwinner A10 (sun4i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A10 (sun4i) CPU
+ * based devices separately. Please do not add anything in here.
*/
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * A10 specific configuration
- */
-
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Configuration settings for the Allwinner A64 (sun50i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A64 (and later) sun50i
+ * CPU based devices separately. Please do not add anything in here.
*/
-
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * A64 specific configuration
- */
-
-#ifndef CONFIG_SUN50I_GEN_H6
-#define GICD_BASE 0x1c81000
-#define GICC_BASE 0x1c82000
-#else
-#define GICD_BASE 0x3021000
-#define GICC_BASE 0x3022000
-#endif
-
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
/*
* (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
*
- * Configuration settings for the Allwinner A13 (sun5i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A13 (sun5i) CPU
+ * based devices separately. Please do not add anything in here.
*/
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * High Level Configuration Options
- */
-
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
* (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
* (C) Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
*
- * Configuration settings for the Allwinner A31 (sun6i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A31 (sun6i) CPU
+ * based devices separately. Please do not add anything in here.
*/
-
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
* (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
* (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
*
- * Configuration settings for the Allwinner A20 (sun7i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A20 (sun7i) CPU
+ * based devices separately. Please do not add anything in here.
*/
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
/*
* (C) Copyright 2014 Chen-Yu Tsai <wens@csie.org>
*
- * Configuration settings for the Allwinner A23 (sun8i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A23 (and later) sun8i
+ * CPU based devices separately. Please do not add anything in here.
*/
-
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * A23 specific configuration
- */
-
-#include <asm/arch/cpu.h>
-
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
/*
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
*
- * Configuration settings for the Allwinner A80 (sun9i) CPU
+ * Placeholder wrapper to allow addressing Allwinner A80 (sun9i) CPU
+ * based devices separately. Please do not add anything in here.
*/
-
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * A80 specific configuration
- */
-
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Configuration settings for new Allwinner F-series (suniv) CPU
+ * Placeholder wrapper to allow addressing Allwinner F-series (suniv) CPU
+ * based devices separately. Please do not add anything in here.
*/
-
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
- * Include common sunxi configuration where most the settings are
- */
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2018 Marek Behún <kabel@kernel.org>
*
* Based on mvebu_armada-37xx.h by Stefan Roese <sr@denx.de>
*/
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2017 Marek Behún <kabel@kernel.org>
* Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
*/
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * 2017 by Marek Behun <marek.behun@nic.cz>
+ * 2017 by Marek Behún <kabel@kernel.org>
*
* Derived from code in ext4/dev.c, which was based on reiserfs/dev.c
*/
/* Used for Macronix and Winbond flashes. */
#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
+#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
+#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
+#define SPINOR_OP_RD_CR2 0x71 /* Read configuration register 2 */
+#define SPINOR_OP_WR_CR2 0x72 /* Write configuration register 2 */
+#define SPINOR_OP_MXIC_DTR_RD 0xee /* Fast Read opcode in DTR mode */
+#define SPINOR_REG_MXIC_CR2_MODE 0x00000000 /* For setting octal DTR mode */
+#define SPINOR_REG_MXIC_OPI_DTR_EN 0x2 /* Enable Octal DTR */
+#define SPINOR_REG_MXIC_CR2_DC 0x00000300 /* For setting dummy cycles */
+#define SPINOR_REG_MXIC_DC_20 0x0 /* Setting dummy cycles to 20 */
+#define MXIC_MAX_DC 20 /* Maximum value of dummy cycles */
/* Used for Spansion flashes only. */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
SNOR_F_USE_CLSR = BIT(5),
SNOR_F_BROKEN_RESET = BIT(6),
SNOR_F_SOFT_RESET = BIT(7),
+ SNOR_F_IO_MODE_EN_VOLATILE = BIT(8),
};
struct spi_nor;
* spi-nor will send the erase opcode via write_reg()
* @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR
* @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR
- * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
- * completely locked
+ * @flash_is_unlocked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
+ * completely unlocked
* @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode
* @octal_dtr_enable: [FLASH-SPECIFIC] enables SPI NOR octal DTR mode.
* @ready: [FLASH-SPECIFIC] check if the flash is ready
int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
- int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+ int (*flash_is_unlocked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
int (*quad_enable)(struct spi_nor *nor);
int (*octal_dtr_enable)(struct spi_nor *nor);
int (*ready)(struct spi_nor *nor);
/*
* Helper for work with variadic macros
*
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ * 2017 Marek Behún, CZ.NIC, kabel@kernel.org
*/
#ifndef __VARIADIC_MACRO_H__
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0+
-# Copyright (C) 2020 Marek Behún <marek.behun@nic.cz>
+# Copyright (C) 2020 Marek Behún <kabel@kernel.org>
# Generate __ADDRESSABLE(symbol) for every linker list entry symbol, so that LTO
# does not optimize these symbols away
}
DM_TEST(dm_test_wdt_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-static int dm_test_wdt_gpio(struct unit_test_state *uts)
+static int dm_test_wdt_gpio_toggle(struct unit_test_state *uts)
{
/*
* The sandbox wdt gpio is "connected" to gpio bank a, offset
* 7. Use the sandbox back door to verify that the gpio-wdt
- * driver behaves as expected.
+ * driver behaves as expected when using the 'toggle' algorithm.
*/
struct udevice *wdt, *gpio;
const u64 timeout = 42;
const int offset = 7;
int val;
- ut_assertok(uclass_get_device_by_driver(UCLASS_WDT,
- DM_DRIVER_GET(wdt_gpio), &wdt));
+ ut_assertok(uclass_get_device_by_name(UCLASS_WDT,
+ "wdt-gpio-toggle", &wdt));
ut_assertnonnull(wdt);
ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio));
return 0;
}
-DM_TEST(dm_test_wdt_gpio, UT_TESTF_SCAN_FDT);
+DM_TEST(dm_test_wdt_gpio_toggle, UT_TESTF_SCAN_FDT);
+
+static int dm_test_wdt_gpio_level(struct unit_test_state *uts)
+{
+ /*
+ * The sandbox wdt gpio is "connected" to gpio bank a, offset
+ * 7. Use the sandbox back door to verify that the gpio-wdt
+ * driver behaves as expected when using the 'level' algorithm.
+ */
+ struct udevice *wdt, *gpio;
+ const u64 timeout = 42;
+ const int offset = 7;
+ int val;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_WDT,
+ "wdt-gpio-level", &wdt));
+ ut_assertnonnull(wdt);
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio));
+ ut_assertnonnull(gpio);
+ ut_assertok(wdt_start(wdt, timeout, 0));
+
+ val = sandbox_gpio_get_value(gpio, offset);
+ ut_assertok(wdt_reset(wdt));
+ ut_asserteq(val, sandbox_gpio_get_value(gpio, offset));
+ ut_assertok(wdt_reset(wdt));
+ ut_asserteq(val, sandbox_gpio_get_value(gpio, offset));
+
+ ut_asserteq(-ENOSYS, wdt_stop(wdt));
+
+ return 0;
+}
+DM_TEST(dm_test_wdt_gpio_level, UT_TESTF_SCAN_FDT);
static int dm_test_wdt_watchdog_reset(struct unit_test_state *uts)
{
uint reset_count;
int val;
- ut_assertok(uclass_get_device_by_driver(UCLASS_WDT,
- DM_DRIVER_GET(wdt_gpio), &gpio_wdt));
+ ut_assertok(uclass_get_device_by_name(UCLASS_WDT,
+ "wdt-gpio-toggle", &gpio_wdt));
ut_assertnonnull(gpio_wdt);
ut_assertok(uclass_get_device_by_driver(UCLASS_WDT,
DM_DRIVER_GET(wdt_sandbox), &sandbox_wdt));
*
* (c) 2012 Daniel Stodden <daniel.stodden@gmail.com>
* (c) 2021 Pali Rohár <pali@kernel.org>
- * (c) 2021 Marek Behún <marek.behun@nic.cz>
+ * (c) 2021 Marek Behún <kabel@kernel.org>
*
* References:
* - "88F6180, 88F6190, 88F6192, and 88F6281: Integrated Controller: Functional
* termios fuctions to support arbitrary baudrates (on Linux)
*
* Copyright (c) 2021 Pali Rohár <pali@kernel.org>
- * Copyright (c) 2021 Marek Behún <marek.behun@nic.cz>
+ * Copyright (c) 2021 Marek Behún <kabel@kernel.org>
*/
#ifndef _TERMIOS_LINUX_H_