Merge branch 'master' of git://git.denx.de/u-boot-mips

master
Tom Rini 8 years ago
commit 423620b9d4
  1. 57
      arch/mips/Kconfig
  2. 2
      arch/mips/cpu/Makefile
  3. 45
      arch/mips/cpu/cm_init.S
  4. 7
      arch/mips/cpu/cpu.c
  5. 93
      arch/mips/cpu/start.S
  6. 2
      arch/mips/cpu/u-boot.lds
  7. 2
      arch/mips/dts/Makefile
  8. 222
      arch/mips/dts/img,boston.dts
  9. 21
      arch/mips/dts/microAptiv.dtsi
  10. 62
      arch/mips/dts/nexys4ddr.dts
  11. 9
      arch/mips/include/asm/cache.h
  12. 62
      arch/mips/include/asm/cm.h
  13. 7
      arch/mips/include/asm/global_data.h
  14. 13
      arch/mips/include/asm/mipsregs.h
  15. 101
      arch/mips/lib/cache.c
  16. 271
      arch/mips/lib/cache_init.S
  17. 2
      arch/mips/mach-ath79/cpu.c
  18. 16
      board/imgtec/boston/Kconfig
  19. 6
      board/imgtec/boston/MAINTAINERS
  20. 9
      board/imgtec/boston/Makefile
  21. 21
      board/imgtec/boston/boston-lcd.h
  22. 26
      board/imgtec/boston/boston-regs.h
  23. 30
      board/imgtec/boston/checkboard.c
  24. 30
      board/imgtec/boston/ddr.c
  25. 56
      board/imgtec/boston/lowlevel_init.S
  26. 6
      board/imgtec/malta/lowlevel_init.S
  27. 15
      board/imgtec/xilfpga/Kconfig
  28. 6
      board/imgtec/xilfpga/MAINTAINERS
  29. 7
      board/imgtec/xilfpga/Makefile
  30. 55
      board/imgtec/xilfpga/README
  31. 20
      board/imgtec/xilfpga/xilfpga.c
  32. 6
      common/board_f.c
  33. 41
      configs/boston32r2_defconfig
  34. 42
      configs/boston32r2el_defconfig
  35. 41
      configs/boston64r2_defconfig
  36. 42
      configs/boston64r2el_defconfig
  37. 25
      configs/imgtec_xilfpga_defconfig
  38. 58
      doc/README.boston
  39. 8
      drivers/clk/Kconfig
  40. 1
      drivers/clk/Makefile
  41. 97
      drivers/clk/clk_boston.c
  42. 78
      drivers/core/lists.c
  43. 20
      drivers/core/regmap.c
  44. 11
      drivers/core/syscon-uclass.c
  45. 2
      drivers/net/Kconfig
  46. 28
      drivers/net/pch_gbe.c
  47. 90
      drivers/net/xilinx_emaclite.c
  48. 7
      drivers/pci/Kconfig
  49. 1
      drivers/pci/Makefile
  50. 2
      drivers/pci/pci-uclass.c
  51. 220
      drivers/pci/pcie_xilinx.c
  52. 21
      drivers/serial/ns16550.c
  53. 2
      include/clk.h
  54. 81
      include/configs/boston.h
  55. 68
      include/configs/imgtec_xilfpga.h
  56. 13
      include/dt-bindings/clock/boston-clock.h
  57. 9
      include/dt-bindings/interrupt-controller/mips-gic.h

@ -26,6 +26,8 @@ config TARGET_MALTA
select DM
select DM_SERIAL
select DYNAMIC_IO_PORT_BASE
select MIPS_CM
select MIPS_L2_CACHE
select OF_CONTROL
select OF_ISA_BUS
select SUPPORTS_BIG_ENDIAN
@ -73,10 +75,43 @@ config MACH_PIC32
select OF_CONTROL
select DM
config TARGET_BOSTON
bool "Support Boston"
select DM
select DM_SERIAL
select OF_CONTROL
select MIPS_CM
select MIPS_L1_CACHE_SHIFT_6
select MIPS_L2_CACHE
select SUPPORTS_BIG_ENDIAN
select SUPPORTS_LITTLE_ENDIAN
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select SUPPORTS_CPU_MIPS32_R6
select SUPPORTS_CPU_MIPS64_R1
select SUPPORTS_CPU_MIPS64_R2
select SUPPORTS_CPU_MIPS64_R6
config TARGET_XILFPGA
bool "Support Imagination Xilfpga"
select OF_CONTROL
select DM
select DM_SERIAL
select DM_GPIO
select DM_ETH
select SUPPORTS_LITTLE_ENDIAN
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select MIPS_L1_CACHE_SHIFT_4
help
This supports IMGTEC MIPSfpga platform
endchoice
source "board/dbau1x00/Kconfig"
source "board/imgtec/boston/Kconfig"
source "board/imgtec/malta/Kconfig"
source "board/imgtec/xilfpga/Kconfig"
source "board/micronas/vct/Kconfig"
source "board/pb1x00/Kconfig"
source "board/qemu-mips/Kconfig"
@ -300,9 +335,31 @@ config MIPS_L1_CACHE_SHIFT
default "4" if MIPS_L1_CACHE_SHIFT_4
default "5"
config MIPS_L2_CACHE
bool
help
Select this if your system includes an L2 cache and you want U-Boot
to initialise & maintain it.
config DYNAMIC_IO_PORT_BASE
bool
config MIPS_CM
bool
help
Select this if your system contains a MIPS Coherence Manager and you
wish U-Boot to configure it or make use of it to retrieve system
information such as cache configuration.
config MIPS_CM_BASE
hex
default 0x1fbf8000
help
The physical base address at which to map the MIPS Coherence Manager
Global Configuration Registers (GCRs). This should be set such that
the GCRs occupy a region of the physical address space which is
otherwise unused, or at minimum that software doesn't need to access.
endif
endmenu

@ -7,3 +7,5 @@ extra-y = start.o
obj-y += time.o
obj-y += interrupts.o
obj-y += cpu.o
obj-$(CONFIG_MIPS_CM) += cm_init.o

@ -0,0 +1,45 @@
/*
* MIPS Coherence Manager (CM) Initialisation
*
* Copyright (c) 2016 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/cm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
LEAF(mips_cm_map)
/* Config3 must exist for a CM to be present */
mfc0 t0, CP0_CONFIG, 1
bgez t0, 2f
mfc0 t0, CP0_CONFIG, 2
bgez t0, 2f
/* Check Config3.CMGCR to determine CM presence */
mfc0 t0, CP0_CONFIG, 3
and t0, t0, MIPS_CONF3_CMGCR
beqz t0, 2f
/* Find the current physical GCR base address */
1: MFC0 t0, CP0_CMGCRBASE
PTR_SLL t0, t0, 4
/* If the GCRs are where we want, we're done */
PTR_LI t1, CONFIG_MIPS_CM_BASE
beq t0, t1, 2f
/* Move the GCRs to our configured base address */
PTR_LI t2, CKSEG1
PTR_ADDU t0, t0, t2
sw zero, GCR_BASE_UPPER(t0)
sw t1, GCR_BASE(t0)
/* Re-check the GCR base */
b 1b
2: jr ra
END(mips_cm_map)

@ -8,6 +8,7 @@
#include <common.h>
#include <command.h>
#include <linux/compiler.h>
#include <asm/cache.h>
#include <asm/mipsregs.h>
#include <asm/reboot.h>
@ -35,3 +36,9 @@ void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
write_c0_index(index);
tlb_write_indexed();
}
int arch_cpu_init(void)
{
mips_cache_probe();
return 0;
}

