diff options
author | Boris BREZILLON <boris.brezillon@free-electrons.com> | 2015-03-12 10:54:27 -0400 |
---|---|---|
committer | Nicolas Ferre <nicolas.ferre@atmel.com> | 2015-03-13 10:11:04 -0400 |
commit | ea4abe7f3a3216f5d98dcc7a884e10f20b264429 (patch) | |
tree | 170a840a62a135fb415a3c23c9943054dc0edde8 | |
parent | 8c07f664a6c48bfc44ce9352c8c2fba55f1d108b (diff) |
ARM: at91: add soc detection infrastructure
Add new structures and functions to handle AT91 SoC detection.
[alexandre.belloni@free-electrons.com: reworked DBGU detection]
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-at91/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/soc.c | 97 | ||||
-rw-r--r-- | arch/arm/mach-at91/soc.h | 35 |
4 files changed, 134 insertions, 1 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e7ce6612bc42..f6c5b05e8de8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -363,6 +363,7 @@ config ARCH_AT91 | |||
363 | select IRQ_DOMAIN | 363 | select IRQ_DOMAIN |
364 | select PINCTRL | 364 | select PINCTRL |
365 | select PINCTRL_AT91 | 365 | select PINCTRL_AT91 |
366 | select SOC_BUS | ||
366 | select USE_OF | 367 | select USE_OF |
367 | help | 368 | help |
368 | This enables support for systems based on Atmel | 369 | This enables support for systems based on Atmel |
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 7df8c854f80f..709f059602b9 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := setup.o | 5 | obj-y := setup.o soc.o |
6 | 6 | ||
7 | obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o | 7 | obj-$(CONFIG_SOC_AT91SAM9) += sam9_smc.o |
8 | 8 | ||
diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c new file mode 100644 index 000000000000..54343ffa3e53 --- /dev/null +++ b/arch/arm/mach-at91/soc.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Atmel | ||
3 | * | ||
4 | * Alexandre Belloni <alexandre.belloni@free-electrons.com | ||
5 | * Boris Brezillon <boris.brezillon@free-electrons.com | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) "AT91: " fmt | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/sys_soc.h> | ||
21 | |||
22 | #include "soc.h" | ||
23 | |||
24 | #define AT91_DBGU_CIDR 0x40 | ||
25 | #define AT91_DBGU_CIDR_VERSION(x) ((x) & 0x1f) | ||
26 | #define AT91_DBGU_CIDR_EXT BIT(31) | ||
27 | #define AT91_DBGU_CIDR_MATCH_MASK 0x7fffffe0 | ||
28 | #define AT91_DBGU_EXID 0x44 | ||
29 | |||
30 | struct soc_device * __init at91_soc_init(const struct at91_soc *socs) | ||
31 | { | ||
32 | struct soc_device_attribute *soc_dev_attr; | ||
33 | const struct at91_soc *soc; | ||
34 | struct soc_device *soc_dev; | ||
35 | struct device_node *np; | ||
36 | void __iomem *regs; | ||
37 | u32 cidr, exid; | ||
38 | |||
39 | np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu"); | ||
40 | if (!np) | ||
41 | np = of_find_compatible_node(NULL, NULL, | ||
42 | "atmel,at91sam9260-dbgu"); | ||
43 | |||
44 | if (!np) { | ||
45 | pr_warn("Could not find DBGU node"); | ||
46 | return NULL; | ||
47 | } | ||
48 | |||
49 | regs = of_iomap(np, 0); | ||
50 | of_node_put(np); | ||
51 | |||
52 | if (!regs) { | ||
53 | pr_warn("Could not map DBGU iomem range"); | ||
54 | return NULL; | ||
55 | } | ||
56 | |||
57 | cidr = readl(regs + AT91_DBGU_CIDR); | ||
58 | exid = readl(regs + AT91_DBGU_EXID); | ||
59 | |||
60 | iounmap(regs); | ||
61 | |||
62 | for (soc = socs; soc->name; soc++) { | ||
63 | if (soc->cidr_match != (cidr & AT91_DBGU_CIDR_MATCH_MASK)) | ||
64 | continue; | ||
65 | |||
66 | if (!(cidr & AT91_DBGU_CIDR_EXT) || soc->exid_match == exid) | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | if (!soc->name) { | ||
71 | pr_warn("Could not find matching SoC description\n"); | ||
72 | return NULL; | ||
73 | } | ||
74 | |||
75 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
76 | if (!soc_dev_attr) | ||
77 | return NULL; | ||
78 | |||
79 | soc_dev_attr->family = soc->family; | ||
80 | soc_dev_attr->soc_id = soc->name; | ||
81 | soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", | ||
82 | AT91_DBGU_CIDR_VERSION(cidr)); | ||
83 | soc_dev = soc_device_register(soc_dev_attr); | ||
84 | if (IS_ERR(soc_dev)) { | ||
85 | kfree(soc_dev_attr->revision); | ||
86 | kfree(soc_dev_attr); | ||
87 | pr_warn("Could not register SoC device\n"); | ||
88 | return NULL; | ||
89 | } | ||
90 | |||
91 | if (soc->family) | ||
92 | pr_info("Detected SoC family: %s\n", soc->family); | ||
93 | pr_info("Detected SoC: %s, revision %X\n", soc->name, | ||
94 | AT91_DBGU_CIDR_VERSION(cidr)); | ||
95 | |||
96 | return soc_dev; | ||
97 | } | ||
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h new file mode 100644 index 000000000000..9678a3b2d282 --- /dev/null +++ b/arch/arm/mach-at91/soc.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Atmel | ||
3 | * | ||
4 | * Boris Brezillon <boris.brezillon@free-electrons.com | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef __AT91_SOC_H | ||
13 | #define __AT91_SOC_H | ||
14 | |||
15 | #include <linux/sys_soc.h> | ||
16 | |||
17 | struct at91_soc { | ||
18 | u32 cidr_match; | ||
19 | u32 exid_match; | ||
20 | const char *name; | ||
21 | const char *family; | ||
22 | }; | ||
23 | |||
24 | #define AT91_SOC(__cidr, __exid, __name, __family) \ | ||
25 | { \ | ||
26 | .cidr_match = (__cidr), \ | ||
27 | .exid_match = (__exid), \ | ||
28 | .name = (__name), \ | ||
29 | .family = (__family), \ | ||
30 | } | ||
31 | |||
32 | struct soc_device * __init | ||
33 | at91_soc_init(const struct at91_soc *socs); | ||
34 | |||
35 | #endif /* __AT91_SOC_H */ | ||