[PATCH] ARM: at91: move SoC detection to its own driver

Nicolas Ferre nicolas.ferre at atmel.com
Thu Feb 16 02:43:04 PST 2017


Le 16/02/2017 à 11:31, Alexandre Belloni a écrit :
> To simplify machine init and as the soc_device struct is not used as the
> parent for on-chip devices anymore, move SoC detection to its own driver.
> 
> Change in dmesg:
>  - before:
> DMA: preallocated 256 KiB pool for atomic coherent allocations
> AT91: Detected SoC family: sama5d2
> AT91: Detected SoC: sama5d27, revision 0
> No ATAGs?
> clocksource: tcb_clksrc: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 184217874325 ns
> at_xdmac f0010000.dma-controller: 16 channels, mapped at 0xe085b000
> SCSI subsystem initialized
> 
>  - after:
> DMA: preallocated 256 KiB pool for atomic coherent allocations
> No ATAGs?
> clocksource: tcb_clksrc: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 184217874325 ns
> at_xdmac f0010000.dma-controller: 16 channels, mapped at 0xe0859000
> AT91: Detected SoC family: sama5d2
> AT91: Detected SoC: sama5d27, revision 0
> SCSI subsystem initialized
> 
> Suggested-by: Arnd Bergmann <arnd at arndb.de>
> Signed-off-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>

ok:
Acked-by: Nicolas Ferre <nicolas.ferre at microchip.com>

