1 /* 2 * SH-X3 Prototype Setup 3 * 4 * Copyright (C) 2007 - 2010 Paul Mundt 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 #include <linux/platform_device.h> 11 #include <linux/init.h> 12 #include <linux/serial.h> 13 #include <linux/serial_sci.h> 14 #include <linux/io.h> 15 #include <linux/gpio.h> 16 #include <linux/sh_timer.h> 17 #include <cpu/shx3.h> 18 #include <asm/mmzone.h> 19 20 /* 21 * This intentionally only registers SCIF ports 0, 1, and 3. SCIF 2 22 * INTEVT values overlap with the FPU EXPEVT ones, requiring special 23 * demuxing in the exception dispatch path. 24 * 25 * As this overlap is something that never should have made it in to 26 * silicon in the first place, we just refuse to deal with the port at 27 * all rather than adding infrastructure to hack around it. 28 */ 29 static struct plat_sci_port scif0_platform_data = { 30 .mapbase = 0xffc30000, 31 .flags = UPF_BOOT_AUTOCONF, 32 .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, 33 .scbrr_algo_id = SCBRR_ALGO_2, 34 .type = PORT_SCIF, 35 .irqs = { 40, 41, 43, 42 }, 36 }; 37 38 static struct platform_device scif0_device = { 39 .name = "sh-sci", 40 .id = 0, 41 .dev = { 42 .platform_data = &scif0_platform_data, 43 }, 44 }; 45 46 static struct plat_sci_port scif1_platform_data = { 47 .mapbase = 0xffc40000, 48 .flags = UPF_BOOT_AUTOCONF, 49 .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, 50 .scbrr_algo_id = SCBRR_ALGO_2, 51 .type = PORT_SCIF, 52 .irqs = { 44, 45, 47, 46 }, 53 }; 54 55 static struct platform_device scif1_device = { 56 .name = "sh-sci", 57 .id = 1, 58 .dev = { 59 .platform_data = &scif1_platform_data, 60 }, 61 }; 62 63 static struct plat_sci_port scif2_platform_data = { 64 .mapbase = 0xffc60000, 65 .flags = UPF_BOOT_AUTOCONF, 66 .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, 67 .scbrr_algo_id = SCBRR_ALGO_2, 68 .type = PORT_SCIF, 69 .irqs = { 52, 53, 55, 54 }, 70 }; 71 72 static struct platform_device scif2_device = { 73 .name = "sh-sci", 74 .id = 2, 75 .dev = { 76 .platform_data = &scif2_platform_data, 77 }, 78 }; 79 80 static struct sh_timer_config tmu0_platform_data = { 81 .channel_offset = 0x04, 82 .timer_bit = 0, 83 .clockevent_rating = 200, 84 }; 85 86 static struct resource tmu0_resources[] = { 87 [0] = { 88 .start = 0xffc10008, 89 .end = 0xffc10013, 90 .flags = IORESOURCE_MEM, 91 }, 92 [1] = { 93 .start = 16, 94 .flags = IORESOURCE_IRQ, 95 }, 96 }; 97 98 static struct platform_device tmu0_device = { 99 .name = "sh_tmu", 100 .id = 0, 101 .dev = { 102 .platform_data = &tmu0_platform_data, 103 }, 104 .resource = tmu0_resources, 105 .num_resources = ARRAY_SIZE(tmu0_resources), 106 }; 107 108 static struct sh_timer_config tmu1_platform_data = { 109 .channel_offset = 0x10, 110 .timer_bit = 1, 111 .clocksource_rating = 200, 112 }; 113 114 static struct resource tmu1_resources[] = { 115 [0] = { 116 .start = 0xffc10014, 117 .end = 0xffc1001f, 118 .flags = IORESOURCE_MEM, 119 }, 120 [1] = { 121 .start = 17, 122 .flags = IORESOURCE_IRQ, 123 }, 124 }; 125 126 static struct platform_device tmu1_device = { 127 .name = "sh_tmu", 128 .id = 1, 129 .dev = { 130 .platform_data = &tmu1_platform_data, 131 }, 132 .resource = tmu1_resources, 133 .num_resources = ARRAY_SIZE(tmu1_resources), 134 }; 135 136 static struct sh_timer_config tmu2_platform_data = { 137 .channel_offset = 0x1c, 138 .timer_bit = 2, 139 }; 140 141 static struct resource tmu2_resources[] = { 142 [0] = { 143 .start = 0xffc10020, 144 .end = 0xffc1002f, 145 .flags = IORESOURCE_MEM, 146 }, 147 [1] = { 148 .start = 18, 149 .flags = IORESOURCE_IRQ, 150 }, 151 }; 152 153 static struct platform_device tmu2_device = { 154 .name = "sh_tmu", 155 .id = 2, 156 .dev = { 157 .platform_data = &tmu2_platform_data, 158 }, 159 .resource = tmu2_resources, 160 .num_resources = ARRAY_SIZE(tmu2_resources), 161 }; 162 163 static struct sh_timer_config tmu3_platform_data = { 164 .channel_offset = 0x04, 165 .timer_bit = 0, 166 }; 167 168 static struct resource tmu3_resources[] = { 169 [0] = { 170 .start = 0xffc20008, 171 .end = 0xffc20013, 172 .flags = IORESOURCE_MEM, 173 }, 174 [1] = { 175 .start = 19, 176 .flags = IORESOURCE_IRQ, 177 }, 178 }; 179 180 static struct platform_device tmu3_device = { 181 .name = "sh_tmu", 182 .id = 3, 183 .dev = { 184 .platform_data = &tmu3_platform_data, 185 }, 186 .resource = tmu3_resources, 187 .num_resources = ARRAY_SIZE(tmu3_resources), 188 }; 189 190 static struct sh_timer_config tmu4_platform_data = { 191 .channel_offset = 0x10, 192 .timer_bit = 1, 193 }; 194 195 static struct resource tmu4_resources[] = { 196 [0] = { 197 .start = 0xffc20014, 198 .end = 0xffc2001f, 199 .flags = IORESOURCE_MEM, 200 }, 201 [1] = { 202 .start = 20, 203 .flags = IORESOURCE_IRQ, 204 }, 205 }; 206 207 static struct platform_device tmu4_device = { 208 .name = "sh_tmu", 209 .id = 4, 210 .dev = { 211 .platform_data = &tmu4_platform_data, 212 }, 213 .resource = tmu4_resources, 214 .num_resources = ARRAY_SIZE(tmu4_resources), 215 }; 216 217 static struct sh_timer_config tmu5_platform_data = { 218 .channel_offset = 0x1c, 219 .timer_bit = 2, 220 }; 221 222 static struct resource tmu5_resources[] = { 223 [0] = { 224 .start = 0xffc20020, 225 .end = 0xffc2002b, 226 .flags = IORESOURCE_MEM, 227 }, 228 [1] = { 229 .start = 21, 230 .flags = IORESOURCE_IRQ, 231 }, 232 }; 233 234 static struct platform_device tmu5_device = { 235 .name = "sh_tmu", 236 .id = 5, 237 .dev = { 238 .platform_data = &tmu5_platform_data, 239 }, 240 .resource = tmu5_resources, 241 .num_resources = ARRAY_SIZE(tmu5_resources), 242 }; 243 244 static struct platform_device *shx3_early_devices[] __initdata = { 245 &scif0_device, 246 &scif1_device, 247 &scif2_device, 248 &tmu0_device, 249 &tmu1_device, 250 &tmu2_device, 251 &tmu3_device, 252 &tmu4_device, 253 &tmu5_device, 254 }; 255 256 static int __init shx3_devices_setup(void) 257 { 258 return platform_add_devices(shx3_early_devices, 259 ARRAY_SIZE(shx3_early_devices)); 260 } 261 arch_initcall(shx3_devices_setup); 262 263 void __init plat_early_device_setup(void) 264 { 265 early_platform_add_devices(shx3_early_devices, 266 ARRAY_SIZE(shx3_early_devices)); 267 } 268 269 enum { 270 UNUSED = 0, 271 272 /* interrupt sources */ 273 IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, 274 IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, 275 IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, 276 IRL_HHLL, IRL_HHLH, IRL_HHHL, 277 IRQ0, IRQ1, IRQ2, IRQ3, 278 HUDII, 279 TMU0, TMU1, TMU2, TMU3, TMU4, TMU5, 280 PCII0, PCII1, PCII2, PCII3, PCII4, 281 PCII5, PCII6, PCII7, PCII8, PCII9, 282 SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI, 283 SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI, 284 SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI, 285 SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI, 286 DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, 287 DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE, 288 DU, 289 DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8, DMAC1_DMINT9, 290 DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE, 291 IIC, VIN0, VIN1, VCORE0, ATAPI, 292 DTU0, DTU1, DTU2, DTU3, 293 FE0, FE1, 294 GPIO0, GPIO1, GPIO2, GPIO3, 295 PAM, IRM, 296 INTICI0, INTICI1, INTICI2, INTICI3, 297 INTICI4, INTICI5, INTICI6, INTICI7, 298 299 /* interrupt groups */ 300 IRL, PCII56789, SCIF0, SCIF1, SCIF2, SCIF3, 301 DMAC0, DMAC1, 302 }; 303 304 static struct intc_vect vectors[] __initdata = { 305 INTC_VECT(HUDII, 0x3e0), 306 INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), 307 INTC_VECT(TMU2, 0x440), INTC_VECT(TMU3, 0x460), 308 INTC_VECT(TMU4, 0x480), INTC_VECT(TMU5, 0x4a0), 309 INTC_VECT(PCII0, 0x500), INTC_VECT(PCII1, 0x520), 310 INTC_VECT(PCII2, 0x540), INTC_VECT(PCII3, 0x560), 311 INTC_VECT(PCII4, 0x580), INTC_VECT(PCII5, 0x5a0), 312 INTC_VECT(PCII6, 0x5c0), INTC_VECT(PCII7, 0x5e0), 313 INTC_VECT(PCII8, 0x600), INTC_VECT(PCII9, 0x620), 314 INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720), 315 INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760), 316 INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0), 317 INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0), 318 INTC_VECT(SCIF3_ERI, 0x880), INTC_VECT(SCIF3_RXI, 0x8a0), 319 INTC_VECT(SCIF3_BRI, 0x8c0), INTC_VECT(SCIF3_TXI, 0x8e0), 320 INTC_VECT(DMAC0_DMINT0, 0x900), INTC_VECT(DMAC0_DMINT1, 0x920), 321 INTC_VECT(DMAC0_DMINT2, 0x940), INTC_VECT(DMAC0_DMINT3, 0x960), 322 INTC_VECT(DMAC0_DMINT4, 0x980), INTC_VECT(DMAC0_DMINT5, 0x9a0), 323 INTC_VECT(DMAC0_DMAE, 0x9c0), 324 INTC_VECT(DU, 0x9e0), 325 INTC_VECT(DMAC1_DMINT6, 0xa00), INTC_VECT(DMAC1_DMINT7, 0xa20), 326 INTC_VECT(DMAC1_DMINT8, 0xa40), INTC_VECT(DMAC1_DMINT9, 0xa60), 327 INTC_VECT(DMAC1_DMINT10, 0xa80), INTC_VECT(DMAC1_DMINT11, 0xaa0), 328 INTC_VECT(DMAC1_DMAE, 0xac0), 329 INTC_VECT(IIC, 0xae0), 330 INTC_VECT(VIN0, 0xb00), INTC_VECT(VIN1, 0xb20), 331 INTC_VECT(VCORE0, 0xb00), INTC_VECT(ATAPI, 0xb60), 332 INTC_VECT(DTU0, 0xc00), INTC_VECT(DTU0, 0xc20), 333 INTC_VECT(DTU0, 0xc40), 334 INTC_VECT(DTU1, 0xc60), INTC_VECT(DTU1, 0xc80), 335 INTC_VECT(DTU1, 0xca0), 336 INTC_VECT(DTU2, 0xcc0), INTC_VECT(DTU2, 0xce0), 337 INTC_VECT(DTU2, 0xd00), 338 INTC_VECT(DTU3, 0xd20), INTC_VECT(DTU3, 0xd40), 339 INTC_VECT(DTU3, 0xd60), 340 INTC_VECT(FE0, 0xe00), INTC_VECT(FE1, 0xe20), 341 INTC_VECT(GPIO0, 0xe40), INTC_VECT(GPIO1, 0xe60), 342 INTC_VECT(GPIO2, 0xe80), INTC_VECT(GPIO3, 0xea0), 343 INTC_VECT(PAM, 0xec0), INTC_VECT(IRM, 0xee0), 344 INTC_VECT(INTICI0, 0xf00), INTC_VECT(INTICI1, 0xf20), 345 INTC_VECT(INTICI2, 0xf40), INTC_VECT(INTICI3, 0xf60), 346 INTC_VECT(INTICI4, 0xf80), INTC_VECT(INTICI5, 0xfa0), 347 INTC_VECT(INTICI6, 0xfc0), INTC_VECT(INTICI7, 0xfe0), 348 }; 349 350 static struct intc_group groups[] __initdata = { 351 INTC_GROUP(IRL, IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, 352 IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, 353 IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, 354 IRL_HHLL, IRL_HHLH, IRL_HHHL), 355 INTC_GROUP(PCII56789, PCII5, PCII6, PCII7, PCII8, PCII9), 356 INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI), 357 INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI), 358 INTC_GROUP(SCIF3, SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI), 359 INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, 360 DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE), 361 INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8, 362 DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11), 363 }; 364 365 #define INT2DISTCR0 0xfe4108a0 366 #define INT2DISTCR1 0xfe4108a4 367 #define INT2DISTCR2 0xfe4108a8 368 369 static struct intc_mask_reg mask_registers[] __initdata = { 370 { 0xfe410030, 0xfe410050, 32, /* CnINTMSK0 / CnINTMSKCLR0 */ 371 { IRQ0, IRQ1, IRQ2, IRQ3 } }, 372 { 0xfe410040, 0xfe410060, 32, /* CnINTMSK1 / CnINTMSKCLR1 */ 373 { IRL } }, 374 { 0xfe410820, 0xfe410850, 32, /* CnINT2MSK0 / CnINT2MSKCLR0 */ 375 { FE1, FE0, 0, ATAPI, VCORE0, VIN1, VIN0, IIC, 376 DU, GPIO3, GPIO2, GPIO1, GPIO0, PAM, 0, 0, 377 0, 0, 0, 0, 0, 0, 0, 0, /* HUDI bits ignored */ 378 0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, }, 379 INTC_SMP_BALANCING(INT2DISTCR0) }, 380 { 0xfe410830, 0xfe410860, 32, /* CnINT2MSK1 / CnINT2MSKCLR1 */ 381 { 0, 0, 0, 0, DTU3, DTU2, DTU1, DTU0, /* IRM bits ignored */ 382 PCII9, PCII8, PCII7, PCII6, PCII5, PCII4, PCII3, PCII2, 383 PCII1, PCII0, DMAC1_DMAE, DMAC1_DMINT11, 384 DMAC1_DMINT10, DMAC1_DMINT9, DMAC1_DMINT8, DMAC1_DMINT7, 385 DMAC1_DMINT6, DMAC0_DMAE, DMAC0_DMINT5, DMAC0_DMINT4, 386 DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 }, 387 INTC_SMP_BALANCING(INT2DISTCR1) }, 388 { 0xfe410840, 0xfe410870, 32, /* CnINT2MSK2 / CnINT2MSKCLR2 */ 389 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 390 SCIF3_TXI, SCIF3_BRI, SCIF3_RXI, SCIF3_ERI, 391 SCIF2_TXI, SCIF2_BRI, SCIF2_RXI, SCIF2_ERI, 392 SCIF1_TXI, SCIF1_BRI, SCIF1_RXI, SCIF1_ERI, 393 SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI }, 394 INTC_SMP_BALANCING(INT2DISTCR2) }, 395 }; 396 397 static struct intc_prio_reg prio_registers[] __initdata = { 398 { 0xfe410010, 0, 32, 4, /* INTPRI */ { IRQ0, IRQ1, IRQ2, IRQ3 } }, 399 400 { 0xfe410800, 0, 32, 4, /* INT2PRI0 */ { 0, HUDII, TMU5, TMU4, 401 TMU3, TMU2, TMU1, TMU0 } }, 402 { 0xfe410804, 0, 32, 4, /* INT2PRI1 */ { DTU3, DTU2, DTU1, DTU0, 403 SCIF3, SCIF2, 404 SCIF1, SCIF0 } }, 405 { 0xfe410808, 0, 32, 4, /* INT2PRI2 */ { DMAC1, DMAC0, 406 PCII56789, PCII4, 407 PCII3, PCII2, 408 PCII1, PCII0 } }, 409 { 0xfe41080c, 0, 32, 4, /* INT2PRI3 */ { FE1, FE0, ATAPI, VCORE0, 410 VIN1, VIN0, IIC, DU} }, 411 { 0xfe410810, 0, 32, 4, /* INT2PRI4 */ { 0, 0, PAM, GPIO3, 412 GPIO2, GPIO1, GPIO0, IRM } }, 413 { 0xfe410090, 0xfe4100a0, 32, 4, /* CnICIPRI / CnICIPRICLR */ 414 { INTICI7, INTICI6, INTICI5, INTICI4, 415 INTICI3, INTICI2, INTICI1, INTICI0 }, INTC_SMP(4, 4) }, 416 }; 417 418 static DECLARE_INTC_DESC(intc_desc, "shx3", vectors, groups, 419 mask_registers, prio_registers, NULL); 420 421 /* Support for external interrupt pins in IRQ mode */ 422 static struct intc_vect vectors_irq[] __initdata = { 423 INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280), 424 INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300), 425 }; 426 427 static struct intc_sense_reg sense_registers[] __initdata = { 428 { 0xfe41001c, 32, 2, /* ICR1 */ { IRQ0, IRQ1, IRQ2, IRQ3 } }, 429 }; 430 431 static DECLARE_INTC_DESC(intc_desc_irq, "shx3-irq", vectors_irq, groups, 432 mask_registers, prio_registers, sense_registers); 433 434 /* External interrupt pins in IRL mode */ 435 static struct intc_vect vectors_irl[] __initdata = { 436 INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220), 437 INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260), 438 INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0), 439 INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0), 440 INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320), 441 INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360), 442 INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0), 443 INTC_VECT(IRL_HHHL, 0x3c0), 444 }; 445 446 static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups, 447 mask_registers, prio_registers, NULL); 448 449 void __init plat_irq_setup_pins(int mode) 450 { 451 int ret = 0; 452 453 switch (mode) { 454 case IRQ_MODE_IRQ: 455 ret |= gpio_request(GPIO_FN_IRQ3, intc_desc_irq.name); 456 ret |= gpio_request(GPIO_FN_IRQ2, intc_desc_irq.name); 457 ret |= gpio_request(GPIO_FN_IRQ1, intc_desc_irq.name); 458 ret |= gpio_request(GPIO_FN_IRQ0, intc_desc_irq.name); 459 460 if (unlikely(ret)) { 461 pr_err("Failed to set IRQ mode\n"); 462 return; 463 } 464 465 register_intc_controller(&intc_desc_irq); 466 break; 467 case IRQ_MODE_IRL3210: 468 ret |= gpio_request(GPIO_FN_IRL3, intc_desc_irl.name); 469 ret |= gpio_request(GPIO_FN_IRL2, intc_desc_irl.name); 470 ret |= gpio_request(GPIO_FN_IRL1, intc_desc_irl.name); 471 ret |= gpio_request(GPIO_FN_IRL0, intc_desc_irl.name); 472 473 if (unlikely(ret)) { 474 pr_err("Failed to set IRL mode\n"); 475 return; 476 } 477 478 register_intc_controller(&intc_desc_irl); 479 break; 480 default: 481 BUG(); 482 } 483 } 484 485 void __init plat_irq_setup(void) 486 { 487 reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq)); 488 reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl)); 489 490 register_intc_controller(&intc_desc); 491 } 492 493 void __init plat_mem_setup(void) 494 { 495 unsigned int nid = 1; 496 497 /* Register CPU#0 URAM space as Node 1 */ 498 setup_bootmem_node(nid++, 0x145f0000, 0x14610000); /* CPU0 */ 499 500 #if 0 501 /* XXX: Not yet.. */ 502 setup_bootmem_node(nid++, 0x14df0000, 0x14e10000); /* CPU1 */ 503 setup_bootmem_node(nid++, 0x155f0000, 0x15610000); /* CPU2 */ 504 setup_bootmem_node(nid++, 0x15df0000, 0x15e10000); /* CPU3 */ 505 #endif 506 507 setup_bootmem_node(nid++, 0x16000000, 0x16020000); /* CSM */ 508 } 509