@ -12,10 +12,6 @@
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#ifndef CONFIG_SYS_MIPS_CACHE_MODE
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
#endif
#ifndef CONFIG_SYS_INIT_SP_ADDR
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \
CONFIG_SYS_INIT_SP_OFFSET)
@ -112,9 +108,28 @@ ENTRY(_start)
.align 4
reset:
#if __mips_isa_rev >= 6
mfc0 t0, CP0_CONFIG, 5
and t0, t0, MIPS_CONF5_VP
beqz t0, 1f
nop
b 2f
mfc0 t0, CP0_GLOBALNUMBER
#endif
1: mfc0 t0, CP0_EBASE
and t0, t0, EBASE_CPUNUM
/* Hang if this isn't the first CPU in the system */
2: beqz t0, 4f
nop
3: wait
b 3b
nop
/* Clear watch registers */
MTC0 zero, CP0_WATCHLO
4: MTC0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
/* WP(Watch Pending), SW0/1 should be cleared */
@ -127,9 +142,11 @@ reset:
mtc0 zero, CP0_COMPARE
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/* CONFIG0 register */
li t0, CONF_CM_UNCACHED
mfc0 t0, CP0_CONFIG
and t0, t0, MIPS_CONF_IMPL
or t0, t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
ehb
#endif
/*
@ -144,20 +161,31 @@ reset:
1:
PTR_L gp, 0(ra)
#ifdef CONFIG_MIPS_CM
PTR_LA t9, mips_cm_map
jalr t9
nop
#endif
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
/* Initialize any external memory */
PTR_LA t9, lowlevel_init
jalr t9
nop
# endif
/* Initialize caches... */
PTR_LA t9, mips_cache_reset
jalr t9
nop
/* ... and enable them */
li t0, CONFIG_SYS_MIPS_CACHE_MODE
mtc0 t0, CP0_CONFIG
# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
/* Initialize any external memory */
PTR_LA t9, lowlevel_init
jalr t9
nop
# endif
#endif
/* Set up temporary stack */
@ -214,12 +242,9 @@ ENTRY(relocate_code)
PTR_LI t0, CONFIG_SYS_MONITOR_BASE
PTR_SUB s1, s2, t0 # s1 <-- relocation offset
PTR_LA t3, in_ram
PTR_L t2, -(3 * PTRSIZE)(t3) # t2 <-- __image_copy_end
PTR_LA t2, __image_copy_end
move t1, a2
PTR_ADD gp, s1 # adjust gp
/*
* t0 = source address
* t1 = target address
@ -232,32 +257,14 @@ ENTRY(relocate_code)
blt t0, t2, 1b
PTR_ADDU t1, PTRSIZE
/* If caches were enabled, we would have to flush them here. */
PTR_SUB a1, t1, s2 # a1 <-- size
PTR_LA t9, flush_cache
jalr t9
move a0, s2 # a0 <-- destination address
/* Jump to where we've relocated ourselves */
PTR_ADDIU t0, s2, in_ram - _start
jr t0
nop
PTR __rel_dyn_end
PTR __rel_dyn_start
PTR __image_copy_end
PTR _GLOBAL_OFFSET_TABLE_
PTR num_got_entries
in_ram:
/*
* Now we want to update GOT.
*
* GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
* generated by GNU ld. Skip these reserved entries from relocation.
*/
PTR_L t3, -(1 * PTRSIZE)(t0) # t3 <-- num_got_entries
PTR_L t8, -(2 * PTRSIZE)(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_
PTR_LA t3, num_got_entries
PTR_LA t8, _GLOBAL_OFFSET_TABLE_
PTR_ADD t8, s1 # t8 now holds relocated _G_O_T_
PTR_ADDIU t8, t8, 2 * PTRSIZE # skipping first two entries
PTR_LI t2, 2
@ -272,8 +279,8 @@ in_ram:
PTR_ADDIU t8, PTRSIZE
/* Update dynamic relocations */
PTR_L t1, -(4 * PTRSIZE)(t0) # t1 <-- __rel_dyn_start
PTR_L t2, -(5 * PTRSIZE)(t0) # t2 <-- __rel_dyn_end
PTR_LA t1, __rel_dyn_start
PTR_LA t2, __rel_dyn_end
b 2f # skip first reserved entry
PTR_ADDIU t1, 2 * PTRSIZE
@ -298,6 +305,20 @@ in_ram:
PTR_ADDIU t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes
/*
* Flush caches to ensure our newly modified instructions are visible
* to the instruction cache. We're still running with the old GOT, so
* apply the reloc offset to the start address.
*/
PTR_LA a0, __text_start
PTR_LA a1, __text_end
PTR_SUB a1, a1, a0
PTR_LA t9, flush_cache
jalr t9
PTR_ADD a0, s1
PTR_ADD gp, s1 # adjust gp
/*
* Clear BSS
*
* GOT is now relocated. Thus __bss_start and __bss_end can be

@ -19,7 +19,9 @@ SECTIONS
. = ALIGN(4);
.text : {
__text_start = .;
*(.text*)
__text_end = .;
}
. = ALIGN(4);

@ -4,8 +4,10 @@
dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb
dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb
dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
dtb-$(CONFIG_TARGET_XILFPGA) += nexys4ddr.dtb
dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
targets += $(dtb-y)

@ -0,0 +1,222 @@
/dts-v1/;
#include <dt-bindings/clock/boston-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/mips-gic.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "img,boston";
chosen {
stdout-path = &uart0;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "img,mips";
reg = <0>;
clocks = <&clk_boston BOSTON_CLK_CPU>;
};
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x10000000>;
};
gic: interrupt-controller {
compatible = "mti,gic";
interrupt-controller;
#interrupt-cells = <3>;
timer {
compatible = "mti,gic-timer";
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
clocks = <&clk_boston BOSTON_CLK_CPU>;
};
};
pci0: pci@10000000 {
status = "disabled";
compatible = "xlnx,axi-pcie-host-1.00.a";
device_type = "pci";
reg = <0x10000000 0x2000000>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 2 IRQ_TYPE_LEVEL_HIGH>;
ranges = <0x02000000 0 0x40000000
0x40000000 0 0x40000000>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pci0_intc 0>,
<0 0 0 2 &pci0_intc 1>,
<0 0 0 3 &pci0_intc 2>,
<0 0 0 4 &pci0_intc 3>;
pci0_intc: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
pci1: pci@12000000 {
status = "disabled";
compatible = "xlnx,axi-pcie-host-1.00.a";
device_type = "pci";
reg = <0x12000000 0x2000000>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 1 IRQ_TYPE_LEVEL_HIGH>;
ranges = <0x02000000 0 0x20000000
0x20000000 0 0x20000000>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pci1_intc 0>,
<0 0 0 2 &pci1_intc 1>,
<0 0 0 3 &pci1_intc 2>,
<0 0 0 4 &pci1_intc 3>;
pci1_intc: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
pci2: pci@14000000 {
compatible = "xlnx,axi-pcie-host-1.00.a";
device_type = "pci";
reg = <0x14000000 0x2000000>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 0 IRQ_TYPE_LEVEL_HIGH>;
ranges = <0x02000000 0 0x16000000
0x16000000 0 0x100000>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pci2_intc 0>,
<0 0 0 2 &pci2_intc 1>,
<0 0 0 3 &pci2_intc 2>,
<0 0 0 4 &pci2_intc 3>;
pci2_intc: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
pci2_root@0,0,0 {
compatible = "pci10ee,7021";
reg = <0x00000000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
eg20t_bridge@1,0,0 {
compatible = "pci8086,8800";
reg = <0x00010000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
eg20t_mac@2,0,1 {
compatible = "pci8086,8802";
reg = <0x00020100 0 0 0 0>;
phy-reset-gpios = <&eg20t_gpio 6 GPIO_ACTIVE_LOW>;
};
eg20t_gpio: eg20t_gpio@2,0,2 {
compatible = "pci8086,8803";
reg = <0x00020200 0 0 0 0>;
gpio-controller;
#gpio-cells = <2>;
};
eg20t_i2c@2,12,2 {
compatible = "pci8086,8817";
reg = <0x00026200 0 0 0 0>;
#address-cells = <1>;
#size-cells = <0>;
rtc@0x68 {
compatible = "st,m41t81s";
reg = <0x68>;
};
};
};
};
};
plat_regs: system-controller@17ffd000 {
compatible = "img,boston-platform-regs", "syscon";
reg = <0x17ffd000 0x1000>;
u-boot,dm-pre-reloc;
};
clk_boston: clock {
compatible = "img,boston-clock";
#clock-cells = <1>;
regmap = <&plat_regs>;
u-boot,dm-pre-reloc;
};
reboot: syscon-reboot {
compatible = "syscon-reboot";
regmap = <&plat_regs>;
offset = <0x10>;
mask = <0x10>;
};
uart0: uart@17ffe000 {
compatible = "ns16550a";
reg = <0x17ffe000 0x1000>;
reg-shift = <2>;
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_boston BOSTON_CLK_SYS>;
u-boot,dm-pre-reloc;
};
lcd: lcd@17fff000 {
compatible = "img,boston-lcd";
reg = <0x17fff000 0x8>;
};
flash@18000000 {
compatible = "cfi-flash";
reg = <0x18000000 0x8000000>;
bank-width = <2>;
};
};

@ -0,0 +1,21 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "img,xilfpga";
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "mips,m14Kc";
clocks = <&ext>;
reg = <0>;
};
};
ext: ext {
compatible = "fixed-clock";
#clock-cells = <0>;
};
};

@ -0,0 +1,62 @@
/dts-v1/;
#include "microAptiv.dtsi"
/ {
compatible = "digilent,nexys4ddr";
memory {
device_type = "memory";
reg = <0x0 0x08000000>;
};
cpuintc: interrupt-controller@0 {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
compatible = "mti,cpu-interrupt-controller";
};
aliases {
console = &axi_uart16550;
};
axi_ethernetlite: ethernet@10e00000 {
compatible = "xlnx,xps-ethernetlite-1.00.a";
device_type = "network";
local-mac-address = [08 86 4C 0D F7 09];
phy-handle = <&phy0>;
reg = <0x10e00000 0x10000>;
xlnx,duplex = <0x1>;
xlnx,include-global-buffers = <0x1>;
xlnx,include-internal-loopback = <0x0>;
xlnx,include-mdio = <0x1>;
xlnx,instance = "axi_ethernetlite_inst";
xlnx,rx-ping-pong = <0x1>;
xlnx,s-axi-id-width = <0x1>;
xlnx,tx-ping-pong = <0x1>;
xlnx,use-internal = <0x0>;
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: phy@1 {
compatible = <0x0007c0f0 0xfffffff0>;
device_type = "ethernet-phy";
reg = <1>;
} ;
} ;
} ;
axi_uart16550: serial@10400000 {
compatible = "ns16550a";
reg = <0x10400000 0x10000>;
reg-shift = <2>;
reg-offset = <0x1000>;
clock-frequency = <50000000>;
};
};

@ -19,4 +19,13 @@
*/
#define CONFIG_SYS_CACHELINE_SIZE ARCH_DMA_MINALIGN
/**
* mips_cache_probe() - Probe the properties of the caches
*
* Call this to probe the properties such as line sizes of the caches
* present in the system, if any. This must be done before cache maintenance
* functions such as flush_cache may be called.
*/
void mips_cache_probe(void);
#endif /* __MIPS_CACHE_H__ */

@ -0,0 +1,62 @@
/*
* MIPS Coherence Manager (CM) Register Definitions
*
* Copyright (c) 2016 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __MIPS_ASM_CM_H__
#define __MIPS_ASM_CM_H__
/* Global Control Register (GCR) offsets */
#define GCR_BASE 0x0008
#define GCR_BASE_UPPER 0x000c
#define GCR_REV 0x0030
#define GCR_L2_CONFIG 0x0130
#define GCR_L2_TAG_ADDR 0x0600
#define GCR_L2_TAG_ADDR_UPPER 0x0604
#define GCR_L2_TAG_STATE 0x0608
#define GCR_L2_TAG_STATE_UPPER 0x060c
#define GCR_L2_DATA 0x0610
#define GCR_L2_DATA_UPPER 0x0614
#define GCR_Cx_COHERENCE 0x2008
/* GCR_REV CM versions */
#define GCR_REV_CM3 0x0800
/* GCR_L2_CONFIG fields */
#define GCR_L2_CONFIG_ASSOC_SHIFT 0
#define GCR_L2_CONFIG_ASSOC_BITS 8
#define GCR_L2_CONFIG_LINESZ_SHIFT 8
#define GCR_L2_CONFIG_LINESZ_BITS 4
#define GCR_L2_CONFIG_SETSZ_SHIFT 12
#define GCR_L2_CONFIG_SETSZ_BITS 4
#define GCR_L2_CONFIG_BYPASS (1 << 20)
/* GCR_Cx_COHERENCE */
#define GCR_Cx_COHERENCE_DOM_EN (0xff << 0)
#define GCR_Cx_COHERENCE_EN (0x1 << 0)
#ifndef __ASSEMBLY__
#include <asm/io.h>
static inline void *mips_cm_base(void)
{
return (void *)CKSEG1ADDR(CONFIG_MIPS_CM_BASE);
}
static inline unsigned long mips_cm_l2_line_size(void)
{
unsigned long l2conf, line_sz;
l2conf = __raw_readl(mips_cm_base() + GCR_L2_CONFIG);
line_sz = l2conf >> GCR_L2_CONFIG_LINESZ_SHIFT;
line_sz &= GENMASK(GCR_L2_CONFIG_LINESZ_BITS - 1, 0);
return line_sz ? (2 << line_sz) : 0;
}
#endif /* !__ASSEMBLY__ */
#endif /* __MIPS_ASM_CM_H__ */

@ -21,6 +21,13 @@ struct arch_global_data {
unsigned long rev;
unsigned long ver;
#endif
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
unsigned short l1i_line_size;
unsigned short l1d_line_size;
#endif
#ifdef CONFIG_MIPS_L2_CACHE
unsigned short l2_line_size;
#endif
};
#include <asm-generic/global_data.h>

@ -39,6 +39,7 @@
#define CP0_ENTRYLO0 $2
#define CP0_ENTRYLO1 $3
#define CP0_CONF $3
#define CP0_GLOBALNUMBER $3, 1
#define CP0_CONTEXT $4
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
@ -361,6 +362,11 @@
#define CAUSEF_BD (_ULCAST_(1) << 31)
/*
* Bits in the coprocessor 0 EBase register.
*/
#define EBASE_CPUNUM 0x3ff
/*
* Bits in the coprocessor 0 config register.
*/
/* Generic bits. */
@ -450,6 +456,7 @@
#define MIPS_CONF_MT_FTLB (_ULCAST_(4) << 7)
#define MIPS_CONF_AR (_ULCAST_(7) << 10)
#define MIPS_CONF_AT (_ULCAST_(3) << 13)
#define MIPS_CONF_IMPL (_ULCAST_(0x1ff) << 16)
#define MIPS_CONF_M (_ULCAST_(1) << 31)
/*
@ -484,9 +491,13 @@
#define MIPS_CONF1_TLBS_SIZE (6)
#define MIPS_CONF1_TLBS (_ULCAST_(63) << MIPS_CONF1_TLBS_SHIFT)
#define MIPS_CONF2_SA_SHF 0
#define MIPS_CONF2_SA (_ULCAST_(15) << 0)
#define MIPS_CONF2_SL_SHF 4
#define MIPS_CONF2_SL (_ULCAST_(15) << 4)
#define MIPS_CONF2_SS_SHF 8
#define MIPS_CONF2_SS (_ULCAST_(15) << 8)
#define MIPS_CONF2_L2B (_ULCAST_(1) << 12)
#define MIPS_CONF2_SU (_ULCAST_(15) << 12)
#define MIPS_CONF2_TA (_ULCAST_(15) << 16)
#define MIPS_CONF2_TL (_ULCAST_(15) << 20)
@ -548,8 +559,10 @@
#define MIPS_CONF5_MRP (_ULCAST_(1) << 3)
#define MIPS_CONF5_LLB (_ULCAST_(1) << 4)
#define MIPS_CONF5_MVH (_ULCAST_(1) << 5)
#define MIPS_CONF5_VP (_ULCAST_(1) << 7)
#define MIPS_CONF5_FRE (_ULCAST_(1) << 8)
#define MIPS_CONF5_UFE (_ULCAST_(1) << 9)
#define MIPS_CONF5_L2C (_ULCAST_(1) << 10)
#define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27)
#define MIPS_CONF5_EVA (_ULCAST_(1) << 28)
#define MIPS_CONF5_CV (_ULCAST_(1) << 29)

@ -7,34 +7,85 @@
#include <common.h>
#include <asm/cacheops.h>
#include <asm/cm.h>
#include <asm/mipsregs.h>
static inline unsigned long icache_line_size(void)
DECLARE_GLOBAL_DATA_PTR;
static void probe_l2(void)
{
unsigned long conf1, il;
#ifdef CONFIG_MIPS_L2_CACHE
unsigned long conf2, sl;
bool l2c = false;
if (!(read_c0_config1() & MIPS_CONF_M))
return;
if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
return CONFIG_SYS_ICACHE_LINE_SIZE;
conf2 = read_c0_config2();
if (__mips_isa_rev >= 6) {
l2c = conf2 & MIPS_CONF_M;
if (l2c)
l2c = read_c0_config3() & MIPS_CONF_M;
if (l2c)
l2c = read_c0_config4() & MIPS_CONF_M;
if (l2c)
l2c = read_c0_config5() & MIPS_CONF5_L2C;
}
if (l2c && config_enabled(CONFIG_MIPS_CM)) {
gd->arch.l2_line_size = mips_cm_l2_line_size();
} else if (l2c) {
/* We don't know how to retrieve L2 config on this system */
BUG();
} else {
sl = (conf2 & MIPS_CONF2_SL) >> MIPS_CONF2_SL_SHF;
gd->arch.l2_line_size = sl ? (2 << sl) : 0;
}
#endif
}
void mips_cache_probe(void)
{
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
unsigned long conf1, il, dl;
conf1 = read_c0_config1();
il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
if (!il)
return 0;
return 2 << il;
dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
gd->arch.l1i_line_size = il ? (2 << il) : 0;
gd->arch.l1d_line_size = dl ? (2 << dl) : 0;
#endif
probe_l2();
}
static inline unsigned long dcache_line_size(void)
static inline unsigned long icache_line_size(void)
{
unsigned long conf1, dl;
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
return gd->arch.l1i_line_size;
#else
return CONFIG_SYS_ICACHE_LINE_SIZE;
#endif
}
if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
return CONFIG_SYS_DCACHE_LINE_SIZE;
static inline unsigned long dcache_line_size(void)
{
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
return gd->arch.l1d_line_size;
#else
return CONFIG_SYS_DCACHE_LINE_SIZE;
#endif
}
conf1 = read_c0_config1();
dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
if (!dl)
return 0;
return 2 << dl;
static inline unsigned long scache_line_size(void)
{
#ifdef CONFIG_MIPS_L2_CACHE
return gd->arch.l2_line_size;
#else
return 0;
#endif
}
#define cache_loop(start, end, lsize, ops...) do { \
@ -53,12 +104,13 @@ void flush_cache(ulong start_addr, ulong size)
{
unsigned long ilsize = icache_line_size();
unsigned long dlsize = dcache_line_size();
unsigned long slsize = scache_line_size();
/* aend will be miscalculated when size is zero, so we return here */
if (size == 0)
return;
if (ilsize == dlsize) {
if ((ilsize == dlsize) && !slsize) {
/* flush I-cache & D-cache simultaneously */
cache_loop(start_addr, start_addr + size, ilsize,
HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I);
@ -68,6 +120,11 @@ void flush_cache(ulong start_addr, ulong size)
/* flush D-cache */
cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D);
/* flush L2 cache */
if (slsize)
cache_loop(start_addr, start_addr + size, slsize,
HIT_WRITEBACK_INV_SD);
/* flush I-cache */
cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I);
}
@ -75,21 +132,31 @@ void flush_cache(ulong start_addr, ulong size)
void flush_dcache_range(ulong start_addr, ulong stop)
{
unsigned long lsize = dcache_line_size();
unsigned long slsize = scache_line_size();
/* aend will be miscalculated when size is zero, so we return here */
if (start_addr == stop)
return;
cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D);
/* flush L2 cache */
if (slsize)
cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD);
}
void invalidate_dcache_range(ulong start_addr, ulong stop)
{
unsigned long lsize = dcache_line_size();
unsigned long slsize = scache_line_size();
/* aend will be miscalculated when size is zero, so we return here */
if (start_addr == stop)
return;
/* invalidate L2 cache */
if (slsize)
cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD);
cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D);
}

