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