1/* 2 * sh7372 processor support 3 * 4 * Copyright (C) 2010 Magnus Damm 5 * Copyright (C) 2008 Yoshihiro Shimoda 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20#include <linux/kernel.h> 21#include <linux/init.h> 22#include <linux/interrupt.h> 23#include <linux/irq.h> 24#include <linux/platform_device.h> 25#include <linux/delay.h> 26#include <linux/input.h> 27#include <linux/io.h> 28#include <linux/serial_sci.h> 29#include <linux/sh_dma.h> 30#include <linux/sh_intc.h> 31#include <linux/sh_timer.h> 32#include <mach/hardware.h> 33#include <mach/sh7372.h> 34#include <asm/mach-types.h> 35#include <asm/mach/arch.h> 36 37/* SCIFA0 */ 38static struct plat_sci_port scif0_platform_data = { 39 .mapbase = 0xe6c40000, 40 .flags = UPF_BOOT_AUTOCONF, 41 .type = PORT_SCIFA, 42 .irqs = { evt2irq(0x0c00), evt2irq(0x0c00), 43 evt2irq(0x0c00), evt2irq(0x0c00) }, 44}; 45 46static struct platform_device scif0_device = { 47 .name = "sh-sci", 48 .id = 0, 49 .dev = { 50 .platform_data = &scif0_platform_data, 51 }, 52}; 53 54/* SCIFA1 */ 55static struct plat_sci_port scif1_platform_data = { 56 .mapbase = 0xe6c50000, 57 .flags = UPF_BOOT_AUTOCONF, 58 .type = PORT_SCIFA, 59 .irqs = { evt2irq(0x0c20), evt2irq(0x0c20), 60 evt2irq(0x0c20), evt2irq(0x0c20) }, 61}; 62 63static struct platform_device scif1_device = { 64 .name = "sh-sci", 65 .id = 1, 66 .dev = { 67 .platform_data = &scif1_platform_data, 68 }, 69}; 70 71/* SCIFA2 */ 72static struct plat_sci_port scif2_platform_data = { 73 .mapbase = 0xe6c60000, 74 .flags = UPF_BOOT_AUTOCONF, 75 .type = PORT_SCIFA, 76 .irqs = { evt2irq(0x0c40), evt2irq(0x0c40), 77 evt2irq(0x0c40), evt2irq(0x0c40) }, 78}; 79 80static struct platform_device scif2_device = { 81 .name = "sh-sci", 82 .id = 2, 83 .dev = { 84 .platform_data = &scif2_platform_data, 85 }, 86}; 87 88/* SCIFA3 */ 89static struct plat_sci_port scif3_platform_data = { 90 .mapbase = 0xe6c70000, 91 .flags = UPF_BOOT_AUTOCONF, 92 .type = PORT_SCIFA, 93 .irqs = { evt2irq(0x0c60), evt2irq(0x0c60), 94 evt2irq(0x0c60), evt2irq(0x0c60) }, 95}; 96 97static struct platform_device scif3_device = { 98 .name = "sh-sci", 99 .id = 3, 100 .dev = { 101 .platform_data = &scif3_platform_data, 102 }, 103}; 104 105/* SCIFA4 */ 106static struct plat_sci_port scif4_platform_data = { 107 .mapbase = 0xe6c80000, 108 .flags = UPF_BOOT_AUTOCONF, 109 .type = PORT_SCIFA, 110 .irqs = { evt2irq(0x0d20), evt2irq(0x0d20), 111 evt2irq(0x0d20), evt2irq(0x0d20) }, 112}; 113 114static struct platform_device scif4_device = { 115 .name = "sh-sci", 116 .id = 4, 117 .dev = { 118 .platform_data = &scif4_platform_data, 119 }, 120}; 121 122/* SCIFA5 */ 123static struct plat_sci_port scif5_platform_data = { 124 .mapbase = 0xe6cb0000, 125 .flags = UPF_BOOT_AUTOCONF, 126 .type = PORT_SCIFA, 127 .irqs = { evt2irq(0x0d40), evt2irq(0x0d40), 128 evt2irq(0x0d40), evt2irq(0x0d40) }, 129}; 130 131static struct platform_device scif5_device = { 132 .name = "sh-sci", 133 .id = 5, 134 .dev = { 135 .platform_data = &scif5_platform_data, 136 }, 137}; 138 139/* SCIFB */ 140static struct plat_sci_port scif6_platform_data = { 141 .mapbase = 0xe6c30000, 142 .flags = UPF_BOOT_AUTOCONF, 143 .type = PORT_SCIFB, 144 .irqs = { evt2irq(0x0d60), evt2irq(0x0d60), 145 evt2irq(0x0d60), evt2irq(0x0d60) }, 146}; 147 148static struct platform_device scif6_device = { 149 .name = "sh-sci", 150 .id = 6, 151 .dev = { 152 .platform_data = &scif6_platform_data, 153 }, 154}; 155 156/* CMT */ 157static struct sh_timer_config cmt10_platform_data = { 158 .name = "CMT10", 159 .channel_offset = 0x10, 160 .timer_bit = 0, 161 .clk = "cmt1", 162 .clockevent_rating = 125, 163 .clocksource_rating = 125, 164}; 165 166static struct resource cmt10_resources[] = { 167 [0] = { 168 .name = "CMT10", 169 .start = 0xe6138010, 170 .end = 0xe613801b, 171 .flags = IORESOURCE_MEM, 172 }, 173 [1] = { 174 .start = evt2irq(0x0b00), /* CMT1_CMT10 */ 175 .flags = IORESOURCE_IRQ, 176 }, 177}; 178 179static struct platform_device cmt10_device = { 180 .name = "sh_cmt", 181 .id = 10, 182 .dev = { 183 .platform_data = &cmt10_platform_data, 184 }, 185 .resource = cmt10_resources, 186 .num_resources = ARRAY_SIZE(cmt10_resources), 187}; 188 189/* I2C */ 190static struct resource iic0_resources[] = { 191 [0] = { 192 .name = "IIC0", 193 .start = 0xFFF20000, 194 .end = 0xFFF20425 - 1, 195 .flags = IORESOURCE_MEM, 196 }, 197 [1] = { 198 .start = intcs_evt2irq(0xe00), /* IIC0_ALI0 */ 199 .end = intcs_evt2irq(0xe60), /* IIC0_DTEI0 */ 200 .flags = IORESOURCE_IRQ, 201 }, 202}; 203 204static struct platform_device iic0_device = { 205 .name = "i2c-sh_mobile", 206 .id = 0, /* "i2c0" clock */ 207 .num_resources = ARRAY_SIZE(iic0_resources), 208 .resource = iic0_resources, 209}; 210 211static struct resource iic1_resources[] = { 212 [0] = { 213 .name = "IIC1", 214 .start = 0xE6C20000, 215 .end = 0xE6C20425 - 1, 216 .flags = IORESOURCE_MEM, 217 }, 218 [1] = { 219 .start = evt2irq(0x780), /* IIC1_ALI1 */ 220 .end = evt2irq(0x7e0), /* IIC1_DTEI1 */ 221 .flags = IORESOURCE_IRQ, 222 }, 223}; 224 225static struct platform_device iic1_device = { 226 .name = "i2c-sh_mobile", 227 .id = 1, /* "i2c1" clock */ 228 .num_resources = ARRAY_SIZE(iic1_resources), 229 .resource = iic1_resources, 230}; 231 232/* DMA */ 233/* Transmit sizes and respective CHCR register values */ 234enum { 235 XMIT_SZ_8BIT = 0, 236 XMIT_SZ_16BIT = 1, 237 XMIT_SZ_32BIT = 2, 238 XMIT_SZ_64BIT = 7, 239 XMIT_SZ_128BIT = 3, 240 XMIT_SZ_256BIT = 4, 241 XMIT_SZ_512BIT = 5, 242}; 243 244/* log2(size / 8) - used to calculate number of transfers */ 245#define TS_SHIFT { \ 246 [XMIT_SZ_8BIT] = 0, \ 247 [XMIT_SZ_16BIT] = 1, \ 248 [XMIT_SZ_32BIT] = 2, \ 249 [XMIT_SZ_64BIT] = 3, \ 250 [XMIT_SZ_128BIT] = 4, \ 251 [XMIT_SZ_256BIT] = 5, \ 252 [XMIT_SZ_512BIT] = 6, \ 253} 254 255#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | \ 256 (((i) & 0xc) << (20 - 2))) 257 258static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = { 259 { 260 .slave_id = SHDMA_SLAVE_SCIF0_TX, 261 .addr = 0xe6c40020, 262 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 263 .mid_rid = 0x21, 264 }, { 265 .slave_id = SHDMA_SLAVE_SCIF0_RX, 266 .addr = 0xe6c40024, 267 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 268 .mid_rid = 0x22, 269 }, { 270 .slave_id = SHDMA_SLAVE_SCIF1_TX, 271 .addr = 0xe6c50020, 272 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 273 .mid_rid = 0x25, 274 }, { 275 .slave_id = SHDMA_SLAVE_SCIF1_RX, 276 .addr = 0xe6c50024, 277 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 278 .mid_rid = 0x26, 279 }, { 280 .slave_id = SHDMA_SLAVE_SCIF2_TX, 281 .addr = 0xe6c60020, 282 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 283 .mid_rid = 0x29, 284 }, { 285 .slave_id = SHDMA_SLAVE_SCIF2_RX, 286 .addr = 0xe6c60024, 287 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 288 .mid_rid = 0x2a, 289 }, { 290 .slave_id = SHDMA_SLAVE_SCIF3_TX, 291 .addr = 0xe6c70020, 292 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 293 .mid_rid = 0x2d, 294 }, { 295 .slave_id = SHDMA_SLAVE_SCIF3_RX, 296 .addr = 0xe6c70024, 297 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 298 .mid_rid = 0x2e, 299 }, { 300 .slave_id = SHDMA_SLAVE_SCIF4_TX, 301 .addr = 0xe6c80020, 302 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 303 .mid_rid = 0x39, 304 }, { 305 .slave_id = SHDMA_SLAVE_SCIF4_RX, 306 .addr = 0xe6c80024, 307 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 308 .mid_rid = 0x3a, 309 }, { 310 .slave_id = SHDMA_SLAVE_SCIF5_TX, 311 .addr = 0xe6cb0020, 312 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 313 .mid_rid = 0x35, 314 }, { 315 .slave_id = SHDMA_SLAVE_SCIF5_RX, 316 .addr = 0xe6cb0024, 317 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 318 .mid_rid = 0x36, 319 }, { 320 .slave_id = SHDMA_SLAVE_SCIF6_TX, 321 .addr = 0xe6c30040, 322 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 323 .mid_rid = 0x3d, 324 }, { 325 .slave_id = SHDMA_SLAVE_SCIF6_RX, 326 .addr = 0xe6c30060, 327 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), 328 .mid_rid = 0x3e, 329 }, { 330 .slave_id = SHDMA_SLAVE_SDHI0_TX, 331 .addr = 0xe6850030, 332 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), 333 .mid_rid = 0xc1, 334 }, { 335 .slave_id = SHDMA_SLAVE_SDHI0_RX, 336 .addr = 0xe6850030, 337 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), 338 .mid_rid = 0xc2, 339 }, { 340 .slave_id = SHDMA_SLAVE_SDHI1_TX, 341 .addr = 0xe6860030, 342 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), 343 .mid_rid = 0xc9, 344 }, { 345 .slave_id = SHDMA_SLAVE_SDHI1_RX, 346 .addr = 0xe6860030, 347 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), 348 .mid_rid = 0xca, 349 }, { 350 .slave_id = SHDMA_SLAVE_SDHI2_TX, 351 .addr = 0xe6870030, 352 .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), 353 .mid_rid = 0xcd, 354 }, { 355 .slave_id = SHDMA_SLAVE_SDHI2_RX, 356 .addr = 0xe6870030, 357 .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), 358 .mid_rid = 0xce, 359 }, 360}; 361 362static const struct sh_dmae_channel sh7372_dmae_channels[] = { 363 { 364 .offset = 0, 365 .dmars = 0, 366 .dmars_bit = 0, 367 }, { 368 .offset = 0x10, 369 .dmars = 0, 370 .dmars_bit = 8, 371 }, { 372 .offset = 0x20, 373 .dmars = 4, 374 .dmars_bit = 0, 375 }, { 376 .offset = 0x30, 377 .dmars = 4, 378 .dmars_bit = 8, 379 }, { 380 .offset = 0x50, 381 .dmars = 8, 382 .dmars_bit = 0, 383 }, { 384 .offset = 0x60, 385 .dmars = 8, 386 .dmars_bit = 8, 387 } 388}; 389 390static const unsigned int ts_shift[] = TS_SHIFT; 391 392static struct sh_dmae_pdata dma_platform_data = { 393 .slave = sh7372_dmae_slaves, 394 .slave_num = ARRAY_SIZE(sh7372_dmae_slaves), 395 .channel = sh7372_dmae_channels, 396 .channel_num = ARRAY_SIZE(sh7372_dmae_channels), 397 .ts_low_shift = 3, 398 .ts_low_mask = 0x18, 399 .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */ 400 .ts_high_mask = 0x00300000, 401 .ts_shift = ts_shift, 402 .ts_shift_num = ARRAY_SIZE(ts_shift), 403 .dmaor_init = DMAOR_DME, 404}; 405 406/* Resource order important! */ 407static struct resource sh7372_dmae0_resources[] = { 408 { 409 /* Channel registers and DMAOR */ 410 .start = 0xfe008020, 411 .end = 0xfe00808f, 412 .flags = IORESOURCE_MEM, 413 }, 414 { 415 /* DMARSx */ 416 .start = 0xfe009000, 417 .end = 0xfe00900b, 418 .flags = IORESOURCE_MEM, 419 }, 420 { 421 /* DMA error IRQ */ 422 .start = 246, 423 .end = 246, 424 .flags = IORESOURCE_IRQ, 425 }, 426 { 427 /* IRQ for channels 0-5 */ 428 .start = 240, 429 .end = 245, 430 .flags = IORESOURCE_IRQ, 431 }, 432}; 433 434/* Resource order important! */ 435static struct resource sh7372_dmae1_resources[] = { 436 { 437 /* Channel registers and DMAOR */ 438 .start = 0xfe018020, 439 .end = 0xfe01808f, 440 .flags = IORESOURCE_MEM, 441 }, 442 { 443 /* DMARSx */ 444 .start = 0xfe019000, 445 .end = 0xfe01900b, 446 .flags = IORESOURCE_MEM, 447 }, 448 { 449 /* DMA error IRQ */ 450 .start = 254, 451 .end = 254, 452 .flags = IORESOURCE_IRQ, 453 }, 454 { 455 /* IRQ for channels 0-5 */ 456 .start = 248, 457 .end = 253, 458 .flags = IORESOURCE_IRQ, 459 }, 460}; 461 462/* Resource order important! */ 463static struct resource sh7372_dmae2_resources[] = { 464 { 465 /* Channel registers and DMAOR */ 466 .start = 0xfe028020, 467 .end = 0xfe02808f, 468 .flags = IORESOURCE_MEM, 469 }, 470 { 471 /* DMARSx */ 472 .start = 0xfe029000, 473 .end = 0xfe02900b, 474 .flags = IORESOURCE_MEM, 475 }, 476 { 477 /* DMA error IRQ */ 478 .start = 262, 479 .end = 262, 480 .flags = IORESOURCE_IRQ, 481 }, 482 { 483 /* IRQ for channels 0-5 */ 484 .start = 256, 485 .end = 261, 486 .flags = IORESOURCE_IRQ, 487 }, 488}; 489 490static struct platform_device dma0_device = { 491 .name = "sh-dma-engine", 492 .id = 0, 493 .resource = sh7372_dmae0_resources, 494 .num_resources = ARRAY_SIZE(sh7372_dmae0_resources), 495 .dev = { 496 .platform_data = &dma_platform_data, 497 }, 498}; 499 500static struct platform_device dma1_device = { 501 .name = "sh-dma-engine", 502 .id = 1, 503 .resource = sh7372_dmae1_resources, 504 .num_resources = ARRAY_SIZE(sh7372_dmae1_resources), 505 .dev = { 506 .platform_data = &dma_platform_data, 507 }, 508}; 509 510static struct platform_device dma2_device = { 511 .name = "sh-dma-engine", 512 .id = 2, 513 .resource = sh7372_dmae2_resources, 514 .num_resources = ARRAY_SIZE(sh7372_dmae2_resources), 515 .dev = { 516 .platform_data = &dma_platform_data, 517 }, 518}; 519 520static struct platform_device *sh7372_early_devices[] __initdata = { 521 &scif0_device, 522 &scif1_device, 523 &scif2_device, 524 &scif3_device, 525 &scif4_device, 526 &scif5_device, 527 &scif6_device, 528 &cmt10_device, 529 &iic0_device, 530 &iic1_device, 531 &dma0_device, 532 &dma1_device, 533 &dma2_device, 534}; 535 536void __init sh7372_add_standard_devices(void) 537{ 538 platform_add_devices(sh7372_early_devices, 539 ARRAY_SIZE(sh7372_early_devices)); 540} 541 542void __init sh7372_add_early_devices(void) 543{ 544 early_platform_add_devices(sh7372_early_devices, 545 ARRAY_SIZE(sh7372_early_devices)); 546} 547