Date: Wed, 31 Aug 2011 10:42:42 +0000 (UTC) From: Grzegorz Bernacki <gber@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r225293 - in projects/armv6/sys: arm/include arm/mv arm/mv/armadaxp boot/fdt/dts conf Message-ID: <201108311042.p7VAggwe097213@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gber Date: Wed Aug 31 10:42:42 2011 New Revision: 225293 URL: http://svn.freebsd.org/changeset/base/225293 Log: Support for Marvell's Armada XP (MV-78160). It is initial import of Armada port. More patches with fixes, cleanup and missing functionality will be submitted soon. Obtained from: Marvell, Semihalf Added: projects/armv6/sys/arm/mv/armadaxp/ projects/armv6/sys/arm/mv/armadaxp/armadaxp.c projects/armv6/sys/arm/mv/armadaxp/armadaxp_mp.c projects/armv6/sys/arm/mv/armadaxp/files.armadaxp projects/armv6/sys/arm/mv/armadaxp/std.armadaxp projects/armv6/sys/arm/mv/armadaxp/std.mv78x60 projects/armv6/sys/arm/mv/mpic.c projects/armv6/sys/arm/mv/std-pj4b.mv projects/armv6/sys/boot/fdt/dts/db88f78160.dts Modified: projects/armv6/sys/arm/include/vmparam.h projects/armv6/sys/arm/mv/common.c projects/armv6/sys/arm/mv/files.mv projects/armv6/sys/arm/mv/mv_machdep.c projects/armv6/sys/arm/mv/mvreg.h projects/armv6/sys/arm/mv/mvvar.h projects/armv6/sys/arm/mv/mvwin.h projects/armv6/sys/arm/mv/timer.c projects/armv6/sys/conf/options.arm Modified: projects/armv6/sys/arm/include/vmparam.h ============================================================================== --- projects/armv6/sys/arm/include/vmparam.h Wed Aug 31 09:35:22 2011 (r225292) +++ projects/armv6/sys/arm/include/vmparam.h Wed Aug 31 10:42:42 2011 (r225293) @@ -116,7 +116,9 @@ #endif #define VM_MAXUSER_ADDRESS KERNBASE - ARM_KERN_DIRECTMAP #else /* ARM_USE_SMALL_ALLOC */ +#ifndef VM_MAXUSER_ADDRESS #define VM_MAXUSER_ADDRESS KERNBASE +#endif /* VM_MAXUSER_ADDRESS */ #endif /* ARM_USE_SMALL_ALLOC */ #define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS Added: projects/armv6/sys/arm/mv/armadaxp/armadaxp.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/armv6/sys/arm/mv/armadaxp/armadaxp.c Wed Aug 31 10:42:42 2011 (r225293) @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2011 Semihalf. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: FreeBSD: src/sys/arm/mv/kirkwood/sheevaplug.c,v 1.2 2010/06/13 13:28:53 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/bus.h> + +#include <arm/mv/mvreg.h> +#include <arm/mv/mvvar.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + +#include <machine/fdt.h> + +struct resource_spec mv_gpio_res[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +uint32_t +get_tclk(void) +{ + + return (TCLK_200MHZ); +} + +uint32_t +get_l2clk(void) +{ + + return (TCLK_667MHZ); +} + +int +fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap, vm_offset_t io_va, + vm_offset_t mem_va) +{ + + return (0); +} + Added: projects/armv6/sys/arm/mv/armadaxp/armadaxp_mp.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/armv6/sys/arm/mv/armadaxp/armadaxp_mp.c Wed Aug 31 10:42:42 2011 (r225293) @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 2011 Semihalf. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/smp.h> + +#include <machine/smp.h> +#include <machine/fdt.h> + +#include <arm/mv/mvwin.h> + +/* XXX move to separate header files*/ +#define IPI_SELF 0 +#define IPI_ALL 1 +#define IPI_ALL_BUT_SELF 2 +void mpic_ipi_send(int cpus, u_int ipi); +static int platform_get_ncpus(void); + +#define MV_AXP_CPU_DIVCLK_BASE (MV_BASE + 0x18700) +#define MV_AXP_CPU_DIVCLK_CTRL0 0x00 +#define MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL0 0x08 +#define MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL1 0x0c + +#define MV_COHERENCY_FABRIC_BASE (MV_MBUS_BRIDGE_BASE + 0x200) +#define MV_COHER_FABRIC_CTRL 0x00 +#define MV_COHER_FABRIC_CONF 0x04 + +/* Coherency Fabric registers */ +static uint32_t +read_coher_fabric(uint32_t reg) +{ + + return (bus_space_read_4(fdtbus_bs_tag, MV_COHERENCY_FABRIC_BASE, reg)); +} + +#ifdef not_yet +static void +write_coher_fabric(uint32_t reg, uint32_t val) +{ + + bus_space_write_4(fdtbus_bs_tag, MV_COHERENCY_FABRIC_BASE, reg, val); +} +#endif + +/* Coherency Fabric registers */ +static uint32_t +read_cpu_clkdiv(uint32_t reg) +{ + + return (bus_space_read_4(fdtbus_bs_tag, MV_AXP_CPU_DIVCLK_BASE, reg)); +} + +static void +write_cpu_clkdiv(uint32_t reg, uint32_t val) +{ + + bus_space_write_4(fdtbus_bs_tag, MV_AXP_CPU_DIVCLK_BASE, reg, val); +} + +#if 0 +static void +hello_message(void) +{ + uint32_t cpuid; + + __asm __volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (cpuid)); + printf("CPU AP #%d is ready to serve you my sire.\n", cpuid); +} +#endif + +void +platform_mp_setmaxid(void) +{ + + mp_maxid = 3; +} + +int +platform_mp_probe(void) +{ + + mp_ncpus = platform_get_ncpus(); + + return (mp_ncpus > 1); +} + +int +platform_mp_start_ap(int cpuid) +{ + uint32_t reg; + + if (cpuid == 1) { + if (mp_ncpus > 1) { + reg = read_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL0); + reg &= 0x00ffffff; + reg |= 0x01000000; + write_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL0, reg); + } + if (mp_ncpus > 2) { + reg = read_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL1); + reg &= 0xff00ffff; + reg |= 0x00010000; + write_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL1, reg); + } + if (mp_ncpus > 3) { + reg = read_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL1); + reg &= 0x00ffffff; + reg |= 0x01000000; + write_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL2_RATIO_FULL1, reg); + } + + reg = read_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL0); + reg |= ((0x1 << (mp_ncpus - 1)) - 1) << 21; + write_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL0, reg); + reg = read_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL0); + reg |= 0x01000000; + write_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL0, reg); + + DELAY(100); + reg &= ~(0xf << 21); + write_cpu_clkdiv(MV_AXP_CPU_DIVCLK_CTRL0, reg); + DELAY(100); + + } + + return (0); +} + +static int +platform_get_ncpus(void) +{ + + return ((read_coher_fabric(MV_COHER_FABRIC_CONF) & 0xf) + 1); +} + +#ifdef not_yet +static void +platform_ipi_send(int cpu, u_int ipi) +{ + + mpic_ipi_send(cpu, ipi); +} +#endif Added: projects/armv6/sys/arm/mv/armadaxp/files.armadaxp ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/armv6/sys/arm/mv/armadaxp/files.armadaxp Wed Aug 31 10:42:42 2011 (r225293) @@ -0,0 +1,6 @@ +# $FreeBSD: src/sys/arm/mv/kirkwood/files.db88f6xxx,v 1.1 2008/10/13 20:07:13 raj Exp $ + +arm/mv/armadaxp/armadaxp.c standard +arm/mv/mpic.c standard +arm/mv/rtc.c standard +arm/mv/armadaxp/armadaxp_mp.c optional smp Added: projects/armv6/sys/arm/mv/armadaxp/std.armadaxp ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/armv6/sys/arm/mv/armadaxp/std.armadaxp Wed Aug 31 10:42:42 2011 (r225293) @@ -0,0 +1,15 @@ +# $FreeBSD: src/sys/arm/mv/kirkwood/std.db88f6xxx,v 1.1 2008/10/13 20:07:13 raj Exp $ + +# kernel gets loaded at 0x00f00000 by the loader, but runs at virtual address +# 0xc0f00000. RAM starts at 0. We put the pagetable at a reasonable place +# in memory, but may need to bounce it higher if there's a problem with this. +# We could paper over this by loading the kernel at 0xc0000000 virtual, but +# that leads to other complications, so we'll just reclaim the lower region of +# ram after we're loaded. Put the page tables for startup at 1MB. +makeoptions KERNPHYSADDR=0x00f00000 +makeoptions KERNVIRTADDR=0xc0f00000 + +options KERNPHYSADDR=0x00f00000 +options KERNVIRTADDR=0xc0f00000 +options PHYSADDR=0x00000000 +options STARTUP_PAGETABLE_ADDR=0x00100000 Added: projects/armv6/sys/arm/mv/armadaxp/std.mv78x60 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/armv6/sys/arm/mv/armadaxp/std.mv78x60 Wed Aug 31 10:42:42 2011 (r225293) @@ -0,0 +1,5 @@ +# $FreeBSD: src/sys/arm/mv/kirkwood/std.db88f6xxx,v 1.1 2008/10/13 20:07:13 raj Exp $ + +include "../mv/std-pj4b.mv" +include "../mv/armadaxp/std.armadaxp" +files "../mv/armadaxp/files.armadaxp" Modified: projects/armv6/sys/arm/mv/common.c ============================================================================== --- projects/armv6/sys/arm/mv/common.c Wed Aug 31 09:35:22 2011 (r225292) +++ projects/armv6/sys/arm/mv/common.c Wed Aug 31 10:42:42 2011 (r225293) @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. + * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD. * All rights reserved. * * Developed by Semihalf. @@ -29,6 +29,8 @@ * SUCH DAMAGE. */ +#include "opt_global.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -36,17 +38,27 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/bus.h> #include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/kdb.h> +#include <sys/reboot.h> #include <dev/fdt/fdt_common.h> #include <dev/ofw/openfirm.h> #include <machine/bus.h> #include <machine/fdt.h> +#include <machine/vmparam.h> #include <arm/mv/mvreg.h> #include <arm/mv/mvvar.h> #include <arm/mv/mvwin.h> + +MALLOC_DEFINE(M_IDMA, "idma", "idma dma test memory"); + +#define IDMA_DEBUG +#undef IDMA_DEBUG + #define MAX_CPU_WIN 5 #define DEBUG @@ -67,7 +79,9 @@ __FBSDID("$FreeBSD$"); static int win_eth_can_remap(int i); +#ifndef SOC_MV_FREY static int decode_win_cpu_valid(void); +#endif static int decode_win_usb_valid(void); static int decode_win_eth_valid(void); static int decode_win_pcie_valid(void); @@ -76,10 +90,11 @@ static int decode_win_cesa_valid(void); static int decode_win_idma_valid(void); static int decode_win_xor_valid(void); +#ifndef SOC_MV_FREY static void decode_win_cpu_setup(void); +#endif static void decode_win_usb_setup(u_long); static void decode_win_eth_setup(u_long); -static void decode_win_pcie_setup(u_long); static void decode_win_sata_setup(u_long); static void decode_win_cesa_setup(u_long); static void decode_win_idma_setup(u_long); @@ -96,7 +111,6 @@ static int fdt_get_ranges(const char *, static int win_cpu_from_dt(void); static int fdt_win_setup(void); -static uint32_t used_cpu_wins; static uint32_t dev_mask = 0; static int cpu_wins_no = 0; static int eth_port = 0; @@ -104,7 +118,7 @@ static int usb_port = 0; static struct decode_win cpu_win_tbl[MAX_CPU_WIN]; -static const struct decode_win *cpu_wins = cpu_win_tbl; +const struct decode_win *cpu_wins = cpu_win_tbl; typedef void (*decode_win_setup_t)(u_long); typedef void (*dump_win_t)(u_long); @@ -254,13 +268,22 @@ cpu_extra_feat(void) uint32_t ef = 0; soc_id(&dev, &rev); - if (dev == MV_DEV_88F6281 || dev == MV_DEV_MV78100_Z0 || - dev == MV_DEV_MV78100) + + switch (dev) { + case MV_DEV_88F6281: + case MV_DEV_88RC8180: + case MV_DEV_MV78100_Z0: + case MV_DEV_MV78100: __asm __volatile("mrc p15, 1, %0, c15, c1, 0" : "=r" (ef)); - else if (dev == MV_DEV_88F5182 || dev == MV_DEV_88F5281) + break; + case MV_DEV_88F5182: + case MV_DEV_88F5281: __asm __volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (ef)); - else if (bootverbose) - printf("This ARM Core does not support any extra features\n"); + break; + default: + if (bootverbose) + printf("This ARM Core does not support any extra features\n"); + } return (ef); } @@ -273,7 +296,7 @@ uint32_t soc_power_ctrl_get(uint32_t mask) { -#ifndef SOC_MV_ORION +#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) && !defined(SOC_MV_FREY) if (mask != CPU_PM_CTRL_NONE) mask &= read_cpu_ctrl(CPU_PM_CTRL); @@ -291,7 +314,7 @@ void soc_power_ctrl_set(uint32_t mask) { -#ifndef SOC_MV_ORION +#if !defined(SOC_MV_ORION) && !defined(SOC_MV_LOKIPLUS) if (mask != CPU_PM_CTRL_NONE) write_cpu_ctrl(CPU_PM_CTRL, mask); #endif @@ -314,7 +337,7 @@ soc_id(uint32_t *dev, uint32_t *rev) static void soc_identify(void) { - uint32_t d, r; + uint32_t d, r, size, mode; const char *dev; const char *rev; @@ -354,12 +377,35 @@ soc_identify(void) else if (r == 3) rev = "A1"; break; + case MV_DEV_88RC8180: + dev = "Marvell 88RC8180"; + break; + case MV_DEV_88RC9480: + dev = "Marvell 88RC9480"; + break; + case MV_DEV_88RC9580: + dev = "Marvell 88RC9580"; + break; + case MV_DEV_88F6781: + dev = "Marvell 88F6781"; + if (r == 2) + rev = "Y0"; + break; case MV_DEV_MV78100_Z0: dev = "Marvell MV78100 Z0"; break; case MV_DEV_MV78100: dev = "Marvell MV78100"; break; + case MV_DEV_MV78160: + dev = "Marvell MV78160"; + break; + case MV_DEV_MV78260: + dev = "Marvell MV78260"; + break; + case MV_DEV_MV78460: + dev = "Marvell MV78460"; + break; default: dev = "UNKNOWN"; break; @@ -370,7 +416,28 @@ soc_identify(void) printf(" rev %s", rev); printf(", TClock %dMHz\n", get_tclk() / 1000 / 1000); - /* TODO add info on currently set endianess */ + mode = read_cpu_ctrl(CPU_CONFIG); + printf(" Instruction cache prefetch %s, data cache prefetch %s\n", + (mode & CPU_CONFIG_IC_PREF) ? "enabled" : "disabled", + (mode & CPU_CONFIG_DC_PREF) ? "enabled" : "disabled"); + + switch (d) { + case MV_DEV_88F6281: + mode = read_cpu_ctrl(CPU_L2_CONFIG) & CPU_L2_CONFIG_MODE; + printf(" 256KB 4-way set-associative %s unified L2 cache\n", + mode ? "write-through" : "write-back"); + break; + case MV_DEV_MV78100: + mode = read_cpu_ctrl(CPU_CONTROL); + size = mode & CPU_CONTROL_L2_SIZE; + mode = mode & CPU_CONTROL_L2_MODE; + printf(" %s set-associative %s unified L2 cache\n", + size ? "256KB 4-way" : "512KB 8-way", + mode ? "write-through" : "write-back"); + break; + default: + break; + } } static void @@ -387,6 +454,17 @@ platform_identify(void *dummy) SYSINIT(platform_identify, SI_SUB_CPU, SI_ORDER_SECOND, platform_identify, NULL); +#ifdef KDB +static void +mv_enter_debugger(void *dummy) +{ + + if (boothowto & RB_KDB) + kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); +} +SYSINIT(mv_enter_debugger, SI_SUB_CPU, SI_ORDER_ANY, mv_enter_debugger, NULL); +#endif + int soc_decode_win(void) { @@ -406,6 +484,7 @@ soc_decode_win(void) /* Retrieve our ID: some windows facilities vary between SoC models */ soc_id(&dev, &rev); +#ifndef SOC_MV_FREY if (!decode_win_cpu_valid() || !decode_win_usb_valid() || !decode_win_eth_valid() || !decode_win_idma_valid() || !decode_win_pcie_valid() || !decode_win_sata_valid() || @@ -413,6 +492,13 @@ soc_decode_win(void) return (EINVAL); decode_win_cpu_setup(); +#else + if (!decode_win_usb_valid() || + !decode_win_eth_valid() || !decode_win_idma_valid() || + !decode_win_pcie_valid() || !decode_win_sata_valid() || + !decode_win_cesa_valid() || !decode_win_xor_valid()) + return (EINVAL); +#endif if (MV_DUMP_WIN) soc_dump_decode_win(); @@ -427,6 +513,7 @@ soc_decode_win(void) /************************************************************************** * Decode windows registers accessors **************************************************************************/ +#if !defined(SOC_MV_FREY) WIN_REG_IDX_RD(win_cpu, cr, MV_WIN_CPU_CTRL, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_RD(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_RD(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) @@ -435,9 +522,7 @@ WIN_REG_IDX_WR(win_cpu, cr, MV_WIN_CPU_C WIN_REG_IDX_WR(win_cpu, br, MV_WIN_CPU_BASE, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_WR(win_cpu, remap_l, MV_WIN_CPU_REMAP_LO, MV_MBUS_BRIDGE_BASE) WIN_REG_IDX_WR(win_cpu, remap_h, MV_WIN_CPU_REMAP_HI, MV_MBUS_BRIDGE_BASE) - -WIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) -WIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) +#endif WIN_REG_BASE_IDX_RD(win_usb, cr, MV_WIN_USB_CTRL) WIN_REG_BASE_IDX_RD(win_usb, br, MV_WIN_USB_BASE) @@ -476,7 +561,10 @@ WIN_REG_BASE_IDX_RD(win_pcie, remap, MV_ WIN_REG_BASE_IDX_WR(win_pcie, cr, MV_WIN_PCIE_CTRL); WIN_REG_BASE_IDX_WR(win_pcie, br, MV_WIN_PCIE_BASE); WIN_REG_BASE_IDX_WR(win_pcie, remap, MV_WIN_PCIE_REMAP); -WIN_REG_BASE_IDX_WR(pcie, bar, MV_PCIE_BAR); +WIN_REG_BASE_IDX_RD(pcie_bar, br, MV_PCIE_BAR_BASE); +WIN_REG_BASE_IDX_WR(pcie_bar, br, MV_PCIE_BAR_BASE); +WIN_REG_BASE_IDX_WR(pcie_bar, brh, MV_PCIE_BAR_BASE_H); +WIN_REG_BASE_IDX_WR(pcie_bar, cr, MV_PCIE_BAR_CTRL); WIN_REG_BASE_IDX_RD(win_idma, br, MV_WIN_IDMA_BASE) WIN_REG_BASE_IDX_RD(win_idma, sz, MV_WIN_IDMA_SIZE) @@ -493,7 +581,44 @@ WIN_REG_BASE_IDX_RD(win_sata, cr, MV_WIN WIN_REG_BASE_IDX_RD(win_sata, br, MV_WIN_SATA_BASE); WIN_REG_BASE_IDX_WR(win_sata, cr, MV_WIN_SATA_CTRL); WIN_REG_BASE_IDX_WR(win_sata, br, MV_WIN_SATA_BASE); +#ifndef SOC_MV_DOVE +WIN_REG_IDX_RD(ddr, br, MV_WIN_DDR_BASE, MV_DDR_CADR_BASE) +WIN_REG_IDX_RD(ddr, sz, MV_WIN_DDR_SIZE, MV_DDR_CADR_BASE) +#else +/* + * On 88F6781 (Dove) SoC DDR Controller is accessed through + * single MBUS <-> AXI bridge. In this case we provide emulated + * ddr_br_read() and ddr_sz_read() functions to keep compatibility + * with common decoding windows setup code. + */ + +static inline uint32_t ddr_br_read(int i) +{ + uint32_t mmap; + /* Read Memory Address Map Register for CS i */ + mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0); + + /* Return CS i base address */ + return (mmap & 0xFF000000); +} + +static inline uint32_t ddr_sz_read(int i) +{ + uint32_t mmap, size; + + /* Read Memory Address Map Register for CS i */ + mmap = bus_space_read_4(fdtbus_bs_tag, MV_DDR_CADR_BASE + (i * 0x10), 0); + + /* Extract size of CS space in 64kB units */ + size = (1 << ((mmap >> 16) & 0x0F)); + + /* Return CS size and enable/disable status */ + return (((size - 1) << 16) | (mmap & 0x01)); +} +#endif + +#if !defined(SOC_MV_FREY) /************************************************************************** * Decode windows helper routines **************************************************************************/ @@ -539,8 +664,10 @@ win_cpu_can_remap(int i) if ((dev == MV_DEV_88F5182 && i < 2) || (dev == MV_DEV_88F5281 && i < 4) || (dev == MV_DEV_88F6281 && i < 4) || - (dev == MV_DEV_MV78100 && i < 8) || - (dev == MV_DEV_MV78100_Z0 && i < 8)) + (dev == MV_DEV_88RC8180 && i < 2) || + (dev == MV_DEV_88F6781 && i < 4) || + (dev == MV_DEV_MV78100_Z0 && i < 8) || + ((dev & MV_DEV_FAMILY_MASK) == MV_DEV_DISCOVERY && i < 8)) return (1); return (0); @@ -593,7 +720,7 @@ decode_win_cpu_valid(void) rv = 0; } - if (cpu_wins[i].remap >= 0 && win_cpu_can_remap(i) != 1) { + if (cpu_wins[i].remap != ~0 && win_cpu_can_remap(i) != 1) { printf("CPU window#%d: not capable of remapping, but " "val 0x%08x defined\n", i, cpu_wins[i].remap); rv = 0; @@ -613,6 +740,13 @@ decode_win_cpu_valid(void) continue; } + if (b != (b & ~(s - 1))) { + printf("CPU window#%d: address 0x%08x is not aligned " + "to 0x%08x\n", i, b, s); + rv = 0; + continue; + } + j = decode_win_overlap(i, cpu_wins_no, &cpu_wins[0]); if (j >= 0) { printf("CPU window#%d: (0x%08x - 0x%08x) overlaps " @@ -628,21 +762,39 @@ decode_win_cpu_valid(void) int decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size, - int remap) + vm_paddr_t remap) { uint32_t br, cr; - int win; + int win, i; - if (used_cpu_wins >= MV_WIN_CPU_MAX) - return (0); + if (remap == ~0) { + win = MV_WIN_CPU_MAX - 1; + i = -1; + } else { + win = 0; + i = 1; + } - win = used_cpu_wins++; + while ((win >= 0) && (win < MV_WIN_CPU_MAX)) { + cr = win_cpu_cr_read(win); + if ((cr & MV_WIN_CPU_ENABLE_BIT) == 0) + break; + if ((cr & ((0xff << MV_WIN_CPU_ATTR_SHIFT) | + (0x1f << MV_WIN_CPU_TARGET_SHIFT))) == + ((attr << MV_WIN_CPU_ATTR_SHIFT) | + (target << MV_WIN_CPU_TARGET_SHIFT))) + break; + win += i; + } + if ((win < 0) || (win >= MV_WIN_CPU_MAX) || + ((remap != ~0) && (win_cpu_can_remap(win) == 0))) + return (-1); br = base & 0xffff0000; win_cpu_br_write(win, br); if (win_cpu_can_remap(win)) { - if (remap >= 0) { + if (remap != ~0) { win_cpu_remap_l_write(win, remap & 0xffff0000); win_cpu_remap_h_write(win, 0); } else { @@ -656,7 +808,8 @@ decode_win_cpu_set(int target, int attr, } } - cr = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1; + cr = ((size - 1) & 0xffff0000) | (attr << MV_WIN_CPU_ATTR_SHIFT) | + (target << MV_WIN_CPU_TARGET_SHIFT) | MV_WIN_CPU_ENABLE_BIT; win_cpu_cr_write(win, cr); return (0); @@ -667,8 +820,6 @@ decode_win_cpu_setup(void) { int i; - used_cpu_wins = 0; - /* Disable all CPU windows */ for (i = 0; i < MV_WIN_CPU_MAX; i++) { win_cpu_cr_write(i, 0); @@ -686,7 +837,7 @@ decode_win_cpu_setup(void) cpu_wins[i].size, cpu_wins[i].remap); } - +#endif /* * Check if we're able to cover all active DDR banks. */ @@ -739,6 +890,13 @@ ddr_size(int i) uint32_t ddr_attr(int i) { + uint32_t dev, rev; + + soc_id(&dev, &rev); + if (dev == MV_DEV_88RC8180) + return ((ddr_sz_read(i) & 0xf0) >> 4); + if (dev == MV_DEV_88F6781) + return (0); return (i == 0 ? 0xe : (i == 1 ? 0xd : @@ -749,8 +907,21 @@ ddr_attr(int i) uint32_t ddr_target(int i) { + uint32_t dev, rev; - /* Mbus unit ID is 0x0 for DDR SDRAM controller */ + soc_id(&dev, &rev); + if (dev == MV_DEV_88RC8180) { + i = (ddr_sz_read(i) & 0xf0) >> 4; + return (i == 0xe ? 0xc : + (i == 0xd ? 0xd : + (i == 0xb ? 0xe : + (i == 0x7 ? 0xf : 0xc)))); + } + + /* + * On SOCs other than 88RC8180 Mbus unit ID for + * DDR SDRAM controller is always 0x0. + */ return (0); } @@ -833,7 +1004,7 @@ win_eth_can_remap(int i) /* ETH encode windows 0-3 have remap capability */ if (i < 4) return (1); - + return (0); } @@ -894,6 +1065,12 @@ decode_win_eth_dump(u_long base) win_eth_epap_read(base)); } +#if defined(SOC_MV_LOKIPLUS) +#define MV_WIN_ETH_DDR_TRGT(n) 0 +#else +#define MV_WIN_ETH_DDR_TRGT(n) ddr_target(n) +#endif + static void decode_win_eth_setup(u_long base) { @@ -920,7 +1097,7 @@ decode_win_eth_setup(u_long base) for (i = 0; i < MV_WIN_DDR_MAX; i++) if (ddr_is_active(i)) { - br = ddr_base(i) | (ddr_attr(i) << 8) | ddr_target(i); + br = ddr_base(i) | (ddr_attr(i) << 8) | MV_WIN_ETH_DDR_TRGT(i); sz = ((ddr_size(i) - 1) & 0xffff0000); /* Set the first free ETH window */ @@ -954,15 +1131,21 @@ decode_win_eth_valid(void) * PCIE windows routines **************************************************************************/ -static void +void decode_win_pcie_setup(u_long base) { - uint32_t size = 0; + uint32_t size = 0, ddrbase = ~0; uint32_t cr, br; int i, j; - for (i = 0; i < MV_PCIE_BAR_MAX; i++) - pcie_bar_write(base, i, 0); + for (i = 0; i < MV_PCIE_BAR_MAX; i++) { + pcie_bar_br_write(base, i, + MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); + if (i < 3) + pcie_bar_brh_write(base, i, 0); + if (i > 0) + pcie_bar_cr_write(base, i, 0); + } for (i = 0; i < MV_WIN_PCIE_MAX; i++) { win_pcie_cr_write(base, i, 0); @@ -970,6 +1153,13 @@ decode_win_pcie_setup(u_long base) win_pcie_remap_write(base, i, 0); } + /* On End-Point only set BAR size to 1MB regardless of DDR size */ + if ((bus_space_read_4(fdtbus_bs_tag, base, MV_PCIE_CONTROL) + & MV_PCIE_ROOT_CMPLX) == 0) { + pcie_bar_cr_write(base, 1, 0xf0000 | 1); + return; + } + for (i = 0; i < MV_WIN_DDR_MAX; i++) { if (ddr_is_active(i)) { /* Map DDR to BAR 1 */ @@ -977,6 +1167,8 @@ decode_win_pcie_setup(u_long base) size += ddr_size(i) & 0xffff0000; cr |= (ddr_attr(i) << 8) | (ddr_target(i) << 4) | 1; br = ddr_base(i); + if (br < ddrbase) + ddrbase = br; /* Use the first available PCIE window */ for (j = 0; j < MV_WIN_PCIE_MAX; j++) { @@ -996,7 +1188,11 @@ decode_win_pcie_setup(u_long base) * form value passed to register to get correct value. */ size -= 0x10000; - pcie_bar_write(base, 0, size | 1); + pcie_bar_cr_write(base, 1, size | 1); + pcie_bar_br_write(base, 1, ddrbase | + MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); + pcie_bar_br_write(base, 0, fdt_immr_pa | + MV_PCIE_BAR_64BIT | MV_PCIE_BAR_PREFETCH_EN); } static int @@ -1282,7 +1478,6 @@ xor_ctrl_write(u_long base, int i, int c /* * Set channel protection 'val' for window 'w' on channel 'c' */ - static void xor_chan_write(u_long base, int c, int e, int w, int val) { @@ -1740,7 +1935,7 @@ win_cpu_from_dt(void) /* Retrieve 'ranges' property of '/localbus' node. */ if ((err = fdt_get_ranges("/localbus", ranges, sizeof(ranges), &tuples, &tuple_size)) != 0) - return (err); + return (0); /* * Fill CPU decode windows table. @@ -1755,9 +1950,9 @@ win_cpu_from_dt(void) cpu_win_tbl[t].attr = fdt32_to_cpu(ranges[i + 1]); cpu_win_tbl[t].base = fdt32_to_cpu(ranges[i + 2]); cpu_win_tbl[t].size = fdt32_to_cpu(ranges[i + 3]); - cpu_win_tbl[t].remap = -1; + cpu_win_tbl[t].remap = ~0; debugf("target = 0x%0x attr = 0x%0x base = 0x%0x " - "size = 0x%0x remap = %d\n", cpu_win_tbl[t].target, + "size = 0x%0x remap = 0x%0x\n", cpu_win_tbl[t].target, cpu_win_tbl[t].attr, cpu_win_tbl[t].base, cpu_win_tbl[t].size, cpu_win_tbl[t].remap); } @@ -1784,7 +1979,7 @@ moveon: cpu_win_tbl[t].attr = MV_WIN_CESA_ATTR; cpu_win_tbl[t].base = sram_base; cpu_win_tbl[t].size = sram_size; - cpu_win_tbl[t].remap = -1; + cpu_win_tbl[t].remap = ~0; debugf("sram: base = 0x%0lx size = 0x%0lx\n", sram_base, sram_size); return (0); @@ -1802,15 +1997,12 @@ fdt_win_setup(void) if (node == 0) panic("fdt_win_setup: no root node"); - node = fdt_find_compatible(node, "simple-bus", 1); - if (node == 0) - return (ENXIO); - /* - * Traverse through all children of simple-bus node, and retrieve - * decode windows data for devices (if applicable). + * Traverse through all children of root and simple-bus nodes. + * For each found device retrieve decode windows data (if applicable). */ - for (child = OF_child(node); child != 0; child = OF_peer(child)) + child = OF_child(node); + while (child != 0) { for (i = 0; soc_nodes[i].compat != NULL; i++) { soc_node = &soc_nodes[i]; @@ -1822,7 +2014,7 @@ fdt_win_setup(void) if (err != 0) return (err); - base += fdt_immr_va; + base = (base & 0x000fffff) | fdt_immr_va; if (soc_node->decode_handler != NULL) soc_node->decode_handler(base); else @@ -1832,6 +2024,19 @@ fdt_win_setup(void) soc_node->dump_handler(base); } + /* + * Once done with root-level children let's move down to + * simple-bus and its children. + */ + child = OF_peer(child); + if ((child == 0) && (node == OF_finddevice("/"))) { + node = fdt_find_compatible(node, "simple-bus", 1); + if (node == 0) + return (ENXIO); + child = OF_child(node); + } + } + return (0); } @@ -1862,7 +2067,8 @@ fdt_pic_decode_ic(phandle_t node, pcell_ int *pol) { - if (!fdt_is_compatible(node, "mrvl,pic")) + if (!fdt_is_compatible(node, "mrvl,pic") && + !fdt_is_compatible(node, "mrvl,mpic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); Modified: projects/armv6/sys/arm/mv/files.mv ============================================================================== --- projects/armv6/sys/arm/mv/files.mv Wed Aug 31 09:35:22 2011 (r225292) +++ projects/armv6/sys/arm/mv/files.mv Wed Aug 31 10:42:42 2011 (r225293) @@ -14,14 +14,17 @@ # arm/arm/bus_space_generic.c standard arm/arm/cpufunc_asm_arm10.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv5.S standard arm/arm/cpufunc_asm_armv5_ec.S standard +arm/arm/cpufunc_asm_armv7.S standard arm/arm/cpufunc_asm_sheeva.S standard +arm/arm/cpufunc_asm_pj4b.S standard arm/arm/irq_dispatch.S standard arm/mv/bus_space.c standard arm/mv/common.c standard arm/mv/gpio.c standard -arm/mv/ic.c standard arm/mv/mv_machdep.c standard arm/mv/mv_pci.c optional pci arm/mv/mv_sata.c optional ata | atamvsata Added: projects/armv6/sys/arm/mv/mpic.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/armv6/sys/arm/mv/mpic.c Wed Aug 31 10:42:42 2011 (r225293) @@ -0,0 +1,266 @@ +/*- + * Copyright (c) 2006 Benno Rice. + * Copyright (C) 2007-2011 MARVELL INTERNATIONAL LTD. + * All rights reserved. + * + * Developed by Semihalf. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108311042.p7VAggwe097213>