@ -13,6 +13,7 @@
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>
#include <asm/cm.h>
#ifndef CONFIG_SYS_MIPS_CACHE_MODE
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
@ -95,22 +96,147 @@
* with good parity is available. This routine will initialise an area of
* memory starting at location zero to be used as a source of parity.
*
* Note that this function does not follow the standard calling convention &
* may clobber typically callee-saved registers.
*
* RETURNS: N/A
*
*/
#define R_RETURN s0
#define R_IC_SIZE s1
#define R_IC_LINE s2
#define R_DC_SIZE s3
#define R_DC_LINE s4
#define R_L2_SIZE s5
#define R_L2_LINE s6
#define R_L2_BYPASSED s7
#define R_L2_L2C t8
LEAF(mips_cache_reset)
move R_RETURN, ra
#ifdef CONFIG_MIPS_L2_CACHE
/*
* For there to be an L2 present, Config2 must be present. If it isn't
* then we proceed knowing there's no L2 cache.
*/
move R_L2_SIZE, zero
move R_L2_LINE, zero
move R_L2_BYPASSED, zero
move R_L2_L2C, zero
mfc0 t0, CP0_CONFIG, 1
bgez t0, l2_probe_done
/*
* From MIPSr6 onwards the L2 cache configuration might not be reported
* by Config2. The Config5.L2C bit indicates whether this is the case,
* and if it is then we need knowledge of where else to look. For cores
* from Imagination Technologies this is a CM GCR.
*/
# if __mips_isa_rev >= 6
/* Check that Config5 exists */
mfc0 t0, CP0_CONFIG, 2
bgez t0, l2_probe_cop0
mfc0 t0, CP0_CONFIG, 3
bgez t0, l2_probe_cop0
mfc0 t0, CP0_CONFIG, 4
bgez t0, l2_probe_cop0
/* Check Config5.L2C is set */
mfc0 t0, CP0_CONFIG, 5
and R_L2_L2C, t0, MIPS_CONF5_L2C
beqz R_L2_L2C, l2_probe_cop0
/* Config5.L2C is set */
# ifdef CONFIG_MIPS_CM
/* The CM will provide L2 configuration */
PTR_LI t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
lw t1, GCR_L2_CONFIG(t0)
bgez t1, l2_probe_done
ext R_L2_LINE, t1, \
GCR_L2_CONFIG_LINESZ_SHIFT, GCR_L2_CONFIG_LINESZ_BITS
beqz R_L2_LINE, l2_probe_done
li t2, 2
sllv R_L2_LINE, t2, R_L2_LINE
ext t2, t1, GCR_L2_CONFIG_ASSOC_SHIFT, GCR_L2_CONFIG_ASSOC_BITS
addiu t2, t2, 1
mul R_L2_SIZE, R_L2_LINE, t2
ext t2, t1, GCR_L2_CONFIG_SETSZ_SHIFT, GCR_L2_CONFIG_SETSZ_BITS
sllv R_L2_SIZE, R_L2_SIZE, t2
li t2, 64
mul R_L2_SIZE, R_L2_SIZE, t2
/* Bypass the L2 cache so that we can init the L1s early */
or t1, t1, GCR_L2_CONFIG_BYPASS
sw t1, GCR_L2_CONFIG(t0)
sync
li R_L2_BYPASSED, 1
/* Zero the L2 tag registers */
sw zero, GCR_L2_TAG_ADDR(t0)
sw zero, GCR_L2_TAG_ADDR_UPPER(t0)
sw zero, GCR_L2_TAG_STATE(t0)
sw zero, GCR_L2_TAG_STATE_UPPER(t0)
sw zero, GCR_L2_DATA(t0)
sw zero, GCR_L2_DATA_UPPER(t0)
sync
# else
/* We don't know how to retrieve L2 configuration on this system */
# endif
b l2_probe_done
# endif
/*
* For pre-r6 systems, or r6 systems with Config5.L2C==0, probe the L2
* cache configuration from the cop0 Config2 register.
*/
l2_probe_cop0:
mfc0 t0, CP0_CONFIG, 2
srl R_L2_LINE, t0, MIPS_CONF2_SL_SHF
andi R_L2_LINE, R_L2_LINE, MIPS_CONF2_SL >> MIPS_CONF2_SL_SHF
beqz R_L2_LINE, l2_probe_done
li t1, 2
sllv R_L2_LINE, t1, R_L2_LINE
srl t1, t0, MIPS_CONF2_SA_SHF
andi t1, t1, MIPS_CONF2_SA >> MIPS_CONF2_SA_SHF
addiu t1, t1, 1
mul R_L2_SIZE, R_L2_LINE, t1
srl t1, t0, MIPS_CONF2_SS_SHF
andi t1, t1, MIPS_CONF2_SS >> MIPS_CONF2_SS_SHF
sllv R_L2_SIZE, R_L2_SIZE, t1
li t1, 64
mul R_L2_SIZE, R_L2_SIZE, t1
/* Attempt to bypass the L2 so that we can init the L1s early */
or t0, t0, MIPS_CONF2_L2B
mtc0 t0, CP0_CONFIG, 2
ehb
mfc0 t0, CP0_CONFIG, 2
and R_L2_BYPASSED, t0, MIPS_CONF2_L2B
/* Zero the L2 tag registers */
mtc0 zero, CP0_TAGLO, 4
ehb
l2_probe_done:
#endif
#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
li t2, CONFIG_SYS_ICACHE_SIZE
li t8, CONFIG_SYS_ICACHE_LINE_SIZE
li R_IC_SIZE, CONFIG_SYS_ICACHE_SIZE
li R_IC_LINE, CONFIG_SYS_ICACHE_LINE_SIZE
#else
l1_info t2, t8, MIPS_CONF1_IA_SHF
l1_info R_IC_SIZE, R_IC_LINE, MIPS_CONF1_IA_SHF
#endif
#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
li t3, CONFIG_SYS_DCACHE_SIZE
li t9, CONFIG_SYS_DCACHE_LINE_SIZE
li R_DC_SIZE, CONFIG_SYS_DCACHE_SIZE
li R_DC_LINE, CONFIG_SYS_DCACHE_LINE_SIZE
#else
l1_info t3, t9, MIPS_CONF1_DA_SHF
l1_info R_DC_SIZE, R_DC_LINE, MIPS_CONF1_DA_SHF
#endif
#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
@ -123,9 +249,9 @@ LEAF(mips_cache_reset)
li v0, CONFIG_SYS_DCACHE_SIZE
#endif
#else
move v0, t2
sltu t1, t2, t3
movn v0, t3, t1
move v0, R_IC_SIZE
sltu t1, R_IC_SIZE, R_DC_SIZE
movn v0, R_DC_SIZE, t1
#endif
/*
* Now clear that much memory starting from zero.
@ -138,13 +264,36 @@ LEAF(mips_cache_reset)
#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
#ifdef CONFIG_MIPS_L2_CACHE
/*
* If the L2 is bypassed, init the L1 first so that we can execute the
* rest of the cache initialisation using the L1 instruction cache.
*/
bnez R_L2_BYPASSED, l1_init
l2_init:
PTR_LI t0, INDEX_BASE
PTR_ADDU t1, t0, R_L2_SIZE
1: cache INDEX_STORE_TAG_SD, 0(t0)
PTR_ADDU t0, t0, R_L2_LINE
bne t0, t1, 1b
/*
* If the L2 was bypassed then we already initialised the L1s before
* the L2, so we are now done.
*/
bnez R_L2_BYPASSED, l2_unbypass
#endif
/*
* The TagLo registers used depend upon the CPU implementation, but the
* architecture requires that it is safe for software to write to both
* TagLo selects 0 & 2 covering supported cases.
*/
l1_init:
mtc0 zero, CP0_TAGLO
mtc0 zero, CP0_TAGLO, 2
ehb
/*
* The caches are probably in an indeterminate state, so we force good
@ -158,40 +307,122 @@ LEAF(mips_cache_reset)
/*
* Initialize the I-cache first,
*/
blez t2, 1f
blez R_IC_SIZE, 1f
PTR_LI t0, INDEX_BASE
PTR_ADDU t1, t0, t2
PTR_ADDU t1, t0, R_IC_SIZE
/* clear tag to invalidate */
cache_loop t0, t1, t8, INDEX_STORE_TAG_I
cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
/* fill once, so data field parity is correct */
PTR_LI t0, INDEX_BASE
cache_loop t0, t1, t8, FILL
cache_loop t0, t1, R_IC_LINE, FILL
/* invalidate again - prudent but not strictly neccessary */
PTR_LI t0, INDEX_BASE
cache_loop t0, t1, t8, INDEX_STORE_TAG_I
cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
#endif
/* Enable use of the I-cache by setting Config.K0 */
sync
mfc0 t0, CP0_CONFIG
li t1, CONFIG_SYS_MIPS_CACHE_MODE
#if __mips_isa_rev >= 2
ins t0, t1, 0, 3
#else
ori t0, t0, CONF_CM_CMASK
xori t0, t0, CONF_CM_CMASK
or t0, t0, t1
#endif
mtc0 t0, CP0_CONFIG
/*
* then initialize D-cache.
*/
1: blez t3, 3f
1: blez R_DC_SIZE, 3f
PTR_LI t0, INDEX_BASE
PTR_ADDU t1, t0, t3
PTR_ADDU t1, t0, R_DC_SIZE
/* clear all tags */
cache_loop t0, t1, t9, INDEX_STORE_TAG_D
cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
/* load from each line (in cached space) */
PTR_LI t0, INDEX_BASE
2: LONG_L zero, 0(t0)
PTR_ADDU t0, t9
PTR_ADDU t0, R_DC_LINE
bne t0, t1, 2b
/* clear all tags */
PTR_LI t0, INDEX_BASE
cache_loop t0, t1, t9, INDEX_STORE_TAG_D
cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
#endif
3:
#ifdef CONFIG_MIPS_L2_CACHE
/* If the L2 isn't bypassed then we're done */
beqz R_L2_BYPASSED, return
/* The L2 is bypassed - go initialise it */
b l2_init
3: jr ra
l2_unbypass:
# if __mips_isa_rev >= 6
beqz R_L2_L2C, 1f
li t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
lw t1, GCR_L2_CONFIG(t0)
xor t1, t1, GCR_L2_CONFIG_BYPASS
sw t1, GCR_L2_CONFIG(t0)
sync
ehb
b 2f
# endif
1: mfc0 t0, CP0_CONFIG, 2
xor t0, t0, MIPS_CONF2_L2B
mtc0 t0, CP0_CONFIG, 2
ehb
2:
# ifdef CONFIG_MIPS_CM
/* Config3 must exist for a CM to be present */
mfc0 t0, CP0_CONFIG, 1
bgez t0, 2f
mfc0 t0, CP0_CONFIG, 2
bgez t0, 2f
/* Check Config3.CMGCR to determine CM presence */
mfc0 t0, CP0_CONFIG, 3
and t0, t0, MIPS_CONF3_CMGCR
beqz t0, 2f
/* Change Config.K0 to a coherent CCA */
mfc0 t0, CP0_CONFIG
li t1, CONF_CM_CACHABLE_COW
#if __mips_isa_rev >= 2
ins t0, t1, 0, 3
#else
ori t0, t0, CONF_CM_CMASK
xori t0, t0, CONF_CM_CMASK
or t0, t0, t1
#endif
mtc0 t0, CP0_CONFIG
/*
* Join the coherent domain such that the caches of this core are kept
* coherent with those of other cores.
*/
PTR_LI t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
lw t1, GCR_REV(t0)
li t2, GCR_REV_CM3
li t3, GCR_Cx_COHERENCE_EN
bge t1, t2, 1f
li t3, GCR_Cx_COHERENCE_DOM_EN
1: sw t3, GCR_Cx_COHERENCE(t0)
ehb
2:
# endif
#endif
return:
/* Ensure all cache operations complete before returning */
sync
jr ra
END(mips_cache_reset)
/*

@ -46,7 +46,7 @@ static const struct ath79_soc_desc desc[] = {
{ATH79_SOC_QCA9561, "9561", REV_ID_MAJOR_QCA9561, 0},
};
int arch_cpu_init(void)
int mach_cpu_init(void)
{
void __iomem *base;
enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;

@ -0,0 +1,16 @@
if TARGET_BOSTON
config SYS_BOARD
default "boston"
config SYS_VENDOR
default "imgtec"
config SYS_CONFIG_NAME
default "boston"
config SYS_TEXT_BASE
default 0x9fc00000 if 32BIT
default 0xffffffff9fc00000 if 64BIT
endif

@ -0,0 +1,6 @@
BOSTON BOARD
M: Paul Burton <paul.burton@imgtec.com>
S: Maintained
F: board/imgtec/boston/
F: include/configs/boston.h
F: configs/boston_defconfig

@ -0,0 +1,9 @@
#
# Copyright (C) 2016 Imagination Technologies
#
# SPDX-License-Identifier: GPL-2.0
#
obj-y += checkboard.o
obj-y += ddr.o
obj-y += lowlevel_init.o

@ -0,0 +1,21 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef __BOARD_BOSTON_LCD_H__
#define __BOARD_BOSTON_LCD_H__
/**
* lowlevel_display() - Display a message on Boston's LCD
* @msg: The string to display
*
* Display the string @msg on the 7 character LCD display of the Boston board.
* This is typically used for debug or to present some form of status
* indication to the user, allowing faults to be identified when things go
* wrong early enough that the UART isn't up.
*/
void lowlevel_display(const char msg[static 8]);
#endif /* __BOARD_BOSTON_LCD_H__ */

