U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
April 2022
- 186 participants
- 739 discussions
This series collects together various misc patches that were needed when
building mainline U-Boot against Chromium OS verified boot. Most of them
fix minor bugs.
Simon Glass (18):
buildman: Update default config to build for sandbox
buildman: Fix up cfgutil
binman: Correct Chromium OS entry types
errno: Avoid including strings in SPL
abuf: Correct a corner case with abuf_realloc()
fdt: Correct condition for SEPARATE_BSS
fdt: sandbox: Avoid looking for an appended device tree
lzma: Tidy up the function prototype
cbfs: Add some more definititions
cros_ec: Complete the comment for cros_ec_read_batt_charge()
spi: Avoid checking console in SPL
disk: Correct the conditions for SPL
Add a default for TPL_TEXT_BASE
Make ASYMMETRIC_KEY_TYPE depend on FIT_SIGNATURE
stdint: Add a definition of UINT8_MAX
dm: core: Add a required struct declaration
dm: core: Tidy up comments in uclass headers
dm: blk: Expand iteration and add tests
common/spl/Kconfig | 1 +
disk/Makefile | 10 +--
drivers/block/blk-uclass.c | 24 +++++++
drivers/mtd/spi/spi-nor-core.c | 2 +-
include/blk.h | 45 +++++++++++++
include/cbfs.h | 43 +++++++++++++
include/cros_ec.h | 1 +
include/dm/device-internal.h | 1 +
include/dm/uclass-internal.h | 18 +++---
include/dm/uclass.h | 13 ++--
include/errno.h | 2 +-
include/stdint.h | 7 +++
lib/abuf.c | 4 +-
lib/crypto/Kconfig | 1 +
lib/fdtdec.c | 5 +-
lib/lzma/LzmaTools.c | 4 +-
lib/lzma/LzmaTools.h | 17 ++++-
test/dm/blk.c | 111 +++++++++++++++++++++++++++++++++
test/lib/abuf.c | 29 +++++++++
tools/binman/btool/futility.py | 4 +-
tools/binman/etype/vblock.py | 2 +-
tools/buildman/bsettings.py | 1 +
tools/buildman/cfgutil.py | 4 +-
23 files changed, 315 insertions(+), 34 deletions(-)
--
2.35.1.574.g5d30c73bfb-goog
3
22
This is needed for SDP downloads of eg. fitimages
in SPL stage.
Signed-off-by: Manuel Traut <manut(a)mecka.net>
---
common/spl/Kconfig | 10 +++
common/usb_hub.c | 4 +
drivers/usb/gadget/Makefile | 18 ++--
drivers/usb/gadget/ci_udc.c | 159 +++++++++++++++++-------------------
drivers/usb/gadget/ci_udc.h | 2 +-
drivers/usb/host/Makefile | 2 +-
6 files changed, 98 insertions(+), 97 deletions(-)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index dc319adeac..f5545d2cb2 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1181,6 +1181,16 @@ config SPL_USB_GADGET
if SPL_USB_GADGET
+config SPL_CI_UDC
+ bool "Support USB CI UDC controller in SPL"
+ help
+ Enables CI UDC driver to be available in SPL
+
+config SPL_USB_EHCI_HCD
+ bool "Support USB EHCI Host in SPL"
+ help
+ Enables EHCI host driver in SPL.
+
config SPL_USB_ETHER
bool "Support USB Ethernet drivers"
depends on SPL_NET
diff --git a/common/usb_hub.c b/common/usb_hub.c
index ba11a188ca..d572d7dd17 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -166,7 +166,9 @@ static void usb_hub_power_on(struct usb_hub_device
*hub)
int i;
struct usb_device *dev;
unsigned pgood_delay = hub->desc.bPwrOn2PwrGood * 2;
+#ifndef CONFIG_SPL_BUILD
const char *env;
+#endif
dev = hub->pusb_dev;
@@ -185,6 +187,7 @@ static void usb_hub_power_on(struct usb_hub_device
*hub)
return;
#endif
+#ifndef CONFIG_SPL_BUILD
/*
* Wait for power to become stable,
* plus spec-defined max time for device to connect
@@ -196,6 +199,7 @@ static void usb_hub_power_on(struct usb_hub_device
*hub)
pgood_delay = max(pgood_delay,
(unsigned)simple_strtol(env, NULL, 0));
debug("pgood_delay=%dms\n", pgood_delay);
+#endif
/*
* Do a minimum delay of the larger value of 100ms or pgood_delay
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index d5d891b205..df88ae2f30 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -21,16 +21,16 @@ obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_udc_otg.o
obj-$(CONFIG_USB_GADGET_DWC2_OTG_PHY) += dwc2_udc_otg_phy.o
obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
obj-$(CONFIG_USB_GADGET_MAX3420) += max3420_udc.o
-obj-$(CONFIG_CI_UDC) += ci_udc.o
+obj-$(CONFIG_$(SPL_)CI_UDC) += ci_udc.o
ifndef CONFIG_SPL_BUILD
-obj-$(CONFIG_USB_GADGET_DOWNLOAD) += g_dnl.o
-obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
-obj-$(CONFIG_DFU_OVER_USB) += f_dfu.o
-obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
-obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
-obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
-obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
-obj-$(CONFIG_USB_FUNCTION_ACM) += f_acm.o
+obj-$(CONFIG_$(SPL_)USB_GADGET_DOWNLOAD) += g_dnl.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_THOR) += f_thor.o
+obj-$(CONFIG_$(SPL_)DFU_OVER_USB) += f_dfu.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_FASTBOOT) += f_fastboot.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_SDP) += f_sdp.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_ROCKUSB) += f_rockusb.o
+obj-$(CONFIG_$(SPL_)USB_FUNCTION_ACM) += f_acm.o
endif
endif
ifdef CONFIG_USB_ETHER
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 542684c1c3..2e274331fe 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -25,6 +25,7 @@
#include <usb/ci_udc.h>
#include "../host/ehci.h"
#include "ci_udc.h"
+#include <dm.h>
/*
* Check if the system has too long cachelines. If the cachelines are
@@ -94,10 +95,42 @@ static struct usb_request *
ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags);
static void ci_ep_free_request(struct usb_ep *ep, struct usb_request
*_req);
+static int ci_gadget_start(struct usb_gadget *g, struct
usb_gadget_driver *d);
+static int ci_gadget_stop(struct usb_gadget *g);
+
static struct usb_gadget_ops ci_udc_ops = {
- .pullup = ci_pullup,
+ .pullup = ci_pullup,
+ .udc_start = ci_gadget_start,
+ .udc_stop = ci_gadget_stop,
+};
+
+static struct ci_drv controller = {
+ .gadget = {
+ .name = "ci_udc",
+ .ops = &ci_udc_ops,
+ .is_dualspeed = 1,
+ .is_otg = 0,
+ .is_a_peripheral = 0,
+ .b_hnp_enable = 0,
+ .a_hnp_support = 0,
+ .a_alt_hnp_support = 0,
+ },
};
+static int ci_gadget_start(struct usb_gadget *g, struct
usb_gadget_driver *d)
+{
+ controller.driver = d;
+ printf("Registered gadget driver %s\n", controller.gadget.name);
+ return 0;
+}
+
+static int ci_gadget_stop(struct usb_gadget *g)
+{
+ printf("Unregistered gadget driver %s\n", controller.gadget.name);
+ controller.driver = 0;
+ return 0;
+}
+
static struct usb_ep_ops ci_ep_ops = {
.enable = ci_ep_enable,
.disable = ci_ep_disable,
@@ -107,10 +140,6 @@ static struct usb_ep_ops ci_ep_ops = {
.free_request = ci_ep_free_request,
};
-__weak void ci_init_after_reset(struct ehci_ctrl *ctrl)
-{
-}
-
/* Init values for USB endpoints. */
static const struct usb_ep ci_ep_init[5] = {
[0] = { /* EP 0 */
@@ -140,15 +169,6 @@ static const struct usb_ep ci_ep_init[5] = {
},
};
-static struct ci_drv controller = {
- .gadget = {
- .name = "ci_udc",
- .ops = &ci_udc_ops,
- .is_dualspeed = 1,
- .max_speed = USB_SPEED_HIGH,
- },
-};
-
/**
* ci_get_qh() - return queue head for endpoint
* @ep_num: Endpoint number
@@ -310,7 +330,7 @@ static void ci_ep_free_request(struct usb_ep *ep,
struct usb_request *req)
static void ep_enable(int num, int in, int maxpacket)
{
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
unsigned n;
n = readl(&udc->epctrl[num]);
@@ -432,7 +452,7 @@ static void ci_debounce(struct ci_req *ci_req, int
in)
static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
{
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
struct ept_queue_item *item;
struct ept_queue_head *head;
int bit, num, len, in;
@@ -673,7 +693,7 @@ static void handle_setup(void)
struct ci_ep *ci_ep = &controller.ep[0];
struct ci_req *ci_req;
struct usb_request *req;
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
struct ept_queue_head *head;
struct usb_ctrlrequest r;
int status = 0;
@@ -776,7 +796,7 @@ static void stop_activity(void)
{
int i, num, in;
struct ept_queue_head *head;
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
writel(readl(&udc->epcomp), &udc->epcomp);
#ifdef CONFIG_CI_UDC_HAS_HOSTPC
writel(readl(&udc->epsetupstat), &udc->epsetupstat);
@@ -800,16 +820,18 @@ static void stop_activity(void)
}
}
-void udc_irq(void)
+static int udc_irq(void)
{
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
- unsigned n = readl(&udc->usbsts);
- writel(n, &udc->usbsts);
+ struct ci_udc *udc = controller.udc;
+ unsigned n;
int bit, i, num, in;
+ n = readl(&udc->usbsts);
+ writel(n, &udc->usbsts);
+
n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI);
if (n == 0)
- return;
+ return IRQ_NONE;
if (n & STS_URI) {
DBG("-- reset --\n");
@@ -867,23 +889,17 @@ void udc_irq(void)
}
}
}
+ return IRQ_HANDLED;
}
-int usb_gadget_handle_interrupts(int index)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
{
- u32 value;
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
-
- value = readl(&udc->usbsts);
- if (value)
- udc_irq();
-
- return value;
+ return udc_irq();
}
void udc_disconnect(void)
{
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
/* disable pullup */
stop_activity();
writel(USBCMD_FS2, &udc->usbcmd);
@@ -894,14 +910,12 @@ void udc_disconnect(void)
static int ci_pullup(struct usb_gadget *gadget, int is_on)
{
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
if (is_on) {
/* RESET */
writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd);
udelay(200);
- ci_init_after_reset(controller.ctrl);
-
writel((unsigned long)controller.epts, &udc->epinitaddr);
/* select DEVICE mode */
@@ -924,7 +938,7 @@ static int ci_pullup(struct usb_gadget *gadget, int
is_on)
return 0;
}
-static int ci_udc_probe(void)
+static int ci_udc_probe(struct udevice *dev)
{
struct ept_queue_head *head;
int i;
@@ -936,6 +950,9 @@ static int ci_udc_probe(void)
const int eplist_raw_sz = num * sizeof(struct ept_queue_head);
const int eplist_sz = roundup(eplist_raw_sz, ARCH_DMA_MINALIGN);
+ controller.driver = 0;
+ controller.udc = (struct ci_udc *) 0x32e40140; // TODO read from DTB
+
/* The QH list must be aligned to 4096 bytes. */
controller.epts = memalign(eplist_align, eplist_sz);
if (!controller.epts)
@@ -1010,66 +1027,36 @@ static int ci_udc_probe(void)
return -ENOMEM;
}
- return 0;
+ return usb_add_gadget_udc((struct device *)dev, &controller.gadget);
}
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+static int ci_udc_remove(struct udevice *dev)
{
- int ret;
-
- if (!driver)
- return -EINVAL;
- if (!driver->bind || !driver->setup || !driver->disconnect)
- return -EINVAL;
-
-#if CONFIG_IS_ENABLED(DM_USB)
- ret = usb_setup_ehci_gadget(&controller.ctrl);
-#else
- ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void
**)&controller.ctrl);
-#endif
- if (ret)
- return ret;
-
- ret = ci_udc_probe();
- if (ret) {
- DBG("udc probe failed, returned %d\n", ret);
- return ret;
- }
-
- ret = driver->bind(&controller.gadget);
- if (ret) {
- DBG("driver->bind() returned %d\n", ret);
- return ret;
- }
- controller.driver = driver;
-
- return 0;
-}
-
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
- udc_disconnect();
-
- driver->unbind(&controller.gadget);
- controller.driver = NULL;
-
+ usb_del_gadget_udc(&controller.gadget);
ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req);
free(controller.items_mem);
free(controller.epts);
-#if CONFIG_IS_ENABLED(DM_USB)
- usb_remove_ehci_gadget(&controller.ctrl);
-#else
- usb_lowlevel_stop(0);
- controller.ctrl = NULL;
-#endif
-
- return 0;
+ return dm_scan_fdt_dev(dev);
}
+static const struct udevice_id ci_udc_ids[] = {
+ { .compatible = "fsl,imx27-usb-gadget" },
+ {},
+};
+
+U_BOOT_DRIVER(ci_udc_usb) = {
+ .name = "ci-udc",
+ .id = UCLASS_USB_GADGET_GENERIC,
+ .of_match = ci_udc_ids,
+ .probe = ci_udc_probe,
+ .remove = ci_udc_remove,
+ .priv_auto = sizeof(struct ci_udc),
+};
+
bool dfu_usb_get_reset(void)
{
- struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = controller.udc;
return !!(readl(&udc->usbsts) & STS_URI);
}
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 95cc07992b..c087ac533d 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -101,7 +101,7 @@ struct ci_drv {
struct ci_req *ep0_req;
bool ep0_data_phase;
struct usb_gadget_driver *driver;
- struct ehci_ctrl *ctrl;
+ struct ci_udc *udc;
struct ept_queue_head *epts;
uint8_t *items_mem;
struct ci_ep ep[NUM_ENDPOINTS];
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index eb6fe9f6b3..08474daaf2 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_USB_OHCI_PCI) += ohci-pci.o
obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o
# echi
-obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
+obj-$(CONFIG_$(SPL_)USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_EHCI_ARMADA100) += ehci-armada100.o utmi-armada100.o
obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
--
2.30.2
1
0

07 Apr '22
Swap the arguments as that seems to have been the author's intention.
Note: This fix wasn't tested on hardware and will result in more bits
being set by the underlying writel() in rk_clrsetreg(), which
might bring unexpected behavioural changes.
Fixes: b07911840025 ("net: gmac_rockchip: add support for px30")
Signed-off-by: Pierre-Clément Tosi <ptosi(a)google.com>
Cc: Joe Hershberger <joe.hershberger(a)ni.com>
Cc: Heiko Stuebner <heiko(a)sntech.de>
Cc: Kever Yang <kever.yang(a)rock-chips.com>
Cc: Tom Rini <trini(a)konsulko.com>
---
drivers/net/gmac_rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 04008d2b19..0ecbcdf641 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -350,7 +350,7 @@ static void px30_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata)
struct px30_grf *grf;
enum {
PX30_GMAC_PHY_INTF_SEL_SHIFT = 4,
- PX30_GMAC_PHY_INTF_SEL_MASK = GENMASK(4, 6),
+ PX30_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4),
PX30_GMAC_PHY_INTF_SEL_RMII = BIT(6),
};
--
2.35.1.723.g4982287a31-goog
8
26

