1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com> 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/dma-mapping.h> 8 #include <linux/err.h> 9 #include <linux/mtd/partitions.h> 10 #include <linux/sizes.h> 11 #include <linux/phy.h> 12 #include <linux/serial_8250.h> 13 #include <linux/stmmac.h> 14 #include <linux/usb/ehci_pdriver.h> 15 16 #include <platform.h> 17 #include <loongson1.h> 18 19 /* 8250/16550 compatible UART */ 20 #define LS1X_UART(_id) \ 21 { \ 22 .mapbase = LS1X_UART ## _id ## _BASE, \ 23 .irq = LS1X_UART ## _id ## _IRQ, \ 24 .iotype = UPIO_MEM, \ 25 .flags = UPF_IOREMAP | UPF_FIXED_TYPE, \ 26 .type = PORT_16550A, \ 27 } 28 29 static struct plat_serial8250_port ls1x_serial8250_pdata[] = { 30 LS1X_UART(0), 31 LS1X_UART(1), 32 LS1X_UART(2), 33 LS1X_UART(3), 34 {}, 35 }; 36 37 struct platform_device ls1x_uart_pdev = { 38 .name = "serial8250", 39 .id = PLAT8250_DEV_PLATFORM, 40 .dev = { 41 .platform_data = ls1x_serial8250_pdata, 42 }, 43 }; 44 45 void __init ls1x_serial_set_uartclk(struct platform_device *pdev) 46 { 47 struct clk *clk; 48 struct plat_serial8250_port *p; 49 50 clk = clk_get(&pdev->dev, pdev->name); 51 if (IS_ERR(clk)) { 52 pr_err("unable to get %s clock, err=%ld", 53 pdev->name, PTR_ERR(clk)); 54 return; 55 } 56 clk_prepare_enable(clk); 57 58 for (p = pdev->dev.platform_data; p->flags != 0; ++p) 59 p->uartclk = clk_get_rate(clk); 60 } 61 62 /* Synopsys Ethernet GMAC */ 63 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { 64 .phy_mask = 0, 65 }; 66 67 static struct stmmac_dma_cfg ls1x_eth_dma_cfg = { 68 .pbl = 1, 69 }; 70 71 int ls1x_eth_mux_init(struct platform_device *pdev, void *priv) 72 { 73 struct plat_stmmacenet_data *plat_dat = NULL; 74 u32 val; 75 76 val = __raw_readl(LS1X_MUX_CTRL1); 77 78 #if defined(CONFIG_LOONGSON1_LS1B) 79 plat_dat = dev_get_platdata(&pdev->dev); 80 if (plat_dat->bus_id) { 81 __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 | 82 GMAC1_USE_UART0, LS1X_MUX_CTRL0); 83 switch (plat_dat->phy_interface) { 84 case PHY_INTERFACE_MODE_RGMII: 85 val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23); 86 break; 87 case PHY_INTERFACE_MODE_MII: 88 val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23); 89 break; 90 default: 91 pr_err("unsupported mii mode %d\n", 92 plat_dat->phy_interface); 93 return -ENOTSUPP; 94 } 95 val &= ~GMAC1_SHUT; 96 } else { 97 switch (plat_dat->phy_interface) { 98 case PHY_INTERFACE_MODE_RGMII: 99 val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01); 100 break; 101 case PHY_INTERFACE_MODE_MII: 102 val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01); 103 break; 104 default: 105 pr_err("unsupported mii mode %d\n", 106 plat_dat->phy_interface); 107 return -ENOTSUPP; 108 } 109 val &= ~GMAC0_SHUT; 110 } 111 __raw_writel(val, LS1X_MUX_CTRL1); 112 #elif defined(CONFIG_LOONGSON1_LS1C) 113 plat_dat = dev_get_platdata(&pdev->dev); 114 115 val &= ~PHY_INTF_SELI; 116 if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII) 117 val |= 0x4 << PHY_INTF_SELI_SHIFT; 118 __raw_writel(val, LS1X_MUX_CTRL1); 119 120 val = __raw_readl(LS1X_MUX_CTRL0); 121 __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0); 122 #endif 123 124 return 0; 125 } 126 127 static struct plat_stmmacenet_data ls1x_eth0_pdata = { 128 .bus_id = 0, 129 .phy_addr = -1, 130 #if defined(CONFIG_LOONGSON1_LS1B) 131 .phy_interface = PHY_INTERFACE_MODE_MII, 132 #elif defined(CONFIG_LOONGSON1_LS1C) 133 .phy_interface = PHY_INTERFACE_MODE_RMII, 134 #endif 135 .mdio_bus_data = &ls1x_mdio_bus_data, 136 .dma_cfg = &ls1x_eth_dma_cfg, 137 .has_gmac = 1, 138 .tx_coe = 1, 139 .rx_queues_to_use = 1, 140 .tx_queues_to_use = 1, 141 .init = ls1x_eth_mux_init, 142 }; 143 144 static struct resource ls1x_eth0_resources[] = { 145 [0] = { 146 .start = LS1X_GMAC0_BASE, 147 .end = LS1X_GMAC0_BASE + SZ_64K - 1, 148 .flags = IORESOURCE_MEM, 149 }, 150 [1] = { 151 .name = "macirq", 152 .start = LS1X_GMAC0_IRQ, 153 .flags = IORESOURCE_IRQ, 154 }, 155 }; 156 157 struct platform_device ls1x_eth0_pdev = { 158 .name = "stmmaceth", 159 .id = 0, 160 .num_resources = ARRAY_SIZE(ls1x_eth0_resources), 161 .resource = ls1x_eth0_resources, 162 .dev = { 163 .platform_data = &ls1x_eth0_pdata, 164 }, 165 }; 166 167 #ifdef CONFIG_LOONGSON1_LS1B 168 static struct plat_stmmacenet_data ls1x_eth1_pdata = { 169 .bus_id = 1, 170 .phy_addr = -1, 171 .phy_interface = PHY_INTERFACE_MODE_MII, 172 .mdio_bus_data = &ls1x_mdio_bus_data, 173 .dma_cfg = &ls1x_eth_dma_cfg, 174 .has_gmac = 1, 175 .tx_coe = 1, 176 .rx_queues_to_use = 1, 177 .tx_queues_to_use = 1, 178 .init = ls1x_eth_mux_init, 179 }; 180 181 static struct resource ls1x_eth1_resources[] = { 182 [0] = { 183 .start = LS1X_GMAC1_BASE, 184 .end = LS1X_GMAC1_BASE + SZ_64K - 1, 185 .flags = IORESOURCE_MEM, 186 }, 187 [1] = { 188 .name = "macirq", 189 .start = LS1X_GMAC1_IRQ, 190 .flags = IORESOURCE_IRQ, 191 }, 192 }; 193 194 struct platform_device ls1x_eth1_pdev = { 195 .name = "stmmaceth", 196 .id = 1, 197 .num_resources = ARRAY_SIZE(ls1x_eth1_resources), 198 .resource = ls1x_eth1_resources, 199 .dev = { 200 .platform_data = &ls1x_eth1_pdata, 201 }, 202 }; 203 #endif /* CONFIG_LOONGSON1_LS1B */ 204 205 /* GPIO */ 206 static struct resource ls1x_gpio0_resources[] = { 207 [0] = { 208 .start = LS1X_GPIO0_BASE, 209 .end = LS1X_GPIO0_BASE + SZ_4 - 1, 210 .flags = IORESOURCE_MEM, 211 }, 212 }; 213 214 struct platform_device ls1x_gpio0_pdev = { 215 .name = "ls1x-gpio", 216 .id = 0, 217 .num_resources = ARRAY_SIZE(ls1x_gpio0_resources), 218 .resource = ls1x_gpio0_resources, 219 }; 220 221 static struct resource ls1x_gpio1_resources[] = { 222 [0] = { 223 .start = LS1X_GPIO1_BASE, 224 .end = LS1X_GPIO1_BASE + SZ_4 - 1, 225 .flags = IORESOURCE_MEM, 226 }, 227 }; 228 229 struct platform_device ls1x_gpio1_pdev = { 230 .name = "ls1x-gpio", 231 .id = 1, 232 .num_resources = ARRAY_SIZE(ls1x_gpio1_resources), 233 .resource = ls1x_gpio1_resources, 234 }; 235 236 /* USB EHCI */ 237 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); 238 239 static struct resource ls1x_ehci_resources[] = { 240 [0] = { 241 .start = LS1X_EHCI_BASE, 242 .end = LS1X_EHCI_BASE + SZ_32K - 1, 243 .flags = IORESOURCE_MEM, 244 }, 245 [1] = { 246 .start = LS1X_EHCI_IRQ, 247 .flags = IORESOURCE_IRQ, 248 }, 249 }; 250 251 static struct usb_ehci_pdata ls1x_ehci_pdata = { 252 }; 253 254 struct platform_device ls1x_ehci_pdev = { 255 .name = "ehci-platform", 256 .id = -1, 257 .num_resources = ARRAY_SIZE(ls1x_ehci_resources), 258 .resource = ls1x_ehci_resources, 259 .dev = { 260 .dma_mask = &ls1x_ehci_dmamask, 261 .platform_data = &ls1x_ehci_pdata, 262 }, 263 }; 264 265 /* Real Time Clock */ 266 struct platform_device ls1x_rtc_pdev = { 267 .name = "ls1x-rtc", 268 .id = -1, 269 }; 270 271 /* Watchdog */ 272 static struct resource ls1x_wdt_resources[] = { 273 { 274 .start = LS1X_WDT_BASE, 275 .end = LS1X_WDT_BASE + SZ_16 - 1, 276 .flags = IORESOURCE_MEM, 277 }, 278 }; 279 280 struct platform_device ls1x_wdt_pdev = { 281 .name = "ls1x-wdt", 282 .id = -1, 283 .num_resources = ARRAY_SIZE(ls1x_wdt_resources), 284 .resource = ls1x_wdt_resources, 285 }; 286
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.