diff options
author | Fabio Estevam <fabio.estevam@freescale.com> | 2013-06-04 09:18:45 -0400 |
---|---|---|
committer | Shawn Guo <shawn.guo@linaro.org> | 2013-06-17 03:41:48 -0400 |
commit | 2046338dcbc60404ede8f034a13f02548ac70054 (patch) | |
tree | 7941058c783ee26955af656a6d5d54b36d870d14 | |
parent | 115581cfc9dc868b5f2c230d0236976276bc9dbb (diff) |
ARM: mxs: Use soc bus infrastructure
Using the soc bus infrastructure is helpful for reporting several SoC related
information such as: family, machine, SoC name and SoC revision.
$ cat /sys/bus/soc/devices/soc0/family
Freescale MXS Family
$ cat /sys/bus/soc/devices/soc0/machine
Freescale i.MX28 Evaluation Kit
$ cat /sys/bus/soc/devices/soc0/soc_id
i.MX28
$ cat /sys/bus/soc/devices/soc0/revision
TO1.2
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
-rw-r--r-- | arch/arm/mach-mxs/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-mxs/mach-mxs.c | 117 |
2 files changed, 117 insertions, 1 deletions
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index 4dc2fbba0ecd..59c30ef56790 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig | |||
@@ -25,6 +25,7 @@ config ARCH_MXS | |||
25 | select GENERIC_CLOCKEVENTS | 25 | select GENERIC_CLOCKEVENTS |
26 | select HAVE_CLK_PREPARE | 26 | select HAVE_CLK_PREPARE |
27 | select PINCTRL | 27 | select PINCTRL |
28 | select SOC_BUS | ||
28 | select SOC_IMX23 | 29 | select SOC_IMX23 |
29 | select SOC_IMX28 | 30 | select SOC_IMX28 |
30 | select STMP_DEVICE | 31 | select STMP_DEVICE |
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 66fe810aa631..f0bf6076fa32 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
26 | #include <linux/phy.h> | 26 | #include <linux/phy.h> |
27 | #include <linux/pinctrl/consumer.h> | 27 | #include <linux/pinctrl/consumer.h> |
28 | #include <linux/sys_soc.h> | ||
28 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
29 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
30 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
@@ -38,12 +39,28 @@ | |||
38 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 | 39 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 |
39 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 | 40 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 |
40 | 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 | |||
41 | #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) | 55 | #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) |
42 | 56 | ||
43 | #define MXS_SET_ADDR 0x4 | 57 | #define MXS_SET_ADDR 0x4 |
44 | #define MXS_CLR_ADDR 0x8 | 58 | #define MXS_CLR_ADDR 0x8 |
45 | #define MXS_TOG_ADDR 0xc | 59 | #define MXS_TOG_ADDR 0xc |
46 | 60 | ||
61 | static u32 chipid; | ||
62 | static u32 socid; | ||
63 | |||
47 | static inline void __mxs_setl(u32 mask, void __iomem *reg) | 64 | static inline void __mxs_setl(u32 mask, void __iomem *reg) |
48 | { | 65 | { |
49 | __raw_writel(mask, reg + MXS_SET_ADDR); | 66 | __raw_writel(mask, reg + MXS_SET_ADDR); |
@@ -361,8 +378,106 @@ static void __init cfa10037_init(void) | |||
361 | update_fec_mac_prop(OUI_CRYSTALFONTZ); | 378 | update_fec_mac_prop(OUI_CRYSTALFONTZ); |
362 | } | 379 | } |
363 | 380 | ||
381 | static const char __init *mxs_get_soc_id(void) | ||
382 | { | ||
383 | struct device_node *np; | ||
384 | void __iomem *digctl_base; | ||
385 | |||
386 | np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl"); | ||
387 | digctl_base = of_iomap(np, 0); | ||
388 | WARN_ON(!digctl_base); | ||
389 | |||
390 | chipid = readl(digctl_base + HW_DIGCTL_CHIPID); | ||
391 | socid = chipid & HW_DIGCTL_CHIPID_MASK; | ||
392 | |||
393 | iounmap(digctl_base); | ||
394 | of_node_put(np); | ||
395 | |||
396 | switch (socid) { | ||
397 | case HW_DIGCTL_CHIPID_MX23: | ||
398 | return "i.MX23"; | ||
399 | case HW_DIGCTL_CHIPID_MX28: | ||
400 | return "i.MX28"; | ||
401 | default: | ||
402 | return "Unknown"; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | static u32 __init mxs_get_cpu_rev(void) | ||
407 | { | ||
408 | u32 rev = chipid & HW_DIGCTL_REV_MASK; | ||
409 | |||
410 | switch (socid) { | ||
411 | case HW_DIGCTL_CHIPID_MX23: | ||
412 | switch (rev) { | ||
413 | case 0x0: | ||
414 | return MXS_CHIP_REVISION_1_0; | ||
415 | case 0x1: | ||
416 | return MXS_CHIP_REVISION_1_1; | ||
417 | case 0x2: | ||
418 | return MXS_CHIP_REVISION_1_2; | ||
419 | case 0x3: | ||
420 | return MXS_CHIP_REVISION_1_3; | ||
421 | case 0x4: | ||
422 | return MXS_CHIP_REVISION_1_4; | ||
423 | default: | ||
424 | return MXS_CHIP_REV_UNKNOWN; | ||
425 | } | ||
426 | case HW_DIGCTL_CHIPID_MX28: | ||
427 | switch (rev) { | ||
428 | case 0x0: | ||
429 | return MXS_CHIP_REVISION_1_1; | ||
430 | case 0x1: | ||
431 | return MXS_CHIP_REVISION_1_2; | ||
432 | default: | ||
433 | return MXS_CHIP_REV_UNKNOWN; | ||
434 | } | ||
435 | default: | ||
436 | return MXS_CHIP_REV_UNKNOWN; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | static const char __init *mxs_get_revision(void) | ||
441 | { | ||
442 | u32 rev = mxs_get_cpu_rev(); | ||
443 | |||
444 | if (rev != MXS_CHIP_REV_UNKNOWN) | ||
445 | return kasprintf(GFP_KERNEL, "TO%d.%d", (rev >> 4) & 0xf, | ||
446 | rev & 0xf); | ||
447 | else | ||
448 | return kasprintf(GFP_KERNEL, "%s", "Unknown"); | ||
449 | } | ||
450 | |||
364 | static void __init mxs_machine_init(void) | 451 | static void __init mxs_machine_init(void) |
365 | { | 452 | { |
453 | struct device_node *root; | ||
454 | struct device *parent; | ||
455 | struct soc_device *soc_dev; | ||
456 | struct soc_device_attribute *soc_dev_attr; | ||
457 | int ret; | ||
458 | |||
459 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
460 | if (!soc_dev_attr) | ||
461 | return; | ||
462 | |||
463 | root = of_find_node_by_path("/"); | ||
464 | ret = of_property_read_string(root, "model", &soc_dev_attr->machine); | ||
465 | if (ret) | ||
466 | return; | ||
467 | |||
468 | soc_dev_attr->family = "Freescale MXS Family"; | ||
469 | soc_dev_attr->soc_id = mxs_get_soc_id(); | ||
470 | soc_dev_attr->revision = mxs_get_revision(); | ||
471 | |||
472 | soc_dev = soc_device_register(soc_dev_attr); | ||
473 | if (IS_ERR(soc_dev)) { | ||
474 | kfree(soc_dev_attr->revision); | ||
475 | kfree(soc_dev_attr); | ||
476 | return; | ||
477 | } | ||
478 | |||
479 | parent = soc_device_to_device(soc_dev); | ||
480 | |||
366 | if (of_machine_is_compatible("fsl,imx28-evk")) | 481 | if (of_machine_is_compatible("fsl,imx28-evk")) |
367 | imx28_evk_init(); | 482 | imx28_evk_init(); |
368 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) | 483 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) |
@@ -373,7 +488,7 @@ static void __init mxs_machine_init(void) | |||
373 | cfa10049_init(); | 488 | cfa10049_init(); |
374 | 489 | ||
375 | of_platform_populate(NULL, of_default_bus_match_table, | 490 | of_platform_populate(NULL, of_default_bus_match_table, |
376 | mxs_auxdata_lookup, NULL); | 491 | mxs_auxdata_lookup, parent); |
377 | 492 | ||
378 | if (of_machine_is_compatible("karo,tx28")) | 493 | if (of_machine_is_compatible("karo,tx28")) |
379 | tx28_post_init(); | 494 | tx28_post_init(); |