@ -0,0 +1,26 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef __BOARD_BOSTON_REGS_H__
#define __BOARD_BOSTON_REGS_H__
#include <asm/addrspace.h>
#define BOSTON_PLAT_BASE CKSEG1ADDR(0x17ffd000)
#define BOSTON_LCD_BASE CKSEG1ADDR(0x17fff000)
/*
* Platform Register Definitions
*/
#define BOSTON_PLAT_CORE_CL (BOSTON_PLAT_BASE + 0x04)
#define BOSTON_PLAT_DDR3STAT (BOSTON_PLAT_BASE + 0x14)
# define BOSTON_PLAT_DDR3STAT_CALIB (1 << 2)
#define BOSTON_PLAT_DDRCONF0 (BOSTON_PLAT_BASE + 0x38)
# define BOSTON_PLAT_DDRCONF0_SIZE (0xf << 0)
#endif /* __BOARD_BOSTON_REGS_H__ */

@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include "boston-lcd.h"
#include "boston-regs.h"
int checkboard(void)
{
u32 changelist;
lowlevel_display("U-boot ");
printf("Board: MIPS Boston\n");
printf("CPU: 0x%08x", read_c0_prid());
changelist = __raw_readl((uint32_t *)BOSTON_PLAT_CORE_CL);
if (changelist > 1)
printf(" cl%x", changelist);
putc('\n');
return 0;
}