> ---
>  arch/arm/mach-at91/Makefile                     |   1 -
>  arch/arm/mach-at91/at91rm9200.c                 |  15 +-
>  arch/arm/mach-at91/at91sam9.c                   |  46 +----
>  arch/arm/mach-at91/sama5.c                      |  52 +-----
>  arch/arm/mach-at91/soc.c                        | 142 ---------------
>  drivers/soc/Kconfig                             |   1 +
>  drivers/soc/Makefile                            |   1 +
>  drivers/soc/atmel/Kconfig                       |   6 +
>  drivers/soc/atmel/Makefile                      |   1 +
>  drivers/soc/atmel/soc.c                         | 231 ++++++++++++++++++++++++
>  {arch/arm/mach-at91 => drivers/soc/atmel}/soc.h |   0
>  11 files changed, 243 insertions(+), 253 deletions(-)
>  delete mode 100644 arch/arm/mach-at91/soc.c
>  create mode 100644 drivers/soc/atmel/Kconfig
>  create mode 100644 drivers/soc/atmel/Makefile
>  create mode 100644 drivers/soc/atmel/soc.c
>  rename {arch/arm/mach-at91 => drivers/soc/atmel}/soc.h (100%)
> 
> diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
> index c5bbf8bb8c0f..ae913484712e 100644
> --- a/arch/arm/mach-at91/Makefile
> +++ b/arch/arm/mach-at91/Makefile
> @@ -1,7 +1,6 @@
>  #
>  # Makefile for the linux kernel.
>  #
> -obj-y		:= soc.o
>  
>  # CPU-specific support
>  obj-$(CONFIG_SOC_AT91RM9200)	+= at91rm9200.o
> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
> index d068ec3cd1f6..656ad409a253 100644
> --- a/arch/arm/mach-at91/at91rm9200.c
> +++ b/arch/arm/mach-at91/at91rm9200.c
> @@ -14,23 +14,10 @@
>  #include <asm/mach/arch.h>
>  
>  #include "generic.h"
> -#include "soc.h"
> -
> -static const struct at91_soc rm9200_socs[] = {
> -	AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"),
> -	{ /* sentinel */ },
> -};
>  
>  static void __init at91rm9200_dt_device_init(void)
>  {
> -	struct soc_device *soc;
> -	struct device *soc_dev = NULL;
> -
> -	soc = at91_soc_init(rm9200_socs);
> -	if (soc != NULL)
> -		soc_dev = soc_device_to_device(soc);
> -
> -	of_platform_default_populate(NULL, NULL, soc_dev);
> +	of_platform_default_populate(NULL, NULL, NULL);
>  
>  	at91rm9200_pm_init();
>  }
> diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c
> index ba28e9cc584d..b5280d42dece 100644
> --- a/arch/arm/mach-at91/at91sam9.c
> +++ b/arch/arm/mach-at91/at91sam9.c
> @@ -14,54 +14,10 @@
>  #include <asm/system_misc.h>
>  
>  #include "generic.h"
> -#include "soc.h"
> -
> -static const struct at91_soc at91sam9_socs[] = {
> -	AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL),
> -	AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL),
> -	AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL),
> -	AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL),
> -	AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL),
> -	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH,
> -		 "at91sam9m11", "at91sam9g45"),
> -	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH,
> -		 "at91sam9m10", "at91sam9g45"),
> -	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH,
> -		 "at91sam9g46", "at91sam9g45"),
> -	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH,
> -		 "at91sam9g45", "at91sam9g45"),
> -	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH,
> -		 "at91sam9g15", "at91sam9x5"),
> -	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH,
> -		 "at91sam9g35", "at91sam9x5"),
> -	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH,
> -		 "at91sam9x35", "at91sam9x5"),
> -	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH,
> -		 "at91sam9g25", "at91sam9x5"),
> -	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH,
> -		 "at91sam9x25", "at91sam9x5"),
> -	AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH,
> -		 "at91sam9cn12", "at91sam9n12"),
> -	AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH,
> -		 "at91sam9n12", "at91sam9n12"),
> -	AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH,
> -		 "at91sam9cn11", "at91sam9n12"),
> -	AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
> -	AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
> -	AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
> -	{ /* sentinel */ },
> -};
>  
>  static void __init at91sam9_common_init(void)
>  {
> -	struct soc_device *soc;
> -	struct device *soc_dev = NULL;
> -
> -	soc = at91_soc_init(at91sam9_socs);
> -	if (soc != NULL)
> -		soc_dev = soc_device_to_device(soc);
> -
> -	of_platform_default_populate(NULL, NULL, soc_dev);
> +	of_platform_default_populate(NULL, NULL, NULL);
>  }
>  
>  static void __init at91sam9_dt_device_init(void)
> diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c
> index b272c45b400f..6d157d0ead8e 100644
> --- a/arch/arm/mach-at91/sama5.c
> +++ b/arch/arm/mach-at91/sama5.c
> @@ -15,60 +15,10 @@
>  #include <asm/system_misc.h>
>  
>  #include "generic.h"
> -#include "soc.h"
> -
> -static const struct at91_soc sama5_socs[] = {
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
> -		 "sama5d21", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH,
> -		 "sama5d22", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH,
> -		 "sama5d23", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH,
> -		 "sama5d24", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH,
> -		 "sama5d24", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH,
> -		 "sama5d26", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH,
> -		 "sama5d27", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH,
> -		 "sama5d27", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
> -		 "sama5d28", "sama5d2"),
> -	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
> -		 "sama5d28", "sama5d2"),
> -	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
> -		 "sama5d31", "sama5d3"),
> -	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
> -		 "sama5d33", "sama5d3"),
> -	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH,
> -		 "sama5d34", "sama5d3"),
> -	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH,
> -		 "sama5d35", "sama5d3"),
> -	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH,
> -		 "sama5d36", "sama5d3"),
> -	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH,
> -		 "sama5d41", "sama5d4"),
> -	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH,
> -		 "sama5d42", "sama5d4"),
> -	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH,
> -		 "sama5d43", "sama5d4"),
> -	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
> -		 "sama5d44", "sama5d4"),
> -	{ /* sentinel */ },
> -};
>  
>  static void __init sama5_dt_device_init(void)
>  {
> -	struct soc_device *soc;
> -	struct device *soc_dev = NULL;
> -
> -	soc = at91_soc_init(sama5_socs);
> -	if (soc != NULL)
> -		soc_dev = soc_device_to_device(soc);
> -
> -	of_platform_default_populate(NULL, NULL, soc_dev);
> +	of_platform_default_populate(NULL, NULL, NULL);
>  	sama5_pm_init();
>  }
>  
> diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c
> deleted file mode 100644
> index c6fda75ddb89..000000000000
> --- a/arch/arm/mach-at91/soc.c
> +++ /dev/null
> @@ -1,142 +0,0 @@
> -/*
> - * Copyright (C) 2015 Atmel
> - *
> - * Alexandre Belloni <alexandre.belloni at free-electrons.com
> - * Boris Brezillon <boris.brezillon at free-electrons.com
> - *
> - * This file is licensed under the terms of the GNU General Public
> - * License version 2.  This program is licensed "as is" without any
> - * warranty of any kind, whether express or implied.
> - *
> - */
> -
> -#define pr_fmt(fmt)	"AT91: " fmt
> -
> -#include <linux/io.h>
> -#include <linux/of.h>
> -#include <linux/of_address.h>
> -#include <linux/of_platform.h>
> -#include <linux/slab.h>
> -#include <linux/sys_soc.h>
> -
> -#include "soc.h"
> -
> -#define AT91_DBGU_CIDR			0x40
> -#define AT91_DBGU_EXID			0x44
> -#define AT91_CHIPID_CIDR		0x00
> -#define AT91_CHIPID_EXID		0x04
> -#define AT91_CIDR_VERSION(x)		((x) & 0x1f)
> -#define AT91_CIDR_EXT			BIT(31)
> -#define AT91_CIDR_MATCH_MASK		0x7fffffe0
> -
> -static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid)
> -{
> -	struct device_node *np;
> -	void __iomem *regs;
> -
> -	np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu");
> -	if (!np)
> -		np = of_find_compatible_node(NULL, NULL,
> -					     "atmel,at91sam9260-dbgu");
> -	if (!np)
> -		return -ENODEV;
> -
> -	regs = of_iomap(np, 0);
> -	of_node_put(np);
> -
> -	if (!regs) {
> -		pr_warn("Could not map DBGU iomem range");
> -		return -ENXIO;
> -	}
> -
> -	*cidr = readl(regs + AT91_DBGU_CIDR);
> -	*exid = readl(regs + AT91_DBGU_EXID);
> -
> -	iounmap(regs);
> -
> -	return 0;
> -}
> -
> -static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
> -{
> -	struct device_node *np;
> -	void __iomem *regs;
> -
> -	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid");
> -	if (!np)
> -		return -ENODEV;
> -
> -	regs = of_iomap(np, 0);
> -	of_node_put(np);
> -
> -	if (!regs) {
> -		pr_warn("Could not map DBGU iomem range");
> -		return -ENXIO;
> -	}
> -
> -	*cidr = readl(regs + AT91_CHIPID_CIDR);
> -	*exid = readl(regs + AT91_CHIPID_EXID);
> -
> -	iounmap(regs);
> -
> -	return 0;
> -}
> -
> -struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
> -{
> -	struct soc_device_attribute *soc_dev_attr;
> -	const struct at91_soc *soc;
> -	struct soc_device *soc_dev;
> -	u32 cidr, exid;
> -	int ret;
> -
> -	/*
> -	 * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more
> -	 * in the dbgu device but in the chipid device whose purpose is only
> -	 * to expose these two registers.
> -	 */
> -	ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid);
> -	if (ret)
> -		ret = at91_get_cidr_exid_from_chipid(&cidr, &exid);
> -	if (ret) {
> -		if (ret == -ENODEV)
> -			pr_warn("Could not find identification node");
> -		return NULL;
> -	}
> -
> -	for (soc = socs; soc->name; soc++) {
> -		if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK))
> -			continue;
> -
> -		if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid)
> -			break;
> -	}
> -
> -	if (!soc->name) {
> -		pr_warn("Could not find matching SoC description\n");
> -		return NULL;
> -	}
> -
> -	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
> -	if (!soc_dev_attr)
> -		return NULL;
> -
> -	soc_dev_attr->family = soc->family;
> -	soc_dev_attr->soc_id = soc->name;
> -	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
> -					   AT91_CIDR_VERSION(cidr));
> -	soc_dev = soc_device_register(soc_dev_attr);
> -	if (IS_ERR(soc_dev)) {
> -		kfree(soc_dev_attr->revision);
> -		kfree(soc_dev_attr);
> -		pr_warn("Could not register SoC device\n");
> -		return NULL;
> -	}
> -
> -	if (soc->family)
> -		pr_info("Detected SoC family: %s\n", soc->family);
> -	pr_info("Detected SoC: %s, revision %X\n", soc->name,
> -		AT91_CIDR_VERSION(cidr));
> -
> -	return soc_dev;
> -}
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index e6e90e80519a..d7728ad4574f 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -1,5 +1,6 @@
>  menu "SOC (System On Chip) specific Drivers"
>  
> +source "drivers/soc/atmel/Kconfig"
>  source "drivers/soc/bcm/Kconfig"
>  source "drivers/soc/fsl/qbman/Kconfig"
>  source "drivers/soc/fsl/qe/Kconfig"
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 50c23d0bd457..aca402073e7e 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -2,6 +2,7 @@
>  # Makefile for the Linux Kernel SOC specific device drivers.
>  #
>  
> +obj-$(CONFIG_ARCH_AT91)		+= atmel/
>  obj-y				+= bcm/
>  obj-$(CONFIG_ARCH_DOVE)		+= dove/
>  obj-$(CONFIG_MACH_DOVE)		+= dove/
> diff --git a/drivers/soc/atmel/Kconfig b/drivers/soc/atmel/Kconfig
> new file mode 100644
> index 000000000000..6242ebb41abb
> --- /dev/null
> +++ b/drivers/soc/atmel/Kconfig
> @@ -0,0 +1,6 @@
> +config AT91_SOC_ID
> +	bool "SoC bus for Atmel ARM SoCs"
> +	depends on ARCH_AT91 || COMPILE_TEST
> +	default ARCH_AT91
> +	help
> +	  Include support for the SoC bus on the Atmel ARM SoCs.
> diff --git a/drivers/soc/atmel/Makefile b/drivers/soc/atmel/Makefile
> new file mode 100644
> index 000000000000..2d92f32e4ea5
> --- /dev/null
> +++ b/drivers/soc/atmel/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_AT91_SOC_ID) += soc.o
> diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c
> new file mode 100644
> index 000000000000..4790094b498e
> --- /dev/null
> +++ b/drivers/soc/atmel/soc.c
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright (C) 2015 Atmel
> + *
> + * Alexandre Belloni <alexandre.belloni at free-electrons.com
> + * Boris Brezillon <boris.brezillon at free-electrons.com
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + *
> + */
> +
> +#define pr_fmt(fmt)	"AT91: " fmt
> +
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +#include <linux/sys_soc.h>
> +
> +#include "soc.h"
> +
> +#define AT91_DBGU_CIDR			0x40
> +#define AT91_DBGU_EXID			0x44
> +#define AT91_CHIPID_CIDR		0x00
> +#define AT91_CHIPID_EXID		0x04
> +#define AT91_CIDR_VERSION(x)		((x) & 0x1f)
> +#define AT91_CIDR_EXT			BIT(31)
> +#define AT91_CIDR_MATCH_MASK		0x7fffffe0
> +
> +static const struct at91_soc __initconst socs[] = {
> +#ifdef CONFIG_SOC_AT91RM9200
> +	AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"),
> +#endif
> +#ifdef CONFIG_SOC_AT91SAM9
> +	AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL),
> +	AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL),
> +	AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL),
> +	AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL),
> +	AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL),
> +	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH,
> +		 "at91sam9m11", "at91sam9g45"),
> +	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH,
> +		 "at91sam9m10", "at91sam9g45"),
> +	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH,
> +		 "at91sam9g46", "at91sam9g45"),
> +	AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH,
> +		 "at91sam9g45", "at91sam9g45"),
> +	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH,
> +		 "at91sam9g15", "at91sam9x5"),
> +	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH,
> +		 "at91sam9g35", "at91sam9x5"),
> +	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH,
> +		 "at91sam9x35", "at91sam9x5"),
> +	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH,
> +		 "at91sam9g25", "at91sam9x5"),
> +	AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH,
> +		 "at91sam9x25", "at91sam9x5"),
> +	AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH,
> +		 "at91sam9cn12", "at91sam9n12"),
> +	AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH,
> +		 "at91sam9n12", "at91sam9n12"),
> +	AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH,
> +		 "at91sam9cn11", "at91sam9n12"),
> +	AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
> +	AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
> +	AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
> +#endif
> +#ifdef CONFIG_SOC_SAMA5
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
> +		 "sama5d21", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH,
> +		 "sama5d22", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH,
> +		 "sama5d23", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH,
> +		 "sama5d24", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH,
> +		 "sama5d24", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH,
> +		 "sama5d26", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH,
> +		 "sama5d27", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH,
> +		 "sama5d27", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
> +		 "sama5d28", "sama5d2"),
> +	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
> +		 "sama5d28", "sama5d2"),
> +	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
> +		 "sama5d31", "sama5d3"),
> +	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
> +		 "sama5d33", "sama5d3"),
> +	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH,
> +		 "sama5d34", "sama5d3"),
> +	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH,
> +		 "sama5d35", "sama5d3"),
> +	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH,
> +		 "sama5d36", "sama5d3"),
> +	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH,
> +		 "sama5d41", "sama5d4"),
> +	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH,
> +		 "sama5d42", "sama5d4"),
> +	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH,
> +		 "sama5d43", "sama5d4"),
> +	AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
> +		 "sama5d44", "sama5d4"),
> +#endif
> +	{ /* sentinel */ },
> +};
> +
> +static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid)
> +{
> +	struct device_node *np;
> +	void __iomem *regs;
> +
> +	np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu");
> +	if (!np)
> +		np = of_find_compatible_node(NULL, NULL,
> +					     "atmel,at91sam9260-dbgu");
> +	if (!np)
> +		return -ENODEV;
> +
> +	regs = of_iomap(np, 0);
> +	of_node_put(np);
> +
> +	if (!regs) {
> +		pr_warn("Could not map DBGU iomem range");
> +		return -ENXIO;
> +	}
> +
> +	*cidr = readl(regs + AT91_DBGU_CIDR);
> +	*exid = readl(regs + AT91_DBGU_EXID);
> +
> +	iounmap(regs);
> +
> +	return 0;
> +}
> +
> +static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
> +{
> +	struct device_node *np;
> +	void __iomem *regs;
> +
> +	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid");
> +	if (!np)
> +		return -ENODEV;
> +
> +	regs = of_iomap(np, 0);
> +	of_node_put(np);
> +
> +	if (!regs) {
> +		pr_warn("Could not map DBGU iomem range");
> +		return -ENXIO;
> +	}
> +
> +	*cidr = readl(regs + AT91_CHIPID_CIDR);
> +	*exid = readl(regs + AT91_CHIPID_EXID);
> +
> +	iounmap(regs);
> +
> +	return 0;
> +}
> +
> +struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
> +{
> +	struct soc_device_attribute *soc_dev_attr;
> +	const struct at91_soc *soc;
> +	struct soc_device *soc_dev;
> +	u32 cidr, exid;
> +	int ret;
> +
> +	/*
> +	 * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more
> +	 * in the dbgu device but in the chipid device whose purpose is only
> +	 * to expose these two registers.
> +	 */
> +	ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid);
> +	if (ret)
> +		ret = at91_get_cidr_exid_from_chipid(&cidr, &exid);
> +	if (ret) {
> +		if (ret == -ENODEV)
> +			pr_warn("Could not find identification node");
> +		return NULL;
> +	}
> +
> +	for (soc = socs; soc->name; soc++) {
> +		if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK))
> +			continue;
> +
> +		if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid)
> +			break;
> +	}
> +
> +	if (!soc->name) {
> +		pr_warn("Could not find matching SoC description\n");
> +		return NULL;
> +	}
> +
> +	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
> +	if (!soc_dev_attr)
> +		return NULL;
> +
> +	soc_dev_attr->family = soc->family;
> +	soc_dev_attr->soc_id = soc->name;
> +	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
> +					   AT91_CIDR_VERSION(cidr));
> +	soc_dev = soc_device_register(soc_dev_attr);
> +	if (IS_ERR(soc_dev)) {
> +		kfree(soc_dev_attr->revision);
> +		kfree(soc_dev_attr);
> +		pr_warn("Could not register SoC device\n");
> +		return NULL;
> +	}
> +
> +	if (soc->family)
> +		pr_info("Detected SoC family: %s\n", soc->family);
> +	pr_info("Detected SoC: %s, revision %X\n", soc->name,
> +		AT91_CIDR_VERSION(cidr));
> +
> +	return soc_dev;
> +}
> +
> +static int __init atmel_soc_device_init(void)
> +{
> +	at91_soc_init(socs);
> +
> +	return 0;
> +}
> +subsys_initcall(atmel_soc_device_init);
> diff --git a/arch/arm/mach-at91/soc.h b/drivers/soc/atmel/soc.h
> similarity index 100%
> rename from arch/arm/mach-at91/soc.h
> rename to drivers/soc/atmel/soc.h
> 


-- 
Nicolas Ferre



More information about the linux-arm-kernel mailing list