* [PATCH 01/20] RISC-V: socs: add Kconfig entry for StarFive JH7100
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 02/20] net: designware: add support for IP integrated into StarFive SoC Ahmad Fatoum
` (18 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The JH7100 is the SoC in the pre-production BeagleV. The normal one
will have a JH7110. Add Kconfig symbols, so newly introduced symbols
can depend on them.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/riscv/Kconfig.socs | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 67d19caeb3b0..9c82a36fe4bd 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -42,4 +42,19 @@ config BOARD_HIFIVE
endif
+config SOC_STARFIVE
+ bool "StarFive SoCs"
+ select CLINT_TIMER
+ help
+ This enables support for SiFive SoC platform hardware.
+
+if SOC_STARFIVE
+
+config SOC_STARFIVE_JH7100
+ bool
+ select SOC_SIFIVE
+
+endif
+
+
endmenu
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 02/20] net: designware: add support for IP integrated into StarFive SoC
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 01/20] RISC-V: socs: add Kconfig entry for StarFive JH7100 Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 03/20] mfd: add TI TPS65086 PMIC restart driver Ahmad Fatoum
` (17 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The Designware MAC on the StarFive jh7100 needs some special speed
configuration. Match against a new starfive,stmmac compatible that
describes that.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/net/Kconfig | 8 +++
drivers/net/Makefile | 1 +
drivers/net/designware.c | 7 +-
drivers/net/designware.h | 1 +
drivers/net/designware_starfive.c | 109 ++++++++++++++++++++++++++++++
include/soc/starfive/sysmain.h | 15 ++++
6 files changed, 138 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/designware_starfive.c
create mode 100644 include/soc/starfive/sysmain.h
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0d55ea7a3b60..ed018dbf9a67 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -82,6 +82,14 @@ config DRIVER_NET_DESIGNWARE_SOCFPGA
This option enables support for the Synopsys
Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA.
+config DRIVER_NET_DESIGNWARE_STARFIVE
+ bool "Designware Universal MAC ethernet driver for StarFive platforms"
+ depends on SOC_STARFIVE || COMPILE_TEST
+ select MFD_SYSCON
+ help
+ This option enables support for the Synopsys
+ Designware Core Univesal MAC 10M/100M/1G ethernet IP on StarFive.
+
endif
config DRIVER_NET_DESIGNWARE_EQOS
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 656d45a868a5..0ce310de05c2 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC) += davinci_emac.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_GENERIC) += designware_generic.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA) += designware_socfpga.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STARFIVE) += designware_starfive.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_EQOS) += designware_eqos.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 0ee6d3d78ac7..e815d74ce9b8 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -457,11 +457,12 @@ struct dw_eth_dev *dwc_drv_probe(struct device_d *dev)
if (ret)
return ERR_PTR(ret);
- if (drvdata && drvdata->enh_desc)
+ if (drvdata) {
priv->enh_desc = drvdata->enh_desc;
- else
+ priv->fix_mac_speed = drvdata->fix_mac_speed;
+ } else {
dev_warn(dev, "No drvdata specified\n");
-
+ }
if (pdata) {
priv->phy_addr = pdata->phy_addr;
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index 0a6a6bf1a497..ef3705b1e387 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -35,6 +35,7 @@ struct dw_eth_dev {
struct dw_eth_drvdata {
bool enh_desc;
+ void (*fix_mac_speed)(int speed);
void *priv;
};
diff --git a/drivers/net/designware_starfive.c b/drivers/net/designware_starfive.c
new file mode 100644
index 000000000000..e7e3fe5fb364
--- /dev/null
+++ b/drivers/net/designware_starfive.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <mfd/syscon.h>
+#include <soc/starfive/sysmain.h>
+#include "designware.h"
+
+/*
+ * GMAC_GTXCLK
+ * bit name access default description
+ * [31] _gmac_gtxclk enable RW 0x0 "1:enable; 0:disable"
+ * [30] reserved - 0x0 reserved
+ * [29:8] reserved - 0x0 reserved
+ * [7:0] gmac_gtxclk ratio RW 0x4 divider value
+ *
+ * 1000M: gtxclk@125M => 500/125 = 0x4
+ * 100M: gtxclk@25M => 500/25 = 0x14
+ * 10M: gtxclk@2.5M => 500/2.5 = 0xc8
+ */
+
+#define CLKGEN_BASE 0x11800000
+#define CLKGEN_GMAC_GTXCLK_OFFSET 0x1EC
+#define CLKGEN_GMAC_GTXCLK_ADDR (CLKGEN_BASE + CLKGEN_GMAC_GTXCLK_OFFSET)
+
+
+#define CLKGEN_125M_DIV 0x4
+#define CLKGEN_25M_DIV 0x14
+#define CLKGEN_2_5M_DIV 0xc8
+
+static void dwmac_fixed_speed(int speed)
+{
+ /* TODO: move this into clk driver */
+ void __iomem *addr = IOMEM(CLKGEN_GMAC_GTXCLK_ADDR);
+ u32 value;
+
+ value = readl(addr) & (~0x000000FF);
+
+ switch (speed) {
+ case SPEED_1000: value |= CLKGEN_125M_DIV; break;
+ case SPEED_100: value |= CLKGEN_25M_DIV; break;
+ case SPEED_10: value |= CLKGEN_2_5M_DIV; break;
+ default: return;
+ }
+
+ writel(value, addr);
+}
+
+static struct dw_eth_drvdata starfive_drvdata = {
+ .enh_desc = 1,
+ .fix_mac_speed = dwmac_fixed_speed,
+};
+
+static int starfive_dwc_ether_probe(struct device_d *dev)
+{
+ struct dw_eth_dev *dwc;
+ struct regmap *regmap;
+ int ret;
+ struct clk_bulk_data clks[] = {
+ { .id = "ptp_ref" },
+ { .id = "tx" },
+ };
+
+ regmap = syscon_regmap_lookup_by_phandle(dev->device_node, "starfive,sysmain");
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Could not get starfive,sysmain node\n");
+ return PTR_ERR(regmap);
+ }
+
+ ret = clk_bulk_get(dev, ARRAY_SIZE(clks), clks);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_enable(ARRAY_SIZE(clks), clks);
+ if (ret < 0)
+ return ret;
+
+ ret = device_reset(dev);
+ if (ret)
+ return ret;
+
+ dwc = dwc_drv_probe(dev);
+ if (IS_ERR(dwc))
+ return PTR_ERR(dwc);
+
+ if (phy_interface_mode_is_rgmii(dwc->interface)) {
+ regmap_update_bits(regmap, SYSMAIN_GMAC_PHY_INTF_SEL, 0x7, 0x1);
+ regmap_write(regmap, SYSMAIN_GMAC_GTXCLK_DLYCHAIN_SEL, 0x4);
+ }
+
+ return 0;
+}
+
+static struct of_device_id starfive_dwc_ether_compatible[] = {
+ { .compatible = "starfive,stmmac", .data = &starfive_drvdata },
+ { /* sentinel */ }
+};
+
+static struct driver_d starfive_dwc_ether_driver = {
+ .name = "starfive-designware_eth",
+ .probe = starfive_dwc_ether_probe,
+ .of_compatible = starfive_dwc_ether_compatible,
+};
+device_platform_driver(starfive_dwc_ether_driver);
diff --git a/include/soc/starfive/sysmain.h b/include/soc/starfive/sysmain.h
new file mode 100644
index 000000000000..b58f8d9825fd
--- /dev/null
+++ b/include/soc/starfive/sysmain.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _STARFIVE_SYSMAIN_H_
+#define _STARFIVE_SYSMAIN_H_
+
+#define SYSMAIN_PLL0_REG 0x00
+#define SYSMAIN_PLL1_REG 0x04
+#define SYSMAIN_PLL2_REG 0x08
+#define SYSMAIN_PLLS_STAT 0x0c
+
+#define SYSMAIN_GMAC_PHY_INTF_SEL 0x70
+#define SYSMAIN_GMAC_GTXCLK_DLYCHAIN_SEL 0xC8
+
+
+#endif //_SYSCON_SYSMAIN_CTRL_MACRO_H_
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 03/20] mfd: add TI TPS65086 PMIC restart driver
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 01/20] RISC-V: socs: add Kconfig entry for StarFive JH7100 Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 02/20] net: designware: add support for IP integrated into StarFive SoC Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-06-07 6:44 ` Sascha Hauer
2021-05-31 7:38 ` [PATCH 04/20] mtd: spi-nor: cadence: fix 64-bit issues Ahmad Fatoum
` (16 subsequent siblings)
19 siblings, 1 reply; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The PMIC offers regulators, GPIOs and system restart. Add restart only
for now.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/mfd/Kconfig | 10 +++
drivers/mfd/Makefile | 2 +
drivers/mfd/core.c | 25 +++++++
drivers/mfd/tps65086.c | 76 ++++++++++++++++++++
drivers/power/reset/Kconfig | 6 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/tps65086-restart.c | 55 +++++++++++++++
include/linux/mfd/core.h | 26 +++++++
include/linux/mfd/tps65086.h | 98 ++++++++++++++++++++++++++
9 files changed, 299 insertions(+)
create mode 100644 drivers/mfd/core.c
create mode 100644 drivers/mfd/tps65086.c
create mode 100644 drivers/power/reset/tps65086-restart.c
create mode 100644 include/linux/mfd/core.h
create mode 100644 include/linux/mfd/tps65086.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d7a8949bafc8..6c76c86fa0cc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -40,6 +40,16 @@ config MFD_SYSCON
help
Select this option to enable accessing system control registers
+config MFD_TPS65086
+ bool "TI TPS65086 Power Management Integrated Chips (PMICs)"
+ depends on I2C
+ help
+ If you say yes here you get support for the TPS65086 series of
+ Power Management chips.
+ This driver provides common support for accessing the device,
+ additional drivers must be enabled in order to use the
+ functionality of the device.
+
config MFD_TWLCORE
bool
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 690e53693ebc..45037e06d62b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MFD_MC34704) += mc34704.o
obj-$(CONFIG_MFD_MC9SDZ60) += mc9sdz60.o
obj-$(CONFIG_MFD_STMPE) += stmpe-i2c.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
+obj-$(CONFIG_MFD_TPS65086) += tps65086.o
obj-$(CONFIG_MFD_TWLCORE) += twl-core.o
obj-$(CONFIG_MFD_TWL4030) += twl4030.o
obj-$(CONFIG_MFD_TWL6030) += twl6030.o
@@ -17,3 +18,4 @@ obj-$(CONFIG_FINTEK_SUPERIO) += fintek-superio.o
obj-$(CONFIG_SMSC_SUPERIO) += smsc-superio.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o
+obj-y += core.o
diff --git a/drivers/mfd/core.c b/drivers/mfd/core.c
new file mode 100644
index 000000000000..ee600d4baafd
--- /dev/null
+++ b/drivers/mfd/core.c
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/mfd/core.h>
+#include <driver.h>
+
+int mfd_add_devices(struct device_d *parent, const struct mfd_cell *cells, int n_devs)
+{
+ struct device_d *dev;
+ int ret, i;
+
+ for (i = 0; i < n_devs; i++) {
+ dev = device_alloc(cells[i].name, DEVICE_ID_DYNAMIC);
+ dev->parent = parent;
+
+ ret = platform_device_register(dev);
+ if (ret)
+ return ret;
+
+ ret = device_add_data(dev, (void *)&cells[i], sizeof(cells[i]));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c
new file mode 100644
index 000000000000..12127922ad2b
--- /dev/null
+++ b/drivers/mfd/tps65086.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
+ * Andrew F. Davis <afd@ti.com>
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <i2c/i2c.h>
+#include <linux/mfd/core.h>
+#include <init.h>
+#include <malloc.h>
+#include <of.h>
+#include <regmap.h>
+#include <xfuncs.h>
+
+#include <linux/mfd/tps65086.h>
+
+static const struct mfd_cell tps65086_cells[] = {
+ { .name = "tps65086-regulator", },
+ { .name = "tps65086-gpio", },
+};
+
+static const struct regmap_config tps65086_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xB6,
+};
+
+static const struct of_device_id tps65086_of_match_table[] = {
+ { .compatible = "ti,tps65086", },
+ { /* sentinel */ }
+};
+
+static int tps65086_probe(struct device_d *dev)
+{
+ struct tps65086 *tps;
+ unsigned int version;
+ int ret;
+
+ tps = xzalloc(sizeof(*tps));
+ tps->dev = dev;
+
+ tps->regmap = regmap_init_i2c(to_i2c_client(dev), &tps65086_regmap_config);
+ if (IS_ERR(tps->regmap)) {
+ dev_err(tps->dev, "Failed to initialize register map\n");
+ return PTR_ERR(tps->regmap);
+ }
+
+ ret = regmap_read(tps->regmap, TPS65086_DEVICEID, &version);
+ if (ret) {
+ dev_err(tps->dev, "Failed to read revision register\n");
+ return ret;
+ }
+
+ dev_info(tps->dev, "Device: TPS65086%01lX, OTP: %c, Rev: %ld\n",
+ (version & TPS65086_DEVICEID_PART_MASK),
+ (char)((version & TPS65086_DEVICEID_OTP_MASK) >> 4) + 'A',
+ (version & TPS65086_DEVICEID_REV_MASK) >> 6);
+
+ dev->priv = tps;
+
+ return mfd_add_devices(tps->dev, tps65086_cells, ARRAY_SIZE(tps65086_cells));
+}
+
+static struct driver_d tps65086_driver = {
+ .name = "tps65086",
+ .of_compatible = tps65086_of_match_table,
+ .probe = tps65086_probe,
+};
+device_i2c_driver(tps65086_driver);
+
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
+MODULE_DESCRIPTION("TPS65086 PMIC Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index dec1482ccd0c..09d6ba0d9031 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -44,3 +44,9 @@ config POWER_RESET_GPIO_RESTART
This driver supports restarting your board via a GPIO line.
If your board needs a GPIO high/low to restart, say Y and
create a binding in your devicetree.
+
+config POWER_RESET_TPS65086
+ bool "TPS65086 restart driver"
+ depends on MFD_TPS65086
+ help
+ Reset TPS65086 PMIC on restart.
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 33d29d2d9546..b362400ba5ef 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o
obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
+obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o
diff --git a/drivers/power/reset/tps65086-restart.c b/drivers/power/reset/tps65086-restart.c
new file mode 100644
index 000000000000..686f215a7781
--- /dev/null
+++ b/drivers/power/reset/tps65086-restart.c
@@ -0,0 +1,55 @@
+
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Emil Renner Berthing
+ */
+
+#include <common.h>
+#include <init.h>
+#include <regmap.h>
+#include <restart.h>
+
+#include <linux/mfd/tps65086.h>
+
+struct tps65086_restart {
+ struct restart_handler handler;
+ struct tps65086 *tps;
+};
+
+static void __noreturn tps65086_restart_handle(struct restart_handler *this)
+{
+ struct tps65086_restart *tps65086_restart =
+ container_of(this, struct tps65086_restart, handler);
+ int ret;
+
+ ret = regmap_write(tps65086_restart->tps->regmap, TPS65086_FORCESHUTDN, 1);
+ WARN_ON(ret);
+
+ /* give it a little time */
+ mdelay(200);
+
+ panic("Unable to restart system\n");
+}
+
+static int tps65086_restart_probe(struct device_d *dev)
+{
+ struct tps65086_restart *tps65086_restart;
+
+ tps65086_restart = xzalloc(sizeof(*tps65086_restart));
+ tps65086_restart->tps = dev->parent->priv;
+
+ tps65086_restart->handler.name = "tps65086-restart";
+ tps65086_restart->handler.restart = tps65086_restart_handle;
+ tps65086_restart->handler.priority = 192;
+
+ return restart_handler_register(&tps65086_restart->handler);
+}
+
+static struct driver_d tps65086_restart_driver = {
+ .name = "tps65086-restart",
+ .probe = tps65086_restart_probe,
+};
+device_platform_driver(tps65086_restart_driver);
+
+MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
+MODULE_DESCRIPTION("TPS65086 restart driver");
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
new file mode 100644
index 000000000000..b67ed25b1de8
--- /dev/null
+++ b/include/linux/mfd/core.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * drivers/mfd/mfd-core.h
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ * Copyright (c) 2007 Dmitry Baryshkov
+ */
+
+#ifndef MFD_CORE_H
+#define MFD_CORE_H
+
+#include <driver.h>
+
+/*
+ * This struct describes the MFD part ("cell").
+ * After registration the copy of this structure will become the platform data
+ * of the resulting device_d
+ */
+struct mfd_cell {
+ const char *name;
+};
+
+int mfd_add_devices(struct device_d *parent, const struct mfd_cell *cells, int n_devs);
+
+#endif
diff --git a/include/linux/mfd/tps65086.h b/include/linux/mfd/tps65086.h
new file mode 100644
index 000000000000..70ecde153ff2
--- /dev/null
+++ b/include/linux/mfd/tps65086.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
+ * Andrew F. Davis <afd@ti.com>
+ *
+ * Based on the TPS65912 driver
+ */
+
+#ifndef __LINUX_MFD_TPS65086_H
+#define __LINUX_MFD_TPS65086_H
+
+#include <driver.h>
+#include <regmap.h>
+
+/* List of registers for TPS65086 */
+#define TPS65086_DEVICEID 0x01
+#define TPS65086_IRQ 0x02
+#define TPS65086_IRQ_MASK 0x03
+#define TPS65086_PMICSTAT 0x04
+#define TPS65086_SHUTDNSRC 0x05
+#define TPS65086_BUCK1CTRL 0x20
+#define TPS65086_BUCK2CTRL 0x21
+#define TPS65086_BUCK3DECAY 0x22
+#define TPS65086_BUCK3VID 0x23
+#define TPS65086_BUCK3SLPCTRL 0x24
+#define TPS65086_BUCK4CTRL 0x25
+#define TPS65086_BUCK5CTRL 0x26
+#define TPS65086_BUCK6CTRL 0x27
+#define TPS65086_LDOA2CTRL 0x28
+#define TPS65086_LDOA3CTRL 0x29
+#define TPS65086_DISCHCTRL1 0x40
+#define TPS65086_DISCHCTRL2 0x41
+#define TPS65086_DISCHCTRL3 0x42
+#define TPS65086_PG_DELAY1 0x43
+#define TPS65086_FORCESHUTDN 0x91
+#define TPS65086_BUCK1SLPCTRL 0x92
+#define TPS65086_BUCK2SLPCTRL 0x93
+#define TPS65086_BUCK4VID 0x94
+#define TPS65086_BUCK4SLPVID 0x95
+#define TPS65086_BUCK5VID 0x96
+#define TPS65086_BUCK5SLPVID 0x97
+#define TPS65086_BUCK6VID 0x98
+#define TPS65086_BUCK6SLPVID 0x99
+#define TPS65086_LDOA2VID 0x9A
+#define TPS65086_LDOA3VID 0x9B
+#define TPS65086_BUCK123CTRL 0x9C
+#define TPS65086_PG_DELAY2 0x9D
+#define TPS65086_PIN_EN_MASK1 0x9E
+#define TPS65086_PIN_EN_MASK2 0x9F
+#define TPS65086_SWVTT_EN 0x9F
+#define TPS65086_PIN_EN_OVR1 0xA0
+#define TPS65086_PIN_EN_OVR2 0xA1
+#define TPS65086_GPOCTRL 0xA1
+#define TPS65086_PWR_FAULT_MASK1 0xA2
+#define TPS65086_PWR_FAULT_MASK2 0xA3
+#define TPS65086_GPO1PG_CTRL1 0xA4
+#define TPS65086_GPO1PG_CTRL2 0xA5
+#define TPS65086_GPO4PG_CTRL1 0xA6
+#define TPS65086_GPO4PG_CTRL2 0xA7
+#define TPS65086_GPO2PG_CTRL1 0xA8
+#define TPS65086_GPO2PG_CTRL2 0xA9
+#define TPS65086_GPO3PG_CTRL1 0xAA
+#define TPS65086_GPO3PG_CTRL2 0xAB
+#define TPS65086_LDOA1CTRL 0xAE
+#define TPS65086_PG_STATUS1 0xB0
+#define TPS65086_PG_STATUS2 0xB1
+#define TPS65086_PWR_FAULT_STATUS1 0xB2
+#define TPS65086_PWR_FAULT_STATUS2 0xB3
+#define TPS65086_TEMPCRIT 0xB4
+#define TPS65086_TEMPHOT 0xB5
+#define TPS65086_OC_STATUS 0xB6
+
+/* IRQ Register field definitions */
+#define TPS65086_IRQ_DIETEMP_MASK BIT(0)
+#define TPS65086_IRQ_SHUTDN_MASK BIT(3)
+#define TPS65086_IRQ_FAULT_MASK BIT(7)
+
+/* DEVICEID Register field definitions */
+#define TPS65086_DEVICEID_PART_MASK GENMASK(3, 0)
+#define TPS65086_DEVICEID_OTP_MASK GENMASK(5, 4)
+#define TPS65086_DEVICEID_REV_MASK GENMASK(7, 6)
+
+/* VID Masks */
+#define BUCK_VID_MASK GENMASK(7, 1)
+#define VDOA1_VID_MASK GENMASK(4, 1)
+#define VDOA23_VID_MASK GENMASK(3, 0)
+
+/**
+ * struct tps65086 - state holder for the tps65086 driver
+ *
+ * Device data may be used to access the TPS65086 chip
+ */
+struct tps65086 {
+ struct device_d *dev;
+ struct regmap *regmap;
+};
+
+#endif /* __LINUX_MFD_TPS65086_H */
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 03/20] mfd: add TI TPS65086 PMIC restart driver
2021-05-31 7:38 ` [PATCH 03/20] mfd: add TI TPS65086 PMIC restart driver Ahmad Fatoum
@ 2021-06-07 6:44 ` Sascha Hauer
0 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2021-06-07 6:44 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
Hi Ahmad,
On Mon, May 31, 2021 at 09:38:04AM +0200, Ahmad Fatoum wrote:
> +#include <common.h>
> +#include <driver.h>
> +#include <errno.h>
> +#include <i2c/i2c.h>
> +#include <linux/mfd/core.h>
> +#include <init.h>
> +#include <malloc.h>
> +#include <of.h>
> +#include <regmap.h>
> +#include <xfuncs.h>
> +
> +#include <linux/mfd/tps65086.h>
> +
> +static const struct mfd_cell tps65086_cells[] = {
> + { .name = "tps65086-regulator", },
> + { .name = "tps65086-gpio", },
> +};
Ok to have cells here which do not have a driver yet,
> +static struct driver_d tps65086_restart_driver = {
> + .name = "tps65086-restart",
> + .probe = tps65086_restart_probe,
> +};
but you should register the cells for the existing driver.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 04/20] mtd: spi-nor: cadence: fix 64-bit issues
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (2 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 03/20] mfd: add TI TPS65086 PMIC restart driver Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-06-07 6:51 ` Sascha Hauer
2021-05-31 7:38 ` [PATCH 05/20] nvmem: add StarFive OTP support Ahmad Fatoum
` (15 subsequent siblings)
19 siblings, 1 reply; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Pointers are being cast to unsigned int, which will truncate the address
on 64-bit systems. Fix this.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/mtd/spi-nor/cadence-quadspi.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
index ea53d2cd847a..09015aad43f1 100644
--- a/drivers/mtd/spi-nor/cadence-quadspi.c
+++ b/drivers/mtd/spi-nor/cadence-quadspi.c
@@ -347,8 +347,8 @@ static int cqspi_command_read(struct spi_nor *nor,
if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || rxbuf == NULL) {
dev_err(nor->dev,
- "Invalid input argument, len %d rxbuf 0x%08x\n", n_rx,
- (unsigned int)rxbuf);
+ "Invalid input argument, len %d rxbuf %p\n", n_rx,
+ rxbuf);
return -EINVAL;
}
@@ -393,8 +393,8 @@ static __maybe_unused int cqspi_command_write(struct spi_nor *nor,
if (n_tx > 4 || (n_tx && txbuf == NULL)) {
dev_err(nor->dev,
- "Invalid input argument, cmdlen %d txbuf 0x%08x\n",
- n_tx, (unsigned int)txbuf);
+ "Invalid input argument, cmdlen %d txbuf %p\n",
+ n_tx, txbuf);
return -EINVAL;
}
@@ -433,7 +433,7 @@ static int cqspi_indirect_read_setup(struct spi_nor *nor,
{
struct cqspi_flash_pdata *f_pdata;
struct cqspi_st *cqspi = nor->priv;
- unsigned int ahb_base = (unsigned int) cqspi->ahb_base;
+ unsigned long ahb_base = (unsigned long) cqspi->ahb_base;
void __iomem *reg_base = cqspi->iobase;
unsigned int dummy_clk = 0;
unsigned int dummy_bytes;
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 04/20] mtd: spi-nor: cadence: fix 64-bit issues
2021-05-31 7:38 ` [PATCH 04/20] mtd: spi-nor: cadence: fix 64-bit issues Ahmad Fatoum
@ 2021-06-07 6:51 ` Sascha Hauer
0 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2021-06-07 6:51 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Mon, May 31, 2021 at 09:38:05AM +0200, Ahmad Fatoum wrote:
> Pointers are being cast to unsigned int, which will truncate the address
> on 64-bit systems. Fix this.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> drivers/mtd/spi-nor/cadence-quadspi.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
> index ea53d2cd847a..09015aad43f1 100644
> --- a/drivers/mtd/spi-nor/cadence-quadspi.c
> +++ b/drivers/mtd/spi-nor/cadence-quadspi.c
> @@ -347,8 +347,8 @@ static int cqspi_command_read(struct spi_nor *nor,
>
> if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || rxbuf == NULL) {
> dev_err(nor->dev,
> - "Invalid input argument, len %d rxbuf 0x%08x\n", n_rx,
> - (unsigned int)rxbuf);
> + "Invalid input argument, len %d rxbuf %p\n", n_rx,
> + rxbuf);
> return -EINVAL;
> }
>
> @@ -393,8 +393,8 @@ static __maybe_unused int cqspi_command_write(struct spi_nor *nor,
>
> if (n_tx > 4 || (n_tx && txbuf == NULL)) {
> dev_err(nor->dev,
> - "Invalid input argument, cmdlen %d txbuf 0x%08x\n",
> - n_tx, (unsigned int)txbuf);
> + "Invalid input argument, cmdlen %d txbuf %p\n",
> + n_tx, txbuf);
> return -EINVAL;
> }
>
> @@ -433,7 +433,7 @@ static int cqspi_indirect_read_setup(struct spi_nor *nor,
> {
> struct cqspi_flash_pdata *f_pdata;
> struct cqspi_st *cqspi = nor->priv;
> - unsigned int ahb_base = (unsigned int) cqspi->ahb_base;
> + unsigned long ahb_base = (unsigned long) cqspi->ahb_base;
This makes the warning disappear, but not the underlying problem. The
ahb_base is written to a 32bit register later, so this won't work on
machines which have memory outside the 32bit range.
We had this problem earlier. What did we do there? I think we should
warn when this happens.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 05/20] nvmem: add StarFive OTP support
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (3 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 04/20] mtd: spi-nor: cadence: fix 64-bit issues Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 06/20] RISC-V: dma: support multiple dma_alloc_coherent backends Ahmad Fatoum
` (14 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The OTP holds the ethernet MAC address. Add a driver, so barebox can
read it out.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/nvmem/Kconfig | 8 ++
drivers/nvmem/Makefile | 2 +
drivers/nvmem/starfive-otp.c | 227 +++++++++++++++++++++++++++++++++++
3 files changed, 237 insertions(+)
create mode 100644 drivers/nvmem/starfive-otp.c
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index e4a72b1431a9..377d6c8b15cc 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -59,4 +59,12 @@ config STM32_BSEC
This adds support for the STM32 OTP controller. Reads and writes
to will go to the shadow RAM, not the OTP fuses themselvers.
+config STARFIVE_OTP
+ tristate "Starfive OTP Supprot"
+ depends on SOC_STARFIVE
+ depends on OFDEVICE
+ help
+ This adds support for the StarFive OTP controller. Only reading
+ is currently supported.
+
endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 617e3725a726..83ff3d23cb44 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -20,3 +20,5 @@ nvmem_eeprom_93xx46-y := eeprom_93xx46.o
obj-$(CONFIG_STM32_BSEC) += nvmem_bsec.o
nvmem_bsec-y := bsec.o
+
+obj-$(CONFIG_STARFIVE_OTP) += starfive-otp.o
diff --git a/drivers/nvmem/starfive-otp.c b/drivers/nvmem/starfive-otp.c
new file mode 100644
index 000000000000..5d1a94364d81
--- /dev/null
+++ b/drivers/nvmem/starfive-otp.c
@@ -0,0 +1,227 @@
+// SPDX_License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 StarFive, Inc
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <gpiod.h>
+#include <init.h>
+#include <net.h>
+#include <io.h>
+#include <of.h>
+#include <regmap.h>
+#include <machine_id.h>
+#include <linux/reset.h>
+#include <linux/nvmem-provider.h>
+
+// otp reg offset
+#define OTP_CFGR 0x00
+#define OTPC_IER 0x04
+#define OTPC_SRR 0x08
+#define OTP_OPRR 0x0c
+#define OTPC_CTLR 0x10
+#define OTPC_ADDRR 0x14
+#define OTPC_DINR 0x18
+#define OTPC_DOUTR 0x1c
+
+#define OTP_EMPTY_CELL_VALUE 0xffffffffUL
+
+// cfgr (offset 0x00)
+#define OTP_CFGR_PRG_CNT_MASK 0xff
+#define OTP_CFGR_PRG_CNT_SHIFT 0
+#define OTP_CFGR_DIV_1US_MASK 0xff
+#define OTP_CFGR_DIV_1US_SHIFT 8
+#define OTP_CFGR_RD_CYC_MASK 0x0f
+#define OTP_CFGR_RD_CYC_SHIFT 16
+
+// ier (offset 0x04)
+#define OTPC_IER_DONE_IE BIT(0)
+#define OTPC_IER_BUSY_OPR_IE BIT(1)
+
+// srr (offset 0x08)
+#define OTPC_SRR_DONE BIT(0)
+#define OTPC_SRR_BUSY_OPR BIT(1)
+#define OTPC_SRR_INFO_RD_LOCK BIT(29)
+#define OTPC_SRR_INFO_WR_LOCK BIT(30)
+#define OTPC_SRR_BUSY BIT(31)
+
+// oprr (offset 0x0c)
+#define OTP_OPRR_OPR_MASK 0x00000007
+#define OTP_OPRR_OPR_SHIFT 0
+
+#define OTP_OPR_STANDBY 0x0 // user mode
+#define OTP_OPR_READ 0x1 // user mode
+#define OTP_OPR_MARGIN_READ_PROG 0x2 // testing mode
+#define OTP_OPR_MARGIN_READ_INIT 0x3 // testing mode
+#define OTP_OPR_PROGRAM 0x4 // user mode
+#define OTP_OPR_DEEP_STANDBY 0x5 // user mode
+#define OTP_OPR_DEBUG 0x6 // user mode
+
+// ctlr (offset 0x10, see EG512X32TH028CW01_v1.0.pdf "Pin Description")
+#define OTPC_CTLR_PCE BIT(0)
+#define OTPC_CTLR_PTM_MASK 0x0000000e
+#define OTPC_CTLR_PTM_SHIFT 1
+#define OTPC_CTLR_PDSTB BIT(4)
+#define OTPC_CTLR_PTR BIT(5)
+#define OTPC_CTLR_PPROG BIT(6)
+#define OTPC_CTLR_PWE BIT(7)
+#define OTPC_CTLR_PCLK BIT(8)
+
+// addrr (offset 0x14)
+#define OTPC_ADDRR_PA_MASK 0x000001ff
+#define OTPC_ADDRR_PA_SHIFT 0
+
+/*
+ * data format:
+ * struct starfive_otp_data{
+ * char vendor[32];
+ * uint64_t sn;
+ * uint8_t mac_addr[6];
+ * uint8_t padding_0[2];
+ * }
+ */
+
+struct starfive_otp {
+ int power_gpio;
+ struct starfive_otp_regs __iomem *regs;
+};
+
+struct starfive_otp_regs {
+ /* TODO: add otp ememory_eg512x32 registers define */
+ u32 otp_cfg; /* timing Register */
+ u32 otpc_ie; /* interrupt Enable */
+ u32 otpc_sr; /* status Register */
+ u32 otp_opr; /* operation mode select Register */
+ u32 otpc_ctl; /* otp control port */
+ u32 otpc_addr; /* otp pa port */
+ u32 otpc_din; /* otp pdin port */
+ u32 otpc_dout; /* otp pdout */
+ u32 reserved[504];
+ u32 mem[512];
+};
+
+/*
+ * offset and size are assumed aligned to the size of the fuses (32-bit).
+ */
+static int starfive_otp_read(void *ctx, unsigned offset, unsigned *val)
+{
+ struct starfive_otp *priv = ctx;
+
+ gpio_set_active(priv->power_gpio, true);
+ mdelay(10);
+
+ //otp set to read mode
+ writel(OTP_OPR_READ, &priv->regs->otp_opr);
+ mdelay(5);
+
+ /* read all requested fuses */
+ *val = readl(&priv->regs->mem[offset / 4]);
+
+ gpio_set_active(priv->power_gpio, false);
+ mdelay(5);
+
+ return 0;
+}
+
+static int starfive_otp_write(void *ctx, unsigned offset, unsigned val)
+{
+ return -EOPNOTSUPP;
+}
+
+static struct regmap_bus starfive_otp_regmap_bus = {
+ .reg_read = starfive_otp_read,
+ .reg_write = starfive_otp_write,
+};
+
+static int starfive_otp_set_mac(struct device_node *rnode, struct regmap *map, unsigned offset)
+{
+ u8 mac[8];
+ int ret;
+
+ ret = regmap_bulk_read(map, offset, mac, 8);
+ if (ret)
+ return ret;
+
+ of_eth_register_ethaddr(rnode, mac);
+ return 0;
+}
+
+static int starfive_otp_probe(struct device_d *dev)
+{
+ struct starfive_otp *priv;
+ struct regmap_config config = {};
+ struct nvmem_device *nvmem;
+ struct resource *iores;
+ const __be32 *prop;
+ struct regmap *map;
+ u32 total_fuses;
+ int len, ret;
+
+ ret = device_reset(dev);
+ if (ret)
+ return ret;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ ret = of_property_read_u32(dev->device_node, "fuse-count", &total_fuses);
+ if (ret < 0) {
+ dev_err(dev, "missing required fuse-count property\n");
+ return ret;
+ }
+
+ config.name = "starfive-otp";
+ config.reg_bits = 32;
+ config.val_bits = 32;
+ config.reg_stride = 4;
+ config.max_register = total_fuses;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->regs = IOMEM(iores->start);
+ priv->power_gpio = gpiod_get(dev, "power", GPIOD_OUT_LOW);
+ if (priv->power_gpio < 0)
+ return priv->power_gpio;
+
+ map = regmap_init(dev, &starfive_otp_regmap_bus, priv, &config);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ nvmem = nvmem_regmap_register(map, "starfive-otp");
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ prop = of_get_property(dev->device_node, "barebox,provide-mac-address", &len);
+ if (prop && len == 2 * sizeof(__be32)) {
+ struct device_node *rnode;
+ u32 phandle, offset;
+
+ phandle = be32_to_cpup(prop++);
+
+ rnode = of_find_node_by_phandle(phandle);
+ offset = be32_to_cpup(prop++);
+
+ ret = starfive_otp_set_mac(rnode, map, offset);
+ if (ret)
+ dev_warn(dev, "error setting MAC address: %pe\n", ERR_PTR(ret));
+ }
+
+ return 0;
+}
+
+static struct of_device_id starfive_otp_dt_ids[] = {
+ { .compatible = "starfive,fu740-otp" },
+ { /* sentinel */ }
+};
+
+static struct driver_d starfive_otp_driver = {
+ .name = "starfive_otp",
+ .probe = starfive_otp_probe,
+ .of_compatible = starfive_otp_dt_ids,
+};
+device_platform_driver(starfive_otp_driver);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 06/20] RISC-V: dma: support multiple dma_alloc_coherent backends
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (4 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 05/20] nvmem: add StarFive OTP support Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 07/20] RISC-V: support incoherent I-Cache Ahmad Fatoum
` (13 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
StarFive JH7100 has uncached DDR region at 64G, but Designware MAC v3.70
has 32-bit DMA mask. There's internal RAM in first 4G that's uncached,
which we could use as backing store for dma_alloc_coherent.
Rework code, so SoC specific code can define own implementation.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/riscv/cpu/Makefile | 2 +
arch/riscv/cpu/cache.c | 22 +++++++++++
arch/riscv/cpu/dma.c | 69 ++++++++++++++++++++++++++++++++++
arch/riscv/include/asm/cache.h | 17 +++++++++
arch/riscv/include/asm/dma.h | 42 +++++----------------
5 files changed, 119 insertions(+), 33 deletions(-)
create mode 100644 arch/riscv/cpu/cache.c
create mode 100644 arch/riscv/cpu/dma.c
create mode 100644 arch/riscv/include/asm/cache.h
diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile
index f1312be699a1..e521ca4bfd47 100644
--- a/arch/riscv/cpu/Makefile
+++ b/arch/riscv/cpu/Makefile
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += core.o time.o
+obj-$(CONFIG_HAS_CACHE) += cache.o
+obj-$(CONFIG_HAS_DMA) += dma.o
diff --git a/arch/riscv/cpu/cache.c b/arch/riscv/cpu/cache.c
new file mode 100644
index 000000000000..d5aad7e4038b
--- /dev/null
+++ b/arch/riscv/cpu/cache.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <asm/cache.h>
+
+static struct cache_ops *cache_ops;
+
+void __dma_flush_range(dma_addr_t start, dma_addr_t end)
+{
+ if (cache_ops)
+ cache_ops->dma_flush_range(start, end);
+}
+
+void __dma_inv_range(dma_addr_t start, dma_addr_t end)
+{
+ if (cache_ops)
+ cache_ops->dma_inv_range(start, end);
+}
+
+void riscv_cache_set_ops(struct cache_ops *ops)
+{
+ cache_ops = ops;
+}
diff --git a/arch/riscv/cpu/dma.c b/arch/riscv/cpu/dma.c
new file mode 100644
index 000000000000..d7dc642f5830
--- /dev/null
+++ b/arch/riscv/cpu/dma.c
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <common.h>
+#include <xfuncs.h>
+#include <asm/dma.h>
+#include <asm/cache.h>
+#include <malloc.h>
+
+static void *__dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
+{
+ void *ret;
+
+ ret = xmemalign(PAGE_SIZE, size);
+
+ memset(ret, 0, size);
+
+ if (dma_handle)
+ *dma_handle = (dma_addr_t)ret;
+
+ return ret;
+}
+
+static void __dma_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size)
+{
+ free(vaddr);
+}
+
+static const struct dma_coherent_ops nommu_ops = {
+ .alloc = __dma_alloc_coherent,
+ .free = __dma_free_coherent,
+};
+
+static const struct dma_coherent_ops *dma_coherent_ops = &nommu_ops;
+
+void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
+{
+ return dma_coherent_ops->alloc(size, dma_handle);
+}
+
+void dma_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size)
+{
+ dma_coherent_ops->free(vaddr, dma_handle, size);
+}
+
+void dma_set_coherent_ops(const struct dma_coherent_ops *ops)
+{
+ dma_coherent_ops = ops;
+}
+
+void dma_sync_single_for_cpu(dma_addr_t address, size_t size, enum dma_data_direction dir)
+{
+ /*
+ * FIXME: This function needs a device argument to support non 1:1 mappings
+ */
+ if (dir != DMA_TO_DEVICE)
+ __dma_inv_range(address, address + size);
+}
+
+void dma_sync_single_for_device(dma_addr_t address, size_t size, enum dma_data_direction dir)
+{
+ /*
+ * FIXME: This function needs a device argument to support non 1:1 mappings
+ */
+
+ if (dir == DMA_FROM_DEVICE)
+ __dma_inv_range(address, address + size);
+ else
+ __dma_flush_range(address, address + size);
+}
diff --git a/arch/riscv/include/asm/cache.h b/arch/riscv/include/asm/cache.h
new file mode 100644
index 000000000000..a1cdd6b13b62
--- /dev/null
+++ b/arch/riscv/include/asm/cache.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+#include <linux/types.h>
+
+struct cache_ops {
+ void (*dma_flush_range)(dma_addr_t start, dma_addr_t end);
+ void (*dma_inv_range)(dma_addr_t start, dma_addr_t end);
+};
+
+void __dma_flush_range(dma_addr_t start, dma_addr_t end);
+void __dma_inv_range(dma_addr_t start, dma_addr_t end);
+
+void riscv_cache_set_ops(struct cache_ops *ops);
+
+#endif
diff --git a/arch/riscv/include/asm/dma.h b/arch/riscv/include/asm/dma.h
index 4204653984a3..b880e49732e0 100644
--- a/arch/riscv/include/asm/dma.h
+++ b/arch/riscv/include/asm/dma.h
@@ -2,43 +2,19 @@
#ifndef _ASM_DMA_MAPPING_H
#define _ASM_DMA_MAPPING_H
-#include <common.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
#include <xfuncs.h>
-#include <linux/build_bug.h>
-#include <malloc.h>
-#ifdef CONFIG_MMU
-#error DMA stubs need be replaced when using MMU and caches
-#endif
+struct dma_coherent_ops {
+ void *(*alloc)(size_t size, dma_addr_t *dma_handle);
-static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
-{
- void *ret;
+ void (*free)(void *vaddr, dma_addr_t dma_handle, size_t size);
+};
- ret = xmemalign(PAGE_SIZE, size);
+void dma_set_coherent_ops(const struct dma_coherent_ops *ops);
+#define DMA_ALIGNMENT 64
- memset(ret, 0, size);
-
- if (dma_handle)
- *dma_handle = (dma_addr_t)ret;
-
- return ret;
-}
-
-static inline void dma_free_coherent(void *vaddr, dma_addr_t dma_handle,
- size_t size)
-{
- free(vaddr);
-}
-
-static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
-{
-}
-
-static inline void dma_sync_single_for_device(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
-{
-}
+#include <dma.h>
#endif /* _ASM_DMA_MAPPING_H */
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 07/20] RISC-V: support incoherent I-Cache
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (5 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 06/20] RISC-V: dma: support multiple dma_alloc_coherent backends Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:40 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 08/20] soc: add support for StarFive JH7100 incoherent interconnect Ahmad Fatoum
` (12 subsequent siblings)
19 siblings, 1 reply; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
SiFive SoCs have separate I-Caches that require self-modifying code
like barebox' relocation and PBL extraction code to do cache
maintenance. Implement sync_caches_for_execution and use it where
appropriate.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/riscv/Kconfig.socs | 2 ++
arch/riscv/boot/uncompress.c | 2 ++
arch/riscv/cpu/core.c | 7 +++++++
arch/riscv/include/asm/barebox-riscv.h | 2 ++
arch/riscv/lib/reloc.c | 8 ++++++++
arch/riscv/lib/setupc.S | 2 ++
6 files changed, 23 insertions(+)
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 9c82a36fe4bd..d2970ba1d67f 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -18,6 +18,7 @@ config SOC_VIRT
select RISCV_S_MODE
select BOARD_RISCV_GENERIC_DT
select CLINT_TIMER
+ select HAS_CACHE
help
Generates an image tht can be be booted by QEMU. The image is called
barebox-dt-2nd.img
@@ -30,6 +31,7 @@ config SOC_SIFIVE
select RISCV_TIMER
select HAS_MACB
select HAS_ASM_DEBUG_LL
+ select HAS_CACHE
help
This enables support for SiFive SoC platform hardware.
diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c
index 35a91e8cb62a..9f1d25efb59b 100644
--- a/arch/riscv/boot/uncompress.c
+++ b/arch/riscv/boot/uncompress.c
@@ -63,6 +63,8 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
pbl_barebox_uncompress((void*)barebox_base, pg_start, pg_len);
+ sync_caches_for_execution();
+
barebox = (void *)barebox_base;
pr_debug("jumping to uncompressed image at 0x%p. dtb=0x%p\n", barebox, fdt);
diff --git a/arch/riscv/cpu/core.c b/arch/riscv/cpu/core.c
index 62eb0ca87164..b4727fe7449b 100644
--- a/arch/riscv/cpu/core.c
+++ b/arch/riscv/cpu/core.c
@@ -18,6 +18,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <memory.h>
+#include <asm/barebox-riscv.h>
#include <asm-generic/memory_layout.h>
#include <globalvar.h>
#include <magicvar.h>
@@ -91,3 +92,9 @@ static struct driver_d riscv_driver = {
.of_compatible = riscv_dt_ids,
};
postcore_platform_driver(riscv_driver);
+
+static void arch_shutdown(void)
+{
+ sync_caches_for_execution();
+}
+archshutdown_exitcall(arch_shutdown);
diff --git a/arch/riscv/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h
index bbe6cd040642..abb320242769 100644
--- a/arch/riscv/include/asm/barebox-riscv.h
+++ b/arch/riscv/include/asm/barebox-riscv.h
@@ -27,6 +27,8 @@ void setup_c(void);
void relocate_to_current_adr(void);
void relocate_to_adr(unsigned long target);
+void sync_caches_for_execution(void);
+
void __noreturn __naked barebox_riscv_entry(unsigned long membase, unsigned long memsize,
void *boarddata, unsigned int flags);
diff --git a/arch/riscv/lib/reloc.c b/arch/riscv/lib/reloc.c
index 2fc8818cd698..165190775361 100644
--- a/arch/riscv/lib/reloc.c
+++ b/arch/riscv/lib/reloc.c
@@ -24,6 +24,12 @@
#define RISC_R_TYPE(x) ((x) & 0xFF)
+void sync_caches_for_execution(void)
+{
+ if (IS_ENABLED(CONFIG_HAS_CACHE))
+ asm volatile ("fence.i" ::: "memory");
+}
+
void relocate_to_current_adr(void)
{
unsigned long offset;
@@ -63,4 +69,6 @@ void relocate_to_current_adr(void)
panic("");
}
}
+
+ sync_caches_for_execution();
}
diff --git a/arch/riscv/lib/setupc.S b/arch/riscv/lib/setupc.S
index 5fdd81c2c3ec..d225186c79fd 100644
--- a/arch/riscv/lib/setupc.S
+++ b/arch/riscv/lib/setupc.S
@@ -46,6 +46,8 @@ ENTRY(relocate_to_adr)
jal __memcpy
+ jal sync_caches_for_execution
+
REG_L a0, (SZREG * 1)(sp)
jr a0 /* jump to relocated address */
copied:
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 07/20] RISC-V: support incoherent I-Cache
2021-05-31 7:38 ` [PATCH 07/20] RISC-V: support incoherent I-Cache Ahmad Fatoum
@ 2021-05-31 7:40 ` Ahmad Fatoum
2021-06-07 7:33 ` Ahmad Fatoum
0 siblings, 1 reply; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:40 UTC (permalink / raw)
To: Antony Pavlov; +Cc: barebox
Hello Antony,
On 31.05.21 09:38, Ahmad Fatoum wrote:
> SiFive SoCs have separate I-Caches that require self-modifying code
> like barebox' relocation and PBL extraction code to do cache
> maintenance. Implement sync_caches_for_execution and use it where
> appropriate.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> arch/riscv/Kconfig.socs | 2 ++
> arch/riscv/boot/uncompress.c | 2 ++
> arch/riscv/cpu/core.c | 7 +++++++
> arch/riscv/include/asm/barebox-riscv.h | 2 ++
> arch/riscv/lib/reloc.c | 8 ++++++++
> arch/riscv/lib/setupc.S | 2 ++
> 6 files changed, 23 insertions(+)
>
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 9c82a36fe4bd..d2970ba1d67f 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -18,6 +18,7 @@ config SOC_VIRT
> select RISCV_S_MODE
> select BOARD_RISCV_GENERIC_DT
> select CLINT_TIMER
> + select HAS_CACHE
> help
> Generates an image tht can be be booted by QEMU. The image is called
> barebox-dt-2nd.img
> @@ -30,6 +31,7 @@ config SOC_SIFIVE
> select RISCV_TIMER
> select HAS_MACB
> select HAS_ASM_DEBUG_LL
> + select HAS_CACHE
> help
> This enables support for SiFive SoC platform hardware.
>
> diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c
> index 35a91e8cb62a..9f1d25efb59b 100644
> --- a/arch/riscv/boot/uncompress.c
> +++ b/arch/riscv/boot/uncompress.c
> @@ -63,6 +63,8 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
>
> pbl_barebox_uncompress((void*)barebox_base, pg_start, pg_len);
>
> + sync_caches_for_execution();
> +
> barebox = (void *)barebox_base;
>
> pr_debug("jumping to uncompressed image at 0x%p. dtb=0x%p\n", barebox, fdt);
> diff --git a/arch/riscv/cpu/core.c b/arch/riscv/cpu/core.c
> index 62eb0ca87164..b4727fe7449b 100644
> --- a/arch/riscv/cpu/core.c
> +++ b/arch/riscv/cpu/core.c
> @@ -18,6 +18,7 @@
> #include <linux/clk.h>
> #include <linux/err.h>
> #include <memory.h>
> +#include <asm/barebox-riscv.h>
> #include <asm-generic/memory_layout.h>
> #include <globalvar.h>
> #include <magicvar.h>
> @@ -91,3 +92,9 @@ static struct driver_d riscv_driver = {
> .of_compatible = riscv_dt_ids,
> };
> postcore_platform_driver(riscv_driver);
> +
> +static void arch_shutdown(void)
> +{
> + sync_caches_for_execution();
> +}
> +archshutdown_exitcall(arch_shutdown);
> diff --git a/arch/riscv/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h
> index bbe6cd040642..abb320242769 100644
> --- a/arch/riscv/include/asm/barebox-riscv.h
> +++ b/arch/riscv/include/asm/barebox-riscv.h
> @@ -27,6 +27,8 @@ void setup_c(void);
> void relocate_to_current_adr(void);
> void relocate_to_adr(unsigned long target);
>
> +void sync_caches_for_execution(void);
> +
> void __noreturn __naked barebox_riscv_entry(unsigned long membase, unsigned long memsize,
> void *boarddata, unsigned int flags);
>
> diff --git a/arch/riscv/lib/reloc.c b/arch/riscv/lib/reloc.c
> index 2fc8818cd698..165190775361 100644
> --- a/arch/riscv/lib/reloc.c
> +++ b/arch/riscv/lib/reloc.c
> @@ -24,6 +24,12 @@
>
> #define RISC_R_TYPE(x) ((x) & 0xFF)
>
> +void sync_caches_for_execution(void)
> +{
> + if (IS_ENABLED(CONFIG_HAS_CACHE))
> + asm volatile ("fence.i" ::: "memory");
If Erizo on FPGA chokes on this, we can have it pass
along a feature flag from PBL that says it doesn't
need cache maintenance. Please advise.
> +}
> +
> void relocate_to_current_adr(void)
> {
> unsigned long offset;
> @@ -63,4 +69,6 @@ void relocate_to_current_adr(void)
> panic("");
> }
> }
> +
> + sync_caches_for_execution();
> }
> diff --git a/arch/riscv/lib/setupc.S b/arch/riscv/lib/setupc.S
> index 5fdd81c2c3ec..d225186c79fd 100644
> --- a/arch/riscv/lib/setupc.S
> +++ b/arch/riscv/lib/setupc.S
> @@ -46,6 +46,8 @@ ENTRY(relocate_to_adr)
>
> jal __memcpy
>
> + jal sync_caches_for_execution
> +
> REG_L a0, (SZREG * 1)(sp)
> jr a0 /* jump to relocated address */
> copied:
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 07/20] RISC-V: support incoherent I-Cache
2021-05-31 7:40 ` Ahmad Fatoum
@ 2021-06-07 7:33 ` Ahmad Fatoum
0 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-06-07 7:33 UTC (permalink / raw)
To: Antony Pavlov; +Cc: barebox
On 31.05.21 09:40, Ahmad Fatoum wrote:
> Hello Antony,
>
> On 31.05.21 09:38, Ahmad Fatoum wrote:
>> SiFive SoCs have separate I-Caches that require self-modifying code
>> like barebox' relocation and PBL extraction code to do cache
>> maintenance. Implement sync_caches_for_execution and use it where
>> appropriate.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>> ---
>> +void sync_caches_for_execution(void)
>> +{
>> + if (IS_ENABLED(CONFIG_HAS_CACHE))
>> + asm volatile ("fence.i" ::: "memory");
>
> If Erizo on FPGA chokes on this, we can have it pass
> along a feature flag from PBL that says it doesn't
> need cache maintenance. Please advise.
I now skip over fence.i in the exception handler, so it should be ok
to call this, even on systems that lack Zifencei ISA extension.
I'll send out a v2 soon.
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 08/20] soc: add support for StarFive JH7100 incoherent interconnect
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (6 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 07/20] RISC-V: support incoherent I-Cache Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 09/20] soc: sifive: l2_cache: enable maximum available cache ways Ahmad Fatoum
` (11 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The preproduction JH7100 used in the BeagleV beta does not ensure cache
coherence between CPU and some DMA masters like the Ethernet MAC.
Fix this for streaming DMA mappings by implementing cache cleaning and
discarding. The Flush64 primitive can be used for both as it will
invalidate after flushing and not write-back clean lines.
Coherent DMA mapping will be implemented using allocation from uncached
SRAM in a follow-up commit.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/riscv/Kconfig.socs | 5 +
arch/riscv/include/asm/barrier.h | 27 ++++++
drivers/Makefile | 2 +-
drivers/soc/Makefile | 4 +
drivers/soc/sifive/Makefile | 1 +
drivers/soc/sifive/sifive_l2_cache.c | 137 +++++++++++++++++++++++++++
6 files changed, 175 insertions(+), 1 deletion(-)
create mode 100644 arch/riscv/include/asm/barrier.h
create mode 100644 drivers/soc/Makefile
create mode 100644 drivers/soc/sifive/Makefile
create mode 100644 drivers/soc/sifive/sifive_l2_cache.c
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index d2970ba1d67f..3e4cd3cdad59 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -37,6 +37,11 @@ config SOC_SIFIVE
if SOC_SIFIVE
+config SIFIVE_L2
+ bool
+ help
+ Selected by SoCs with cache incoherent interconnects
+
config BOARD_HIFIVE
bool "HiFive"
depends on ARCH_RV64I
diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h
new file mode 100644
index 000000000000..eff529307a15
--- /dev/null
+++ b/arch/riscv/include/asm/barrier.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Based on arch/arm/include/asm/barrier.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2013 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ */
+
+#ifndef _ASM_RISCV_BARRIER_H
+#define _ASM_RISCV_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop() __asm__ __volatile__ ("nop")
+
+#define RISCV_FENCE(p, s) \
+ __asm__ __volatile__ ("fence " #p "," #s : : : "memory")
+
+/* These barriers need to enforce ordering on both devices or memory. */
+#define mb() RISCV_FENCE(iorw,iorw)
+#define rmb() RISCV_FENCE(ir,ir)
+#define wmb() RISCV_FENCE(ow,ow)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_RISCV_BARRIER_H */
diff --git a/drivers/Makefile b/drivers/Makefile
index be5b0b3b04c9..aeb097e1f5ff 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -39,7 +39,7 @@ obj-$(CONFIG_HAB) += hab/
obj-$(CONFIG_CRYPTO_HW) += crypto/
obj-$(CONFIG_AIODEV) += aiodev/
obj-y += memory/
-obj-y += soc/imx/
+obj-y += soc/
obj-y += nvme/
obj-y += ddr/
obj-y += power/
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
new file mode 100644
index 000000000000..06b8c2a504af
--- /dev/null
+++ b/drivers/soc/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += imx/
+obj-$(CONFIG_SOC_SIFIVE) += sifive/
diff --git a/drivers/soc/sifive/Makefile b/drivers/soc/sifive/Makefile
new file mode 100644
index 000000000000..e8113c66f576
--- /dev/null
+++ b/drivers/soc/sifive/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SIFIVE_L2) += sifive_l2_cache.o
diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c
new file mode 100644
index 000000000000..1ac39c743681
--- /dev/null
+++ b/drivers/soc/sifive/sifive_l2_cache.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SiFive L2 cache controller Driver
+ *
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ *
+ */
+
+#define pr_fmt(fmt) "sifive-l2: " fmt
+
+#include <io.h>
+#include <printk.h>
+#include <stdio.h>
+#include <driver.h>
+#include <init.h>
+#include <of.h>
+#include <asm/cache.h>
+#include <asm/barrier.h>
+
+#define SIFIVE_L2_DIRECCFIX_LOW 0x100
+#define SIFIVE_L2_DIRECCFIX_HIGH 0x104
+#define SIFIVE_L2_DIRECCFIX_COUNT 0x108
+
+#define SIFIVE_L2_DIRECCFAIL_LOW 0x120
+#define SIFIVE_L2_DIRECCFAIL_HIGH 0x124
+#define SIFIVE_L2_DIRECCFAIL_COUNT 0x128
+
+#define SIFIVE_L2_DATECCFIX_LOW 0x140
+#define SIFIVE_L2_DATECCFIX_HIGH 0x144
+#define SIFIVE_L2_DATECCFIX_COUNT 0x148
+
+#define SIFIVE_L2_DATECCFAIL_LOW 0x160
+#define SIFIVE_L2_DATECCFAIL_HIGH 0x164
+#define SIFIVE_L2_DATECCFAIL_COUNT 0x168
+
+#define SIFIVE_L2_FLUSH64 0x200
+
+#define SIFIVE_L2_CONFIG 0x00
+#define SIFIVE_L2_WAYENABLE 0x08
+#define SIFIVE_L2_ECCINJECTERR 0x40
+
+#define SIFIVE_L2_MAX_ECCINTR 4
+
+#define SIFIVE_L2_FLUSH64_LINE_LEN 64
+
+static void __iomem *l2_base = NULL;
+
+static void sifive_l2_config_read(struct device_d *dev)
+{
+ u32 regval, val;
+
+ printf("Cache configuration:\n");
+
+ regval = readl(l2_base + SIFIVE_L2_CONFIG);
+ val = regval & 0xFF;
+ printf(" #Banks: %d\n", val);
+ val = (regval & 0xFF00) >> 8;
+ printf(" #Ways per bank: %d\n", val);
+ val = (regval & 0xFF0000) >> 16;
+ printf(" #Sets per bank: %llu\n", 1llu << val);
+ val = (regval & 0xFF000000) >> 24;
+ printf(" #Bytes per cache block: %llu\n", 1llu << val);
+
+ regval = readl(l2_base + SIFIVE_L2_WAYENABLE);
+ printf(" #Index of the largest way enabled: %d\n", regval);
+}
+
+static void sifive_l2_flush64_range(dma_addr_t start, dma_addr_t end)
+{
+ unsigned long line;
+
+ start = ALIGN_DOWN(start, 64);
+ end = ALIGN(end, 64);
+
+ if (start == end)
+ return;
+
+ mb();
+ for (line = start; line < end; line += SIFIVE_L2_FLUSH64_LINE_LEN) {
+ writeq(line, l2_base + SIFIVE_L2_FLUSH64);
+ mb();
+ }
+}
+
+struct cache_ops sifive_l2_ops = {
+ .dma_flush_range = sifive_l2_flush64_range,
+ .dma_inv_range = sifive_l2_flush64_range,
+};
+
+/* Normally, L2 should be kept coherent between SiFive CPUs and other
+ * DMA masters on the SoC. If that's not the case, add it to the table
+ * here, so barebox dma_map_single and co. flush and invalidate as
+ * necessary.
+ * Note: If barebox is allocating from cacheable memory, you will
+ * need a driver to set dma_coherent_ops as well.
+ */
+static const struct of_device_id incoherent_soc_dt_ids[] = {
+ { "starfive,jh7100" },
+ { /* sentinel */ },
+};
+
+static int sifive_l2_probe(struct device_d *dev)
+{
+ struct resource *iores;
+
+ if (l2_base)
+ return -EBUSY;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ l2_base = IOMEM(iores->start);
+
+ dev->info = sifive_l2_config_read;
+
+ if (of_match_node(incoherent_soc_dt_ids, of_get_root_node())) {
+ riscv_cache_set_ops(&sifive_l2_ops);
+ pr_info("enabling L2 cache ops\n");
+ }
+
+ return 0;
+}
+
+static const struct of_device_id sifive_l2_ids[] = {
+ { .compatible = "sifive,fu540-c000-ccache" },
+ { .compatible = "sifive,fu740-c000-ccache" },
+ { .compatible = "starfive,ccache0" },
+ { /* end of table */ },
+};
+
+static struct driver_d sifive_l2_driver = {
+ .name = "sfive-l2cache",
+ .probe = sifive_l2_probe,
+ .of_compatible = sifive_l2_ids,
+};
+postcore_platform_driver(sifive_l2_driver);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 09/20] soc: sifive: l2_cache: enable maximum available cache ways
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (7 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 08/20] soc: add support for StarFive JH7100 incoherent interconnect Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 10/20] net: designware: fix 64-bit incompatibilities Ahmad Fatoum
` (10 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Previous boot stages may not enable all cache ways, e.g. because they
are running from L2 cache. By the time barebox proper is running,
execution should be from main SDRAM, so it's ok now to enable the
maximum available count of cache ways.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/soc/sifive/sifive_l2_cache.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c
index 1ac39c743681..f2cef133de63 100644
--- a/drivers/soc/sifive/sifive_l2_cache.c
+++ b/drivers/soc/sifive/sifive_l2_cache.c
@@ -16,6 +16,7 @@
#include <of.h>
#include <asm/cache.h>
#include <asm/barrier.h>
+#include <linux/bitops.h>
#define SIFIVE_L2_DIRECCFIX_LOW 0x100
#define SIFIVE_L2_DIRECCFIX_HIGH 0x104
@@ -41,6 +42,9 @@
#define SIFIVE_L2_MAX_ECCINTR 4
+#define MASK_NUM_WAYS GENMASK(15, 8)
+#define NUM_WAYS_SHIFT 8
+
#define SIFIVE_L2_FLUSH64_LINE_LEN 64
static void __iomem *l2_base = NULL;
@@ -87,6 +91,21 @@ struct cache_ops sifive_l2_ops = {
.dma_inv_range = sifive_l2_flush64_range,
};
+static int sifive_l2_enable_ways(void)
+{
+ u32 config;
+ u32 ways;
+
+ config = readl(l2_base + SIFIVE_L2_CONFIG);
+ ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT;
+
+ mb();
+ writel(ways - 1, l2_base + SIFIVE_L2_WAYENABLE);
+ mb();
+
+ return 0;
+}
+
/* Normally, L2 should be kept coherent between SiFive CPUs and other
* DMA masters on the SoC. If that's not the case, add it to the table
* here, so barebox dma_map_single and co. flush and invalidate as
@@ -112,6 +131,8 @@ static int sifive_l2_probe(struct device_d *dev)
l2_base = IOMEM(iores->start);
+ sifive_l2_enable_ways();
+
dev->info = sifive_l2_config_read;
if (of_match_node(incoherent_soc_dt_ids, of_get_root_node())) {
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 10/20] net: designware: fix 64-bit incompatibilities
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (8 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 09/20] soc: sifive: l2_cache: enable maximum available cache ways Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 11/20] dma: support marking SRAM for coherent DMA use Ahmad Fatoum
` (9 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
drivers/net/designware.c handles the older Designware < 4.x MAC IPs,
which do not support DMA beyond 32-bit. They are still being integrated
into SoCs with 64-bit CPUs like the StarFive JH7100.
Fix the driver to support such usage. The driver still has the assumption
that barebox core will only pass it 32-bit pointers. This is now made
explicit by returning error codes when the DMA mask is violated.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/riscv/include/asm/io.h | 10 ++++++++++
drivers/net/designware.c | 28 +++++++++++++++-------------
drivers/net/designware.h | 6 ++++--
3 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h
index 3cdea7fcace1..795e670e3b9b 100644
--- a/arch/riscv/include/asm/io.h
+++ b/arch/riscv/include/asm/io.h
@@ -5,4 +5,14 @@
#include <asm-generic/io.h>
+static inline void *phys_to_virt(unsigned long phys)
+{
+ return (void *)phys;
+}
+
+static inline unsigned long virt_to_phys(volatile void *mem)
+{
+ return (unsigned long)mem;
+}
+
#endif /* __ASM_RISCV_IO_H */
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index e815d74ce9b8..71c62d7ddc94 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -111,8 +111,8 @@ static void tx_descs_init(struct eth_device *dev)
for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
- desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
- desc_p->dmamac_next = &desc_table_p[idx + 1];
+ desc_p->dmamac_addr = virt_to_phys(&txbuffs[idx * CONFIG_ETH_BUFSIZE]);
+ desc_p->dmamac_next = virt_to_phys(&desc_table_p[idx + 1]);
if (priv->enh_desc) {
desc_p->txrx_status &= ~(DESC_ENH_TXSTS_TXINT | DESC_ENH_TXSTS_TXLAST |
@@ -130,7 +130,7 @@ static void tx_descs_init(struct eth_device *dev)
}
/* Correcting the last pointer of the chain */
- desc_p->dmamac_next = &desc_table_p[0];
+ desc_p->dmamac_next = virt_to_phys(&desc_table_p[0]);
writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
priv->tx_currdescnum = 0;
@@ -147,8 +147,8 @@ static void rx_descs_init(struct eth_device *dev)
for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
- desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
- desc_p->dmamac_next = &desc_table_p[idx + 1];
+ desc_p->dmamac_addr = virt_to_phys(&rxbuffs[idx * CONFIG_ETH_BUFSIZE]);
+ desc_p->dmamac_next = virt_to_phys(&desc_table_p[idx + 1]);
desc_p->dmamac_cntl = MAC_MAX_FRAME_SZ;
if (priv->enh_desc)
@@ -156,13 +156,13 @@ static void rx_descs_init(struct eth_device *dev)
else
desc_p->dmamac_cntl |= DESC_RXCTRL_RXCHAIN;
- dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr,
+ dma_sync_single_for_cpu(desc_p->dmamac_addr,
CONFIG_ETH_BUFSIZE, DMA_FROM_DEVICE);
desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
}
/* Correcting the last pointer of the chain */
- desc_p->dmamac_next = &desc_table_p[0];
+ desc_p->dmamac_next = virt_to_phys(&desc_table_p[0]);
writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
priv->rx_currdescnum = 0;
@@ -285,8 +285,8 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length)
return -1;
}
- memcpy((void *)desc_p->dmamac_addr, packet, length);
- dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr, length,
+ memcpy(dmamac_addr(desc_p), packet, length);
+ dma_sync_single_for_device(desc_p->dmamac_addr, length,
DMA_TO_DEVICE);
if (priv->enh_desc) {
@@ -314,7 +314,7 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length)
/* Start the transmission */
writel(POLL_DATA, &dma_p->txpolldemand);
- dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, length,
+ dma_sync_single_for_cpu(desc_p->dmamac_addr, length,
DMA_TO_DEVICE);
return 0;
@@ -358,10 +358,10 @@ static int dwc_ether_rx(struct eth_device *dev)
length = (status & DESC_RXSTS_FRMLENMSK) >>
DESC_RXSTS_FRMLENSHFT;
- dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr,
+ dma_sync_single_for_cpu(desc_p->dmamac_addr,
length, DMA_FROM_DEVICE);
- net_receive(dev, desc_p->dmamac_addr, length);
- dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr,
+ net_receive(dev, dmamac_addr(desc_p), length);
+ dma_sync_single_for_device(desc_p->dmamac_addr,
length, DMA_FROM_DEVICE);
ret = length;
}
@@ -451,6 +451,8 @@ struct dw_eth_dev *dwc_drv_probe(struct device_d *dev)
int ret;
struct dw_eth_drvdata *drvdata;
+ dma_set_mask(dev, DMA_BIT_MASK(32));
+
priv = xzalloc(sizeof(struct dw_eth_dev));
ret = dev_get_drvdata(dev, (const void **)&drvdata);
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index ef3705b1e387..a085a6f16ad1 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -139,10 +139,12 @@ struct eth_dma_regs {
struct dmamacdescr {
u32 txrx_status;
u32 dmamac_cntl;
- void *dmamac_addr;
- struct dmamacdescr *dmamac_next;
+ u32 dmamac_addr;
+ u32 dmamac_next;
};
+#define dmamac_addr(descr) (phys_to_virt((descr)->dmamac_addr))
+
/*
* txrx_status definitions
*/
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 11/20] dma: support marking SRAM for coherent DMA use
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (9 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 10/20] net: designware: fix 64-bit incompatibilities Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-06-07 7:34 ` Sascha Hauer
2021-06-07 7:39 ` Sascha Hauer
2021-05-31 7:38 ` [PATCH 12/20] mci: allocate DMA-able memory Ahmad Fatoum
` (8 subsequent siblings)
19 siblings, 2 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The RISC-V architecture allows overriding the dma_alloc_coherent and
dma_free_coherent. Allow this to be controlled by device tree.
Cache-coherent SoCs won't need this, but incoherent ones that have
uncached regions can register them here.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/Kconfig | 4 ++
common/Makefile | 3 +-
drivers/dma/Kconfig | 6 ++
drivers/dma/Makefile | 1 +
drivers/dma/coherent-pool.c | 120 ++++++++++++++++++++++++++++++++++++
5 files changed, 133 insertions(+), 1 deletion(-)
create mode 100644 drivers/dma/coherent-pool.c
diff --git a/common/Kconfig b/common/Kconfig
index ce349d4ebbf6..dbbcbb946fff 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -303,6 +303,9 @@ config EXPERIMENTAL
bool
prompt "Prompt for experimental code"
+config TLSF
+ bool
+
choice
prompt "malloc implementation"
@@ -311,6 +314,7 @@ config MALLOC_DLMALLOC
config MALLOC_TLSF
bool "tlsf"
+ select TLSF
config MALLOC_DUMMY
bool "dummy malloc"
diff --git a/common/Makefile b/common/Makefile
index 382a4f661f67..0777d2030c99 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -40,7 +40,8 @@ obj-$(CONFIG_GLOBALVAR) += globalvar.o
obj-$(CONFIG_GREGORIAN_CALENDER) += date.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_MALLOC_DLMALLOC) += dlmalloc.o
-obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o tlsf.o calloc.o
+obj-$(CONFIG_TLSF) += tlsf.o
+obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o calloc.o
KASAN_SANITIZE_tlsf.o := n
obj-$(CONFIG_MALLOC_DUMMY) += dummy_malloc.o calloc.o
obj-$(CONFIG_MEMINFO) += meminfo.o
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index c75fc8b9811f..6bc915585fbe 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -1,5 +1,11 @@
menu "DMA support"
+config DMA_COHERENT_POOLS
+ bool
+ depends on RISCV
+ select TLSF
+ imply SRAM
+
config MXS_APBH_DMA
tristate "MXS APBH DMA ENGINE"
depends on ARCH_IMX23 || ARCH_IMX28 || ARCH_IMX6
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 49d6d6573f4f..5503a4af0049 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_MXS_APBH_DMA) += apbh_dma.o
obj-$(CONFIG_HAS_DMA) += map.o
+obj-$(CONFIG_DMA_COHERENT_POOLS) += coherent-pool.o
diff --git a/drivers/dma/coherent-pool.c b/drivers/dma/coherent-pool.c
new file mode 100644
index 000000000000..524283be711f
--- /dev/null
+++ b/drivers/dma/coherent-pool.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#define pr_fmt(fmt) "dma-coherent-pool: " fmt
+
+#include <common.h>
+#include <asm/dma.h>
+#include <linux/list.h>
+#include <errno.h>
+#include <tlsf.h>
+
+struct dma_coherent_pool {
+ tlsf_t handle;
+ const struct resource *resource;
+ struct list_head list;
+};
+
+static LIST_HEAD(pools);
+
+static void *pool_alloc_coherent(size_t size, dma_addr_t *dma_handle)
+{
+ struct dma_coherent_pool *pool;
+ void *ret = NULL;
+
+ list_for_each_entry(pool, &pools, list) {
+ ret = tlsf_memalign(pool->handle, DMA_ALIGNMENT, size);
+ if (!ret)
+ continue;
+ }
+
+ BUG_ON(!ret);
+
+ memset(ret, 0, size);
+
+ if (dma_handle)
+ *dma_handle = (dma_addr_t)ret;
+
+ pr_debug("alloc(%zu) == %p\n", size, ret);
+
+ return ret;
+}
+
+static void pool_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size)
+{
+ resource_size_t addr = (resource_size_t)vaddr;
+ struct dma_coherent_pool *pool;
+
+ list_for_each_entry(pool, &pools, list) {
+ if (pool->resource->start <= addr && addr <= pool->resource->end) {
+ tlsf_free(pool->handle, vaddr);
+ return;
+ }
+ }
+
+ pr_warn("freeing invalid region: %p\n", vaddr);
+}
+
+static const struct dma_coherent_ops pool_ops = {
+ .alloc = pool_alloc_coherent,
+ .free = pool_free_coherent,
+};
+
+static int compare_pool_sizes(struct list_head *_a, struct list_head *_b)
+{
+ struct dma_coherent_pool *a = list_entry(_a, struct dma_coherent_pool, list);
+ struct dma_coherent_pool *b = list_entry(_b, struct dma_coherent_pool, list);
+
+ if (resource_size(a->resource) > resource_size(b->resource))
+ return 1;
+ if (resource_size(a->resource) < resource_size(b->resource))
+ return -1;
+ return 0;
+}
+
+static int dma_declare_coherent_pool(const struct resource *res)
+{
+ struct dma_coherent_pool *pool;
+ tlsf_t handle;
+
+ handle = tlsf_create_with_pool((void *)res->start, resource_size(res));
+ if (!handle)
+ return -EINVAL;
+
+ pool = xmalloc(sizeof(*pool));
+ pool->handle = handle;
+ pool->resource = res;
+
+ list_add_sort(&pool->list, &pools, compare_pool_sizes);
+
+ dma_set_coherent_ops(&pool_ops);
+
+ pr_debug("registered pool @(%llx-%llx)\n", (u64)res->start, (u64)res->end);
+
+ return 0;
+}
+
+static int coherent_dma_pool_probe(struct device_d *dev)
+{
+ struct resource *res;
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ return dma_declare_coherent_pool(res);
+}
+
+static struct of_device_id coherent_dma_pool_dt_ids[] = {
+ { .compatible = "barebox,coherent-dma-pool", },
+ { /* sentinel */ }
+};
+
+static struct driver_d coherent_dma_pool_driver = {
+ .name = "coherent-dma-pool",
+ .probe = coherent_dma_pool_probe,
+ .of_compatible = coherent_dma_pool_dt_ids,
+};
+coredevice_platform_driver(coherent_dma_pool_driver);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 11/20] dma: support marking SRAM for coherent DMA use
2021-05-31 7:38 ` [PATCH 11/20] dma: support marking SRAM for coherent DMA use Ahmad Fatoum
@ 2021-06-07 7:34 ` Sascha Hauer
2021-06-07 7:40 ` Ahmad Fatoum
2021-06-07 7:39 ` Sascha Hauer
1 sibling, 1 reply; 30+ messages in thread
From: Sascha Hauer @ 2021-06-07 7:34 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Mon, May 31, 2021 at 09:38:12AM +0200, Ahmad Fatoum wrote:
> The RISC-V architecture allows overriding the dma_alloc_coherent and
> dma_free_coherent. Allow this to be controlled by device tree.
>
> Cache-coherent SoCs won't need this, but incoherent ones that have
> uncached regions can register them here.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> +static void *pool_alloc_coherent(size_t size, dma_addr_t *dma_handle)
> +{
> + struct dma_coherent_pool *pool;
> + void *ret = NULL;
> +
> + list_for_each_entry(pool, &pools, list) {
> + ret = tlsf_memalign(pool->handle, DMA_ALIGNMENT, size);
> + if (!ret)
> + continue;
> + }
> +
> + BUG_ON(!ret);
Being out of memory is no bug, no?
> +
> + memset(ret, 0, size);
> +
> + if (dma_handle)
> + *dma_handle = (dma_addr_t)ret;
> +
> + pr_debug("alloc(%zu) == %p\n", size, ret);
> +
> + return ret;
> +}
> +
> +static void pool_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size)
> +{
> + resource_size_t addr = (resource_size_t)vaddr;
> + struct dma_coherent_pool *pool;
> +
> + list_for_each_entry(pool, &pools, list) {
> + if (pool->resource->start <= addr && addr <= pool->resource->end) {
Nice :)
I would have written if (addr >= start && addr <= end), but the way you
have written it makes it visually clear from the first sight that addr
should be in that specific range.
> + tlsf_free(pool->handle, vaddr);
> + return;
> + }
> + }
> +
> + pr_warn("freeing invalid region: %p\n", vaddr);
> +}
> +
> +static const struct dma_coherent_ops pool_ops = {
> + .alloc = pool_alloc_coherent,
> + .free = pool_free_coherent,
> +};
> +
> +static int compare_pool_sizes(struct list_head *_a, struct list_head *_b)
> +{
> + struct dma_coherent_pool *a = list_entry(_a, struct dma_coherent_pool, list);
> + struct dma_coherent_pool *b = list_entry(_b, struct dma_coherent_pool, list);
> +
> + if (resource_size(a->resource) > resource_size(b->resource))
> + return 1;
> + if (resource_size(a->resource) < resource_size(b->resource))
> + return -1;
> + return 0;
> +}
> +
> +static int dma_declare_coherent_pool(const struct resource *res)
> +{
> + struct dma_coherent_pool *pool;
> + tlsf_t handle;
> +
> + handle = tlsf_create_with_pool((void *)res->start, resource_size(res));
> + if (!handle)
> + return -EINVAL;
> +
> + pool = xmalloc(sizeof(*pool));
Better xzalloc()? It's too easy to add some element to a structure and
assume that it's initialized.
> + pool->handle = handle;
> + pool->resource = res;
> +
> + list_add_sort(&pool->list, &pools, compare_pool_sizes);
The pools are sorted by their size, but is this a good criterion for the
pools priority?
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 11/20] dma: support marking SRAM for coherent DMA use
2021-06-07 7:34 ` Sascha Hauer
@ 2021-06-07 7:40 ` Ahmad Fatoum
0 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-06-07 7:40 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
Hi,
On 07.06.21 09:34, Sascha Hauer wrote:
> On Mon, May 31, 2021 at 09:38:12AM +0200, Ahmad Fatoum wrote:
>> The RISC-V architecture allows overriding the dma_alloc_coherent and
>> dma_free_coherent. Allow this to be controlled by device tree.
>>
>> Cache-coherent SoCs won't need this, but incoherent ones that have
>> uncached regions can register them here.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>> ---
>> +static void *pool_alloc_coherent(size_t size, dma_addr_t *dma_handle)
>> +{
>> + struct dma_coherent_pool *pool;
>> + void *ret = NULL;
>> +
>> + list_for_each_entry(pool, &pools, list) {
>> + ret = tlsf_memalign(pool->handle, DMA_ALIGNMENT, size);
>> + if (!ret)
>> + continue;
>> + }
>> +
>> + BUG_ON(!ret);
>
> Being out of memory is no bug, no?
It's for dma_alloc_coherent. Other archs use xmemalign and have no handling for
error cases.
>
>> +
>> + memset(ret, 0, size);
>> +
>> + if (dma_handle)
>> + *dma_handle = (dma_addr_t)ret;
>> +
>> + pr_debug("alloc(%zu) == %p\n", size, ret);
>> +
>> + return ret;
>> +}
>> +
>> +static void pool_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size)
>> +{
>> + resource_size_t addr = (resource_size_t)vaddr;
>> + struct dma_coherent_pool *pool;
>> +
>> + list_for_each_entry(pool, &pools, list) {
>> + if (pool->resource->start <= addr && addr <= pool->resource->end) {
>
> Nice :)
> I would have written if (addr >= start && addr <= end), but the way you
> have written it makes it visually clear from the first sight that addr
> should be in that specific range.
Since I posted this series, someone nudged me into a better direction:
Set dma_addr to the cached alias address, which is < 32-bit and return
from alloc_coherent a > 32-bit address within the uncached alias.
As the devices aren't cache coherent, it doesn't matter that the alias they
get is the uncached one.
>
>> + tlsf_free(pool->handle, vaddr);
>> + return;
>> + }
>> + }
>> +
>> + pr_warn("freeing invalid region: %p\n", vaddr);
>> +}
>> +
>> +static const struct dma_coherent_ops pool_ops = {
>> + .alloc = pool_alloc_coherent,
>> + .free = pool_free_coherent,
>> +};
>> +
>> +static int compare_pool_sizes(struct list_head *_a, struct list_head *_b)
>> +{
>> + struct dma_coherent_pool *a = list_entry(_a, struct dma_coherent_pool, list);
>> + struct dma_coherent_pool *b = list_entry(_b, struct dma_coherent_pool, list);
>> +
>> + if (resource_size(a->resource) > resource_size(b->resource))
>> + return 1;
>> + if (resource_size(a->resource) < resource_size(b->resource))
>> + return -1;
>> + return 0;
>> +}
>> +
>> +static int dma_declare_coherent_pool(const struct resource *res)
>> +{
>> + struct dma_coherent_pool *pool;
>> + tlsf_t handle;
>> +
>> + handle = tlsf_create_with_pool((void *)res->start, resource_size(res));
>> + if (!handle)
>> + return -EINVAL;
>> +
>> + pool = xmalloc(sizeof(*pool));
>
> Better xzalloc()? It's too easy to add some element to a structure and
> assume that it's initialized.
>
>> + pool->handle = handle;
>> + pool->resource = res;
>> +
>> + list_add_sort(&pool->list, &pools, compare_pool_sizes);
>
> The pools are sorted by their size, but is this a good criterion for the
> pools priority?
The idea was to have some fixed order, so issues are easier to debug.
With the changes described above, this commit can be replaced.
(The dma_set_ops one before will remain).
Cheers,
Ahmad
>
> Sascha
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 11/20] dma: support marking SRAM for coherent DMA use
2021-05-31 7:38 ` [PATCH 11/20] dma: support marking SRAM for coherent DMA use Ahmad Fatoum
2021-06-07 7:34 ` Sascha Hauer
@ 2021-06-07 7:39 ` Sascha Hauer
1 sibling, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2021-06-07 7:39 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Mon, May 31, 2021 at 09:38:12AM +0200, Ahmad Fatoum wrote:
> The RISC-V architecture allows overriding the dma_alloc_coherent and
> dma_free_coherent. Allow this to be controlled by device tree.
>
> Cache-coherent SoCs won't need this, but incoherent ones that have
> uncached regions can register them here.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> common/Kconfig | 4 ++
> common/Makefile | 3 +-
> drivers/dma/Kconfig | 6 ++
> drivers/dma/Makefile | 1 +
> drivers/dma/coherent-pool.c | 120 ++++++++++++++++++++++++++++++++++++
> 5 files changed, 133 insertions(+), 1 deletion(-)
> create mode 100644 drivers/dma/coherent-pool.c
>
> diff --git a/common/Kconfig b/common/Kconfig
> index ce349d4ebbf6..dbbcbb946fff 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -303,6 +303,9 @@ config EXPERIMENTAL
> bool
> prompt "Prompt for experimental code"
>
> +config TLSF
> + bool
> +
> choice
> prompt "malloc implementation"
>
> @@ -311,6 +314,7 @@ config MALLOC_DLMALLOC
>
> config MALLOC_TLSF
> bool "tlsf"
> + select TLSF
>
> config MALLOC_DUMMY
> bool "dummy malloc"
> diff --git a/common/Makefile b/common/Makefile
> index 382a4f661f67..0777d2030c99 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -40,7 +40,8 @@ obj-$(CONFIG_GLOBALVAR) += globalvar.o
> obj-$(CONFIG_GREGORIAN_CALENDER) += date.o
> obj-$(CONFIG_KALLSYMS) += kallsyms.o
> obj-$(CONFIG_MALLOC_DLMALLOC) += dlmalloc.o
> -obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o tlsf.o calloc.o
> +obj-$(CONFIG_TLSF) += tlsf.o
> +obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o calloc.o
> KASAN_SANITIZE_tlsf.o := n
> obj-$(CONFIG_MALLOC_DUMMY) += dummy_malloc.o calloc.o
> obj-$(CONFIG_MEMINFO) += meminfo.o
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index c75fc8b9811f..6bc915585fbe 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -1,5 +1,11 @@
> menu "DMA support"
>
> +config DMA_COHERENT_POOLS
> + bool
> + depends on RISCV
> + select TLSF
> + imply SRAM
This symbol is invisible and selected when needed. We shouldn't need
this "depends on RISCV"
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 12/20] mci: allocate DMA-able memory
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (10 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 11/20] dma: support marking SRAM for coherent DMA use Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 13/20] mci: allocate sector_buf on demand Ahmad Fatoum
` (7 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Doesn't yet make a difference, but in a future commit, RISC-V will use a
64-bit alignment for the sector buffers by defining a custom dma_alloc.
Prepare for this.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/mci/mci-core.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index a160b9889459..70a8b971ca6d 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -21,6 +21,7 @@
#include <of.h>
#include <linux/err.h>
#include <linux/sizes.h>
+#include <dma.h>
#define MAX_BUFFER_NUMBER 0xffffffff
@@ -1851,7 +1852,7 @@ static int mci_set_probe(struct param_d *param, void *priv)
static int mci_init(void)
{
- sector_buf = xmemalign(32, SECTOR_SIZE);
+ sector_buf = dma_alloc(SECTOR_SIZE);
return 0;
}
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 13/20] mci: allocate sector_buf on demand
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (11 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 12/20] mci: allocate DMA-able memory Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 14/20] dma: allocate 32-byte aligned buffers by default Ahmad Fatoum
` (6 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The MCI core uses a common bounce buffer for unaligned block
reads/writes as well as sd_change_freq. This buffer is allocated at
device initcall level, same as the MMC drivers themselves.
For CONFIG_MCI_STARTUP=y configurations this seems to imply that
sd_change_freq could attempt writing the NULL page. Avoid this
by just allocating the buffer when the first MMC device is registered.
This doesn't solve all issues; so add a comment noting that.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/mci/mci-core.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 70a8b971ca6d..196fecdbd090 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1789,6 +1789,11 @@ static int mci_card_probe(struct mci *mci)
mci->cdevname = basprintf("disk%d", disknum);
}
+ if (!sector_buf)
+ sector_buf = dma_alloc(SECTOR_SIZE);
+
+ /* FIXME we don't check sector_buf against the device dma mask here */
+
rc = mci_startup(mci);
if (rc) {
dev_warn(&mci->dev, "Card's startup fails with %d\n", rc);
@@ -1850,15 +1855,6 @@ static int mci_set_probe(struct param_d *param, void *priv)
return 0;
}
-static int mci_init(void)
-{
- sector_buf = dma_alloc(SECTOR_SIZE);
-
- return 0;
-}
-
-device_initcall(mci_init);
-
int mci_detect_card(struct mci_host *host)
{
int rc;
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 14/20] dma: allocate 32-byte aligned buffers by default
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (12 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 13/20] mci: allocate sector_buf on demand Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 15/20] mci: dw_mmc: enable use on 64-bit CPUs Ahmad Fatoum
` (5 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
If dma_alloc() is really used for streaming-dma between cache-incoherent
masters, it should return cache-line aligned buffers, so we don't risk
invalidating shared cache lines. Bump up the default alignment to 32-bytes.
This doesn't affect ARM, as it defines its own implementation with
64-byte buffers.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/dma.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/dma.h b/include/dma.h
index 1b1cb3a40796..90f9254ea80f 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -8,6 +8,7 @@
#include <malloc.h>
#include <xfuncs.h>
+#include <linux/kernel.h>
#include <dma-dir.h>
#include <asm/dma.h>
@@ -15,10 +16,14 @@
#define DMA_ADDRESS_BROKEN NULL
+#ifndef DMA_ALIGNMENT
+#define DMA_ALIGNMENT 32
+#endif
+
#ifndef dma_alloc
static inline void *dma_alloc(size_t size)
{
- return xmalloc(size);
+ return xmemalign(DMA_ALIGNMENT, ALIGN(size, DMA_ALIGNMENT));
}
#endif
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 15/20] mci: dw_mmc: enable use on 64-bit CPUs
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (13 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 14/20] dma: allocate 32-byte aligned buffers by default Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 16/20] mci: dw_mmc: match against generic "snps, dw-mshc" compatible Ahmad Fatoum
` (4 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Provided that all DMA addresses can be safely truncated to 32-bit, the
driver is already usable on 64-bit CPUs. Silence the warnings and add
a check to ensure that coherent DMA addresses are indeed 32-bit.
arch code will need to make sure that dma_alloc() returns DMA memory
suitable for all DMA masters.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/mci/dw_mmc.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c
index 7979568841fc..db8aa9473458 100644
--- a/drivers/mci/dw_mmc.c
+++ b/drivers/mci/dw_mmc.c
@@ -124,12 +124,12 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host,
dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET);
- dwmci_writel(host, DWMCI_DBADDR, (uint32_t)desc);
+ dwmci_writel(host, DWMCI_DBADDR, virt_to_phys(desc));
if (data->flags & MMC_DATA_READ)
- start_addr = (uint32_t)data->dest;
+ start_addr = virt_to_phys(data->dest);
else
- start_addr = (uint32_t)data->src;
+ start_addr = virt_to_phys((void *)data->src);
do {
flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH;
@@ -145,7 +145,7 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host,
desc->flags = flags;
desc->cnt = cnt;
desc->addr = start_addr + (i * PAGE_SIZE);
- desc->next_addr = (uint32_t)(desc + 1);
+ desc->next_addr = virt_to_phys(desc + 1);
dev_dbg(host->mci.hw_dev, "desc@ 0x%p 0x%08x 0x%08x 0x%08x 0x%08x\n",
desc, flags, cnt, desc->addr, desc->next_addr);
@@ -290,10 +290,10 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
num_bytes = data->blocks * data->blocksize;
if (data->flags & MMC_DATA_WRITE)
- dma_sync_single_for_device((unsigned long)data->src,
+ dma_sync_single_for_device(virt_to_phys((void *)data->src),
num_bytes, DMA_TO_DEVICE);
else
- dma_sync_single_for_device((unsigned long)data->dest,
+ dma_sync_single_for_device(virt_to_phys(data->dest),
num_bytes, DMA_FROM_DEVICE);
ret = dwmci_prepare_data(host, data);
@@ -400,10 +400,10 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
dwmci_writel(host, DWMCI_CTRL, ctrl);
if (data->flags & MMC_DATA_WRITE)
- dma_sync_single_for_cpu((unsigned long)data->src,
+ dma_sync_single_for_cpu(virt_to_phys((void *)data->src),
num_bytes, DMA_TO_DEVICE);
else
- dma_sync_single_for_cpu((unsigned long)data->dest,
+ dma_sync_single_for_cpu(virt_to_phys(data->dest),
num_bytes, DMA_FROM_DEVICE);
}
}
@@ -547,6 +547,9 @@ static int dw_mmc_probe(struct device_d *dev)
struct resource *iores;
struct dwmci_host *host;
struct dw_mmc_platform_data *pdata = dev->platform_data;
+ dma_addr_t idmac;
+
+ dma_set_mask(dev, DMA_BIT_MASK(32));
host = xzalloc(sizeof(*host));
@@ -567,7 +570,12 @@ static int dw_mmc_probe(struct device_d *dev)
host->ioaddr = IOMEM(iores->start);
host->idmac = dma_alloc_coherent(sizeof(*host->idmac) * DW_MMC_NUM_IDMACS,
- DMA_ADDRESS_BROKEN);
+ &idmac); /* still DMA_ADDRESS_BROKEN */
+
+ if (dma_mapping_error(dev, idmac)) {
+ dev_err(dev, "allocated buffer violates DMA mask\n");
+ return -ENOMEM;
+ }
host->mci.send_cmd = dwmci_cmd;
host->mci.set_ios = dwmci_set_ios;
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 16/20] mci: dw_mmc: match against generic "snps, dw-mshc" compatible
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (14 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 15/20] mci: dw_mmc: enable use on 64-bit CPUs Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 17/20] clk: add initial StarFive clock support Ahmad Fatoum
` (3 subsequent siblings)
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
So far, we only matched against instances of the DesignWare MMC
controller on Rockchip and Altera SoCs. Match against the generic
snps,dw-mshc compatible as well.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/mci/dw_mmc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c
index db8aa9473458..55f2d84a883d 100644
--- a/drivers/mci/dw_mmc.c
+++ b/drivers/mci/dw_mmc.c
@@ -623,6 +623,8 @@ static __maybe_unused struct of_device_id dw_mmc_compatible[] = {
.compatible = "rockchip,rk2928-dw-mshc",
}, {
.compatible = "rockchip,rk3288-dw-mshc",
+ }, {
+ .compatible = "snps,dw-mshc",
}, {
/* sentinel */
}
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 17/20] clk: add initial StarFive clock support
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (15 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 16/20] mci: dw_mmc: match against generic "snps, dw-mshc" compatible Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 8:41 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 18/20] reset: add StarFive reset controller driver Ahmad Fatoum
` (2 subsequent siblings)
19 siblings, 1 reply; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
All clocks seem to share a common format:
struct starfive_clk {
u32 divisor : 24;
u32 mux : 6;
u32 invert : 1;
u32 enable : 1;
};
There is no documentation, what the acceptable divisor values are, but
we could already register gates and muxes, do so for now until
documentation is available.
The bulk of this code has been machine-generated by parsing the macros
in the vendor U-Boot <asm/arch-vic7100/clkgen_ctrl_macro.h>.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/clk/Makefile | 1 +
drivers/clk/starfive/Makefile | 3 +
drivers/clk/starfive/clk.h | 64 ++++
drivers/clk/starfive/jh7100-clkgen.c | 363 ++++++++++++++++++++
include/dt-bindings/clock/starfive-jh7100.h | 203 +++++++++++
5 files changed, 634 insertions(+)
create mode 100644 drivers/clk/starfive/Makefile
create mode 100644 drivers/clk/starfive/clk.h
create mode 100644 drivers/clk/starfive/jh7100-clkgen.c
create mode 100644 include/dt-bindings/clock/starfive-jh7100.h
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index b0be8d1bd89a..499df2fe392b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_MACH_MIPS_LOONGSON)+= loongson/
obj-$(CONFIG_ARCH_LAYERSCAPE) += clk-qoric.o
obj-y += analogbits/
obj-$(CONFIG_CLK_SIFIVE) += sifive/
+obj-$(CONFIG_SOC_STARFIVE) += starfive/
diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
new file mode 100644
index 000000000000..7e4104993580
--- /dev/null
+++ b/drivers/clk/starfive/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOC_STARFIVE_JH7100) += jh7100-clkgen.o
diff --git a/drivers/clk/starfive/clk.h b/drivers/clk/starfive/clk.h
new file mode 100644
index 000000000000..cfbf116dcb78
--- /dev/null
+++ b/drivers/clk/starfive/clk.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef STARFIVE_CLK_H_
+#define STARFIVE_CLK_H_
+
+#include <linux/clk.h>
+
+#define STARFIVE_CLK_ENABLE_SHIFT 31
+#define STARFIVE_CLK_INVERT_SHIFT 30
+#define STARFIVE_CLK_MUX_SHIFT 24
+
+static inline struct clk *starfive_clk_underspecifid(const char *name, const char *parent)
+{
+ /*
+ * TODO With documentation available, all users of this functions can be
+ * migrated to one of the above or to a clk_fixed_factor with
+ * appropriate factor
+ */
+ return clk_fixed_factor(name, parent, 1, 1, 0);
+}
+
+static inline struct clk *starfive_clk_divider(const char *name, const char *parent,
+ void __iomem *reg, u8 width)
+{
+ return starfive_clk_underspecifid(name, parent);
+}
+
+static inline struct clk *starfive_clk_gate(const char *name, const char *parent,
+ void __iomem *reg)
+{
+ return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0);
+}
+
+static inline struct clk *starfive_clk_divider_table(const char *name,
+ const char *parent, void __iomem *reg, u8 width,
+ const struct clk_div_table *table)
+{
+ return clk_divider_table(name, parent, CLK_SET_RATE_PARENT, reg, 0,
+ width, table, 0);
+}
+
+static inline struct clk *starfive_clk_gated_divider(const char *name,
+ const char *parent, void __iomem *reg, u8 width)
+{
+ /* TODO divider part */
+ return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0);
+}
+
+static inline struct clk *starfive_clk_gate_dis(const char *name, const char *parent,
+ void __iomem *reg)
+{
+ return clk_gate_inverted(name, parent, reg, STARFIVE_CLK_INVERT_SHIFT, CLK_SET_RATE_PARENT);
+}
+
+static inline struct clk *starfive_clk_mux(const char *name, void __iomem *reg,
+ u8 width, const char * const *parents, u8 num_parents)
+{
+ return clk_mux(name, 0, reg, STARFIVE_CLK_MUX_SHIFT, width, parents, num_parents, 0);
+}
+
+#endif
diff --git a/drivers/clk/starfive/jh7100-clkgen.c b/drivers/clk/starfive/jh7100-clkgen.c
new file mode 100644
index 000000000000..df5353e8e624
--- /dev/null
+++ b/drivers/clk/starfive/jh7100-clkgen.c
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <dt-bindings/clock/starfive-jh7100.h>
+
+#include "clk.h"
+
+
+static const char *cpundbus_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll1_out",
+ [3] = "pll2_out",
+};
+
+static const char *dla_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll1_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *dsp_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll1_out",
+ [3] = "pll2_out",
+};
+
+static const char *gmacusb_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *perh0_root_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+};
+
+static const char *perh1_root_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "pll2_out",
+};
+
+static const char *vin_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll1_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *vout_root_sels[4] = {
+ [0] = "osc_aud",
+ [1] = "pll0_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *cdechifi4_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll1_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *cdec_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll1_out",
+ [3] = "dummy",
+};
+
+static const char *voutbus_root_sels[4] = {
+ [0] = "osc_aud",
+ [1] = "pll0_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *pll2_refclk_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "osc_aud",
+};
+
+static const char *ddrc0_sels[4] = {
+ [0] = "ddrosc_div2",
+ [1] = "ddrpll_div2",
+ [2] = "ddrpll_div4",
+ [3] = "ddrpll_div8",
+};
+
+static const char *ddrc1_sels[4] = {
+ [0] = "ddrosc_div2",
+ [1] = "ddrpll_div2",
+ [2] = "ddrpll_div4",
+ [3] = "ddrpll_div8",
+};
+
+static const char *nne_bus_sels[2] = {
+ [0] = "cpu_axi",
+ [1] = "nnebus_src1",
+};
+
+static const char *usbphy_25m_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "usbphy_plldiv25m",
+};
+
+static const char *gmac_tx_sels[4] = {
+ [0] = "gmac_gtxclk",
+ [1] = "gmac_mii_txclk",
+ [2] = "gmac_rmii_txclk",
+ [3] = "dummy",
+};
+
+static const char *gmac_rx_pre_sels[2] = {
+ [0] = "gmac_gr_mii_rxclk",
+ [1] = "gmac_rmii_rxclk",
+};
+
+static struct clk *clks[CLK_END];
+
+/* assume osc_sys as direct parent for clocks of yet unknown lineage */
+#define UNKNOWN "osc_sys"
+
+static void starfive_clkgen_init(struct device_node *np, void __iomem *base)
+{
+ clks[CLK_OSC_SYS] = of_clk_get_by_name(np, "osc_sys");
+ clks[CLK_OSC_AUD] = of_clk_get_by_name(np, "osc_aud");
+ clks[CLK_PLL0_OUT] = starfive_clk_underspecifid("pll0_out", "osc_sys");
+ clks[CLK_PLL1_OUT] = starfive_clk_underspecifid("pll1_out", "osc_sys");
+ clks[CLK_PLL2_OUT] = starfive_clk_underspecifid("pll2_out", "pll2_refclk");
+ clks[CLK_CPUNDBUS_ROOT] = starfive_clk_mux("cpundbus_root", base + 0x0, 2, cpundbus_root_sels, ARRAY_SIZE(cpundbus_root_sels));
+ clks[CLK_DLA_ROOT] = starfive_clk_mux("dla_root", base + 0x4, 2, dla_root_sels, ARRAY_SIZE(dla_root_sels));
+ clks[CLK_DSP_ROOT] = starfive_clk_mux("dsp_root", base + 0x8, 2, dsp_root_sels, ARRAY_SIZE(dsp_root_sels));
+ clks[CLK_GMACUSB_ROOT] = starfive_clk_mux("gmacusb_root", base + 0xC, 2, gmacusb_root_sels, ARRAY_SIZE(gmacusb_root_sels));
+ clks[CLK_PERH0_ROOT] = starfive_clk_mux("perh0_root", base + 0x10, 1, perh0_root_sels, ARRAY_SIZE(perh0_root_sels));
+ clks[CLK_PERH1_ROOT] = starfive_clk_mux("perh1_root", base + 0x14, 1, perh1_root_sels, ARRAY_SIZE(perh1_root_sels));
+ clks[CLK_VIN_ROOT] = starfive_clk_mux("vin_root", base + 0x18, 2, vin_root_sels, ARRAY_SIZE(vin_root_sels));
+ clks[CLK_VOUT_ROOT] = starfive_clk_mux("vout_root", base + 0x1C, 2, vout_root_sels, ARRAY_SIZE(vout_root_sels));
+ clks[CLK_AUDIO_ROOT] = starfive_clk_gated_divider("audio_root", UNKNOWN, base + 0x20, 4);
+ clks[CLK_CDECHIFI4_ROOT] = starfive_clk_mux("cdechifi4_root", base + 0x24, 2, cdechifi4_root_sels, ARRAY_SIZE(cdechifi4_root_sels));
+ clks[CLK_CDEC_ROOT] = starfive_clk_mux("cdec_root", base + 0x28, 2, cdec_root_sels, ARRAY_SIZE(cdec_root_sels));
+ clks[CLK_VOUTBUS_ROOT] = starfive_clk_mux("voutbus_root", base + 0x2C, 2, voutbus_root_sels, ARRAY_SIZE(voutbus_root_sels));
+ clks[CLK_CPUNBUS_ROOT_DIV] = starfive_clk_divider("cpunbus_root_div", "cpunbus_root", base + 0x30, 2);
+ clks[CLK_DSP_ROOT_DIV] = starfive_clk_divider("dsp_root_div", "dsp_root", base + 0x34, 3);
+ clks[CLK_PERH0_SRC] = starfive_clk_divider("perh0_src", "perh0_root", base + 0x38, 3);
+ clks[CLK_PERH1_SRC] = starfive_clk_divider("perh1_src", "perh1_root", base + 0x3C, 3);
+ clks[CLK_PLL0_TESTOUT] = starfive_clk_gated_divider("pll0_testout", "pll0_out", base + 0x40, 5);
+ clks[CLK_PLL1_TESTOUT] = starfive_clk_gated_divider("pll1_testout", "pll1_out", base + 0x44, 5);
+ clks[CLK_PLL2_TESTOUT] = starfive_clk_gated_divider("pll2_testout", "pll2_out", base + 0x48, 5);
+ clks[CLK_PLL2_REF] = starfive_clk_mux("pll2_refclk", base + 0x4C, 1, pll2_refclk_sels, ARRAY_SIZE(pll2_refclk_sels));
+ clks[CLK_CPU_CORE] = starfive_clk_divider("cpu_core", UNKNOWN, base + 0x50, 4);
+ clks[CLK_CPU_AXI] = starfive_clk_divider("cpu_axi", UNKNOWN, base + 0x54, 4);
+ clks[CLK_AHB_BUS] = starfive_clk_divider("ahb_bus", UNKNOWN, base + 0x58, 4);
+ clks[CLK_APB1_BUS] = starfive_clk_divider("apb1_bus", UNKNOWN, base + 0x5C, 4);
+ clks[CLK_APB2_BUS] = starfive_clk_divider("apb2_bus", UNKNOWN, base + 0x60, 4);
+ clks[CLK_DOM3AHB_BUS] = starfive_clk_gate("dom3ahb_bus", UNKNOWN, base + 0x64);
+ clks[CLK_DOM7AHB_BUS] = starfive_clk_gate("dom7ahb_bus", UNKNOWN, base + 0x68);
+ clks[CLK_U74_CORE0] = starfive_clk_gate("u74_core0", UNKNOWN, base + 0x6C);
+ clks[CLK_U74_CORE1] = starfive_clk_gated_divider("u74_core1", "", base + 0x70, 4);
+ clks[CLK_U74_AXI] = starfive_clk_gate("u74_axi", UNKNOWN, base + 0x74);
+ clks[CLK_U74RTC_TOGGLE] = starfive_clk_gate("u74rtc_toggle", UNKNOWN, base + 0x78);
+ clks[CLK_SGDMA2P_AXI] = starfive_clk_gate("sgdma2p_axi", UNKNOWN, base + 0x7C);
+ clks[CLK_DMA2PNOC_AXI] = starfive_clk_gate("dma2pnoc_axi", UNKNOWN, base + 0x80);
+ clks[CLK_SGDMA2P_AHB] = starfive_clk_gate("sgdma2p_ahb", UNKNOWN, base + 0x84);
+ clks[CLK_DLA_BUS] = starfive_clk_divider("dla_bus", UNKNOWN, base + 0x88, 3);
+ clks[CLK_DLA_AXI] = starfive_clk_gate("dla_axi", UNKNOWN, base + 0x8C);
+ clks[CLK_DLANOC_AXI] = starfive_clk_gate("dlanoc_axi", UNKNOWN, base + 0x90);
+ clks[CLK_DLA_APB] = starfive_clk_gate("dla_apb", UNKNOWN, base + 0x94);
+ clks[CLK_VP6_CORE] = starfive_clk_gated_divider("vp6_core", UNKNOWN, base + 0x98, 3);
+ clks[CLK_VP6BUS_SRC] = starfive_clk_divider("vp6bus_src", UNKNOWN, base + 0x9C, 3);
+ clks[CLK_VP6_AXI] = starfive_clk_gated_divider("vp6_axi", UNKNOWN, base + 0xA0, 3);
+ clks[CLK_VCDECBUS_SRC] = starfive_clk_divider("vcdecbus_src", UNKNOWN, base + 0xA4, 3);
+ clks[CLK_VDEC_BUS] = starfive_clk_divider("vdec_bus", UNKNOWN, base + 0xA8, 4);
+ clks[CLK_VDEC_AXI] = starfive_clk_gate("vdec_axi", UNKNOWN, base + 0xAC);
+ clks[CLK_VDECBRG_MAIN] = starfive_clk_gate("vdecbrg_mainclk", UNKNOWN, base + 0xB0);
+ clks[CLK_VDEC_BCLK] = starfive_clk_gated_divider("vdec_bclk", UNKNOWN, base + 0xB4, 4);
+ clks[CLK_VDEC_CCLK] = starfive_clk_gated_divider("vdec_cclk", UNKNOWN, base + 0xB8, 4);
+ clks[CLK_VDEC_APB] = starfive_clk_gate("vdec_apb", UNKNOWN, base + 0xBC);
+ clks[CLK_JPEG_AXI] = starfive_clk_gated_divider("jpeg_axi", UNKNOWN, base + 0xC0, 4);
+ clks[CLK_JPEG_CCLK] = starfive_clk_gated_divider("jpeg_cclk", UNKNOWN, base + 0xC4, 4);
+ clks[CLK_JPEG_APB] = starfive_clk_gate("jpeg_apb", UNKNOWN, base + 0xC8);
+ clks[CLK_GC300_2X] = starfive_clk_gated_divider("gc300_2x", UNKNOWN, base + 0xCC, 4);
+ clks[CLK_GC300_AHB] = starfive_clk_gate("gc300_ahb", UNKNOWN, base + 0xD0);
+ clks[CLK_JPCGC300_AXIBUS] = starfive_clk_divider("jpcgc300_axibus", UNKNOWN, base + 0xD4, 4);
+ clks[CLK_GC300_AXI] = starfive_clk_gate("gc300_axi", UNKNOWN, base + 0xD8);
+ clks[CLK_JPCGC300_MAIN] = starfive_clk_gate("jpcgc300_mainclk", UNKNOWN, base + 0xDC);
+ clks[CLK_VENC_BUS] = starfive_clk_divider("venc_bus", UNKNOWN, base + 0xE0, 4);
+ clks[CLK_VENC_AXI] = starfive_clk_gate("venc_axi", UNKNOWN, base + 0xE4);
+ clks[CLK_VENCBRG_MAIN] = starfive_clk_gate("vencbrg_mainclk", UNKNOWN, base + 0xE8);
+ clks[CLK_VENC_BCLK] = starfive_clk_gated_divider("venc_bclk", UNKNOWN, base + 0xEC, 4);
+ clks[CLK_VENC_CCLK] = starfive_clk_gated_divider("venc_cclk", UNKNOWN, base + 0xF0, 4);
+ clks[CLK_VENC_APB] = starfive_clk_gate("venc_apb", UNKNOWN, base + 0xF4);
+ clks[CLK_DDRPLL_DIV2] = starfive_clk_gated_divider("ddrpll_div2", UNKNOWN, base + 0xF8, 2);
+ clks[CLK_DDRPLL_DIV4] = starfive_clk_gated_divider("ddrpll_div4", UNKNOWN, base + 0xFC, 2);
+ clks[CLK_DDRPLL_DIV8] = starfive_clk_gated_divider("ddrpll_div8", UNKNOWN, base + 0x100, 2);
+ clks[CLK_DDROSC_DIV2] = starfive_clk_gated_divider("ddrosc_div2", UNKNOWN, base + 0x104, 2);
+ clks[CLK_DDRC0] = starfive_clk_mux("ddrc0", base + 0x108, 2, ddrc0_sels, ARRAY_SIZE(ddrc0_sels));
+ clks[CLK_DDRC1] = starfive_clk_mux("ddrc1", base + 0x10C, 2, ddrc1_sels, ARRAY_SIZE(ddrc1_sels));
+ clks[CLK_DDRPHY_APB] = starfive_clk_gate("ddrphy_apb", UNKNOWN, base + 0x110);
+ clks[CLK_NOC_ROB] = starfive_clk_divider("noc_rob", UNKNOWN, base + 0x114, 4);
+ clks[CLK_NOC_COG] = starfive_clk_divider("noc_cog", UNKNOWN, base + 0x118, 4);
+ clks[CLK_NNE_AHB] = starfive_clk_gate("nne_ahb", UNKNOWN, base + 0x11C);
+ clks[CLK_NNEBUS_SRC1] = starfive_clk_divider("nnebus_src1", UNKNOWN, base + 0x120, 3);
+ clks[CLK_NNE_BUS] = starfive_clk_mux("nne_bus", base + 0x124, 2, nne_bus_sels, ARRAY_SIZE(nne_bus_sels));
+ clks[CLK_NNE_AXI] = starfive_clk_gate("nne_axi", UNKNOWN, base + 0x128);
+ clks[CLK_NNENOC_AXI] = starfive_clk_gate("nnenoc_axi", UNKNOWN, base + 0x12C);
+ clks[CLK_DLASLV_AXI] = starfive_clk_gate("dlaslv_axi", UNKNOWN, base + 0x130);
+ clks[CLK_DSPX2C_AXI] = starfive_clk_gate("dspx2c_axi", UNKNOWN, base + 0x134);
+ clks[CLK_HIFI4_SRC] = starfive_clk_divider("hifi4_src", UNKNOWN, base + 0x138, 3);
+ clks[CLK_HIFI4_COREFREE] = starfive_clk_divider("hifi4_corefree", UNKNOWN, base + 0x13C, 4);
+ clks[CLK_HIFI4_CORE] = starfive_clk_gate("hifi4_core", UNKNOWN, base + 0x140);
+ clks[CLK_HIFI4_BUS] = starfive_clk_divider("hifi4_bus", UNKNOWN, base + 0x144, 4);
+ clks[CLK_HIFI4_AXI] = starfive_clk_gate("hifi4_axi", UNKNOWN, base + 0x148);
+ clks[CLK_HIFI4NOC_AXI] = starfive_clk_gate("hifi4noc_axi", UNKNOWN, base + 0x14C);
+ clks[CLK_SGDMA1P_BUS] = starfive_clk_divider("sgdma1p_bus", UNKNOWN, base + 0x150, 4);
+ clks[CLK_SGDMA1P_AXI] = starfive_clk_gate("sgdma1p_axi", UNKNOWN, base + 0x154);
+ clks[CLK_DMA1P_AXI] = starfive_clk_gate("dma1p_axi", UNKNOWN, base + 0x158);
+ clks[CLK_X2C_AXI] = starfive_clk_gated_divider("x2c_axi", UNKNOWN, base + 0x15C, 4);
+ clks[CLK_USB_BUS] = starfive_clk_divider("usb_bus", UNKNOWN, base + 0x160, 4);
+ clks[CLK_USB_AXI] = starfive_clk_gate("usb_axi", UNKNOWN, base + 0x164);
+ clks[CLK_USBNOC_AXI] = starfive_clk_gate("usbnoc_axi", UNKNOWN, base + 0x168);
+ clks[CLK_USBPHY_ROOTDIV] = starfive_clk_divider("usbphy_rootdiv", UNKNOWN, base + 0x16C, 3);
+ clks[CLK_USBPHY_125M] = starfive_clk_gated_divider("usbphy_125m", UNKNOWN, base + 0x170, 4);
+ clks[CLK_USBPHY_PLLDIV25M] = starfive_clk_gated_divider("usbphy_plldiv25m", UNKNOWN, base + 0x174, 6);
+ clks[CLK_USBPHY_25M] = starfive_clk_mux("usbphy_25m", base + 0x178, 1, usbphy_25m_sels, ARRAY_SIZE(usbphy_25m_sels));
+ clks[CLK_AUDIO_DIV] = starfive_clk_divider("audio_div", UNKNOWN, base + 0x17C, 18);
+ clks[CLK_AUDIO_SRC] = starfive_clk_gate("audio_src", UNKNOWN, base + 0x180);
+ clks[CLK_AUDIO_12288] = starfive_clk_gate("audio_12288", UNKNOWN, base + 0x184);
+ clks[CLK_VIN_SRC] = starfive_clk_gated_divider("vin_src", UNKNOWN, base + 0x188, 3);
+ clks[CLK_ISP0_BUS] = starfive_clk_divider("isp0_bus", UNKNOWN, base + 0x18C, 4);
+ clks[CLK_ISP0_AXI] = starfive_clk_gate("isp0_axi", UNKNOWN, base + 0x190);
+ clks[CLK_ISP0NOC_AXI] = starfive_clk_gate("isp0noc_axi", UNKNOWN, base + 0x194);
+ clks[CLK_ISPSLV_AXI] = starfive_clk_gate("ispslv_axi", UNKNOWN, base + 0x198);
+ clks[CLK_ISP1_BUS] = starfive_clk_divider("isp1_bus", UNKNOWN, base + 0x19C, 4);
+ clks[CLK_ISP1_AXI] = starfive_clk_gate("isp1_axi", UNKNOWN, base + 0x1A0);
+ clks[CLK_ISP1NOC_AXI] = starfive_clk_gate("isp1noc_axi", UNKNOWN, base + 0x1A4);
+ clks[CLK_VIN_BUS] = starfive_clk_divider("vin_bus", UNKNOWN, base + 0x1A8, 4);
+ clks[CLK_VIN_AXI] = starfive_clk_gate("vin_axi", UNKNOWN, base + 0x1AC);
+ clks[CLK_VINNOC_AXI] = starfive_clk_gate("vinnoc_axi", UNKNOWN, base + 0x1B0);
+ clks[CLK_VOUT_SRC] = starfive_clk_gated_divider("vout_src", UNKNOWN, base + 0x1B4, 3);
+ clks[CLK_DISPBUS_SRC] = starfive_clk_divider("dispbus_src", UNKNOWN, base + 0x1B8, 3);
+ clks[CLK_DISP_BUS] = starfive_clk_divider("disp_bus", UNKNOWN, base + 0x1BC, 3);
+ clks[CLK_DISP_AXI] = starfive_clk_gate("disp_axi", UNKNOWN, base + 0x1C0);
+ clks[CLK_DISPNOC_AXI] = starfive_clk_gate("dispnoc_axi", UNKNOWN, base + 0x1C4);
+ clks[CLK_SDIO0_AHB] = starfive_clk_gate("sdio0_ahb", UNKNOWN, base + 0x1C8);
+ clks[CLK_SDIO0_CCLKINT] = starfive_clk_gated_divider("sdio0_cclkint", UNKNOWN, base + 0x1CC, 5);
+ clks[CLK_SDIO0_CCLKINT_INV] = starfive_clk_gate_dis("sdio0_cclkint_inv", UNKNOWN, base + 0x1D0);
+ clks[CLK_SDIO1_AHB] = starfive_clk_gate("sdio1_ahb", UNKNOWN, base + 0x1D4);
+ clks[CLK_SDIO1_CCLKINT] = starfive_clk_gated_divider("sdio1_cclkint", UNKNOWN, base + 0x1D8, 5);
+ clks[CLK_SDIO1_CCLKINT_INV] = starfive_clk_gate_dis("sdio1_cclkint_inv", UNKNOWN, base + 0x1DC);
+ clks[CLK_GMAC_AHB] = starfive_clk_gate("gmac_ahb", UNKNOWN, base + 0x1E0);
+ clks[CLK_GMAC_ROOT_DIV] = starfive_clk_divider("gmac_root_div", UNKNOWN, base + 0x1E4, 4);
+ clks[CLK_GMAC_PTP_REF] = starfive_clk_gated_divider("gmac_ptp_refclk", UNKNOWN, base + 0x1E8, 5);
+ clks[CLK_GMAC_GTX] = starfive_clk_gated_divider("gmac_gtxclk", UNKNOWN, base + 0x1EC, 8);
+ clks[CLK_GMAC_RMII_TX] = starfive_clk_gated_divider("gmac_rmii_txclk", UNKNOWN, base + 0x1F0, 4);
+ clks[CLK_GMAC_RMII_RX] = starfive_clk_gated_divider("gmac_rmii_rxclk", UNKNOWN, base + 0x1F4, 4);
+ clks[CLK_GMAC_TX] = starfive_clk_mux("gmac_tx", base + 0x1F8, 2, gmac_tx_sels, ARRAY_SIZE(gmac_tx_sels));
+ clks[CLK_GMAC_TX_INV] = starfive_clk_gate_dis("gmac_tx_inv", UNKNOWN, base + 0x1FC);
+ clks[CLK_GMAC_RX_PRE] = starfive_clk_mux("gmac_rx_pre", base + 0x200, 1, gmac_rx_pre_sels, ARRAY_SIZE(gmac_rx_pre_sels));
+ clks[CLK_GMAC_RX_INV] = starfive_clk_gate_dis("gmac_rx_inv", UNKNOWN, base + 0x204);
+ clks[CLK_GMAC_RMII] = starfive_clk_gate("gmac_rmii", UNKNOWN, base + 0x208);
+ clks[CLK_GMAC_TOPHYREF] = starfive_clk_gated_divider("gmac_tophyref", UNKNOWN, base + 0x20C, 7);
+ clks[CLK_SPI2AHB_AHB] = starfive_clk_gate("spi2ahb_ahb", UNKNOWN, base + 0x210);
+ clks[CLK_SPI2AHB_CORE] = starfive_clk_gated_divider("spi2ahb_core", UNKNOWN, base + 0x214, 5);
+ clks[CLK_EZMASTER_AHB] = starfive_clk_gate("ezmaster_ahb", UNKNOWN, base + 0x218);
+ clks[CLK_E24_AHB] = starfive_clk_gate("e24_ahb", UNKNOWN, base + 0x21C);
+ clks[CLK_E24RTC_TOGGLE] = starfive_clk_gate("e24rtc_toggle", UNKNOWN, base + 0x220);
+ clks[CLK_QSPI_AHB] = starfive_clk_gate("qspi_ahb", UNKNOWN, base + 0x224);
+ clks[CLK_QSPI_APB] = starfive_clk_gate("qspi_apb", UNKNOWN, base + 0x228);
+ clks[CLK_QSPI_REF] = starfive_clk_gated_divider("qspi_refclk", UNKNOWN, base + 0x22C, 5);
+ clks[CLK_SEC_AHB] = starfive_clk_gate("sec_ahb", UNKNOWN, base + 0x230);
+ clks[CLK_AES] = starfive_clk_gate("aes_clk", UNKNOWN, base + 0x234);
+ clks[CLK_SHA] = starfive_clk_gate("sha_clk", UNKNOWN, base + 0x238);
+ clks[CLK_PKA] = starfive_clk_gate("pka_clk", UNKNOWN, base + 0x23C);
+ clks[CLK_TRNG_APB] = starfive_clk_gate("trng_apb", UNKNOWN, base + 0x240);
+ clks[CLK_OTP_APB] = starfive_clk_gate("otp_apb", UNKNOWN, base + 0x244);
+ clks[CLK_UART0_APB] = starfive_clk_gate("uart0_apb", UNKNOWN, base + 0x248);
+ clks[CLK_UART0_CORE] = starfive_clk_gated_divider("uart0_core", UNKNOWN, base + 0x24C, 6);
+ clks[CLK_UART1_APB] = starfive_clk_gate("uart1_apb", UNKNOWN, base + 0x250);
+ clks[CLK_UART1_CORE] = starfive_clk_gated_divider("uart1_core", UNKNOWN, base + 0x254, 6);
+ clks[CLK_SPI0_APB] = starfive_clk_gate("spi0_apb", UNKNOWN, base + 0x258);
+ clks[CLK_SPI0_CORE] = starfive_clk_gated_divider("spi0_core", UNKNOWN, base + 0x25C, 6);
+ clks[CLK_SPI1_APB] = starfive_clk_gate("spi1_apb", UNKNOWN, base + 0x260);
+ clks[CLK_SPI1_CORE] = starfive_clk_gated_divider("spi1_core", UNKNOWN, base + 0x264, 6);
+ clks[CLK_I2C0_APB] = starfive_clk_gate("i2c0_apb", UNKNOWN, base + 0x268);
+ clks[CLK_I2C0_CORE] = starfive_clk_gated_divider("i2c0_core", UNKNOWN, base + 0x26C, 6);
+ clks[CLK_I2C1_APB] = starfive_clk_gate("i2c1_apb", UNKNOWN, base + 0x270);
+ clks[CLK_I2C1_CORE] = starfive_clk_gated_divider("i2c1_core", UNKNOWN, base + 0x274, 6);
+ clks[CLK_GPIO_APB] = starfive_clk_gate("gpio_apb", UNKNOWN, base + 0x278);
+ clks[CLK_UART2_APB] = starfive_clk_gate("uart2_apb", UNKNOWN, base + 0x27C);
+ clks[CLK_UART2_CORE] = starfive_clk_gated_divider("uart2_core", UNKNOWN, base + 0x280, 6);
+ clks[CLK_UART3_APB] = starfive_clk_gate("uart3_apb", UNKNOWN, base + 0x284);
+ clks[CLK_UART3_CORE] = starfive_clk_gated_divider("uart3_core", UNKNOWN, base + 0x288, 6);
+ clks[CLK_SPI2_APB] = starfive_clk_gate("spi2_apb", UNKNOWN, base + 0x28C);
+ clks[CLK_SPI2_CORE] = starfive_clk_gated_divider("spi2_core", UNKNOWN, base + 0x290, 6);
+ clks[CLK_SPI3_APB] = starfive_clk_gate("spi3_apb", UNKNOWN, base + 0x294);
+ clks[CLK_SPI3_CORE] = starfive_clk_gated_divider("spi3_core", UNKNOWN, base + 0x298, 6);
+ clks[CLK_I2C2_APB] = starfive_clk_gate("i2c2_apb", UNKNOWN, base + 0x29C);
+ clks[CLK_I2C2_CORE] = starfive_clk_gated_divider("i2c2_core", UNKNOWN, base + 0x2A0, 6);
+ clks[CLK_I2C3_APB] = starfive_clk_gate("i2c3_apb", UNKNOWN, base + 0x2A4);
+ clks[CLK_I2C3_CORE] = starfive_clk_gated_divider("i2c3_core", UNKNOWN, base + 0x2A8, 6);
+ clks[CLK_WDTIMER_APB] = starfive_clk_gate("wdtimer_apb", UNKNOWN, base + 0x2AC);
+ clks[CLK_WDT_CORE] = starfive_clk_gated_divider("wdt_coreclk", UNKNOWN, base + 0x2B0, 6);
+ clks[CLK_TIMER0_CORE] = starfive_clk_gated_divider("timer0_coreclk", UNKNOWN, base + 0x2B4, 6);
+ clks[CLK_TIMER1_CORE] = starfive_clk_gated_divider("timer1_coreclk", UNKNOWN, base + 0x2B8, 6);
+ clks[CLK_TIMER2_CORE] = starfive_clk_gated_divider("timer2_coreclk", UNKNOWN, base + 0x2BC, 6);
+ clks[CLK_TIMER3_CORE] = starfive_clk_gated_divider("timer3_coreclk", UNKNOWN, base + 0x2C0, 6);
+ clks[CLK_TIMER4_CORE] = starfive_clk_gated_divider("timer4_coreclk", UNKNOWN, base + 0x2C4, 6);
+ clks[CLK_TIMER5_CORE] = starfive_clk_gated_divider("timer5_coreclk", UNKNOWN, base + 0x2C8, 6);
+ clks[CLK_TIMER6_CORE] = starfive_clk_gated_divider("timer6_coreclk", UNKNOWN, base + 0x2CC, 6);
+ clks[CLK_VP6INTC_APB] = starfive_clk_gate("vp6intc_apb", UNKNOWN, base + 0x2D0);
+ clks[CLK_PWM_APB] = starfive_clk_gate("pwm_apb", UNKNOWN, base + 0x2D4);
+ clks[CLK_MSI_APB] = starfive_clk_gate("msi_apb", UNKNOWN, base + 0x2D8);
+ clks[CLK_TEMP_APB] = starfive_clk_gate("temp_apb", UNKNOWN, base + 0x2DC);
+ clks[CLK_TEMP_SENSE] = starfive_clk_gated_divider("temp_sense", UNKNOWN, base + 0x2E0, 5);
+ clks[CLK_SYSERR_APB] = starfive_clk_gate("syserr_apb", UNKNOWN, base + 0x2E4);
+}
+
+static struct clk_onecell_data clk_data;
+
+static int starfive_clkgen_clk_probe(struct device_d *dev)
+{
+ struct resource *iores;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ starfive_clkgen_init(dev->device_node, IOMEM(iores->start));
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ &clk_data);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id starfive_clkgen_clk_dt_ids[] = {
+ { .compatible = "starfive,jh7100-clkgen" },
+ { /* sentinel */ }
+};
+
+static struct driver_d starfive_clkgen_clk_driver = {
+ .probe = starfive_clkgen_clk_probe,
+ .name = "starfive-clkgen",
+ .of_compatible = starfive_clkgen_clk_dt_ids,
+};
+core_platform_driver(starfive_clkgen_clk_driver);
diff --git a/include/dt-bindings/clock/starfive-jh7100.h b/include/dt-bindings/clock/starfive-jh7100.h
new file mode 100644
index 000000000000..9ad5e7f9bfd5
--- /dev/null
+++ b/include/dt-bindings/clock/starfive-jh7100.h
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H
+#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H
+
+#define CLK_OSC_SYS 0
+#define CLK_OSC_AUD 1
+#define CLK_PLL0_OUT 2
+#define CLK_PLL1_OUT 3
+#define CLK_PLL2_OUT 4
+#define CLK_CPUNDBUS_ROOT 5
+#define CLK_DLA_ROOT 6
+#define CLK_DSP_ROOT 7
+#define CLK_GMACUSB_ROOT 8
+#define CLK_PERH0_ROOT 9
+#define CLK_PERH1_ROOT 10
+#define CLK_VIN_ROOT 11
+#define CLK_VOUT_ROOT 12
+#define CLK_AUDIO_ROOT 13
+#define CLK_CDECHIFI4_ROOT 14
+#define CLK_CDEC_ROOT 15
+#define CLK_VOUTBUS_ROOT 16
+#define CLK_CPUNBUS_ROOT_DIV 17
+#define CLK_DSP_ROOT_DIV 18
+#define CLK_PERH0_SRC 19
+#define CLK_PERH1_SRC 20
+#define CLK_PLL0_TESTOUT 21
+#define CLK_PLL1_TESTOUT 22
+#define CLK_PLL2_TESTOUT 23
+#define CLK_PLL2_REF 24
+#define CLK_CPU_CORE 25
+#define CLK_CPU_AXI 26
+#define CLK_AHB_BUS 27
+#define CLK_APB1_BUS 28
+#define CLK_APB2_BUS 29
+#define CLK_DOM3AHB_BUS 30
+#define CLK_DOM7AHB_BUS 31
+#define CLK_U74_CORE0 32
+#define CLK_U74_CORE1 33
+#define CLK_U74_AXI 34
+#define CLK_U74RTC_TOGGLE 35
+#define CLK_SGDMA2P_AXI 35
+#define CLK_DMA2PNOC_AXI 37
+#define CLK_SGDMA2P_AHB 37
+#define CLK_DLA_BUS 39
+#define CLK_DLA_AXI 40
+#define CLK_DLANOC_AXI 41
+#define CLK_DLA_APB 42
+#define CLK_VP6_CORE 43
+#define CLK_VP6BUS_SRC 44
+#define CLK_VP6_AXI 45
+#define CLK_VCDECBUS_SRC 46
+#define CLK_VDEC_BUS 47
+#define CLK_VDEC_AXI 48
+#define CLK_VDECBRG_MAIN 49
+#define CLK_VDEC_BCLK 50
+#define CLK_VDEC_CCLK 51
+#define CLK_VDEC_APB 52
+#define CLK_JPEG_AXI 53
+#define CLK_JPEG_CCLK 54
+#define CLK_JPEG_APB 55
+#define CLK_GC300_2X 56
+#define CLK_GC300_AHB 57
+#define CLK_JPCGC300_AXIBUS 58
+#define CLK_GC300_AXI 59
+#define CLK_JPCGC300_MAIN 60
+#define CLK_VENC_BUS 61
+#define CLK_VENC_AXI 62
+#define CLK_VENCBRG_MAIN 63
+#define CLK_VENC_BCLK 64
+#define CLK_VENC_CCLK 65
+#define CLK_VENC_APB 66
+#define CLK_DDRPLL_DIV2 67
+#define CLK_DDRPLL_DIV4 68
+#define CLK_DDRPLL_DIV8 69
+#define CLK_DDROSC_DIV2 70
+#define CLK_DDRC0 71
+#define CLK_DDRC1 72
+#define CLK_DDRPHY_APB 73
+#define CLK_NOC_ROB 74
+#define CLK_NOC_COG 75
+#define CLK_NNE_AHB 76
+#define CLK_NNEBUS_SRC1 77
+#define CLK_NNE_BUS 78
+#define CLK_NNE_AXI 79
+#define CLK_NNENOC_AXI 80
+#define CLK_DLASLV_AXI 81
+#define CLK_DSPX2C_AXI 82
+#define CLK_HIFI4_SRC 83
+#define CLK_HIFI4_COREFREE 84
+#define CLK_HIFI4_CORE 85
+#define CLK_HIFI4_BUS 86
+#define CLK_HIFI4_AXI 87
+#define CLK_HIFI4NOC_AXI 88
+#define CLK_SGDMA1P_BUS 89
+#define CLK_SGDMA1P_AXI 90
+#define CLK_DMA1P_AXI 91
+#define CLK_X2C_AXI 92
+#define CLK_USB_BUS 93
+#define CLK_USB_AXI 94
+#define CLK_USBNOC_AXI 95
+#define CLK_USBPHY_ROOTDIV 96
+#define CLK_USBPHY_125M 97
+#define CLK_USBPHY_PLLDIV25M 98
+#define CLK_USBPHY_25M 99
+#define CLK_AUDIO_DIV 100
+#define CLK_AUDIO_SRC 101
+#define CLK_AUDIO_12288 102
+#define CLK_VIN_SRC 103
+#define CLK_ISP0_BUS 104
+#define CLK_ISP0_AXI 105
+#define CLK_ISP0NOC_AXI 106
+#define CLK_ISPSLV_AXI 107
+#define CLK_ISP1_BUS 108
+#define CLK_ISP1_AXI 109
+#define CLK_ISP1NOC_AXI 110
+#define CLK_VIN_BUS 111
+#define CLK_VIN_AXI 112
+#define CLK_VINNOC_AXI 113
+#define CLK_VOUT_SRC 114
+#define CLK_DISPBUS_SRC 115
+#define CLK_DISP_BUS 116
+#define CLK_DISP_AXI 117
+#define CLK_DISPNOC_AXI 118
+#define CLK_SDIO0_AHB 119
+#define CLK_SDIO0_CCLKINT 120
+#define CLK_SDIO0_CCLKINT_INV 121
+#define CLK_SDIO1_AHB 122
+#define CLK_SDIO1_CCLKINT 123
+#define CLK_SDIO1_CCLKINT_INV 124
+#define CLK_GMAC_AHB 125
+#define CLK_GMAC_ROOT_DIV 126
+#define CLK_GMAC_PTP_REF 127
+#define CLK_GMAC_GTX 128
+#define CLK_GMAC_RMII_TX 129
+#define CLK_GMAC_RMII_RX 130
+#define CLK_GMAC_TX 131
+#define CLK_GMAC_TX_INV 132
+#define CLK_GMAC_RX_PRE 133
+#define CLK_GMAC_RX_INV 134
+#define CLK_GMAC_RMII 135
+#define CLK_GMAC_TOPHYREF 136
+#define CLK_SPI2AHB_AHB 137
+#define CLK_SPI2AHB_CORE 138
+#define CLK_EZMASTER_AHB 139
+#define CLK_E24_AHB 140
+#define CLK_E24RTC_TOGGLE 141
+#define CLK_QSPI_AHB 142
+#define CLK_QSPI_APB 143
+#define CLK_QSPI_REF 144
+#define CLK_SEC_AHB 145
+#define CLK_AES 146
+#define CLK_SHA 147
+#define CLK_PKA 148
+#define CLK_TRNG_APB 149
+#define CLK_OTP_APB 150
+#define CLK_UART0_APB 151
+#define CLK_UART0_CORE 152
+#define CLK_UART1_APB 153
+#define CLK_UART1_CORE 154
+#define CLK_SPI0_APB 155
+#define CLK_SPI0_CORE 156
+#define CLK_SPI1_APB 157
+#define CLK_SPI1_CORE 158
+#define CLK_I2C0_APB 159
+#define CLK_I2C0_CORE 160
+#define CLK_I2C1_APB 161
+#define CLK_I2C1_CORE 162
+#define CLK_GPIO_APB 163
+#define CLK_UART2_APB 164
+#define CLK_UART2_CORE 165
+#define CLK_UART3_APB 166
+#define CLK_UART3_CORE 167
+#define CLK_SPI2_APB 168
+#define CLK_SPI2_CORE 169
+#define CLK_SPI3_APB 170
+#define CLK_SPI3_CORE 171
+#define CLK_I2C2_APB 172
+#define CLK_I2C2_CORE 173
+#define CLK_I2C3_APB 174
+#define CLK_I2C3_CORE 175
+#define CLK_WDTIMER_APB 176
+#define CLK_WDT_CORE 177
+#define CLK_TIMER0_CORE 178
+#define CLK_TIMER1_CORE 179
+#define CLK_TIMER2_CORE 180
+#define CLK_TIMER3_CORE 181
+#define CLK_TIMER4_CORE 182
+#define CLK_TIMER5_CORE 183
+#define CLK_TIMER6_CORE 184
+#define CLK_VP6INTC_APB 185
+#define CLK_PWM_APB 186
+#define CLK_MSI_APB 187
+#define CLK_TEMP_APB 188
+#define CLK_TEMP_SENSE 189
+#define CLK_SYSERR_APB 190
+
+#define CLK_END 191
+
+#endif
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 17/20] clk: add initial StarFive clock support
2021-05-31 7:38 ` [PATCH 17/20] clk: add initial StarFive clock support Ahmad Fatoum
@ 2021-05-31 8:41 ` Ahmad Fatoum
0 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 8:41 UTC (permalink / raw)
To: barebox
On 31.05.21 09:38, Ahmad Fatoum wrote:
> All clocks seem to share a common format:
>
> struct starfive_clk {
> u32 divisor : 24;
> u32 mux : 6;
> u32 invert : 1;
> u32 enable : 1;
> };
>
> There is no documentation, what the acceptable divisor values are, but
> we could already register gates and muxes, do so for now until
> documentation is available.
>
> The bulk of this code has been machine-generated by parsing the macros
> in the vendor U-Boot <asm/arch-vic7100/clkgen_ctrl_macro.h>.
If someone's curious:
https://gist.github.com/a3f/085ea5d58e3bf3e5536e441b1a45f0ce
Advising to rinse your eyes afterwards.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> drivers/clk/Makefile | 1 +
> drivers/clk/starfive/Makefile | 3 +
> drivers/clk/starfive/clk.h | 64 ++++
> drivers/clk/starfive/jh7100-clkgen.c | 363 ++++++++++++++++++++
> include/dt-bindings/clock/starfive-jh7100.h | 203 +++++++++++
> 5 files changed, 634 insertions(+)
> create mode 100644 drivers/clk/starfive/Makefile
> create mode 100644 drivers/clk/starfive/clk.h
> create mode 100644 drivers/clk/starfive/jh7100-clkgen.c
> create mode 100644 include/dt-bindings/clock/starfive-jh7100.h
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index b0be8d1bd89a..499df2fe392b 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -23,3 +23,4 @@ obj-$(CONFIG_MACH_MIPS_LOONGSON)+= loongson/
> obj-$(CONFIG_ARCH_LAYERSCAPE) += clk-qoric.o
> obj-y += analogbits/
> obj-$(CONFIG_CLK_SIFIVE) += sifive/
> +obj-$(CONFIG_SOC_STARFIVE) += starfive/
> diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
> new file mode 100644
> index 000000000000..7e4104993580
> --- /dev/null
> +++ b/drivers/clk/starfive/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_SOC_STARFIVE_JH7100) += jh7100-clkgen.o
> diff --git a/drivers/clk/starfive/clk.h b/drivers/clk/starfive/clk.h
> new file mode 100644
> index 000000000000..cfbf116dcb78
> --- /dev/null
> +++ b/drivers/clk/starfive/clk.h
> @@ -0,0 +1,64 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2021 Ahmad Fatoum, Pengutronix
> + */
> +
> +#ifndef STARFIVE_CLK_H_
> +#define STARFIVE_CLK_H_
> +
> +#include <linux/clk.h>
> +
> +#define STARFIVE_CLK_ENABLE_SHIFT 31
> +#define STARFIVE_CLK_INVERT_SHIFT 30
> +#define STARFIVE_CLK_MUX_SHIFT 24
> +
> +static inline struct clk *starfive_clk_underspecifid(const char *name, const char *parent)
> +{
> + /*
> + * TODO With documentation available, all users of this functions can be
> + * migrated to one of the above or to a clk_fixed_factor with
> + * appropriate factor
> + */
> + return clk_fixed_factor(name, parent, 1, 1, 0);
> +}
> +
> +static inline struct clk *starfive_clk_divider(const char *name, const char *parent,
> + void __iomem *reg, u8 width)
> +{
> + return starfive_clk_underspecifid(name, parent);
> +}
> +
> +static inline struct clk *starfive_clk_gate(const char *name, const char *parent,
> + void __iomem *reg)
> +{
> + return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0);
> +}
> +
> +static inline struct clk *starfive_clk_divider_table(const char *name,
> + const char *parent, void __iomem *reg, u8 width,
> + const struct clk_div_table *table)
> +{
> + return clk_divider_table(name, parent, CLK_SET_RATE_PARENT, reg, 0,
> + width, table, 0);
> +}
> +
> +static inline struct clk *starfive_clk_gated_divider(const char *name,
> + const char *parent, void __iomem *reg, u8 width)
> +{
> + /* TODO divider part */
> + return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0);
> +}
> +
> +static inline struct clk *starfive_clk_gate_dis(const char *name, const char *parent,
> + void __iomem *reg)
> +{
> + return clk_gate_inverted(name, parent, reg, STARFIVE_CLK_INVERT_SHIFT, CLK_SET_RATE_PARENT);
> +}
> +
> +static inline struct clk *starfive_clk_mux(const char *name, void __iomem *reg,
> + u8 width, const char * const *parents, u8 num_parents)
> +{
> + return clk_mux(name, 0, reg, STARFIVE_CLK_MUX_SHIFT, width, parents, num_parents, 0);
> +}
> +
> +#endif
> diff --git a/drivers/clk/starfive/jh7100-clkgen.c b/drivers/clk/starfive/jh7100-clkgen.c
> new file mode 100644
> index 000000000000..df5353e8e624
> --- /dev/null
> +++ b/drivers/clk/starfive/jh7100-clkgen.c
> @@ -0,0 +1,363 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2021 Ahmad Fatoum, Pengutronix
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <driver.h>
> +#include <linux/clk.h>
> +#include <io.h>
> +#include <of.h>
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <dt-bindings/clock/starfive-jh7100.h>
> +
> +#include "clk.h"
> +
> +
> +static const char *cpundbus_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll0_out",
> + [2] = "pll1_out",
> + [3] = "pll2_out",
> +};
> +
> +static const char *dla_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll1_out",
> + [2] = "pll2_out",
> + [3] = "dummy",
> +};
> +
> +static const char *dsp_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll0_out",
> + [2] = "pll1_out",
> + [3] = "pll2_out",
> +};
> +
> +static const char *gmacusb_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll0_out",
> + [2] = "pll2_out",
> + [3] = "dummy",
> +};
> +
> +static const char *perh0_root_sels[2] = {
> + [0] = "osc_sys",
> + [1] = "pll0_out",
> +};
> +
> +static const char *perh1_root_sels[2] = {
> + [0] = "osc_sys",
> + [1] = "pll2_out",
> +};
> +
> +static const char *vin_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll1_out",
> + [2] = "pll2_out",
> + [3] = "dummy",
> +};
> +
> +static const char *vout_root_sels[4] = {
> + [0] = "osc_aud",
> + [1] = "pll0_out",
> + [2] = "pll2_out",
> + [3] = "dummy",
> +};
> +
> +static const char *cdechifi4_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll1_out",
> + [2] = "pll2_out",
> + [3] = "dummy",
> +};
> +
> +static const char *cdec_root_sels[4] = {
> + [0] = "osc_sys",
> + [1] = "pll0_out",
> + [2] = "pll1_out",
> + [3] = "dummy",
> +};
> +
> +static const char *voutbus_root_sels[4] = {
> + [0] = "osc_aud",
> + [1] = "pll0_out",
> + [2] = "pll2_out",
> + [3] = "dummy",
> +};
> +
> +static const char *pll2_refclk_sels[2] = {
> + [0] = "osc_sys",
> + [1] = "osc_aud",
> +};
> +
> +static const char *ddrc0_sels[4] = {
> + [0] = "ddrosc_div2",
> + [1] = "ddrpll_div2",
> + [2] = "ddrpll_div4",
> + [3] = "ddrpll_div8",
> +};
> +
> +static const char *ddrc1_sels[4] = {
> + [0] = "ddrosc_div2",
> + [1] = "ddrpll_div2",
> + [2] = "ddrpll_div4",
> + [3] = "ddrpll_div8",
> +};
> +
> +static const char *nne_bus_sels[2] = {
> + [0] = "cpu_axi",
> + [1] = "nnebus_src1",
> +};
> +
> +static const char *usbphy_25m_sels[2] = {
> + [0] = "osc_sys",
> + [1] = "usbphy_plldiv25m",
> +};
> +
> +static const char *gmac_tx_sels[4] = {
> + [0] = "gmac_gtxclk",
> + [1] = "gmac_mii_txclk",
> + [2] = "gmac_rmii_txclk",
> + [3] = "dummy",
> +};
> +
> +static const char *gmac_rx_pre_sels[2] = {
> + [0] = "gmac_gr_mii_rxclk",
> + [1] = "gmac_rmii_rxclk",
> +};
> +
> +static struct clk *clks[CLK_END];
> +
> +/* assume osc_sys as direct parent for clocks of yet unknown lineage */
> +#define UNKNOWN "osc_sys"
> +
> +static void starfive_clkgen_init(struct device_node *np, void __iomem *base)
> +{
> + clks[CLK_OSC_SYS] = of_clk_get_by_name(np, "osc_sys");
> + clks[CLK_OSC_AUD] = of_clk_get_by_name(np, "osc_aud");
> + clks[CLK_PLL0_OUT] = starfive_clk_underspecifid("pll0_out", "osc_sys");
> + clks[CLK_PLL1_OUT] = starfive_clk_underspecifid("pll1_out", "osc_sys");
> + clks[CLK_PLL2_OUT] = starfive_clk_underspecifid("pll2_out", "pll2_refclk");
> + clks[CLK_CPUNDBUS_ROOT] = starfive_clk_mux("cpundbus_root", base + 0x0, 2, cpundbus_root_sels, ARRAY_SIZE(cpundbus_root_sels));
> + clks[CLK_DLA_ROOT] = starfive_clk_mux("dla_root", base + 0x4, 2, dla_root_sels, ARRAY_SIZE(dla_root_sels));
> + clks[CLK_DSP_ROOT] = starfive_clk_mux("dsp_root", base + 0x8, 2, dsp_root_sels, ARRAY_SIZE(dsp_root_sels));
> + clks[CLK_GMACUSB_ROOT] = starfive_clk_mux("gmacusb_root", base + 0xC, 2, gmacusb_root_sels, ARRAY_SIZE(gmacusb_root_sels));
> + clks[CLK_PERH0_ROOT] = starfive_clk_mux("perh0_root", base + 0x10, 1, perh0_root_sels, ARRAY_SIZE(perh0_root_sels));
> + clks[CLK_PERH1_ROOT] = starfive_clk_mux("perh1_root", base + 0x14, 1, perh1_root_sels, ARRAY_SIZE(perh1_root_sels));
> + clks[CLK_VIN_ROOT] = starfive_clk_mux("vin_root", base + 0x18, 2, vin_root_sels, ARRAY_SIZE(vin_root_sels));
> + clks[CLK_VOUT_ROOT] = starfive_clk_mux("vout_root", base + 0x1C, 2, vout_root_sels, ARRAY_SIZE(vout_root_sels));
> + clks[CLK_AUDIO_ROOT] = starfive_clk_gated_divider("audio_root", UNKNOWN, base + 0x20, 4);
> + clks[CLK_CDECHIFI4_ROOT] = starfive_clk_mux("cdechifi4_root", base + 0x24, 2, cdechifi4_root_sels, ARRAY_SIZE(cdechifi4_root_sels));
> + clks[CLK_CDEC_ROOT] = starfive_clk_mux("cdec_root", base + 0x28, 2, cdec_root_sels, ARRAY_SIZE(cdec_root_sels));
> + clks[CLK_VOUTBUS_ROOT] = starfive_clk_mux("voutbus_root", base + 0x2C, 2, voutbus_root_sels, ARRAY_SIZE(voutbus_root_sels));
> + clks[CLK_CPUNBUS_ROOT_DIV] = starfive_clk_divider("cpunbus_root_div", "cpunbus_root", base + 0x30, 2);
> + clks[CLK_DSP_ROOT_DIV] = starfive_clk_divider("dsp_root_div", "dsp_root", base + 0x34, 3);
> + clks[CLK_PERH0_SRC] = starfive_clk_divider("perh0_src", "perh0_root", base + 0x38, 3);
> + clks[CLK_PERH1_SRC] = starfive_clk_divider("perh1_src", "perh1_root", base + 0x3C, 3);
> + clks[CLK_PLL0_TESTOUT] = starfive_clk_gated_divider("pll0_testout", "pll0_out", base + 0x40, 5);
> + clks[CLK_PLL1_TESTOUT] = starfive_clk_gated_divider("pll1_testout", "pll1_out", base + 0x44, 5);
> + clks[CLK_PLL2_TESTOUT] = starfive_clk_gated_divider("pll2_testout", "pll2_out", base + 0x48, 5);
> + clks[CLK_PLL2_REF] = starfive_clk_mux("pll2_refclk", base + 0x4C, 1, pll2_refclk_sels, ARRAY_SIZE(pll2_refclk_sels));
> + clks[CLK_CPU_CORE] = starfive_clk_divider("cpu_core", UNKNOWN, base + 0x50, 4);
> + clks[CLK_CPU_AXI] = starfive_clk_divider("cpu_axi", UNKNOWN, base + 0x54, 4);
> + clks[CLK_AHB_BUS] = starfive_clk_divider("ahb_bus", UNKNOWN, base + 0x58, 4);
> + clks[CLK_APB1_BUS] = starfive_clk_divider("apb1_bus", UNKNOWN, base + 0x5C, 4);
> + clks[CLK_APB2_BUS] = starfive_clk_divider("apb2_bus", UNKNOWN, base + 0x60, 4);
> + clks[CLK_DOM3AHB_BUS] = starfive_clk_gate("dom3ahb_bus", UNKNOWN, base + 0x64);
> + clks[CLK_DOM7AHB_BUS] = starfive_clk_gate("dom7ahb_bus", UNKNOWN, base + 0x68);
> + clks[CLK_U74_CORE0] = starfive_clk_gate("u74_core0", UNKNOWN, base + 0x6C);
> + clks[CLK_U74_CORE1] = starfive_clk_gated_divider("u74_core1", "", base + 0x70, 4);
> + clks[CLK_U74_AXI] = starfive_clk_gate("u74_axi", UNKNOWN, base + 0x74);
> + clks[CLK_U74RTC_TOGGLE] = starfive_clk_gate("u74rtc_toggle", UNKNOWN, base + 0x78);
> + clks[CLK_SGDMA2P_AXI] = starfive_clk_gate("sgdma2p_axi", UNKNOWN, base + 0x7C);
> + clks[CLK_DMA2PNOC_AXI] = starfive_clk_gate("dma2pnoc_axi", UNKNOWN, base + 0x80);
> + clks[CLK_SGDMA2P_AHB] = starfive_clk_gate("sgdma2p_ahb", UNKNOWN, base + 0x84);
> + clks[CLK_DLA_BUS] = starfive_clk_divider("dla_bus", UNKNOWN, base + 0x88, 3);
> + clks[CLK_DLA_AXI] = starfive_clk_gate("dla_axi", UNKNOWN, base + 0x8C);
> + clks[CLK_DLANOC_AXI] = starfive_clk_gate("dlanoc_axi", UNKNOWN, base + 0x90);
> + clks[CLK_DLA_APB] = starfive_clk_gate("dla_apb", UNKNOWN, base + 0x94);
> + clks[CLK_VP6_CORE] = starfive_clk_gated_divider("vp6_core", UNKNOWN, base + 0x98, 3);
> + clks[CLK_VP6BUS_SRC] = starfive_clk_divider("vp6bus_src", UNKNOWN, base + 0x9C, 3);
> + clks[CLK_VP6_AXI] = starfive_clk_gated_divider("vp6_axi", UNKNOWN, base + 0xA0, 3);
> + clks[CLK_VCDECBUS_SRC] = starfive_clk_divider("vcdecbus_src", UNKNOWN, base + 0xA4, 3);
> + clks[CLK_VDEC_BUS] = starfive_clk_divider("vdec_bus", UNKNOWN, base + 0xA8, 4);
> + clks[CLK_VDEC_AXI] = starfive_clk_gate("vdec_axi", UNKNOWN, base + 0xAC);
> + clks[CLK_VDECBRG_MAIN] = starfive_clk_gate("vdecbrg_mainclk", UNKNOWN, base + 0xB0);
> + clks[CLK_VDEC_BCLK] = starfive_clk_gated_divider("vdec_bclk", UNKNOWN, base + 0xB4, 4);
> + clks[CLK_VDEC_CCLK] = starfive_clk_gated_divider("vdec_cclk", UNKNOWN, base + 0xB8, 4);
> + clks[CLK_VDEC_APB] = starfive_clk_gate("vdec_apb", UNKNOWN, base + 0xBC);
> + clks[CLK_JPEG_AXI] = starfive_clk_gated_divider("jpeg_axi", UNKNOWN, base + 0xC0, 4);
> + clks[CLK_JPEG_CCLK] = starfive_clk_gated_divider("jpeg_cclk", UNKNOWN, base + 0xC4, 4);
> + clks[CLK_JPEG_APB] = starfive_clk_gate("jpeg_apb", UNKNOWN, base + 0xC8);
> + clks[CLK_GC300_2X] = starfive_clk_gated_divider("gc300_2x", UNKNOWN, base + 0xCC, 4);
> + clks[CLK_GC300_AHB] = starfive_clk_gate("gc300_ahb", UNKNOWN, base + 0xD0);
> + clks[CLK_JPCGC300_AXIBUS] = starfive_clk_divider("jpcgc300_axibus", UNKNOWN, base + 0xD4, 4);
> + clks[CLK_GC300_AXI] = starfive_clk_gate("gc300_axi", UNKNOWN, base + 0xD8);
> + clks[CLK_JPCGC300_MAIN] = starfive_clk_gate("jpcgc300_mainclk", UNKNOWN, base + 0xDC);
> + clks[CLK_VENC_BUS] = starfive_clk_divider("venc_bus", UNKNOWN, base + 0xE0, 4);
> + clks[CLK_VENC_AXI] = starfive_clk_gate("venc_axi", UNKNOWN, base + 0xE4);
> + clks[CLK_VENCBRG_MAIN] = starfive_clk_gate("vencbrg_mainclk", UNKNOWN, base + 0xE8);
> + clks[CLK_VENC_BCLK] = starfive_clk_gated_divider("venc_bclk", UNKNOWN, base + 0xEC, 4);
> + clks[CLK_VENC_CCLK] = starfive_clk_gated_divider("venc_cclk", UNKNOWN, base + 0xF0, 4);
> + clks[CLK_VENC_APB] = starfive_clk_gate("venc_apb", UNKNOWN, base + 0xF4);
> + clks[CLK_DDRPLL_DIV2] = starfive_clk_gated_divider("ddrpll_div2", UNKNOWN, base + 0xF8, 2);
> + clks[CLK_DDRPLL_DIV4] = starfive_clk_gated_divider("ddrpll_div4", UNKNOWN, base + 0xFC, 2);
> + clks[CLK_DDRPLL_DIV8] = starfive_clk_gated_divider("ddrpll_div8", UNKNOWN, base + 0x100, 2);
> + clks[CLK_DDROSC_DIV2] = starfive_clk_gated_divider("ddrosc_div2", UNKNOWN, base + 0x104, 2);
> + clks[CLK_DDRC0] = starfive_clk_mux("ddrc0", base + 0x108, 2, ddrc0_sels, ARRAY_SIZE(ddrc0_sels));
> + clks[CLK_DDRC1] = starfive_clk_mux("ddrc1", base + 0x10C, 2, ddrc1_sels, ARRAY_SIZE(ddrc1_sels));
> + clks[CLK_DDRPHY_APB] = starfive_clk_gate("ddrphy_apb", UNKNOWN, base + 0x110);
> + clks[CLK_NOC_ROB] = starfive_clk_divider("noc_rob", UNKNOWN, base + 0x114, 4);
> + clks[CLK_NOC_COG] = starfive_clk_divider("noc_cog", UNKNOWN, base + 0x118, 4);
> + clks[CLK_NNE_AHB] = starfive_clk_gate("nne_ahb", UNKNOWN, base + 0x11C);
> + clks[CLK_NNEBUS_SRC1] = starfive_clk_divider("nnebus_src1", UNKNOWN, base + 0x120, 3);
> + clks[CLK_NNE_BUS] = starfive_clk_mux("nne_bus", base + 0x124, 2, nne_bus_sels, ARRAY_SIZE(nne_bus_sels));
> + clks[CLK_NNE_AXI] = starfive_clk_gate("nne_axi", UNKNOWN, base + 0x128);
> + clks[CLK_NNENOC_AXI] = starfive_clk_gate("nnenoc_axi", UNKNOWN, base + 0x12C);
> + clks[CLK_DLASLV_AXI] = starfive_clk_gate("dlaslv_axi", UNKNOWN, base + 0x130);
> + clks[CLK_DSPX2C_AXI] = starfive_clk_gate("dspx2c_axi", UNKNOWN, base + 0x134);
> + clks[CLK_HIFI4_SRC] = starfive_clk_divider("hifi4_src", UNKNOWN, base + 0x138, 3);
> + clks[CLK_HIFI4_COREFREE] = starfive_clk_divider("hifi4_corefree", UNKNOWN, base + 0x13C, 4);
> + clks[CLK_HIFI4_CORE] = starfive_clk_gate("hifi4_core", UNKNOWN, base + 0x140);
> + clks[CLK_HIFI4_BUS] = starfive_clk_divider("hifi4_bus", UNKNOWN, base + 0x144, 4);
> + clks[CLK_HIFI4_AXI] = starfive_clk_gate("hifi4_axi", UNKNOWN, base + 0x148);
> + clks[CLK_HIFI4NOC_AXI] = starfive_clk_gate("hifi4noc_axi", UNKNOWN, base + 0x14C);
> + clks[CLK_SGDMA1P_BUS] = starfive_clk_divider("sgdma1p_bus", UNKNOWN, base + 0x150, 4);
> + clks[CLK_SGDMA1P_AXI] = starfive_clk_gate("sgdma1p_axi", UNKNOWN, base + 0x154);
> + clks[CLK_DMA1P_AXI] = starfive_clk_gate("dma1p_axi", UNKNOWN, base + 0x158);
> + clks[CLK_X2C_AXI] = starfive_clk_gated_divider("x2c_axi", UNKNOWN, base + 0x15C, 4);
> + clks[CLK_USB_BUS] = starfive_clk_divider("usb_bus", UNKNOWN, base + 0x160, 4);
> + clks[CLK_USB_AXI] = starfive_clk_gate("usb_axi", UNKNOWN, base + 0x164);
> + clks[CLK_USBNOC_AXI] = starfive_clk_gate("usbnoc_axi", UNKNOWN, base + 0x168);
> + clks[CLK_USBPHY_ROOTDIV] = starfive_clk_divider("usbphy_rootdiv", UNKNOWN, base + 0x16C, 3);
> + clks[CLK_USBPHY_125M] = starfive_clk_gated_divider("usbphy_125m", UNKNOWN, base + 0x170, 4);
> + clks[CLK_USBPHY_PLLDIV25M] = starfive_clk_gated_divider("usbphy_plldiv25m", UNKNOWN, base + 0x174, 6);
> + clks[CLK_USBPHY_25M] = starfive_clk_mux("usbphy_25m", base + 0x178, 1, usbphy_25m_sels, ARRAY_SIZE(usbphy_25m_sels));
> + clks[CLK_AUDIO_DIV] = starfive_clk_divider("audio_div", UNKNOWN, base + 0x17C, 18);
> + clks[CLK_AUDIO_SRC] = starfive_clk_gate("audio_src", UNKNOWN, base + 0x180);
> + clks[CLK_AUDIO_12288] = starfive_clk_gate("audio_12288", UNKNOWN, base + 0x184);
> + clks[CLK_VIN_SRC] = starfive_clk_gated_divider("vin_src", UNKNOWN, base + 0x188, 3);
> + clks[CLK_ISP0_BUS] = starfive_clk_divider("isp0_bus", UNKNOWN, base + 0x18C, 4);
> + clks[CLK_ISP0_AXI] = starfive_clk_gate("isp0_axi", UNKNOWN, base + 0x190);
> + clks[CLK_ISP0NOC_AXI] = starfive_clk_gate("isp0noc_axi", UNKNOWN, base + 0x194);
> + clks[CLK_ISPSLV_AXI] = starfive_clk_gate("ispslv_axi", UNKNOWN, base + 0x198);
> + clks[CLK_ISP1_BUS] = starfive_clk_divider("isp1_bus", UNKNOWN, base + 0x19C, 4);
> + clks[CLK_ISP1_AXI] = starfive_clk_gate("isp1_axi", UNKNOWN, base + 0x1A0);
> + clks[CLK_ISP1NOC_AXI] = starfive_clk_gate("isp1noc_axi", UNKNOWN, base + 0x1A4);
> + clks[CLK_VIN_BUS] = starfive_clk_divider("vin_bus", UNKNOWN, base + 0x1A8, 4);
> + clks[CLK_VIN_AXI] = starfive_clk_gate("vin_axi", UNKNOWN, base + 0x1AC);
> + clks[CLK_VINNOC_AXI] = starfive_clk_gate("vinnoc_axi", UNKNOWN, base + 0x1B0);
> + clks[CLK_VOUT_SRC] = starfive_clk_gated_divider("vout_src", UNKNOWN, base + 0x1B4, 3);
> + clks[CLK_DISPBUS_SRC] = starfive_clk_divider("dispbus_src", UNKNOWN, base + 0x1B8, 3);
> + clks[CLK_DISP_BUS] = starfive_clk_divider("disp_bus", UNKNOWN, base + 0x1BC, 3);
> + clks[CLK_DISP_AXI] = starfive_clk_gate("disp_axi", UNKNOWN, base + 0x1C0);
> + clks[CLK_DISPNOC_AXI] = starfive_clk_gate("dispnoc_axi", UNKNOWN, base + 0x1C4);
> + clks[CLK_SDIO0_AHB] = starfive_clk_gate("sdio0_ahb", UNKNOWN, base + 0x1C8);
> + clks[CLK_SDIO0_CCLKINT] = starfive_clk_gated_divider("sdio0_cclkint", UNKNOWN, base + 0x1CC, 5);
> + clks[CLK_SDIO0_CCLKINT_INV] = starfive_clk_gate_dis("sdio0_cclkint_inv", UNKNOWN, base + 0x1D0);
> + clks[CLK_SDIO1_AHB] = starfive_clk_gate("sdio1_ahb", UNKNOWN, base + 0x1D4);
> + clks[CLK_SDIO1_CCLKINT] = starfive_clk_gated_divider("sdio1_cclkint", UNKNOWN, base + 0x1D8, 5);
> + clks[CLK_SDIO1_CCLKINT_INV] = starfive_clk_gate_dis("sdio1_cclkint_inv", UNKNOWN, base + 0x1DC);
> + clks[CLK_GMAC_AHB] = starfive_clk_gate("gmac_ahb", UNKNOWN, base + 0x1E0);
> + clks[CLK_GMAC_ROOT_DIV] = starfive_clk_divider("gmac_root_div", UNKNOWN, base + 0x1E4, 4);
> + clks[CLK_GMAC_PTP_REF] = starfive_clk_gated_divider("gmac_ptp_refclk", UNKNOWN, base + 0x1E8, 5);
> + clks[CLK_GMAC_GTX] = starfive_clk_gated_divider("gmac_gtxclk", UNKNOWN, base + 0x1EC, 8);
> + clks[CLK_GMAC_RMII_TX] = starfive_clk_gated_divider("gmac_rmii_txclk", UNKNOWN, base + 0x1F0, 4);
> + clks[CLK_GMAC_RMII_RX] = starfive_clk_gated_divider("gmac_rmii_rxclk", UNKNOWN, base + 0x1F4, 4);
> + clks[CLK_GMAC_TX] = starfive_clk_mux("gmac_tx", base + 0x1F8, 2, gmac_tx_sels, ARRAY_SIZE(gmac_tx_sels));
> + clks[CLK_GMAC_TX_INV] = starfive_clk_gate_dis("gmac_tx_inv", UNKNOWN, base + 0x1FC);
> + clks[CLK_GMAC_RX_PRE] = starfive_clk_mux("gmac_rx_pre", base + 0x200, 1, gmac_rx_pre_sels, ARRAY_SIZE(gmac_rx_pre_sels));
> + clks[CLK_GMAC_RX_INV] = starfive_clk_gate_dis("gmac_rx_inv", UNKNOWN, base + 0x204);
> + clks[CLK_GMAC_RMII] = starfive_clk_gate("gmac_rmii", UNKNOWN, base + 0x208);
> + clks[CLK_GMAC_TOPHYREF] = starfive_clk_gated_divider("gmac_tophyref", UNKNOWN, base + 0x20C, 7);
> + clks[CLK_SPI2AHB_AHB] = starfive_clk_gate("spi2ahb_ahb", UNKNOWN, base + 0x210);
> + clks[CLK_SPI2AHB_CORE] = starfive_clk_gated_divider("spi2ahb_core", UNKNOWN, base + 0x214, 5);
> + clks[CLK_EZMASTER_AHB] = starfive_clk_gate("ezmaster_ahb", UNKNOWN, base + 0x218);
> + clks[CLK_E24_AHB] = starfive_clk_gate("e24_ahb", UNKNOWN, base + 0x21C);
> + clks[CLK_E24RTC_TOGGLE] = starfive_clk_gate("e24rtc_toggle", UNKNOWN, base + 0x220);
> + clks[CLK_QSPI_AHB] = starfive_clk_gate("qspi_ahb", UNKNOWN, base + 0x224);
> + clks[CLK_QSPI_APB] = starfive_clk_gate("qspi_apb", UNKNOWN, base + 0x228);
> + clks[CLK_QSPI_REF] = starfive_clk_gated_divider("qspi_refclk", UNKNOWN, base + 0x22C, 5);
> + clks[CLK_SEC_AHB] = starfive_clk_gate("sec_ahb", UNKNOWN, base + 0x230);
> + clks[CLK_AES] = starfive_clk_gate("aes_clk", UNKNOWN, base + 0x234);
> + clks[CLK_SHA] = starfive_clk_gate("sha_clk", UNKNOWN, base + 0x238);
> + clks[CLK_PKA] = starfive_clk_gate("pka_clk", UNKNOWN, base + 0x23C);
> + clks[CLK_TRNG_APB] = starfive_clk_gate("trng_apb", UNKNOWN, base + 0x240);
> + clks[CLK_OTP_APB] = starfive_clk_gate("otp_apb", UNKNOWN, base + 0x244);
> + clks[CLK_UART0_APB] = starfive_clk_gate("uart0_apb", UNKNOWN, base + 0x248);
> + clks[CLK_UART0_CORE] = starfive_clk_gated_divider("uart0_core", UNKNOWN, base + 0x24C, 6);
> + clks[CLK_UART1_APB] = starfive_clk_gate("uart1_apb", UNKNOWN, base + 0x250);
> + clks[CLK_UART1_CORE] = starfive_clk_gated_divider("uart1_core", UNKNOWN, base + 0x254, 6);
> + clks[CLK_SPI0_APB] = starfive_clk_gate("spi0_apb", UNKNOWN, base + 0x258);
> + clks[CLK_SPI0_CORE] = starfive_clk_gated_divider("spi0_core", UNKNOWN, base + 0x25C, 6);
> + clks[CLK_SPI1_APB] = starfive_clk_gate("spi1_apb", UNKNOWN, base + 0x260);
> + clks[CLK_SPI1_CORE] = starfive_clk_gated_divider("spi1_core", UNKNOWN, base + 0x264, 6);
> + clks[CLK_I2C0_APB] = starfive_clk_gate("i2c0_apb", UNKNOWN, base + 0x268);
> + clks[CLK_I2C0_CORE] = starfive_clk_gated_divider("i2c0_core", UNKNOWN, base + 0x26C, 6);
> + clks[CLK_I2C1_APB] = starfive_clk_gate("i2c1_apb", UNKNOWN, base + 0x270);
> + clks[CLK_I2C1_CORE] = starfive_clk_gated_divider("i2c1_core", UNKNOWN, base + 0x274, 6);
> + clks[CLK_GPIO_APB] = starfive_clk_gate("gpio_apb", UNKNOWN, base + 0x278);
> + clks[CLK_UART2_APB] = starfive_clk_gate("uart2_apb", UNKNOWN, base + 0x27C);
> + clks[CLK_UART2_CORE] = starfive_clk_gated_divider("uart2_core", UNKNOWN, base + 0x280, 6);
> + clks[CLK_UART3_APB] = starfive_clk_gate("uart3_apb", UNKNOWN, base + 0x284);
> + clks[CLK_UART3_CORE] = starfive_clk_gated_divider("uart3_core", UNKNOWN, base + 0x288, 6);
> + clks[CLK_SPI2_APB] = starfive_clk_gate("spi2_apb", UNKNOWN, base + 0x28C);
> + clks[CLK_SPI2_CORE] = starfive_clk_gated_divider("spi2_core", UNKNOWN, base + 0x290, 6);
> + clks[CLK_SPI3_APB] = starfive_clk_gate("spi3_apb", UNKNOWN, base + 0x294);
> + clks[CLK_SPI3_CORE] = starfive_clk_gated_divider("spi3_core", UNKNOWN, base + 0x298, 6);
> + clks[CLK_I2C2_APB] = starfive_clk_gate("i2c2_apb", UNKNOWN, base + 0x29C);
> + clks[CLK_I2C2_CORE] = starfive_clk_gated_divider("i2c2_core", UNKNOWN, base + 0x2A0, 6);
> + clks[CLK_I2C3_APB] = starfive_clk_gate("i2c3_apb", UNKNOWN, base + 0x2A4);
> + clks[CLK_I2C3_CORE] = starfive_clk_gated_divider("i2c3_core", UNKNOWN, base + 0x2A8, 6);
> + clks[CLK_WDTIMER_APB] = starfive_clk_gate("wdtimer_apb", UNKNOWN, base + 0x2AC);
> + clks[CLK_WDT_CORE] = starfive_clk_gated_divider("wdt_coreclk", UNKNOWN, base + 0x2B0, 6);
> + clks[CLK_TIMER0_CORE] = starfive_clk_gated_divider("timer0_coreclk", UNKNOWN, base + 0x2B4, 6);
> + clks[CLK_TIMER1_CORE] = starfive_clk_gated_divider("timer1_coreclk", UNKNOWN, base + 0x2B8, 6);
> + clks[CLK_TIMER2_CORE] = starfive_clk_gated_divider("timer2_coreclk", UNKNOWN, base + 0x2BC, 6);
> + clks[CLK_TIMER3_CORE] = starfive_clk_gated_divider("timer3_coreclk", UNKNOWN, base + 0x2C0, 6);
> + clks[CLK_TIMER4_CORE] = starfive_clk_gated_divider("timer4_coreclk", UNKNOWN, base + 0x2C4, 6);
> + clks[CLK_TIMER5_CORE] = starfive_clk_gated_divider("timer5_coreclk", UNKNOWN, base + 0x2C8, 6);
> + clks[CLK_TIMER6_CORE] = starfive_clk_gated_divider("timer6_coreclk", UNKNOWN, base + 0x2CC, 6);
> + clks[CLK_VP6INTC_APB] = starfive_clk_gate("vp6intc_apb", UNKNOWN, base + 0x2D0);
> + clks[CLK_PWM_APB] = starfive_clk_gate("pwm_apb", UNKNOWN, base + 0x2D4);
> + clks[CLK_MSI_APB] = starfive_clk_gate("msi_apb", UNKNOWN, base + 0x2D8);
> + clks[CLK_TEMP_APB] = starfive_clk_gate("temp_apb", UNKNOWN, base + 0x2DC);
> + clks[CLK_TEMP_SENSE] = starfive_clk_gated_divider("temp_sense", UNKNOWN, base + 0x2E0, 5);
> + clks[CLK_SYSERR_APB] = starfive_clk_gate("syserr_apb", UNKNOWN, base + 0x2E4);
> +}
> +
> +static struct clk_onecell_data clk_data;
> +
> +static int starfive_clkgen_clk_probe(struct device_d *dev)
> +{
> + struct resource *iores;
> +
> + iores = dev_request_mem_resource(dev, 0);
> + if (IS_ERR(iores))
> + return PTR_ERR(iores);
> +
> + starfive_clkgen_init(dev->device_node, IOMEM(iores->start));
> +
> + clk_data.clks = clks;
> + clk_data.clk_num = ARRAY_SIZE(clks);
> + of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
> + &clk_data);
> +
> + return 0;
> +}
> +
> +static __maybe_unused struct of_device_id starfive_clkgen_clk_dt_ids[] = {
> + { .compatible = "starfive,jh7100-clkgen" },
> + { /* sentinel */ }
> +};
> +
> +static struct driver_d starfive_clkgen_clk_driver = {
> + .probe = starfive_clkgen_clk_probe,
> + .name = "starfive-clkgen",
> + .of_compatible = starfive_clkgen_clk_dt_ids,
> +};
> +core_platform_driver(starfive_clkgen_clk_driver);
> diff --git a/include/dt-bindings/clock/starfive-jh7100.h b/include/dt-bindings/clock/starfive-jh7100.h
> new file mode 100644
> index 000000000000..9ad5e7f9bfd5
> --- /dev/null
> +++ b/include/dt-bindings/clock/starfive-jh7100.h
> @@ -0,0 +1,203 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR X11 */
> +/*
> + * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H
> +#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H
> +
> +#define CLK_OSC_SYS 0
> +#define CLK_OSC_AUD 1
> +#define CLK_PLL0_OUT 2
> +#define CLK_PLL1_OUT 3
> +#define CLK_PLL2_OUT 4
> +#define CLK_CPUNDBUS_ROOT 5
> +#define CLK_DLA_ROOT 6
> +#define CLK_DSP_ROOT 7
> +#define CLK_GMACUSB_ROOT 8
> +#define CLK_PERH0_ROOT 9
> +#define CLK_PERH1_ROOT 10
> +#define CLK_VIN_ROOT 11
> +#define CLK_VOUT_ROOT 12
> +#define CLK_AUDIO_ROOT 13
> +#define CLK_CDECHIFI4_ROOT 14
> +#define CLK_CDEC_ROOT 15
> +#define CLK_VOUTBUS_ROOT 16
> +#define CLK_CPUNBUS_ROOT_DIV 17
> +#define CLK_DSP_ROOT_DIV 18
> +#define CLK_PERH0_SRC 19
> +#define CLK_PERH1_SRC 20
> +#define CLK_PLL0_TESTOUT 21
> +#define CLK_PLL1_TESTOUT 22
> +#define CLK_PLL2_TESTOUT 23
> +#define CLK_PLL2_REF 24
> +#define CLK_CPU_CORE 25
> +#define CLK_CPU_AXI 26
> +#define CLK_AHB_BUS 27
> +#define CLK_APB1_BUS 28
> +#define CLK_APB2_BUS 29
> +#define CLK_DOM3AHB_BUS 30
> +#define CLK_DOM7AHB_BUS 31
> +#define CLK_U74_CORE0 32
> +#define CLK_U74_CORE1 33
> +#define CLK_U74_AXI 34
> +#define CLK_U74RTC_TOGGLE 35
> +#define CLK_SGDMA2P_AXI 35
> +#define CLK_DMA2PNOC_AXI 37
> +#define CLK_SGDMA2P_AHB 37
> +#define CLK_DLA_BUS 39
> +#define CLK_DLA_AXI 40
> +#define CLK_DLANOC_AXI 41
> +#define CLK_DLA_APB 42
> +#define CLK_VP6_CORE 43
> +#define CLK_VP6BUS_SRC 44
> +#define CLK_VP6_AXI 45
> +#define CLK_VCDECBUS_SRC 46
> +#define CLK_VDEC_BUS 47
> +#define CLK_VDEC_AXI 48
> +#define CLK_VDECBRG_MAIN 49
> +#define CLK_VDEC_BCLK 50
> +#define CLK_VDEC_CCLK 51
> +#define CLK_VDEC_APB 52
> +#define CLK_JPEG_AXI 53
> +#define CLK_JPEG_CCLK 54
> +#define CLK_JPEG_APB 55
> +#define CLK_GC300_2X 56
> +#define CLK_GC300_AHB 57
> +#define CLK_JPCGC300_AXIBUS 58
> +#define CLK_GC300_AXI 59
> +#define CLK_JPCGC300_MAIN 60
> +#define CLK_VENC_BUS 61
> +#define CLK_VENC_AXI 62
> +#define CLK_VENCBRG_MAIN 63
> +#define CLK_VENC_BCLK 64
> +#define CLK_VENC_CCLK 65
> +#define CLK_VENC_APB 66
> +#define CLK_DDRPLL_DIV2 67
> +#define CLK_DDRPLL_DIV4 68
> +#define CLK_DDRPLL_DIV8 69
> +#define CLK_DDROSC_DIV2 70
> +#define CLK_DDRC0 71
> +#define CLK_DDRC1 72
> +#define CLK_DDRPHY_APB 73
> +#define CLK_NOC_ROB 74
> +#define CLK_NOC_COG 75
> +#define CLK_NNE_AHB 76
> +#define CLK_NNEBUS_SRC1 77
> +#define CLK_NNE_BUS 78
> +#define CLK_NNE_AXI 79
> +#define CLK_NNENOC_AXI 80
> +#define CLK_DLASLV_AXI 81
> +#define CLK_DSPX2C_AXI 82
> +#define CLK_HIFI4_SRC 83
> +#define CLK_HIFI4_COREFREE 84
> +#define CLK_HIFI4_CORE 85
> +#define CLK_HIFI4_BUS 86
> +#define CLK_HIFI4_AXI 87
> +#define CLK_HIFI4NOC_AXI 88
> +#define CLK_SGDMA1P_BUS 89
> +#define CLK_SGDMA1P_AXI 90
> +#define CLK_DMA1P_AXI 91
> +#define CLK_X2C_AXI 92
> +#define CLK_USB_BUS 93
> +#define CLK_USB_AXI 94
> +#define CLK_USBNOC_AXI 95
> +#define CLK_USBPHY_ROOTDIV 96
> +#define CLK_USBPHY_125M 97
> +#define CLK_USBPHY_PLLDIV25M 98
> +#define CLK_USBPHY_25M 99
> +#define CLK_AUDIO_DIV 100
> +#define CLK_AUDIO_SRC 101
> +#define CLK_AUDIO_12288 102
> +#define CLK_VIN_SRC 103
> +#define CLK_ISP0_BUS 104
> +#define CLK_ISP0_AXI 105
> +#define CLK_ISP0NOC_AXI 106
> +#define CLK_ISPSLV_AXI 107
> +#define CLK_ISP1_BUS 108
> +#define CLK_ISP1_AXI 109
> +#define CLK_ISP1NOC_AXI 110
> +#define CLK_VIN_BUS 111
> +#define CLK_VIN_AXI 112
> +#define CLK_VINNOC_AXI 113
> +#define CLK_VOUT_SRC 114
> +#define CLK_DISPBUS_SRC 115
> +#define CLK_DISP_BUS 116
> +#define CLK_DISP_AXI 117
> +#define CLK_DISPNOC_AXI 118
> +#define CLK_SDIO0_AHB 119
> +#define CLK_SDIO0_CCLKINT 120
> +#define CLK_SDIO0_CCLKINT_INV 121
> +#define CLK_SDIO1_AHB 122
> +#define CLK_SDIO1_CCLKINT 123
> +#define CLK_SDIO1_CCLKINT_INV 124
> +#define CLK_GMAC_AHB 125
> +#define CLK_GMAC_ROOT_DIV 126
> +#define CLK_GMAC_PTP_REF 127
> +#define CLK_GMAC_GTX 128
> +#define CLK_GMAC_RMII_TX 129
> +#define CLK_GMAC_RMII_RX 130
> +#define CLK_GMAC_TX 131
> +#define CLK_GMAC_TX_INV 132
> +#define CLK_GMAC_RX_PRE 133
> +#define CLK_GMAC_RX_INV 134
> +#define CLK_GMAC_RMII 135
> +#define CLK_GMAC_TOPHYREF 136
> +#define CLK_SPI2AHB_AHB 137
> +#define CLK_SPI2AHB_CORE 138
> +#define CLK_EZMASTER_AHB 139
> +#define CLK_E24_AHB 140
> +#define CLK_E24RTC_TOGGLE 141
> +#define CLK_QSPI_AHB 142
> +#define CLK_QSPI_APB 143
> +#define CLK_QSPI_REF 144
> +#define CLK_SEC_AHB 145
> +#define CLK_AES 146
> +#define CLK_SHA 147
> +#define CLK_PKA 148
> +#define CLK_TRNG_APB 149
> +#define CLK_OTP_APB 150
> +#define CLK_UART0_APB 151
> +#define CLK_UART0_CORE 152
> +#define CLK_UART1_APB 153
> +#define CLK_UART1_CORE 154
> +#define CLK_SPI0_APB 155
> +#define CLK_SPI0_CORE 156
> +#define CLK_SPI1_APB 157
> +#define CLK_SPI1_CORE 158
> +#define CLK_I2C0_APB 159
> +#define CLK_I2C0_CORE 160
> +#define CLK_I2C1_APB 161
> +#define CLK_I2C1_CORE 162
> +#define CLK_GPIO_APB 163
> +#define CLK_UART2_APB 164
> +#define CLK_UART2_CORE 165
> +#define CLK_UART3_APB 166
> +#define CLK_UART3_CORE 167
> +#define CLK_SPI2_APB 168
> +#define CLK_SPI2_CORE 169
> +#define CLK_SPI3_APB 170
> +#define CLK_SPI3_CORE 171
> +#define CLK_I2C2_APB 172
> +#define CLK_I2C2_CORE 173
> +#define CLK_I2C3_APB 174
> +#define CLK_I2C3_CORE 175
> +#define CLK_WDTIMER_APB 176
> +#define CLK_WDT_CORE 177
> +#define CLK_TIMER0_CORE 178
> +#define CLK_TIMER1_CORE 179
> +#define CLK_TIMER2_CORE 180
> +#define CLK_TIMER3_CORE 181
> +#define CLK_TIMER4_CORE 182
> +#define CLK_TIMER5_CORE 183
> +#define CLK_TIMER6_CORE 184
> +#define CLK_VP6INTC_APB 185
> +#define CLK_PWM_APB 186
> +#define CLK_MSI_APB 187
> +#define CLK_TEMP_APB 188
> +#define CLK_TEMP_SENSE 189
> +#define CLK_SYSERR_APB 190
> +
> +#define CLK_END 191
> +
> +#endif
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 18/20] reset: add StarFive reset controller driver
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (16 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 17/20] clk: add initial StarFive clock support Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-06-07 8:00 ` Sascha Hauer
2021-05-31 7:38 ` [PATCH 19/20] watchdog: add StarFive watchdog driver Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 20/20] hw_random: add driver for RNG on StarFive SoC Ahmad Fatoum
19 siblings, 1 reply; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The StarFive SoC has a single reset controller, which seems to control
reset of all clocks and peripherals. It differs from the ones supported
by the Linux reset-simple driver in that it has a dedicated status
registers that needs to be polled to verify the reset has completed.
Also special is that most resets (> 70) are synchronous. As the reset
status poll would just time out without the clock, have the reset
controller enable the clock as part of the reset. OS can decide later,
which clocks to disable again.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/riscv/Kconfig.socs | 1 +
drivers/reset/Kconfig | 6 +
drivers/reset/Makefile | 1 +
drivers/reset/reset-starfive-vic.c | 204 ++++++++++++++++++
.../reset-controller/starfive-jh7100.h | 126 +++++++++++
include/soc/starfive/rstgen.h | 41 ++++
6 files changed, 379 insertions(+)
create mode 100644 drivers/reset/reset-starfive-vic.c
create mode 100644 include/dt-bindings/reset-controller/starfive-jh7100.h
create mode 100644 include/soc/starfive/rstgen.h
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 3e4cd3cdad59..d2b4a955d1c4 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -52,6 +52,7 @@ endif
config SOC_STARFIVE
bool "StarFive SoCs"
select CLINT_TIMER
+ select ARCH_HAS_RESET_CONTROLLER
help
This enables support for SiFive SoC platform hardware.
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 316ece9e7176..9429f107bb67 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -27,4 +27,10 @@ config RESET_STM32
help
This enables the reset controller driver for STM32MP and STM32 MCUs.
+config RESET_STARFIVE
+ bool "StarFive Controller Driver" if COMPILE_TEST
+ default SOC_STARFIVE
+ help
+ This enables the reset controller driver for the StarFive JH7100.
+
endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 8460c4b154f5..ce494baae58e 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o
obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_STM32) += reset-stm32.o
+obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o
diff --git a/drivers/reset/reset-starfive-vic.c b/drivers/reset/reset-starfive-vic.c
new file mode 100644
index 000000000000..d6a8d0138ab2
--- /dev/null
+++ b/drivers/reset/reset-starfive-vic.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ *
+ * StarFive Reset Controller driver
+ */
+#define pr_fmt(fmt) "reset-starfive: " fmt
+
+#include <common.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/reset-controller.h>
+#include <soc/starfive/rstgen.h>
+#include <dt-bindings/reset-controller/starfive-jh7100.h>
+#include <dt-bindings/clock/starfive-jh7100.h>
+
+struct starfive_rstgen {
+ void __iomem *base;
+ struct reset_controller_dev rcdev;
+ const struct starfive_rstgen_ops *ops;
+ struct device_node *clknp;
+ const int *sync_resets;
+};
+
+static struct starfive_rstgen *to_starfive_rstgen(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct starfive_rstgen, rcdev);
+}
+
+static const int jh7110_rstgen_sync_resets[RSTN_END] = {
+ [RSTN_SGDMA2P_AHB] = CLK_SGDMA2P_AHB,
+ [RSTN_SGDMA2P_AXI] = CLK_SGDMA2P_AXI,
+ [RSTN_DMA2PNOC_AXI] = CLK_DMA2PNOC_AXI,
+ [RSTN_DLA_AXI] = CLK_DLA_AXI,
+ [RSTN_DLANOC_AXI] = CLK_DLANOC_AXI,
+ [RSTN_DLA_APB] = CLK_DLA_APB,
+ [RSTN_VDECBRG_MAIN] = CLK_VDECBRG_MAIN,
+ [RSTN_VDEC_AXI] = CLK_VDEC_AXI,
+ [RSTN_VDEC_BCLK] = CLK_VDEC_BCLK,
+ [RSTN_VDEC_CCLK] = CLK_VDEC_CCLK,
+ [RSTN_VDEC_APB] = CLK_VDEC_APB,
+ [RSTN_JPEG_AXI] = CLK_JPEG_AXI,
+ [RSTN_JPEG_CCLK] = CLK_JPEG_CCLK,
+ [RSTN_JPEG_APB] = CLK_JPEG_APB,
+ [RSTN_JPCGC300_MAIN] = CLK_JPCGC300_MAIN,
+ [RSTN_GC300_2X] = CLK_GC300_2X,
+ [RSTN_GC300_AXI] = CLK_GC300_AXI,
+ [RSTN_GC300_AHB] = CLK_GC300_AHB,
+ [RSTN_VENC_AXI] = CLK_VENC_AXI,
+ [RSTN_VENCBRG_MAIN] = CLK_VENCBRG_MAIN,
+ [RSTN_VENC_BCLK] = CLK_VENC_BCLK,
+ [RSTN_VENC_CCLK] = CLK_VENC_CCLK,
+ [RSTN_VENC_APB] = CLK_VENC_APB,
+ [RSTN_DDRPHY_APB] = CLK_DDRPHY_APB,
+ [RSTN_USB_AXI] = CLK_USB_AXI,
+ [RSTN_SGDMA1P_AXI] = CLK_SGDMA1P_AXI,
+ [RSTN_DMA1P_AXI] = CLK_DMA1P_AXI,
+ [RSTN_NNE_AHB] = CLK_NNE_AHB,
+ [RSTN_NNE_AXI] = CLK_NNE_AXI,
+ [RSTN_NNENOC_AXI] = CLK_NNENOC_AXI,
+ [RSTN_DLASLV_AXI] = CLK_DLASLV_AXI,
+ [RSTN_VOUT_SRC] = CLK_VOUT_SRC,
+ [RSTN_DISP_AXI] = CLK_DISP_AXI,
+ [RSTN_DISPNOC_AXI] = CLK_DISPNOC_AXI,
+ [RSTN_SDIO0_AHB] = CLK_SDIO0_AHB,
+ [RSTN_SDIO1_AHB] = CLK_SDIO1_AHB,
+ [RSTN_GMAC_AHB] = CLK_GMAC_AHB,
+ [RSTN_SPI2AHB_AHB] = CLK_SPI2AHB_AHB,
+ [RSTN_SPI2AHB_CORE] = CLK_SPI2AHB_CORE,
+ [RSTN_EZMASTER_AHB] = CLK_EZMASTER_AHB,
+ [RSTN_SEC_AHB] = CLK_SEC_AHB,
+ [RSTN_AES] = CLK_AES,
+ [RSTN_PKA] = CLK_PKA,
+ [RSTN_SHA] = CLK_SHA,
+ [RSTN_TRNG_APB] = CLK_TRNG_APB,
+ [RSTN_OTP_APB] = CLK_OTP_APB,
+ [RSTN_UART0_APB] = CLK_UART0_APB,
+ [RSTN_UART0_CORE] = CLK_UART0_CORE,
+ [RSTN_UART1_APB] = CLK_UART1_APB,
+ [RSTN_UART1_CORE] = CLK_UART1_CORE,
+ [RSTN_SPI0_APB] = CLK_SPI0_APB,
+ [RSTN_SPI0_CORE] = CLK_SPI0_CORE,
+ [RSTN_SPI1_APB] = CLK_SPI1_APB,
+ [RSTN_SPI1_CORE] = CLK_SPI1_CORE,
+ [RSTN_I2C0_APB] = CLK_I2C0_APB,
+ [RSTN_I2C0_CORE] = CLK_I2C0_CORE,
+ [RSTN_I2C1_APB] = CLK_I2C1_APB,
+ [RSTN_I2C1_CORE] = CLK_I2C1_CORE,
+ [RSTN_GPIO_APB] = CLK_GPIO_APB,
+ [RSTN_UART2_APB] = CLK_UART2_APB,
+ [RSTN_UART2_CORE] = CLK_UART2_CORE,
+ [RSTN_UART3_APB] = CLK_UART3_APB,
+ [RSTN_UART3_CORE] = CLK_UART3_CORE,
+ [RSTN_SPI2_APB] = CLK_SPI2_APB,
+ [RSTN_SPI2_CORE] = CLK_SPI2_CORE,
+ [RSTN_SPI3_APB] = CLK_SPI3_APB,
+ [RSTN_SPI3_CORE] = CLK_SPI3_CORE,
+ [RSTN_I2C2_APB] = CLK_I2C2_APB,
+ [RSTN_I2C2_CORE] = CLK_I2C2_CORE,
+ [RSTN_I2C3_APB] = CLK_I2C3_APB,
+ [RSTN_I2C3_CORE] = CLK_I2C3_CORE,
+ [RSTN_WDTIMER_APB] = CLK_WDTIMER_APB,
+ [RSTN_WDT] = CLK_WDT_CORE,
+ [RSTN_VP6INTC_APB] = CLK_VP6INTC_APB,
+ [RSTN_TEMP_APB] = CLK_TEMP_APB,
+ [RSTN_TEMP_SENSE] = CLK_TEMP_SENSE,
+};
+
+static int starfive_reset_clk_enable(struct starfive_rstgen *priv, unsigned id)
+{
+ struct of_phandle_args clkspec = {
+ .np = priv->clknp,
+ .args_count = 1,
+ };
+
+ if (!priv->sync_resets || !priv->sync_resets[id])
+ return 0;
+
+ clkspec.args[0] = priv->sync_resets[id];
+
+ pr_debug("synchronous reset=%u clk=%u\n", id, priv->sync_resets[id]);
+
+ return clk_enable(of_clk_get_from_provider(&clkspec));
+}
+
+static int starfive_rstgen(struct reset_controller_dev *rcdev, unsigned id, bool assert)
+{
+ struct starfive_rstgen *priv = to_starfive_rstgen(rcdev);
+ void __iomem *base = priv->base;
+
+ starfive_reset_clk_enable(priv, id);
+
+ __starfive_rstgen(base, id, assert);
+ return wait_on_timeout(NSEC_PER_MSEC, __starfive_rstgen_asserted(base, id) == assert);
+}
+
+static int starfive_rstgen_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return starfive_rstgen(rcdev, id, true);
+}
+
+static int starfive_rstgen_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return starfive_rstgen(rcdev, id, false);
+}
+
+static int starfive_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+ int ret;
+
+ ret = starfive_rstgen_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ udelay(2);
+
+ return starfive_rstgen_deassert(rcdev, id);
+}
+
+static const struct reset_control_ops starfive_rstgen_ops = {
+ .assert = starfive_rstgen_assert,
+ .deassert = starfive_rstgen_deassert,
+ .reset = starfive_reset,
+};
+
+static int starfive_rstgen_probe(struct device_d *dev)
+{
+ struct starfive_rstgen *priv;
+ struct resource *iores;
+
+ priv = xzalloc(sizeof(*priv));
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ if ((priv->sync_resets = device_get_match_data(dev))) {
+ priv->clknp = of_find_compatible_node(NULL, NULL, "starfive,jh7100-clkgen");
+ if (!priv->clknp)
+ return -ENODEV;
+ }
+
+ priv->base = IOMEM(iores->start);
+ priv->rcdev.nr_resets = RSTN_END;
+ priv->rcdev.ops = &starfive_rstgen_ops;
+ priv->rcdev.of_node = dev->device_node;
+
+ return reset_controller_register(&priv->rcdev);
+}
+
+static const struct of_device_id starfive_rstgen_reset_dt_ids[] = {
+ { .compatible = "starfive,jh7100-rstgen", .data = jh7110_rstgen_sync_resets },
+ { /* sentinel */ },
+};
+
+static struct driver_d starfive_rstgen_reset_driver = {
+ .name = "starfive_rstgen",
+ .probe = starfive_rstgen_probe,
+ .of_compatible = starfive_rstgen_reset_dt_ids,
+};
+core_platform_driver(starfive_rstgen_reset_driver);
diff --git a/include/dt-bindings/reset-controller/starfive-jh7100.h b/include/dt-bindings/reset-controller/starfive-jh7100.h
new file mode 100644
index 000000000000..390a528576b9
--- /dev/null
+++ b/include/dt-bindings/reset-controller/starfive-jh7100.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_STARFIVE_JH7100
+#define _DT_BINDINGS_RESET_CONTROLLER_STARFIVE_JH7100
+
+#define RSTN_DOM3AHB_BUS 0
+#define RSTN_DOM7AHB_BUS 1
+#define RST_U74 2
+#define RSTN_U74_AXI 3
+#define RSTN_SGDMA2P_AHB 4
+#define RSTN_SGDMA2P_AXI 5
+#define RSTN_DMA2PNOC_AXI 6
+#define RSTN_DLA_AXI 7
+#define RSTN_DLANOC_AXI 8
+#define RSTN_DLA_APB 9
+#define RST_VP6_DRESET 10
+#define RST_VP6_BRESET 11
+#define RSTN_VP6_AXI 12
+#define RSTN_VDECBRG_MAIN 13
+#define RSTN_VDEC_AXI 14
+#define RSTN_VDEC_BCLK 15
+#define RSTN_VDEC_CCLK 16
+#define RSTN_VDEC_APB 17
+#define RSTN_JPEG_AXI 18
+#define RSTN_JPEG_CCLK 19
+#define RSTN_JPEG_APB 20
+#define RSTN_JPCGC300_MAIN 21
+#define RSTN_GC300_2X 22
+#define RSTN_GC300_AXI 23
+#define RSTN_GC300_AHB 24
+#define RSTN_VENC_AXI 25
+#define RSTN_VENCBRG_MAIN 26
+#define RSTN_VENC_BCLK 27
+#define RSTN_VENC_CCLK 28
+#define RSTN_VENC_APB 29
+#define RSTN_DDRPHY_APB 30
+#define RSTN_NOC_ROB 31
+#define RSTN_NOC_COG 32
+#define RSTN_HIFI4_AXI 33
+#define RSTN_HIFI4NOC_AXI 34
+#define RST_HIFI4_drESET 35
+#define RST_HIFI4_bRESET 36
+#define RSTN_USB_AXI 37
+#define RSTN_USBNOC_AXI 38
+#define RSTN_SGDMA1P_AXI 39
+#define RSTN_DMA1P_AXI 40
+#define RSTN_X2C_AXI 41
+#define RSTN_NNE_AHB 42
+#define RSTN_NNE_AXI 43
+#define RSTN_NNENOC_AXI 44
+#define RSTN_DLASLV_AXI 45
+#define RSTN_DSPX2C_AXI 46
+#define RSTN_VIN_SRC 47
+#define RSTN_ISPSLV_AXI 48
+#define RSTN_VIN_AXI 49
+#define RSTN_VINNOC_AXI 50
+#define RSTN_ISP0_AXI 51
+#define RSTN_ISP0NOC_AXI 52
+#define RSTN_ISP1_AXI 53
+#define RSTN_ISP1NOC_AXI 54
+#define RSTN_VOUT_SRC 55
+#define RSTN_DISP_AXI 56
+#define RSTN_DISPNOC_AXI 57
+#define RSTN_SDIO0_AHB 58
+#define RSTN_SDIO1_AHB 59
+#define RSTN_GMAC_AHB 60
+#define RSTN_SPI2AHB_AHB 61
+#define RSTN_SPI2AHB_CORE 62
+#define RSTN_EZMASTER_AHB 63
+#define RST_E24 64
+#define RSTN_QSPI_AHB 65
+#define RSTN_QSPI_CORE 66
+#define RSTN_QSPI_APB 67
+#define RSTN_SEC_AHB 68
+#define RSTN_AES 69
+#define RSTN_PKA 70
+#define RSTN_SHA 71
+#define RSTN_TRNG_APB 72
+#define RSTN_OTP_APB 73
+#define RSTN_UART0_APB 74
+#define RSTN_UART0_CORE 75
+#define RSTN_UART1_APB 76
+#define RSTN_UART1_CORE 77
+#define RSTN_SPI0_APB 78
+#define RSTN_SPI0_CORE 79
+#define RSTN_SPI1_APB 80
+#define RSTN_SPI1_CORE 81
+#define RSTN_I2C0_APB 82
+#define RSTN_I2C0_CORE 83
+#define RSTN_I2C1_APB 84
+#define RSTN_I2C1_CORE 85
+#define RSTN_GPIO_APB 86
+#define RSTN_UART2_APB 87
+#define RSTN_UART2_CORE 88
+#define RSTN_UART3_APB 89
+#define RSTN_UART3_CORE 90
+#define RSTN_SPI2_APB 91
+#define RSTN_SPI2_CORE 92
+#define RSTN_SPI3_APB 93
+#define RSTN_SPI3_CORE 94
+#define RSTN_I2C2_APB 95
+#define RSTN_I2C2_CORE 96
+#define RSTN_I2C3_APB 97
+#define RSTN_I2C3_CORE 98
+#define RSTN_WDTIMER_APB 99
+#define RSTN_WDT 100
+#define RSTN_TIMER0 101
+#define RSTN_TIMER1 102
+#define RSTN_TIMER2 103
+#define RSTN_TIMER3 104
+#define RSTN_TIMER4 105
+#define RSTN_TIMER5 106
+#define RSTN_TIMER6 107
+#define RSTN_VP6INTC_APB 108
+#define RSTN_PWM_APB 109
+#define RSTN_MSI_APB 110
+#define RSTN_TEMP_APB 111
+#define RSTN_TEMP_SENSE 112
+#define RSTN_SYSERR_APB 113
+
+#define RSTN_END 114
+
+#endif
diff --git a/include/soc/starfive/rstgen.h b/include/soc/starfive/rstgen.h
new file mode 100644
index 000000000000..7a674aabe9f2
--- /dev/null
+++ b/include/soc/starfive/rstgen.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SOC_STARFIVE_RSTGEN_H_
+#define __SOC_STARFIVE_RSTGEN_H_
+
+#include <dt-bindings/reset-controller/starfive-jh7100.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+#define STARFIVE_RSTGEN_STATUS 0x10
+
+static inline void __iomem *starfive_rstgen_bank(void __iomem *base, unsigned long *id)
+{
+ void __iomem *bank = base + *id / (4 * BITS_PER_BYTE) * 4;
+ *id %= 4 * BITS_PER_BYTE;
+ return bank;
+}
+
+static inline void __starfive_rstgen(void __iomem *base, unsigned long id, bool assert)
+{
+ void __iomem *bank = starfive_rstgen_bank(base, &id);
+ u32 val;
+
+ val = readl(bank);
+
+ if (assert)
+ val |= BIT(id);
+ else
+ val &= ~BIT(id);
+
+ writel(val, bank);
+}
+
+static bool __starfive_rstgen_asserted(void __iomem *base, unsigned long id)
+{
+ void __iomem *bank = starfive_rstgen_bank(base, &id);
+
+ return !(readl(bank + STARFIVE_RSTGEN_STATUS) & BIT(id));
+}
+
+#endif
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 18/20] reset: add StarFive reset controller driver
2021-05-31 7:38 ` [PATCH 18/20] reset: add StarFive reset controller driver Ahmad Fatoum
@ 2021-06-07 8:00 ` Sascha Hauer
0 siblings, 0 replies; 30+ messages in thread
From: Sascha Hauer @ 2021-06-07 8:00 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Mon, May 31, 2021 at 09:38:19AM +0200, Ahmad Fatoum wrote:
> The StarFive SoC has a single reset controller, which seems to control
> reset of all clocks and peripherals. It differs from the ones supported
> by the Linux reset-simple driver in that it has a dedicated status
> registers that needs to be polled to verify the reset has completed.
>
> Also special is that most resets (> 70) are synchronous. As the reset
> status poll would just time out without the clock, have the reset
> controller enable the clock as part of the reset. OS can decide later,
> which clocks to disable again.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> arch/riscv/Kconfig.socs | 1 +
> drivers/reset/Kconfig | 6 +
> drivers/reset/Makefile | 1 +
> drivers/reset/reset-starfive-vic.c | 204 ++++++++++++++++++
> .../reset-controller/starfive-jh7100.h | 126 +++++++++++
> include/soc/starfive/rstgen.h | 41 ++++
> 6 files changed, 379 insertions(+)
> create mode 100644 drivers/reset/reset-starfive-vic.c
> create mode 100644 include/dt-bindings/reset-controller/starfive-jh7100.h
> create mode 100644 include/soc/starfive/rstgen.h
>
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 3e4cd3cdad59..d2b4a955d1c4 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -52,6 +52,7 @@ endif
> config SOC_STARFIVE
> bool "StarFive SoCs"
> select CLINT_TIMER
> + select ARCH_HAS_RESET_CONTROLLER
> help
> This enables support for SiFive SoC platform hardware.
>
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 316ece9e7176..9429f107bb67 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -27,4 +27,10 @@ config RESET_STM32
> help
> This enables the reset controller driver for STM32MP and STM32 MCUs.
>
> +config RESET_STARFIVE
> + bool "StarFive Controller Driver" if COMPILE_TEST
> + default SOC_STARFIVE
> + help
> + This enables the reset controller driver for the StarFive JH7100.
> +
> endif
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 8460c4b154f5..ce494baae58e 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -2,3 +2,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o
> obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
> obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
> obj-$(CONFIG_RESET_STM32) += reset-stm32.o
> +obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o
> diff --git a/drivers/reset/reset-starfive-vic.c b/drivers/reset/reset-starfive-vic.c
> new file mode 100644
> index 000000000000..d6a8d0138ab2
> --- /dev/null
> +++ b/drivers/reset/reset-starfive-vic.c
> @@ -0,0 +1,204 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
> + *
> + * StarFive Reset Controller driver
> + */
> +#define pr_fmt(fmt) "reset-starfive: " fmt
> +
> +#include <common.h>
> +#include <init.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/reset-controller.h>
> +#include <soc/starfive/rstgen.h>
> +#include <dt-bindings/reset-controller/starfive-jh7100.h>
> +#include <dt-bindings/clock/starfive-jh7100.h>
> +
> +struct starfive_rstgen {
> + void __iomem *base;
> + struct reset_controller_dev rcdev;
> + const struct starfive_rstgen_ops *ops;
> + struct device_node *clknp;
> + const int *sync_resets;
> +};
> +
> +static struct starfive_rstgen *to_starfive_rstgen(struct reset_controller_dev *rcdev)
> +{
> + return container_of(rcdev, struct starfive_rstgen, rcdev);
> +}
> +
> +static const int jh7110_rstgen_sync_resets[RSTN_END] = {
> + [RSTN_SGDMA2P_AHB] = CLK_SGDMA2P_AHB,
> + [RSTN_SGDMA2P_AXI] = CLK_SGDMA2P_AXI,
> + [RSTN_DMA2PNOC_AXI] = CLK_DMA2PNOC_AXI,
> + [RSTN_DLA_AXI] = CLK_DLA_AXI,
> + [RSTN_DLANOC_AXI] = CLK_DLANOC_AXI,
> + [RSTN_DLA_APB] = CLK_DLA_APB,
> + [RSTN_VDECBRG_MAIN] = CLK_VDECBRG_MAIN,
> + [RSTN_VDEC_AXI] = CLK_VDEC_AXI,
> + [RSTN_VDEC_BCLK] = CLK_VDEC_BCLK,
> + [RSTN_VDEC_CCLK] = CLK_VDEC_CCLK,
> + [RSTN_VDEC_APB] = CLK_VDEC_APB,
> + [RSTN_JPEG_AXI] = CLK_JPEG_AXI,
> + [RSTN_JPEG_CCLK] = CLK_JPEG_CCLK,
> + [RSTN_JPEG_APB] = CLK_JPEG_APB,
> + [RSTN_JPCGC300_MAIN] = CLK_JPCGC300_MAIN,
> + [RSTN_GC300_2X] = CLK_GC300_2X,
> + [RSTN_GC300_AXI] = CLK_GC300_AXI,
> + [RSTN_GC300_AHB] = CLK_GC300_AHB,
> + [RSTN_VENC_AXI] = CLK_VENC_AXI,
> + [RSTN_VENCBRG_MAIN] = CLK_VENCBRG_MAIN,
> + [RSTN_VENC_BCLK] = CLK_VENC_BCLK,
> + [RSTN_VENC_CCLK] = CLK_VENC_CCLK,
> + [RSTN_VENC_APB] = CLK_VENC_APB,
> + [RSTN_DDRPHY_APB] = CLK_DDRPHY_APB,
> + [RSTN_USB_AXI] = CLK_USB_AXI,
> + [RSTN_SGDMA1P_AXI] = CLK_SGDMA1P_AXI,
> + [RSTN_DMA1P_AXI] = CLK_DMA1P_AXI,
> + [RSTN_NNE_AHB] = CLK_NNE_AHB,
> + [RSTN_NNE_AXI] = CLK_NNE_AXI,
> + [RSTN_NNENOC_AXI] = CLK_NNENOC_AXI,
> + [RSTN_DLASLV_AXI] = CLK_DLASLV_AXI,
> + [RSTN_VOUT_SRC] = CLK_VOUT_SRC,
> + [RSTN_DISP_AXI] = CLK_DISP_AXI,
> + [RSTN_DISPNOC_AXI] = CLK_DISPNOC_AXI,
> + [RSTN_SDIO0_AHB] = CLK_SDIO0_AHB,
> + [RSTN_SDIO1_AHB] = CLK_SDIO1_AHB,
> + [RSTN_GMAC_AHB] = CLK_GMAC_AHB,
> + [RSTN_SPI2AHB_AHB] = CLK_SPI2AHB_AHB,
> + [RSTN_SPI2AHB_CORE] = CLK_SPI2AHB_CORE,
> + [RSTN_EZMASTER_AHB] = CLK_EZMASTER_AHB,
> + [RSTN_SEC_AHB] = CLK_SEC_AHB,
> + [RSTN_AES] = CLK_AES,
> + [RSTN_PKA] = CLK_PKA,
> + [RSTN_SHA] = CLK_SHA,
> + [RSTN_TRNG_APB] = CLK_TRNG_APB,
> + [RSTN_OTP_APB] = CLK_OTP_APB,
> + [RSTN_UART0_APB] = CLK_UART0_APB,
> + [RSTN_UART0_CORE] = CLK_UART0_CORE,
> + [RSTN_UART1_APB] = CLK_UART1_APB,
> + [RSTN_UART1_CORE] = CLK_UART1_CORE,
> + [RSTN_SPI0_APB] = CLK_SPI0_APB,
> + [RSTN_SPI0_CORE] = CLK_SPI0_CORE,
> + [RSTN_SPI1_APB] = CLK_SPI1_APB,
> + [RSTN_SPI1_CORE] = CLK_SPI1_CORE,
> + [RSTN_I2C0_APB] = CLK_I2C0_APB,
> + [RSTN_I2C0_CORE] = CLK_I2C0_CORE,
> + [RSTN_I2C1_APB] = CLK_I2C1_APB,
> + [RSTN_I2C1_CORE] = CLK_I2C1_CORE,
> + [RSTN_GPIO_APB] = CLK_GPIO_APB,
> + [RSTN_UART2_APB] = CLK_UART2_APB,
> + [RSTN_UART2_CORE] = CLK_UART2_CORE,
> + [RSTN_UART3_APB] = CLK_UART3_APB,
> + [RSTN_UART3_CORE] = CLK_UART3_CORE,
> + [RSTN_SPI2_APB] = CLK_SPI2_APB,
> + [RSTN_SPI2_CORE] = CLK_SPI2_CORE,
> + [RSTN_SPI3_APB] = CLK_SPI3_APB,
> + [RSTN_SPI3_CORE] = CLK_SPI3_CORE,
> + [RSTN_I2C2_APB] = CLK_I2C2_APB,
> + [RSTN_I2C2_CORE] = CLK_I2C2_CORE,
> + [RSTN_I2C3_APB] = CLK_I2C3_APB,
> + [RSTN_I2C3_CORE] = CLK_I2C3_CORE,
> + [RSTN_WDTIMER_APB] = CLK_WDTIMER_APB,
> + [RSTN_WDT] = CLK_WDT_CORE,
> + [RSTN_VP6INTC_APB] = CLK_VP6INTC_APB,
> + [RSTN_TEMP_APB] = CLK_TEMP_APB,
> + [RSTN_TEMP_SENSE] = CLK_TEMP_SENSE,
> +};
> +
> +static int starfive_reset_clk_enable(struct starfive_rstgen *priv, unsigned id)
> +{
> + struct of_phandle_args clkspec = {
> + .np = priv->clknp,
> + .args_count = 1,
> + };
> +
> + if (!priv->sync_resets || !priv->sync_resets[id])
> + return 0;
> +
> + clkspec.args[0] = priv->sync_resets[id];
> +
> + pr_debug("synchronous reset=%u clk=%u\n", id, priv->sync_resets[id]);
> +
> + return clk_enable(of_clk_get_from_provider(&clkspec));
This clock is enabled twice per reset cycle and never disabled. It
should be balanced or enabled only once.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 19/20] watchdog: add StarFive watchdog driver
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (17 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 18/20] reset: add StarFive reset controller driver Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
2021-05-31 7:38 ` [PATCH 20/20] hw_random: add driver for RNG on StarFive SoC Ahmad Fatoum
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/watchdog/Kconfig | 7 +++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/starfive_wdt.c | 97 +++++++++++++++++++++++++++++++++
3 files changed, 105 insertions(+)
create mode 100644 drivers/watchdog/starfive_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 542659825045..8aeca0bd6f5f 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -148,4 +148,11 @@ config ITCO_WDT
NO_REBOOT flag which prevents the watchdog from rebooting the
machine.
+config STARFIVE_WDT
+ tristate "StarFive Watchdog Timer"
+ depends on SOC_STARFIVE && OFDEVICE
+ help
+ If you say yes here you get support for the watchdog device
+ on StarFive SoCs.
+
endif
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 0b598af40218..4e784b5aaa30 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o
obj-$(CONFIG_GPIO_WATCHDOG) += gpio_wdt.o
obj-$(CONFIG_ITCO_WDT) += itco_wdt.o
+obj-$(CONFIG_STARFIVE_WDT) += starfive_wdt.o
diff --git a/drivers/watchdog/starfive_wdt.c b/drivers/watchdog/starfive_wdt.c
new file mode 100644
index 000000000000..abe20f7a1a82
--- /dev/null
+++ b/drivers/watchdog/starfive_wdt.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Kalray Inc.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <watchdog.h>
+#include <linux/reset.h>
+
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#define WDT_REG_RESET_EN 0x104
+#define WDT_REG_TIMEOUT 0x108
+#define WDT_REG_CONTROL 0x110
+#define WDT_REG_UNLOCK 0x13c
+
+#define WDT_UNLOCK_KEY 0x378f0765
+
+struct starfive_wdt {
+ uint32_t clk_rate;
+ struct watchdog wdd;
+ void __iomem *base;
+ bool setup;
+};
+
+static int starfive_wdt_set_timeout(struct watchdog *wdd, unsigned int timeout)
+{
+ struct starfive_wdt *wd = container_of(wdd, struct starfive_wdt, wdd);
+
+ writel(0, wd->base + WDT_REG_CONTROL);
+
+ if (timeout > 0) {
+ timeout *= wd->clk_rate;
+ writel(timeout, wd->base + WDT_REG_TIMEOUT);
+ writel(1, wd->base + WDT_REG_CONTROL);
+ }
+
+ return 0;
+}
+
+static int starfive_wdt_drv_probe(struct device_d *dev)
+{
+ struct starfive_wdt *wd;
+ struct resource *iores;
+ struct watchdog *wdd;
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get(dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ wd = xzalloc(sizeof(*wd));
+ wd->base = IOMEM(iores->start);
+
+ wd->clk_rate = clk_get_rate(clk);
+
+ ret = device_reset_all(dev);
+ if (ret)
+ return ret;
+
+ writel(WDT_UNLOCK_KEY, wd->base + WDT_REG_UNLOCK);
+ wd->base = IOMEM(iores->start);
+ /* reset, not interrupt, on timer expiry */
+ writel(1, wd->base + WDT_REG_RESET_EN);
+
+ wdd = &wd->wdd;
+ wdd->name = "starfive_wdt";
+ wdd->hwdev = dev;
+ wdd->set_timeout = starfive_wdt_set_timeout;
+ wdd->timeout_max = U32_MAX / wd->clk_rate;
+
+ wdd->running = readl(wd->base + WDT_REG_CONTROL) & 1 ?
+ WDOG_HW_RUNNING : WDOG_HW_NOT_RUNNING;
+
+ return watchdog_register(wdd);
+}
+
+static struct of_device_id starfive_wdt_of_match[] = {
+ { .compatible = "starfive,wdt", },
+ { /* sentinel */ }
+};
+
+static struct driver_d starfive_wdt_driver = {
+ .name = "starfive-wdt",
+ .probe = starfive_wdt_drv_probe,
+ .of_compatible = starfive_wdt_of_match,
+};
+device_platform_driver(starfive_wdt_driver);
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 20/20] hw_random: add driver for RNG on StarFive SoC
2021-05-31 7:38 [PATCH 00/20] RISC-V: prepare for BeagleV pre-production board support Ahmad Fatoum
` (18 preceding siblings ...)
2021-05-31 7:38 ` [PATCH 19/20] watchdog: add StarFive watchdog driver Ahmad Fatoum
@ 2021-05-31 7:38 ` Ahmad Fatoum
19 siblings, 0 replies; 30+ messages in thread
From: Ahmad Fatoum @ 2021-05-31 7:38 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Straight port from the vendor kernel with the difference that we
take the device out of reset. This allows to load older kernels that
don't yet do reset and clock handling.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/hw_random/Kconfig | 7 +
drivers/hw_random/Makefile | 1 +
drivers/hw_random/starfive-vic-rng.c | 200 +++++++++++++++++++++++++++
3 files changed, 208 insertions(+)
create mode 100644 drivers/hw_random/starfive-vic-rng.c
diff --git a/drivers/hw_random/Kconfig b/drivers/hw_random/Kconfig
index a84c03efef90..764911f4d35e 100644
--- a/drivers/hw_random/Kconfig
+++ b/drivers/hw_random/Kconfig
@@ -36,4 +36,11 @@ config HW_RANDOM_VIRTIO
This driver provides guest-side support for the virtual Random Number
Generator hardware.
+config HW_RANDOM_STARFIVE
+ tristate "StarFive Random Number Generator"
+ depends on SOC_STARFIVE || COMPILE_TEST
+ help
+ This driver provides barebox support for the Random Number
+ Generator hardware found on the StarFive family of SoCs.
+
endif
diff --git a/drivers/hw_random/Makefile b/drivers/hw_random/Makefile
index 4bab3967fc4d..4cf33d2d93e6 100644
--- a/drivers/hw_random/Makefile
+++ b/drivers/hw_random/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_HWRNG_MXC_RNGC) += mxc-rngc.o
obj-$(CONFIG_HWRNG_STM32) += stm32-rng.o
obj-$(CONFIG_HWRNG_DEV_RANDOM) += dev-random.o
obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
+obj-$(CONFIG_HW_RANDOM_STARFIVE) += starfive-vic-rng.o
diff --git a/drivers/hw_random/starfive-vic-rng.c b/drivers/hw_random/starfive-vic-rng.c
new file mode 100644
index 000000000000..45badd5200b6
--- /dev/null
+++ b/drivers/hw_random/starfive-vic-rng.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
+ */
+#include <common.h>
+#include <linux/err.h>
+#include <io.h>
+#include <of.h>
+#include <driver.h>
+#include <linux/hw_random.h>
+#include <linux/reset.h>
+
+#define VIC_RAND_LEN 4
+
+#define VIC_CTRL 0x00
+#define VIC_MODE 0x04
+#define VIC_SMODE 0x08
+#define VIC_STAT 0x0C
+#define VIC_IE 0x10
+#define VIC_ISTAT 0x14
+#define VIC_ALARM 0x18
+#define VIC_BUILD_ID 0x1C
+#define VIC_FEATURES 0x20
+#define VIC_RAND0 0x24
+#define VIC_NPA_DATA0 0x34
+#define VIC_SEED0 0x74
+#define VIC_IA_RDATA 0xA4
+#define VIC_IA_WDATA 0xA8
+#define VIC_IA_ADDR 0xAC
+#define VIC_IA_CMD 0xB0
+
+/* CTRL */
+#define VIC_CTRL_CMD_NOP 0
+#define VIC_CTRL_CMD_GEN_NOISE 1
+#define VIC_CTRL_CMD_GEN_NONCE 2
+#define VIC_CTRL_CMD_CREATE_STATE 3
+#define VIC_CTRL_CMD_RENEW_STATE 4
+#define VIC_CTRL_CMD_REFRESH_ADDIN 5
+#define VIC_CTRL_CMD_GEN_RANDOM 6
+#define VIC_CTRL_CMD_ADVANCE_STATE 7
+#define VIC_CTRL_CMD_KAT 8
+#define VIC_CTRL_CMD_ZEROIZE 15
+
+/* SMODE */
+#define _VIC_SMODE_SECURE_EN 1
+
+#define VIC_SMODE_SECURE_EN(x) ((x) << _VIC_SMODE_SECURE_EN)
+
+/* STAT */
+#define _VIC_STAT_BUSY 31
+
+#define VIC_STAT_BUSY (1UL << _VIC_STAT_BUSY)
+
+/* IE */
+#define _VIC_IE_GLBL 31
+#define _VIC_IE_DONE 4
+#define _VIC_IE_ALARMS 3
+#define _VIC_IE_NOISE_RDY 2
+#define _VIC_IE_KAT_COMPLETE 1
+#define _VIC_IE_ZEROIZE 0
+
+#define VIC_IE_GLBL (1UL << _VIC_IE_GLBL)
+#define VIC_IE_DONE (1UL << _VIC_IE_DONE)
+#define VIC_IE_ALARMS (1UL << _VIC_IE_ALARMS)
+#define VIC_IE_NOISE_RDY (1UL << _VIC_IE_NOISE_RDY)
+#define VIC_IE_KAT_COMPLETE (1UL << _VIC_IE_KAT_COMPLETE)
+#define VIC_IE_ZEROIZE (1UL << _VIC_IE_ZEROIZE)
+#define VIC_IE_ALL (VIC_IE_GLBL | VIC_IE_DONE | VIC_IE_ALARMS | \
+ VIC_IE_NOISE_RDY | VIC_IE_KAT_COMPLETE | VIC_IE_ZEROIZE)
+
+#define to_vic_rng(p) container_of(p, struct vic_rng, rng)
+
+struct vic_rng {
+ struct device_d *dev;
+ void __iomem *base;
+ struct hwrng rng;
+};
+
+static inline void vic_wait_till_idle(struct vic_rng *hrng)
+{
+ while(readl(hrng->base + VIC_STAT) & VIC_STAT_BUSY)
+ ;
+}
+
+static inline void vic_rng_irq_mask_clear(struct vic_rng *hrng)
+{
+ u32 data = readl(hrng->base + VIC_ISTAT);
+ writel(data, hrng->base + VIC_ISTAT);
+ writel(0, hrng->base + VIC_ALARM);
+}
+
+static int vic_trng_cmd(struct vic_rng *hrng, u32 cmd)
+{
+ vic_wait_till_idle(hrng);
+
+ switch (cmd) {
+ case VIC_CTRL_CMD_NOP:
+ case VIC_CTRL_CMD_GEN_NOISE:
+ case VIC_CTRL_CMD_GEN_NONCE:
+ case VIC_CTRL_CMD_CREATE_STATE:
+ case VIC_CTRL_CMD_RENEW_STATE:
+ case VIC_CTRL_CMD_REFRESH_ADDIN:
+ case VIC_CTRL_CMD_GEN_RANDOM:
+ case VIC_CTRL_CMD_ADVANCE_STATE:
+ case VIC_CTRL_CMD_KAT:
+ case VIC_CTRL_CMD_ZEROIZE:
+ writel(cmd, hrng->base + VIC_CTRL);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vic_rng_init(struct hwrng *rng)
+{
+ struct vic_rng *hrng = to_vic_rng(rng);
+ int ret;
+
+ ret = device_reset(rng->dev);
+ if (ret)
+ return ret;
+
+ // clear register: ISTAT
+ vic_rng_irq_mask_clear(hrng);
+
+ // set mission mode
+ writel(VIC_SMODE_SECURE_EN(1), hrng->base + VIC_SMODE);
+
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE);
+ vic_wait_till_idle(hrng);
+
+ // set interrupt
+ writel(VIC_IE_ALL, hrng->base + VIC_IE);
+
+ // zeroize
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
+
+ vic_wait_till_idle(hrng);
+
+ return 0;
+}
+
+static int vic_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ struct vic_rng *hrng = to_vic_rng(rng);
+
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE);
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_CREATE_STATE);
+
+ vic_wait_till_idle(hrng);
+ max = min_t(size_t, max, VIC_RAND_LEN * 4);
+
+ writel(0x0, hrng->base + VIC_MODE);
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_RANDOM);
+
+ vic_wait_till_idle(hrng);
+ memcpy_fromio(buf, hrng->base + VIC_RAND0, max);
+ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
+
+ vic_wait_till_idle(hrng);
+ return max;
+}
+
+static int vic_rng_probe(struct device_d *dev)
+{
+ struct vic_rng *hrng;
+ struct resource *res;
+
+ hrng = xzalloc(sizeof(*hrng));
+
+ res = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ hrng->base = IOMEM(res->start);
+ hrng->dev = dev;
+
+ hrng->rng.name = dev_name(dev);
+ hrng->rng.init = vic_rng_init;
+ hrng->rng.read = vic_rng_read;
+
+ return hwrng_register(dev, &hrng->rng);
+}
+
+static const struct of_device_id vic_rng_dt_ids[] = {
+ { .compatible = "starfive,vic-rng" },
+ { /* sentinel */ }
+};
+
+static struct driver_d vic_rng_driver = {
+ .name = "vic-rng",
+ .probe = vic_rng_probe,
+ .of_compatible = vic_rng_dt_ids,
+};
+device_platform_driver(vic_rng_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
+MODULE_DESCRIPTION("Starfive VIC random number generator driver");
--
2.29.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 30+ messages in thread