@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <asm/io.h>
#include "boston-regs.h"
phys_size_t initdram(int board_type)
{
u32 ddrconf0 = __raw_readl((uint32_t *)BOSTON_PLAT_DDRCONF0);
return (phys_size_t)(ddrconf0 & BOSTON_PLAT_DDRCONF0_SIZE) << 30;
}
ulong board_get_usable_ram_top(ulong total_size)
{
DECLARE_GLOBAL_DATA_PTR;
if (gd->ram_top < CONFIG_SYS_SDRAM_BASE) {
/* 2GB wrapped around to 0 */
return CKSEG0ADDR(256 << 20);
}
return min_t(unsigned long, gd->ram_top, CKSEG0ADDR(256 << 20));
}

@ -0,0 +1,56 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <config.h>
#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include "boston-regs.h"
.data
msg_ddr_cal: .ascii "DDR Cal "
msg_ddr_ok: .ascii "DDR OK "
.text
LEAF(lowlevel_init)
move s0, ra
PTR_LA a0, msg_ddr_cal
bal lowlevel_display
PTR_LI t0, BOSTON_PLAT_DDR3STAT
1: lw t1, 0(t0)
andi t1, t1, BOSTON_PLAT_DDR3STAT_CALIB
beqz t1, 1b
PTR_LA a0, msg_ddr_ok
bal lowlevel_display
move v0, zero
jr s0
END(lowlevel_init)
LEAF(lowlevel_display)
.set push
.set noat
PTR_LI AT, BOSTON_LCD_BASE
#ifdef CONFIG_64BIT
ld k1, 0(a0)
sd k1, 0(AT)
#else
lw k1, 0(a0)
sw k1, 0(AT)
lw k1, 4(a0)
sw k1, 4(AT)
#endif
.set pop
1: jr ra
END(lowlevel_display)

@ -28,12 +28,6 @@
.globl lowlevel_init
lowlevel_init:
/* disable any L2 cache for now */
sync
mfc0 t0, CP0_CONFIG, 2
ori t0, t0, 0x1 << 12
mtc0 t0, CP0_CONFIG, 2
/* detect the core card */
PTR_LI t0, CKSEG1ADDR(MALTA_REVISION)
lw t0, 0(t0)

@ -0,0 +1,15 @@
if TARGET_XILFPGA
config SYS_BOARD
default "xilfpga"
config SYS_VENDOR
default "imgtec"
config SYS_CONFIG_NAME
default "imgtec_xilfpga"
config SYS_TEXT_BASE
default 0x80C00000
endif

@ -0,0 +1,6 @@
XILFPGA BOARD
M: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
S: Maintained
F: board/imgtec/xilfpga
F: include/configs/xilfpga.h
F: configs/imgtec_xilfpga_defconfig

@ -0,0 +1,7 @@
#
# Copyright (C) 2016, Imagination Technologies Ltd.
# Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y := xilfpga.o

@ -0,0 +1,55 @@
/*
* Copyright (C) 2016, Imagination Technologies Ltd.
*
* Zubair Lutfullah Kakakhel, Zubair.Kakakhel@imgtec.com
*/
MIPSfpga
=======================================
MIPSfpga is an FPGA based development platform by Imagination Technologies
As we are dealing with a MIPS core instantiated on an FPGA, specifications
are fluid and can be varied in RTL.
The example project provided by IMGTEC runs on the Nexys4DDR board by
Digilent powered by the ARTIX-7 FPGA by Xilinx. Relevant details about
the example project and the Nexys4DDR board:
- microAptiv UP core m14Kc
- 50MHz clock speed
- 128Mbyte DDR RAM at 0x0000_0000
- 8Kbyte RAM at 0x1000_0000
- axi_intc at 0x1020_0000
- axi_uart16550 at 0x1040_0000
- axi_gpio at 0x1060_0000
- axi_i2c at 0x10A0_0000
- custom_gpio at 0x10C0_0000
- axi_ethernetlite at 0x10E0_0000
- 8Kbyte BootRAM at 0x1FC0_0000
- 16Mbyte QPI at 0x1D00_0000
Boot protocol:
--------------
The BootRAM is a writeable "RAM" in FPGA at 0x1FC0_0000.
This is for easy reprogrammibility via JTAG.
DDR initialization is already handled by a HW IP block.
When the example project bitstream is loaded, the cpu_reset button
needs to be pressed.
The bootram initializes the cache and axi_uart
Then checks if there is anything non 0xffff_ffff at location 0x1D40_0000
If there is, then that is considered as u-boot. u-boot is copied from
0x1D40_0000 to memory and the bootram jumps into u-boot code.
At this point, the board is ready to load the Linux kernel + buildroot initramfs
This can be done in multiple ways:
1- JTAG load the binary and jump into it.
2- Load kernel stored in the QSPI flash at 0x1D80_0000
3- Load uImage via tftp. Ethernet works in u-boot.
e.g. env set server ip 192.168.154.45; dhcp uImage; bootm

@ -0,0 +1,20 @@
/*
* Imagination Technologies MIPSfpga platform code
*
* Copyright (C) 2016, Imagination Technologies Ltd.
*
* Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
*
* SPDX-License-Identifier: GPL-2.0+
*
*/
#include <common.h>
/* initialize the DDR Controller and PHY */
phys_size_t initdram(int board_type)
{
/* MIG IP block is smart and doesn't need SW
* to do any init */
return CONFIG_SYS_SDRAM_SIZE; /* in bytes */
}

@ -290,6 +290,11 @@ __weak int arch_cpu_init(void)
return 0;
}
__weak int mach_cpu_init(void)
{
return 0;
}
#ifdef CONFIG_SANDBOX
static int setup_ram_buf(void)
{
@ -860,6 +865,7 @@ static init_fnc_t init_sequence_f[] = {
x86_fsp_init,
#endif
arch_cpu_init, /* basic arch cpu dependent setup */
mach_cpu_init, /* SoC/machine dependent CPU setup */
initf_dm,
arch_cpu_init_dm,
mark_bootstage, /* need timer, go after init dm */

@ -0,0 +1,41 @@
CONFIG_MIPS=y
CONFIG_TARGET_BOSTON=y
CONFIG_SYS_TEXT_BASE=0x9fc00000
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_BEST_MATCH=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="boston # "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
CONFIG_CMD_GREPENV=y
CONFIG_CMD_MEMTEST=y
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_SNTP=y
CONFIG_CMD_DNS=y
CONFIG_CMD_LINK_LOCAL=y
CONFIG_CMD_TIME=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_CLK=y
CONFIG_MTD=y
CONFIG_CFI_FLASH=y
CONFIG_DM_ETH=y
CONFIG_PCH_GBE=y
CONFIG_DM_PCI=y
CONFIG_PCI_XILINX=y
CONFIG_SYS_NS16550=y
CONFIG_LZ4=y

@ -0,0 +1,42 @@
CONFIG_MIPS=y
CONFIG_TARGET_BOSTON=y
CONFIG_SYS_TEXT_BASE=0x9fc00000
CONFIG_SYS_LITTLE_ENDIAN=y
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_BEST_MATCH=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="boston # "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
CONFIG_CMD_GREPENV=y
CONFIG_CMD_MEMTEST=y
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_SNTP=y
CONFIG_CMD_DNS=y
CONFIG_CMD_LINK_LOCAL=y
CONFIG_CMD_TIME=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_CLK=y
CONFIG_MTD=y
CONFIG_CFI_FLASH=y
CONFIG_DM_ETH=y
CONFIG_PCH_GBE=y
CONFIG_DM_PCI=y
CONFIG_PCI_XILINX=y
CONFIG_SYS_NS16550=y
CONFIG_LZ4=y

@ -0,0 +1,41 @@
CONFIG_MIPS=y
CONFIG_TARGET_BOSTON=y
CONFIG_CPU_MIPS64_R2=y
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_BEST_MATCH=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="boston # "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
CONFIG_CMD_GREPENV=y
CONFIG_CMD_MEMTEST=y
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_SNTP=y
CONFIG_CMD_DNS=y
CONFIG_CMD_LINK_LOCAL=y
CONFIG_CMD_TIME=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_CLK=y
CONFIG_MTD=y
CONFIG_CFI_FLASH=y
CONFIG_DM_ETH=y
CONFIG_PCH_GBE=y
CONFIG_DM_PCI=y
CONFIG_PCI_XILINX=y
CONFIG_SYS_NS16550=y
CONFIG_LZ4=y

@ -0,0 +1,42 @@
CONFIG_MIPS=y
CONFIG_TARGET_BOSTON=y
CONFIG_SYS_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS64_R2=y
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_BEST_MATCH=y
CONFIG_OF_STDOUT_VIA_ALIAS=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="boston # "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
CONFIG_CMD_GREPENV=y
CONFIG_CMD_MEMTEST=y
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_SNTP=y
CONFIG_CMD_DNS=y
CONFIG_CMD_LINK_LOCAL=y
CONFIG_CMD_TIME=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_CLK=y
CONFIG_MTD=y
CONFIG_CFI_FLASH=y
CONFIG_DM_ETH=y
CONFIG_PCH_GBE=y
CONFIG_DM_PCI=y
CONFIG_PCI_XILINX=y
CONFIG_SYS_NS16550=y
CONFIG_LZ4=y

@ -0,0 +1,25 @@
CONFIG_MIPS=y
CONFIG_SYS_MALLOC_F_LEN=0x600
CONFIG_TARGET_XILFPGA=y
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEFAULT_DEVICE_TREE="nexys4ddr"
CONFIG_BOOTDELAY=5
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="MIPSfpga # "
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_SAVEENV is not set
CONFIG_CMD_MEMINFO=y
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_NETCONSOLE=y
CONFIG_CLK=y
CONFIG_XILINX_EMACLITE=y
CONFIG_SYS_NS16550=y
CONFIG_CMD_DHRYSTONE=y

@ -0,0 +1,58 @@
MIPS Boston Development Board
---------
About
---------
The MIPS Boston development board is built around an FPGA & 3 PCIe controllers,
one of which is connected to an Intel EG20T Platform Controller Hub which
provides most connectivity to the board. It is used during the development &
testing of both new CPUs and the software support for them. It is essentially
the successor of the older MIPS Malta board.
--------
QEMU
--------
U-Boot can be run on a currently out-of-tree branch of QEMU with support for
the Boston board added. This QEMU code can currently be found in the "boston"
branch of git://git.linux-mips.org/pub/scm/paul/qemu.git and used like so:
$ git clone git://git.linux-mips.org/pub/scm/paul/qemu.git -b boston
$ cd qemu
$ ./configure --target-list=mips64el-softmmu
$ make
$ ./mips64el-softmmu/qemu-system-mips64el -M boston -m 2G \
-bios u-boot.bin -serial stdio
Please note that QEMU will default to emulating the I6400 CPU which implements
the MIPS64r6 ISA, and at the time of writing doesn't implement any earlier CPUs
with support for the CPS features the Boston board relies upon. You will
therefore need to configure U-Boot to build for MIPSr6 in order to obtain a
binary that will work in QEMU.
-------------
Toolchain
-------------
If building for MIPSr6 then you will need a toolchain including GCC 5.x or
newer, or the Codescape toolchain available for download from Imagination
Technologies:
http://codescape-mips-sdk.imgtec.com/components/toolchain/2015.06-05/
The "IMG GNU Linux Toolchain" is capable of building for all current MIPS ISAs,
architecture revisions & both endiannesses.
--------
TODO
--------
- AHCI support
- CPU driver
- Exception handling (+UHI?)
- Flash support
- IOCU support
- L2 cache support
- More general LCD display driver
- Multi-arch-variant multi-endian fat binary

@ -20,6 +20,14 @@ config SPL_CLK
setting up clocks within SPL, and allows the same drivers to be
used as U-Boot proper.
config CLK_BOSTON
def_bool y if TARGET_BOSTON
depends on CLK
select REGMAP
select SYSCON
help
Enable this to support the clocks
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/uniphier/Kconfig"
source "drivers/clk/exynos/Kconfig"

@ -15,3 +15,4 @@ obj-y += tegra/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_CLK_EXYNOS) += exynos/
obj-$(CONFIG_CLK_AT91) += at91/
obj-$(CONFIG_CLK_BOSTON) += clk_boston.o

@ -0,0 +1,97 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <dt-bindings/clock/boston-clock.h>
#include <regmap.h>
#include <syscon.h>
struct clk_boston {
struct regmap *regmap;
};
#define BOSTON_PLAT_MMCMDIV 0x30
# define BOSTON_PLAT_MMCMDIV_CLK0DIV (0xff << 0)
# define BOSTON_PLAT_MMCMDIV_INPUT (0xff << 8)
# define BOSTON_PLAT_MMCMDIV_MUL (0xff << 16)
# define BOSTON_PLAT_MMCMDIV_CLK1DIV (0xff << 24)
static uint32_t ext_field(uint32_t val, uint32_t mask)
{
return (val & mask) >> (ffs(mask) - 1);
}
static ulong clk_boston_get_rate(struct clk *clk)
{
struct clk_boston *state = dev_get_platdata(clk->dev);
uint32_t in_rate, mul, div;
uint mmcmdiv;
int err;
err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
if (err)
return 0;
in_rate = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT);
mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL);
switch (clk->id) {
case BOSTON_CLK_SYS:
div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV);
break;
case BOSTON_CLK_CPU:
div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV);
break;
default:
return 0;
}
return (in_rate * mul * 1000000) / div;
}
const struct clk_ops clk_boston_ops = {
.get_rate = clk_boston_get_rate,
};
static int clk_boston_ofdata_to_platdata(struct udevice *dev)
{
struct clk_boston *state = dev_get_platdata(dev);
struct udevice *syscon;
int err;
err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
"regmap", &syscon);
if (err) {
error("unable to find syscon device\n");
return err;
}
state->regmap = syscon_get_regmap(syscon);
if (!state->regmap) {
error("unable to find regmap\n");
return -ENODEV;
}
return 0;
}
static const struct udevice_id clk_boston_match[] = {
{
.compatible = "img,boston-clock",
},
{ /* sentinel */ }
};
U_BOOT_DRIVER(clk_boston) = {
.name = "boston_clock",
.id = UCLASS_CLK,
.of_match = clk_boston_match,
.ofdata_to_platdata = clk_boston_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct clk_boston),
.ops = &clk_boston_ops,
};

