1/* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 5 * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson 6 * License terms: GNU General Public License (GPL) version 2 7 */ 8 9#include <linux/platform_device.h> 10#include <linux/io.h> 11#include <linux/mfd/dbx500-prcmu.h> 12#include <linux/clksrc-dbx500-prcmu.h> 13#include <linux/sys_soc.h> 14#include <linux/err.h> 15#include <linux/slab.h> 16#include <linux/stat.h> 17#include <linux/of.h> 18#include <linux/of_irq.h> 19#include <linux/irq.h> 20#include <linux/irqchip.h> 21#include <linux/irqchip/arm-gic.h> 22#include <linux/platform_data/clk-ux500.h> 23#include <linux/platform_data/arm-ux500-pm.h> 24 25#include <asm/mach/map.h> 26 27#include "setup.h" 28 29#include "board-mop500.h" 30#include "db8500-regs.h" 31#include "id.h" 32 33void ux500_restart(enum reboot_mode mode, const char *cmd) 34{ 35 local_irq_disable(); 36 local_fiq_disable(); 37 38 prcmu_system_reset(0); 39} 40 41/* 42 * FIXME: Should we set up the GPIO domain here? 43 * 44 * The problem is that we cannot put the interrupt resources into the platform 45 * device until the irqdomain has been added. Right now, we set the GIC interrupt 46 * domain from init_irq(), then load the gpio driver from 47 * core_initcall(nmk_gpio_init) and add the platform devices from 48 * arch_initcall(customize_machine). 49 * 50 * This feels fragile because it depends on the gpio device getting probed 51 * _before_ any device uses the gpio interrupts. 52*/ 53void __init ux500_init_irq(void) 54{ 55 gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND); 56 irqchip_init(); 57 58 /* 59 * Init clocks here so that they are available for system timer 60 * initialization. 61 */ 62 if (cpu_is_u8500_family()) { 63 prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1); 64 ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1); 65 66 u8500_of_clk_init(U8500_CLKRST1_BASE, 67 U8500_CLKRST2_BASE, 68 U8500_CLKRST3_BASE, 69 U8500_CLKRST5_BASE, 70 U8500_CLKRST6_BASE); 71 } else if (cpu_is_u9540()) { 72 prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1); 73 ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1); 74 u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE, 75 U8500_CLKRST3_BASE, U8500_CLKRST5_BASE, 76 U8500_CLKRST6_BASE); 77 } else if (cpu_is_u8540()) { 78 prcmu_early_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1); 79 ux500_pm_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1); 80 u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE, 81 U8500_CLKRST3_BASE, U8500_CLKRST5_BASE, 82 U8500_CLKRST6_BASE); 83 } 84} 85 86static const char * __init ux500_get_machine(void) 87{ 88 return kasprintf(GFP_KERNEL, "DB%4x", dbx500_partnumber()); 89} 90 91static const char * __init ux500_get_family(void) 92{ 93 return kasprintf(GFP_KERNEL, "ux500"); 94} 95 96static const char * __init ux500_get_revision(void) 97{ 98 unsigned int rev = dbx500_revision(); 99 100 if (rev == 0x01) 101 return kasprintf(GFP_KERNEL, "%s", "ED"); 102 else if (rev >= 0xA0) 103 return kasprintf(GFP_KERNEL, "%d.%d", 104 (rev >> 4) - 0xA + 1, rev & 0xf); 105 106 return kasprintf(GFP_KERNEL, "%s", "Unknown"); 107} 108 109static ssize_t ux500_get_process(struct device *dev, 110 struct device_attribute *attr, 111 char *buf) 112{ 113 if (dbx500_id.process == 0x00) 114 return sprintf(buf, "Standard\n"); 115 116 return sprintf(buf, "%02xnm\n", dbx500_id.process); 117} 118 119static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr, 120 const char *soc_id) 121{ 122 soc_dev_attr->soc_id = soc_id; 123 soc_dev_attr->machine = ux500_get_machine(); 124 soc_dev_attr->family = ux500_get_family(); 125 soc_dev_attr->revision = ux500_get_revision(); 126} 127 128static const struct device_attribute ux500_soc_attr = 129 __ATTR(process, S_IRUGO, ux500_get_process, NULL); 130 131struct device * __init ux500_soc_device_init(const char *soc_id) 132{ 133 struct device *parent; 134 struct soc_device *soc_dev; 135 struct soc_device_attribute *soc_dev_attr; 136 137 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 138 if (!soc_dev_attr) 139 return ERR_PTR(-ENOMEM); 140 141 soc_info_populate(soc_dev_attr, soc_id); 142 143 soc_dev = soc_device_register(soc_dev_attr); 144 if (IS_ERR(soc_dev)) { 145 kfree(soc_dev_attr); 146 return NULL; 147 } 148 149 parent = soc_device_to_device(soc_dev); 150 device_create_file(parent, &ux500_soc_attr); 151 152 return parent; 153} 154