diff options
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r-- | arch/arm/mach-mxs/mach-mxs.c | 130 |
1 files changed, 119 insertions, 11 deletions
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 5b62b6489d4b..7fa611c1b287 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c | |||
@@ -19,13 +19,13 @@ | |||
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/irqchip.h> | ||
23 | #include <linux/irqchip/mxs.h> | 22 | #include <linux/irqchip/mxs.h> |
24 | #include <linux/micrel_phy.h> | 23 | #include <linux/micrel_phy.h> |
25 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
26 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
27 | #include <linux/phy.h> | 26 | #include <linux/phy.h> |
28 | #include <linux/pinctrl/consumer.h> | 27 | #include <linux/pinctrl/consumer.h> |
28 | #include <linux/sys_soc.h> | ||
29 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
30 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
31 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
@@ -39,12 +39,28 @@ | |||
39 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 | 39 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 |
40 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 | 40 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 |
41 | 41 | ||
42 | #define HW_DIGCTL_CHIPID 0x310 | ||
43 | #define HW_DIGCTL_CHIPID_MASK (0xffff << 16) | ||
44 | #define HW_DIGCTL_REV_MASK 0xff | ||
45 | #define HW_DIGCTL_CHIPID_MX23 (0x3780 << 16) | ||
46 | #define HW_DIGCTL_CHIPID_MX28 (0x2800 << 16) | ||
47 | |||
48 | #define MXS_CHIP_REVISION_1_0 0x10 | ||
49 | #define MXS_CHIP_REVISION_1_1 0x11 | ||
50 | #define MXS_CHIP_REVISION_1_2 0x12 | ||
51 | #define MXS_CHIP_REVISION_1_3 0x13 | ||
52 | #define MXS_CHIP_REVISION_1_4 0x14 | ||
53 | #define MXS_CHIP_REV_UNKNOWN 0xff | ||
54 | |||
42 | #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) | 55 | #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) |
43 | 56 | ||
44 | #define MXS_SET_ADDR 0x4 | 57 | #define MXS_SET_ADDR 0x4 |
45 | #define MXS_CLR_ADDR 0x8 | 58 | #define MXS_CLR_ADDR 0x8 |
46 | #define MXS_TOG_ADDR 0xc | 59 | #define MXS_TOG_ADDR 0xc |
47 | 60 | ||
61 | static u32 chipid; | ||
62 | static u32 socid; | ||
63 | |||
48 | static inline void __mxs_setl(u32 mask, void __iomem *reg) | 64 | static inline void __mxs_setl(u32 mask, void __iomem *reg) |
49 | { | 65 | { |
50 | __raw_writel(mask, reg + MXS_SET_ADDR); | 66 | __raw_writel(mask, reg + MXS_SET_ADDR); |
@@ -352,29 +368,123 @@ static void __init tx28_post_init(void) | |||
352 | pinctrl_put(pctl); | 368 | pinctrl_put(pctl); |
353 | } | 369 | } |
354 | 370 | ||
355 | static void __init cfa10049_init(void) | 371 | static void __init crystalfontz_init(void) |
356 | { | 372 | { |
357 | update_fec_mac_prop(OUI_CRYSTALFONTZ); | 373 | update_fec_mac_prop(OUI_CRYSTALFONTZ); |
358 | } | 374 | } |
359 | 375 | ||
360 | static void __init cfa10037_init(void) | 376 | static const char __init *mxs_get_soc_id(void) |
361 | { | 377 | { |
362 | update_fec_mac_prop(OUI_CRYSTALFONTZ); | 378 | struct device_node *np; |
379 | void __iomem *digctl_base; | ||
380 | |||
381 | np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl"); | ||
382 | digctl_base = of_iomap(np, 0); | ||
383 | WARN_ON(!digctl_base); | ||
384 | |||
385 | chipid = readl(digctl_base + HW_DIGCTL_CHIPID); | ||
386 | socid = chipid & HW_DIGCTL_CHIPID_MASK; | ||
387 | |||
388 | iounmap(digctl_base); | ||
389 | of_node_put(np); | ||
390 | |||
391 | switch (socid) { | ||
392 | case HW_DIGCTL_CHIPID_MX23: | ||
393 | return "i.MX23"; | ||
394 | case HW_DIGCTL_CHIPID_MX28: | ||
395 | return "i.MX28"; | ||
396 | default: | ||
397 | return "Unknown"; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | static u32 __init mxs_get_cpu_rev(void) | ||
402 | { | ||
403 | u32 rev = chipid & HW_DIGCTL_REV_MASK; | ||
404 | |||
405 | switch (socid) { | ||
406 | case HW_DIGCTL_CHIPID_MX23: | ||
407 | switch (rev) { | ||
408 | case 0x0: | ||
409 | return MXS_CHIP_REVISION_1_0; | ||
410 | case 0x1: | ||
411 | return MXS_CHIP_REVISION_1_1; | ||
412 | case 0x2: | ||
413 | return MXS_CHIP_REVISION_1_2; | ||
414 | case 0x3: | ||
415 | return MXS_CHIP_REVISION_1_3; | ||
416 | case 0x4: | ||
417 | return MXS_CHIP_REVISION_1_4; | ||
418 | default: | ||
419 | return MXS_CHIP_REV_UNKNOWN; | ||
420 | } | ||
421 | case HW_DIGCTL_CHIPID_MX28: | ||
422 | switch (rev) { | ||
423 | case 0x0: | ||
424 | return MXS_CHIP_REVISION_1_1; | ||
425 | case 0x1: | ||
426 | return MXS_CHIP_REVISION_1_2; | ||
427 | default: | ||
428 | return MXS_CHIP_REV_UNKNOWN; | ||
429 | } | ||
430 | default: | ||
431 | return MXS_CHIP_REV_UNKNOWN; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | static const char __init *mxs_get_revision(void) | ||
436 | { | ||
437 | u32 rev = mxs_get_cpu_rev(); | ||
438 | |||
439 | if (rev != MXS_CHIP_REV_UNKNOWN) | ||
440 | return kasprintf(GFP_KERNEL, "TO%d.%d", (rev >> 4) & 0xf, | ||
441 | rev & 0xf); | ||
442 | else | ||
443 | return kasprintf(GFP_KERNEL, "%s", "Unknown"); | ||
363 | } | 444 | } |
364 | 445 | ||
365 | static void __init mxs_machine_init(void) | 446 | static void __init mxs_machine_init(void) |
366 | { | 447 | { |
448 | struct device_node *root; | ||
449 | struct device *parent; | ||
450 | struct soc_device *soc_dev; | ||
451 | struct soc_device_attribute *soc_dev_attr; | ||
452 | int ret; | ||
453 | |||
454 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
455 | if (!soc_dev_attr) | ||
456 | return; | ||
457 | |||
458 | root = of_find_node_by_path("/"); | ||
459 | ret = of_property_read_string(root, "model", &soc_dev_attr->machine); | ||
460 | if (ret) | ||
461 | return; | ||
462 | |||
463 | soc_dev_attr->family = "Freescale MXS Family"; | ||
464 | soc_dev_attr->soc_id = mxs_get_soc_id(); | ||
465 | soc_dev_attr->revision = mxs_get_revision(); | ||
466 | |||
467 | soc_dev = soc_device_register(soc_dev_attr); | ||
468 | if (IS_ERR(soc_dev)) { | ||
469 | kfree(soc_dev_attr->revision); | ||
470 | kfree(soc_dev_attr); | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | parent = soc_device_to_device(soc_dev); | ||
475 | |||
367 | if (of_machine_is_compatible("fsl,imx28-evk")) | 476 | if (of_machine_is_compatible("fsl,imx28-evk")) |
368 | imx28_evk_init(); | 477 | imx28_evk_init(); |
369 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) | 478 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) |
370 | apx4devkit_init(); | 479 | apx4devkit_init(); |
371 | else if (of_machine_is_compatible("crystalfontz,cfa10037")) | 480 | else if (of_machine_is_compatible("crystalfontz,cfa10037") || |
372 | cfa10037_init(); | 481 | of_machine_is_compatible("crystalfontz,cfa10049") || |
373 | else if (of_machine_is_compatible("crystalfontz,cfa10049")) | 482 | of_machine_is_compatible("crystalfontz,cfa10055") || |
374 | cfa10049_init(); | 483 | of_machine_is_compatible("crystalfontz,cfa10057")) |
484 | crystalfontz_init(); | ||
375 | 485 | ||
376 | of_platform_populate(NULL, of_default_bus_match_table, | 486 | of_platform_populate(NULL, of_default_bus_match_table, |
377 | mxs_auxdata_lookup, NULL); | 487 | mxs_auxdata_lookup, parent); |
378 | 488 | ||
379 | if (of_machine_is_compatible("karo,tx28")) | 489 | if (of_machine_is_compatible("karo,tx28")) |
380 | tx28_post_init(); | 490 | tx28_post_init(); |
@@ -434,8 +544,6 @@ static const char *mxs_dt_compat[] __initdata = { | |||
434 | }; | 544 | }; |
435 | 545 | ||
436 | DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") | 546 | DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") |
437 | .map_io = debug_ll_io_init, | ||
438 | .init_irq = irqchip_init, | ||
439 | .handle_irq = icoll_handle_irq, | 547 | .handle_irq = icoll_handle_irq, |
440 | .init_time = mxs_timer_init, | 548 | .init_time = mxs_timer_init, |
441 | .init_machine = mxs_machine_init, | 549 | .init_machine = mxs_machine_init, |