linux/arch/arm/mach-clps711x/devices.c
<<
>>
Prefs
   1/*
   2 *  CLPS711X common devices definitions
   3 *
   4 *  Author: Alexander Shiyan <shc_work@mail.ru>, 2013-2014
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/io.h>
  13#include <linux/of_fdt.h>
  14#include <linux/platform_device.h>
  15#include <linux/random.h>
  16#include <linux/sizes.h>
  17#include <linux/slab.h>
  18#include <linux/sys_soc.h>
  19
  20#include <asm/system_info.h>
  21
  22#include <mach/hardware.h>
  23
  24static const struct resource clps711x_cpuidle_res __initconst =
  25        DEFINE_RES_MEM(CLPS711X_PHYS_BASE + HALT, SZ_128);
  26
  27static void __init clps711x_add_cpuidle(void)
  28{
  29        platform_device_register_simple("clps711x-cpuidle", PLATFORM_DEVID_NONE,
  30                                        &clps711x_cpuidle_res, 1);
  31}
  32
  33static const phys_addr_t clps711x_gpios[][2] __initconst = {
  34        { PADR, PADDR },
  35        { PBDR, PBDDR },
  36        { PCDR, PCDDR },
  37        { PDDR, PDDDR },
  38        { PEDR, PEDDR },
  39};
  40
  41static void __init clps711x_add_gpio(void)
  42{
  43        unsigned i;
  44        struct resource gpio_res[2];
  45
  46        memset(gpio_res, 0, sizeof(gpio_res));
  47
  48        gpio_res[0].flags = IORESOURCE_MEM;
  49        gpio_res[1].flags = IORESOURCE_MEM;
  50
  51        for (i = 0; i < ARRAY_SIZE(clps711x_gpios); i++) {
  52                gpio_res[0].start = CLPS711X_PHYS_BASE + clps711x_gpios[i][0];
  53                gpio_res[0].end = gpio_res[0].start;
  54                gpio_res[1].start = CLPS711X_PHYS_BASE + clps711x_gpios[i][1];
  55                gpio_res[1].end = gpio_res[1].start;
  56
  57                platform_device_register_simple("clps711x-gpio", i,
  58                                                gpio_res, ARRAY_SIZE(gpio_res));
  59        }
  60}
  61
  62const struct resource clps711x_syscon_res[] __initconst = {
  63        /* SYSCON1, SYSFLG1 */
  64        DEFINE_RES_MEM(CLPS711X_PHYS_BASE + SYSCON1, SZ_128),
  65        /* SYSCON2, SYSFLG2 */
  66        DEFINE_RES_MEM(CLPS711X_PHYS_BASE + SYSCON2, SZ_128),
  67        /* SYSCON3 */
  68        DEFINE_RES_MEM(CLPS711X_PHYS_BASE + SYSCON3, SZ_64),
  69};
  70
  71static void __init clps711x_add_syscon(void)
  72{
  73        unsigned i;
  74
  75        for (i = 0; i < ARRAY_SIZE(clps711x_syscon_res); i++)
  76                platform_device_register_simple("syscon", i + 1,
  77                                                &clps711x_syscon_res[i], 1);
  78}
  79
  80static const struct resource clps711x_uart1_res[] __initconst = {
  81        DEFINE_RES_MEM(CLPS711X_PHYS_BASE + UARTDR1, SZ_128),
  82        DEFINE_RES_IRQ(IRQ_UTXINT1),
  83        DEFINE_RES_IRQ(IRQ_URXINT1),
  84};
  85
  86static const struct resource clps711x_uart2_res[] __initconst = {
  87        DEFINE_RES_MEM(CLPS711X_PHYS_BASE + UARTDR2, SZ_128),
  88        DEFINE_RES_IRQ(IRQ_UTXINT2),
  89        DEFINE_RES_IRQ(IRQ_URXINT2),
  90};
  91
  92static void __init clps711x_add_uart(void)
  93{
  94        platform_device_register_simple("clps711x-uart", 0, clps711x_uart1_res,
  95                                        ARRAY_SIZE(clps711x_uart1_res));
  96        platform_device_register_simple("clps711x-uart", 1, clps711x_uart2_res,
  97                                        ARRAY_SIZE(clps711x_uart2_res));
  98};
  99
 100static void __init clps711x_soc_init(void)
 101{
 102        struct soc_device_attribute *soc_dev_attr;
 103        struct soc_device *soc_dev;
 104        void __iomem *base;
 105        u32 id[5];
 106
 107        base = ioremap(CLPS711X_PHYS_BASE, SZ_32K);
 108        if (!base)
 109                return;
 110
 111        id[0] = readl(base + UNIQID);
 112        id[1] = readl(base + RANDID0);
 113        id[2] = readl(base + RANDID1);
 114        id[3] = readl(base + RANDID2);
 115        id[4] = readl(base + RANDID3);
 116        system_rev = SYSFLG1_VERID(readl(base + SYSFLG1));
 117
 118        add_device_randomness(id, sizeof(id));
 119
 120        system_serial_low = id[0];
 121
 122        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
 123        if (!soc_dev_attr)
 124                goto out_unmap;
 125
 126        soc_dev_attr->machine = of_flat_dt_get_machine_name();
 127        soc_dev_attr->family = "Cirrus Logic CLPS711X";
 128        soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u", system_rev);
 129        soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%08x", id[0]);
 130
 131        soc_dev = soc_device_register(soc_dev_attr);
 132        if (IS_ERR(soc_dev)) {
 133                kfree(soc_dev_attr->revision);
 134                kfree(soc_dev_attr->soc_id);
 135                kfree(soc_dev_attr);
 136        }
 137
 138out_unmap:
 139        iounmap(base);
 140}
 141
 142void __init clps711x_devices_init(void)
 143{
 144        clps711x_add_cpuidle();
 145        clps711x_add_gpio();
 146        clps711x_add_syscon();
 147        clps711x_add_uart();
 148        clps711x_soc_init();
 149}
 150