| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * SH7201 setup |
| 4 | * |
| 5 | * Copyright (C) 2008 Peter Griffin pgriffin@mpc-data.co.uk |
| 6 | * Copyright (C) 2009 Paul Mundt |
| 7 | */ |
| 8 | #include <linux/platform_device.h> |
| 9 | #include <linux/init.h> |
| 10 | #include <linux/serial.h> |
| 11 | #include <linux/serial_sci.h> |
| 12 | #include <linux/sh_timer.h> |
| 13 | #include <linux/io.h> |
| 14 | #include <asm/platform_early.h> |
| 15 | |
| 16 | enum { |
| 17 | UNUSED = 0, |
| 18 | |
| 19 | /* interrupt sources */ |
| 20 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, |
| 21 | PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7, |
| 22 | |
| 23 | ADC_ADI, |
| 24 | |
| 25 | MTU20_ABCD, MTU20_VEF, MTU21_AB, MTU21_VU, MTU22_AB, MTU22_VU, |
| 26 | MTU23_ABCD, MTU24_ABCD, MTU25_UVW, MTU2_TCI3V, MTU2_TCI4V, |
| 27 | |
| 28 | RTC, WDT, |
| 29 | |
| 30 | IIC30, IIC31, IIC32, |
| 31 | |
| 32 | DMAC0_DMINT0, DMAC1_DMINT1, |
| 33 | DMAC2_DMINT2, DMAC3_DMINT3, |
| 34 | |
| 35 | SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7, |
| 36 | |
| 37 | DMAC0_DMINTA, DMAC4_DMINT4, DMAC5_DMINT5, DMAC6_DMINT6, |
| 38 | DMAC7_DMINT7, |
| 39 | |
| 40 | RCAN0, RCAN1, |
| 41 | |
| 42 | SSI0_SSII, SSI1_SSII, |
| 43 | |
| 44 | TMR0, TMR1, |
| 45 | |
| 46 | /* interrupt groups */ |
| 47 | PINT, |
| 48 | }; |
| 49 | |
| 50 | static struct intc_vect vectors[] __initdata = { |
| 51 | INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65), |
| 52 | INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67), |
| 53 | INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69), |
| 54 | INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71), |
| 55 | |
| 56 | INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81), |
| 57 | INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83), |
| 58 | INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85), |
| 59 | INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87), |
| 60 | |
| 61 | INTC_IRQ(ADC_ADI, 92), |
| 62 | |
| 63 | INTC_IRQ(MTU20_ABCD, 108), INTC_IRQ(MTU20_ABCD, 109), |
| 64 | INTC_IRQ(MTU20_ABCD, 110), INTC_IRQ(MTU20_ABCD, 111), |
| 65 | |
| 66 | INTC_IRQ(MTU20_VEF, 112), INTC_IRQ(MTU20_VEF, 113), |
| 67 | INTC_IRQ(MTU20_VEF, 114), |
| 68 | |
| 69 | INTC_IRQ(MTU21_AB, 116), INTC_IRQ(MTU21_AB, 117), |
| 70 | INTC_IRQ(MTU21_VU, 120), INTC_IRQ(MTU21_VU, 121), |
| 71 | |
| 72 | INTC_IRQ(MTU22_AB, 124), INTC_IRQ(MTU22_AB, 125), |
| 73 | INTC_IRQ(MTU22_VU, 128), INTC_IRQ(MTU22_VU, 129), |
| 74 | |
| 75 | INTC_IRQ(MTU23_ABCD, 132), INTC_IRQ(MTU23_ABCD, 133), |
| 76 | INTC_IRQ(MTU23_ABCD, 134), INTC_IRQ(MTU23_ABCD, 135), |
| 77 | |
| 78 | INTC_IRQ(MTU2_TCI3V, 136), |
| 79 | |
| 80 | INTC_IRQ(MTU24_ABCD, 140), INTC_IRQ(MTU24_ABCD, 141), |
| 81 | INTC_IRQ(MTU24_ABCD, 142), INTC_IRQ(MTU24_ABCD, 143), |
| 82 | |
| 83 | INTC_IRQ(MTU2_TCI4V, 144), |
| 84 | |
| 85 | INTC_IRQ(MTU25_UVW, 148), INTC_IRQ(MTU25_UVW, 149), |
| 86 | INTC_IRQ(MTU25_UVW, 150), |
| 87 | |
| 88 | INTC_IRQ(RTC, 152), INTC_IRQ(RTC, 153), |
| 89 | INTC_IRQ(RTC, 154), |
| 90 | |
| 91 | INTC_IRQ(WDT, 156), |
| 92 | |
| 93 | INTC_IRQ(IIC30, 157), INTC_IRQ(IIC30, 158), |
| 94 | INTC_IRQ(IIC30, 159), INTC_IRQ(IIC30, 160), |
| 95 | INTC_IRQ(IIC30, 161), |
| 96 | |
| 97 | INTC_IRQ(IIC31, 164), INTC_IRQ(IIC31, 165), |
| 98 | INTC_IRQ(IIC31, 166), INTC_IRQ(IIC31, 167), |
| 99 | INTC_IRQ(IIC31, 168), |
| 100 | |
| 101 | INTC_IRQ(IIC32, 170), INTC_IRQ(IIC32, 171), |
| 102 | INTC_IRQ(IIC32, 172), INTC_IRQ(IIC32, 173), |
| 103 | INTC_IRQ(IIC32, 174), |
| 104 | |
| 105 | INTC_IRQ(DMAC0_DMINT0, 176), INTC_IRQ(DMAC1_DMINT1, 177), |
| 106 | INTC_IRQ(DMAC2_DMINT2, 178), INTC_IRQ(DMAC3_DMINT3, 179), |
| 107 | |
| 108 | INTC_IRQ(SCIF0, 180), INTC_IRQ(SCIF0, 181), |
| 109 | INTC_IRQ(SCIF0, 182), INTC_IRQ(SCIF0, 183), |
| 110 | INTC_IRQ(SCIF1, 184), INTC_IRQ(SCIF1, 185), |
| 111 | INTC_IRQ(SCIF1, 186), INTC_IRQ(SCIF1, 187), |
| 112 | INTC_IRQ(SCIF2, 188), INTC_IRQ(SCIF2, 189), |
| 113 | INTC_IRQ(SCIF2, 190), INTC_IRQ(SCIF2, 191), |
| 114 | INTC_IRQ(SCIF3, 192), INTC_IRQ(SCIF3, 193), |
| 115 | INTC_IRQ(SCIF3, 194), INTC_IRQ(SCIF3, 195), |
| 116 | INTC_IRQ(SCIF4, 196), INTC_IRQ(SCIF4, 197), |
| 117 | INTC_IRQ(SCIF4, 198), INTC_IRQ(SCIF4, 199), |
| 118 | INTC_IRQ(SCIF5, 200), INTC_IRQ(SCIF5, 201), |
| 119 | INTC_IRQ(SCIF5, 202), INTC_IRQ(SCIF5, 203), |
| 120 | INTC_IRQ(SCIF6, 204), INTC_IRQ(SCIF6, 205), |
| 121 | INTC_IRQ(SCIF6, 206), INTC_IRQ(SCIF6, 207), |
| 122 | INTC_IRQ(SCIF7, 208), INTC_IRQ(SCIF7, 209), |
| 123 | INTC_IRQ(SCIF7, 210), INTC_IRQ(SCIF7, 211), |
| 124 | |
| 125 | INTC_IRQ(DMAC0_DMINTA, 212), INTC_IRQ(DMAC4_DMINT4, 216), |
| 126 | INTC_IRQ(DMAC5_DMINT5, 217), INTC_IRQ(DMAC6_DMINT6, 218), |
| 127 | INTC_IRQ(DMAC7_DMINT7, 219), |
| 128 | |
| 129 | INTC_IRQ(RCAN0, 228), INTC_IRQ(RCAN0, 229), |
| 130 | INTC_IRQ(RCAN0, 230), |
| 131 | INTC_IRQ(RCAN0, 231), INTC_IRQ(RCAN0, 232), |
| 132 | |
| 133 | INTC_IRQ(RCAN1, 234), INTC_IRQ(RCAN1, 235), |
| 134 | INTC_IRQ(RCAN1, 236), |
| 135 | INTC_IRQ(RCAN1, 237), INTC_IRQ(RCAN1, 238), |
| 136 | |
| 137 | INTC_IRQ(SSI0_SSII, 244), INTC_IRQ(SSI1_SSII, 245), |
| 138 | |
| 139 | INTC_IRQ(TMR0, 246), INTC_IRQ(TMR0, 247), |
| 140 | INTC_IRQ(TMR0, 248), |
| 141 | |
| 142 | INTC_IRQ(TMR1, 252), INTC_IRQ(TMR1, 253), |
| 143 | INTC_IRQ(TMR1, 254), |
| 144 | }; |
| 145 | |
| 146 | static struct intc_group groups[] __initdata = { |
| 147 | INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3, |
| 148 | PINT4, PINT5, PINT6, PINT7), |
| 149 | }; |
| 150 | |
| 151 | static struct intc_prio_reg prio_registers[] __initdata = { |
| 152 | { 0xfffe9418, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } }, |
| 153 | { 0xfffe941a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } }, |
| 154 | { 0xfffe9420, 0, 16, 4, /* IPR05 */ { PINT, 0, ADC_ADI, 0 } }, |
| 155 | { 0xfffe9800, 0, 16, 4, /* IPR06 */ { 0, MTU20_ABCD, MTU20_VEF, MTU21_AB } }, |
| 156 | { 0xfffe9802, 0, 16, 4, /* IPR07 */ { MTU21_VU, MTU22_AB, MTU22_VU, MTU23_ABCD } }, |
| 157 | { 0xfffe9804, 0, 16, 4, /* IPR08 */ { MTU2_TCI3V, MTU24_ABCD, MTU2_TCI4V, MTU25_UVW } }, |
| 158 | |
| 159 | { 0xfffe9806, 0, 16, 4, /* IPR09 */ { RTC, WDT, IIC30, 0 } }, |
| 160 | { 0xfffe9808, 0, 16, 4, /* IPR10 */ { IIC31, IIC32, DMAC0_DMINT0, DMAC1_DMINT1 } }, |
| 161 | { 0xfffe980a, 0, 16, 4, /* IPR11 */ { DMAC2_DMINT2, DMAC3_DMINT3, SCIF0, SCIF1 } }, |
| 162 | { 0xfffe980c, 0, 16, 4, /* IPR12 */ { SCIF2, SCIF3, SCIF4, SCIF5 } }, |
| 163 | { 0xfffe980e, 0, 16, 4, /* IPR13 */ { SCIF6, SCIF7, DMAC0_DMINTA, DMAC4_DMINT4 } }, |
| 164 | { 0xfffe9810, 0, 16, 4, /* IPR14 */ { DMAC5_DMINT5, DMAC6_DMINT6, DMAC7_DMINT7, 0 } }, |
| 165 | { 0xfffe9812, 0, 16, 4, /* IPR15 */ { 0, RCAN0, RCAN1, 0 } }, |
| 166 | { 0xfffe9814, 0, 16, 4, /* IPR16 */ { SSI0_SSII, SSI1_SSII, TMR0, TMR1 } }, |
| 167 | }; |
| 168 | |
| 169 | static struct intc_mask_reg mask_registers[] __initdata = { |
| 170 | { 0xfffe9408, 0, 16, /* PINTER */ |
| 171 | { 0, 0, 0, 0, 0, 0, 0, 0, |
| 172 | PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } }, |
| 173 | }; |
| 174 | |
| 175 | static DECLARE_INTC_DESC(intc_desc, "sh7201" , vectors, groups, |
| 176 | mask_registers, prio_registers, NULL); |
| 177 | |
| 178 | static struct plat_sci_port scif0_platform_data = { |
| 179 | .scscr = SCSCR_REIE, |
| 180 | .type = PORT_SCIF, |
| 181 | }; |
| 182 | |
| 183 | static struct resource scif0_resources[] = { |
| 184 | DEFINE_RES_MEM(0xfffe8000, 0x100), |
| 185 | DEFINE_RES_IRQ(180), |
| 186 | }; |
| 187 | |
| 188 | static struct platform_device scif0_device = { |
| 189 | .name = "sh-sci" , |
| 190 | .id = 0, |
| 191 | .resource = scif0_resources, |
| 192 | .num_resources = ARRAY_SIZE(scif0_resources), |
| 193 | .dev = { |
| 194 | .platform_data = &scif0_platform_data, |
| 195 | }, |
| 196 | }; |
| 197 | |
| 198 | static struct plat_sci_port scif1_platform_data = { |
| 199 | .scscr = SCSCR_REIE, |
| 200 | .type = PORT_SCIF, |
| 201 | }; |
| 202 | |
| 203 | static struct resource scif1_resources[] = { |
| 204 | DEFINE_RES_MEM(0xfffe8800, 0x100), |
| 205 | DEFINE_RES_IRQ(184), |
| 206 | }; |
| 207 | |
| 208 | static struct platform_device scif1_device = { |
| 209 | .name = "sh-sci" , |
| 210 | .id = 1, |
| 211 | .resource = scif1_resources, |
| 212 | .num_resources = ARRAY_SIZE(scif1_resources), |
| 213 | .dev = { |
| 214 | .platform_data = &scif1_platform_data, |
| 215 | }, |
| 216 | }; |
| 217 | |
| 218 | static struct plat_sci_port scif2_platform_data = { |
| 219 | .scscr = SCSCR_REIE, |
| 220 | .type = PORT_SCIF, |
| 221 | }; |
| 222 | |
| 223 | static struct resource scif2_resources[] = { |
| 224 | DEFINE_RES_MEM(0xfffe9000, 0x100), |
| 225 | DEFINE_RES_IRQ(188), |
| 226 | }; |
| 227 | |
| 228 | static struct platform_device scif2_device = { |
| 229 | .name = "sh-sci" , |
| 230 | .id = 2, |
| 231 | .resource = scif2_resources, |
| 232 | .num_resources = ARRAY_SIZE(scif2_resources), |
| 233 | .dev = { |
| 234 | .platform_data = &scif2_platform_data, |
| 235 | }, |
| 236 | }; |
| 237 | |
| 238 | static struct plat_sci_port scif3_platform_data = { |
| 239 | .scscr = SCSCR_REIE, |
| 240 | .type = PORT_SCIF, |
| 241 | }; |
| 242 | |
| 243 | static struct resource scif3_resources[] = { |
| 244 | DEFINE_RES_MEM(0xfffe9800, 0x100), |
| 245 | DEFINE_RES_IRQ(192), |
| 246 | }; |
| 247 | |
| 248 | static struct platform_device scif3_device = { |
| 249 | .name = "sh-sci" , |
| 250 | .id = 3, |
| 251 | .resource = scif3_resources, |
| 252 | .num_resources = ARRAY_SIZE(scif3_resources), |
| 253 | .dev = { |
| 254 | .platform_data = &scif3_platform_data, |
| 255 | }, |
| 256 | }; |
| 257 | |
| 258 | static struct plat_sci_port scif4_platform_data = { |
| 259 | .scscr = SCSCR_REIE, |
| 260 | .type = PORT_SCIF, |
| 261 | }; |
| 262 | |
| 263 | static struct resource scif4_resources[] = { |
| 264 | DEFINE_RES_MEM(0xfffea000, 0x100), |
| 265 | DEFINE_RES_IRQ(196), |
| 266 | }; |
| 267 | |
| 268 | static struct platform_device scif4_device = { |
| 269 | .name = "sh-sci" , |
| 270 | .id = 4, |
| 271 | .resource = scif4_resources, |
| 272 | .num_resources = ARRAY_SIZE(scif4_resources), |
| 273 | .dev = { |
| 274 | .platform_data = &scif4_platform_data, |
| 275 | }, |
| 276 | }; |
| 277 | |
| 278 | static struct plat_sci_port scif5_platform_data = { |
| 279 | .scscr = SCSCR_REIE, |
| 280 | .type = PORT_SCIF, |
| 281 | }; |
| 282 | |
| 283 | static struct resource scif5_resources[] = { |
| 284 | DEFINE_RES_MEM(0xfffea800, 0x100), |
| 285 | DEFINE_RES_IRQ(200), |
| 286 | }; |
| 287 | |
| 288 | static struct platform_device scif5_device = { |
| 289 | .name = "sh-sci" , |
| 290 | .id = 5, |
| 291 | .resource = scif5_resources, |
| 292 | .num_resources = ARRAY_SIZE(scif5_resources), |
| 293 | .dev = { |
| 294 | .platform_data = &scif5_platform_data, |
| 295 | }, |
| 296 | }; |
| 297 | |
| 298 | static struct plat_sci_port scif6_platform_data = { |
| 299 | .scscr = SCSCR_REIE, |
| 300 | .type = PORT_SCIF, |
| 301 | }; |
| 302 | |
| 303 | static struct resource scif6_resources[] = { |
| 304 | DEFINE_RES_MEM(0xfffeb000, 0x100), |
| 305 | DEFINE_RES_IRQ(204), |
| 306 | }; |
| 307 | |
| 308 | static struct platform_device scif6_device = { |
| 309 | .name = "sh-sci" , |
| 310 | .id = 6, |
| 311 | .resource = scif6_resources, |
| 312 | .num_resources = ARRAY_SIZE(scif6_resources), |
| 313 | .dev = { |
| 314 | .platform_data = &scif6_platform_data, |
| 315 | }, |
| 316 | }; |
| 317 | |
| 318 | static struct plat_sci_port scif7_platform_data = { |
| 319 | .scscr = SCSCR_REIE, |
| 320 | .type = PORT_SCIF, |
| 321 | }; |
| 322 | |
| 323 | static struct resource scif7_resources[] = { |
| 324 | DEFINE_RES_MEM(0xfffeb800, 0x100), |
| 325 | DEFINE_RES_IRQ(208), |
| 326 | }; |
| 327 | |
| 328 | static struct platform_device scif7_device = { |
| 329 | .name = "sh-sci" , |
| 330 | .id = 7, |
| 331 | .resource = scif7_resources, |
| 332 | .num_resources = ARRAY_SIZE(scif7_resources), |
| 333 | .dev = { |
| 334 | .platform_data = &scif7_platform_data, |
| 335 | }, |
| 336 | }; |
| 337 | |
| 338 | static struct resource rtc_resources[] = { |
| 339 | [0] = { |
| 340 | .start = 0xffff0800, |
| 341 | .end = 0xffff2000 + 0x58 - 1, |
| 342 | .flags = IORESOURCE_IO, |
| 343 | }, |
| 344 | [1] = { |
| 345 | /* Shared Period/Carry/Alarm IRQ */ |
| 346 | .start = 152, |
| 347 | .flags = IORESOURCE_IRQ, |
| 348 | }, |
| 349 | }; |
| 350 | |
| 351 | static struct platform_device rtc_device = { |
| 352 | .name = "sh-rtc" , |
| 353 | .id = -1, |
| 354 | .num_resources = ARRAY_SIZE(rtc_resources), |
| 355 | .resource = rtc_resources, |
| 356 | }; |
| 357 | |
| 358 | static struct resource mtu2_resources[] = { |
| 359 | DEFINE_RES_MEM(0xfffe4000, 0x400), |
| 360 | DEFINE_RES_IRQ_NAMED(108, "tgi0a" ), |
| 361 | DEFINE_RES_IRQ_NAMED(116, "tgi1a" ), |
| 362 | DEFINE_RES_IRQ_NAMED(124, "tgi1b" ), |
| 363 | }; |
| 364 | |
| 365 | static struct platform_device mtu2_device = { |
| 366 | .name = "sh-mtu2" , |
| 367 | .id = -1, |
| 368 | .resource = mtu2_resources, |
| 369 | .num_resources = ARRAY_SIZE(mtu2_resources), |
| 370 | }; |
| 371 | |
| 372 | static struct platform_device *sh7201_devices[] __initdata = { |
| 373 | &scif0_device, |
| 374 | &scif1_device, |
| 375 | &scif2_device, |
| 376 | &scif3_device, |
| 377 | &scif4_device, |
| 378 | &scif5_device, |
| 379 | &scif6_device, |
| 380 | &scif7_device, |
| 381 | &rtc_device, |
| 382 | &mtu2_device, |
| 383 | }; |
| 384 | |
| 385 | static int __init sh7201_devices_setup(void) |
| 386 | { |
| 387 | return platform_add_devices(sh7201_devices, |
| 388 | ARRAY_SIZE(sh7201_devices)); |
| 389 | } |
| 390 | arch_initcall(sh7201_devices_setup); |
| 391 | |
| 392 | void __init plat_irq_setup(void) |
| 393 | { |
| 394 | register_intc_controller(&intc_desc); |
| 395 | } |
| 396 | |
| 397 | static struct platform_device *sh7201_early_devices[] __initdata = { |
| 398 | &scif0_device, |
| 399 | &scif1_device, |
| 400 | &scif2_device, |
| 401 | &scif3_device, |
| 402 | &scif4_device, |
| 403 | &scif5_device, |
| 404 | &scif6_device, |
| 405 | &scif7_device, |
| 406 | &mtu2_device, |
| 407 | }; |
| 408 | |
| 409 | #define STBCR3 0xfffe0408 |
| 410 | |
| 411 | void __init plat_early_device_setup(void) |
| 412 | { |
| 413 | /* enable MTU2 clock */ |
| 414 | __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3); |
| 415 | |
| 416 | sh_early_platform_add_devices(sh7201_early_devices, |
| 417 | ARRAY_SIZE(sh7201_early_devices)); |
| 418 | } |
| 419 | |