@ -101,36 +101,24 @@ int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
/**
* driver_check_compatible() - Check if a driver is compatible with this node
* driver_check_compatible() - Check if a driver matches a compatible string
*
* @param blob: Device tree pointer
* @param offset: Offset of node in device tree
* @param of_match: List of compatible strings to match
* @param of_idp: Returns the match that was found
* @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
* does not have a compatible string, other error <0 if there is a device
* tree error
* @param compat: The compatible string to search for
* @return 0 if there is a match, -ENOENT if no match
*/
static int driver_check_compatible(const void *blob, int offset,
const struct udevice_id *of_match,
const struct udevice_id **of_idp)
static int driver_check_compatible(const struct udevice_id *of_match,
const struct udevice_id **of_idp,
const char *compat)
{
int ret;
*of_idp = NULL;
if (!of_match)
return -ENOENT;
while (of_match->compatible) {
ret = fdt_node_check_compatible(blob, offset,
of_match->compatible);
if (!ret) {
if (!strcmp(of_match->compatible, compat)) {
*of_idp = of_match;
return 0;
} else if (ret == -FDT_ERR_NOTFOUND) {
return -ENODEV;
} else if (ret < 0) {
return -EINVAL;
}
of_match++;
}
@ -147,28 +135,46 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
struct driver *entry;
struct udevice *dev;
bool found = false;
const char *name;
const char *name, *compat_list, *compat;
int compat_length, i;
int result = 0;
int ret = 0;
dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
name = fdt_get_name(blob, offset, NULL);
dm_dbg("bind node %s\n", name);
if (devp)
*devp = NULL;
for (entry = driver; entry != driver + n_ents; entry++) {
ret = driver_check_compatible(blob, offset, entry->of_match,
&id);
name = fdt_get_name(blob, offset, NULL);
if (ret == -ENOENT) {
continue;
} else if (ret == -ENODEV) {
compat_list = fdt_getprop(blob, offset, "compatible", &compat_length);
if (!compat_list) {
if (compat_length == -FDT_ERR_NOTFOUND) {
dm_dbg("Device '%s' has no compatible string\n", name);
break;
} else if (ret) {
dm_warn("Device tree error at offset %d\n", offset);
result = ret;
break;
return 0;
}
dm_warn("Device tree error at offset %d\n", offset);
return compat_length;
}
/*
* Walk through the compatible string list, attempting to match each
* compatible string in order such that we match in order of priority
* from the first string to the last.
*/
for (i = 0; i < compat_length; i += strlen(compat) + 1) {
compat = compat_list + i;
dm_dbg(" - attempt to match compatible string '%s'\n",
compat);
for (entry = driver; entry != driver + n_ents; entry++) {
ret = driver_check_compatible(entry->of_match, &id,
compat);
if (!ret)
break;
}
if (entry == driver + n_ents)
continue;
dm_dbg(" - found match at '%s'\n", entry->name);
ret = device_bind_with_driver_data(parent, entry, name,
id->data, offset, &dev);
@ -188,10 +194,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
break;
}
if (!found && !result && ret != -ENODEV) {
dm_dbg("No match for node '%s'\n",
fdt_get_name(blob, offset, NULL));
}
if (!found && !result && ret != -ENODEV)
dm_dbg("No match for node '%s'\n", name);
return result;
}

@ -13,6 +13,8 @@
#include <mapmem.h>
#include <regmap.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
static struct regmap *regmap_alloc_count(int count)
@ -117,3 +119,21 @@ int regmap_uninit(struct regmap *map)
return 0;
}
int regmap_read(struct regmap *map, uint offset, uint *valp)
{
uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
*valp = le32_to_cpu(readl(ptr));
return 0;
}
int regmap_write(struct regmap *map, uint offset, uint val)
{
uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
writel(cpu_to_le32(val), ptr);
return 0;
}

@ -95,3 +95,14 @@ UCLASS_DRIVER(syscon) = {
.per_device_auto_alloc_size = sizeof(struct syscon_uc_info),
.pre_probe = syscon_pre_probe,
};
static const struct udevice_id generic_syscon_ids[] = {
{ .compatible = "syscon" },
{ }
};
U_BOOT_DRIVER(generic_syscon) = {
.name = "syscon",
.id = UCLASS_SYSCON,
.of_match = generic_syscon_ids,
};

@ -175,7 +175,7 @@ config XILINX_AXIEMAC
This MAC is present in Xilinx Microblaze, Zynq and ZynqMP SoCs.
config XILINX_EMACLITE
depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP || MIPS)
select PHYLIB
select MII
bool "Xilinx Ethernetlite"

@ -118,14 +118,14 @@ static void pch_gbe_rx_descs_init(struct udevice *dev)
memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM);
for (i = 0; i < PCH_GBE_DESC_NUM; i++)
rx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev,
(u32)(priv->rx_buff[i]));
(ulong)(priv->rx_buff[i]));
writel(dm_pci_phys_to_mem(priv->dev, (u32)rx_desc),
writel(dm_pci_phys_to_mem(priv->dev, (ulong)rx_desc),
&mac_regs->rx_dsc_base);
writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1),
&mac_regs->rx_dsc_size);
writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_desc + 1)),
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_desc + 1)),
&mac_regs->rx_dsc_sw_p);
}
@ -137,11 +137,11 @@ static void pch_gbe_tx_descs_init(struct udevice *dev)
memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM);
writel(dm_pci_phys_to_mem(priv->dev, (u32)tx_desc),
writel(dm_pci_phys_to_mem(priv->dev, (ulong)tx_desc),
&mac_regs->tx_dsc_base);
writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1),
&mac_regs->tx_dsc_size);
writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_desc + 1)),
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_desc + 1)),
&mac_regs->tx_dsc_sw_p);
}
@ -251,7 +251,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length)
if (length < 64)
frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (u32)packet);
tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (ulong)packet);
tx_desc->length = length;
tx_desc->tx_words_eob = length + 3;
tx_desc->tx_frame_ctrl = frame_ctrl;
@ -262,7 +262,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length)
if (++priv->tx_idx >= PCH_GBE_DESC_NUM)
priv->tx_idx = 0;
writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_head + priv->tx_idx)),
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_head + priv->tx_idx)),
&mac_regs->tx_dsc_sw_p);
start = get_timer(0);
@ -283,7 +283,7 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
struct pch_gbe_priv *priv = dev_get_priv(dev);
struct pch_gbe_regs *mac_regs = priv->mac_regs;
struct pch_gbe_rx_desc *rx_desc;
u32 hw_desc, buffer_addr, length;
ulong hw_desc, buffer_addr, length;
rx_desc = &priv->rx_desc[priv->rx_idx];
@ -291,7 +291,7 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
hw_desc = readl(&mac_regs->rx_dsc_hw_p_hld);
/* Just return if not receiving any packet */
if ((u32)rx_desc == hw_desc)
if ((ulong)rx_desc == hw_desc)
return -EAGAIN;
buffer_addr = dm_pci_mem_to_phys(priv->dev, rx_desc->buffer_addr);
@ -315,7 +315,7 @@ static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length)
if (++rx_swp >= PCH_GBE_DESC_NUM)
rx_swp = 0;
writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_head + rx_swp)),
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_head + rx_swp)),
&mac_regs->rx_dsc_sw_p);
return 0;
@ -421,7 +421,7 @@ int pch_gbe_probe(struct udevice *dev)
{
struct pch_gbe_priv *priv;
struct eth_pdata *plat = dev_get_platdata(dev);
u32 iobase;
void *iobase;
/*
* The priv structure contains the descriptors and frame buffers which
@ -432,11 +432,9 @@ int pch_gbe_probe(struct udevice *dev)
priv->dev = dev;
dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = dm_pci_mem_to_phys(dev, iobase);
iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
plat->iobase = iobase;
plat->iobase = (ulong)iobase;
priv->mac_regs = (struct pch_gbe_regs *)iobase;
/* Read MAC address from SROM and initialize dev->enetaddr with it */

@ -19,6 +19,7 @@
#include <fdtdec.h>
#include <asm-generic/errno.h>
#include <linux/kernel.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
@ -154,7 +155,7 @@ static int wait_for_bit(const char *func, u32 *reg, const u32 mask,
unsigned long start = get_timer(0);
while (1) {
val = readl(reg);
val = __raw_readl(reg);
if (!set)
val = ~val;
@ -193,16 +194,17 @@ static u32 phyread(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
if (mdio_wait(regs))
return 1;
u32 ctrl_reg = in_be32(&regs->mdioctrl);
out_be32(&regs->mdioaddr, XEL_MDIOADDR_OP_MASK |
((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT) | registernum));
out_be32(&regs->mdioctrl, ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
u32 ctrl_reg = __raw_readl(&regs->mdioctrl);
__raw_writel(XEL_MDIOADDR_OP_MASK
| ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
| registernum), &regs->mdioaddr);
__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, &regs->mdioctrl);
if (mdio_wait(regs))
return 1;
/* Read data */
*data = in_be32(&regs->mdiord);
*data = __raw_readl(&regs->mdiord);
return 0;
}
@ -220,11 +222,12 @@ static u32 phywrite(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
* Data register. Finally, set the Status bit in the MDIO Control
* register to start a MDIO write transaction.
*/
u32 ctrl_reg = in_be32(&regs->mdioctrl);
out_be32(&regs->mdioaddr, ~XEL_MDIOADDR_OP_MASK &
((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT) | registernum));
out_be32(&regs->mdiowr, data);
out_be32(&regs->mdioctrl, ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
u32 ctrl_reg = __raw_readl(&regs->mdioctrl);
__raw_writel(~XEL_MDIOADDR_OP_MASK
& ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
| registernum), &regs->mdioaddr);
__raw_writel(data, &regs->mdiowr);
__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, &regs->mdioctrl);
if (mdio_wait(regs))
return 1;
@ -327,27 +330,27 @@ static int emaclite_start(struct udevice *dev)
* TX - TX_PING & TX_PONG initialization
*/
/* Restart PING TX */
out_be32(&regs->tx_ping_tsr, 0);
__raw_writel(0, &regs->tx_ping_tsr);
/* Copy MAC address */
xemaclite_alignedwrite(pdata->enetaddr, &regs->tx_ping,
ENET_ADDR_LENGTH);
/* Set the length */
out_be32(&regs->tx_ping_tplr, ENET_ADDR_LENGTH);
__raw_writel(ENET_ADDR_LENGTH, &regs->tx_ping_tplr);
/* Update the MAC address in the EMAC Lite */
out_be32(&regs->tx_ping_tsr, XEL_TSR_PROG_MAC_ADDR);
__raw_writel(XEL_TSR_PROG_MAC_ADDR, &regs->tx_ping_tsr);
/* Wait for EMAC Lite to finish with the MAC address update */
while ((in_be32 (&regs->tx_ping_tsr) &
while ((__raw_readl(&regs->tx_ping_tsr) &
XEL_TSR_PROG_MAC_ADDR) != 0)
;
if (emaclite->txpp) {
/* The same operation with PONG TX */
out_be32(&regs->tx_pong_tsr, 0);
__raw_writel(0, &regs->tx_pong_tsr);
xemaclite_alignedwrite(pdata->enetaddr, &regs->tx_pong,
ENET_ADDR_LENGTH);
out_be32(&regs->tx_pong_tplr, ENET_ADDR_LENGTH);
out_be32(&regs->tx_pong_tsr, XEL_TSR_PROG_MAC_ADDR);
while ((in_be32(&regs->tx_pong_tsr) &
__raw_writel(ENET_ADDR_LENGTH, &regs->tx_pong_tplr);
__raw_writel(XEL_TSR_PROG_MAC_ADDR, &regs->tx_pong_tsr);
while ((__raw_readl(&regs->tx_pong_tsr) &
XEL_TSR_PROG_MAC_ADDR) != 0)
;
}
@ -356,13 +359,13 @@ static int emaclite_start(struct udevice *dev)
* RX - RX_PING & RX_PONG initialization
*/
/* Write out the value to flush the RX buffer */
out_be32(&regs->rx_ping_rsr, XEL_RSR_RECV_IE_MASK);
__raw_writel(XEL_RSR_RECV_IE_MASK, &regs->rx_ping_rsr);
if (emaclite->rxpp)
out_be32(&regs->rx_pong_rsr, XEL_RSR_RECV_IE_MASK);
__raw_writel(XEL_RSR_RECV_IE_MASK, &regs->rx_pong_rsr);
out_be32(&regs->mdioctrl, XEL_MDIOCTRL_MDIOEN_MASK);
if (in_be32(&regs->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
__raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, &regs->mdioctrl);
if (__raw_readl(&regs->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
if (!setup_phy(dev))
return -1;
@ -379,9 +382,9 @@ static int xemaclite_txbufferavailable(struct xemaclite *emaclite)
* Read the other buffer register
* and determine if the other buffer is available
*/
tmp = ~in_be32(&regs->tx_ping_tsr);
tmp = ~__raw_readl(&regs->tx_ping_tsr);
if (emaclite->txpp)
tmp |= ~in_be32(&regs->tx_pong_tsr);
tmp |= ~__raw_readl(&regs->tx_pong_tsr);
return !(tmp & XEL_TSR_XMIT_BUSY_MASK);
}
@ -405,40 +408,42 @@ static int emaclite_send(struct udevice *dev, void *ptr, int len)
if (!maxtry) {
printf("Error: Timeout waiting for ethernet TX buffer\n");
/* Restart PING TX */
out_be32(&regs->tx_ping_tsr, 0);
__raw_writel(0, &regs->tx_ping_tsr);
if (emaclite->txpp) {
out_be32(&regs->tx_pong_tsr, 0);
__raw_writel(0, &regs->tx_pong_tsr);
}
return -1;
}
/* Determine if the expected buffer address is empty */
reg = in_be32(&regs->tx_ping_tsr);
reg = __raw_readl(&regs->tx_ping_tsr);
if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
debug("Send packet from tx_ping buffer\n");
/* Write the frame to the buffer */
xemaclite_alignedwrite(ptr, &regs->tx_ping, len);
out_be32(&regs->tx_ping_tplr, len &
(XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO));
reg = in_be32(&regs->tx_ping_tsr);
__raw_writel(len
& (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO),
&regs->tx_ping_tplr);
reg = __raw_readl(&regs->tx_ping_tsr);
reg |= XEL_TSR_XMIT_BUSY_MASK;
out_be32(&regs->tx_ping_tsr, reg);
__raw_writel(reg, &regs->tx_ping_tsr);
return 0;
}
if (emaclite->txpp) {
/* Determine if the expected buffer address is empty */
reg = in_be32(&regs->tx_pong_tsr);
reg = __raw_readl(&regs->tx_pong_tsr);
if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
debug("Send packet from tx_pong buffer\n");
/* Write the frame to the buffer */
xemaclite_alignedwrite(ptr, &regs->tx_pong, len);
out_be32(&regs->tx_pong_tplr, len &
__raw_writel(len &
(XEL_TPLR_LENGTH_MASK_HI |
XEL_TPLR_LENGTH_MASK_LO));
reg = in_be32(&regs->tx_pong_tsr);
XEL_TPLR_LENGTH_MASK_LO),
&regs->tx_pong_tplr);
reg = __raw_readl(&regs->tx_pong_tsr);
reg |= XEL_TSR_XMIT_BUSY_MASK;
out_be32(&regs->tx_pong_tsr, reg);
__raw_writel(reg, &regs->tx_pong_tsr);
return 0;
}
}
@ -458,7 +463,7 @@ static int emaclite_recv(struct udevice *dev, int flags, uchar **packetp)
try_again:
if (!emaclite->use_rx_pong_buffer_next) {
reg = in_be32(&regs->rx_ping_rsr);
reg = __raw_readl(&regs->rx_ping_rsr);
debug("Testing data at rx_ping\n");
if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
debug("Data found in rx_ping buffer\n");
@ -478,7 +483,7 @@ try_again:
goto try_again;
}
} else {
reg = in_be32(&regs->rx_pong_rsr);
reg = __raw_readl(&regs->rx_pong_rsr);
debug("Testing data at rx_pong\n");
if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
debug("Data found in rx_pong buffer\n");
@ -525,9 +530,9 @@ try_again:
length - first_read);
/* Acknowledge the frame */
reg = in_be32(ack);
reg = __raw_readl(ack);
reg &= ~XEL_RSR_RECV_DONE_MASK;
out_be32(ack, reg);
__raw_writel(reg, ack);
debug("Packet receive from 0x%p, length %dB\n", addr, length);
*packetp = etherrxbuff;
@ -595,7 +600,8 @@ static int emaclite_ofdata_to_platdata(struct udevice *dev)
int offset = 0;
pdata->iobase = (phys_addr_t)dev_get_addr(dev);
emaclite->regs = (struct emaclite_regs *)pdata->iobase;
emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
0x10000);
emaclite->phyaddr = -1;

@ -39,4 +39,11 @@ config PCI_TEGRA
with a total of 5 lanes. Some boards require this for Ethernet
support to work (e.g. beaver, jetson-tk1).
config PCI_XILINX
bool "Xilinx AXI Bridge for PCI Express"
depends on DM_PCI
help
Enable support for the Xilinx AXI bridge for PCI express, an IP block
which can be used on some generations of Xilinx FPGAs.
endmenu

@ -31,3 +31,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o
obj-$(CONFIG_WINBOND_83C553) += w83c553f.o
obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o

@ -837,7 +837,7 @@ static int pci_uclass_pre_probe(struct udevice *bus)
hose = bus->uclass_priv;
/* For bridges, use the top-level PCI controller */
if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) {
if (!device_is_on_pci_bus(bus)) {
hose->ctlr = bus;
ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset,
bus->of_offset);

@ -0,0 +1,220 @@
/*
* Xilinx AXI Bridge for PCI Express Driver
*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <dm.h>
#include <pci.h>
#include <asm/io.h>
/**
* struct xilinx_pcie - Xilinx PCIe controller state
* @hose: The parent classes PCI controller state
* @cfg_base: The base address of memory mapped configuration space
*/
struct xilinx_pcie {
struct pci_controller hose;
void *cfg_base;
};
/* Register definitions */
#define XILINX_PCIE_REG_PSCR 0x144
#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11)
/**
* pcie_xilinx_link_up() - Check whether the PCIe link is up
* @pcie: Pointer to the PCI controller state
*
* Checks whether the PCIe link for the given device is up or down.
*
* Return: true if the link is up, else false
*/
static bool pcie_xilinx_link_up(struct xilinx_pcie *pcie)
{
uint32_t pscr = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_PSCR);
return pscr & XILINX_PCIE_REG_PSCR_LNKUP;
}
/**
* pcie_xilinx_config_address() - Calculate the address of a config access
* @pcie: Pointer to the PCI controller state
* @bdf: Identifies the PCIe device to access
* @offset: The offset into the device's configuration space
* @paddress: Pointer to the pointer to write the calculates address to
*
* Calculates the address that should be accessed to perform a PCIe
* configuration space access for a given device identified by the PCIe
* controller device @pcie and the bus, device & function numbers in @bdf. If
* access to the device is not valid then the function will return an error
* code. Otherwise the address to access will be written to the pointer pointed
* to by @paddress.
*
* Return: 0 on success, else -ENODEV
*/
static int pcie_xilinx_config_address(struct xilinx_pcie *pcie, pci_dev_t bdf,
uint offset, void **paddress)
{
unsigned int bus = PCI_BUS(bdf);
unsigned int dev = PCI_DEV(bdf);
unsigned int func = PCI_FUNC(bdf);
void *addr;
if ((bus > 0) && !pcie_xilinx_link_up(pcie))
return -ENODEV;
/*
* Busses 0 (host-PCIe bridge) & 1 (its immediate child) are
* limited to a single device each.
*/
if ((bus < 2) && (dev > 0))
return -ENODEV;
addr = pcie->cfg_base;
addr += bus << 20;
addr += dev << 15;
addr += func << 12;
addr += offset;
*paddress = addr;
return 0;
}
/**
* pcie_xilinx_read_config() - Read from configuration space
* @pcie: Pointer to the PCI controller state
* @bdf: Identifies the PCIe device to access
* @offset: The offset into the device's configuration space
* @valuep: A pointer at which to store the read value
* @size: Indicates the size of access to perform
*
* Read a value of size @size from offset @offset within the configuration
* space of the device identified by the bus, device & function numbers in @bdf
* on the PCI bus @bus.
*
* Return: 0 on success, else -ENODEV or -EINVAL
*/
static int pcie_xilinx_read_config(struct udevice *bus, pci_dev_t bdf,
uint offset, ulong *valuep,
enum pci_size_t size)
{
struct xilinx_pcie *pcie = dev_get_priv(bus);
void *address;
int err;
err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
if (err < 0) {
*valuep = pci_get_ff(size);
return 0;
}
switch (size) {
case PCI_SIZE_8:
*valuep = __raw_readb(address);
return 0;
case PCI_SIZE_16:
*valuep = __raw_readw(address);
return 0;
case PCI_SIZE_32:
*valuep = __raw_readl(address);
return 0;
default:
return -EINVAL;
}
}
/**
* pcie_xilinx_write_config() - Write to configuration space
* @pcie: Pointer to the PCI controller state
* @bdf: Identifies the PCIe device to access
* @offset: The offset into the device's configuration space
* @value: The value to write
* @size: Indicates the size of access to perform
*
* Write the value @value of size @size from offset @offset within the
* configuration space of the device identified by the bus, device & function
* numbers in @bdf on the PCI bus @bus.
*
* Return: 0 on success, else -ENODEV or -EINVAL
*/
static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf,
uint offset, ulong value,
enum pci_size_t size)
{
struct xilinx_pcie *pcie = dev_get_priv(bus);
void *address;
int err;
err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
if (err < 0)
return 0;
switch (size) {
case PCI_SIZE_8:
__raw_writeb(value, address);
return 0;
case PCI_SIZE_16:
__raw_writew(value, address);
return 0;
case PCI_SIZE_32:
__raw_writel(value, address);
return 0;
default:
return -EINVAL;
}
}
/**
* pcie_xilinx_ofdata_to_platdata() - Translate from DT to device state
* @dev: A pointer to the device being operated on
*
* Translate relevant data from the device tree pertaining to device @dev into
* state that the driver will later make use of. This state is stored in the
* device's private data structure.
*
* Return: 0 on success, else -EINVAL
*/
static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev)
{
struct xilinx_pcie *pcie = dev_get_priv(dev);
struct fdt_resource reg_res;
DECLARE_GLOBAL_DATA_PTR;
int err;
err = fdt_get_resource(gd->fdt_blob, dev->of_offset, "reg",
0, &reg_res);
if (err < 0) {
error("\"reg\" resource not found\n");
return err;
}
pcie->cfg_base = map_physmem(reg_res.start,
fdt_resource_size(&reg_res),
MAP_NOCACHE);
return 0;
}
static const struct dm_pci_ops pcie_xilinx_ops = {
.read_config = pcie_xilinx_read_config,
.write_config = pcie_xilinx_write_config,
};
static const struct udevice_id pcie_xilinx_ids[] = {
{ .compatible = "xlnx,axi-pcie-host-1.00.a" },
{ }
};
U_BOOT_DRIVER(pcie_xilinx) = {
.name = "pcie_xilinx",
.id = UCLASS_PCI,
.of_match = pcie_xilinx_ids,
.ops = &pcie_xilinx_ops,
.ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct xilinx_pcie),
};

