162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/clk.h> 762306a36Sopenharmony_ci#include <linux/dma-mapping.h> 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/mtd/partitions.h> 1062306a36Sopenharmony_ci#include <linux/sizes.h> 1162306a36Sopenharmony_ci#include <linux/phy.h> 1262306a36Sopenharmony_ci#include <linux/serial_8250.h> 1362306a36Sopenharmony_ci#include <linux/stmmac.h> 1462306a36Sopenharmony_ci#include <linux/usb/ehci_pdriver.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <platform.h> 1762306a36Sopenharmony_ci#include <loongson1.h> 1862306a36Sopenharmony_ci#include <dma.h> 1962306a36Sopenharmony_ci#include <nand.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 8250/16550 compatible UART */ 2262306a36Sopenharmony_ci#define LS1X_UART(_id) \ 2362306a36Sopenharmony_ci { \ 2462306a36Sopenharmony_ci .mapbase = LS1X_UART ## _id ## _BASE, \ 2562306a36Sopenharmony_ci .irq = LS1X_UART ## _id ## _IRQ, \ 2662306a36Sopenharmony_ci .iotype = UPIO_MEM, \ 2762306a36Sopenharmony_ci .flags = UPF_IOREMAP | UPF_FIXED_TYPE, \ 2862306a36Sopenharmony_ci .type = PORT_16550A, \ 2962306a36Sopenharmony_ci } 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic struct plat_serial8250_port ls1x_serial8250_pdata[] = { 3262306a36Sopenharmony_ci LS1X_UART(0), 3362306a36Sopenharmony_ci LS1X_UART(1), 3462306a36Sopenharmony_ci LS1X_UART(2), 3562306a36Sopenharmony_ci LS1X_UART(3), 3662306a36Sopenharmony_ci {}, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct platform_device ls1x_uart_pdev = { 4062306a36Sopenharmony_ci .name = "serial8250", 4162306a36Sopenharmony_ci .id = PLAT8250_DEV_PLATFORM, 4262306a36Sopenharmony_ci .dev = { 4362306a36Sopenharmony_ci .platform_data = ls1x_serial8250_pdata, 4462306a36Sopenharmony_ci }, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_civoid __init ls1x_serial_set_uartclk(struct platform_device *pdev) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct clk *clk; 5062306a36Sopenharmony_ci struct plat_serial8250_port *p; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci clk = clk_get(&pdev->dev, pdev->name); 5362306a36Sopenharmony_ci if (IS_ERR(clk)) { 5462306a36Sopenharmony_ci pr_err("unable to get %s clock, err=%ld", 5562306a36Sopenharmony_ci pdev->name, PTR_ERR(clk)); 5662306a36Sopenharmony_ci return; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci clk_prepare_enable(clk); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci for (p = pdev->dev.platform_data; p->flags != 0; ++p) 6162306a36Sopenharmony_ci p->uartclk = clk_get_rate(clk); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* Synopsys Ethernet GMAC */ 6562306a36Sopenharmony_cistatic struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { 6662306a36Sopenharmony_ci .phy_mask = 0, 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic struct stmmac_dma_cfg ls1x_eth_dma_cfg = { 7062306a36Sopenharmony_ci .pbl = 1, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciint ls1x_eth_mux_init(struct platform_device *pdev, void *priv) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci struct plat_stmmacenet_data *plat_dat = NULL; 7662306a36Sopenharmony_ci u32 val; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci val = __raw_readl(LS1X_MUX_CTRL1); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#if defined(CONFIG_LOONGSON1_LS1B) 8162306a36Sopenharmony_ci plat_dat = dev_get_platdata(&pdev->dev); 8262306a36Sopenharmony_ci if (plat_dat->bus_id) { 8362306a36Sopenharmony_ci __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 | 8462306a36Sopenharmony_ci GMAC1_USE_UART0, LS1X_MUX_CTRL0); 8562306a36Sopenharmony_ci switch (plat_dat->phy_interface) { 8662306a36Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII: 8762306a36Sopenharmony_ci val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23); 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci case PHY_INTERFACE_MODE_MII: 9062306a36Sopenharmony_ci val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23); 9162306a36Sopenharmony_ci break; 9262306a36Sopenharmony_ci default: 9362306a36Sopenharmony_ci pr_err("unsupported mii mode %d\n", 9462306a36Sopenharmony_ci plat_dat->phy_interface); 9562306a36Sopenharmony_ci return -ENOTSUPP; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci val &= ~GMAC1_SHUT; 9862306a36Sopenharmony_ci } else { 9962306a36Sopenharmony_ci switch (plat_dat->phy_interface) { 10062306a36Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII: 10162306a36Sopenharmony_ci val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01); 10262306a36Sopenharmony_ci break; 10362306a36Sopenharmony_ci case PHY_INTERFACE_MODE_MII: 10462306a36Sopenharmony_ci val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01); 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci default: 10762306a36Sopenharmony_ci pr_err("unsupported mii mode %d\n", 10862306a36Sopenharmony_ci plat_dat->phy_interface); 10962306a36Sopenharmony_ci return -ENOTSUPP; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci val &= ~GMAC0_SHUT; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci __raw_writel(val, LS1X_MUX_CTRL1); 11462306a36Sopenharmony_ci#elif defined(CONFIG_LOONGSON1_LS1C) 11562306a36Sopenharmony_ci plat_dat = dev_get_platdata(&pdev->dev); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci val &= ~PHY_INTF_SELI; 11862306a36Sopenharmony_ci if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII) 11962306a36Sopenharmony_ci val |= 0x4 << PHY_INTF_SELI_SHIFT; 12062306a36Sopenharmony_ci __raw_writel(val, LS1X_MUX_CTRL1); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci val = __raw_readl(LS1X_MUX_CTRL0); 12362306a36Sopenharmony_ci __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0); 12462306a36Sopenharmony_ci#endif 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic struct plat_stmmacenet_data ls1x_eth0_pdata = { 13062306a36Sopenharmony_ci .bus_id = 0, 13162306a36Sopenharmony_ci .phy_addr = -1, 13262306a36Sopenharmony_ci#if defined(CONFIG_LOONGSON1_LS1B) 13362306a36Sopenharmony_ci .phy_interface = PHY_INTERFACE_MODE_MII, 13462306a36Sopenharmony_ci#elif defined(CONFIG_LOONGSON1_LS1C) 13562306a36Sopenharmony_ci .phy_interface = PHY_INTERFACE_MODE_RMII, 13662306a36Sopenharmony_ci#endif 13762306a36Sopenharmony_ci .mdio_bus_data = &ls1x_mdio_bus_data, 13862306a36Sopenharmony_ci .dma_cfg = &ls1x_eth_dma_cfg, 13962306a36Sopenharmony_ci .has_gmac = 1, 14062306a36Sopenharmony_ci .tx_coe = 1, 14162306a36Sopenharmony_ci .rx_queues_to_use = 1, 14262306a36Sopenharmony_ci .tx_queues_to_use = 1, 14362306a36Sopenharmony_ci .init = ls1x_eth_mux_init, 14462306a36Sopenharmony_ci}; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic struct resource ls1x_eth0_resources[] = { 14762306a36Sopenharmony_ci [0] = { 14862306a36Sopenharmony_ci .start = LS1X_GMAC0_BASE, 14962306a36Sopenharmony_ci .end = LS1X_GMAC0_BASE + SZ_64K - 1, 15062306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 15162306a36Sopenharmony_ci }, 15262306a36Sopenharmony_ci [1] = { 15362306a36Sopenharmony_ci .name = "macirq", 15462306a36Sopenharmony_ci .start = LS1X_GMAC0_IRQ, 15562306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 15662306a36Sopenharmony_ci }, 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistruct platform_device ls1x_eth0_pdev = { 16062306a36Sopenharmony_ci .name = "stmmaceth", 16162306a36Sopenharmony_ci .id = 0, 16262306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ls1x_eth0_resources), 16362306a36Sopenharmony_ci .resource = ls1x_eth0_resources, 16462306a36Sopenharmony_ci .dev = { 16562306a36Sopenharmony_ci .platform_data = &ls1x_eth0_pdata, 16662306a36Sopenharmony_ci }, 16762306a36Sopenharmony_ci}; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci#ifdef CONFIG_LOONGSON1_LS1B 17062306a36Sopenharmony_cistatic struct plat_stmmacenet_data ls1x_eth1_pdata = { 17162306a36Sopenharmony_ci .bus_id = 1, 17262306a36Sopenharmony_ci .phy_addr = -1, 17362306a36Sopenharmony_ci .phy_interface = PHY_INTERFACE_MODE_MII, 17462306a36Sopenharmony_ci .mdio_bus_data = &ls1x_mdio_bus_data, 17562306a36Sopenharmony_ci .dma_cfg = &ls1x_eth_dma_cfg, 17662306a36Sopenharmony_ci .has_gmac = 1, 17762306a36Sopenharmony_ci .tx_coe = 1, 17862306a36Sopenharmony_ci .rx_queues_to_use = 1, 17962306a36Sopenharmony_ci .tx_queues_to_use = 1, 18062306a36Sopenharmony_ci .init = ls1x_eth_mux_init, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic struct resource ls1x_eth1_resources[] = { 18462306a36Sopenharmony_ci [0] = { 18562306a36Sopenharmony_ci .start = LS1X_GMAC1_BASE, 18662306a36Sopenharmony_ci .end = LS1X_GMAC1_BASE + SZ_64K - 1, 18762306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 18862306a36Sopenharmony_ci }, 18962306a36Sopenharmony_ci [1] = { 19062306a36Sopenharmony_ci .name = "macirq", 19162306a36Sopenharmony_ci .start = LS1X_GMAC1_IRQ, 19262306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 19362306a36Sopenharmony_ci }, 19462306a36Sopenharmony_ci}; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistruct platform_device ls1x_eth1_pdev = { 19762306a36Sopenharmony_ci .name = "stmmaceth", 19862306a36Sopenharmony_ci .id = 1, 19962306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ls1x_eth1_resources), 20062306a36Sopenharmony_ci .resource = ls1x_eth1_resources, 20162306a36Sopenharmony_ci .dev = { 20262306a36Sopenharmony_ci .platform_data = &ls1x_eth1_pdata, 20362306a36Sopenharmony_ci }, 20462306a36Sopenharmony_ci}; 20562306a36Sopenharmony_ci#endif /* CONFIG_LOONGSON1_LS1B */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* GPIO */ 20862306a36Sopenharmony_cistatic struct resource ls1x_gpio0_resources[] = { 20962306a36Sopenharmony_ci [0] = { 21062306a36Sopenharmony_ci .start = LS1X_GPIO0_BASE, 21162306a36Sopenharmony_ci .end = LS1X_GPIO0_BASE + SZ_4 - 1, 21262306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 21362306a36Sopenharmony_ci }, 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistruct platform_device ls1x_gpio0_pdev = { 21762306a36Sopenharmony_ci .name = "ls1x-gpio", 21862306a36Sopenharmony_ci .id = 0, 21962306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ls1x_gpio0_resources), 22062306a36Sopenharmony_ci .resource = ls1x_gpio0_resources, 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistatic struct resource ls1x_gpio1_resources[] = { 22462306a36Sopenharmony_ci [0] = { 22562306a36Sopenharmony_ci .start = LS1X_GPIO1_BASE, 22662306a36Sopenharmony_ci .end = LS1X_GPIO1_BASE + SZ_4 - 1, 22762306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 22862306a36Sopenharmony_ci }, 22962306a36Sopenharmony_ci}; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistruct platform_device ls1x_gpio1_pdev = { 23262306a36Sopenharmony_ci .name = "ls1x-gpio", 23362306a36Sopenharmony_ci .id = 1, 23462306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ls1x_gpio1_resources), 23562306a36Sopenharmony_ci .resource = ls1x_gpio1_resources, 23662306a36Sopenharmony_ci}; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/* USB EHCI */ 23962306a36Sopenharmony_cistatic u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic struct resource ls1x_ehci_resources[] = { 24262306a36Sopenharmony_ci [0] = { 24362306a36Sopenharmony_ci .start = LS1X_EHCI_BASE, 24462306a36Sopenharmony_ci .end = LS1X_EHCI_BASE + SZ_32K - 1, 24562306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 24662306a36Sopenharmony_ci }, 24762306a36Sopenharmony_ci [1] = { 24862306a36Sopenharmony_ci .start = LS1X_EHCI_IRQ, 24962306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 25062306a36Sopenharmony_ci }, 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic struct usb_ehci_pdata ls1x_ehci_pdata = { 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistruct platform_device ls1x_ehci_pdev = { 25762306a36Sopenharmony_ci .name = "ehci-platform", 25862306a36Sopenharmony_ci .id = -1, 25962306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ls1x_ehci_resources), 26062306a36Sopenharmony_ci .resource = ls1x_ehci_resources, 26162306a36Sopenharmony_ci .dev = { 26262306a36Sopenharmony_ci .dma_mask = &ls1x_ehci_dmamask, 26362306a36Sopenharmony_ci .platform_data = &ls1x_ehci_pdata, 26462306a36Sopenharmony_ci }, 26562306a36Sopenharmony_ci}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* Real Time Clock */ 26862306a36Sopenharmony_cistruct platform_device ls1x_rtc_pdev = { 26962306a36Sopenharmony_ci .name = "ls1x-rtc", 27062306a36Sopenharmony_ci .id = -1, 27162306a36Sopenharmony_ci}; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci/* Watchdog */ 27462306a36Sopenharmony_cistatic struct resource ls1x_wdt_resources[] = { 27562306a36Sopenharmony_ci { 27662306a36Sopenharmony_ci .start = LS1X_WDT_BASE, 27762306a36Sopenharmony_ci .end = LS1X_WDT_BASE + SZ_16 - 1, 27862306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 27962306a36Sopenharmony_ci }, 28062306a36Sopenharmony_ci}; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistruct platform_device ls1x_wdt_pdev = { 28362306a36Sopenharmony_ci .name = "ls1x-wdt", 28462306a36Sopenharmony_ci .id = -1, 28562306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ls1x_wdt_resources), 28662306a36Sopenharmony_ci .resource = ls1x_wdt_resources, 28762306a36Sopenharmony_ci}; 288