0001
0002
0003
0004
0005 #include <linux/kernel.h>
0006 #include <linux/amba/mmci.h>
0007 #include <linux/io.h>
0008 #include <linux/irqchip.h>
0009 #include <linux/of_irq.h>
0010 #include <linux/of_address.h>
0011 #include <linux/of_platform.h>
0012 #include <linux/sched_clock.h>
0013 #include <linux/regmap.h>
0014 #include <linux/mfd/syscon.h>
0015
0016 #include <asm/mach/arch.h>
0017 #include <asm/mach/map.h>
0018
0019 #include "integrator-hardware.h"
0020 #include "integrator-cm.h"
0021 #include "integrator.h"
0022
0023
0024 static struct regmap *cm_map;
0025
0026 static void __iomem *intcp_con_base;
0027
0028 #define CM_COUNTER_OFFSET 0x28
0029
0030
0031
0032
0033
0034
0035
0036
0037 static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
0038 {
0039 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
0040 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
0041 .length = SZ_4K,
0042 .type = MT_DEVICE
0043 }, {
0044 .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
0045 .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
0046 .length = SZ_4K,
0047 .type = MT_DEVICE
0048 }, {
0049 .virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
0050 .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
0051 .length = SZ_4K,
0052 .type = MT_DEVICE
0053 }
0054 };
0055
0056 static void __init intcp_map_io(void)
0057 {
0058 iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
0059 }
0060
0061
0062
0063
0064
0065
0066
0067 static unsigned int mmc_status(struct device *dev)
0068 {
0069 unsigned int status = readl(__io_address(0xca000000 + 4));
0070 writel(8, intcp_con_base + 8);
0071
0072 return status & 8;
0073 }
0074
0075 static struct mmci_platform_data mmc_data = {
0076 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
0077 .status = mmc_status,
0078 };
0079
0080 static u64 notrace intcp_read_sched_clock(void)
0081 {
0082 unsigned int val;
0083
0084
0085 regmap_read(cm_map, CM_COUNTER_OFFSET, &val);
0086 return val;
0087 }
0088
0089 static void __init intcp_init_early(void)
0090 {
0091 cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
0092 if (IS_ERR(cm_map))
0093 return;
0094 sched_clock_register(intcp_read_sched_clock, 32, 24000000);
0095 }
0096
0097 static void __init intcp_init_irq_of(void)
0098 {
0099 cm_init();
0100 irqchip_init();
0101 }
0102
0103
0104
0105
0106
0107 static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
0108 OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
0109 "mmci", &mmc_data),
0110 { },
0111 };
0112
0113 static const struct of_device_id intcp_syscon_match[] = {
0114 { .compatible = "arm,integrator-cp-syscon"},
0115 { },
0116 };
0117
0118 static void __init intcp_init_of(void)
0119 {
0120 struct device_node *cpcon;
0121
0122 cpcon = of_find_matching_node(NULL, intcp_syscon_match);
0123 if (!cpcon)
0124 return;
0125
0126 intcp_con_base = of_iomap(cpcon, 0);
0127 if (!intcp_con_base)
0128 return;
0129
0130 of_platform_default_populate(NULL, intcp_auxdata_lookup, NULL);
0131 }
0132
0133 static const char * intcp_dt_board_compat[] = {
0134 "arm,integrator-cp",
0135 NULL,
0136 };
0137
0138 DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
0139 .reserve = integrator_reserve,
0140 .map_io = intcp_map_io,
0141 .init_early = intcp_init_early,
0142 .init_irq = intcp_init_irq_of,
0143 .init_machine = intcp_init_of,
0144 .dt_compat = intcp_dt_board_compat,
0145 MACHINE_END