@ -5,6 +5,7 @@
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
@ -352,6 +353,8 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
{
struct ns16550_platdata *plat = dev->platdata;
fdt_addr_t addr;
struct clk clk;
int err;
/* try Processor Local Bus device first */
addr = dev_get_addr(dev);
@ -397,9 +400,21 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
"reg-offset", 0);
plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"reg-shift", 0);
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"clock-frequency",
CONFIG_SYS_NS16550_CLK);
err = clk_get_by_index(dev, 0, &clk);
if (!err) {
err = clk_get_rate(&clk);
if (!IS_ERR_VALUE(err))
plat->clock = err;
} else if (err != -ENODEV && err != -ENOSYS) {
debug("ns16550 failed to get clock\n");
return err;
}
if (!plat->clock)
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"clock-frequency",
CONFIG_SYS_NS16550_CLK);
if (!plat->clock) {
debug("ns16550 clock not defined\n");
return -EINVAL;

@ -59,7 +59,7 @@ struct clk {
unsigned long id;
};
#if CONFIG_IS_ENABLED(OF_CONTROL)
#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK)
struct phandle_2_cell;
int clk_get_by_index_platdata(struct udevice *dev, int index,
struct phandle_2_cell *cells, struct clk *clk);

@ -0,0 +1,81 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef __CONFIGS_BOSTON_H__
#define __CONFIGS_BOSTON_H__
/*
* General board configuration
*/
#define CONFIG_DISPLAY_BOARDINFO
/*
* CPU
*/
#define CONFIG_SYS_MIPS_TIMER_FREQ 30000000
/*
* PCI
*/
#define CONFIG_PCI
#define CONFIG_PCI_PNP
#define CONFIG_CMD_PCI
/*
* Memory map
*/
#ifdef CONFIG_64BIT
# define CONFIG_SYS_SDRAM_BASE 0xffffffff80000000
#else
# define CONFIG_SYS_SDRAM_BASE 0x80000000
#endif
#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x100000)
#define CONFIG_SYS_MEMTEST_START (CONFIG_SYS_SDRAM_BASE + 0)
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x10000000)
#define CONFIG_SYS_MALLOC_LEN (256 * 1024)
/*
* Console
*/
#define CONFIG_SYS_MAXARGS 16
#define CONFIG_SYS_CBSIZE 256
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
sizeof(CONFIG_SYS_PROMPT) + 16)
#define CONFIG_SYS_LONGHELP
#define CONFIG_BAUDRATE 115200
/*
* Flash
*/
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_SYS_FLASH_CFI
#define CONFIG_SYS_FLASH_PROTECTION
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT 1
#define CONFIG_SYS_MAX_FLASH_SECT 1024
/*
* Environment
*/
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SECT_SIZE 0x20000
#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
#ifdef CONFIG_64BIT
# define CONFIG_ENV_ADDR \
(0xffffffffb8000000 + (128 << 20) - CONFIG_ENV_SIZE)
#else
# define CONFIG_ENV_ADDR \
(0xb8000000 + (128 << 20) - CONFIG_ENV_SIZE)
#endif
#endif /* __CONFIGS_BOSTON_H__ */

