1 /* 2 * arch/arm/mach-spear6xx/spear6xx.c 3 * 4 * SPEAr6XX machines common source file 5 * 6 * Copyright (C) 2009 ST Microelectronics 7 * Rajeev Kumar<rajeev-dlh.kumar@st.com> 8 * 9 * Copyright 2012 Stefan Roese <sr@denx.de> 10 * 11 * This file is licensed under the terms of the GNU General Public 12 * License version 2. This program is licensed "as is" without any 13 * warranty of any kind, whether express or implied. 14 */ 15 16 #include <linux/amba/pl08x.h> 17 #include <linux/clk.h> 18 #include <linux/err.h> 19 #include <linux/irqchip.h> 20 #include <linux/of.h> 21 #include <linux/of_address.h> 22 #include <linux/of_platform.h> 23 #include <linux/amba/pl080.h> 24 #include <asm/mach/arch.h> 25 #include <asm/mach/time.h> 26 #include <asm/mach/map.h> 27 #include "pl080.h" 28 #include "generic.h" 29 #include <mach/spear.h> 30 #include <mach/misc_regs.h> 31 32 /* dmac device registration */ 33 static struct pl08x_channel_data spear600_dma_info[] = { 34 { 35 .bus_id = "ssp1_rx", 36 .min_signal = 0, 37 .max_signal = 0, 38 .muxval = 0, 39 .periph_buses = PL08X_AHB1, 40 }, { 41 .bus_id = "ssp1_tx", 42 .min_signal = 1, 43 .max_signal = 1, 44 .muxval = 0, 45 .periph_buses = PL08X_AHB1, 46 }, { 47 .bus_id = "uart0_rx", 48 .min_signal = 2, 49 .max_signal = 2, 50 .muxval = 0, 51 .periph_buses = PL08X_AHB1, 52 }, { 53 .bus_id = "uart0_tx", 54 .min_signal = 3, 55 .max_signal = 3, 56 .muxval = 0, 57 .periph_buses = PL08X_AHB1, 58 }, { 59 .bus_id = "uart1_rx", 60 .min_signal = 4, 61 .max_signal = 4, 62 .muxval = 0, 63 .periph_buses = PL08X_AHB1, 64 }, { 65 .bus_id = "uart1_tx", 66 .min_signal = 5, 67 .max_signal = 5, 68 .muxval = 0, 69 .periph_buses = PL08X_AHB1, 70 }, { 71 .bus_id = "ssp2_rx", 72 .min_signal = 6, 73 .max_signal = 6, 74 .muxval = 0, 75 .periph_buses = PL08X_AHB2, 76 }, { 77 .bus_id = "ssp2_tx", 78 .min_signal = 7, 79 .max_signal = 7, 80 .muxval = 0, 81 .periph_buses = PL08X_AHB2, 82 }, { 83 .bus_id = "ssp0_rx", 84 .min_signal = 8, 85 .max_signal = 8, 86 .muxval = 0, 87 .periph_buses = PL08X_AHB1, 88 }, { 89 .bus_id = "ssp0_tx", 90 .min_signal = 9, 91 .max_signal = 9, 92 .muxval = 0, 93 .periph_buses = PL08X_AHB1, 94 }, { 95 .bus_id = "i2c_rx", 96 .min_signal = 10, 97 .max_signal = 10, 98 .muxval = 0, 99 .periph_buses = PL08X_AHB1, 100 }, { 101 .bus_id = "i2c_tx", 102 .min_signal = 11, 103 .max_signal = 11, 104 .muxval = 0, 105 .periph_buses = PL08X_AHB1, 106 }, { 107 .bus_id = "irda", 108 .min_signal = 12, 109 .max_signal = 12, 110 .muxval = 0, 111 .periph_buses = PL08X_AHB1, 112 }, { 113 .bus_id = "adc", 114 .min_signal = 13, 115 .max_signal = 13, 116 .muxval = 0, 117 .periph_buses = PL08X_AHB2, 118 }, { 119 .bus_id = "to_jpeg", 120 .min_signal = 14, 121 .max_signal = 14, 122 .muxval = 0, 123 .periph_buses = PL08X_AHB1, 124 }, { 125 .bus_id = "from_jpeg", 126 .min_signal = 15, 127 .max_signal = 15, 128 .muxval = 0, 129 .periph_buses = PL08X_AHB1, 130 }, { 131 .bus_id = "ras0_rx", 132 .min_signal = 0, 133 .max_signal = 0, 134 .muxval = 1, 135 .periph_buses = PL08X_AHB1, 136 }, { 137 .bus_id = "ras0_tx", 138 .min_signal = 1, 139 .max_signal = 1, 140 .muxval = 1, 141 .periph_buses = PL08X_AHB1, 142 }, { 143 .bus_id = "ras1_rx", 144 .min_signal = 2, 145 .max_signal = 2, 146 .muxval = 1, 147 .periph_buses = PL08X_AHB1, 148 }, { 149 .bus_id = "ras1_tx", 150 .min_signal = 3, 151 .max_signal = 3, 152 .muxval = 1, 153 .periph_buses = PL08X_AHB1, 154 }, { 155 .bus_id = "ras2_rx", 156 .min_signal = 4, 157 .max_signal = 4, 158 .muxval = 1, 159 .periph_buses = PL08X_AHB1, 160 }, { 161 .bus_id = "ras2_tx", 162 .min_signal = 5, 163 .max_signal = 5, 164 .muxval = 1, 165 .periph_buses = PL08X_AHB1, 166 }, { 167 .bus_id = "ras3_rx", 168 .min_signal = 6, 169 .max_signal = 6, 170 .muxval = 1, 171 .periph_buses = PL08X_AHB1, 172 }, { 173 .bus_id = "ras3_tx", 174 .min_signal = 7, 175 .max_signal = 7, 176 .muxval = 1, 177 .periph_buses = PL08X_AHB1, 178 }, { 179 .bus_id = "ras4_rx", 180 .min_signal = 8, 181 .max_signal = 8, 182 .muxval = 1, 183 .periph_buses = PL08X_AHB1, 184 }, { 185 .bus_id = "ras4_tx", 186 .min_signal = 9, 187 .max_signal = 9, 188 .muxval = 1, 189 .periph_buses = PL08X_AHB1, 190 }, { 191 .bus_id = "ras5_rx", 192 .min_signal = 10, 193 .max_signal = 10, 194 .muxval = 1, 195 .periph_buses = PL08X_AHB1, 196 }, { 197 .bus_id = "ras5_tx", 198 .min_signal = 11, 199 .max_signal = 11, 200 .muxval = 1, 201 .periph_buses = PL08X_AHB1, 202 }, { 203 .bus_id = "ras6_rx", 204 .min_signal = 12, 205 .max_signal = 12, 206 .muxval = 1, 207 .periph_buses = PL08X_AHB1, 208 }, { 209 .bus_id = "ras6_tx", 210 .min_signal = 13, 211 .max_signal = 13, 212 .muxval = 1, 213 .periph_buses = PL08X_AHB1, 214 }, { 215 .bus_id = "ras7_rx", 216 .min_signal = 14, 217 .max_signal = 14, 218 .muxval = 1, 219 .periph_buses = PL08X_AHB1, 220 }, { 221 .bus_id = "ras7_tx", 222 .min_signal = 15, 223 .max_signal = 15, 224 .muxval = 1, 225 .periph_buses = PL08X_AHB1, 226 }, { 227 .bus_id = "ext0_rx", 228 .min_signal = 0, 229 .max_signal = 0, 230 .muxval = 2, 231 .periph_buses = PL08X_AHB2, 232 }, { 233 .bus_id = "ext0_tx", 234 .min_signal = 1, 235 .max_signal = 1, 236 .muxval = 2, 237 .periph_buses = PL08X_AHB2, 238 }, { 239 .bus_id = "ext1_rx", 240 .min_signal = 2, 241 .max_signal = 2, 242 .muxval = 2, 243 .periph_buses = PL08X_AHB2, 244 }, { 245 .bus_id = "ext1_tx", 246 .min_signal = 3, 247 .max_signal = 3, 248 .muxval = 2, 249 .periph_buses = PL08X_AHB2, 250 }, { 251 .bus_id = "ext2_rx", 252 .min_signal = 4, 253 .max_signal = 4, 254 .muxval = 2, 255 .periph_buses = PL08X_AHB2, 256 }, { 257 .bus_id = "ext2_tx", 258 .min_signal = 5, 259 .max_signal = 5, 260 .muxval = 2, 261 .periph_buses = PL08X_AHB2, 262 }, { 263 .bus_id = "ext3_rx", 264 .min_signal = 6, 265 .max_signal = 6, 266 .muxval = 2, 267 .periph_buses = PL08X_AHB2, 268 }, { 269 .bus_id = "ext3_tx", 270 .min_signal = 7, 271 .max_signal = 7, 272 .muxval = 2, 273 .periph_buses = PL08X_AHB2, 274 }, { 275 .bus_id = "ext4_rx", 276 .min_signal = 8, 277 .max_signal = 8, 278 .muxval = 2, 279 .periph_buses = PL08X_AHB2, 280 }, { 281 .bus_id = "ext4_tx", 282 .min_signal = 9, 283 .max_signal = 9, 284 .muxval = 2, 285 .periph_buses = PL08X_AHB2, 286 }, { 287 .bus_id = "ext5_rx", 288 .min_signal = 10, 289 .max_signal = 10, 290 .muxval = 2, 291 .periph_buses = PL08X_AHB2, 292 }, { 293 .bus_id = "ext5_tx", 294 .min_signal = 11, 295 .max_signal = 11, 296 .muxval = 2, 297 .periph_buses = PL08X_AHB2, 298 }, { 299 .bus_id = "ext6_rx", 300 .min_signal = 12, 301 .max_signal = 12, 302 .muxval = 2, 303 .periph_buses = PL08X_AHB2, 304 }, { 305 .bus_id = "ext6_tx", 306 .min_signal = 13, 307 .max_signal = 13, 308 .muxval = 2, 309 .periph_buses = PL08X_AHB2, 310 }, { 311 .bus_id = "ext7_rx", 312 .min_signal = 14, 313 .max_signal = 14, 314 .muxval = 2, 315 .periph_buses = PL08X_AHB2, 316 }, { 317 .bus_id = "ext7_tx", 318 .min_signal = 15, 319 .max_signal = 15, 320 .muxval = 2, 321 .periph_buses = PL08X_AHB2, 322 }, 323 }; 324 325 static struct pl08x_platform_data spear6xx_pl080_plat_data = { 326 .memcpy_channel = { 327 .bus_id = "memcpy", 328 .cctl_memcpy = 329 (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \ 330 PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \ 331 PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \ 332 PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \ 333 PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \ 334 PL080_CONTROL_PROT_SYS), 335 }, 336 .lli_buses = PL08X_AHB1, 337 .mem_buses = PL08X_AHB1, 338 .get_signal = pl080_get_signal, 339 .put_signal = pl080_put_signal, 340 .slave_channels = spear600_dma_info, 341 .num_slave_channels = ARRAY_SIZE(spear600_dma_info), 342 }; 343 344 /* 345 * Following will create 16MB static virtual/physical mappings 346 * PHYSICAL VIRTUAL 347 * 0xF0000000 0xF0000000 348 * 0xF1000000 0xF1000000 349 * 0xD0000000 0xFD000000 350 * 0xFC000000 0xFC000000 351 */ 352 struct map_desc spear6xx_io_desc[] __initdata = { 353 { 354 .virtual = (unsigned long)VA_SPEAR6XX_ML_CPU_BASE, 355 .pfn = __phys_to_pfn(SPEAR_ICM3_ML1_2_BASE), 356 .length = 2 * SZ_16M, 357 .type = MT_DEVICE 358 }, { 359 .virtual = (unsigned long)VA_SPEAR_ICM1_2_BASE, 360 .pfn = __phys_to_pfn(SPEAR_ICM1_2_BASE), 361 .length = SZ_16M, 362 .type = MT_DEVICE 363 }, { 364 .virtual = (unsigned long)VA_SPEAR_ICM3_SMI_CTRL_BASE, 365 .pfn = __phys_to_pfn(SPEAR_ICM3_SMI_CTRL_BASE), 366 .length = SZ_16M, 367 .type = MT_DEVICE 368 }, 369 }; 370 371 /* This will create static memory mapping for selected devices */ 372 void __init spear6xx_map_io(void) 373 { 374 iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc)); 375 } 376 377 void __init spear6xx_timer_init(void) 378 { 379 char pclk_name[] = "pll3_clk"; 380 struct clk *gpt_clk, *pclk; 381 382 spear6xx_clk_init(MISC_BASE); 383 384 /* get the system timer clock */ 385 gpt_clk = clk_get_sys("gpt0", NULL); 386 if (IS_ERR(gpt_clk)) { 387 pr_err("%s:couldn't get clk for gpt\n", __func__); 388 BUG(); 389 } 390 391 /* get the suitable parent clock for timer*/ 392 pclk = clk_get(NULL, pclk_name); 393 if (IS_ERR(pclk)) { 394 pr_err("%s:couldn't get %s as parent for gpt\n", 395 __func__, pclk_name); 396 BUG(); 397 } 398 399 clk_set_parent(gpt_clk, pclk); 400 clk_put(gpt_clk); 401 clk_put(pclk); 402 403 spear_setup_of_timer(); 404 } 405 406 /* Add auxdata to pass platform data */ 407 struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = { 408 OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL, 409 &spear6xx_pl080_plat_data), 410 {} 411 }; 412 413 static void __init spear600_dt_init(void) 414 { 415 of_platform_populate(NULL, of_default_bus_match_table, 416 spear6xx_auxdata_lookup, NULL); 417 } 418 419 static const char *spear600_dt_board_compat[] = { 420 "st,spear600", 421 NULL 422 }; 423 424 DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)") 425 .map_io = spear6xx_map_io, 426 .init_irq = irqchip_init, 427 .init_time = spear6xx_timer_init, 428 .init_machine = spear600_dt_init, 429 .restart = spear_restart, 430 .dt_compat = spear600_dt_board_compat, 431 MACHINE_END 432