1/* 2 * device.c -- common ColdFire SoC device support 3 * 4 * (C) Copyright 2011, Greg Ungerer <gerg@uclinux.org> 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/init.h> 13#include <linux/io.h> 14#include <linux/spi/spi.h> 15#include <linux/gpio.h> 16#include <linux/fec.h> 17#include <asm/traps.h> 18#include <asm/coldfire.h> 19#include <asm/mcfsim.h> 20#include <asm/mcfuart.h> 21#include <asm/mcfqspi.h> 22 23/* 24 * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. 25 */ 26static struct mcf_platform_uart mcf_uart_platform_data[] = { 27 { 28 .mapbase = MCFUART_BASE0, 29 .irq = MCF_IRQ_UART0, 30 }, 31 { 32 .mapbase = MCFUART_BASE1, 33 .irq = MCF_IRQ_UART1, 34 }, 35#ifdef MCFUART_BASE2 36 { 37 .mapbase = MCFUART_BASE2, 38 .irq = MCF_IRQ_UART2, 39 }, 40#endif 41#ifdef MCFUART_BASE3 42 { 43 .mapbase = MCFUART_BASE3, 44 .irq = MCF_IRQ_UART3, 45 }, 46#endif 47#ifdef MCFUART_BASE4 48 { 49 .mapbase = MCFUART_BASE4, 50 .irq = MCF_IRQ_UART4, 51 }, 52#endif 53#ifdef MCFUART_BASE5 54 { 55 .mapbase = MCFUART_BASE5, 56 .irq = MCF_IRQ_UART5, 57 }, 58#endif 59#ifdef MCFUART_BASE6 60 { 61 .mapbase = MCFUART_BASE6, 62 .irq = MCF_IRQ_UART6, 63 }, 64#endif 65#ifdef MCFUART_BASE7 66 { 67 .mapbase = MCFUART_BASE7, 68 .irq = MCF_IRQ_UART7, 69 }, 70#endif 71#ifdef MCFUART_BASE8 72 { 73 .mapbase = MCFUART_BASE8, 74 .irq = MCF_IRQ_UART8, 75 }, 76#endif 77#ifdef MCFUART_BASE9 78 { 79 .mapbase = MCFUART_BASE9, 80 .irq = MCF_IRQ_UART9, 81 }, 82#endif 83 { }, 84}; 85 86static struct platform_device mcf_uart = { 87 .name = "mcfuart", 88 .id = 0, 89 .dev.platform_data = mcf_uart_platform_data, 90}; 91 92#ifdef CONFIG_FEC 93 94#ifdef CONFIG_M5441x 95#define FEC_NAME "enet-fec" 96static struct fec_platform_data fec_pdata = { 97 .phy = PHY_INTERFACE_MODE_RMII, 98}; 99#define FEC_PDATA (&fec_pdata) 100#else 101#define FEC_NAME "fec" 102#define FEC_PDATA NULL 103#endif 104 105/* 106 * Some ColdFire cores contain the Fast Ethernet Controller (FEC) 107 * block. It is Freescale's own hardware block. Some ColdFires 108 * have 2 of these. 109 */ 110static struct resource mcf_fec0_resources[] = { 111 { 112 .start = MCFFEC_BASE0, 113 .end = MCFFEC_BASE0 + MCFFEC_SIZE0 - 1, 114 .flags = IORESOURCE_MEM, 115 }, 116 { 117 .start = MCF_IRQ_FECRX0, 118 .end = MCF_IRQ_FECRX0, 119 .flags = IORESOURCE_IRQ, 120 }, 121 { 122 .start = MCF_IRQ_FECTX0, 123 .end = MCF_IRQ_FECTX0, 124 .flags = IORESOURCE_IRQ, 125 }, 126 { 127 .start = MCF_IRQ_FECENTC0, 128 .end = MCF_IRQ_FECENTC0, 129 .flags = IORESOURCE_IRQ, 130 }, 131}; 132 133static struct platform_device mcf_fec0 = { 134 .name = FEC_NAME, 135 .id = 0, 136 .num_resources = ARRAY_SIZE(mcf_fec0_resources), 137 .resource = mcf_fec0_resources, 138 .dev.platform_data = FEC_PDATA, 139}; 140 141#ifdef MCFFEC_BASE1 142static struct resource mcf_fec1_resources[] = { 143 { 144 .start = MCFFEC_BASE1, 145 .end = MCFFEC_BASE1 + MCFFEC_SIZE1 - 1, 146 .flags = IORESOURCE_MEM, 147 }, 148 { 149 .start = MCF_IRQ_FECRX1, 150 .end = MCF_IRQ_FECRX1, 151 .flags = IORESOURCE_IRQ, 152 }, 153 { 154 .start = MCF_IRQ_FECTX1, 155 .end = MCF_IRQ_FECTX1, 156 .flags = IORESOURCE_IRQ, 157 }, 158 { 159 .start = MCF_IRQ_FECENTC1, 160 .end = MCF_IRQ_FECENTC1, 161 .flags = IORESOURCE_IRQ, 162 }, 163}; 164 165static struct platform_device mcf_fec1 = { 166 .name = FEC_NAME, 167 .id = 1, 168 .num_resources = ARRAY_SIZE(mcf_fec1_resources), 169 .resource = mcf_fec1_resources, 170 .dev.platform_data = FEC_PDATA, 171}; 172#endif /* MCFFEC_BASE1 */ 173#endif /* CONFIG_FEC */ 174 175#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) 176/* 177 * The ColdFire QSPI module is an SPI protocol hardware block used 178 * on a number of different ColdFire CPUs. 179 */ 180static struct resource mcf_qspi_resources[] = { 181 { 182 .start = MCFQSPI_BASE, 183 .end = MCFQSPI_BASE + MCFQSPI_SIZE - 1, 184 .flags = IORESOURCE_MEM, 185 }, 186 { 187 .start = MCF_IRQ_QSPI, 188 .end = MCF_IRQ_QSPI, 189 .flags = IORESOURCE_IRQ, 190 }, 191}; 192 193static int mcf_cs_setup(struct mcfqspi_cs_control *cs_control) 194{ 195 int status; 196 197 status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0"); 198 if (status) { 199 pr_debug("gpio_request for MCFQSPI_CS0 failed\n"); 200 goto fail0; 201 } 202 status = gpio_direction_output(MCFQSPI_CS0, 1); 203 if (status) { 204 pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n"); 205 goto fail1; 206 } 207 208 status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1"); 209 if (status) { 210 pr_debug("gpio_request for MCFQSPI_CS1 failed\n"); 211 goto fail1; 212 } 213 status = gpio_direction_output(MCFQSPI_CS1, 1); 214 if (status) { 215 pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n"); 216 goto fail2; 217 } 218 219 status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2"); 220 if (status) { 221 pr_debug("gpio_request for MCFQSPI_CS2 failed\n"); 222 goto fail2; 223 } 224 status = gpio_direction_output(MCFQSPI_CS2, 1); 225 if (status) { 226 pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n"); 227 goto fail3; 228 } 229 230#ifdef MCFQSPI_CS3 231 status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3"); 232 if (status) { 233 pr_debug("gpio_request for MCFQSPI_CS3 failed\n"); 234 goto fail3; 235 } 236 status = gpio_direction_output(MCFQSPI_CS3, 1); 237 if (status) { 238 pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n"); 239 gpio_free(MCFQSPI_CS3); 240 goto fail3; 241 } 242#endif 243 244 return 0; 245 246fail3: 247 gpio_free(MCFQSPI_CS2); 248fail2: 249 gpio_free(MCFQSPI_CS1); 250fail1: 251 gpio_free(MCFQSPI_CS0); 252fail0: 253 return status; 254} 255 256static void mcf_cs_teardown(struct mcfqspi_cs_control *cs_control) 257{ 258#ifdef MCFQSPI_CS3 259 gpio_free(MCFQSPI_CS3); 260#endif 261 gpio_free(MCFQSPI_CS2); 262 gpio_free(MCFQSPI_CS1); 263 gpio_free(MCFQSPI_CS0); 264} 265 266static void mcf_cs_select(struct mcfqspi_cs_control *cs_control, 267 u8 chip_select, bool cs_high) 268{ 269 switch (chip_select) { 270 case 0: 271 gpio_set_value(MCFQSPI_CS0, cs_high); 272 break; 273 case 1: 274 gpio_set_value(MCFQSPI_CS1, cs_high); 275 break; 276 case 2: 277 gpio_set_value(MCFQSPI_CS2, cs_high); 278 break; 279#ifdef MCFQSPI_CS3 280 case 3: 281 gpio_set_value(MCFQSPI_CS3, cs_high); 282 break; 283#endif 284 } 285} 286 287static void mcf_cs_deselect(struct mcfqspi_cs_control *cs_control, 288 u8 chip_select, bool cs_high) 289{ 290 switch (chip_select) { 291 case 0: 292 gpio_set_value(MCFQSPI_CS0, !cs_high); 293 break; 294 case 1: 295 gpio_set_value(MCFQSPI_CS1, !cs_high); 296 break; 297 case 2: 298 gpio_set_value(MCFQSPI_CS2, !cs_high); 299 break; 300#ifdef MCFQSPI_CS3 301 case 3: 302 gpio_set_value(MCFQSPI_CS3, !cs_high); 303 break; 304#endif 305 } 306} 307 308static struct mcfqspi_cs_control mcf_cs_control = { 309 .setup = mcf_cs_setup, 310 .teardown = mcf_cs_teardown, 311 .select = mcf_cs_select, 312 .deselect = mcf_cs_deselect, 313}; 314 315static struct mcfqspi_platform_data mcf_qspi_data = { 316 .bus_num = 0, 317 .num_chipselect = 4, 318 .cs_control = &mcf_cs_control, 319}; 320 321static struct platform_device mcf_qspi = { 322 .name = "mcfqspi", 323 .id = 0, 324 .num_resources = ARRAY_SIZE(mcf_qspi_resources), 325 .resource = mcf_qspi_resources, 326 .dev.platform_data = &mcf_qspi_data, 327}; 328#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */ 329 330static struct platform_device *mcf_devices[] __initdata = { 331 &mcf_uart, 332#ifdef CONFIG_FEC 333 &mcf_fec0, 334#ifdef MCFFEC_BASE1 335 &mcf_fec1, 336#endif 337#endif 338#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) 339 &mcf_qspi, 340#endif 341}; 342 343/* 344 * Some ColdFire UARTs let you set the IRQ line to use. 345 */ 346static void __init mcf_uart_set_irq(void) 347{ 348#ifdef MCFUART_UIVR 349 /* UART0 interrupt setup */ 350 writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCFSIM_UART1ICR); 351 writeb(MCF_IRQ_UART0, MCFUART_BASE0 + MCFUART_UIVR); 352 mcf_mapirq2imr(MCF_IRQ_UART0, MCFINTC_UART0); 353 354 /* UART1 interrupt setup */ 355 writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCFSIM_UART2ICR); 356 writeb(MCF_IRQ_UART1, MCFUART_BASE1 + MCFUART_UIVR); 357 mcf_mapirq2imr(MCF_IRQ_UART1, MCFINTC_UART1); 358#endif 359} 360 361static int __init mcf_init_devices(void) 362{ 363 mcf_uart_set_irq(); 364 platform_add_devices(mcf_devices, ARRAY_SIZE(mcf_devices)); 365 return 0; 366} 367 368arch_initcall(mcf_init_devices); 369 370