@ -0,0 +1,68 @@
/*
* Copyright (C) 2016, Imagination Technologies Ltd.
*
* Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
*
* SPDX-License-Identifier: GPL-2.0+
*
* Imagination Technologies Ltd. MIPSfpga
*/
#ifndef __XILFPGA_CONFIG_H
#define __XILFPGA_CONFIG_H
/* BootROM + MIG is pretty smart. DDR and Cache initialized */
#define CONFIG_SKIP_LOWLEVEL_INIT
/*--------------------------------------------
* CPU configuration
*/
/* CPU Timer rate */
#define CONFIG_SYS_MIPS_TIMER_FREQ 50000000
/* Cache Configuration */
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
/*----------------------------------------------------------------------
* Memory Layout
*/
/* SDRAM Configuration (for final code, data, stack, heap) */
#define CONFIG_SYS_SDRAM_BASE 0x80000000
#define CONFIG_SYS_SDRAM_SIZE 0x08000000 /* 128 Mbytes */
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE - 0x1000)
#define CONFIG_SYS_MALLOC_LEN (256 << 10)
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_LOAD_ADDR 0x80500000 /* default load address */
/*----------------------------------------------------------------------
* Commands
*/
#define CONFIG_SYS_LONGHELP /* undef to save memory */
/*-------------------------------------------------
* FLASH configuration
*/
#define CONFIG_SYS_NO_FLASH
/*------------------------------------------------------------
* Console Configuration
*/
#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */
#define CONFIG_SYS_MAXARGS 16 /* max number of command args*/
#define CONFIG_BAUDRATE 115200
/* -------------------------------------------------
* Environment
*/
#define CONFIG_ENV_IS_NOWHERE 1
#define CONFIG_ENV_SIZE 0x4000
/* ---------------------------------------------------------------------
* Board boot configuration
*/
#define CONFIG_TIMESTAMP /* Print image info with timestamp */
#endif /* __XILFPGA_CONFIG_H */

@ -0,0 +1,13 @@
/*
* Copyright (C) 2016 Imagination Technologies
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__
#define __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__
#define BOSTON_CLK_SYS 0
#define BOSTON_CLK_CPU 1
#endif /* __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__ */

@ -0,0 +1,9 @@
#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_MIPS_GIC_H
#define _DT_BINDINGS_INTERRUPT_CONTROLLER_MIPS_GIC_H
#include <dt-bindings/interrupt-controller/irq.h>
#define GIC_SHARED 0
#define GIC_LOCAL 1
#endif
Loading…
Cancel
Save