[PATCH] LS1043ARDB, LS1046ARDB, LS1088ARDB: Enable SPL_OF_CONTROL in SECURE Boot defconfig
by Kshitiz Varshney 07 Apr '22
by Kshitiz Varshney 07 Apr '22
07 Apr '22
If enable SPL_DM without SPL_OF_CONTROL,
build errors "undefined reference to fdt_get_resource",
is coming in function `caam_jr_probe'.
Added SPL_OF_CONTROL to remove the error.
Signed-off-by: Kshitiz Varshney <kshitiz.varshney(a)nxp.com>
---
configs/ls1043ardb_nand_SECURE_BOOT_defconfig | 1 +
configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig | 1 +
configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig | 1 +
configs/ls1088ardb_sdcard_qspi_SECURE_BOOT_defconfig | 1 +
4 files changed, 4 insertions(+)
diff --git a/configs/ls1043ardb_nand_SECURE_BOOT_defconfig b/configs/ls1043ardb_nand_SECURE_BOOT_defconfig
index 3ca7dac9e8..e7d7a43351 100644
--- a/configs/ls1043ardb_nand_SECURE_BOOT_defconfig
+++ b/configs/ls1043ardb_nand_SECURE_BOOT_defconfig
@@ -45,6 +45,7 @@ CONFIG_MP=y
CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:2m@0x100000(nor_bank0_uboot),40m@0x1100000(nor_bank0_fit),7m(nor_bank0_user),2m@0x4100000(nor_bank4_uboot),40m@0x5100000(nor_bank4_fit),-(nor_bank4_user);7e800000.flash:1m(nand_uboot),1m(nand_uboot_env),20m(nand_fit);spi0.0:1m(uboot),5m(kernel),1m(dtb),9m(file_system)"
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM=y
diff --git a/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig b/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig
index 06c1ce5053..c83492c814 100644
--- a/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig
+++ b/configs/ls1043ardb_sdcard_SECURE_BOOT_defconfig
@@ -45,6 +45,7 @@ CONFIG_MP=y
CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:2m@0x100000(nor_bank0_uboot),40m@0x1100000(nor_bank0_fit),7m(nor_bank0_user),2m@0x4100000(nor_bank4_uboot),40m@0x5100000(nor_bank4_fit),-(nor_bank4_user);7e800000.flash:1m(nand_uboot),1m(nand_uboot_env),20m(nand_fit);spi0.0:1m(uboot),5m(kernel),1m(dtb),9m(file_system)"
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM=y
diff --git a/configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig b/configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig
index 5caf24f800..7f2285424a 100644
--- a/configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig
+++ b/configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig
@@ -45,6 +45,7 @@ CONFIG_MP=y
CONFIG_MTDPARTS_DEFAULT="mtdparts=1550000.spi-0:1m(rcw),15m(u-boot),48m(kernel.itb);7e800000.flash:16m(nand_uboot),48m(nand_kernel),448m(nand_free)"
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM=y
diff --git a/configs/ls1088ardb_sdcard_qspi_SECURE_BOOT_defconfig b/configs/ls1088ardb_sdcard_qspi_SECURE_BOOT_defconfig
index 24e4ba7229..0598160fcb 100644
--- a/configs/ls1088ardb_sdcard_qspi_SECURE_BOOT_defconfig
+++ b/configs/ls1088ardb_sdcard_qspi_SECURE_BOOT_defconfig
@@ -50,6 +50,7 @@ CONFIG_CMD_USB=y
CONFIG_CMD_CACHE=y
CONFIG_MP=y
CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_NET_RANDOM_ETHADDR=y
--
2.25.1
1
0

[PATCH v6 0/7] fpga: zynqmp: Adding support of loading authenticated images
by Adrian Fiergolski 07 Apr '22
by Adrian Fiergolski 07 Apr '22
07 Apr '22
This patchset introduces support for the authenticated FPGA images
on ZynqMP boards, besides that introducing common way to pass the
compatible property to any fpga driver.
It bases on the initial work by Jorge Ramirez-Ortiz <jorge(a)foundries.io>
https://patchwork.ozlabs.org/project/uboot/patch/20211015091506.2602-1-jorg…
https://patchwork.ozlabs.org/project/uboot/patch/20211005111324.19749-3-jor…
Changed in v6:
- add support for the encrypted bitfiles
Changes in v5:
- replace ifdef with if() where it's possible
Changes in v4:
- change interface to xilinx_desc->operations->open() callback.
- fix a bug from previous version of the patchset in dereferencing
of a parent fpga_desc structure.
Changes in v3:
- remove the patch which introduced CMD_SPL_FPGA_LOAD_SECURE.
- fix mixing definitions/declarations.
- replace strcmp() calls with more secure strncmp().
- document the "u-boot,zynqmp-fpga-ddrauth" compatible string.
- fix code style by check-patch recommendations.
Changes in v2:
- add function fit_fpga_load() to simplify calls of fpga_load()
from contexts without a compatible attribute.
- move all ZynqMP-specific logic to drivers/fpga/zynqmppl.c
- prepare for passing a "compatible" FDT property to any fpga driver.
Oleksandr Suvorov (6):
fpga: add option for loading FPGA secure bitstreams
fpga: add fit_fpga_load function
fpga: xilinx: pass an address of xilinx_desc in fpga_desc
fpga: xilinx: add missed identifier names
fpga: xilinx: pass xilinx_desc pointer address into load() ops
fpga: zynqmp: support loading authenticated images
Adrian Fiergolski (1):
fpga: zynqmp: support loading encrypted bitfiles
2
13
This is the only place where i.MX8M code does SMCCC call, remove it.
The output has little value as it prints some part of commit ID, and
worse, if there is no SMC handler installed, the code outright hangs
or crashes the system.
By removing this one instance of SMCCC call, U-Boot no longer depends
on SMC handlers and can boot without hanging in any case. If there is
a need to dump this commit ID, use CMD_SMC instead and do 'smc' call
from U-Boot shell or scripts instead of hard-coding SMCCC dependency
into architecture code. This particular code can be replaced by:
=> smc 0xc2000003 0 0 0 0 0 0
Signed-off-by: Marek Vasut <marex(a)denx.de>
Cc: Fabio Estevam <festevam(a)gmail.com>
Cc: Peng Fan <peng.fan(a)nxp.com>
Cc: Stefano Babic <sbabic(a)denx.de>
---
NOTE: This could also be hidden behind ARM_PSCI_FW , but I would rather
just remove this hard dependency, it makes U-Boot porting easier.
---
arch/arm/mach-imx/imx8m/soc.c | 20 --------------------
1 file changed, 20 deletions(-)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 1a5a391443d..45c5476bbc7 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -27,7 +27,6 @@
#include <fdt_support.h>
#include <fsl_wdog.h>
#include <imx_sip.h>
-#include <linux/arm-smccc.h>
#include <linux/bitops.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -1191,27 +1190,8 @@ void reset_cpu(void)
#endif
#if defined(CONFIG_ARCH_MISC_INIT)
-static void acquire_buildinfo(void)
-{
- u64 atf_commit = 0;
- struct arm_smccc_res res;
-
- /* Get ARM Trusted Firmware commit id */
- arm_smccc_smc(IMX_SIP_BUILDINFO, IMX_SIP_BUILDINFO_GET_COMMITHASH,
- 0, 0, 0, 0, 0, 0, &res);
- atf_commit = res.a0;
- if (atf_commit == 0xffffffff) {
- debug("ATF does not support build info\n");
- atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */
- }
-
- printf("\n BuildInfo:\n - ATF %s\n\n", (char *)&atf_commit);
-}
-
int arch_misc_init(void)
{
- acquire_buildinfo();
-
return 0;
}
#endif
--
2.35.1
2
1
Add clock tables required for bing up ECSPI interfaces
Signed-off-by: Elmar Albert <ealbert(a)data-modul.com>
Cc: Fabio Estevam <festevam(a)denx.de>
Cc: Peng Fan <peng.fan(a)nxp.com>
Cc: Stefano Babic <sbabic(a)denx.de>
Cc: uboot-imx <uboot-imx(a)nxp.com>
Signed-off-by: Elmar Albert <ealbert(a)data-modul.com>
---
drivers/clk/imx/clk-imx8mp.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index ad84ce38ed..8a374ef0b5 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -160,6 +160,18 @@ static const char *imx8mp_gic_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_p
"sys_pll2_100m", "sys_pll1_800m",
"sys_pll2_500m", "clk_ext4", "audio_pll2_out" };
+static const char *imx8mp_ecspi1_sels[] = {"clock-osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mp_ecspi2_sels[] = {"clock-osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mp_ecspi3_sels[] = {"clock-osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
static const char *imx8mp_wdog_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_160m",
"vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
"sys_pll1_80m", "sys_pll2_166m" };
@@ -274,6 +286,9 @@ static int imx8mp_clk_probe(struct udevice *dev)
clk_dm(IMX8MP_CLK_UART3, imx8m_clk_composite("uart3", imx8mp_uart3_sels, base + 0xb000));
clk_dm(IMX8MP_CLK_UART4, imx8m_clk_composite("uart4", imx8mp_uart4_sels, base + 0xb080));
clk_dm(IMX8MP_CLK_GIC, imx8m_clk_composite_critical("gic", imx8mp_gic_sels, base + 0xb200));
+ clk_dm(IMX8MP_CLK_ECSPI1, imx8m_clk_composite("ecspi1", imx8mp_ecspi1_sels, base + 0xb280));
+ clk_dm(IMX8MP_CLK_ECSPI2, imx8m_clk_composite("ecspi2", imx8mp_ecspi2_sels, base + 0xb300));
+ clk_dm(IMX8MP_CLK_ECSPI3, imx8m_clk_composite("ecspi3", imx8mp_ecspi3_sels, base + 0xc180));
clk_dm(IMX8MP_CLK_WDOG, imx8m_clk_composite("wdog", imx8mp_wdog_sels, base + 0xb900));
clk_dm(IMX8MP_CLK_USDHC3, imx8m_clk_composite("usdhc3", imx8mp_usdhc3_sels, base + 0xbc80));
@@ -282,7 +297,9 @@ static int imx8mp_clk_probe(struct udevice *dev)
clk_dm(IMX8MP_CLK_DRAM_CORE, imx_clk_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mp_dram_core_sels, ARRAY_SIZE(imx8mp_dram_core_sels), CLK_IS_CRITICAL));
clk_dm(IMX8MP_CLK_DRAM1_ROOT, imx_clk_gate4_flags("dram1_root_clk", "dram_core_clk", base + 0x4050, 0, CLK_IS_CRITICAL));
-
+ clk_dm(IMX8MP_CLK_ECSPI1_ROOT, imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0));
+ clk_dm(IMX8MP_CLK_ECSPI2_ROOT, imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0));
+ clk_dm(IMX8MP_CLK_ECSPI3_ROOT, imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0));
clk_dm(IMX8MP_CLK_ENET1_ROOT, imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0));
clk_dm(IMX8MP_CLK_GPIO1_ROOT, imx_clk_gate4("gpio1_root_clk", "ipg_root", base + 0x40b0, 0));
clk_dm(IMX8MP_CLK_GPIO2_ROOT, imx_clk_gate4("gpio2_root_clk", "ipg_root", base + 0x40c0, 0));
--
2.25.1
2
1
Loongson 1C is a cost-effective SOC chip for industrial control and
the Internet of Things. The Loongson 1C includes a floating-point
processing unit, supports multiple types of memory, and supports
high-capacity MLC NAND Flash. Loongson 1C provides developers with a
wealth of peripheral interfaces and on-chip modules, including Camera
controller, USB OTG and USB HOST interfaces, AC97/I2S controller, LCD
controller, SPI interface, UART interface, etc., providing sufficient
computing power and multi-application connectivity.
Some highlights of this SoC are:
- Single core LS232, MIPS32 instruction set compatible, main frequency
300MHZ
- 16KB data cache and 16KB instruction cache
- 64 bit float unit, hardware division
- 8/16 bit SDRAM controller, 45 ~ 133MHz
- 8/16 bit SRAM, NAND
- I2S/AC97, LCD, MAC, USB, OTG, SPI, I2C, PWM, CAN, SDIO, ADC
- 12 UARTs
See Techinical Reference Manual for details: https://www.loongson.cn/
introduce base support for the ls1c300 SoC.
- debug UART2
- serial console
- clock
- watchdog
- sysreset
- many uarts
Signed-off-by: Du Huanpeng <dhu(a)hodcarrier.org>
---
Changelog for v2:
1. dtsi:
add status disabled for uart0 ~ uart11
remove bootargs from chosen
make serial0 alias for uart2
oscillator remove @0 unit-address
change uart2 address to kuseg
2. cleanup Kconfig and update defconfig
- make these options configurable, disabled by default:
CMD_DM
DM_ETH
DM_GPIO
DM_SPI
DM_SPI_FLASH
DM_RESET
PINCONF
PINCTRL
PINMUX
RESET_LSMIPS
- make these options configurable, enabled by default:
CLK
DISPLAY_CPUINFO
SYSRESET
ROM_EXCEPTION_VECTORS
- disabled:
CONFIG_ENV_IS_IN_SPI_FLASH
3. fix codingstyle drivers/watchdog/lsmips-wdt.c
- priv->base + offset
- add comment for default clock value
4. remove address base definition header
- remove arch/mips/mach-lsmips/ls1c300/ls1c300.h
- clean up files uses this header
5. spl and debug uart
- add comment for spl & debug uart pinmuxing
- cleanup unused registers base header
6. dtsi
- add "loongson,ls1c300-uart" to all uart node
7. board dts
- add memory node to board dts, start at 0x80000000, size 64MB
8. Kconfig
- make ROM_EXCEPTION_VECTORS user configureable
- enable ROM_EXCEPTION_VECTORS in defconfig
9.
- seperate sdram_init to sdram_init.S
- add macro helpers to do sdram, pll lowlevel init
10. dtsi
- move clock nodes to /clocks/xxx
11.
- define CONFIG_SKIP_LOWLEVEL_INIT to 1
12.
- remove option PINCTRL_LS1C300 from Kconfig
13.
- dram_init, use get_ram_size() to detect ram size.
14. clk driver
- create custom clock ops for PLL
- remove debug code
15.
- rebase to 59bffec43a657598b194b9eb30dc01eec06078c7
- remove CONFIG_SYS_MONITOR_BASE from include/configs/
> commit e4d741f8abc4a92426d3a826f99390c3abe02d61
> Author: Tom Rini <trini(a)konsulko.com>
> Date: Thu Mar 24 17:18:05 2022 -0400
>
> Convert CONFIG_SYS_MONITOR_BASE to Kconfig
---
MAINTAINERS | 13 ++
arch/mips/Kconfig | 11 ++
arch/mips/Makefile | 1 +
arch/mips/dts/Makefile | 1 +
arch/mips/dts/loongson32-ls1c300b.dtsi | 166 ++++++++++++++++++
arch/mips/dts/ls1c300-eval.dts | 31 ++++
arch/mips/mach-lsmips/Kconfig | 76 ++++++++
arch/mips/mach-lsmips/Makefile | 6 +
arch/mips/mach-lsmips/cpu.c | 19 ++
arch/mips/mach-lsmips/include/mach/serial.h | 16 ++
arch/mips/mach-lsmips/ls1c300/Makefile | 7 +
arch/mips/mach-lsmips/ls1c300/gpio.c | 66 +++++++
arch/mips/mach-lsmips/ls1c300/init.c | 59 +++++++
arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 136 ++++++++++++++
arch/mips/mach-lsmips/ls1c300/sdram.S | 93 ++++++++++
arch/mips/mach-lsmips/ls1c300/serial.c | 109 ++++++++++++
arch/mips/mach-lsmips/spl.c | 47 +++++
board/loongson/ls1c300-eval/Kconfig | 12 ++
board/loongson/ls1c300-eval/MAINTAINERS | 7 +
board/loongson/ls1c300-eval/Makefile | 3 +
board/loongson/ls1c300-eval/board.c | 20 +++
configs/ls1c300_defconfig | 54 ++++++
drivers/clk/Makefile | 1 +
drivers/clk/lsmips/Makefile | 3 +
drivers/clk/lsmips/clk-ls1c300.c | 161 +++++++++++++++++
drivers/watchdog/Kconfig | 8 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/lsmips_wdt.c | 131 ++++++++++++++
include/configs/ls1c300.h | 59 +++++++
include/dt-bindings/clock/ls1c300-clk.h | 48 +++++
30 files changed, 1365 insertions(+)
create mode 100644 arch/mips/dts/loongson32-ls1c300b.dtsi
create mode 100644 arch/mips/dts/ls1c300-eval.dts
create mode 100644 arch/mips/mach-lsmips/Kconfig
create mode 100644 arch/mips/mach-lsmips/Makefile
create mode 100644 arch/mips/mach-lsmips/cpu.c
create mode 100644 arch/mips/mach-lsmips/include/mach/serial.h
create mode 100644 arch/mips/mach-lsmips/ls1c300/Makefile
create mode 100644 arch/mips/mach-lsmips/ls1c300/gpio.c
create mode 100644 arch/mips/mach-lsmips/ls1c300/init.c
create mode 100644 arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
create mode 100644 arch/mips/mach-lsmips/ls1c300/sdram.S
create mode 100644 arch/mips/mach-lsmips/ls1c300/serial.c
create mode 100644 arch/mips/mach-lsmips/spl.c
create mode 100644 board/loongson/ls1c300-eval/Kconfig
create mode 100644 board/loongson/ls1c300-eval/MAINTAINERS
create mode 100644 board/loongson/ls1c300-eval/Makefile
create mode 100644 board/loongson/ls1c300-eval/board.c
create mode 100644 configs/ls1c300_defconfig
create mode 100644 drivers/clk/lsmips/Makefile
create mode 100644 drivers/clk/lsmips/clk-ls1c300.c
create mode 100644 drivers/watchdog/lsmips_wdt.c
create mode 100644 include/configs/ls1c300.h
create mode 100644 include/dt-bindings/clock/ls1c300-clk.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 0fc034f01f..a6927fa4a5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -954,6 +954,19 @@ F: drivers/net/cortina_ni.c
F: drivers/net/cortina_ni.h
F: drivers/net/phy/ca_phy.c
+MIPS LOONGSON LS1C300
+M: Du Huanpeng <dhu(a)hodcarrier.org>
+S: Maintained
+F: arch/mips/dts/loongson32-ls1c300b.dtsi
+F: arch/mips/dts/ls1c300-eval.dts
+F: arch/mips/mach-lsmips/
+F: board/loongson/ls1c300-eval/
+F: configs/ls1c300_defconfig
+F: drivers/clk/lsmips/
+F: drivers/watchdog/lsmips_wdt.c
+F: include/configs/ls1c300.h
+F: include/dt-bindings/clock/ls1c300-clk.h
+
MIPS MEDIATEK
M: Weijie Gao <weijie.gao(a)mediatek.com>
R: GSS_MTK_Uboot_upstream <GSS_MTK_Uboot_upstream(a)mediatek.com>
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 06cae68ee5..461bb2a99b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -93,6 +93,16 @@ config ARCH_MTMIPS
select SUPPORTS_LITTLE_ENDIAN
select SUPPORT_SPL
+config ARCH_LSMIPS
+ bool "Support Loongson MIPS platforms"
+ select DM
+ select DM_SERIAL
+ select OF_CONTROL
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ select SUPPORTS_LITTLE_ENDIAN
+ select SUPPORT_SPL
+
config ARCH_JZ47XX
bool "Support Ingenic JZ47xx"
select SUPPORT_SPL
@@ -175,6 +185,7 @@ source "arch/mips/mach-bmips/Kconfig"
source "arch/mips/mach-jz47xx/Kconfig"
source "arch/mips/mach-pic32/Kconfig"
source "arch/mips/mach-mtmips/Kconfig"
+source "arch/mips/mach-lsmips/Kconfig"
source "arch/mips/mach-octeon/Kconfig"
if MIPS
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6502aebd29..e944502497 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -16,6 +16,7 @@ machine-$(CONFIG_ARCH_BMIPS) += bmips
machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
machine-$(CONFIG_MACH_PIC32) += pic32
machine-$(CONFIG_ARCH_MTMIPS) += mtmips
+machine-$(CONFIG_ARCH_LSMIPS) += lsmips
machine-$(CONFIG_ARCH_MSCC) += mscc
machine-${CONFIG_ARCH_OCTEON} += octeon
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 95144b24dc..915acfd573 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_BOARD_MT7620_MT7530_RFB) += mediatek,mt7620-mt7530-rfb.dtb
dtb-$(CONFIG_BOARD_MT7628_RFB) += mediatek,mt7628-rfb.dtb
dtb-$(CONFIG_BOARD_GARDENA_SMART_GATEWAY_MT7688) += gardena-smart-gateway-mt7688.dtb
dtb-$(CONFIG_BOARD_LINKIT_SMART_7688) += linkit-smart-7688.dtb
+dtb-$(CONFIG_BOARD_LS1C300) += ls1c300-eval.dtb
dtb-$(CONFIG_TARGET_OCTEON_EBB7304) += mrvl,octeon-ebb7304.dtb
dtb-$(CONFIG_TARGET_OCTEON_NIC23) += mrvl,octeon-nic23.dtb
dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb
diff --git a/arch/mips/dts/loongson32-ls1c300b.dtsi b/arch/mips/dts/loongson32-ls1c300b.dtsi
new file mode 100644
index 0000000000..a47f1927cd
--- /dev/null
+++ b/arch/mips/dts/loongson32-ls1c300b.dtsi
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ls1c300-clk.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "loongson,ls1c300-soc";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ compatible = "loongson,gs232", "mips,mips4Kc";
+ clocks = <&acc CLK_CPU>;
+ };
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ u-boot,dm-pre-reloc;
+
+ xtal: oscillator {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ #clock-cells = <0>;
+ };
+
+ acc: clock-controller@1fe78030 {
+ compatible = "loongson,ls1c300-clk";
+ clocks = <&xtal>;
+ #clock-cells = <1>;
+ reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
+ u-boot,dm-pre-reloc;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ uart0: serial@1fe40000 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART0>;
+ reg = <0x1fe40000 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart1: serial@1fe44000 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART1>;
+ reg = <0x1fe44000 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart2: serial@1fe48000 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART2>;
+ reg = <0x1fe48000 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart3: serial@1fe4c000 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART3>;
+ reg = <0x1fe4c000 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart4: serial@1fe4c400 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART4>;
+ reg = <0x1fe4c400 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart5: serial@1fe4c500 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART5>;
+ reg = <0x1fe4c500 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart6: serial@1fe4c600 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART6>;
+ reg = <0x1fe4c600 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart7: serial@1fe4c700 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART7>;
+ reg = <0x1fe4c700 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart8: serial@1fe4c800 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART8>;
+ reg = <0x1fe4c800 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart9: serial@1fe4c900 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART9>;
+ reg = <0x1fe4c900 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart10: serial@1fe4ca00 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART10>;
+ reg = <0x1fe4ca00 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ uart11: serial@1fe4cb00 {
+ compatible = "loongson,ls1c300-uart", "ns16550a";
+ clocks = <&acc CLK_UART11>;
+ reg = <0x1fe4cb00 0x100>;
+ reg-shift = <0>;
+
+ status = "disabled";
+ };
+
+ wdt: watchdog@1fe5c060 {
+ compatible = "loongson,ls1c300-wdt";
+ clocks = <&acc CLK_WDT>;
+ reg = <0x1fe5c060 0x10>;
+ };
+
+ reset-controller {
+ compatible = "wdt-reboot";
+ wdt = <&wdt>;
+ };
+
+ };
+};
diff --git a/arch/mips/dts/ls1c300-eval.dts b/arch/mips/dts/ls1c300-eval.dts
new file mode 100644
index 0000000000..eaf65b2d96
--- /dev/null
+++ b/arch/mips/dts/ls1c300-eval.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+/dts-v1/;
+
+#include "loongson32-ls1c300b.dtsi"
+
+/ {
+ compatible = "lsmips,ls1c300-soc";
+ model = "ls1c300-eval";
+
+ aliases {
+ serial0 = &uart2;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x4000000>;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
diff --git a/arch/mips/mach-lsmips/Kconfig b/arch/mips/mach-lsmips/Kconfig
new file mode 100644
index 0000000000..2e43a98bfb
--- /dev/null
+++ b/arch/mips/mach-lsmips/Kconfig
@@ -0,0 +1,76 @@
+menu "Loongson MIPS platforms"
+ depends on ARCH_LSMIPS
+
+config SYS_MALLOC_F_LEN
+ default 0x1000
+
+config SYS_SOC
+ default "ls1c300" if SOC_LS1C300
+
+config SYS_DCACHE_SIZE
+ default 16384
+
+config SYS_DCACHE_LINE_SIZE
+ default 32
+
+config SYS_ICACHE_SIZE
+ default 16384
+
+config SYS_ICACHE_LINE_SIZE
+ default 32
+
+config SYS_TEXT_BASE
+ default 0xbfc00000 if !SPL
+ default 0x80200000 if SPL
+
+config SPL_TEXT_BASE
+ default 0xbfc00000
+
+config SPL_PAYLOAD
+ default "u-boot-lzma.img" if SPL_LZMA
+
+config BUILD_TARGET
+ default "u-boot-with-spl.bin" if SPL
+
+choice
+ prompt "Loongson MIPS SoC select"
+
+config SOC_LS1C300
+ bool "LS1C300"
+ select MIPS_L1_CACHE_SHIFT_5
+ select CLK_CCF
+ select SPL_SEPARATE_BSS if SPL
+ select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
+ select SPL_LOADER_SUPPORT if SPL
+ select SPL_OF_CONTROL if SPL_DM
+ select SPL_SIMPLE_BUS if SPL_DM
+ select SPL_DM_SERIAL if SPL_DM
+ select SPL_CLK if SPL_DM && SPL_SERIAL
+ select SPL_SYSRESET if SPL_DM
+ select SPL_OF_LIBFDT if SPL_OF_CONTROL
+ help
+ This supports Loongson LS1C300
+
+endchoice
+
+choice
+ prompt "Board select"
+
+config BOARD_LS1C300
+ bool "Loongson LS1C300 Eval"
+ depends on SOC_LS1C300
+ help
+ ls1c300-eval board has a LS1C300 SoC with 64MiB of SDRAM
+ and 512KiB of flash (SPI NOR) and additional NAND storage.
+
+endchoice
+
+config CONS_PIN
+ int "pin group used in uart"
+ default 0
+ help
+ Select pin group connected to UART for your board.
+
+source "board/loongson/ls1c300-eval/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-lsmips/Makefile b/arch/mips/mach-lsmips/Makefile
new file mode 100644
index 0000000000..654143a5f7
--- /dev/null
+++ b/arch/mips/mach-lsmips/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+
+obj-$(CONFIG_SOC_LS1C300) += ls1c300/
diff --git a/arch/mips/mach-lsmips/cpu.c b/arch/mips/mach-lsmips/cpu.c
new file mode 100644
index 0000000000..4205d8ef83
--- /dev/null
+++ b/arch/mips/mach-lsmips/cpu.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr(a)denx.de>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
+ return 0;
+}
diff --git a/arch/mips/mach-lsmips/include/mach/serial.h b/arch/mips/mach-lsmips/include/mach/serial.h
new file mode 100644
index 0000000000..4da1cb434c
--- /dev/null
+++ b/arch/mips/mach-lsmips/include/mach/serial.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __LSMIPS_SERIAL_H_
+#define __LSMIPS_SERIAL_H_
+
+void lsmips_spl_serial_init(void);
+int gpio_set_alternate(int gpio, int func);
+
+#endif /* __LSMIPS_SERIAL_H_ */
diff --git a/arch/mips/mach-lsmips/ls1c300/Makefile b/arch/mips/mach-lsmips/ls1c300/Makefile
new file mode 100644
index 0000000000..17b9d6fb9c
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += lowlevel_init.o
+obj-y += sdram.o
+obj-y += init.o
+obj-y += gpio.o
+obj-$(CONFIG_SPL_BUILD) += serial.o
diff --git a/arch/mips/mach-lsmips/ls1c300/gpio.c b/arch/mips/mach-lsmips/ls1c300/gpio.c
new file mode 100644
index 0000000000..2195738b2b
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/gpio.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <linux/errno.h>
+#include <asm/bitops.h>
+
+#define CBUS_FIRST0 0xbfd011c0
+#define CBUS_SECOND0 0xbfd011d0
+#define CBUS_THIRD0 0xbfd011e0
+#define CBUS_FOURTHT0 0xbfd011f0
+#define CBUS_FIFTHT0 0xbfd01200
+
+#define CBUS_FIRST1 0xbfd011c4
+#define CBUS_SECOND1 0xbfd011d4
+#define CBUS_THIRD1 0xbfd011e4
+#define CBUS_FOURTHT1 0xbfd011f4
+#define CBUS_FIFTHT1 0xbfd01204
+
+#define CBUS_FIRST2 0xbfd011c8
+#define CBUS_SECOND2 0xbfd011d8
+#define CBUS_THIRD2 0xbfd011e8
+#define CBUS_FOURTHT2 0xbfd011f8
+#define CBUS_FIFTHT2 0xbfd01208
+
+#define CBUS_FIRST3 0xbfd011cc
+#define CBUS_SECOND3 0xbfd011dc
+#define CBUS_THIRD3 0xbfd011ec
+#define CBUS_FOURTHT3 0xbfd011fc
+#define CBUS_FIFTHT3 0xbfd0120c
+
+/*
+ * pinmux for debug uart and spl only, for others, please
+ * use a pinctrl driver and device-tree for pin muxing.
+ *
+ * @gpio: gpio number
+ * @func: alternate function 1 to 5, 0 for GPIO.
+ */
+
+int gpio_set_alternate(int gpio, int func)
+{
+ volatile void __iomem *addr;
+ int i;
+
+ if (gpio < 0 || gpio > 104)
+ return -ENODEV;
+ if (func < 0 || func > 5)
+ return -EINVAL;
+
+ if (func) {
+ i = func - 1;
+ addr = (void *)CBUS_FIRST0 + i * 16;
+ set_bit(gpio, addr);
+ } else {
+ /* GPIO, clear CBUS 1 ~ 5 */
+ i = 5;
+ }
+
+ while (i--) {
+ addr = (void *)CBUS_FIRST0 + 16 * i;
+ clear_bit(gpio, addr);
+ }
+
+ return 0;
+}
diff --git a/arch/mips/mach-lsmips/ls1c300/init.c b/arch/mips/mach-lsmips/ls1c300/init.c
new file mode 100644
index 0000000000..f86b6fd4f1
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/init.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * based on: arch/mips/mach-mtmips/mt7628/init.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int print_cpuinfo(void)
+{
+ struct udevice *udev;
+ struct clk clk;
+ int ret;
+ ulong xtal;
+ char buf[SZ_32];
+
+ printf("CPU: Loongson ls1c300b\n");
+
+ ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(ls1c300_clk), &udev);
+
+ if (ret) {
+ printf("error: clock driver not found.\n");
+ return 0;
+ }
+
+ clk.dev = udev;
+
+ clk.id = CLK_XTAL;
+ xtal = clk_get_rate(&clk);
+
+ clk.id = CLK_CPU_THROT;
+ gd->cpu_clk = clk_get_rate(&clk);
+
+ clk.id = CLK_SDRAM;
+ gd->mem_clk = clk_get_rate(&clk);
+
+ printf("Clock: CPU: %sMHz, ", strmhz(buf, gd->cpu_clk));
+ printf("SDRAM: %sMHz, ", strmhz(buf, gd->mem_clk));
+ printf("XTAL: %sMHz\n", strmhz(buf, xtal));
+
+ return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+ return gd->cpu_clk;
+}
diff --git a/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
new file mode 100644
index 0000000000..a8d1359cf5
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <config.h>
+#include <asm-offsets.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <linux/sizes.h>
+
+/* PLL control register */
+#define NAND_BASE 0xbfe70000
+#define START_FREQ 0x8030
+#define CLK_DIV_PARAM 0x8034
+#define CPU_THROT 0xc010
+
+/* START_FREQ */
+#define PLL_VALID 31
+#define Reserved_24 24
+#define FRAC_N 16
+#define M_PLL 8
+#define Reserved_4 4
+#define RST_TIME 2
+#define SDRAM_DIV 0
+ #define SDRAM_DIV2 0
+ #define SDRAM_DIV4 1
+ #define SDRAM_DIV3 2
+
+/* CLK_DIV_PARAM */
+#define PIX_DIV 24
+#define CAM_DIV 16
+#define CPU_DIV 8
+#define PIX_DIV_VALID 5
+#define PIX_SEL 4
+#define CAM_DIV_VALID 3
+#define CAM_SEL 2
+#define CPU_DIV_VALID 1
+#define CPU_SEL 0
+
+/* Document:
+ * Freq_PLL = XIN *(M_PLL + FRAC_N)/4
+ */
+#define XIN 24000000
+#define PLL_VALID_1 (1<<PLL_VALID)
+#define PREP_M_PLL(Freq_PLL) (((Freq_PLL * 4) / XIN) << M_PLL)
+#define PREP_SDRAM_DIV(div) (div<<SDRAM_DIV)
+#define PREP_CPU_DIV(div1) ((0x80|div1)<<CPU_DIV | (div1&&div1)<<CPU_DIV_VALID)
+#define PREP_PIX_DIV(div2) (div2<<PIX_DIV)
+#define PREP_CAM_DIV(div3) (div3<<CAM_DIV)
+
+/* PLL @264MHz, CPU @132MHz, SDRAM @66MHz */
+#define CFG_START_FREQ (PLL_VALID_1 | PREP_M_PLL(264000000) | SDRAM_DIV2)
+#define CFG_CLK_DIV_PARAM (PREP_CPU_DIV(2) | PREP_PIX_DIV(0x24) | PREP_CAM_DIV(0x24))
+#define CFG_CPU_THROT 15
+
+/* SPI0 control register */
+#define SPI0_BASE 0xbfe80000
+#define SPCR 0
+#define SPSR 1
+#define TxFIFO 2
+#define RxFIFO 2
+#define SPER 3
+#define SFC_PARAM 4
+ #define CLK_DIV 4
+ #define DUAL_IO 3
+ #define FAST_READ 2
+ #define BURST_EN 1
+ #define MEMORY_EN 0
+#define SFC_SOFTCS 5
+#define SFC_TIMING 6
+ #define T_FAST 2
+ #define T_CSH 0
+
+ .set noreorder
+LEAF(ls1c300_pll_init)
+#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
+ li t0, NAND_BASE
+ li t1, CFG_START_FREQ
+ li t2, CFG_CLK_DIV_PARAM
+ li t3, CFG_CPU_THROT
+
+ sw t3, CPU_THROT (t0)
+ sw t2, CLK_DIV_PARAM (t0)
+ sw t1, START_FREQ (t0)
+ nop
+
+ ori t2, 1<<CPU_SEL
+ sw t2, CLK_DIV_PARAM (t0)
+#endif
+ li v0, 264000000
+ jr ra
+ nop
+END(ls1c300_pll_init)
+
+LEAF(ls1c300_spi_init)
+#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
+ li t0, SPI0_BASE
+ li t1, (1<<MEMORY_EN) | (1<<BURST_EN) | (1<<FAST_READ) | (1<<DUAL_IO)
+ sb t1, SFC_PARAM (t0)
+ li t2, (1<<T_FAST) | (1<<T_CSH)
+ sb t2, SFC_TIMING (t0)
+#endif
+ jr ra
+ nop
+END(ls1c300_spi_init)
+
+NESTED(lowlevel_init, 0, ra)
+ /* Save ra and do real lowlevel initialization */
+ move s0, ra
+ /* Setup PLL @264MHz */
+ PTR_LA t9, ls1c300_pll_init
+ jalr t9
+ nop
+
+ /* Setup SPI Dual IO@33MHz */
+ PTR_LA t9, ls1c300_spi_init
+ jalr t9
+ nop
+
+ /* Setup external SDRAM @66MHz */
+ PTR_LA t9, ls1c300_sdram_init
+ jalr t9
+ nop
+
+ move ra, s0
+ jr ra
+ nop
+END(lowlevel_init)
diff --git a/arch/mips/mach-lsmips/ls1c300/sdram.S b/arch/mips/mach-lsmips/ls1c300/sdram.S
new file mode 100644
index 0000000000..6b3a347508
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/sdram.S
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <config.h>
+#include <asm-offsets.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <linux/sizes.h>
+
+/* sdram control 64 bit register */
+#define SD_CONFIG 0xbfd00000
+#define SD_CONFIGHI 0x414
+#define SD_CONFIGLO 0x410
+
+#define CONFIG_VALID 41
+#define HANG_UP 40
+#define DEF_SEL 39
+#define TWR 37
+#define TREF 25
+#define TRAS 21
+#define TRFC 17
+#define TRP 14
+#define TCL 11
+#define TRCD 8
+
+#define SD_BIT 6
+ #define SD_8BIT (0<<SD_BIT)
+ #define SD_16BIT (1<<SD_BIT)
+ #define SD_32BIT (2<<SD_BIT)
+#define SD_CSIZE 3
+ #define SD_CSIZE_512 (0<<SD_CSIZE)
+ #define SD_CSIZE_1K (1<<SD_CSIZE)
+ #define SD_CSIZE_2K (2<<SD_CSIZE)
+ #define SD_CSIZE_4K (3<<SD_CSIZE)
+ #define SD_CSIZE_256 (7<<SD_CSIZE)
+#define SD_RSIZE 0
+ #define SD_RSIZE_2K (0<<SD_RSIZE)
+ #define SD_RSIZE_4K (1<<SD_RSIZE)
+ #define SD_RSIZE_8K (2<<SD_RSIZE)
+ #define SD_RSIZE_16K (3<<SD_RSIZE)
+
+#define SD_CFG_1(tWR, tREF, tRAS, tRFC, tRP, tCL, tRCD) \
+ ((tWR<<TWR)|(tREF<<TREF)|(tRAS<<TRAS)|(tRFC<<TRFC)|(tRP<<TRP)|(tCL<<TCL)|(tRCD<<TRCD))
+#define CFG_SD_0(b, c, r) \
+ ((b<<SD_BIT)|(c<<SD_CSIZE)|(r<<SD_RSIZE))
+
+/* recommended values by ls1c300 user manual,
+ * tweat to fit your board.
+ */
+#define SD_CONFIG_133MHz SD_CFG_1(2, 0x818, 6, 8, 3, 3, 3)
+#define SD_CONFIG_100MHz SD_CFG_1(2, 0x620, 5, 6, 2, 3, 2)
+#define SD_CONFIG_75MHz SD_CFG_1(1, 0x494, 4, 5, 2, 2, 2)
+#define SD_CONFIG_33MHz SD_CFG_1(1, 0x204, 2, 2, 1, 2, 1)
+
+#define SD_CONFIG_66MHz SD_CFG_1(1, 0x401, 4, 4, 2, 2, 2)
+
+#define SD_CONFIG64 (SD_CONFIG_66MHz | SD_16BIT | SD_CSIZE_1K | SD_RSIZE_8K)
+#define CFG_SDCONFIGHI (SD_CONFIG64 /(1<<32))
+#define CFG_SDCONFIGLO (SD_CONFIG64 %(1<<32))
+
+ .set noreorder
+/* Loongson ls1c300 SoC do not have onchip sram for initial stack,
+ * initialize the external sdram on reset as early as possiable.
+ */
+LEAF(ls1c300_sdram_init)
+#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
+ li t0, SD_CONFIG
+ li t1, CFG_SDCONFIGLO
+ li t2, CFG_SDCONFIGHI
+
+ sw t1, SD_CONFIGLO (t0)
+ sw t2, SD_CONFIGHI (t0)
+ nop
+
+ sw t1, SD_CONFIGLO (t0)
+ sw t2, SD_CONFIGHI (t0)
+ nop
+
+ ori t2, 1<<(CONFIG_VALID-32)
+ sw t1, SD_CONFIGLO (t0)
+ sw t2, SD_CONFIGHI (t0)
+#endif
+ li v0, SZ_64M
+ jr ra
+ nop
+END(ls1c300_sdram_init)
+
+
diff --git a/arch/mips/mach-lsmips/ls1c300/serial.c b/arch/mips/mach-lsmips/ls1c300/serial.c
new file mode 100644
index 0000000000..e13762d973
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/serial.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <mach/serial.h>
+#include <linux/kernel.h>
+
+struct uart_pin_config {
+ char port;
+ char af;
+ char rx;
+ char tx;
+};
+
+struct uart_pin_config con[] = {
+#if CONFIG_CONS_INDEX == 0
+{ 0, 2, 74, 75 },
+{ 0, 3, 23, 24 },
+{ 0, 3, 99, 100 },
+
+#elif CONFIG_CONS_INDEX == 1
+{ 1, 1, 17, 18 },
+{ 1, 1, 101, 102 },
+{ 1, 2, 40, 41 },
+{ 1, 4, 2, 3 },
+
+#elif CONFIG_CONS_INDEX == 2
+{ 2, 2, 36, 37 },
+{ 2, 2, 42, 43 },
+{ 2, 3, 27, 28 },
+{ 2, 3, 103, 104 },
+{ 2, 4, 4, 5 },
+
+#elif CONFIG_CONS_INDEX == 3
+{ 3, 2, 17, 18 },
+{ 3, 2, 33, 34 },
+{ 3, 2, 44, 45 },
+{ 3, 4, 0, 1 },
+
+#elif CONFIG_CONS_INDEX == 4
+{ 4, 5, 23, 24 },
+{ 4, 5, 58, 59 },
+{ 4, 5, 80, 79 },
+
+#elif CONFIG_CONS_INDEX == 5
+{ 5, 5, 25, 26 },
+{ 5, 5, 60, 61 },
+{ 5, 5, 81, 78 },
+
+#elif CONFIG_CONS_INDEX == 6
+{ 6, 5, 27, 46 },
+{ 6, 5, 62, 63 },
+
+#elif CONFIG_CONS_INDEX == 7
+{ 7, 5, 57, 56 },
+{ 7, 5, 64, 65 },
+{ 7, 5, 87, 88 },
+
+#elif CONFIG_CONS_INDEX == 8
+{ 8, 5, 55, 54 },
+{ 8, 5, 66, 67 },
+{ 8, 5, 89, 90 },
+
+#elif CONFIG_CONS_INDEX == 9
+{ 9, 5, 53, 52 },
+{ 9, 5, 68, 69 },
+{ 9, 5, 85, 86 },
+
+#elif CONFIG_CONS_INDEX == 10
+{ 10, 5, 51, 50 },
+{ 10, 5, 70, 71 },
+{ 10, 5, 84, 82 },
+
+#elif CONFIG_CONS_INDEX == 11
+{ 11, 5, 49, 48 },
+{ 11, 5, 72, 73 },
+#endif /* CONFIG_CONS_INDEX */
+};
+
+#define UART2_RX 36
+#define UART2_TX 37
+#define AFUNC 2
+
+void lsmips_spl_serial_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL
+ int pin_rx, pin_tx;
+ int afunc;
+
+ if (CONFIG_CONS_PIN < ARRAY_SIZE(con)) {
+ pin_rx = con[CONFIG_CONS_PIN].rx;
+ pin_tx = con[CONFIG_CONS_PIN].tx;
+ afunc = con[CONFIG_CONS_PIN].af;
+ } else {
+ pin_rx = UART2_RX;
+ pin_tx = UART2_TX;
+ afunc = AFUNC;
+ }
+
+ gpio_set_alternate(pin_rx, afunc);
+ gpio_set_alternate(pin_tx, afunc);
+#endif /* CONFIG_SPL_SERIAL */
+ return ;
+}
diff --git a/arch/mips/mach-lsmips/spl.c b/arch/mips/mach-lsmips/spl.c
new file mode 100644
index 0000000000..c7c28989f2
--- /dev/null
+++ b/arch/mips/mach-lsmips/spl.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <spl.h>
+#include <asm/sections.h>
+#include <linux/libfdt.h>
+#include <linux/sizes.h>
+#include <mach/serial.h>
+
+void __noreturn board_init_f(ulong dummy)
+{
+ spl_init();
+
+#ifdef CONFIG_SPL_SERIAL
+ /*
+ * lsmips_spl_serial_init() is useful if debug uart is enabled,
+ * or DM based serial is not enabled.
+ */
+ lsmips_spl_serial_init();
+ preloader_console_init();
+#endif
+
+ board_init_r(NULL, 0);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+ spl_boot_list[0] = BOOT_DEVICE_NOR;
+}
+
+unsigned long spl_nor_get_uboot_base(void)
+{
+ void *uboot_base = __image_copy_end;
+
+ if (fdt_magic(uboot_base) == FDT_MAGIC)
+ return (unsigned long)uboot_base + fdt_totalsize(uboot_base);
+
+ return (unsigned long)uboot_base;
+}
diff --git a/board/loongson/ls1c300-eval/Kconfig b/board/loongson/ls1c300-eval/Kconfig
new file mode 100644
index 0000000000..e427570a83
--- /dev/null
+++ b/board/loongson/ls1c300-eval/Kconfig
@@ -0,0 +1,12 @@
+if BOARD_LS1C300
+
+config SYS_BOARD
+ default "ls1c300-eval"
+
+config SYS_VENDOR
+ default "loongson"
+
+config SYS_CONFIG_NAME
+ default "ls1c300"
+
+endif
diff --git a/board/loongson/ls1c300-eval/MAINTAINERS b/board/loongson/ls1c300-eval/MAINTAINERS
new file mode 100644
index 0000000000..5420198dab
--- /dev/null
+++ b/board/loongson/ls1c300-eval/MAINTAINERS
@@ -0,0 +1,7 @@
+LS1C300_EVAL BOARD
+M: Du Huanpeng<dhu(a)hodcarrier.org>
+S: Maintained
+F: board/loongson/ls1c300-eval
+F: include/configs/ls1c300.h
+F: configs/ls1c300_defconfig
+F: arch/mips/dts/ls1c300-eval.dts
diff --git a/board/loongson/ls1c300-eval/Makefile b/board/loongson/ls1c300-eval/Makefile
new file mode 100644
index 0000000000..db129c5aba
--- /dev/null
+++ b/board/loongson/ls1c300-eval/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += board.o
diff --git a/board/loongson/ls1c300-eval/board.c b/board/loongson/ls1c300-eval/board.c
new file mode 100644
index 0000000000..2f588a0dcb
--- /dev/null
+++ b/board/loongson/ls1c300-eval/board.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <mach/serial.h>
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+
+#define UART2_RX 36
+#define UART2_TX 37
+#define AFUNC 2
+
+void board_debug_uart_init(void)
+{
+ gpio_set_alternate(UART2_TX, AFUNC);
+ gpio_set_alternate(UART2_RX, AFUNC);
+}
+#endif
diff --git a/configs/ls1c300_defconfig b/configs/ls1c300_defconfig
new file mode 100644
index 0000000000..3f0689c7f9
--- /dev/null
+++ b/configs/ls1c300_defconfig
@@ -0,0 +1,54 @@
+CONFIG_MIPS=y
+CONFIG_SYS_MALLOC_F_LEN=0x40000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x1000
+CONFIG_DEFAULT_DEVICE_TREE="ls1c300-eval"
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL_SIZE_LIMIT=0x100000
+CONFIG_SPL=y
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xbfe48000
+CONFIG_DEBUG_UART_CLOCK=66000000
+CONFIG_ARCH_LSMIPS=y
+CONFIG_SPL_PAYLOAD="u-boot.img"
+CONFIG_ROM_EXCEPTION_VECTORS=y
+# CONFIG_MIPS_CACHE_SETUP is not set
+# CONFIG_MIPS_CACHE_DISABLE is not set
+CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEBUG_UART=y
+CONFIG_SYS_LOAD_ADDR=0x80010000
+CONFIG_FIT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_LOGLEVEL=9
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_NOR_SUPPORT=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_CLK=y
+# CONFIG_CMD_LOADS is not set
+# CONFIG_PARTITIONS is not set
+CONFIG_OF_EMBED=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+# CONFIG_NET is not set
+CONFIG_CLK=y
+CONFIG_SPL_CLK_CCF=y
+# CONFIG_INPUT is not set
+# CONFIG_POWER is not set
+CONFIG_CONS_INDEX=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_WATCHDOG=y
+CONFIG_SYSRESET_WATCHDOG_AUTO=y
+CONFIG_WATCHDOG_TIMEOUT_MSECS=3000
+CONFIG_WDT_LSMIPS=y
+CONFIG_REGEX=y
+# CONFIG_GZIP is not set
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bb4eee5d99..51562ca4a6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -17,6 +17,7 @@ obj-y += tegra/
obj-y += ti/
obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_LSMIPS) += lsmips/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
diff --git a/drivers/clk/lsmips/Makefile b/drivers/clk/lsmips/Makefile
new file mode 100644
index 0000000000..0a47269cd3
--- /dev/null
+++ b/drivers/clk/lsmips/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
diff --git a/drivers/clk/lsmips/clk-ls1c300.c b/drivers/clk/lsmips/clk-ls1c300.c
new file mode 100644
index 0000000000..fe274e2570
--- /dev/null
+++ b/drivers/clk/lsmips/clk-ls1c300.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * reference:
+ * drivers/clk/microchip/mpfs_clk.c
+ * drivers/clk/clk_octeon.c
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/* PLL/SDRAM Frequency Configuration Register */
+#define START_FREQ 0
+#define CLK_DIV_PARAM 4
+
+/* START_FREQ */
+#define PLL_VALID BIT(31)
+#define RESERVED0 GENMASK(30, 24)
+#define FRAC_N GENMASK(23, 16)
+#define M_PLL GENMASK(15, 8)
+#define RESERVED1 GENMASK(7, 4)
+#define RST_TIME GENMASK(3, 2)
+#define SDRAM_DIV GENMASK(1, 0)
+/* CLK_DIV_PARAM */
+#define PIX_DIV GENMASK(31, 24)
+#define CAM_DIV GENMASK(23, 16)
+#define CPU_DIV GENMASK(15, 8)
+#define RESERVED2 GENMASK(7, 6)
+#define PIX_DIV_VALID BIT(5)
+#define PIX_SEL BIT(4)
+#define CAM_DIV_VALID BIT(3)
+#define CAM_SEL BIT(2)
+#define CPU_DIV_VALID BIT(1)
+#define CPU_SEL BIT(0)
+/* CPU_THROT */
+#define CPU_THROT GENMASK(3, 0)
+
+static const struct clk_div_table sdram_div_table[] = {
+ {.val = 0, .div = 2},
+ {.val = 1, .div = 4},
+ {.val = 2, .div = 3},
+ {.val = 3, .div = 3},
+};
+
+ulong ls1c300_pll_get_rate(struct clk *clk)
+{
+ unsigned int mult, div;
+ unsigned int val;
+ long long parent_rate;
+ void *base;
+
+ parent_rate = clk_get_parent_rate(clk);
+ base = (void *)clk->data;
+ val = readl(base + START_FREQ);
+
+ mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
+ div = 4;
+ val = (mult * parent_rate) / div;
+
+ return val;
+}
+
+static ulong ls1c300_clk_get_rate(struct clk *clk)
+{
+ struct clk *cl;
+ ulong rate;
+ int err;
+
+ err = clk_get_by_id(clk->id, &cl);
+ if (err)
+ return err;
+
+ rate = clk_get_rate(cl);
+ return rate;
+}
+
+static int ls1c300_clk_probe(struct udevice *dev)
+{
+ void __iomem *base;
+ void __iomem *cpu_throt;
+ void __iomem *addr;
+
+ struct clk *cl, clk;
+
+ int ret;
+ const char *parent_name;
+ unsigned int mult, div;
+ int flags;
+
+ base = (void *)dev_remap_addr_index(dev, 0);
+ cpu_throt = (void *)dev_remap_addr_index(dev, 1);
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_get_rate(&clk);
+
+ parent_name = clk.dev->name;
+
+ cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+ cl->data = (unsigned long)base;
+ ret = clk_register(cl, "clk-ls1c300-pll", "pll", parent_name);
+ clk_dm(CLK_PLL, cl);
+
+ addr = base + CLK_DIV_PARAM;
+ flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+ cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr, 8, 7, flags);
+ clk_dm(CLK_CPU, cl);
+ cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
+ clk_dm(CLK_CAMERA, cl);
+ cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
+ clk_dm(CLK_PIX, cl);
+
+ mult = FIELD_GET(CPU_THROT, readl(cpu_throt)) + 1;
+ div = 16;
+ cl = clk_register_fixed_factor(NULL, "cpu_throt_factor", "cpu_div", CLK_GET_RATE_NOCACHE, mult, div);
+ clk_dm(CLK_CPU_THROT, cl);
+
+ addr = base + START_FREQ;
+ cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
+ to_clk_divider(cl)->table = sdram_div_table;
+ clk_dm(CLK_SDRAM, cl);
+
+ return 0;
+}
+
+static const struct udevice_id ls1c300_clk_ids[] = {
+ { .compatible = "loongson,ls1c300-clk" },
+ { }
+};
+
+struct clk_ops clk_ls1c300_pll_ops = {
+ .get_rate = ls1c300_pll_get_rate,
+};
+
+static const struct clk_ops ls1c300_clk_ops = {
+ .get_rate = ls1c300_clk_get_rate,
+};
+
+U_BOOT_DRIVER(clk_ls1c300_pll) = {
+ .name = "clk-ls1c300-pll",
+ .id = UCLASS_CLK,
+ .ops = &clk_ls1c300_pll_ops,
+};
+
+U_BOOT_DRIVER(ls1c300_clk) = {
+ .name = "ls1c300-clk",
+ .id = UCLASS_CLK,
+ .of_match = ls1c300_clk_ids,
+ .probe = ls1c300_clk_probe,
+ .priv_auto = sizeof(struct clk),
+ .ops = &ls1c300_clk_ops,
+};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 5b614cfa6e..a9af5e5eb6 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -168,6 +168,14 @@ config WDT_GPIO
doc/device-tree-bindings/watchdog/gpio-wdt.txt for
information on how to describe the watchdog in device tree.
+config WDT_LSMIPS
+ bool "Loongson MIPS watchdog timer support"
+ depends on WDT
+ help
+ Select this to enable watchdog timer for Loongson SoCs.
+ The watchdog timer is stopped when initialized.
+ It performs full SoC reset.
+
config WDT_MPC8xx
bool "MPC8xx watchdog timer support"
depends on WDT && MPC8xx
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a35bd559f5..cb596af904 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
+obj-$(CONFIG_WDT_LSMIPS) += lsmips_wdt.o
obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
diff --git a/drivers/watchdog/lsmips_wdt.c b/drivers/watchdog/lsmips_wdt.c
new file mode 100644
index 0000000000..1e0c4a3a7c
--- /dev/null
+++ b/drivers/watchdog/lsmips_wdt.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Watchdog driver for MediaTek SoCs
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee(a)mediatek.com>
+ *
+ * based on: drivers/watchdog/mtk_wdt.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <hang.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <clk.h>
+
+
+struct lsmips_wdt_priv {
+ void __iomem *base;
+#define WDT_EN 0
+#define WDT_TIMER 4
+#define WDT_SET 8
+ ulong clock;
+ unsigned long timeout;
+};
+
+static int lsmips_wdt_reset(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(priv->timeout, priv->base + WDT_TIMER);
+ writel(1, priv->base + WDT_SET);
+
+ return 0;
+}
+
+static int lsmips_wdt_stop(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(0, priv->base + WDT_EN);
+ return 0;
+}
+
+static int lsmips_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(1, priv->base + WDT_EN);
+ writel(1, priv->base + WDT_TIMER);
+ writel(1, priv->base + WDT_SET);
+
+ hang();
+ return 0;
+}
+
+static int lsmips_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+ unsigned int timeout;
+
+ timeout = U32_MAX / (priv->clock / 1000);
+
+ if (timeout < timeout_ms)
+ timeout = U32_MAX;
+ else
+ timeout = timeout_ms * (priv->clock / 1000);
+
+ debug("WDT: reload = %08x\n", timeout);
+
+ writel(1, priv->base + WDT_EN);
+ writel(timeout, priv->base + WDT_TIMER);
+ writel(1, priv->base + WDT_SET);
+
+ priv->timeout = timeout;
+
+ return 0;
+}
+
+static int lsmips_wdt_probe(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+ struct clk cl;
+
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -ENOENT;
+
+ if (clk_get_by_index(dev, 0, &cl) == 0)
+ priv->clock = clk_get_rate(&cl);
+
+ if (priv->clock < 45000000 || priv->clock > 133000000) {
+ /*
+ * according to datasheet, the SDRAM works at the range frequency of 45~133MHz,
+ * the watchdog's clock is the same with the SDRAM, see page 32.
+ * so, if we got a clock out of this range,
+ * probably the clock is wrong or working without SDRAM.
+ * assign a default value 1^26 in this case.
+ */
+ priv->clock = 67108864;
+ }
+
+ debug("WDT: clock = %ld\n", priv->clock);
+
+ writel(0, priv->base + WDT_EN);
+ return 0;
+}
+
+static const struct wdt_ops lsmips_wdt_ops = {
+ .start = lsmips_wdt_start,
+ .reset = lsmips_wdt_reset,
+ .stop = lsmips_wdt_stop,
+ .expire_now = lsmips_wdt_expire_now,
+};
+
+static const struct udevice_id lsmips_wdt_ids[] = {
+ { .compatible = "loongson,ls1c300-wdt"},
+ {}
+};
+
+U_BOOT_DRIVER(lsmips_wdt) = {
+ .name = "lsmips_wdt",
+ .id = UCLASS_WDT,
+ .of_match = lsmips_wdt_ids,
+ .priv_auto = sizeof(struct lsmips_wdt_priv),
+ .probe = lsmips_wdt_probe,
+ .ops = &lsmips_wdt_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/ls1c300.h b/include/configs/ls1c300.h
new file mode 100644
index 0000000000..c460b4564b
--- /dev/null
+++ b/include/configs/ls1c300.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ * based on: include/configs/mt7628.h
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __CONFIG_LS1C300_H__
+#define __CONFIG_LS1C300_H__
+
+#define CONFIG_SYS_HZ 1000
+
+#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+#define CONFIG_SYS_LOAD_ADDR 0x80010000
+
+#define CONFIG_SYS_INIT_SP_OFFSET 0x80000
+
+#define CONFIG_SYS_BOOTM_LEN 0x1000000
+
+#define CONFIG_SYS_MAXARGS 16
+#define CONFIG_SYS_CBSIZE 1024
+
+/* Serial SPL */
+#define CONFIG_SYS_NS16550_SERIAL
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL)
+#define CONFIG_SYS_NS16550_CLK 66000000
+#define CONFIG_SYS_NS16550_REG_SIZE (-1)
+#define CONFIG_SYS_NS16550_COM1 0xbfe44000
+#define CONFIG_SYS_NS16550_COM2 0xbfe48000
+#define CONFIG_SYS_NS16550_COM3 0xbfe4c000
+#define CONFIG_SYS_NS16550_COM4 0xbfe4c400
+#define CONFIG_SYS_NS16550_COM5 0xbfe4c500
+#define CONFIG_SYS_NS16550_COM6 0xbfe4c600
+#endif
+
+/* Serial common */
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }
+
+/* SPL */
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+#define CONFIG_SKIP_LOWLEVEL_INIT 1
+#endif
+
+#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE
+#define CONFIG_SPL_BSS_START_ADDR 0x80010000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x10000
+#define CONFIG_SPL_MAX_SIZE 0x10000
+#define CONFIG_SPL_PAD_TO 0
+
+#define CONFIG_MALLOC_F_ADDR 0x80100000 /* FIXME: find a proper place */
+
+/* Dummy value */
+#define CONFIG_SYS_UBOOT_BASE 0
+
+#endif /* __CONFIG_LS1C300_H__ */
diff --git a/include/dt-bindings/clock/ls1c300-clk.h b/include/dt-bindings/clock/ls1c300-clk.h
new file mode 100644
index 0000000000..735fa61789
--- /dev/null
+++ b/include/dt-bindings/clock/ls1c300-clk.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __DT_BINDINGS_LS1C300_CLK_H__
+#define __DT_BINDINGS_LS1C300_CLK_H__
+
+/* Base clocks */
+#define CLK_XTAL 0
+#define CLK_PLL 1
+#define CLK_CPU 2
+#define CLK_CPU_THROT 7
+#define CLK_SDRAM 3
+
+#define CLK_CAMERA 4
+#define CLK_DC 5
+#define CLK_PIX 5
+#define CLK_AXIMUX 6
+
+/* Peripheral clocks */
+#define CLK_UART0 3
+#define CLK_UART1 3
+#define CLK_UART2 3
+#define CLK_UART3 3
+#define CLK_UART4 3
+#define CLK_UART5 3
+#define CLK_UART6 3
+#define CLK_UART7 3
+#define CLK_UART8 3
+#define CLK_UART9 3
+#define CLK_UART10 3
+#define CLK_UART11 3
+#define CLK_CAN0 3
+#define CLK_CAN1 3
+#define CLK_I2C0 3
+#define CLK_PWM 3
+#define CLK_I2S 3
+#define CLK_RTC 3
+#define CLK_I2C1 3
+#define CLK_SDIO 3
+#define CLK_I2C2 3
+#define CLK_ADC 3
+#define CLK_NAND 3
+
+#define CLK_WDT 3
+
+#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
--
2.25.1
2
1
Loongson 1C is a cost-effective SOC chip for industrial control and
the Internet of Things. The Loongson 1C includes a floating-point
processing unit, supports multiple types of memory, and supports
high-capacity MLC NAND Flash. Loongson 1C provides developers with a
wealth of peripheral interfaces and on-chip modules, including Camera
controller, USB OTG and USB HOST interfaces, AC97/I2S controller, LCD
controller, SPI interface, UART interface, etc., providing sufficient
computing power and multi-application connectivity.
Some highlights of this SoC are:
- Single core LS232, MIPS32 instruction set compatible, main frequency
300MHZ
- 16KB data cache and 16KB instruction cache
- 64 bit float unit, hardware division
- 8/16 bit SDRAM controller, 45 ~ 133MHz
- 8/16 bit SRAM, NAND
- I2S/AC97, LCD, MAC, USB, OTG, SPI, I2C, PWM, CAN, SDIO, ADC
- 12 UARTs
See Techinical Reference Manual for details: https://www.loongson.cn/
introduce base support for the ls1c300 SoC.
- debug UART2
- serial console
- clock
- watchdog
- sysreset
- many uarts
Signed-off-by: Du Huanpeng <dhu(a)hodcarrier.org>
---
arch/mips/Kconfig | 25 +++
arch/mips/Makefile | 1 +
arch/mips/dts/Makefile | 1 +
arch/mips/dts/loongson32-ls1c300b.dtsi | 138 +++++++++++++++++
arch/mips/dts/ls1c300-eval.dts | 27 ++++
arch/mips/mach-lsmips/Kconfig | 77 ++++++++++
arch/mips/mach-lsmips/Makefile | 6 +
arch/mips/mach-lsmips/cpu.c | 24 +++
arch/mips/mach-lsmips/include/mach/serial.h | 16 ++
arch/mips/mach-lsmips/ls1c300/Makefile | 6 +
arch/mips/mach-lsmips/ls1c300/gpio.c | 60 ++++++++
arch/mips/mach-lsmips/ls1c300/init.c | 60 ++++++++
arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 123 +++++++++++++++
arch/mips/mach-lsmips/ls1c300/ls1c300.h | 52 +++++++
arch/mips/mach-lsmips/ls1c300/serial.c | 112 ++++++++++++++
arch/mips/mach-lsmips/spl.c | 47 ++++++
board/loongson/ls1c300-eval/Kconfig | 12 ++
board/loongson/ls1c300-eval/MAINTAINERS | 7 +
board/loongson/ls1c300-eval/Makefile | 3 +
board/loongson/ls1c300-eval/board.c | 20 +++
configs/ls1c300_defconfig | 65 ++++++++
drivers/clk/Makefile | 1 +
drivers/clk/lsmips/Makefile | 3 +
drivers/clk/lsmips/clk-ls1c300.c | 145 ++++++++++++++++++
drivers/watchdog/Kconfig | 8 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/lsmips_wdt.c | 126 +++++++++++++++
include/configs/ls1c300.h | 61 ++++++++
include/dt-bindings/clock/ls1c300-clk.h | 48 ++++++
29 files changed, 1275 insertions(+)
create mode 100644 arch/mips/dts/loongson32-ls1c300b.dtsi
create mode 100644 arch/mips/dts/ls1c300-eval.dts
create mode 100644 arch/mips/mach-lsmips/Kconfig
create mode 100644 arch/mips/mach-lsmips/Makefile
create mode 100644 arch/mips/mach-lsmips/cpu.c
create mode 100644 arch/mips/mach-lsmips/include/mach/serial.h
create mode 100644 arch/mips/mach-lsmips/ls1c300/Makefile
create mode 100644 arch/mips/mach-lsmips/ls1c300/gpio.c
create mode 100644 arch/mips/mach-lsmips/ls1c300/init.c
create mode 100644 arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
create mode 100644 arch/mips/mach-lsmips/ls1c300/ls1c300.h
create mode 100644 arch/mips/mach-lsmips/ls1c300/serial.c
create mode 100644 arch/mips/mach-lsmips/spl.c
create mode 100644 board/loongson/ls1c300-eval/Kconfig
create mode 100644 board/loongson/ls1c300-eval/MAINTAINERS
create mode 100644 board/loongson/ls1c300-eval/Makefile
create mode 100644 board/loongson/ls1c300-eval/board.c
create mode 100644 configs/ls1c300_defconfig
create mode 100644 drivers/clk/lsmips/Makefile
create mode 100644 drivers/clk/lsmips/clk-ls1c300.c
create mode 100644 drivers/watchdog/lsmips_wdt.c
create mode 100644 include/configs/ls1c300.h
create mode 100644 include/dt-bindings/clock/ls1c300-clk.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 28234aa0bb..d95868ef4b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -93,6 +93,30 @@ config ARCH_MTMIPS
select SUPPORTS_LITTLE_ENDIAN
select SUPPORT_SPL
+config ARCH_LSMIPS
+ bool "Support Loongson MIPS platforms"
+ select CLK
+ imply CMD_DM
+ select DISPLAY_CPUINFO
+ select DM
+ imply DM_ETH
+ imply DM_GPIO
+ select DM_RESET
+ select DM_SERIAL
+ select PINCTRL
+ select PINMUX
+ select PINCONF
+ select RESET_LSMIPS
+ imply DM_SPI
+ imply DM_SPI_FLASH
+ select OF_CONTROL
+ select ROM_EXCEPTION_VECTORS
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ select SUPPORTS_LITTLE_ENDIAN
+ select SYSRESET
+ select SUPPORT_SPL
+
config ARCH_JZ47XX
bool "Support Ingenic JZ47xx"
select SUPPORT_SPL
@@ -174,6 +198,7 @@ source "arch/mips/mach-bmips/Kconfig"
source "arch/mips/mach-jz47xx/Kconfig"
source "arch/mips/mach-pic32/Kconfig"
source "arch/mips/mach-mtmips/Kconfig"
+source "arch/mips/mach-lsmips/Kconfig"
source "arch/mips/mach-octeon/Kconfig"
if MIPS
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6502aebd29..e944502497 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -16,6 +16,7 @@ machine-$(CONFIG_ARCH_BMIPS) += bmips
machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
machine-$(CONFIG_MACH_PIC32) += pic32
machine-$(CONFIG_ARCH_MTMIPS) += mtmips
+machine-$(CONFIG_ARCH_LSMIPS) += lsmips
machine-$(CONFIG_ARCH_MSCC) += mscc
machine-${CONFIG_ARCH_OCTEON} += octeon
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 95144b24dc..915acfd573 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_BOARD_MT7620_MT7530_RFB) += mediatek,mt7620-mt7530-rfb.dtb
dtb-$(CONFIG_BOARD_MT7628_RFB) += mediatek,mt7628-rfb.dtb
dtb-$(CONFIG_BOARD_GARDENA_SMART_GATEWAY_MT7688) += gardena-smart-gateway-mt7688.dtb
dtb-$(CONFIG_BOARD_LINKIT_SMART_7688) += linkit-smart-7688.dtb
+dtb-$(CONFIG_BOARD_LS1C300) += ls1c300-eval.dtb
dtb-$(CONFIG_TARGET_OCTEON_EBB7304) += mrvl,octeon-ebb7304.dtb
dtb-$(CONFIG_TARGET_OCTEON_NIC23) += mrvl,octeon-nic23.dtb
dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb
diff --git a/arch/mips/dts/loongson32-ls1c300b.dtsi b/arch/mips/dts/loongson32-ls1c300b.dtsi
new file mode 100644
index 0000000000..a574495301
--- /dev/null
+++ b/arch/mips/dts/loongson32-ls1c300b.dtsi
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ls1c300-clk.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "loongson,ls1c300-soc";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ compatible = "loongson,gs232", "mips,mips4Kc";
+ clocks = <&acc CLK_CPU>;
+ };
+ };
+
+ xtal: oscillator@0 {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ #clock-cells = <0>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ // TODO: add more device.
+
+ acc: clock-controller@1fe78030 {
+ compatible = "loongson,ls1c300-clk";
+ clocks = <&xtal>;
+ #clock-cells = <1>;
+ reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
+ u-boot,dm-pre-reloc;
+ };
+
+ uart0: serial@1fe40000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART0>;
+ reg = <0x1fe40000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart1: serial@1fe44000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART1>;
+ reg = <0x1fe44000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart2: serial@bfe48000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART2>;
+ reg = <0xbfe48000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart3: serial@1fe4c000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART3>;
+ reg = <0x1fe4c000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart4: serial@1fe4c400 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART4>;
+ reg = <0x1fe4c400 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart5: serial@1fe4c500 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART5>;
+ reg = <0x1fe4c500 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart6: serial@1fe4c600 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART6>;
+ reg = <0x1fe4c600 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart7: serial@1fe4c700 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART7>;
+ reg = <0x1fe4c700 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart8: serial@1fe4c800 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART8>;
+ reg = <0x1fe4c800 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart9: serial@1fe4c900 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART9>;
+ reg = <0x1fe4c900 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart10: serial@1fe4ca00 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART10>;
+ reg = <0x1fe4ca00 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart11: serial@1fe4cb00 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART11>;
+ reg = <0x1fe4cb00 0x100>;
+ reg-shift = <0>;
+ };
+
+ wdt: watchdog@1fe5c060 {
+ compatible = "loongson,ls1c300-wdt";
+ clocks = <&acc CLK_WDT>;
+ reg = <0x1fe5c060 0x10>;
+ };
+
+ reset-controller {
+ compatible = "wdt-reboot";
+ wdt = <&wdt>;
+ };
+
+ };
+};
diff --git a/arch/mips/dts/ls1c300-eval.dts b/arch/mips/dts/ls1c300-eval.dts
new file mode 100644
index 0000000000..5bf1ec0985
--- /dev/null
+++ b/arch/mips/dts/ls1c300-eval.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+/dts-v1/;
+
+#include "loongson32-ls1c300b.dtsi"
+
+/ {
+ compatible = "lsmips,ls1c300-soc";
+ model = "ls1c300-eval";
+
+ aliases {
+ console = &uart2;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200";
+ stdout-path = &uart2;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
diff --git a/arch/mips/mach-lsmips/Kconfig b/arch/mips/mach-lsmips/Kconfig
new file mode 100644
index 0000000000..cb679875a7
--- /dev/null
+++ b/arch/mips/mach-lsmips/Kconfig
@@ -0,0 +1,77 @@
+menu "Loongson MIPS platforms"
+ depends on ARCH_LSMIPS
+
+config SYS_MALLOC_F_LEN
+ default 0x1000
+
+config SYS_SOC
+ default "ls1c300" if SOC_LS1C300
+
+config SYS_DCACHE_SIZE
+ default 16384
+
+config SYS_DCACHE_LINE_SIZE
+ default 32
+
+config SYS_ICACHE_SIZE
+ default 16384
+
+config SYS_ICACHE_LINE_SIZE
+ default 32
+
+config SYS_TEXT_BASE
+ default 0xbfc00000 if !SPL
+ default 0x80200000 if SPL
+
+config SPL_TEXT_BASE
+ default 0xbfc00000
+
+config SPL_PAYLOAD
+ default "u-boot-lzma.img" if SPL_LZMA
+
+config BUILD_TARGET
+ default "u-boot-with-spl.bin" if SPL
+
+choice
+ prompt "Loongson MIPS SoC select"
+
+config SOC_LS1C300
+ bool "LS1C300"
+ select MIPS_L1_CACHE_SHIFT_5
+ select PINCTRL_LS1C300
+ select CLK_CCF
+ select SPL_SEPARATE_BSS if SPL
+ select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
+ select SPL_LOADER_SUPPORT if SPL
+ select SPL_OF_CONTROL if SPL_DM
+ select SPL_SIMPLE_BUS if SPL_DM
+ select SPL_DM_SERIAL if SPL_DM
+ select SPL_CLK if SPL_DM && SPL_SERIAL
+ select SPL_SYSRESET if SPL_DM
+ select SPL_OF_LIBFDT if SPL_OF_CONTROL
+ help
+ This supports Loongson LS1C300
+
+endchoice
+
+choice
+ prompt "Board select"
+
+config BOARD_LS1C300
+ bool "Loongson LS1C300 Eval"
+ depends on SOC_LS1C300
+ help
+ ls1c300-eval board has a LS1C300 SoC with 64MiB of SDRAM
+ and 512KiB of flash (SPI NOR) and additional NAND storage.
+
+endchoice
+
+config CONS_PIN_SELECT
+ int "pin group used in uart"
+ default 0
+ help
+ Select pin group connected to UART for your board.
+
+source "board/loongson/ls1c300-eval/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-lsmips/Makefile b/arch/mips/mach-lsmips/Makefile
new file mode 100644
index 0000000000..654143a5f7
--- /dev/null
+++ b/arch/mips/mach-lsmips/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+
+obj-$(CONFIG_SOC_LS1C300) += ls1c300/
diff --git a/arch/mips/mach-lsmips/cpu.c b/arch/mips/mach-lsmips/cpu.c
new file mode 100644
index 0000000000..00513253e8
--- /dev/null
+++ b/arch/mips/mach-lsmips/cpu.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr(a)denx.de>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+#ifdef CONFIG_SKIP_LOWLEVEL_INIT
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
+#else
+ gd->ram_size = SZ_64M;
+#endif
+
+ return 0;
+}
diff --git a/arch/mips/mach-lsmips/include/mach/serial.h b/arch/mips/mach-lsmips/include/mach/serial.h
new file mode 100644
index 0000000000..4da1cb434c
--- /dev/null
+++ b/arch/mips/mach-lsmips/include/mach/serial.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __LSMIPS_SERIAL_H_
+#define __LSMIPS_SERIAL_H_
+
+void lsmips_spl_serial_init(void);
+int gpio_set_alternate(int gpio, int func);
+
+#endif /* __LSMIPS_SERIAL_H_ */
diff --git a/arch/mips/mach-lsmips/ls1c300/Makefile b/arch/mips/mach-lsmips/ls1c300/Makefile
new file mode 100644
index 0000000000..d30069e67e
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += lowlevel_init.o
+obj-y += init.o
+obj-y += gpio.o
+obj-$(CONFIG_SPL_BUILD) += serial.o
diff --git a/arch/mips/mach-lsmips/ls1c300/gpio.c b/arch/mips/mach-lsmips/ls1c300/gpio.c
new file mode 100644
index 0000000000..cca91aed93
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/gpio.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#define CBUS_FIRST0 0xbfd011c0
+#define CBUS_SECOND0 0xbfd011d0
+#define CBUS_THIRD0 0xbfd011e0
+#define CBUS_FOURTHT0 0xbfd011f0
+#define CBUS_FIFTHT0 0xbfd01200
+
+#define CBUS_FIRST1 0xbfd011c4
+#define CBUS_SECOND1 0xbfd011d4
+#define CBUS_THIRD1 0xbfd011e4
+#define CBUS_FOURTHT1 0xbfd011f4
+#define CBUS_FIFTHT1 0xbfd01204
+
+#define CBUS_FIRST2 0xbfd011c8
+#define CBUS_SECOND2 0xbfd011d8
+#define CBUS_THIRD2 0xbfd011e8
+#define CBUS_FOURTHT2 0xbfd011f8
+#define CBUS_FIFTHT2 0xbfd01208
+
+#define CBUS_FIRST3 0xbfd011cc
+#define CBUS_SECOND3 0xbfd011dc
+#define CBUS_THIRD3 0xbfd011ec
+#define CBUS_FOURTHT3 0xbfd011fc
+#define CBUS_FIFTHT3 0xbfd0120c
+
+int gpio_set_alternate(int gpio, int func)
+{
+ volatile void __iomem *addr;
+ int i;
+
+ if (gpio < 0 || gpio > 104)
+ return -ENODEV;
+ if (func < 0)
+ return -EINVAL;
+
+ if (func) {
+ i = func - 1;
+ addr = (void *)CBUS_FIRST0 + i * 16;
+ set_bit(gpio, addr);
+ } else {
+ /* GPIO, clear CBUS 1 ~ 5 */
+ i = 5;
+ }
+
+ while (i--) {
+ addr = (void *)CBUS_FIRST0 + 16 * i;
+ clear_bit(gpio, addr);
+ }
+
+ return 0;
+}
diff --git a/arch/mips/mach-lsmips/ls1c300/init.c b/arch/mips/mach-lsmips/ls1c300/init.c
new file mode 100644
index 0000000000..457beeedca
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/init.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * based on: arch/mips/mach-mtmips/mt7628/init.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include "ls1c300.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int print_cpuinfo(void)
+{
+ struct udevice *udev;
+ struct clk clk;
+ int ret;
+ ulong xtal;
+ char buf[SZ_32];
+
+ printf("CPU: Loongson ls1c300b\n");
+
+ ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(ls1c300_clk), &udev);
+
+ if (ret) {
+ printf("error: clock driver not found.\n");
+ return 0;
+ }
+
+ clk.dev = udev;
+
+ clk.id = CLK_XTAL;
+ xtal = clk_get_rate(&clk);
+
+ clk.id = CLK_CPU_THROT;
+ gd->cpu_clk = clk_get_rate(&clk);
+
+ clk.id = CLK_SDRAM;
+ gd->mem_clk = clk_get_rate(&clk);
+
+ printf("Clock: CPU: %sMHz, ", strmhz(buf, gd->cpu_clk));
+ printf("SDRAM: %sMHz, ", strmhz(buf, gd->mem_clk));
+ printf("XTAL: %sMHz\n", strmhz(buf, xtal));
+
+ return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+ return gd->cpu_clk;
+}
diff --git a/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
new file mode 100644
index 0000000000..f9e2f94e83
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <config.h>
+#include <asm-offsets.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <linux/sizes.h>
+
+/* PLL */
+#define NAND_BASE 0xbfe78000
+#define START_FREQ 0xbfe78030
+#define CLK_DIV_PARAM 0xbfe78034
+
+/* SPI */
+#define SPI0_BASE 0xbfe80000
+
+/* SDRAM */
+#define SD_CONFIG 0xbfd00000
+#define SD_CONFIGL 0xbfd00410
+#define SD_CONFIGH 0xbfd00414
+
+ .set noreorder
+
+/* PLL: 264MHz CPU: 132MHz SDRAM: 66MHz */
+LEAF(ls1c300_pll_init)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ li t0, NAND_BASE
+ li t2, 555844098
+ sw t2, 0x34 (t0)
+
+ li t1, 2147494924
+ sw t1, 0x30 (t0)
+
+ ori t2, 1
+ sw t2, 0x34 (t0)
+#endif
+/* TODO: recalc rate to v0 */
+ li v0, 132000000
+ jr ra
+ nop
+END(ls1c300_pll_init)
+
+/* SPI: Dual IO@33MHz */
+LEAF(ls1c300_spi_init)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ li t0, SPI0_BASE
+ li t1, 0x07
+ li t2, 0x05
+ sb t1, 0x4(t0)
+ sb t1, 0x6(t0)
+#endif
+ jr ra
+ nop
+END(ls1c300_spi_init)
+
+/* SDRAM: 66MHz */
+// 8M x 16Bit x 4 Banks */
+// Organization | Row Address | Column Address
+// 32Mx16 | A0~A12 | A0-A9
+
+// 128Mx4 | A0~A12 | A0-A9, A11, A12
+// 64Mx8 | A0~A12 | A0-A9, A11
+// 32Mx16 | A0~A12 | A0-A9
+
+LEAF(ls1c300_sdram_init)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ li t0, SD_CONFIG
+ li t1, 0x028A924A
+ li t2, 0x00000028
+sdram_cfg:
+ sw t1, 0x410(t0)
+ sw t2, 0x414(t0)
+ nop
+ sw t1, 0x410(t0)
+ sw t2, 0x414(t0)
+ ori t2, 0x200
+ sw t1, 0x410(t0)
+ sw t2, 0x414(t0)
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+ li v0, SZ_64M
+ jr ra
+ nop
+END(ls1c300_sdram_init)
+
+
+/*
+ * SDRAM@132MHz, CPU@297MHz, SPI@33MHz
+ * SDRAM@100MHz, CPU@300MHz, SPI@50MHz
+ * SDRAM@66MHz, CPU@132MHz, SPI@33MHz <--
+ */
+
+NESTED(lowlevel_init, 0, ra)
+ /* Save ra and do real lowlevel initialization */
+ move s0, ra
+ /* Setup PLL @264MHz */
+ PTR_LA t9, ls1c300_pll_init
+ jalr t9
+ nop
+
+ /* Setup SPI Dual IO@33MHz */
+ PTR_LA t9, ls1c300_spi_init
+ jalr t9
+ nop
+
+ /* Setup external SDRAM @66MHz */
+ PTR_LA t9, ls1c300_sdram_init
+ jalr t9
+ nop
+
+ move ra, s0
+ jr ra
+ nop
+END(lowlevel_init)
diff --git a/arch/mips/mach-lsmips/ls1c300/ls1c300.h b/arch/mips/mach-lsmips/ls1c300/ls1c300.h
new file mode 100644
index 0000000000..70a5def841
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/ls1c300.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __LS1C300_H__
+#define __LS1C300_H__
+
+/* generated, don't edit */
+
+#define SDRAM_BASE 0x00000000
+#define CAMERA_BASE 0x1c280000
+#define DC_BASE 0x1c300000
+#define AXIMUX_BASE 0x1f000000
+
+#define SPI0MEM_BASE 0x1d000000
+#define SPI1MEM_BASE 0x1e000000
+#define Boot_BASE 0xbfc00000
+#define CONFREG_BASE 0x1fd00000
+#define OTG_BASE 0x1fe00000
+#define MAC_BASE 0x1fe10000
+#define USB_BASE 0x1fe20000
+#define APB_BASE 0x1fe40000
+#define SPI0_BASE 0x1fe80000
+#define SPI1_BASE 0x1fec0000
+
+#define UART0_BASE 0x1fe40000
+#define UART1_BASE 0x1fe44000
+#define UART2_BASE 0x1fe48000
+#define UART3_BASE 0x1fe4c000
+#define UART4_BASE 0x1fe4c400
+#define UART5_BASE 0x1fe4c500
+#define UART6_BASE 0x1fe4c600
+#define UART7_BASE 0x1fe4c700
+#define UART8_BASE 0x1fe4c800
+#define UART9_BASE 0x1fe4c900
+#define UART10_BASE 0x1fe4ca00
+#define UART11_BASE 0x1fe4cb00
+#define CAN0_BASE 0x1fe50000
+#define CAN1_BASE 0x1fe54000
+#define I2C0_BASE 0x1fe58000
+#define PWM_BASE 0x1fe5c000
+#define I2S_BASE 0x1fe60000
+#define RTC_BASE 0x1fe64000
+#define I2C1_BASE 0x1fe68000
+#define SDIO_BASE 0x1fe6c000
+#define I2C2_BASE 0x1fe70000
+#define ADC_BASE 0x1fe74000
+#define NAND_BASE 0x1fe78000
+#define HCNTR_BASE 0x1fe7c000
+
+#endif /* __LS1C300_H__ */
diff --git a/arch/mips/mach-lsmips/ls1c300/serial.c b/arch/mips/mach-lsmips/ls1c300/serial.c
new file mode 100644
index 0000000000..88bc18ef85
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/serial.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mach/serial.h>
+#include <linux/kernel.h>
+#include "ls1c300.h"
+
+struct uart_pin_config {
+ char port;
+ char af;
+ char rx;
+ char tx;
+};
+
+struct uart_pin_config con[] = {
+#if CONFIG_CONS_INDEX == 0
+{ 0, 2, 74, 75 },
+{ 0, 3, 23, 24 },
+{ 0, 3, 99, 100 },
+
+#elif CONFIG_CONS_INDEX == 1
+{ 1, 1, 17, 18 },
+{ 1, 1, 101, 102 },
+{ 1, 2, 40, 41 },
+{ 1, 4, 2, 3 },
+
+#elif CONFIG_CONS_INDEX == 2
+{ 2, 2, 36, 37 },
+{ 2, 2, 42, 43 },
+{ 2, 3, 27, 28 },
+{ 2, 3, 103, 104 },
+{ 2, 4, 4, 5 },
+
+#elif CONFIG_CONS_INDEX == 3
+{ 3, 2, 17, 18 },
+{ 3, 2, 33, 34 },
+{ 3, 2, 44, 45 },
+{ 3, 4, 0, 1 },
+
+#elif CONFIG_CONS_INDEX == 4
+{ 4, 5, 23, 24 },
+{ 4, 5, 58, 59 },
+{ 4, 5, 80, 79 },
+
+#elif CONFIG_CONS_INDEX == 5
+{ 5, 5, 25, 26 },
+{ 5, 5, 60, 61 },
+{ 5, 5, 81, 78 },
+
+#elif CONFIG_CONS_INDEX == 6
+{ 6, 5, 27, 46 },
+{ 6, 5, 62, 63 },
+
+#elif CONFIG_CONS_INDEX == 7
+{ 7, 5, 57, 56 },
+{ 7, 5, 64, 65 },
+{ 7, 5, 87, 88 },
+
+#elif CONFIG_CONS_INDEX == 8
+{ 8, 5, 55, 54 },
+{ 8, 5, 66, 67 },
+{ 8, 5, 89, 90 },
+
+#elif CONFIG_CONS_INDEX == 9
+{ 9, 5, 53, 52 },
+{ 9, 5, 68, 69 },
+{ 9, 5, 85, 86 },
+
+#elif CONFIG_CONS_INDEX == 10
+{ 10, 5, 51, 50 },
+{ 10, 5, 70, 71 },
+{ 10, 5, 84, 82 },
+
+#elif CONFIG_CONS_INDEX == 11
+{ 11, 5, 49, 48 },
+{ 11, 5, 72, 73 },
+#endif /* CONFIG_CONS_INDEX */
+};
+
+#define UART2_RX 36
+#define UART2_TX 37
+#define AFUNC 2
+
+void lsmips_spl_serial_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL
+ int pin_rx, pin_tx;
+ int afunc;
+
+ if (CONFIG_CONS_PIN_SELECT < ARRAY_SIZE(con)) {
+ pin_rx = con[CONFIG_CONS_PIN_SELECT].rx;
+ pin_tx = con[CONFIG_CONS_PIN_SELECT].tx;
+ afunc = con[CONFIG_CONS_PIN_SELECT].af;
+ } else {
+ pin_rx = UART2_RX;
+ pin_tx = UART2_TX;
+ afunc = AFUNC;
+ }
+
+ gpio_set_alternate(pin_rx, afunc);
+ gpio_set_alternate(pin_tx, afunc);
+#endif /* CONFIG_SPL_SERIAL */
+ return ;
+}
diff --git a/arch/mips/mach-lsmips/spl.c b/arch/mips/mach-lsmips/spl.c
new file mode 100644
index 0000000000..c7c28989f2
--- /dev/null
+++ b/arch/mips/mach-lsmips/spl.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <spl.h>
+#include <asm/sections.h>
+#include <linux/libfdt.h>
+#include <linux/sizes.h>
+#include <mach/serial.h>
+
+void __noreturn board_init_f(ulong dummy)
+{
+ spl_init();
+
+#ifdef CONFIG_SPL_SERIAL
+ /*
+ * lsmips_spl_serial_init() is useful if debug uart is enabled,
+ * or DM based serial is not enabled.
+ */
+ lsmips_spl_serial_init();
+ preloader_console_init();
+#endif
+
+ board_init_r(NULL, 0);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+ spl_boot_list[0] = BOOT_DEVICE_NOR;
+}
+
+unsigned long spl_nor_get_uboot_base(void)
+{
+ void *uboot_base = __image_copy_end;
+
+ if (fdt_magic(uboot_base) == FDT_MAGIC)
+ return (unsigned long)uboot_base + fdt_totalsize(uboot_base);
+
+ return (unsigned long)uboot_base;
+}
diff --git a/board/loongson/ls1c300-eval/Kconfig b/board/loongson/ls1c300-eval/Kconfig
new file mode 100644
index 0000000000..e427570a83
--- /dev/null
+++ b/board/loongson/ls1c300-eval/Kconfig
@@ -0,0 +1,12 @@
+if BOARD_LS1C300
+
+config SYS_BOARD
+ default "ls1c300-eval"
+
+config SYS_VENDOR
+ default "loongson"
+
+config SYS_CONFIG_NAME
+ default "ls1c300"
+
+endif
diff --git a/board/loongson/ls1c300-eval/MAINTAINERS b/board/loongson/ls1c300-eval/MAINTAINERS
new file mode 100644
index 0000000000..5420198dab
--- /dev/null
+++ b/board/loongson/ls1c300-eval/MAINTAINERS
@@ -0,0 +1,7 @@
+LS1C300_EVAL BOARD
+M: Du Huanpeng<dhu(a)hodcarrier.org>
+S: Maintained
+F: board/loongson/ls1c300-eval
+F: include/configs/ls1c300.h
+F: configs/ls1c300_defconfig
+F: arch/mips/dts/ls1c300-eval.dts
diff --git a/board/loongson/ls1c300-eval/Makefile b/board/loongson/ls1c300-eval/Makefile
new file mode 100644
index 0000000000..db129c5aba
--- /dev/null
+++ b/board/loongson/ls1c300-eval/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += board.o
diff --git a/board/loongson/ls1c300-eval/board.c b/board/loongson/ls1c300-eval/board.c
new file mode 100644
index 0000000000..2f588a0dcb
--- /dev/null
+++ b/board/loongson/ls1c300-eval/board.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <mach/serial.h>
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+
+#define UART2_RX 36
+#define UART2_TX 37
+#define AFUNC 2
+
+void board_debug_uart_init(void)
+{
+ gpio_set_alternate(UART2_TX, AFUNC);
+ gpio_set_alternate(UART2_RX, AFUNC);
+}
+#endif
diff --git a/configs/ls1c300_defconfig b/configs/ls1c300_defconfig
new file mode 100644
index 0000000000..c47fe5b98f
--- /dev/null
+++ b/configs/ls1c300_defconfig
@@ -0,0 +1,65 @@
+CONFIG_MIPS=y
+CONFIG_SYS_MALLOC_F_LEN=0x40000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x30000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_DEFAULT_DEVICE_TREE="ls1c300-eval"
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL_SIZE_LIMIT=0x100000
+CONFIG_SPL=y
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xbfe48000
+CONFIG_DEBUG_UART_CLOCK=66000000
+CONFIG_ARCH_LSMIPS=y
+CONFIG_SPL_PAYLOAD="u-boot.img"
+# CONFIG_MIPS_CACHE_SETUP is not set
+# CONFIG_MIPS_CACHE_DISABLE is not set
+CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEBUG_UART=y
+CONFIG_SYS_LOAD_ADDR=0x80010000
+CONFIG_FIT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_LOGLEVEL=9
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_NOR_SUPPORT=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_CLK=y
+# CONFIG_CMD_DM is not set
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_SPI=y
+CONFIG_CMD_WDT=y
+# CONFIG_PARTITIONS is not set
+CONFIG_OF_EMBED=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+# CONFIG_NET is not set
+# CONFIG_INPUT is not set
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XMC=y
+CONFIG_CONS_INDEX=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_SYSRESET_WATCHDOG=y
+CONFIG_SYSRESET_WATCHDOG_AUTO=y
+CONFIG_WATCHDOG_TIMEOUT_MSECS=3000
+CONFIG_WDT_LSMIPS=y
+CONFIG_REGEX=y
+CONFIG_LZMA=y
+CONFIG_SPL_LZMA=y
+CONFIG_SPL_GZIP=y
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bb4eee5d99..51562ca4a6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -17,6 +17,7 @@ obj-y += tegra/
obj-y += ti/
obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_LSMIPS) += lsmips/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
diff --git a/drivers/clk/lsmips/Makefile b/drivers/clk/lsmips/Makefile
new file mode 100644
index 0000000000..0a47269cd3
--- /dev/null
+++ b/drivers/clk/lsmips/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
diff --git a/drivers/clk/lsmips/clk-ls1c300.c b/drivers/clk/lsmips/clk-ls1c300.c
new file mode 100644
index 0000000000..c78e23d695
--- /dev/null
+++ b/drivers/clk/lsmips/clk-ls1c300.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * reference:
+ * drivers/clk/microchip/mpfs_clk.c
+ * drivers/clk/clk_octeon.c
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/* START_FREQ */
+#define PLL_VALID BIT(31)
+#define RESERVED0 GENMASK(30, 24)
+#define FRAC_N GENMASK(23, 16)
+#define M_PLL GENMASK(15, 8)
+#define RESERVED1 GENMASK(7, 4)
+#define RST_TIME GENMASK(3, 2)
+#define SDRAM_DIV GENMASK(1, 0)
+/* CLK_DIV_PARAM */
+#define PIX_DIV GENMASK(31, 24)
+#define CAM_DIV GENMASK(23, 16)
+#define CPU_DIV GENMASK(15, 8)
+#define RESERVED2 GENMASK(7, 6)
+#define PIX_DIV_VALID BIT(5)
+#define PIX_SEL BIT(4)
+#define CAM_DIV_VALID BIT(3)
+#define CAM_SEL BIT(2)
+#define CPU_DIV_VALID BIT(1)
+#define CPU_SEL BIT(0)
+/* CPU_THROT */
+#define CPU_THROT GENMASK(3, 0)
+
+static const struct clk_div_table sdram_div_table[] = {
+ {.val = 0, .div = 2},
+ {.val = 1, .div = 4},
+ {.val = 2, .div = 3},
+ {.val = 3, .div = 3},
+};
+
+static ulong ls1c300_clk_get_rate(struct clk *clk)
+{
+ struct clk *cl;
+ ulong rate;
+ int err;
+
+ err = clk_get_by_id(clk->id, &cl);
+ if (err)
+ return err;
+
+ rate = clk_get_rate(cl);
+ return rate;
+}
+
+static int ls1c300_clk_enable(struct clk *clk)
+{
+ /* Nothing to do on Octeon */
+ return 0;
+}
+
+static const struct clk_ops ls1c300_clk_ops = {
+ .enable = ls1c300_clk_enable,
+ .get_rate = ls1c300_clk_get_rate,
+};
+
+static int ls1c300_clk_probe(struct udevice *dev)
+{
+ void __iomem *base;
+ void __iomem *cpu_throt;
+ void __iomem *addr;
+
+ struct clk *cl, clk;
+
+ int ret;
+ const char *parent_name;
+ unsigned int mult, div;
+ unsigned int val;
+ int flags;
+
+ base = (void *)dev_remap_addr_index(dev, 0);
+#define START_FREQ (0)
+#define CLK_DIV_PARAM (4)
+ cpu_throt = (void *)dev_remap_addr_index(dev, 1);
+
+ debug(" base: %p\n", base);
+ debug("cpu_throt: %p\n", cpu_throt);
+
+ val = readl(base + START_FREQ);
+ debug(" START_FREQ: [%08x]\n", val);
+ val = readl(base + CLK_DIV_PARAM);
+ debug("CLK_DIV_PARAM: [%08x]\n", val);
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_get_rate(&clk);
+
+ parent_name = clk.dev->name;
+ val = readl(base + START_FREQ);
+ mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val); div = 4;
+ cl = clk_register_fixed_factor(NULL, "pll", parent_name, 0, mult, div);
+ clk_dm(CLK_PLL, cl);
+
+ addr = base + CLK_DIV_PARAM;
+ flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+ cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr, 8, 7, flags);
+ clk_dm(CLK_CPU, cl);
+ cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
+ clk_dm(CLK_CAMERA, cl);
+ cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
+ clk_dm(CLK_PIX, cl);
+
+ mult = FIELD_GET(CPU_THROT, readl(cpu_throt)) + 1; div = 16;
+ cl = clk_register_fixed_factor(NULL, "cpu_throt_factor", "cpu_div", CLK_GET_RATE_NOCACHE, mult, div);
+ clk_dm(CLK_CPU_THROT, cl);
+
+ addr = base + START_FREQ;
+ cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
+ to_clk_divider(cl)->table = sdram_div_table;
+ clk_dm(CLK_SDRAM, cl);
+
+ return 0;
+}
+
+static const struct udevice_id ls1c300_clk_ids[] = {
+ { .compatible = "loongson,ls1c300-clk" },
+ { }
+};
+
+U_BOOT_DRIVER(ls1c300_clk) = {
+ .name = "ls1c300-clk",
+ .id = UCLASS_CLK,
+ .of_match = ls1c300_clk_ids,
+ .probe = ls1c300_clk_probe,
+ .priv_auto = sizeof(struct clk),
+ .ops = &ls1c300_clk_ops,
+};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f90f0ca02b..289b568188 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -167,6 +167,14 @@ config WDT_GPIO
doc/device-tree-bindings/watchdog/gpio-wdt.txt for
information on how to describe the watchdog in device tree.
+config WDT_LSMIPS
+ bool "Loongson MIPS watchdog timer support"
+ depends on WDT
+ help
+ Select this to enable watchdog timer for Loongson SoCs.
+ The watchdog timer is stopped when initialized.
+ It performs full SoC reset.
+
config WDT_MPC8xx
bool "MPC8xx watchdog timer support"
depends on WDT && MPC8xx
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a35bd559f5..cb596af904 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
+obj-$(CONFIG_WDT_LSMIPS) += lsmips_wdt.o
obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
diff --git a/drivers/watchdog/lsmips_wdt.c b/drivers/watchdog/lsmips_wdt.c
new file mode 100644
index 0000000000..ef91cae349
--- /dev/null
+++ b/drivers/watchdog/lsmips_wdt.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Watchdog driver for MediaTek SoCs
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee(a)mediatek.com>
+ *
+ * based on: drivers/watchdog/mtk_wdt.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <hang.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <clk.h>
+
+#define WDT_EN (priv->base + 0)
+#define WDT_TIMER (priv->base + 4)
+#define WDT_SET (priv->base + 8)
+
+struct lsmips_wdt_priv {
+ void __iomem *base;
+ ulong clock;
+ unsigned long timeout;
+};
+
+static int lsmips_wdt_reset(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(priv->timeout, WDT_TIMER);
+ writel(1, WDT_SET);
+
+ return 0;
+}
+
+static int lsmips_wdt_stop(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(0, WDT_EN);
+ return 0;
+}
+
+static int lsmips_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(1, WDT_EN);
+ writel(1, WDT_TIMER);
+ writel(1, WDT_SET);
+
+ hang();
+ return 0;
+}
+
+static int lsmips_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+ unsigned int timeout;
+
+ timeout = U32_MAX / (priv->clock / 1000);
+
+ if (timeout < timeout_ms)
+ timeout = U32_MAX;
+ else
+ timeout = timeout_ms * (priv->clock / 1000);
+
+ debug("WDT: reload = %08x\n", timeout);
+
+ writel(1, WDT_EN);
+ writel(timeout, WDT_TIMER);
+ writel(1, WDT_SET);
+
+ priv->timeout = timeout;
+
+ return 0;
+}
+
+static int lsmips_wdt_probe(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+ struct clk cl;
+
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -ENOENT;
+
+ if (clk_get_by_index(dev, 0, &cl) == 0)
+ priv->clock = clk_get_rate(&cl);
+
+ if (priv->clock < 33000000 || priv->clock > 150000000) {
+ /* assume 67MHz by default */
+ priv->clock = 67108864;
+ }
+
+ debug("WDT: clock = %ld\n", priv->clock);
+
+ writel(0, WDT_EN);
+ return 0;
+}
+
+static const struct wdt_ops lsmips_wdt_ops = {
+ .start = lsmips_wdt_start,
+ .reset = lsmips_wdt_reset,
+ .stop = lsmips_wdt_stop,
+ .expire_now = lsmips_wdt_expire_now,
+};
+
+static const struct udevice_id lsmips_wdt_ids[] = {
+ { .compatible = "loongson,ls1c300-wdt"},
+ {}
+};
+
+U_BOOT_DRIVER(lsmips_wdt) = {
+ .name = "lsmips_wdt",
+ .id = UCLASS_WDT,
+ .of_match = lsmips_wdt_ids,
+ .priv_auto = sizeof(struct lsmips_wdt_priv),
+ .probe = lsmips_wdt_probe,
+ .ops = &lsmips_wdt_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/ls1c300.h b/include/configs/ls1c300.h
new file mode 100644
index 0000000000..a96deb6bb2
--- /dev/null
+++ b/include/configs/ls1c300.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao(a)mediatek.com>
+ * based on: include/configs/mt7628.h
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __CONFIG_LS1C300_H__
+#define __CONFIG_LS1C300_H__
+
+#define CONFIG_SYS_HZ 1000
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+#define CONFIG_SYS_LOAD_ADDR 0x80010000
+
+#define CONFIG_SYS_INIT_SP_OFFSET 0x80000
+
+#define CONFIG_SYS_BOOTM_LEN 0x1000000
+
+#define CONFIG_SYS_MAXARGS 16
+#define CONFIG_SYS_CBSIZE 1024
+
+/* Serial SPL */
+#define CONFIG_SYS_NS16550_SERIAL
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL)
+#define CONFIG_SYS_NS16550_CLK 66000000
+#define CONFIG_SYS_NS16550_REG_SIZE (-1)
+#define CONFIG_SYS_NS16550_COM1 0xbfe44000
+#define CONFIG_SYS_NS16550_COM2 0xbfe48000
+#define CONFIG_SYS_NS16550_COM3 0xbfe4c000
+#define CONFIG_SYS_NS16550_COM4 0xbfe4c400
+#define CONFIG_SYS_NS16550_COM5 0xbfe4c500
+#define CONFIG_SYS_NS16550_COM6 0xbfe4c600
+#endif
+
+/* Serial common */
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }
+
+/* SPL */
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
+
+#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE
+#define CONFIG_SPL_BSS_START_ADDR 0x80010000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x10000
+#define CONFIG_SPL_MAX_SIZE 0x10000
+#define CONFIG_SPL_PAD_TO 0
+
+#define CONFIG_MALLOC_F_ADDR 0x80100000 /* FIXME: find a proper place */
+
+/* Dummy value */
+#define CONFIG_SYS_UBOOT_BASE 0
+
+#endif /* __CONFIG_LS1C300_H__ */
diff --git a/include/dt-bindings/clock/ls1c300-clk.h b/include/dt-bindings/clock/ls1c300-clk.h
new file mode 100644
index 0000000000..735fa61789
--- /dev/null
+++ b/include/dt-bindings/clock/ls1c300-clk.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu(a)hodcarrier.org>
+ */
+
+#ifndef __DT_BINDINGS_LS1C300_CLK_H__
+#define __DT_BINDINGS_LS1C300_CLK_H__
+
+/* Base clocks */
+#define CLK_XTAL 0
+#define CLK_PLL 1
+#define CLK_CPU 2
+#define CLK_CPU_THROT 7
+#define CLK_SDRAM 3
+
+#define CLK_CAMERA 4
+#define CLK_DC 5
+#define CLK_PIX 5
+#define CLK_AXIMUX 6
+
+/* Peripheral clocks */
+#define CLK_UART0 3
+#define CLK_UART1 3
+#define CLK_UART2 3
+#define CLK_UART3 3
+#define CLK_UART4 3
+#define CLK_UART5 3
+#define CLK_UART6 3
+#define CLK_UART7 3
+#define CLK_UART8 3
+#define CLK_UART9 3
+#define CLK_UART10 3
+#define CLK_UART11 3
+#define CLK_CAN0 3
+#define CLK_CAN1 3
+#define CLK_I2C0 3
+#define CLK_PWM 3
+#define CLK_I2S 3
+#define CLK_RTC 3
+#define CLK_I2C1 3
+#define CLK_SDIO 3
+#define CLK_I2C2 3
+#define CLK_ADC 3
+#define CLK_NAND 3
+
+#define CLK_WDT 3
+
+#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
--
2.25.1
4
5
Hi Tom,
The following changes since commit 59bffec43a657598b194b9eb30dc01eec06078c7:
Merge branch '2022-04-04-platform-updates' (2022-04-05 13:45:22 -0400)
are available in the Git repository at:
https://source.denx.de/u-boot/custodians/u-boot-riscv.git
for you to fetch changes up to 776e8aca0bad2900dc9c12b87dedb732a9f8e39b:
riscv: alloc space exhausted (2022-04-06 10:58:13 +0800)
CI result shows no issue: https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/11595
----------------------------------------------------------------
Heinrich Schuchardt (5):
cmd: sbi: add Performance Monitoring Unit Extension
riscv: provide missing base extension functions
cmd/sbi: add missing SBI information
riscv: enable CONFIG_CMD_SBI for QEMU boards
riscv: alloc space exhausted
Kconfig | 2 +-
arch/riscv/Kconfig | 3 ---
arch/riscv/include/asm/sbi.h | 4 ++++
arch/riscv/lib/sbi.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
board/emulation/qemu-riscv/Kconfig | 1 +
cmd/riscv/sbi.c | 14 +++++++++++++-
6 files changed, 84 insertions(+), 5 deletions(-)
Best regards,
Leo
2
1