Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com>
0004  */
0005 
0006 #include <linux/clk.h>
0007 #include <linux/dma-mapping.h>
0008 #include <linux/err.h>
0009 #include <linux/mtd/partitions.h>
0010 #include <linux/sizes.h>
0011 #include <linux/phy.h>
0012 #include <linux/serial_8250.h>
0013 #include <linux/stmmac.h>
0014 #include <linux/usb/ehci_pdriver.h>
0015 
0016 #include <platform.h>
0017 #include <loongson1.h>
0018 #include <cpufreq.h>
0019 #include <dma.h>
0020 #include <nand.h>
0021 
0022 /* 8250/16550 compatible UART */
0023 #define LS1X_UART(_id)                      \
0024     {                           \
0025         .mapbase    = LS1X_UART ## _id ## _BASE,    \
0026         .irq        = LS1X_UART ## _id ## _IRQ, \
0027         .iotype     = UPIO_MEM,         \
0028         .flags      = UPF_IOREMAP | UPF_FIXED_TYPE, \
0029         .type       = PORT_16550A,          \
0030     }
0031 
0032 static struct plat_serial8250_port ls1x_serial8250_pdata[] = {
0033     LS1X_UART(0),
0034     LS1X_UART(1),
0035     LS1X_UART(2),
0036     LS1X_UART(3),
0037     {},
0038 };
0039 
0040 struct platform_device ls1x_uart_pdev = {
0041     .name       = "serial8250",
0042     .id     = PLAT8250_DEV_PLATFORM,
0043     .dev        = {
0044         .platform_data = ls1x_serial8250_pdata,
0045     },
0046 };
0047 
0048 void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
0049 {
0050     struct clk *clk;
0051     struct plat_serial8250_port *p;
0052 
0053     clk = clk_get(&pdev->dev, pdev->name);
0054     if (IS_ERR(clk)) {
0055         pr_err("unable to get %s clock, err=%ld",
0056                pdev->name, PTR_ERR(clk));
0057         return;
0058     }
0059     clk_prepare_enable(clk);
0060 
0061     for (p = pdev->dev.platform_data; p->flags != 0; ++p)
0062         p->uartclk = clk_get_rate(clk);
0063 }
0064 
0065 /* CPUFreq */
0066 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
0067     .clk_name   = "cpu_clk",
0068     .osc_clk_name   = "osc_clk",
0069     .max_freq   = 266 * 1000,
0070     .min_freq   = 33 * 1000,
0071 };
0072 
0073 struct platform_device ls1x_cpufreq_pdev = {
0074     .name       = "ls1x-cpufreq",
0075     .dev        = {
0076         .platform_data = &ls1x_cpufreq_pdata,
0077     },
0078 };
0079 
0080 /* Synopsys Ethernet GMAC */
0081 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
0082     .phy_mask   = 0,
0083 };
0084 
0085 static struct stmmac_dma_cfg ls1x_eth_dma_cfg = {
0086     .pbl        = 1,
0087 };
0088 
0089 int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
0090 {
0091     struct plat_stmmacenet_data *plat_dat = NULL;
0092     u32 val;
0093 
0094     val = __raw_readl(LS1X_MUX_CTRL1);
0095 
0096 #if defined(CONFIG_LOONGSON1_LS1B)
0097     plat_dat = dev_get_platdata(&pdev->dev);
0098     if (plat_dat->bus_id) {
0099         __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
0100                  GMAC1_USE_UART0, LS1X_MUX_CTRL0);
0101         switch (plat_dat->phy_interface) {
0102         case PHY_INTERFACE_MODE_RGMII:
0103             val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
0104             break;
0105         case PHY_INTERFACE_MODE_MII:
0106             val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
0107             break;
0108         default:
0109             pr_err("unsupported mii mode %d\n",
0110                    plat_dat->phy_interface);
0111             return -ENOTSUPP;
0112         }
0113         val &= ~GMAC1_SHUT;
0114     } else {
0115         switch (plat_dat->phy_interface) {
0116         case PHY_INTERFACE_MODE_RGMII:
0117             val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
0118             break;
0119         case PHY_INTERFACE_MODE_MII:
0120             val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
0121             break;
0122         default:
0123             pr_err("unsupported mii mode %d\n",
0124                    plat_dat->phy_interface);
0125             return -ENOTSUPP;
0126         }
0127         val &= ~GMAC0_SHUT;
0128     }
0129     __raw_writel(val, LS1X_MUX_CTRL1);
0130 #elif defined(CONFIG_LOONGSON1_LS1C)
0131     plat_dat = dev_get_platdata(&pdev->dev);
0132 
0133     val &= ~PHY_INTF_SELI;
0134     if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII)
0135         val |= 0x4 << PHY_INTF_SELI_SHIFT;
0136     __raw_writel(val, LS1X_MUX_CTRL1);
0137 
0138     val = __raw_readl(LS1X_MUX_CTRL0);
0139     __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0);
0140 #endif
0141 
0142     return 0;
0143 }
0144 
0145 static struct plat_stmmacenet_data ls1x_eth0_pdata = {
0146     .bus_id         = 0,
0147     .phy_addr       = -1,
0148 #if defined(CONFIG_LOONGSON1_LS1B)
0149     .phy_interface      = PHY_INTERFACE_MODE_MII,
0150 #elif defined(CONFIG_LOONGSON1_LS1C)
0151     .phy_interface      = PHY_INTERFACE_MODE_RMII,
0152 #endif
0153     .mdio_bus_data      = &ls1x_mdio_bus_data,
0154     .dma_cfg        = &ls1x_eth_dma_cfg,
0155     .has_gmac       = 1,
0156     .tx_coe         = 1,
0157     .rx_queues_to_use   = 1,
0158     .tx_queues_to_use   = 1,
0159     .init           = ls1x_eth_mux_init,
0160 };
0161 
0162 static struct resource ls1x_eth0_resources[] = {
0163     [0] = {
0164         .start  = LS1X_GMAC0_BASE,
0165         .end    = LS1X_GMAC0_BASE + SZ_64K - 1,
0166         .flags  = IORESOURCE_MEM,
0167     },
0168     [1] = {
0169         .name   = "macirq",
0170         .start  = LS1X_GMAC0_IRQ,
0171         .flags  = IORESOURCE_IRQ,
0172     },
0173 };
0174 
0175 struct platform_device ls1x_eth0_pdev = {
0176     .name       = "stmmaceth",
0177     .id     = 0,
0178     .num_resources  = ARRAY_SIZE(ls1x_eth0_resources),
0179     .resource   = ls1x_eth0_resources,
0180     .dev        = {
0181         .platform_data = &ls1x_eth0_pdata,
0182     },
0183 };
0184 
0185 #ifdef CONFIG_LOONGSON1_LS1B
0186 static struct plat_stmmacenet_data ls1x_eth1_pdata = {
0187     .bus_id         = 1,
0188     .phy_addr       = -1,
0189     .phy_interface      = PHY_INTERFACE_MODE_MII,
0190     .mdio_bus_data      = &ls1x_mdio_bus_data,
0191     .dma_cfg        = &ls1x_eth_dma_cfg,
0192     .has_gmac       = 1,
0193     .tx_coe         = 1,
0194     .rx_queues_to_use   = 1,
0195     .tx_queues_to_use   = 1,
0196     .init           = ls1x_eth_mux_init,
0197 };
0198 
0199 static struct resource ls1x_eth1_resources[] = {
0200     [0] = {
0201         .start  = LS1X_GMAC1_BASE,
0202         .end    = LS1X_GMAC1_BASE + SZ_64K - 1,
0203         .flags  = IORESOURCE_MEM,
0204     },
0205     [1] = {
0206         .name   = "macirq",
0207         .start  = LS1X_GMAC1_IRQ,
0208         .flags  = IORESOURCE_IRQ,
0209     },
0210 };
0211 
0212 struct platform_device ls1x_eth1_pdev = {
0213     .name       = "stmmaceth",
0214     .id     = 1,
0215     .num_resources  = ARRAY_SIZE(ls1x_eth1_resources),
0216     .resource   = ls1x_eth1_resources,
0217     .dev        = {
0218         .platform_data = &ls1x_eth1_pdata,
0219     },
0220 };
0221 #endif  /* CONFIG_LOONGSON1_LS1B */
0222 
0223 /* GPIO */
0224 static struct resource ls1x_gpio0_resources[] = {
0225     [0] = {
0226         .start  = LS1X_GPIO0_BASE,
0227         .end    = LS1X_GPIO0_BASE + SZ_4 - 1,
0228         .flags  = IORESOURCE_MEM,
0229     },
0230 };
0231 
0232 struct platform_device ls1x_gpio0_pdev = {
0233     .name       = "ls1x-gpio",
0234     .id     = 0,
0235     .num_resources  = ARRAY_SIZE(ls1x_gpio0_resources),
0236     .resource   = ls1x_gpio0_resources,
0237 };
0238 
0239 static struct resource ls1x_gpio1_resources[] = {
0240     [0] = {
0241         .start  = LS1X_GPIO1_BASE,
0242         .end    = LS1X_GPIO1_BASE + SZ_4 - 1,
0243         .flags  = IORESOURCE_MEM,
0244     },
0245 };
0246 
0247 struct platform_device ls1x_gpio1_pdev = {
0248     .name       = "ls1x-gpio",
0249     .id     = 1,
0250     .num_resources  = ARRAY_SIZE(ls1x_gpio1_resources),
0251     .resource   = ls1x_gpio1_resources,
0252 };
0253 
0254 /* USB EHCI */
0255 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
0256 
0257 static struct resource ls1x_ehci_resources[] = {
0258     [0] = {
0259         .start  = LS1X_EHCI_BASE,
0260         .end    = LS1X_EHCI_BASE + SZ_32K - 1,
0261         .flags  = IORESOURCE_MEM,
0262     },
0263     [1] = {
0264         .start  = LS1X_EHCI_IRQ,
0265         .flags  = IORESOURCE_IRQ,
0266     },
0267 };
0268 
0269 static struct usb_ehci_pdata ls1x_ehci_pdata = {
0270 };
0271 
0272 struct platform_device ls1x_ehci_pdev = {
0273     .name       = "ehci-platform",
0274     .id     = -1,
0275     .num_resources  = ARRAY_SIZE(ls1x_ehci_resources),
0276     .resource   = ls1x_ehci_resources,
0277     .dev        = {
0278         .dma_mask = &ls1x_ehci_dmamask,
0279         .platform_data = &ls1x_ehci_pdata,
0280     },
0281 };
0282 
0283 /* Real Time Clock */
0284 void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
0285 {
0286     u32 val = __raw_readl(LS1X_RTC_CTRL);
0287 
0288     if (!(val & RTC_EXTCLK_OK))
0289         __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
0290 }
0291 
0292 struct platform_device ls1x_rtc_pdev = {
0293     .name       = "ls1x-rtc",
0294     .id     = -1,
0295 };
0296 
0297 /* Watchdog */
0298 static struct resource ls1x_wdt_resources[] = {
0299     {
0300         .start  = LS1X_WDT_BASE,
0301         .end    = LS1X_WDT_BASE + SZ_16 - 1,
0302         .flags  = IORESOURCE_MEM,
0303     },
0304 };
0305 
0306 struct platform_device ls1x_wdt_pdev = {
0307     .name       = "ls1x-wdt",
0308     .id     = -1,
0309     .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
0310     .resource   = ls1x_wdt_resources,
0311 };