versatile.c (5078B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Versatile board support using the device tree 4 * 5 * Copyright (C) 2010 Secret Lab Technologies Ltd. 6 * Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com> 7 * Copyright (C) 2004 ARM Limited 8 * Copyright (C) 2000 Deep Blue Solutions Ltd 9 */ 10 11#include <linux/init.h> 12#include <linux/io.h> 13#include <linux/of.h> 14#include <linux/of_address.h> 15#include <linux/of_irq.h> 16#include <linux/of_platform.h> 17#include <linux/slab.h> 18#include <linux/amba/bus.h> 19#include <linux/amba/mmci.h> 20#include <asm/mach-types.h> 21#include <asm/mach/arch.h> 22#include <asm/mach/map.h> 23 24/* macro to get at MMIO space when running virtually */ 25#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) 26#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n)) 27 28/* 29 * ------------------------------------------------------------------------ 30 * Versatile Registers 31 * ------------------------------------------------------------------------ 32 */ 33#define VERSATILE_SYS_PCICTL_OFFSET 0x44 34#define VERSATILE_SYS_MCI_OFFSET 0x48 35 36/* 37 * VERSATILE peripheral addresses 38 */ 39#define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */ 40#define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */ 41#define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */ 42 43/* 44 * System controller bit assignment 45 */ 46#define VERSATILE_REFCLK 0 47#define VERSATILE_TIMCLK 1 48 49#define VERSATILE_TIMER1_EnSel 15 50#define VERSATILE_TIMER2_EnSel 17 51#define VERSATILE_TIMER3_EnSel 19 52#define VERSATILE_TIMER4_EnSel 21 53 54static void __iomem *versatile_sys_base; 55 56unsigned int mmc_status(struct device *dev) 57{ 58 struct amba_device *adev = container_of(dev, struct amba_device, dev); 59 u32 mask; 60 61 if (adev->res.start == VERSATILE_MMCI0_BASE) 62 mask = 1; 63 else 64 mask = 2; 65 66 return readl(versatile_sys_base + VERSATILE_SYS_MCI_OFFSET) & mask; 67} 68 69static struct mmci_platform_data mmc0_plat_data = { 70 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 71 .status = mmc_status, 72}; 73 74static struct mmci_platform_data mmc1_plat_data = { 75 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 76 .status = mmc_status, 77}; 78 79/* 80 * Lookup table for attaching a specific name and platform_data pointer to 81 * devices as they get created by of_platform_populate(). Ideally this table 82 * would not exist, but the current clock implementation depends on some devices 83 * having a specific name. 84 */ 85struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = { 86 OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", &mmc0_plat_data), 87 OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", &mmc1_plat_data), 88 {} 89}; 90 91static struct map_desc versatile_io_desc[] __initdata __maybe_unused = { 92 { 93 .virtual = IO_ADDRESS(VERSATILE_SCTL_BASE), 94 .pfn = __phys_to_pfn(VERSATILE_SCTL_BASE), 95 .length = SZ_4K * 9, 96 .type = MT_DEVICE 97 } 98}; 99 100static void __init versatile_map_io(void) 101{ 102 debug_ll_io_init(); 103 iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc)); 104} 105 106static void __init versatile_init_early(void) 107{ 108 u32 val; 109 110 /* 111 * set clock frequency: 112 * VERSATILE_REFCLK is 32KHz 113 * VERSATILE_TIMCLK is 1MHz 114 */ 115 val = readl(__io_address(VERSATILE_SCTL_BASE)); 116 writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | 117 (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 118 (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | 119 (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val, 120 __io_address(VERSATILE_SCTL_BASE)); 121} 122 123static void __init versatile_dt_pci_init(void) 124{ 125 u32 val; 126 struct device_node *np; 127 struct property *newprop; 128 129 np = of_find_compatible_node(NULL, NULL, "arm,versatile-pci"); 130 if (!np) 131 return; 132 133 /* Check if PCI backplane is detected */ 134 val = readl(versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET); 135 if (val & 1) { 136 /* 137 * Enable PCI accesses. Note that the documentaton is 138 * inconsistent whether or not this is needed, but the old 139 * driver had it so we will keep it. 140 */ 141 writel(1, versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET); 142 goto out_put_node; 143 } 144 145 newprop = kzalloc(sizeof(*newprop), GFP_KERNEL); 146 if (!newprop) 147 goto out_put_node; 148 149 newprop->name = kstrdup("status", GFP_KERNEL); 150 newprop->value = kstrdup("disabled", GFP_KERNEL); 151 newprop->length = sizeof("disabled"); 152 of_update_property(np, newprop); 153 154 pr_info("Not plugged into PCI backplane!\n"); 155 156out_put_node: 157 of_node_put(np); 158} 159 160static void __init versatile_dt_init(void) 161{ 162 struct device_node *np; 163 164 np = of_find_compatible_node(NULL, NULL, "arm,core-module-versatile"); 165 if (np) 166 versatile_sys_base = of_iomap(np, 0); 167 WARN_ON(!versatile_sys_base); 168 169 versatile_dt_pci_init(); 170 171 of_platform_default_populate(NULL, versatile_auxdata_lookup, NULL); 172} 173 174static const char *const versatile_dt_match[] __initconst = { 175 "arm,versatile-ab", 176 "arm,versatile-pb", 177 NULL, 178}; 179 180DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)") 181 .map_io = versatile_map_io, 182 .init_early = versatile_init_early, 183 .init_machine = versatile_dt_init, 184 .dt_compat = versatile_dt_match, 185MACHINE_END