^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * arch/arm/mach-mvebu/kirkwood.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Flattened Device Tree board initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/hardware/cache-feroceon-l2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/mach/arch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/mach/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "kirkwood.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "kirkwood-pm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static struct resource kirkwood_cpufreq_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .start = CPU_CONTROL_PHYS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .end = CPU_CONTROL_PHYS + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct platform_device kirkwood_cpufreq_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .name = "kirkwood-cpufreq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .num_resources = ARRAY_SIZE(kirkwood_cpufreq_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .resource = kirkwood_cpufreq_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static void __init kirkwood_cpufreq_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) platform_device_register(&kirkwood_cpufreq_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static struct resource kirkwood_cpuidle_resource[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .start = DDR_OPERATION_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .end = DDR_OPERATION_BASE + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static struct platform_device kirkwood_cpuidle = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .name = "kirkwood_cpuidle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .resource = kirkwood_cpuidle_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .num_resources = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static void __init kirkwood_cpuidle_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) platform_device_register(&kirkwood_cpuidle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MV643XX_ETH_MAC_ADDR_LOW 0x0414
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MV643XX_ETH_MAC_ADDR_HIGH 0x0418
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void __init kirkwood_dt_eth_fixup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * The ethernet interfaces forget the MAC address assigned by u-boot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * if the clocks are turned off. Usually, u-boot on kirkwood boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * has no DT support to properly set local-mac-address property.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * As a workaround, we get the MAC address from mv643xx_eth registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * and update the port device node if no valid MAC address is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct device_node *pnp = of_get_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct property *pmac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) void __iomem *io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u8 *macaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!pnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* skip disabled nodes or nodes with valid MAC address*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!of_device_is_available(pnp) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) !IS_ERR(of_get_mac_address(np)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) goto eth_fixup_skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) clk = of_clk_get(pnp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) goto eth_fixup_skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) io = of_iomap(pnp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) goto eth_fixup_no_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* ensure port clock is not gated to not hang CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) clk_prepare_enable(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* store MAC address register contents in local-mac-address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!pmac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) goto eth_fixup_no_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) pmac->value = pmac + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pmac->length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!pmac->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) kfree(pmac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto eth_fixup_no_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) macaddr = pmac->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) macaddr[0] = (reg >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) macaddr[1] = (reg >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) macaddr[2] = (reg >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) macaddr[3] = reg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) macaddr[4] = (reg >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) macaddr[5] = reg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) of_update_property(np, pmac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) eth_fixup_no_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) iounmap(io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) clk_disable_unprepare(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) eth_fixup_no_map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) clk_put(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) eth_fixup_skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) of_node_put(pnp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Disable propagation of mbus errors to the CPU local bus, as this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * causes mbus errors (which can occur for example for PCI aborts) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * throw CPU aborts, which we're not set up to deal with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static void kirkwood_disable_mbus_error_propagation(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) void __iomem *cpu_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) cpu_config = ioremap(CPU_CONFIG_PHYS, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) writel(readl(cpu_config) & ~CPU_CONFIG_ERROR_PROP, cpu_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static struct of_dev_auxdata auxdata[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) OF_DEV_AUXDATA("marvell,kirkwood-audio", 0xf10a0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) "mvebu-audio", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void __init kirkwood_dt_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) kirkwood_disable_mbus_error_propagation();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) BUG_ON(mvebu_mbus_dt_init(false));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #ifdef CONFIG_CACHE_FEROCEON_L2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) feroceon_of_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) kirkwood_cpufreq_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) kirkwood_cpuidle_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) kirkwood_pm_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) kirkwood_dt_eth_fixup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) of_platform_default_populate(NULL, auxdata, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static const char * const kirkwood_dt_board_compat[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) "marvell,kirkwood",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* Maintainer: Jason Cooper <jason@lakedaemon.net> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .init_machine = kirkwood_dt_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .restart = mvebu_restart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .dt_compat = kirkwood_dt_board_compat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) MACHINE_END