bmips: add new target

This target has full device tree support, thus reducing the number of
patches needed for bcm63xx, in which there's a patch for every board.

The intention is to start with a minimal amount of downstream patches and
start upstreaming all of them.

Current status:
 - Enabling EHCI/OHCI on BCM6358 causes a kernel panic.
 - BCM63268 lacks Timer Clocks/Reset support.
 - No PCI/PCIe drivers.
 - No ethernet drivers.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
This commit is contained in:
Álvaro Fernández Rojas 2021-02-21 10:00:18 +01:00
parent c27532742d
commit 029093a302
80 changed files with 12048 additions and 0 deletions

View File

@ -0,0 +1,23 @@
# SPDX-License-Identifier: GPL-2.0-or-later
include $(TOPDIR)/rules.mk
ARCH:=mips
CPU_TYPE:=mips32
BOARD:=bmips
BOARDNAME:=Broadcom BMIPS
SUBTARGETS:=generic nand
FEATURES:=gpio source-only squashfs usb
KERNEL_PATCHVER:=5.10
define Target/Description
Build firmware images for BCM33xx cable modem chips,
BCM63xx DSL chips and BCM7xxx set-top box chips.
endef
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += kmod-gpio-button-hotplug
$(eval $(call BuildTarget))

View File

@ -0,0 +1,17 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
. /lib/functions/leds.sh
. /lib/functions/uci-defaults.sh
board_config_update
led_usb="$(get_dt_led usb)"
[ -n "$led_usb" ] && ucidef_set_led_usbdev "usb" "usb" "$led_usb" "1-1"
led_usb2="$(get_dt_led usb2)"
[ -n "$led_usb2" ] && ucidef_set_led_usbdev "usb2" "usb2" "$led_usb2" "2-1"
board_config_flush
exit 0

View File

@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-or-later
. /lib/functions.sh
case "$(board_name)" in
comtrend,ar-5315u|\
comtrend,ar-5387un|\
comtrend,vr-3025u)
mtd fixtrx firmware
;;
esac
exit 0

View File

@ -0,0 +1,59 @@
# SPDX-License-Identifier: GPL-2.0-or-later
PART_NAME=firmware
REQUIRE_IMAGE_METADATA=1
platform_check_image() {
return 0
}
cfe_jffs2_nand_upgrade() {
local tar_file="$1"
local kernel_mtd="$(find_mtd_index $CI_KERNPART)"
if [ -z "$kernel_mtd" ]; then
echo "$CI_KERNPART partition not found"
return 1
fi
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
board_dir=${board_dir%/}
local kernel_length=$(tar xf $tar_file ${board_dir}/kernel -O | wc -c 2> /dev/null)
local rootfs_length=$(tar xf $tar_file ${board_dir}/root -O | wc -c 2> /dev/null)
if [ "$kernel_length" = 0 ]; then
echo "kernel cannot be empty"
return 1
fi
flash_erase -j /dev/mtd${kernel_mtd} 0 0
tar xf $tar_file ${board_dir}/kernel -O | nandwrite /dev/mtd${kernel_mtd} -
local rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)"
nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "0" "0"
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
tar xf $tar_file ${board_dir}/root -O | \
ubiupdatevol /dev/$root_ubivol -s $rootfs_length -
nand_do_upgrade_success
}
platform_do_upgrade() {
case "$(board_name)" in
comtrend,ar-5315u|\
comtrend,ar-5387un|\
comtrend,vr-3025u|\
huawei,hg556a-b)
default_do_upgrade "$1"
;;
comtrend,vr-3032u|\
netgear,dgnd3700-v2)
cfe_jffs2_nand_upgrade "$1"
;;
esac
}

View File

@ -0,0 +1,264 @@
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MMAP_RND_BITS_MAX=15
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_BCM6345_EXT_IRQ=y
CONFIG_BCM6345_L1_IRQ=y
CONFIG_BCM63XX_POWER=y
CONFIG_BCM7038_L1_IRQ=y
CONFIG_BCM7038_WDT=y
CONFIG_BCM7120_L2_IRQ=y
CONFIG_BLK_PM=y
CONFIG_BMIPS_GENERIC=y
CONFIG_BOARD_SCACHE=y
CONFIG_BRCMSTB_L2_IRQ=y
CONFIG_CEVT_R4K=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLK_BCM_63XX_GATE=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMMON_CLK=y
# CONFIG_COMMON_CLK_BOSTON is not set
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_CPU_BMIPS=y
CONFIG_CPU_BMIPS32_3300=y
CONFIG_CPU_BMIPS4350=y
CONFIG_CPU_BMIPS4380=y
CONFIG_CPU_BMIPS5000=y
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_RIXI=y
CONFIG_CPU_HAS_SYNC=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_CPU_MIPS32=y
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
CONFIG_CPU_NO_EFFICIENT_FFS=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_CPUFREQ=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CRASH_DUMP=y
CONFIG_CRC16=y
CONFIG_CRYPTO_ACOMP2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CSRC_R4K=y
CONFIG_DEBUG_INFO=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DTC=y
# CONFIG_DT_BCM93384WVG is not set
# CONFIG_DT_BCM93384WVG_VIPER is not set
# CONFIG_DT_BCM96368MVWG is not set
# CONFIG_DT_BCM97125CBMB is not set
# CONFIG_DT_BCM97346DBSMB is not set
# CONFIG_DT_BCM97358SVMB is not set
# CONFIG_DT_BCM97360SVMB is not set
# CONFIG_DT_BCM97362SVMB is not set
# CONFIG_DT_BCM97420C is not set
# CONFIG_DT_BCM97425SVMB is not set
# CONFIG_DT_BCM97435SVMB is not set
# CONFIG_DT_BCM9EJTAGPRB is not set
# CONFIG_DT_COMTREND_VR3032U is not set
# CONFIG_DT_NETGEAR_CVG834G is not set
CONFIG_DT_NONE=y
# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set
# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set
CONFIG_FIXED_PHY=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_LIB_ASHLDI3=y
CONFIG_GENERIC_LIB_ASHRDI3=y
CONFIG_GENERIC_LIB_CMPDI2=y
CONFIG_GENERIC_LIB_LSHRDI3=y
CONFIG_GENERIC_LIB_UCMPDI2=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GPIOLIB=y
# CONFIG_GPIO_BRCMSTB is not set
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_BCM2835=y
CONFIG_HZ=250
CONFIG_HZ_250=y
CONFIG_HZ_PERIODIC=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_MIPS_CPU=y
CONFIG_IRQ_WORK=y
CONFIG_LEDS_BCM6328=y
CONFIG_LEDS_BCM6358=y
CONFIG_LEDS_GPIO=y
CONFIG_LIBFDT=y
CONFIG_LLD_VERSION=0
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MEMFD_CREATE=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MIPS=y
CONFIG_MIPS_ASID_BITS=8
CONFIG_MIPS_ASID_SHIFT=0
CONFIG_MIPS_CBPF_JIT=y
CONFIG_MIPS_CLOCK_VSYSCALL=y
# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set
# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
CONFIG_MIPS_CMDLINE_FROM_DTB=y
CONFIG_MIPS_CPU_SCACHE=y
# CONFIG_MIPS_ELF_APPENDED_DTB is not set
CONFIG_MIPS_EXTERNAL_TIMER=y
CONFIG_MIPS_L1_CACHE_SHIFT=7
CONFIG_MIPS_L1_CACHE_SHIFT_6=y
CONFIG_MIPS_L1_CACHE_SHIFT_7=y
CONFIG_MIPS_LD_CAN_LINK_VDSO=y
# CONFIG_MIPS_NO_APPENDED_DTB is not set
CONFIG_MIPS_NR_CPU_NR_MAP=2
CONFIG_MIPS_O32_FP64_SUPPORT=y
CONFIG_MIPS_RAW_APPENDED_DTB=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MTD_BCM63XX_PARTS is not set
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_BE_BYTE_SWAP=y
# CONFIG_MTD_CFI_GEOMETRY is not set
# CONFIG_MTD_CFI_NOSWAP is not set
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_JEDECPROBE=y
# CONFIG_MTD_PARSER_IMAGETAG is not set
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NO_EXCEPT_FILL=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_NR_CPUS=2
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_PADATA=y
CONFIG_PCI_DRIVERS_LEGACY=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PHYSICAL_START=0x80010000
CONFIG_PHY_BCM63XX_USBH=y
# CONFIG_PHY_BRCM_SATA is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_BCM6318=y
CONFIG_PINCTRL_BCM63268=y
CONFIG_PINCTRL_BCM6328=y
CONFIG_PINCTRL_BCM6358=y
CONFIG_PINCTRL_BCM6362=y
CONFIG_PINCTRL_BCM6368=y
CONFIG_PINCTRL_BCM63XX=y
CONFIG_PM=y
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_PROC_VMCORE=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RATIONAL=y
CONFIG_RCU_NEED_SEGCBLIST=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_RELAY=y
CONFIG_RESET_BCM6345=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_SERIAL_BCM63XX=y
CONFIG_SERIAL_BCM63XX_CONSOLE=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SGL_ALLOC=y
CONFIG_SMP=y
CONFIG_SMP_UP=y
CONFIG_SOC_BCM63XX=y
CONFIG_SPI=y
CONFIG_SPI_BCM63XX=y
CONFIG_SPI_BCM63XX_HSSPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SRCU=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWPHY=y
CONFIG_SYNC_R4K=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_SYS_HAS_CPU_BMIPS=y
CONFIG_SYS_HAS_CPU_BMIPS32_3300=y
CONFIG_SYS_HAS_CPU_BMIPS4350=y
CONFIG_SYS_HAS_CPU_BMIPS4380=y
CONFIG_SYS_HAS_CPU_BMIPS5000=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_HIGHMEM=y
CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_TARGET_ISA_REV=0
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y
CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WEAK_ORDERING=y
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y

View File

@ -0,0 +1,193 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "bcm63268.dtsi"
/ {
model = "Comtrend VR-3032u";
compatible = "comtrend,vr-3032u", "brcm,bcm63168", "brcm,bcm63268";
aliases {
led-boot = &led_power_green;
led-failsafe = &led_power_green;
led-running = &led_power_green;
led-upgrade = &led_power_green;
led-usb = &led_usb_green;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x04000000>;
};
keys {
compatible = "gpio-keys-polled";
poll-interval = <20>;
reset {
label = "reset";
gpios = <&pinctrl 33 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
debounce-interval = <60>;
};
wps {
label = "wps";
gpios = <&pinctrl 34 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;
debounce-interval = <60>;
};
};
};
&ehci {
status = "okay";
};
&leds {
status = "okay";
brcm,serial-leds;
brcm,serial-dat-low;
brcm,serial-shift-inv;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_serial_led>;
led@0 {
/* GPHY0 Spd 0 */
reg = <0>;
brcm,hardware-controlled;
brcm,link-signal-sources = <0>;
};
led@1 {
/* GPHY0 Spd 1 */
reg = <1>;
brcm,hardware-controlled;
brcm,link-signal-sources = <1>;
};
led@2 {
reg = <2>;
active-low;
label = "red:internet";
};
led@3 {
reg = <3>;
active-low;
label = "green:dsl";
};
led_usb_green: led@4 {
reg = <4>;
active-low;
label = "green:usb";
};
led@7 {
reg = <7>;
active-low;
label = "green:wps";
};
led@8 {
reg = <8>;
active-low;
label = "green:internet";
};
led@9 {
/* EPHY0 Act */
reg = <9>;
brcm,hardware-controlled;
};
led@10 {
/* EPHY1 Act */
reg = <10>;
brcm,hardware-controlled;
};
led@11 {
/* EPHY2 Act */
reg = <11>;
brcm,hardware-controlled;
};
led@12 {
/* GPHY0 Act */
reg = <12>;
brcm,hardware-controlled;
};
led@13 {
/* EPHY0 Spd */
reg = <13>;
brcm,hardware-controlled;
};
led@14 {
/* EPHY1 Spd */
reg = <14>;
brcm,hardware-controlled;
};
led@15 {
/* EPHY2 Spd */
reg = <15>;
brcm,hardware-controlled;
};
led_power_green: led@20 {
reg = <20>;
active-low;
label = "green:power";
};
};
&nflash {
status = "okay";
nandcs@0 {
compatible = "brcm,nandcs";
#size-cells = <1>;
#address-cells = <1>;
reg = <0>;
nand-ecc-step-size = <512>;
nand-ecc-strength = <15>;
nand-on-flash-bbt;
brcm,nand-oob-sector-size = <64>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
cferom: partition@0 {
label = "cferom";
reg = <0x0000000 0x0020000>;
read-only;
};
partition@20000 {
compatible = "brcm,wfi-split";
label = "wfi";
reg = <0x0020000 0x7ac0000>;
};
};
};
};
&ohci {
status = "okay";
};
&uart0 {
status = "okay";
};
&usbh {
status = "okay";
};

View File

@ -0,0 +1,182 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "bcm6318.dtsi"
/ {
model = "Comtrend AR-5315u";
compatible = "comtrend,ar-5315u", "brcm,bcm6318";
aliases {
led-boot = &led_power_green;
led-failsafe = &led_power_green;
led-running = &led_power_green;
led-upgrade = &led_power_green;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x04000000>;
};
keys {
compatible = "gpio-keys-polled";
poll-interval = <20>;
wps {
label = "wps";
gpios = <&pinctrl 3 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;
debounce-interval = <60>;
};
reset {
label = "reset";
gpios = <&pinctrl 33 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
debounce-interval = <60>;
};
};
};
&ehci {
status = "okay";
};
&hsspi {
status = "okay";
flash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <62500000>;
spi-tx-bus-width = <2>;
spi-rx-bus-width = <2>;
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
cfe: partition@0 {
reg = <0x000000 0x010000>;
label = "cfe";
read-only;
};
partition@10000 {
compatible = "brcm,bcm963xx-imagetag";
reg = <0x010000 0xfe0000>;
label = "firmware";
};
partition@ff0000 {
reg = <0xff0000 0x010000>;
label = "nvram";
};
};
};
};
&leds {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_leds
&pinctrl_ephy0_act_led &pinctrl_ephy1_act_led
&pinctrl_ephy2_act_led &pinctrl_ephy3_act_led>;
led@0 {
reg = <0>;
active-low;
label = "green:wps";
};
led_power_green: led@1 {
reg = <1>;
active-low;
label = "green:power";
};
led@2 {
reg = <2>;
active-low;
label = "green:usb";
};
led@4 {
reg = <4>;
brcm,hardware-controlled;
brcm,link-signal-sources = <4>;
/* EPHY0 Act */
};
led@5 {
reg = <5>;
brcm,hardware-controlled;
brcm,link-signal-sources = <5>;
/* EPHY1 Act */
};
led@6 {
reg = <6>;
brcm,hardware-controlled;
brcm,link-signal-sources = <6>;
/* EPHY2 Act */
};
led@7 {
reg = <7>;
brcm,hardware-controlled;
brcm,link-signal-sources = <7>;
/* EPHY3 Act */
};
led@8 {
reg = <8>;
active-low;
label = "green:internet";
};
led@9 {
reg = <9>;
active-low;
label = "red:internet";
};
led@10 {
reg = <10>;
active-low;
label = "green:dsl";
};
led@11 {
reg = <11>;
active-low;
label = "red:power";
};
};
&ohci {
status = "okay";
};
&pinctrl {
pinctrl_leds: leds {
function = "led";
pins = "gpio0", "gpio1",
"gpio2", "gpio8",
"gpio9", "gpio10",
"gpio11";
};
};
&uart0 {
status = "okay";
};
&usbh {
status = "okay";
};

View File

@ -0,0 +1,350 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
#include <dt-bindings/clock/bcm6318-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/bcm6318-interrupt-controller.h>
#include <dt-bindings/reset/bcm6318-reset.h>
#include <dt-bindings/soc/bcm6318-pm.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm6318";
aliases {
pinctrl = &pinctrl;
serial0 = &uart0;
spi1 = &hsspi;
};
chosen {
bootargs = "console=ttyS0,115200n8 earlycon";
stdout-path = "serial0:115200n8";
};
clocks {
periph_osc: periph-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "periph";
};
hsspi_osc: hsspi-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <250000000>;
clock-output-names = "hsspi_osc";
};
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
mips-hpt-frequency = <166500000>;
cpu@0 {
compatible = "brcm,bmips3300", "mips,mips4Kc";
device_type = "cpu";
reg = <0>;
};
};
cpu_intc: interrupt-controller {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
memory@0 {
device_type = "memory";
reg = <0 0>;
};
ubus {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
periph_clk: clock-controller@10000004 {
compatible = "brcm,bcm6318-clocks";
reg = <0x10000004 0x4>;
#clock-cells = <1>;
};
ubus_clk: clock-controller@10000008 {
compatible = "brcm,bcm6318-ubus-clocks";
reg = <0x10000008 0x4>;
#clock-cells = <1>;
};
periph_rst: reset-controller@10000010 {
compatible = "brcm,bcm6345-reset";
reg = <0x10000010 0x4>;
#reset-cells = <1>;
};
ext_intc: interrupt-controller@10000018 {
#address-cells = <1>;
compatible = "brcm,bcm6318-ext-intc";
reg = <0x10000018 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6318_IRQ_EXT0>,
<BCM6318_IRQ_EXT1>,
<BCM6318_IRQ_EXT2>,
<BCM6318_IRQ_EXT3>;
};
periph_intc: interrupt-controller@10000020 {
#address-cells = <1>;
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x20>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <2>, <3>;
};
wdt: watchdog@10000068 {
compatible = "brcm,bcm7038-wdt";
reg = <0x10000068 0xc>;
clocks = <&periph_osc>;
timeout-sec = <30>;
};
pll_cntl: syscon@10000074 {
compatible = "syscon";
reg = <0x10000074 0x4>;
native-endian;
};
syscon-reboot {
compatible = "syscon-reboot";
regmap = <&pll_cntl>;
offset = <0>;
mask = <0x1>;
};
pinctrl: pin-controller@10000080 {
compatible = "brcm,bcm6318-pinctrl";
reg = <0x10000080 0x08>,
<0x10000088 0x08>,
<0x10000098 0x04>,
<0x1000009c 0x0c>,
<0x100000d4 0x18>;
reg-names = "dirout", "dat", "mode", "mux", "pad";
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&ext_intc>;
interrupts = <0 0>, <1 0>;
interrupt-names = "gpio33", "gpio34";
pinctrl_ephy0_spd_led: ephy0_spd_led {
function = "ephy0_spd_led";
pins = "gpio0";
};
pinctrl_ephy1_spd_led: ephy1_spd_led {
function = "ephy1_spd_led";
pins = "gpio1";
};
pinctrl_ephy2_spd_led: ephy2_spd_led {
function = "ephy2_spd_led";
pins = "gpio2";
};
pinctrl_ephy3_spd_led: ephy3_spd_led {
function = "ephy3_spd_led";
pins = "gpio3";
};
pinctrl_ephy0_act_led: ephy0_act_led {
function = "ephy0_act_led";
pins = "gpio4";
};
pinctrl_ephy1_act_led: ephy1_act_led {
function = "ephy1_act_led";
pins = "gpio5";
};
pinctrl_ephy2_act_led: ephy2_act_led {
function = "ephy2_act_led";
pins = "gpio6";
};
pinctrl_ephy3_act_led: ephy3_act_led {
function = "ephy3_act_led";
pins = "gpio7";
};
pinctrl_serial_led: serial_led {
pinctrl_serial_led_data: serial_led_data {
function = "serial_led_data";
pins = "gpio6";
};
pinctrl_serial_led_clk: serial_led_clk {
function = "serial_led_clk";
pins = "gpio7";
};
};
pinctrl_inet_act_led: inet_act_led {
function = "inet_act_led";
pins = "gpio8";
};
pinctrl_inet_fail_led: inet_fail_led {
function = "inet_fail_led";
pins = "gpio9";
};
pinctrl_dsl_led: dsl_led {
function = "dsl_led";
pins = "gpio10";
};
pinctrl_post_fail_led: post_fail_led {
function = "post_fail_led";
pins = "gpio11";
};
pinctrl_wlan_wps_led: wlan_wps_led {
function = "wlan_wps_led";
pins = "gpio12";
};
pinctrl_usb_pwron: usb_pwron {
function = "usb_pwron";
pins = "gpio13";
};
pinctrl_usb_device_led: usb_device_led {
function = "usb_device_led";
pins = "gpio13";
};
pinctrl_usb_active: usb_active {
function = "usb_active";
pins = "gpio40";
};
};
uart0: serial@10000100 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000100 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6318_IRQ_UART0>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
leds: led-controller@10000200 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6328-leds";
reg = <0x10000200 0x24>;
status = "disabled";
};
periph_pwr: power-controller@100008e8 {
compatible = "brcm,bcm6318-power-controller";
reg = <0x100008e8 0x4>;
#power-domain-cells = <1>;
};
hsspi: spi@10003000 {
compatible = "brcm,bcm6328-hsspi";
reg = <0x10003000 0x600>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6318_IRQ_HSSPI>;
clocks = <&periph_clk BCM6318_CLK_HSSPI>,
<&hsspi_osc>;
clock-names = "hsspi",
"pll";
resets = <&periph_rst BCM6318_RST_SPI>;
status = "disabled";
};
ehci: usb@10005000 {
compatible = "brcm,bcm6318-ehci", "generic-ehci";
reg = <0x10005000 0x100>;
big-endian;
ignore-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6318_IRQ_EHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
ohci: usb@10005100 {
compatible = "brcm,bcm6318-ohci", "generic-ohci";
reg = <0x10005100 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6318_IRQ_OHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
usbh: usb-phy@10005200 {
compatible = "brcm,bcm6318-usbh-phy";
reg = <0x10005200 0x38>;
#phy-cells = <1>;
clocks = <&periph_clk BCM6318_CLK_USBD>,
<&ubus_clk BCM6318_UCLK_USB>;
clock-names = "usbh",
"usb_ref";
power-domains = <&periph_pwr BCM6318_POWER_DOMAIN_USB>;
resets = <&periph_rst BCM6318_RST_USBH>;
status = "disabled";
};
};
};

View File

@ -0,0 +1,427 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
#include <dt-bindings/clock/bcm63268-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/bcm63268-interrupt-controller.h>
#include <dt-bindings/reset/bcm63268-reset.h>
#include <dt-bindings/soc/bcm63268-pm.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm63268";
aliases {
nflash = &nflash;
pinctrl = &pinctrl;
serial0 = &uart0;
serial1 = &uart1;
spi0 = &lsspi;
spi1 = &hsspi;
};
chosen {
bootargs = "console=ttyS0,115200n8 earlycon";
stdout-path = "serial0:115200n8";
};
clocks {
periph_osc: periph-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "periph";
};
hsspi_osc: hsspi-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <400000000>;
clock-output-names = "hsspi_osc";
};
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
mips-hpt-frequency = <200000000>;
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <0>;
};
cpu@1 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <1>;
};
};
cpu_intc: interrupt-controller {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
memory@0 {
device_type = "memory";
reg = <0 0>;
};
ubus {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
periph_clk: clock-controller@10000004 {
compatible = "brcm,bcm63268-clocks";
reg = <0x10000004 0x4>;
#clock-cells = <1>;
};
pll_cntl: syscon@10000008 {
compatible = "syscon";
reg = <0x10000008 0x4>;
native-endian;
};
syscon-reboot {
compatible = "syscon-reboot";
regmap = <&pll_cntl>;
offset = <0x0>;
mask = <0x1>;
};
periph_rst: reset-controller@10000010 {
compatible = "brcm,bcm6345-reset";
reg = <0x10000010 0x4>;
#reset-cells = <1>;
};
ext_intc: interrupt-controller@10000018 {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0x10000018 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM63268_IRQ_EXT0>,
<BCM63268_IRQ_EXT1>,
<BCM63268_IRQ_EXT2>,
<BCM63268_IRQ_EXT3>;
};
periph_intc: interrupt-controller@10000020 {
#address-cells = <1>;
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x20>,
<0x10000040 0x20>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <2>, <3>;
};
wdt: watchdog@1000009c {
compatible = "brcm,bcm7038-wdt";
reg = <0x1000009c 0xc>;
clocks = <&periph_osc>;
timeout-sec = <30>;
};
pinctrl: pin-controller@100000c0 {
compatible = "brcm,bcm63268-pinctrl";
reg = <0x100000c0 0x8>,
<0x100000c8 0x8>,
<0x100000d0 0x4>,
<0x100000d8 0x4>,
<0x100000dc 0x4>,
<0x100000f8 0x4>;
reg-names = "dirout", "dat", "led", "mode",
"ctrl", "basemode";
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&ext_intc>;
interrupts = <0 0>, <1 0>, <2 0>, <3 0>;
interrupt-names = "gpio32", "gpio33", "gpio34", "gpio35";
pinctrl_serial_led: serial_led {
pinctrl_serial_led_clk: serial_led_clk {
function = "serial_led_clk";
pins = "gpio0";
};
pinctrl_serial_led_data: serial_led_data {
function = "serial_led_data";
pins = "gpio1";
};
};
pinctrl_hsspi_cs4: hsspi_cs4 {
function = "hsspi_cs4";
pins = "gpio16";
};
pinctrl_hsspi_cs5: hsspi_cs5 {
function = "hsspi_cs5";
pins = "gpio17";
};
pinctrl_hsspi_cs6: hsspi_cs6 {
function = "hsspi_cs6";
pins = "gpio8";
};
pinctrl_hsspi_cs7: hsspi_cs7 {
function = "hsspi_cs7";
pins = "gpio9";
};
pinctrl_adsl_spi: adsl_spi {
pinctrl_adsl_spi_miso: adsl_spi_miso {
function = "adsl_spi_miso";
pins = "gpio18";
};
pinctrl_adsl_spi_mosi: adsl_spi_mosi {
function = "adsl_spi_mosi";
pins = "gpio19";
};
};
pinctrl_vreq_clk: vreq_clk {
function = "vreq_clk";
pins = "gpio22";
};
pinctrl_pcie_clkreq_b: pcie_clkreq_b {
function = "pcie_clkreq_b";
pins = "gpio23";
};
pinctrl_robosw_led_clk: robosw_led_clk {
function = "robosw_led_clk";
pins = "gpio30";
};
pinctrl_robosw_led_data: robosw_led_data {
function = "robosw_led_data";
pins = "gpio31";
};
pinctrl_nand: nand {
function = "nand";
group = "nand_grp";
};
pinctrl_gpio35_alt: gpio35_alt {
function = "gpio35_alt";
pin = "gpio35";
};
pinctrl_dectpd: dectpd {
function = "dectpd";
group = "dectpd_grp";
};
pinctrl_vdsl_phy_override_0: vdsl_phy_override_0 {
function = "vdsl_phy_override_0";
group = "vdsl_phy_override_0_grp";
};
pinctrl_vdsl_phy_override_1: vdsl_phy_override_1 {
function = "vdsl_phy_override_1";
group = "vdsl_phy_override_1_grp";
};
pinctrl_vdsl_phy_override_2: vdsl_phy_override_2 {
function = "vdsl_phy_override_2";
group = "vdsl_phy_override_2_grp";
};
pinctrl_vdsl_phy_override_3: vdsl_phy_override_3 {
function = "vdsl_phy_override_3";
group = "vdsl_phy_override_3_grp";
};
pinctrl_dsl_gpio8: dsl_gpio8 {
function = "dsl_gpio8";
group = "dsl_gpio8";
};
pinctrl_dsl_gpio9: dsl_gpio9 {
function = "dsl_gpio9";
group = "dsl_gpio9";
};
};
uart0: serial@10000180 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000180 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_UART0>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
uart1: serial@100001a0 {
compatible = "brcm,bcm6345-uart";
reg = <0x100001a0 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_UART1>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
nflash: nand@10000200 {
compatible = "brcm,nand-bcm6368",
"brcm,brcmnand-v4.0",
"brcm,brcmnand";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x10000200 0x180>,
<0x10000600 0x200>,
<0x100000b0 0x10>;
reg-names = "nand",
"nand-cache",
"nand-int-base";
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_NAND>;
clocks = <&periph_clk BCM63268_CLK_NAND>;
clock-names = "nand";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
status = "disabled";
};
lsspi: spi@10000800 {
compatible = "brcm,bcm6358-spi";
reg = <0x10000800 0x70c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_LSSPI>;
clocks = <&periph_clk BCM63268_CLK_SPI>;
clock-names = "spi";
resets = <&periph_rst BCM63268_RST_SPI>;
status = "disabled";
};
hsspi: spi@10001000 {
compatible = "brcm,bcm6328-hsspi";
reg = <0x10001000 0x600>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_HSSPI>;
clocks = <&periph_clk BCM63268_CLK_HSSPI>,
<&hsspi_osc>;
clock-names = "hsspi",
"pll";
resets = <&periph_rst BCM63268_RST_SPI>;
status = "disabled";
};
periph_pwr: power-controller@1000184c {
compatible = "brcm,bcm63268-power-controller";
reg = <0x1000184c 0x4>;
#power-domain-cells = <1>;
};
leds: led-controller@10001900 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6328-leds";
reg = <0x10001900 0x24>;
status = "disabled";
};
ehci: usb@10002500 {
compatible = "brcm,bcm63268-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
big-endian;
ignore-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_EHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
ohci: usb@10002600 {
compatible = "brcm,bcm63268-ohci", "generic-ohci";
reg = <0x10002600 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <BCM63268_IRQ_OHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
usbh: usb-phy@10002700 {
compatible = "brcm,bcm63268-usbh-phy";
reg = <0x10002700 0x38>;
#phy-cells = <1>;
clocks = <&periph_clk BCM63268_CLK_USBH>;
/* FIXME! <&timer_clk BCM63268_TCLK_USB_REF> */
clock-names = "usbh";
/* FIXME! usb_ref */
power-domains = <&periph_pwr BCM63268_POWER_DOMAIN_USBH>;
resets = <&periph_rst BCM63268_RST_USBH>;
status = "disabled";
};
};
};

View File

@ -0,0 +1,127 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "bcm6328.dtsi"
/ {
model = "Comtrend AR-5387un";
compatible = "comtrend,ar-5387un", "brcm,bcm6328";
aliases {
led-boot = &led_power_green;
led-failsafe = &led_power_green;
led-running = &led_power_green;
led-upgrade = &led_power_green;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x04000000>;
};
keys {
compatible = "gpio-keys-polled";
poll-interval = <20>;
reset {
label = "reset";
gpios = <&pinctrl 23 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
debounce-interval = <60>;
};
};
};
&ehci {
status = "okay";
};
&hsspi {
status = "okay";
flash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <16666667>;
spi-tx-bus-width = <2>;
spi-rx-bus-width = <2>;
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
cfe: partition@0 {
reg = <0x000000 0x010000>;
label = "cfe";
read-only;
};
partition@10000 {
compatible = "brcm,bcm963xx-imagetag";
reg = <0x010000 0xfe0000>;
label = "firmware";
};
partition@ff0000 {
reg = <0xff0000 0x010000>;
label = "nvram";
};
};
};
};
&leds {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_leds>;
led@1 {
reg = <1>;
label = "red:internet";
};
led@4 {
reg = <4>;
label = "red:power";
};
led@7 {
reg = <7>;
label = "green:internet";
};
led_power_green: led@8 {
reg = <8>;
label = "green:power";
};
led@11 {
reg = <11>;
active-low;
label = "green:dsl";
};
};
&ohci {
status = "okay";
};
&pinctrl {
pinctrl_leds: leds {
function = "led";
pins = "gpio1", "gpio4", "gpio7",
"gpio8", "gpio11";
};
};
&uart0 {
status = "okay";
};
&usbh {
status = "okay";
};

View File

@ -0,0 +1,368 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
#include <dt-bindings/clock/bcm6328-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/bcm6328-interrupt-controller.h>
#include <dt-bindings/reset/bcm6328-reset.h>
#include <dt-bindings/soc/bcm6328-pm.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm6328";
aliases {
nflash = &nflash;
pinctrl = &pinctrl;
serial0 = &uart0;
serial1 = &uart1;
spi1 = &hsspi;
};
chosen {
bootargs = "console=ttyS0,115200n8 earlycon";
stdout-path = "serial0:115200n8";
};
clocks {
periph_osc: periph-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "periph";
};
hsspi_osc: hsspi-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <133333333>;
clock-output-names = "hsspi_osc";
};
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
mips-hpt-frequency = <160000000>;
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <0>;
};
cpu@1 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <1>;
};
};
cpu_intc: interrupt-controller {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
memory@0 {
device_type = "memory";
reg = <0 0>;
};
ubus {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
periph_clk: clock-controller@10000004 {
compatible = "brcm,bcm6328-clocks";
reg = <0x10000004 0x4>;
#clock-cells = <1>;
};
periph_rst: reset-controller@10000010 {
compatible = "brcm,bcm6345-reset";
reg = <0x10000010 0x4>;
#reset-cells = <1>;
};
ext_intc: interrupt-controller@10000018 {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0x10000018 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6328_IRQ_EXTO>,
<BCM6328_IRQ_EXT1>,
<BCM6328_IRQ_EXT2>,
<BCM6328_IRQ_EXT3>;
};
periph_intc: interrupt-controller@10000020 {
#address-cells = <1>;
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x10>,
<0x10000030 0x10>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <2>, <3>;
};
wdt: watchdog@1000005c {
compatible = "brcm,bcm7038-wdt";
reg = <0x1000005c 0xc>;
clocks = <&periph_osc>;
timeout-sec = <30>;
};
pll_cntl: syscon@10000068 {
compatible = "syscon";
reg = <0x10000068 0x4>;
native-endian;
};
syscon-reboot {
compatible = "syscon-reboot";
regmap = <&pll_cntl>;
offset = <0>;
mask = <0x1>;
};
pinctrl: pin-controller@10000080 {
compatible = "brcm,bcm6328-pinctrl";
reg = <0x10000080 0x8>,
<0x10000088 0x8>,
<0x10000098 0x4>,
<0x1000009c 0xc>;
reg-names = "dirout", "dat", "mode", "mux";
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&ext_intc>;
interrupts = <3 0>, <2 0>, <0 0>, <1 0>;
interrupt-names = "gpio12", "gpio15",
"gpio23", "gpio24";
pinctrl_serial_led: serial_led {
pinctrl_serial_led_data: serial_led_data {
function = "serial_led_data";
pins = "gpio6";
};
pinctrl_serial_led_clk: serial_led_clk {
function = "serial_led_clk";
pins = "gpio7";
};
};
pinctrl_inet_act_led: inet_act_led {
function = "inet_act_led";
pins = "gpio11";
};
pinctrl_pcie_clkreq: pcie_clkreq {
function = "pcie_clkreq";
pins = "gpio16";
};
pinctrl_ephy0_spd_led: ephy0_spd_led {
function = "led";
pins = "gpio17";
};
pinctrl_ephy1_spd_led: ephy1_spd_led {
function = "led";
pins = "gpio18";
};
pinctrl_ephy2_spd_led: ephy2_spd_led {
function = "led";
pins = "gpio19";
};
pinctrl_ephy3_spd_led: ephy3_spd_led {
function = "led";
pins = "gpio20";
};
pinctrl_ephy0_act_led: ephy0_act_led {
function = "ephy0_act_led";
pins = "gpio25";
};
pinctrl_ephy1_act_led: ephy1_act_led {
function = "ephy1_act_led";
pins = "gpio26";
};
pinctrl_ephy2_act_led: ephy2_act_led {
function = "ephy2_act_led";
pins = "gpio27";
};
pinctrl_ephy3_act_led: ephy3_act_led {
function = "ephy3_act_led";
pins = "gpio28";
};
pinctrl_hsspi_cs1: hsspi_cs1 {
function = "hsspi_cs1";
pins = "hsspi_cs1";
};
pinctrl_usb_port1_device: usb_port1_device {
function = "usb_device_port";
pins = "usb_port1";
};
pinctrl_usb_port1_host: usb_port1_host {
function = "usb_host_port";
pins = "usb_port1";
};
};
uart0: serial@10000100 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000100 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_UART0>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
uart1: serial@10000120 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000120 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_UART1>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
nflash: nand@10000200 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,nand-bcm6368",
"brcm,brcmnand-v2.2",
"brcm,brcmnand";
reg = <0x10000200 0x180>,
<0x10000400 0x200>,
<0x10000070 0x10>;
reg-names = "nand",
"nand-cache",
"nand-int-base";
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_NAND>;
status = "disabled";
};
leds: led-controller@10000800 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6328-leds";
reg = <0x10000800 0x24>;
status = "disabled";
};
hsspi: spi@10001000 {
compatible = "brcm,bcm6328-hsspi";
reg = <0x10001000 0x600>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_HSSPI>;
clocks = <&periph_clk BCM6328_CLK_HSSPI>,
<&hsspi_osc>;
clock-names = "hsspi",
"pll";
resets = <&periph_rst BCM6328_RST_SPI>;
status = "disabled";
};
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6328-power-controller";
reg = <0x10001848 0x4>;
#power-domain-cells = <1>;
};
ehci: usb@10002500 {
compatible = "brcm,bcm6328-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
big-endian;
ignore-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_EHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
ohci: usb@10002600 {
compatible = "brcm,bcm6328-ohci", "generic-ohci";
reg = <0x10002600 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6328_IRQ_OHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
usbh: usb-phy@10002700 {
compatible = "brcm,bcm6328-usbh-phy";
reg = <0x10002700 0x38>;
#phy-cells = <1>;
clocks = <&periph_clk BCM6328_CLK_USBH>;
clock-names = "usbh";
power-domains = <&periph_pwr BCM6328_POWER_DOMAIN_USBH>;
resets = <&periph_rst BCM6328_RST_USBH>;
status = "disabled";
};
};
};

View File

@ -0,0 +1,168 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "bcm6358.dtsi"
/ {
compatible = "huawei,hg556a-b", "brcm,bcm6358";
model = "Huawei EchoLife HG556a (version B)";
aliases {
led-boot = &power_red;
led-failsafe = &power_red;
led-running = &power_red;
led-upgrade = &power_red;
led-dsl = &dsl_red;
led-internet = &dsl_red;
led-usb = &hspa_red;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x04000000>;
};
keys {
compatible = "gpio-keys-polled";
poll-interval = <20>;
help {
label = "help";
gpios = <&pinctrl 8 GPIO_ACTIVE_LOW>;
linux,code = <KEY_HELP>;
debounce-interval = <60>;
};
wlan {
label = "wlan";
gpios = <&pinctrl 9 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WLAN>;
debounce-interval = <60>;
};
restart {
label = "restart";
gpios = <&pinctrl 10 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
debounce-interval = <60>;
};
reset {
label = "reset";
gpios = <&pinctrl 11 GPIO_ACTIVE_LOW>;
linux,code = <KEY_CONFIG>;
debounce-interval = <60>;
};
};
leds {
compatible = "gpio-leds";
led@0 {
label = "red:message";
gpios = <&pinctrl 0 GPIO_ACTIVE_LOW>;
};
hspa_red: led@1 {
label = "red:hspa";
gpios = <&pinctrl 1 GPIO_ACTIVE_LOW>;
};
dsl_red: led@2 {
label = "red:dsl";
gpios = <&pinctrl 2 GPIO_ACTIVE_LOW>;
};
power_red: led@3 {
label = "red:power";
gpios = <&pinctrl 3 GPIO_ACTIVE_LOW>;
};
led@6 {
label = "all";
gpios = <&pinctrl 6 GPIO_ACTIVE_LOW>;
default-state = "on";
};
led@12 {
label = "green:lan1";
gpios = <&pinctrl 12 GPIO_ACTIVE_LOW>;
};
led@13 {
label = "red:lan1";
gpios = <&pinctrl 13 GPIO_ACTIVE_LOW>;
};
led@15 {
label = "green:lan2";
gpios = <&pinctrl 15 GPIO_ACTIVE_LOW>;
};
led@22 {
label = "red:lan2";
gpios = <&pinctrl 22 GPIO_ACTIVE_LOW>;
};
led@23 {
label = "green:lan3";
gpios = <&pinctrl 23 GPIO_ACTIVE_LOW>;
};
led@26 {
label = "red:lan3";
gpios = <&pinctrl 26 GPIO_ACTIVE_LOW>;
};
led@27 {
label = "green:lan4";
gpios = <&pinctrl 27 GPIO_ACTIVE_LOW>;
};
led@28 {
label = "red:lan4";
gpios = <&pinctrl 28 GPIO_ACTIVE_LOW>;
};
};
};
&pflash {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
cfe: partition@0 {
label = "cfe";
reg = <0x000000 0x020000>;
read-only;
};
partition@20000 {
label = "firmware";
reg = <0x020000 0xec0000>;
compatible = "brcm,bcm963xx-imagetag";
};
cal_data: partition@ee0000 {
label = "cal_data";
reg = <0xee0000 0x100000>;
read-only;
};
partition@fe0000 {
label = "nvram";
reg = <0xfe0000 0x020000>;
};
};
};
&uart0 {
status = "okay";
};
&usbh {
status = "okay";
};

View File

@ -0,0 +1,315 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
#include <dt-bindings/clock/bcm6358-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/bcm6358-interrupt-controller.h>
#include <dt-bindings/reset/bcm6358-reset.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm6358";
aliases {
pflash = &pflash;
pinctrl = &pinctrl;
serial0 = &uart0;
serial1 = &uart1;
spi0 = &lsspi;
};
chosen {
bootargs = "console=ttyS0,115200n8 earlycon";
stdout-path = "serial0:115200n8";
};
clocks {
periph_osc: periph-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "periph";
};
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
mips-hpt-frequency = <150000000>;
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <0>;
};
cpu@1 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <1>;
};
};
cpu_intc: interrupt-controller {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
memory@0 {
device_type = "memory";
reg = <0 0>;
};
pflash: nor@1e000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x1e000000 0x2000000>;
bank-width = <2>;
status = "disabled";
};
ubus {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
periph_clk: clock-controller@fffe0004 {
compatible = "brcm,bcm6358-clocks";
reg = <0xfffe0004 0x4>;
#clock-cells = <1>;
};
pll_cntl: syscon@fffe0008 {
compatible = "syscon";
reg = <0xfffe0008 0x4>;
native-endian;
};
syscon-reboot {
compatible = "syscon-reboot";
regmap = <&pll_cntl>;
offset = <0x0>;
mask = <0x1>;
};
periph_intc: interrupt-controller@fffe000c {
#address-cells = <1>;
compatible = "brcm,bcm6345-l1-intc";
reg = <0xfffe000c 0x8>,
<0xfffe0038 0x8>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <2>, <3>;
};
ext_intc0: interrupt-controller@fffe0014 {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0xfffe0014 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6358_IRQ_EXT0>,
<BCM6358_IRQ_EXT1>,
<BCM6358_IRQ_EXT2>,
<BCM6358_IRQ_EXT3>;
};
ext_intc1: interrupt-controller@fffe001c {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0xfffe001c 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6358_IRQ_EXT4>,
<BCM6358_IRQ_EXT5>;
};
periph_rst: reset-controller@fffe0034 {
compatible = "brcm,bcm6345-reset";
reg = <0xfffe0034 0x4>;
#reset-cells = <1>;
};
pinctrl: pin-controller@fffe0080 {
compatible = "brcm,bcm6358-pinctrl";
reg = <0xfffe0080 0x8>,
<0xfffe0088 0x8>;
reg-names = "dirout", "dat", "mode";
brcm,gpiomode = <&gpiomode>;
gpio-controller;
#gpio-cells = <2>;
interrupts-extended = <&ext_intc1 0 0>,
<&ext_intc1 1 0>,
<&ext_intc0 0 0>,
<&ext_intc0 1 0>,
<&ext_intc0 2 0>,
<&ext_intc0 3 0>;
interrupt-names = "gpio32", "gpio33", "gpio34", "gpio35",
"gpio36", "gpio37";
pinctrl_ebi_cs: ebi_cs {
function = "ebi_cs";
groups = "ebi_cs_grp";
};
pinctrl_uart1: uart1 {
function = "uart1";
groups = "uart1_grp";
};
pinctrl_serial_led: serial_led {
function = "serial_led";
groups = "serial_led_grp";
};
pinctrl_legacy_led: legacy_led {
function = "legacy_led";
groups = "legacy_led_grp";
};
pinctrl_led: led {
function = "led";
groups = "led_grp";
};
pinctrl_spi_cs_23: spi_cs {
function = "spi_cs";
groups = "spi_cs_grp";
};
pinctrl_utopia: utopia {
function = "utopia";
groups = "utopia_grp";
};
pinctrl_pwm_syn_clk: pwm_syn_clk {
function = "pwm_syn_clk";
groups = "pwm_syn_clk_grp";
};
pinctrl_sys_irq: sys_irq {
function = "sys_irq";
groups = "sys_irq_grp";
};
};
gpiomode: gpiomode@fffe0098 {
compatible = "brcm,bcm6358-gpiomode", "syscon";
reg = <0xfffe0098 0x4>;
};
leds: led-controller@fffe00d0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6358-leds";
reg = <0xfffe00d0 0x8>;
status = "disabled";
};
uart0: serial@fffe0100 {
compatible = "brcm,bcm6345-uart";
reg = <0xfffe0100 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_UART0>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
uart1: serial@fffe0120 {
compatible = "brcm,bcm6345-uart";
reg = <0xfffe0120 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_UART1>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
lsspi: spi@fffe0800 {
compatible = "brcm,bcm6358-spi";
reg = <0xfffe0800 0x70c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_SPI>;
clocks = <&periph_clk BCM6358_CLK_SPI>;
clock-names = "spi";
resets = <&periph_rst BCM6358_RST_SPI>;
status = "disabled";
};
ehci: usb@fffe1300 {
compatible = "brcm,bcm6358-ehci", "generic-ehci";
reg = <0xfffe1300 0x100>;
big-endian;
ignore-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_EHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
ohci: usb@fffe1400 {
compatible = "brcm,bcm6358-ohci", "generic-ohci";
reg = <0xfffe1400 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6358_IRQ_OHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
usbh: usb-phy@fffe1500 {
compatible = "brcm,bcm6358-usbh-phy";
reg = <0xfffe1500 0x38>;
#phy-cells = <1>;
resets = <&periph_rst BCM6358_RST_USBH>;
status = "disabled";
};
};
};

View File

@ -0,0 +1,226 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "bcm6362.dtsi"
/ {
model = "Netgear DGND3700 v2";
compatible = "netgear,dgnd3700-v2", "brcm,bcm6362";
aliases {
led-boot = &led_power_green;
led-failsafe = &led_power_green;
led-running = &led_power_green;
led-upgrade = &led_power_green;
led-ethernet = &led_ethernet_green;
led-usb = &led_usb1_green;
led-usb2 = &led_usb2_green;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x04000000>;
};
keys {
compatible = "gpio-keys-polled";
poll-interval = <20>;
reset {
label = "reset";
gpios = <&pinctrl 24 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
debounce-interval = <60>;
};
wlan {
label = "wlan";
gpios = <&pinctrl 25 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WLAN>;
debounce-interval = <60>;
};
wps {
label = "wps";
gpios = <&pinctrl 26 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;
debounce-interval = <60>;
};
};
leds {
compatible = "gpio-leds";
led@28 {
label = "green:dsl";
gpios = <&pinctrl 28 GPIO_ACTIVE_LOW>;
};
led@34 {
label = "red:power";
gpios = <&pinctrl 34 GPIO_ACTIVE_LOW>;
};
};
};
&ehci {
status = "okay";
};
&leds {
status = "okay";
brcm,serial-leds;
brcm,serial-dat-low;
brcm,serial-shift-inv;
brcm,serial-mux;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_leds &pinctrl_serial_led>;
led@1 {
reg = <1>;
active-low;
label = "green:internet";
};
led_power_green: led@8 {
reg = <8>;
label = "green:power";
};
led@9 {
reg = <9>;
active-low;
label = "green:wps";
};
led@10 {
reg = <10>;
active-low;
label = "green:usb1";
};
led@11 {
reg = <11>;
active-low;
label = "green:usb2";
};
led@12 {
reg = <12>;
active-low;
label = "amber:internet";
};
led_ethernet_green: led@13 {
reg = <13>;
active-low;
label = "green:ethernet";
};
led@14 {
reg = <14>;
active-low;
label = "amber:dsl";
};
led_usb1_green: led@16 {
reg = <16>;
active-low;
label = "amber:usb1";
};
led_usb2_green: led@17 {
reg = <17>;
active-low;
label = "amber:usb2";
};
led@18 {
reg = <18>;
active-low;
label = "amber:ethernet";
};
};
&nflash {
status = "okay";
nandcs@0 {
compatible = "brcm,nandcs";
#size-cells = <1>;
#address-cells = <1>;
reg = <0>;
nand-ecc-step-size = <512>;
nand-ecc-strength = <15>;
nand-on-flash-bbt;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
cferom: partition@0 {
label = "cferom";
reg = <0x0000000 0x0004000>;
read-only;
};
partition@4000 {
compatible = "brcm,wfi";
label = "wfi";
reg = <0x0004000 0x1c7c000>;
};
partition@1c80000 {
label = "flag";
reg = <0x1c80000 0x0040000>;
read-only;
};
partition@1cc0000 {
label = "pcbasn";
reg = <0x1cc0000 0x0040000>;
read-only;
};
partition@1d00000 {
label = "xxx";
reg = <0x1d00000 0x0080000>;
read-only;
};
partition@1d80000 {
label = "language_dev";
reg = <0x1d80000 0x0040000>;
read-only;
};
partition@1dc0000 {
label = "scnvram";
reg = <0x1dc0000 0x0100000>;
read-only;
};
};
};
};
&ohci {
status = "okay";
};
&pinctrl {
pinctrl_leds: leds {
function = "led";
pins = "gpio1";
};
};
&uart0 {
status = "okay";
};
&usbh {
status = "okay";
};

View File

@ -0,0 +1,468 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
#include <dt-bindings/clock/bcm6362-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/bcm6362-interrupt-controller.h>
#include <dt-bindings/reset/bcm6362-reset.h>
#include <dt-bindings/soc/bcm6362-pm.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm6362";
aliases {
nflash = &nflash;
pinctrl = &pinctrl;
serial0 = &uart0;
serial1 = &uart1;
spi0 = &lsspi;
spi1 = &hsspi;
};
chosen {
bootargs = "console=ttyS0,115200n8 earlycon";
stdout-path = "serial0:115200n8";
};
clocks {
periph_osc: periph-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "periph";
};
hsspi_osc: hsspi-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <400000000>;
clock-output-names = "hsspi_osc";
};
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
mips-hpt-frequency = <200000000>;
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <0>;
};
cpu@1 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <1>;
};
};
cpu_intc: interrupt-controller {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
memory@0 {
device_type = "memory";
reg = <0 0>;
};
ubus {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
periph_clk: clock-controller@10000004 {
compatible = "brcm,bcm6362-clocks";
reg = <0x10000004 0x4>;
#clock-cells = <1>;
};
pll_cntl: syscon@10000008 {
compatible = "syscon";
reg = <0x10000008 0x4>;
native-endian;
};
syscon-reboot {
compatible = "syscon-reboot";
regmap = <&pll_cntl>;
offset = <0x0>;
mask = <0x1>;
};
periph_rst: reset-controller@10000010 {
compatible = "brcm,bcm6345-reset";
reg = <0x10000010 0x4>;
#reset-cells = <1>;
};
ext_intc: interrupt-controller@10000018 {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0x10000018 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6362_IRQ_EXT0>,
<BCM6362_IRQ_EXT1>,
<BCM6362_IRQ_EXT2>,
<BCM6362_IRQ_EXT3>;
};
periph_intc: interrupt-controller@10000020 {
#address-cells = <1>;
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x10>,
<0x10000030 0x10>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <2>, <3>;
};
wdt: watchdog@1000005c {
compatible = "brcm,bcm7038-wdt";
reg = <0x1000005c 0xc>;
clocks = <&periph_osc>;
timeout-sec = <30>;
};
pinctrl: pin-controller@10000080 {
compatible = "brcm,bcm6362-pinctrl";
reg = <0x10000080 0x8>,
<0x10000088 0x8>,
<0x10000090 0x4>,
<0x10000098 0x4>,
<0x1000009c 0x4>,
<0x100000b8 0x4>;
reg-names = "dirout", "dat", "led",
"mode", "ctrl", "basemode";
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&ext_intc>;
interrupts = <0 0>, <1 0>, <2 0>, <3 0>;
interrupt-names = "gpio24", "gpio25",
"gpio26", "gpio27";
pinctrl_usb_device_led: usb_device_led {
function = "usb_device_led";
pins = "gpio0";
};
pinctrl_sys_irq: sys_irq {
function = "sys_irq";
pins = "gpio1";
};
pinctrl_serial_led: serial_led {
pinctrl_serial_led_clk: serial_led_clk {
function = "serial_led_clk";
pins = "gpio2";
};
pinctrl_serial_led_data: serial_led_data {
function = "serial_led_data";
pins = "gpio3";
};
};
pinctrl_robosw_led_data: robosw_led_data {
function = "robosw_led_data";
pins = "gpio4";
};
pinctrl_robosw_led_clk: robosw_led_clk {
function = "robosw_led_clk";
pins = "gpio5";
};
pinctrl_robosw_led0: robosw_led0 {
function = "robosw_led0";
pins = "gpio6";
};
pinctrl_robosw_led1: robosw_led1 {
function = "robosw_led1";
pins = "gpio7";
};
pinctrl_inet_led: inet_led {
function = "inet_led";
pins = "gpio8";
};
pinctrl_spi_cs2: spi_cs2 {
function = "spi_cs2";
pins = "gpio9";
};
pinctrl_spi_cs3: spi_cs3 {
function = "spi_cs3";
pins = "gpio10";
};
pinctrl_ntr_pulse: ntr_pulse {
function = "ntr_pulse";
pins = "gpio11";
};
pinctrl_uart1_scts: uart1_scts {
function = "uart1_scts";
pins = "gpio12";
};
pinctrl_uart1_srts: uart1_srts {
function = "uart1_srts";
pins = "gpio13";
};
pinctrl_uart1: uart1 {
pinctrl_uart1_sdin: uart1_sdin {
function = "uart1_sdin";
pins = "gpio14";
};
pinctrl_uart1_sdout: uart1_sdout {
function = "uart1_sdout";
pins = "gpio15";
};
};
pinctrl_adsl_spi: adsl_spi {
pinctrl_adsl_spi_miso: adsl_spi_miso {
function = "adsl_spi_miso";
pins = "gpio16";
};
pinctrl_adsl_spi_mosi: adsl_spi_mosi {
function = "adsl_spi_mosi";
pins = "gpio17";
};
pinctrl_adsl_spi_clk: adsl_spi_clk {
function = "adsl_spi_clk";
pins = "gpio18";
};
pinctrl_adsl_spi_cs: adsl_spi_cs {
function = "adsl_spi_cs";
pins = "gpio19";
};
};
pinctrl_ephy0_led: ephy0_led {
function = "ephy0_led";
pins = "gpio20";
};
pinctrl_ephy1_led: ephy1_led {
function = "ephy1_led";
pins = "gpio21";
};
pinctrl_ephy2_led: ephy2_led {
function = "ephy2_led";
pins = "gpio22";
};
pinctrl_ephy3_led: ephy3_led {
function = "ephy3_led";
pins = "gpio23";
};
pinctrl_ext_irq0: ext_irq0 {
function = "ext_irq0";
pins = "gpio24";
};
pinctrl_ext_irq1: ext_irq1 {
function = "ext_irq1";
pins = "gpio25";
};
pinctrl_ext_irq2: ext_irq2 {
function = "ext_irq2";
pins = "gpio26";
};
pinctrl_ext_irq3: ext_irq3 {
function = "ext_irq3";
pins = "gpio27";
};
pinctrl_nand: nand {
function = "nand";
group = "nand_grp";
};
};
uart0: serial@10000100 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000100 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_UART0>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
uart1: serial@10000120 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000120 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_UART1>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
nflash: nand@10000200 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,nand-bcm6368",
"brcm,brcmnand-v2.2",
"brcm,brcmnand";
reg = <0x10000200 0x180>,
<0x10000600 0x200>,
<0x10000070 0x10>;
reg-names = "nand",
"nand-cache",
"nand-int-base";
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_NAND>;
clocks = <&periph_clk BCM6362_CLK_NAND>;
clock-names = "nand";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
status = "disabled";
};
lsspi: spi@10000800 {
compatible = "brcm,bcm6358-spi";
reg = <0x10000800 0x70c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_LSSPI>;
clocks = <&periph_clk BCM6362_CLK_SPI>;
clock-names = "spi";
resets = <&periph_rst BCM6362_RST_SPI>;
status = "disabled";
};
hsspi: spi@10001000 {
compatible = "brcm,bcm6328-hsspi";
reg = <0x10001000 0x600>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_HSSPI>;
clocks = <&periph_clk BCM6362_CLK_HSSPI>,
<&hsspi_osc>;
clock-names = "hsspi",
"pll";
resets = <&periph_rst BCM6362_RST_SPI>;
status = "disabled";
};
periph_pwr: power-controller@10001848 {
compatible = "brcm,bcm6362-power-controller";
reg = <0x10001848 0x4>;
#power-domain-cells = <1>;
};
leds: led-controller@10001900 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6328-leds";
reg = <0x10001900 0x24>;
status = "disabled";
};
ehci: usb@10002500 {
compatible = "brcm,bcm6362-ehci", "generic-ehci";
reg = <0x10002500 0x100>;
big-endian;
ignore-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_EHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
ohci: usb@10002600 {
compatible = "brcm,bcm6362-ohci", "generic-ohci";
reg = <0x10002600 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6362_IRQ_OHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
usbh: usb-phy@10002700 {
compatible = "brcm,bcm6362-usbh-phy";
reg = <0x10002700 0x38>;
#phy-cells = <1>;
clocks = <&periph_clk BCM6362_CLK_USBH>;
clock-names = "usbh";
power-domains = <&periph_pwr BCM6362_POWER_DOMAIN_USBH>;
resets = <&periph_rst BCM6362_RST_USBH>;
status = "disabled";
};
};
};

View File

@ -0,0 +1,110 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "bcm6368.dtsi"
/ {
model = "Comtrend VR-3025u";
compatible = "comtrend,vr-3025u", "brcm,bcm6368";
aliases {
led-boot = &led_power_green;
led-failsafe = &led_power_red;
led-running = &led_power_green;
led-upgrade = &led_power_green;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x04000000>;
};
keys {
compatible = "gpio-keys-polled";
poll-interval = <20>;
reset {
label = "reset";
gpios = <&pinctrl 34 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
debounce-interval = <60>;
};
};
leds {
compatible = "gpio-leds";
led@2 {
label = "green:dsl";
gpios = <&pinctrl 2 GPIO_ACTIVE_LOW>;
};
led@5 {
label = "green:internet";
gpios = <&pinctrl 5 GPIO_ACTIVE_HIGH>;
};
led_power_green: led@22 {
label = "green:power";
gpios = <&pinctrl 22 GPIO_ACTIVE_HIGH>;
};
led_power_red: led@24 {
label = "red:power";
gpios = <&pinctrl 24 GPIO_ACTIVE_HIGH>;
};
led@31 {
label = "red:internet";
gpios = <&pinctrl 31 GPIO_ACTIVE_HIGH>;
};
};
};
&ehci {
status = "okay";
};
&ohci {
status = "okay";
};
&pflash {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
cfe: partition@0 {
label = "CFE";
reg = <0x0000000 0x0020000>;
read-only;
};
partition@20000 {
compatible = "brcm,bcm963xx-imagetag";
label = "firmware";
reg = <0x0020000 0x1fc0000>;
};
partition@1fe0000 {
label = "nvram";
reg = <0x1fe0000 0x020000>;
};
};
};
&pinctrl {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pci &pinctrl_ephy0_led &pinctrl_ephy1_led
&pinctrl_ephy2_led &pinctrl_ephy3_led>;
};
&uart0 {
status = "okay";
};
&usbh {
status = "okay";
};

View File

@ -0,0 +1,475 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/dts-v1/;
#include <dt-bindings/clock/bcm6368-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/bcm6368-interrupt-controller.h>
#include <dt-bindings/reset/bcm6368-reset.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm6368";
aliases {
nflash = &nflash;
pflash = &pflash;
pinctrl = &pinctrl;
serial0 = &uart0;
serial1 = &uart1;
spi0 = &lsspi;
};
chosen {
bootargs = "console=ttyS0,115200n8 earlycon";
stdout-path = "serial0:115200n8";
};
clocks {
periph_osc: periph-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "periph";
};
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
mips-hpt-frequency = <200000000>;
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <0>;
};
cpu@1 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
device_type = "cpu";
reg = <1>;
};
};
cpu_intc: interrupt-controller {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
memory@0 {
device_type = "memory";
reg = <0 0>;
};
ubus {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
periph_clk: clock-controller@10000004 {
compatible = "brcm,bcm6368-clocks";
reg = <0x10000004 0x4>;
#clock-cells = <1>;
};
pll_cntl: syscon@10000008 {
compatible = "syscon";
reg = <0x10000008 0x4>;
native-endian;
};
syscon-reboot {
compatible = "syscon-reboot";
regmap = <&pll_cntl>;
offset = <0x0>;
mask = <0x1>;
};
periph_rst: reset-controller@10000010 {
compatible = "brcm,bcm6345-reset";
reg = <0x10000010 0x4>;
#reset-cells = <1>;
};
ext_intc0: interrupt-controller@10000018 {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0x10000018 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6368_IRQ_EXT0>,
<BCM6368_IRQ_EXT1>,
<BCM6368_IRQ_EXT2>,
<BCM6368_IRQ_EXT3>;
};
ext_intc1: interrupt-controller@1000001c {
#address-cells = <1>;
compatible = "brcm,bcm6345-ext-intc";
reg = <0x1000001c 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <BCM6368_IRQ_EXT4>,
<BCM6368_IRQ_EXT5>;
};
periph_intc: interrupt-controller@10000020 {
#address-cells = <1>;
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x10>,
<0x10000030 0x10>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <2>, <3>;
};
wdt: watchdog@1000005c {
compatible = "brcm,bcm7038-wdt";
reg = <0x1000005c 0xc>;
clocks = <&periph_osc>;
timeout-sec = <30>;
};
pinctrl: pin-controller@10000080 {
compatible = "brcm,bcm6368-pinctrl";
reg = <0x10000080 0x8>,
<0x10000088 0x8>,
<0x10000098 0x4>;
reg-names = "dirout", "dat", "mode";
brcm,gpiobasemode = <&gpiobasemode>;
gpio-controller;
#gpio-cells = <2>;
interrupts-extended = <&ext_intc1 0 0>,
<&ext_intc1 1 0>,
<&ext_intc0 0 0>,
<&ext_intc0 1 0>,
<&ext_intc0 2 0>,
<&ext_intc0 3 0>;
interrupt-names = "gpio32", "gpio33", "gpio34", "gpio35",
"gpio36", "gpio37";
pinctrl_analog_afe_0: analog_afe_0 {
function = "analog_afe_0";
pins = "gpio0";
};
pinctrl_analog_afe_1: analog_afe_1 {
function = "analog_afe_1";
pins = "gpio1";
};
pinctrl_sys_irq: sys_irq {
function = "sys_irq";
pins = "gpio2";
};
pinctrl_serial_led: serial_led {
pinctrl_serial_led_data: serial_led_data {
function = "serial_led_data";
pins = "gpio3";
};
pinctrl_serial_led_clk: serial_led_clk {
function = "serial_led_clk";
pins = "gpio4";
};
};
pinctrl_inet_led: inet_led {
function = "inet_led";
pins = "gpio5";
};
pinctrl_ephy0_led: ephy0_led {
function = "ephy0_led";
pins = "gpio6";
};
pinctrl_ephy1_led: ephy1_led {
function = "ephy1_led";
pins = "gpio7";
};
pinctrl_ephy2_led: ephy2_led {
function = "ephy2_led";
pins = "gpio8";
};
pinctrl_ephy3_led: ephy3_led {
function = "ephy3_led";
pins = "gpio9";
};
pinctrl_robosw_led_data: robosw_led_data {
function = "robosw_led_data";
pins = "gpio10";
};
pinctrl_robosw_led_clk: robosw_led_clk {
function = "robosw_led_clk";
pins = "gpio11";
};
pinctrl_robosw_led0: robosw_led0 {
function = "robosw_led0";
pins = "gpio12";
};
pinctrl_robosw_led1: robosw_led1 {
function = "robosw_led1";
pins = "gpio13";
};
pinctrl_usb_device_led: usb_device_led {
function = "usb_device_led";
pins = "gpio14";
};
pinctrl_pci: pci {
pinctrl_pci_req1: pci_req1 {
function = "pci_req1";
pins = "gpio16";
};
pinctrl_pci_gnt1: pci_gnt1 {
function = "pci_gnt1";
pins = "gpio17";
};
pinctrl_pci_intb: pci_intb {
function = "pci_intb";
pins = "gpio18";
};
pinctrl_pci_req0: pci_req0 {
function = "pci_req0";
pins = "gpio19";
};
pinctrl_pci_gnt0: pci_gnt0 {
function = "pci_gnt0";
pins = "gpio20";
};
};
pinctrl_pcmcia: pcmcia {
pinctrl_pcmcia_cd1: pcmcia_cd1 {
function = "pcmcia_cd1";
pins = "gpio22";
};
pinctrl_pcmcia_cd2: pcmcia_cd2 {
function = "pcmcia_cd2";
pins = "gpio23";
};
pinctrl_pcmcia_vs1: pcmcia_vs1 {
function = "pcmcia_vs1";
pins = "gpio24";
};
pinctrl_pcmcia_vs2: pcmcia_vs2 {
function = "pcmcia_vs2";
pins = "gpio25";
};
};
pinctrl_ebi_cs2: ebi_cs2 {
function = "ebi_cs2";
pins = "gpio26";
};
pinctrl_ebi_cs3: ebi_cs3 {
function = "ebi_cs2";
pins = "gpio27";
};
pinctrl_spi_cs2: spi_cs2 {
function = "spi_cs2";
pins = "gpio28";
};
pinctrl_spi_cs3: spi_cs3 {
function = "spi_cs3";
pins = "gpio29";
};
pinctrl_spi_cs4: spi_cs4 {
function = "spi_cs4";
pins = "gpio30";
};
pinctrl_spi_cs5: spi_cs5 {
function = "spi_cs5";
pins = "gpio31";
};
pinctrl_uart1: uart1 {
function = "uart1";
group = "uart1_grp";
};
};
gpiobasemode: gpiobasemode@100000b8 {
compatible = "brcm,bcm6368-gpiobasemode", "syscon";
reg = <0x100000b8 0x4>;
};
leds: led-controller@100000d0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6358-leds";
reg = <0x100000d0 0x8>;
status = "disabled";
};
uart0: serial@10000100 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000100 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_UART0>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
uart1: serial@10000120 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000120 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_UART1>;
clocks = <&periph_osc>;
clock-names = "periph";
status = "disabled";
};
nflash: nand@10000200 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,nand-bcm6368",
"brcm,brcmnand-v2.1",
"brcm,brcmnand";
reg = <0x10000200 0x180>,
<0x10000600 0x200>,
<0x10000070 0x10>;
reg-names = "nand",
"nand-cache",
"nand-int-base";
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_NAND>;
clocks = <&periph_clk BCM6368_CLK_NAND>;
clock-names = "nand";
status = "disabled";
};
lsspi: spi@10000800 {
compatible = "brcm,bcm6358-spi";
reg = <0x10000800 0x70c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_SPI>;
clocks = <&periph_clk BCM6368_CLK_SPI>;
clock-names = "spi";
resets = <&periph_rst BCM6368_RST_SPI>;
status = "disabled";
};
ehci: usb@10001500 {
compatible = "brcm,bcm6368-ehci", "generic-ehci";
reg = <0x10001500 0x100>;
big-endian;
ignore-oc;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_EHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
ohci: usb@10001600 {
compatible = "brcm,bcm6368-ohci", "generic-ohci";
reg = <0x10001600 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <BCM6368_IRQ_OHCI>;
phys = <&usbh 0>;
phy-names = "usb";
status = "disabled";
};
usbh: usb-phy@10001700 {
compatible = "brcm,bcm6368-usbh-phy";
reg = <0x10001700 0x38>;
#phy-cells = <1>;
clocks = <&periph_clk BCM6368_CLK_USBH>;
clock-names = "usbh";
resets = <&periph_rst BCM6368_RST_USBH>;
status = "disabled";
};
random: rng@10004180 {
compatible = "brcm,bcm6368-rng";
reg = <0x10004180 0x14>;
clocks = <&periph_clk BCM6368_CLK_IPSEC>;
clock-names = "ipsec";
};
};
pflash: nor@18000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x18000000 0x2000000>;
bank-width = <2>;
status = "disabled";
};
};

View File

@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6318_H
#define __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6318_H
#define BCM6318_IRQ_TIMER0 0
#define BCM6318_IRQ_TIMER1 1
#define BCM6318_IRQ_TIMER2 2
#define BCM6318_IRQ_TIMER3 3
#define BCM6318_IRQ_USBS 4
#define BCM6318_IRQ_USB_CTL_RX_DMA 5
#define BCM6318_IRQ_USB_CTL_TX_DMA 6
#define BCM6318_IRQ_USB_BULK_RX_DMA 7
#define BCM6318_IRQ_USB_BULK_TX_DMA 8
#define BCM6318_IRQ_USB_ISO_RX_DMA 9
#define BCM6318_IRQ_USB_ISO_TX_DMA 10
#define BCM6318_IRQ_DG 11
#define BCM6318_IRQ_EPHY 12
#define BCM6318_IRQ_EPHY_EN0N 13
#define BCM6318_IRQ_EPHY_EN1N 14
#define BCM6318_IRQ_EPHY_EN2N 15
#define BCM6318_IRQ_EPHY_EN3N 16
#define BCM6318_IRQ_EPHY_EN0 17
#define BCM6318_IRQ_EPHY_EN1 18
#define BCM6318_IRQ_EPHY_EN2 19
#define BCM6318_IRQ_EPHY_EN3 20
#define BCM6318_IRQ_XDSL 21
#define BCM6318_IRQ_SDR 22
#define BCM6318_IRQ_PCIE_RC 23
#define BCM6318_IRQ_EXT0 24
#define BCM6318_IRQ_EXT1 25
#define BCM6318_IRQ_EXT2 26
#define BCM6318_IRQ_EXT3 27
#define BCM6318_IRQ_UART0 28
#define BCM6318_IRQ_HSSPI 29
#define BCM6318_IRQ_WAKE_ON_IRQ 30
#define BCM6318_IRQ_TIMER 31
#define BCM6318_IRQ_ENETSW_RX_DMA0 32
#define BCM6318_IRQ_ENETSW_RX_DMA1 33
#define BCM6318_IRQ_ENETSW_RX_DMA2 34
#define BCM6318_IRQ_ENETSW_RX_DMA3 35
#define BCM6318_IRQ_WDTIMER 37
#define BCM6318_IRQ_ENETSW 40
#define BCM6318_IRQ_OHCI 41
#define BCM6318_IRQ_EHCI 42
#define BCM6318_IRQ_ATM_DMA0 43
#define BCM6318_IRQ_ATM_DMA1 44
#define BCM6318_IRQ_ATM_DMA2 45
#define BCM6318_IRQ_ATM_DMA3 46
#define BCM6318_IRQ_ATM_DMA4 47
#define BCM6318_IRQ_ATM_DMA5 48
#define BCM6318_IRQ_ATM_DMA6 49
#define BCM6318_IRQ_ATM_DMA7 50
#define BCM6318_IRQ_ATM_DMA8 51
#define BCM6318_IRQ_ATM_DMA9 52
#define BCM6318_IRQ_ATM_DMA10 53
#define BCM6318_IRQ_ATM_DMA11 54
#define BCM6318_IRQ_ATM_DMA12 55
#define BCM6318_IRQ_ATM_DMA13 56
#define BCM6318_IRQ_ATM_DMA14 57
#define BCM6318_IRQ_ATM_DMA15 58
#define BCM6318_IRQ_ATM_DMA16 59
#define BCM6318_IRQ_ATM_DMA17 60
#define BCM6318_IRQ_ATM_DMA18 61
#define BCM6318_IRQ_ATM_DMA19 62
#define BCM6318_IRQ_SAR 63
#define BCM6318_IRQ_ADSL_ENERGY 64
#define BCM6318_IRQ_ADSL_ENERGY_N 65
#define BCM6318_IRQ_USB_ENERGY_ON 66
#define BCM6318_IRQ_USB_ENERGY_OFF 67
#define BCM6318_IRQ_PVTMON_TEMP 68
#define BCM6318_IRQ_SYSPLL_LOCK 69
#define BCM6318_IRQ_LCPLL_LOCK 70
#define BCM6318_IRQ_PMU_STABLE 71
#define BCM6318_IRQ_ENETSW_TX_DMA0 72
#define BCM6318_IRQ_ENETSW_TX_DMA1 73
#define BCM6318_IRQ_ENETSW_TX_DMA2 74
#define BCM6318_IRQ_ENETSW_TX_DMA3 75
#define BCM6318_IRQ_EPHY0_IDDQ_ENERGY 76
#define BCM6318_IRQ_EPHY1_IDDQ_ENERGY 77
#define BCM6318_IRQ_EPHY2_IDDQ_ENERGY 78
#define BCM6318_IRQ_EPHY3_IDDQ_ENERGY 79
#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6318_H */

View File

@ -0,0 +1,86 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM63268_H
#define __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM63268_H
#define BCM63268_IRQ_TIMER 0
#define BCM63268_IRQ_ENETSW_RX_DMA0 1
#define BCM63268_IRQ_ENETSW_RX_DMA1 2
#define BCM63268_IRQ_ENETSW_RX_DMA2 3
#define BCM63268_IRQ_ENETSW_RX_DMA3 4
#define BCM63268_IRQ_UART0 5
#define BCM63268_IRQ_HSSPI 6
#define BCM63268_IRQ_WLAN 7
#define BCM63268_IRQ_IPSEC 8
#define BCM63268_IRQ_OHCI 9
#define BCM63268_IRQ_EHCI 10
#define BCM63268_IRQ_USBS 11
#define BCM63268_IRQ_PCM 12
#define BCM63268_IRQ_EPHY 13
#define BCM63268_IRQ_DG 14
#define BCM63268_IRQ_EPHY0_EN 15
#define BCM63268_IRQ_EPHY1_EN 16
#define BCM63268_IRQ_EPHY2_EN 17
#define BCM63268_IRQ_GPHY_EN 18
#define BCM63268_IRQ_USB_CTL_RX_DMA 19
#define BCM63268_IRQ_USB_BULK_RX_DMA 20
#define BCM63268_IRQ_ISO_RX_DMA 21
#define BCM63268_IRQ_IPSEC_DMA0 22
#define BCM63268_IRQ_XDSL 23
#define BCM63268_IRQ_FAP0 24
#define BCM63268_IRQ_FAP1 25
#define BCM63268_IRQ_ATM_DMA0 26
#define BCM63268_IRQ_ATM_DMA1 27
#define BCM63268_IRQ_ATM_DMA2 28
#define BCM63268_IRQ_ATM_DMA3 29
#define BCM63268_IRQ_WAKE_ON_IRQ 30
#define BCM63268_IRQ_GPHY 31
#define BCM63268_IRQ_DECT0 32
#define BCM63268_IRQ_DECT1 33
#define BCM63268_IRQ_UART1 34
#define BCM63268_IRQ_WLAN_GPIO 35
#define BCM63268_IRQ_USB_CTL_TX_DMA 36
#define BCM63268_IRQ_USB_BULK_TX_DMA 37
#define BCM63268_IRQ_ISO_TX_DMA 38
#define BCM63268_IRQ_IPSEC_DMA1 39
#define BCM63268_IRQ_PCIE_RC 40
#define BCM63268_IRQ_PCIE_EP 41
#define BCM63268_IRQ_PCM_DMA0 42
#define BCM63268_IRQ_PCM_DMA1 43
#define BCM63268_IRQ_EXT0 44
#define BCM63268_IRQ_EXT1 45
#define BCM63268_IRQ_EXT2 46
#define BCM63268_IRQ_EXT3 47
#define BCM63268_IRQ_ENETSW 48
#define BCM63268_IRQ_SAR 49
#define BCM63268_IRQ_NAND 50
#define BCM63268_IRQ_RING_OSC 52
#define BCM63268_IRQ_USB_CONNECT 53
#define BCM63268_IRQ_USB_DISCONNECT 54
#define BCM63268_IRQ_PER_MBOX0 55
#define BCM63268_IRQ_PER_MBOX1 56
#define BCM63268_IRQ_PER_MBOX2 57
#define BCM63268_IRQ_PER_MBOX3 58
#define BCM63268_IRQ_ATM_DMA4 59
#define BCM63268_IRQ_ATM_DMA5 60
#define BCM63268_IRQ_ATM_DMA6 61
#define BCM63268_IRQ_ATM_DMA7 62
#define BCM63268_IRQ_ENETSW_TX_DMA0 64
#define BCM63268_IRQ_ENETSW_TX_DMA1 65
#define BCM63268_IRQ_ENETSW_TX_DMA2 66
#define BCM63268_IRQ_ENETSW_TX_DMA3 67
#define BCM63268_IRQ_ATM_DMA8 68
#define BCM63268_IRQ_ATM_DMA9 69
#define BCM63268_IRQ_ATM_DMA10 70
#define BCM63268_IRQ_ATM_DMA11 71
#define BCM63268_IRQ_ATM_DMA12 72
#define BCM63268_IRQ_ATM_DMA13 73
#define BCM63268_IRQ_ATM_DMA14 74
#define BCM63268_IRQ_ATM_DMA15 75
#define BCM63268_IRQ_ATM_DMA16 76
#define BCM63268_IRQ_ATM_DMA17 77
#define BCM63268_IRQ_ATM_DMA18 78
#define BCM63268_IRQ_ATM_DMA19 79
#define BCM63268_IRQ_LSSPI 80
#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM63268_H */

View File

@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6328_H
#define __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6328_H
#define BCM6328_IRQ_NAND 0
#define BCM6328_IRQ_PCM 1
#define BCM6328_IRQ_PCM_DMA0 2
#define BCM6328_IRQ_PCM_DMA1 3
#define BCM6328_IRQ_USBS 4
#define BCM6328_IRQ_USB_CTL_RX_DMA 5
#define BCM6328_IRQ_USB_CTL_TX_DMA 6
#define BCM6328_IRQ_USB_BULK_RX_DMA 7
#define BCM6328_IRQ_USB_BULK_TX_DMA 8
#define BCM6328_IRQ_USB_ISO_RX_DMA 9
#define BCM6328_IRQ_USB_ISO_TX_DMA 10
#define BCM6328_IRQ_DG 11
#define BCM6328_IRQ_EPHY 12
#define BCM6328_IRQ_EPHY_EN0N 13
#define BCM6328_IRQ_EPHY_EN1N 14
#define BCM6328_IRQ_EPHY_EN2N 15
#define BCM6328_IRQ_EPHY_EN3N 16
#define BCM6328_IRQ_EPHY_EN0 17
#define BCM6328_IRQ_EPHY_EN1 18
#define BCM6328_IRQ_EPHY_EN2 19
#define BCM6328_IRQ_EPHY_EN3 20
#define BCM6328_IRQ_XDSL 21
#define BCM6328_IRQ_PCIE_EP 22
#define BCM6328_IRQ_PCIE_RC 23
#define BCM6328_IRQ_EXTO 24
#define BCM6328_IRQ_EXT1 25
#define BCM6328_IRQ_EXT2 26
#define BCM6328_IRQ_EXT3 27
#define BCM6328_IRQ_UART0 28
#define BCM6328_IRQ_HSSPI 29
#define BCM6328_IRQ_WAKE_ON_IRQ 30
#define BCM6328_IRQ_TIMER 31
#define BCM6328_IRQ_ENETSW_RX_DMA0 32
#define BCM6328_IRQ_ENETSW_RX_DMA1 33
#define BCM6328_IRQ_ENETSW_TX_DMA0 34
#define BCM6328_IRQ_ENETSW_TX_DMA1 35
#define BCM6328_IRQ_UART1 39
#define BCM6328_IRQ_ENETSW 40
#define BCM6328_IRQ_OHCI 41
#define BCM6328_IRQ_EHCI 42
#define BCM6328_IRQ_ATM_DMA0 43
#define BCM6328_IRQ_ATM_DMA1 44
#define BCM6328_IRQ_ATM_DMA2 45
#define BCM6328_IRQ_ATM_DMA3 46
#define BCM6328_IRQ_ATM_DMA4 47
#define BCM6328_IRQ_ATM_DMA5 48
#define BCM6328_IRQ_ATM_DMA6 49
#define BCM6328_IRQ_ATM_DMA7 50
#define BCM6328_IRQ_ATM_DMA8 51
#define BCM6328_IRQ_ATM_DMA9 52
#define BCM6328_IRQ_ATM_DMA10 53
#define BCM6328_IRQ_ATM_DMA11 54
#define BCM6328_IRQ_ATM_DMA12 55
#define BCM6328_IRQ_ATM_DMA13 56
#define BCM6328_IRQ_ATM_DMA14 57
#define BCM6328_IRQ_ATM_DMA15 58
#define BCM6328_IRQ_ATM_DMA16 59
#define BCM6328_IRQ_ATM_DMA17 60
#define BCM6328_IRQ_ATM_DMA18 61
#define BCM6328_IRQ_ATM_DMA19 62
#define BCM6328_IRQ_SAR 63
#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6328_H */

View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6358_H
#define __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6358_H
#define BCM6358_IRQ_TIMER 0
#define BCM6358_IRQ_SPI 1
#define BCM6358_IRQ_UART0 2
#define BCM6358_IRQ_UART1 3
#define BCM6358_IRQ_OHCI 5
#define BCM6358_IRQ_EMAC1 6
#define BCM6358_IRQ_USBS 7
#define BCM6358_IRQ_EMAC0 8
#define BCM6358_IRQ_EPHY 9
#define BCM6358_IRQ_EHCI 10
#define BCM6358_IRQ_USB_CTL_RX_DMA 11
#define BCM6358_IRQ_USB_CTL_TX_DMA 12
#define BCM6358_IRQ_USB_BULK_RX_DMA 13
#define BCM6358_IRQ_USB_BULK_TX_DMA 14
#define BCM6358_IRQ_EMAC0_RX_DMA 15
#define BCM6358_IRQ_EMAC0_TX_DMA 16
#define BCM6358_IRQ_EMAC1_RX_DMA 17
#define BCM6358_IRQ_EMAC1_TX_DMA 18
#define BCM6358_IRQ_ATM 19
#define BCM6358_IRQ_EXT4 20
#define BCM6358_IRQ_EXT5 21
#define BCM6358_IRQ_PCM 22
#define BCM6358_IRQ_PCM_RX_DMA 23
#define BCM6358_IRQ_PCM_TX_DMA 24
#define BCM6358_IRQ_EXT0 25
#define BCM6358_IRQ_EXT1 26
#define BCM6358_IRQ_EXT2 27
#define BCM6358_IRQ_EXT3 28
#define BCM6358_IRQ_ADSL 29
#define BCM6358_IRQ_DG 30
#define BCM6358_IRQ_MPI 31
#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6358_H */

View File

@ -0,0 +1,71 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6362_H
#define __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6362_H
#define BCM6362_IRQ_TIMER 0
#define BCM6362_IRQ_RING_OSC 1
#define BCM6362_IRQ_LSSPI 2
#define BCM6362_IRQ_UART0 3
#define BCM6362_IRQ_UART1 4
#define BCM6362_IRQ_HSSPI 5
#define BCM6362_IRQ_WLAN_GPIO 6
#define BCM6362_IRQ_WLAN 7
#define BCM6362_IRQ_IPSEC 8
#define BCM6362_IRQ_OHCI 9
#define BCM6362_IRQ_EHCI 10
#define BCM6362_IRQ_USBS 11
#define BCM6362_IRQ_NAND 12
#define BCM6362_IRQ_PCM 13
#define BCM6362_IRQ_EPHY 14
#define BCM6362_IRQ_DF 15
#define BCM6362_IRQ_EPHY_EN0 16
#define BCM6362_IRQ_EPHY_EN1 17
#define BCM6362_IRQ_EPHY_EN2 18
#define BCM6362_IRQ_EPHY_EN3 19
#define BCM6362_IRQ_USB_CTL_RX_DMA 20
#define BCM6362_IRQ_USB_CTL_TX_DMA 21
#define BCM6362_IRQ_USB_BULK_RX_DMA 22
#define BCM6362_IRQ_USB_BULK_TX_DMA 23
#define BCM6362_IRQ_USB_ISO_RX_DMA 24
#define BCM6362_IRQ_USB_ISO_TX_DMA 25
#define BCM6362_IRQ_IPSEC_DMA0 26
#define BCM6362_IRQ_IPSEC_DMA1 27
#define BCM6362_IRQ_XDSL 28
#define BCM6362_IRQ_FAP 29
#define BCM6362_IRQ_PCIE_RC 30
#define BCM6362_IRQ_PCIE_EP 31
#define BCM6362_IRQ_ENETSW_RX_DMA0 32
#define BCM6362_IRQ_ENETSW_RX_DMA1 33
#define BCM6362_IRQ_ENETSW_RX_DMA2 34
#define BCM6362_IRQ_ENETSW_RX_DMA3 35
#define BCM6362_IRQ_PCM_DMA0 36
#define BCM6362_IRQ_PCM_DMA1 37
#define BCM6362_IRQ_DECT0 38
#define BCM6362_IRQ_DECT1 39
#define BCM6362_IRQ_EXT0 40
#define BCM6362_IRQ_EXT1 41
#define BCM6362_IRQ_EXT2 42
#define BCM6362_IRQ_EXT3 43
#define BCM6362_IRQ_ATM_DMA0 44
#define BCM6362_IRQ_ATM_DMA1 45
#define BCM6362_IRQ_ATM_DMA2 46
#define BCM6362_IRQ_ATM_DMA3 47
#define BCM6362_IRQ_ATM_DMA4 48
#define BCM6362_IRQ_ATM_DMA5 49
#define BCM6362_IRQ_ATM_DMA6 50
#define BCM6362_IRQ_ATM_DMA7 51
#define BCM6362_IRQ_ATM_DMA8 52
#define BCM6362_IRQ_ATM_DMA9 53
#define BCM6362_IRQ_ATM_DMA10 54
#define BCM6362_IRQ_ATM_DMA11 55
#define BCM6362_IRQ_ATM_DMA12 56
#define BCM6362_IRQ_ATM_DMA13 57
#define BCM6362_IRQ_ATM_DMA14 58
#define BCM6362_IRQ_ATM_DMA15 59
#define BCM6362_IRQ_ATM_DMA16 60
#define BCM6362_IRQ_ATM_DMA17 61
#define BCM6362_IRQ_ATM_DMA18 62
#define BCM6362_IRQ_ATM_DMA19 63
#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6362_H */

View File

@ -0,0 +1,71 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6368_H
#define __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6368_H
#define BCM6368_IRQ_TIMER 0
#define BCM6368_IRQ_SPI 1
#define BCM6368_IRQ_UART0 2
#define BCM6368_IRQ_UART1 3
#define BCM6368_IRQ_XDSL 4
#define BCM6368_IRQ_OHCI 5
#define BCM6368_IRQ_IPSEC 6
#define BCM6368_IRQ_EHCI 7
#define BCM6368_IRQ_USBS 8
#define BCM6368_IRQ_RING_OSC 9
#define BCM6368_IRQ_NAND 10
#define BCM6368_IRQ_ATM 11
#define BCM6368_IRQ_PCM 12
#define BCM6368_IRQ_MPI 13
#define BCM6368_IRQ_DG 14
#define BCM6368_IRQ_EPHY 15
#define BCM6368_IRQ_EPHY_EN0 16
#define BCM6368_IRQ_EPHY_EN1 17
#define BCM6368_IRQ_EPHY_EN2 18
#define BCM6368_IRQ_EPHY_EN3 19
#define BCM6368_IRQ_EXT0 20
#define BCM6368_IRQ_EXT1 21
#define BCM6368_IRQ_EXT2 22
#define BCM6368_IRQ_EXT3 23
#define BCM6368_IRQ_EXT4 24
#define BCM6368_IRQ_EXT5 25
#define BCM6368_IRQ_USB_CTL_RX_DMA 26
#define BCM6368_IRQ_USB_CTL_TX_DMA 27
#define BCM6368_IRQ_USB_BULK_RX_DMA 28
#define BCM6368_IRQ_USB_BULK_TX_DMA 29
#define BCM6368_IRQ_USB_ISO_RX_DMA 30
#define BCM6368_IRQ_USB_ISO_TX_DMA 31
#define BCM6368_IRQ_ENETSW_RX_DMA0 32
#define BCM6368_IRQ_ENETSW_RX_DMA1 33
#define BCM6368_IRQ_ENETSW_RX_DMA2 34
#define BCM6368_IRQ_ENETSW_RX_DMA3 35
#define BCM6368_IRQ_ENETSW_TX_DMA0 36
#define BCM6368_IRQ_ENETSW_TX_DMA1 37
#define BCM6368_IRQ_ENETSW_TX_DMA2 38
#define BCM6368_IRQ_ENETSW_TX_DMA3 39
#define BCM6368_IRQ_ATM_DMA0 40
#define BCM6368_IRQ_ATM_DMA1 41
#define BCM6368_IRQ_ATM_DMA2 42
#define BCM6368_IRQ_ATM_DMA3 43
#define BCM6368_IRQ_ATM_DMA4 44
#define BCM6368_IRQ_ATM_DMA5 45
#define BCM6368_IRQ_ATM_DMA6 46
#define BCM6368_IRQ_ATM_DMA7 47
#define BCM6368_IRQ_ATM_DMA8 48
#define BCM6368_IRQ_ATM_DMA9 49
#define BCM6368_IRQ_ATM_DMA10 50
#define BCM6368_IRQ_ATM_DMA11 51
#define BCM6368_IRQ_ATM_DMA12 52
#define BCM6368_IRQ_ATM_DMA13 53
#define BCM6368_IRQ_ATM_DMA14 54
#define BCM6368_IRQ_ATM_DMA15 55
#define BCM6368_IRQ_ATM_DMA16 56
#define BCM6368_IRQ_ATM_DMA17 57
#define BCM6368_IRQ_ATM_DMA18 58
#define BCM6368_IRQ_ATM_DMA19 59
#define BCM6368_IRQ_IPSEC_DMA0 60
#define BCM6368_IRQ_IPSEC_DMA1 61
#define BCM6368_IRQ_PCM_DMA0 62
#define BCM6368_IRQ_PCM_DMA1 63
#endif /* __DT_BINDINGS_INTERRUPT_CONTROLLER_BCM6368_H */

View File

@ -0,0 +1,3 @@
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPLIT_BCM63XX_FW=y

View File

@ -0,0 +1,5 @@
BOARDNAME:=generic
define Target/Description
BMIPS boards without NAND support
endef

View File

@ -0,0 +1,257 @@
# SPDX-License-Identifier: GPL-2.0-or-later
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
KERNEL_LOADADDR := 0x80010000 # RAM start + 64K
LOADER_ENTRY := 0x80a00000 # RAM start + 10M, for relocate
RAMSIZE := 0x02000000 # 32MB
LZMA_TEXT_START := 0x81800000 # 32MB - 8MB
DEVICE_VARS += CHIP_ID DEVICE_LOADADDR
define Build/Compile
rm -rf $(KDIR)/relocate
$(CP) ../../generic/image/relocate $(KDIR)
$(MAKE) -C $(KDIR)/relocate \
CACHELINE_SIZE=16 \
CROSS_COMPILE=$(TARGET_CROSS) \
KERNEL_ADDR=$(KERNEL_LOADADDR) \
LZMA_TEXT_START=$(LOADER_ENTRY)
endef
### Kernel scripts ###
define Build/loader-lzma
@rm -rf $@.src
$(MAKE) -C lzma-loader \
CHIP_ID=$(CHIP_ID) \
KERNEL_ADDR=$(KERNEL_LOADADDR) \
KDIR=$(KDIR) \
LOADER_ADDR=$(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY)) \
LOADER_DATA="$@" \
LOADER_NAME="$(notdir $@)" \
LZMA_TEXT_START=$(LZMA_TEXT_START) \
PKG_BUILD_DIR="$@.src" \
RAMSIZE=$(RAMSIZE) \
TARGET_DIR="$(dir $@)" \
compile loader.$(1)
@mv "$@.$(1)" "$@"
@rm -rf $@.src
endef
define Build/lzma-cfe
# CFE is a LZMA nazi! It took me hours to find out the parameters!
# Also I think lzma has a bug cause it generates different output depending on
# if you use stdin / stdout or not. Use files instead of stdio here, cause
# otherwise CFE will complain and not boot the image.
$(call Build/lzma-no-dict,-d22 -fb64 -a1)
# Strip out the length, CFE doesn't like this
dd if=$@ of=$@.new bs=5 count=1
dd if=$@ of=$@.new ibs=13 obs=5 skip=1 seek=1 conv=notrunc
@mv $@.new $@
endef
define Build/relocate-kernel
# CFE only allows ~4 MiB for the uncompressed kernels, but uncompressed
# kernel might get larger than that, so let CFE unpack and load at a
# higher address and make the kernel relocate itself to the expected
# location.
( \
dd if=$(KDIR)/relocate/loader.bin bs=32 conv=sync && \
perl -e '@s = stat("$@"); print pack("N", @s[7])' && \
cat $@ \
) > $@.relocate
@mv $@.relocate $@
endef
### Image scripts ###
define rootfspad/jffs2-128k
--align-rootfs
endef
define rootfspad/jffs2-64k
--align-rootfs
endef
define rootfspad/squashfs
endef
define Image/FileSystemStrip
$(firstword $(subst +,$(space),$(subst root.,,$(notdir $(1)))))
endef
define Build/cfe-bin
$(STAGING_DIR_HOST)/bin/imagetag -i $(IMAGE_KERNEL) -f $(IMAGE_ROOTFS) \
--output $@ --boardid $(CFE_BOARD_ID) --chipid $(CHIP_ID) \
--entry $(LOADER_ENTRY) --load-addr $(LOADER_ENTRY) \
--info1 "$(call ModelNameLimit16,$(DEVICE_NAME))" \
--info2 "$(call Image/FileSystemStrip,$(IMAGE_ROOTFS))" \
$(call rootfspad/$(call Image/FileSystemStrip,$(IMAGE_ROOTFS))) \
$(CFE_EXTRAS) $(1)
endef
define Build/cfe-jffs2
$(STAGING_DIR_HOST)/bin/mkfs.jffs2 \
--big-endian \
--pad \
--no-cleanmarkers \
--eraseblock=$(patsubst %k,%KiB,$(BLOCKSIZE)) \
--root=$(1) \
--output=$@ \
--compression-mode=none
$(call Build/pad-to,$(BLOCKSIZE))
endef
define Build/cfe-jffs2-cferam
mv $@ $@.kernel
rm -rf $@-cferam
mkdir -p $@-cferam
# CFE ROM checks JFFS2 dirent version of cferam.
# If version is not > 0 it will ignore the fs entry.
# JFFS2 sets version 0 to the first fs entry and increments
# it on the following ones, so let's create a dummy file that
# will have version 0 and let cferam be the second (version 1).
touch $@-cferam/1-openwrt
# Add cferam as the last file in the JFFS2 partition
cp $(KDIR)/bcm63xx-cfe/$(CFE_RAM_FILE) $@-cferam/$(CFE_RAM_JFFS2_NAME)
# The JFFS2 partition creation should result in the following
# layout:
# 1) 1-openwrt (version 0, ino 2)
# 2) cferam.000 (version 1, ino 3)
$(call Build/cfe-jffs2,$@-cferam)
# Some devices need padding between CFE RAM and kernel
$(if $(CFE_RAM_JFFS2_PAD),$(call Build/pad-to,$(CFE_RAM_JFFS2_PAD)))
# Add CFE partition tag
$(if $(CFE_PART_ID),$(call Build/cfe-part-tag))
# Append kernel
dd if=$@.kernel >> $@
rm -f $@.kernel
endef
define Build/cfe-jffs2-kernel
rm -rf $@-kernel
mkdir -p $@-kernel
# CFE RAM checks JFFS2 dirent version of vmlinux.
# If version is not > 0 it will ignore the fs entry.
# JFFS2 sets version 0 to the first fs entry and increments
# it on the following ones, so let's create a dummy file that
# will have version 0 and let cferam be the second (version 1).
touch $@-kernel/1-openwrt
# vmlinux is located on a different JFFS2 partition, but CFE RAM
# ignores it, so let's create another dummy file that will match
# the JFFS2 ino of cferam entry on the first JFFS2 partition.
# CFE RAM won't be able to find vmlinux if cferam has the same
# ino as vmlinux.
touch $@-kernel/2-openwrt
# Add vmlinux as the last file in the JFFS2 partition
$(TOPDIR)/scripts/cfe-bin-header.py \
--input-file $@ \
--output-file $@-kernel/vmlinux.lz \
--load-addr $(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY)) \
--entry-addr $(if $(DEVICE_LOADADDR),$(DEVICE_LOADADDR),$(LOADER_ENTRY))
# The JFFS2 partition creation should result in the following
# layout:
# 1) 1-openwrt (version 0, ino 2)
# 2) 2-openwrt (version 1, ino 3)
# 3) vmlinux.lz (version 2, ino 4)
$(call Build/cfe-jffs2,$@-kernel)
endef
define Build/cfe-part-tag
mv $@ $@.part
$(TOPDIR)/scripts/cfe-partition-tag.py \
--input-file $@.part \
--output-file $@ \
--flags $(CFE_PART_FLAGS) \
--id $(CFE_PART_ID) \
--name $(VERSION_CODE) \
--version $(DEVICE_NAME)
$(call Build/pad-to,$(BLOCKSIZE))
dd if=$@.part >> $@
endef
define Build/cfe-sercomm-crypto
$(TOPDIR)/scripts/sercomm-crypto.py \
--input-file $@ \
--key-file $@.key \
--output-file $@.ser \
--version OpenWrt
$(STAGING_DIR_HOST)/bin/openssl enc -md md5 -aes-256-cbc \
-in $@ -out $@.enc \
-K `cat $@.key` \
-iv 00000000000000000000000000000000
dd if=$@.enc >> $@.ser
mv $@.ser $@
rm -f $@.enc $@.key
endef
define Build/cfe-sercomm-load
$(TOPDIR)/scripts/sercomm-payload.py \
--input-file $@ \
--output-file $@.new \
--pid "$(SERCOMM_PID)"
mv $@.new $@
endef
define Build/cfe-sercomm-part
$(TOPDIR)/scripts/sercomm-partition-tag.py \
--input-file $@ \
--output-file $@.kernel_rootfs \
--part-name kernel_rootfs \
--part-version OpenWrt \
--rootfs-version $(SERCOMM_VERSION)
rm -rf $@-rootfs_lib
mkdir -p $@-rootfs_lib
echo $(SERCOMM_VERSION) > $@-rootfs_lib/lib_ver
$(call Build/cfe-jffs2,$@-rootfs_lib)
$(call Build/pad-to,$(BLOCKSIZE))
$(TOPDIR)/scripts/sercomm-partition-tag.py \
--input-file $@ \
--output-file $@.rootfs_lib \
--part-name rootfs_lib \
--part-version $(SERCOMM_VERSION)
mv $@.kernel_rootfs $@
dd if=$@.rootfs_lib >> $@
endef
define Build/cfe-wfi-tag
$(TOPDIR)/scripts/cfe-wfi-tag.py \
--input-file $@ \
--output-file $@.new \
--version $(if $(1),$(1),$(CFE_WFI_VERSION)) \
--chip-id $(CFE_WFI_CHIP_ID) \
--flash-type $(CFE_WFI_FLASH_TYPE) \
$(if $(CFE_WFI_FLAGS),--flags $(CFE_WFI_FLAGS))
mv $@.new $@
endef
### Device scripts ###
define Device/Default
PROFILES = Default $$(DEVICE_NAME)
KERNEL_DEPENDS = $$(wildcard ../dts/$$(DEVICE_DTS).dts)
DEVICE_DTS_DIR := ../dts
CHIP_ID :=
SOC = bcm$$(CHIP_ID)
DEVICE_DTS = $$(SOC)-$(subst _,-,$(1))
DEVICE_LOADADDR :=
endef
USB1_PACKAGES := kmod-usb-ohci kmod-ledtrig-usbdev
USB2_PACKAGES := $(USB1_PACKAGES) kmod-usb2
include bcm63xx_$(SUBTARGET).mk
$(eval $(call BuildImage))

View File

@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-or-later
DEVICE_VARS += CFE_BOARD_ID CFE_EXTRAS
DEVICE_VARS += FLASH_MB IMAGE_OFFSET
define Device/bcm63xx-cfe
FILESYSTEMS := squashfs jffs2-64k jffs2-128k
KERNEL := kernel-bin | append-dtb | relocate-kernel | lzma
KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | loader-lzma elf
KERNEL_INITRAMFS_SUFFIX := .elf
IMAGES := cfe.bin sysupgrade.bin
IMAGE/cfe.bin := \
cfe-bin $$$$(if $$$$(FLASH_MB),--pad $$$$(shell expr $$$$(FLASH_MB) / 2))
IMAGE/sysupgrade.bin := cfe-bin | append-metadata
BLOCKSIZE := 0x10000
IMAGE_OFFSET :=
FLASH_MB :=
CFE_BOARD_ID :=
CFE_EXTRAS = --block-size $$(BLOCKSIZE) \
--image-offset $$(if $$(IMAGE_OFFSET),$$(IMAGE_OFFSET),$$(BLOCKSIZE))
endef
# Legacy CFEs with specific LZMA parameters and no length
define Device/bcm63xx-cfe-legacy
$(Device/bcm63xx-cfe)
KERNEL := kernel-bin | append-dtb | relocate-kernel | lzma-cfe
endef
define Device/comtrend_ar-5315u
$(Device/bcm63xx-cfe)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := AR-5315u
CHIP_ID := 6318
CFE_BOARD_ID := 96318A-1441N1
FLASH_MB := 16
DEVICE_PACKAGES += $(USB2_PACKAGES)
endef
TARGET_DEVICES += comtrend_ar-5315u
define Device/comtrend_ar-5387un
$(Device/bcm63xx-cfe)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := AR-5387un
CHIP_ID := 6328
CFE_BOARD_ID := 96328A-1441N1
FLASH_MB := 16
DEVICE_PACKAGES += $(USB2_PACKAGES)
endef
TARGET_DEVICES += comtrend_ar-5387un
define Device/comtrend_vr-3025u
$(Device/bcm63xx-cfe)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := VR-3025u
CHIP_ID := 6368
CFE_BOARD_ID := 96368M-1541N
BLOCKSIZE := 0x20000
FLASH_MB := 32
DEVICE_PACKAGES += $(USB2_PACKAGES)
endef
TARGET_DEVICES += comtrend_vr-3025u
define Device/huawei_hg556a-b
$(Device/bcm63xx-cfe-legacy)
DEVICE_VENDOR := Huawei
DEVICE_MODEL := EchoLife HG556a
DEVICE_VARIANT := B
CHIP_ID := 6358
CFE_BOARD_ID := HW556
CFE_EXTRAS += --rsa-signature "EchoLife_HG556a" --tag-version 8
BLOCKSIZE := 0x20000
DEVICE_PACKAGES += $(USB2_PACKAGES)
endef
TARGET_DEVICES += huawei_hg556a-b

View File

@ -0,0 +1,81 @@
# SPDX-License-Identifier: GPL-2.0-or-later
DEVICE_VARS += CFE_PART_FLAGS CFE_PART_ID
DEVICE_VARS += CFE_RAM_FILE
DEVICE_VARS += CFE_RAM_JFFS2_NAME CFE_RAM_JFFS2_PAD
DEVICE_VARS += CFE_WFI_CHIP_ID CFE_WFI_FLASH_TYPE
DEVICE_VARS += CFE_WFI_FLAGS CFE_WFI_VERSION
DEVICE_VARS += SERCOMM_PID SERCOMM_VERSION
# CFE expects a single JFFS2 partition with cferam and kernel. However,
# it's possible to fool CFE into properly loading both cferam and kernel
# from two different JFFS2 partitions by adding dummy files (see
# cfe-jffs2-cferam and cfe-jffs2-kernel).
# Separate JFFS2 partitions allow upgrading openwrt without reflashing cferam
# JFFS2 partition, which is much safer in case anything goes wrong.
define Device/bcm63xx-nand
FILESYSTEMS := squashfs ubifs
KERNEL := kernel-bin | append-dtb | relocate-kernel | lzma | cfe-jffs2-kernel
KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | loader-lzma elf
KERNEL_INITRAMFS_SUFFIX := .elf
IMAGES := cfe.bin sysupgrade.bin
IMAGE/cfe.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) |\
cfe-jffs2-cferam | append-ubi | cfe-wfi-tag
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
KERNEL_SIZE := 5120k
CFE_PART_FLAGS :=
CFE_PART_ID :=
CFE_RAM_FILE :=
CFE_RAM_JFFS2_NAME :=
CFE_RAM_JFFS2_PAD :=
CFE_WFI_VERSION :=
CFE_WFI_CHIP_ID = 0x$$(CHIP_ID)
CFE_WFI_FLASH_TYPE :=
CFE_WFI_FLAGS :=
UBINIZE_OPTS := -E 5
DEVICE_PACKAGES += nand-utils
endef
define Device/sercomm-nand
$(Device/bcm63xx-nand)
IMAGES := factory.img sysupgrade.bin
IMAGE/factory.img := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi |\
cfe-sercomm-part | gzip | cfe-sercomm-load | cfe-sercomm-crypto
SERCOM_PID :=
SERCOMM_VERSION :=
endef
define Device/comtrend_vr-3032u
$(Device/bcm63xx-nand)
DEVICE_VENDOR := Comtrend
DEVICE_MODEL := VR-3032u
CHIP_ID := 63268
SOC := bcm63168
CFE_RAM_FILE := comtrend,vr-3032u/cferam.000
CFE_RAM_JFFS2_NAME := cferam.000
BLOCKSIZE := 128k
PAGESIZE := 2048
SUBPAGESIZE := 512
VID_HDR_OFFSET := 2048
DEVICE_PACKAGES += $(USB2_PACKAGES)
CFE_WFI_FLASH_TYPE := 3
CFE_WFI_VERSION := 0x5732
endef
TARGET_DEVICES += comtrend_vr-3032u
define Device/netgear_dgnd3700-v2
$(Device/bcm63xx-nand)
DEVICE_VENDOR := NETGEAR
DEVICE_MODEL := DGND3700
DEVICE_VARIANT := v2
CHIP_ID := 6362
CFE_RAM_FILE := netgear,dgnd3700-v2/cferam
CFE_RAM_JFFS2_NAME := cferam
CFE_RAM_JFFS2_PAD := 496k
BLOCKSIZE := 16k
PAGESIZE := 512
DEVICE_PACKAGES += $(USB2_PACKAGES)
CFE_WFI_FLASH_TYPE := 2
CFE_WFI_VERSION := 0x5731
endef
TARGET_DEVICES += netgear_dgnd3700-v2

View File

@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
# Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
# Copyright (C) 2011 OpenWrt.org
# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
#
include $(TOPDIR)/rules.mk
LZMA_TEXT_START := 0x80a00000
LOADER := loader.bin
LOADER_NAME := $(basename $(notdir $(LOADER)))
LOADER_DATA :=
TARGET_DIR :=
UART_BASE_3329 := 0xb0000100
UART_BASE_3368 := 0xfff8c100
UART_BASE_3380 := 0xb4e00200
UART_BASE_3383 := 0xb4e00500
UART_BASE_3384 := 0xb4e00500
UART_BASE_6318 := 0xb0000100
UART_BASE_6328 := 0xb0000100
UART_BASE_6338 := 0xfffe0300
UART_BASE_6345 := 0xfffe0300
UART_BASE_6348 := 0xfffe0300
UART_BASE_6358 := 0xfffe0100
UART_BASE_6362 := 0xb0000100
UART_BASE_6368 := 0xb0000100
UART_BASE_63268 := 0xb0000180
UART_BASE_6816 := 0xb0000100
UART_BASE_6818 := 0xb0000100
UART_BASE_6828 := 0xb0000180
UART_BASE := $(if $(UART_BASE_$(CHIP_ID)),$(UART_BASE_$(CHIP_ID)),0)
ifeq ($(TARGET_DIR),)
TARGET_DIR := $(KDIR)
endif
LOADER_BIN := $(TARGET_DIR)/$(LOADER_NAME).bin
LOADER_ELF := $(TARGET_DIR)/$(LOADER_NAME).elf
PKG_NAME := lzma-loader
PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME)
.PHONY : loader-compile loader.bin loader.elf
$(PKG_BUILD_DIR)/.prepared:
mkdir $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
touch $@
loader-compile: $(PKG_BUILD_DIR)/.prepared
$(MAKE) -C $(PKG_BUILD_DIR) CROSS_COMPILE="$(TARGET_CROSS)" \
LZMA_TEXT_START=$(LZMA_TEXT_START) \
LOADER_DATA=$(LOADER_DATA) \
UART_BASE=$(UART_BASE) \
clean all
loader.elf: $(PKG_BUILD_DIR)/loader.elf
$(CP) $< $(LOADER_ELF)
loader.bin: $(PKG_BUILD_DIR)/loader.bin
$(CP) $< $(LOADER_BIN)
download:
prepare: $(PKG_BUILD_DIR)/.prepared
compile: loader-compile
install:
clean:
rm -rf $(PKG_BUILD_DIR)

View File

@ -0,0 +1,584 @@
/*
LzmaDecode.c
LZMA Decoder (optimized for Speed version)
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this Code, expressly permits you to
statically or dynamically link your Code (or bind by name) to the
interfaces of this file without subjecting your linked Code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#include "LzmaDecode.h"
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*Buffer++)
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
#ifdef _LZMA_IN_CB
#define RC_TEST { if (Buffer == BufferLim) \
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
#else
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
#endif
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ UpdateBit0(p); mi <<= 1; A0; } else \
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
{ int i = numLevels; res = 1; \
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
res -= (1 << numLevels); }
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
{
unsigned char prop0;
if (size < LZMA_PROPERTIES_SIZE)
return LZMA_RESULT_DATA_ERROR;
prop0 = propsData[0];
if (prop0 >= (9 * 5 * 5))
return LZMA_RESULT_DATA_ERROR;
{
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
propsRes->lc = prop0;
/*
unsigned char remainder = (unsigned char)(prop0 / 9);
propsRes->lc = prop0 % 9;
propsRes->pb = remainder / 5;
propsRes->lp = remainder % 5;
*/
}
#ifdef _LZMA_OUT_READ
{
int i;
propsRes->DictionarySize = 0;
for (i = 0; i < 4; i++)
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
if (propsRes->DictionarySize == 0)
propsRes->DictionarySize = 1;
}
#endif
return LZMA_RESULT_OK;
}
#define kLzmaStreamWasFinishedId (-1)
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *InCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
{
CProb *p = vs->Probs;
SizeT nowPos = 0;
Byte previousByte = 0;
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
int lc = vs->Properties.lc;
#ifdef _LZMA_OUT_READ
UInt32 Range = vs->Range;
UInt32 Code = vs->Code;
#ifdef _LZMA_IN_CB
const Byte *Buffer = vs->Buffer;
const Byte *BufferLim = vs->BufferLim;
#else
const Byte *Buffer = inStream;
const Byte *BufferLim = inStream + inSize;
#endif
int state = vs->State;
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
int len = vs->RemainLen;
UInt32 globalPos = vs->GlobalPos;
UInt32 distanceLimit = vs->DistanceLimit;
Byte *dictionary = vs->Dictionary;
UInt32 dictionarySize = vs->Properties.DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos;
Byte tempDictionary[4];
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
if (len == kLzmaStreamWasFinishedId)
return LZMA_RESULT_OK;
if (dictionarySize == 0)
{
dictionary = tempDictionary;
dictionarySize = 1;
tempDictionary[0] = vs->TempDictionary[0];
}
if (len == kLzmaNeedInitId)
{
{
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
UInt32 i;
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
rep0 = rep1 = rep2 = rep3 = 1;
state = 0;
globalPos = 0;
distanceLimit = 0;
dictionaryPos = 0;
dictionary[dictionarySize - 1] = 0;
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
}
len = 0;
}
while(len != 0 && nowPos < outSize)
{
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
len--;
}
if (dictionaryPos == 0)
previousByte = dictionary[dictionarySize - 1];
else
previousByte = dictionary[dictionaryPos - 1];
#else /* if !_LZMA_OUT_READ */
int state = 0;
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
int len = 0;
const Byte *Buffer;
const Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
{
UInt32 i;
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
}
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
#endif /* _LZMA_OUT_READ */
while(nowPos < outSize)
{
CProb *prob;
UInt32 bound;
int posState = (int)(
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& posStateMask);
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
int symbol = 1;
UpdateBit0(prob)
prob = p + Literal + (LZMA_LIT_SIZE *
(((
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state >= kNumLitStates)
{
int matchByte;
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
matchByte = dictionary[pos];
#else
matchByte = outStream[nowPos - rep0];
#endif
do
{
int bit;
CProb *probLit;
matchByte <<= 1;
bit = (matchByte & 0x100);
probLit = prob + 0x100 + bit + symbol;
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
}
while (symbol < 0x100);
}
while (symbol < 0x100)
{
CProb *probLit = prob + symbol;
RC_GET_BIT(probLit, symbol)
}
previousByte = (Byte)symbol;
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#endif
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
}
else
{
UpdateBit1(prob);
prob = p + IsRep + state;
IfBit0(prob)
{
UpdateBit0(prob);
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < kNumLitStates ? 0 : 3;
prob = p + LenCoder;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG0 + state;
IfBit0(prob)
{
UpdateBit0(prob);
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
#ifdef _LZMA_OUT_READ
UInt32 pos;
#endif
UpdateBit0(prob);
#ifdef _LZMA_OUT_READ
if (distanceLimit == 0)
#else
if (nowPos == 0)
#endif
return LZMA_RESULT_DATA_ERROR;
state = state < kNumLitStates ? 9 : 11;
#ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
#endif
continue;
}
else
{
UpdateBit1(prob);
}
}
else
{
UInt32 distance;
UpdateBit1(prob);
prob = p + IsRepG1 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep1;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG2 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep2;
}
else
{
UpdateBit1(prob);
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < kNumLitStates ? 8 : 11;
prob = p + RepLenCoder;
}
{
int numBits, offset;
CProb *probLen = prob + LenChoice;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
numBits = kLenNumLowBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenChoice2;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
numBits = kLenNumMidBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
numBits = kLenNumHighBits;
}
}
RangeDecoderBitTreeDecode(probLen, numBits, len);
len += offset;
}
if (state < 4)
{
int posSlot;
state += kNumLitStates;
prob = p + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
rep0 = (2 | ((UInt32)posSlot & 1));
if (posSlot < kEndPosModelIndex)
{
rep0 <<= numDirectBits;
prob = p + SpecPos + rep0 - posSlot - 1;
}
else
{
numDirectBits -= kNumAlignBits;
do
{
RC_NORMALIZE
Range >>= 1;
rep0 <<= 1;
if (Code >= Range)
{
Code -= Range;
rep0 |= 1;
}
}
while (--numDirectBits != 0);
prob = p + Align;
rep0 <<= kNumAlignBits;
numDirectBits = kNumAlignBits;
}
{
int i = 1;
int mi = 1;
do
{
CProb *prob3 = prob + mi;
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
i <<= 1;
}
while(--numDirectBits != 0);
}
}
else
rep0 = posSlot;
if (++rep0 == (UInt32)(0))
{
/* it's for stream version */
len = kLzmaStreamWasFinishedId;
break;
}
}
len += kMatchMinLen;
#ifdef _LZMA_OUT_READ
if (rep0 > distanceLimit)
#else
if (rep0 > nowPos)
#endif
return LZMA_RESULT_DATA_ERROR;
#ifdef _LZMA_OUT_READ
if (dictionarySize - distanceLimit > (UInt32)len)
distanceLimit += len;
else
distanceLimit = dictionarySize;
#endif
do
{
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
len--;
outStream[nowPos++] = previousByte;
}
while(len != 0 && nowPos < outSize);
}
}
RC_NORMALIZE;
#ifdef _LZMA_OUT_READ
vs->Range = Range;
vs->Code = Code;
vs->DictionaryPos = dictionaryPos;
vs->GlobalPos = globalPos + (UInt32)nowPos;
vs->DistanceLimit = distanceLimit;
vs->Reps[0] = rep0;
vs->Reps[1] = rep1;
vs->Reps[2] = rep2;
vs->Reps[3] = rep3;
vs->State = state;
vs->RemainLen = len;
vs->TempDictionary[0] = tempDictionary[0];
#endif
#ifdef _LZMA_IN_CB
vs->Buffer = Buffer;
vs->BufferLim = BufferLim;
#else
*inSizeProcessed = (SizeT)(Buffer - inStream);
#endif
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}

View File

@ -0,0 +1,113 @@
/*
LzmaDecode.h
LZMA Decoder interface
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to
statically or dynamically link your code (or bind by name) to the
interfaces of this file without subjecting your linked code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
#ifndef __LZMADECODE_H
#define __LZMADECODE_H
#include "LzmaTypes.h"
/* #define _LZMA_IN_CB */
/* Use callback for input data */
/* #define _LZMA_OUT_READ */
/* Use read function for output data */
/* #define _LZMA_PROB32 */
/* It can increase speed on some 32-bit CPUs,
but memory usage will be doubled in that case */
/* #define _LZMA_LOC_OPT */
/* Enable local speed optimizations inside code */
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16
#endif
#define LZMA_RESULT_OK 0
#define LZMA_RESULT_DATA_ERROR 1
#ifdef _LZMA_IN_CB
typedef struct _ILzmaInCallback
{
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
} ILzmaInCallback;
#endif
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
typedef struct _CLzmaProperties
{
int lc;
int lp;
int pb;
#ifdef _LZMA_OUT_READ
UInt32 DictionarySize;
#endif
}CLzmaProperties;
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
#define kLzmaNeedInitId (-2)
typedef struct _CLzmaDecoderState
{
CLzmaProperties Properties;
CProb *Probs;
#ifdef _LZMA_IN_CB
const unsigned char *Buffer;
const unsigned char *BufferLim;
#endif
#ifdef _LZMA_OUT_READ
unsigned char *Dictionary;
UInt32 Range;
UInt32 Code;
UInt32 DictionaryPos;
UInt32 GlobalPos;
UInt32 DistanceLimit;
UInt32 Reps[4];
int State;
int RemainLen;
unsigned char TempDictionary[4];
#endif
} CLzmaDecoderState;
#ifdef _LZMA_OUT_READ
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
#endif
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
#endif

View File

@ -0,0 +1,45 @@
/*
LzmaTypes.h
Types for LZMA Decoder
This file written and distributed to public domain by Igor Pavlov.
This file is part of LZMA SDK 4.40 (2006-05-01)
*/
#ifndef __LZMATYPES_H
#define __LZMATYPES_H
#ifndef _7ZIP_BYTE_DEFINED
#define _7ZIP_BYTE_DEFINED
typedef unsigned char Byte;
#endif
#ifndef _7ZIP_UINT16_DEFINED
#define _7ZIP_UINT16_DEFINED
typedef unsigned short UInt16;
#endif
#ifndef _7ZIP_UINT32_DEFINED
#define _7ZIP_UINT32_DEFINED
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#endif
/* #define _LZMA_NO_SYSTEM_SIZE_T */
/* You can use it, if you don't want <stddef.h> */
#ifndef _7ZIP_SIZET_DEFINED
#define _7ZIP_SIZET_DEFINED
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
#include <stddef.h>
typedef size_t SizeT;
#endif
#endif
#endif

View File

@ -0,0 +1,85 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Makefile for the LZMA compressed kernel loader for BMIPS based boards
#
# Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
# Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
#
# Some parts of this file was based on the OpenWrt specific lzma-loader
# for the BCM47xx and ADM5120 based boards:
# Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
# Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com>
# Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
#
LOADER_ADDR :=
KERNEL_ADDR :=
LZMA_TEXT_START := 0x80a00000
LOADER_DATA :=
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
BIN_FLAGS := -O binary -R .reginfo -R .note -R .comment -R .mdebug \
-R .MIPS.abiflags -S
CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
-fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 \
-mno-abicalls -fno-pic -ffunction-sections -pipe \
-ffreestanding -fhonour-copts \
-mabi=32 -march=mips32 \
-Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
CFLAGS += -D_LZMA_PROB32
CFLAGS += -DUART_BASE=$(UART_BASE)
ASFLAGS = $(CFLAGS) -D__ASSEMBLY__
LDFLAGS = -static --gc-sections -no-warn-mismatch
LDFLAGS += -e startup -T loader.lds -Ttext $(LZMA_TEXT_START)
O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
OBJECTS := head.o loader.o cache.o board.o printf.o LzmaDecode.o
ifneq ($(strip $(LOADER_DATA)),)
OBJECTS += data.o
CFLAGS += -DLZMA_WRAPPER=1 -DLOADADDR=$(KERNEL_ADDR)
endif
all: loader.elf
# Don't build dependencies, this may die if $(CC) isn't gcc
dep:
install:
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
%.o : %.S
$(CC) $(ASFLAGS) -c -o $@ $<
data.o: $(LOADER_DATA)
$(LD) -r -b binary --oformat $(O_FORMAT) -T lzma-data.lds -o $@ $<
loader: $(OBJECTS)
$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
loader.bin: loader
$(OBJCOPY) $(BIN_FLAGS) $< $@
loader2.o: loader.bin
$(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $<
loader.elf: loader2.o
$(LD) -e startup -T loader2.lds -Ttext $(LOADER_ADDR) -o $@ $<
mrproper: clean
clean:
rm -f loader *.elf *.bin *.o

View File

@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* BCM63XX specific implementation parts
*
* Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
* Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
*/
#include <stddef.h>
#include "config.h"
#define READREG(r) *(volatile unsigned int *)(r)
#define WRITEREG(r,v) *(volatile unsigned int *)(r) = v
#define UART_IR_REG 0x10
#define UART_FIFO_REG 0x14
static void wait_xfered(void)
{
unsigned int val;
do {
val = READREG(UART_BASE + UART_IR_REG);
if (val & (1 << 5))
break;
} while (1);
}
void board_putc(int ch)
{
if (!UART_BASE)
return;
wait_xfered();
WRITEREG(UART_BASE + UART_FIFO_REG, ch);
wait_xfered();
}

View File

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* The cache manipulation routine has been taken from the U-Boot project.
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
*/
#include "cache.h"
#include "cacheops.h"
#include "config.h"
#include "printf.h"
#define cache_op(op,addr) \
__asm__ __volatile__( \
" .set push \n" \
" .set noreorder \n" \
" .set mips3\n\t \n" \
" cache %0, %1 \n" \
" .set pop \n" \
: \
: "i" (op), "R" (*(unsigned char *)(addr)))
void flush_cache(unsigned long start_addr, unsigned long size)
{
unsigned long lsize = CONFIG_CACHELINE_SIZE;
unsigned long addr = start_addr & ~(lsize - 1);
unsigned long aend = (start_addr + size + (lsize - 1)) & ~(lsize - 1);
printf("blasting from 0x%08x to 0x%08x (0x%08x - 0x%08x)\n", start_addr, size, addr, aend);
while (1) {
cache_op(Hit_Writeback_Inv_D, addr);
cache_op(Hit_Invalidate_I, addr);
if (addr == aend)
break;
addr += lsize;
}
}

View File

@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*/
#ifndef __CACHE_H
#define __CACHE_H
void flush_cache(unsigned long start_addr, unsigned long size);
#endif /* __CACHE_H */

View File

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Cache operations for the cache instruction.
*
* (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle
* (C) Copyright 1999 Silicon Graphics, Inc.
*/
#ifndef __ASM_CACHEOPS_H
#define __ASM_CACHEOPS_H
/*
* Cache Operations available on all MIPS processors with R4000-style caches
*/
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
#define Index_Load_Tag_I 0x04
#define Index_Load_Tag_D 0x05
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
#if defined(CONFIG_CPU_LOONGSON2)
#define Hit_Invalidate_I 0x00
#else
#define Hit_Invalidate_I 0x10
#endif
#define Hit_Invalidate_D 0x11
#define Hit_Writeback_Inv_D 0x15
/*
* R4000-specific cacheops
*/
#define Create_Dirty_Excl_D 0x0d
#define Fill 0x14
#define Hit_Writeback_I 0x18
#define Hit_Writeback_D 0x19
/*
* R4000SC and R4400SC-specific cacheops
*/
#define Index_Invalidate_SI 0x02
#define Index_Writeback_Inv_SD 0x03
#define Index_Load_Tag_SI 0x06
#define Index_Load_Tag_SD 0x07
#define Index_Store_Tag_SI 0x0A
#define Index_Store_Tag_SD 0x0B
#define Create_Dirty_Excl_SD 0x0f
#define Hit_Invalidate_SI 0x12
#define Hit_Invalidate_SD 0x13
#define Hit_Writeback_Inv_SD 0x17
#define Hit_Writeback_SD 0x1b
#define Hit_Set_Virtual_SI 0x1e
#define Hit_Set_Virtual_SD 0x1f
/*
* R5000-specific cacheops
*/
#define R5K_Page_Invalidate_S 0x17
/*
* RM7000-specific cacheops
*/
#define Page_Invalidate_T 0x16
/*
* R10000-specific cacheops
*
* Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
* Most of the _S cacheops are identical to the R4000SC _SD cacheops.
*/
#define Index_Writeback_Inv_S 0x03
#define Index_Load_Tag_S 0x07
#define Index_Store_Tag_S 0x0B
#define Hit_Invalidate_S 0x13
#define Cache_Barrier 0x14
#define Hit_Writeback_Inv_S 0x17
#define Index_Load_Data_I 0x18
#define Index_Load_Data_D 0x19
#define Index_Load_Data_S 0x1b
#define Index_Store_Data_I 0x1c
#define Index_Store_Data_D 0x1d
#define Index_Store_Data_S 0x1f
#endif /* __ASM_CACHEOPS_H */

View File

@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define CONFIG_ICACHE_SIZE (32 * 1024)
#define CONFIG_DCACHE_SIZE (32 * 1024)
#define CONFIG_CACHELINE_SIZE 16
#endif /* _CONFIG_H_ */

View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
*
* Copyright (C) 2001, Monta Vista Software
* Author: jsun@mvista.com or jsun@junsun.net
*/
#ifndef _cp0regdef_h_
#define _cp0regdef_h_
#define CP0_INDEX $0
#define CP0_RANDOM $1
#define CP0_ENTRYLO0 $2
#define CP0_ENTRYLO1 $3
#define CP0_CONTEXT $4
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
#define CP0_BADVADDR $8
#define CP0_COUNT $9
#define CP0_ENTRYHI $10
#define CP0_COMPARE $11
#define CP0_STATUS $12
#define CP0_CAUSE $13
#define CP0_EPC $14
#define CP0_PRID $15
#define CP0_CONFIG $16
#define CP0_LLADDR $17
#define CP0_WATCHLO $18
#define CP0_WATCHHI $19
#define CP0_XCONTEXT $20
#define CP0_FRAMEMASK $21
#define CP0_DIAGNOSTIC $22
#define CP0_PERFORMANCE $25
#define CP0_ECC $26
#define CP0_CACHEERR $27
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CP0_ERROREPC $30
#define read_32bit_c0_register(reg,sel) \
({ int __res; \
if (sel == 0) \
__asm__ __volatile__( \
"mfc0\t%0, " #reg "\n\t" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mfc0\t%0, " #reg ", " #sel "\n\t" \
".set mips0\n\t" \
: "=r" (__res)); \
__res; \
})
#endif

View File

@ -0,0 +1,118 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Some parts of this code was based on the OpenWrt specific lzma-loader
* for the BCM47xx and ADM5120 based boards:
* Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*/
#include <asm/asm.h>
#include <asm/regdef.h>
#include "cp0regdef.h"
#include "cacheops.h"
#include "config.h"
#define KSEG0 0x80000000
.macro ehb
sll zero, 3
.endm
.text
LEAF(startup)
.set noreorder
.set mips32
mtc0 zero, CP0_WATCHLO # clear watch registers
mtc0 zero, CP0_WATCHHI
mtc0 zero, CP0_CAUSE # clear before writing status register
mfc0 t0, CP0_STATUS
li t1, 0x1000001f
or t0, t1
xori t0, 0x1f
mtc0 t0, CP0_STATUS
ehb
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
ehb
la t0, __reloc_label # get linked address of label
bal __reloc_label # branch and link to label to
nop # get actual address
__reloc_label:
subu t0, ra, t0 # get reloc_delta
beqz t0, __reloc_done # if delta is 0 we are in the right place
nop
/* Copy our code to the right place */
la t1, _code_start # get linked address of _code_start
la t2, _code_end # get linked address of _code_end
addu t0, t0, t1 # calculate actual address of _code_start
__reloc_copy:
lw t3, 0(t0)
sw t3, 0(t1)
add t1, 4
blt t1, t2, __reloc_copy
add t0, 4
/* flush cache */
la t0, _code_start
la t1, _code_end
li t2, ~(CONFIG_CACHELINE_SIZE - 1)
and t0, t2
and t1, t2
li t2, CONFIG_CACHELINE_SIZE
b __flush_check
nop
__flush_line:
cache Hit_Writeback_Inv_D, 0(t0)
cache Hit_Invalidate_I, 0(t0)
add t0, t2
__flush_check:
bne t0, t1, __flush_line
nop
sync
__reloc_done:
/* clear bss */
la t0, _bss_start
la t1, _bss_end
b __bss_check
nop
__bss_fill:
sw zero, 0(t0)
addi t0, 4
__bss_check:
bne t0, t1, __bss_fill
nop
/* Setup new "C" stack */
la sp, _stack
/* reserve stack space for a0-a3 registers */
subu sp, 16
/* jump to the decompressor routine */
la t0, loader_main
jr t0
nop
.set reorder
END(startup)

View File

@ -0,0 +1,169 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Some parts of this code was based on the OpenWrt specific lzma-loader
* for the BCM47xx and ADM5120 based boards:
* Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
* Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com>
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*
* The image_header structure has been taken from the U-Boot project.
* (C) Copyright 2008 Semihalf
* (C) Copyright 2000-2005
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <stddef.h>
#include <stdint.h>
#include "config.h"
#include "cache.h"
#include "printf.h"
#include "LzmaDecode.h"
#define KSEG0 0x80000000
#define KSEG1 0xa0000000
#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
#undef LZMA_DEBUG
#ifdef LZMA_DEBUG
# define DBG(f, a...) printf(f, ## a)
#else
# define DBG(f, a...) do {} while (0)
#endif
/* beyond the image end, size not known in advance */
extern unsigned char workspace[];
static CLzmaDecoderState lzma_state;
static unsigned char *lzma_data;
static unsigned long lzma_datasize;
static unsigned long lzma_outsize;
static unsigned long kernel_la;
static void halt(void)
{
printf("\nSystem halted!\n");
for(;;);
}
static __inline__ unsigned char lzma_get_byte(void)
{
unsigned char c;
lzma_datasize--;
c = *lzma_data++;
return c;
}
static int lzma_init_props(void)
{
unsigned char props[LZMA_PROPERTIES_SIZE];
int res;
int i;
/* read lzma properties */
for (i = 0; i < LZMA_PROPERTIES_SIZE; i++)
props[i] = lzma_get_byte();
/* read the lower half of uncompressed size in the header */
lzma_outsize = ((SizeT) lzma_get_byte()) +
((SizeT) lzma_get_byte() << 8) +
((SizeT) lzma_get_byte() << 16) +
((SizeT) lzma_get_byte() << 24);
/* skip rest of the header (upper half of uncompressed size) */
for (i = 0; i < 4; i++)
lzma_get_byte();
res = LzmaDecodeProperties(&lzma_state.Properties, props,
LZMA_PROPERTIES_SIZE);
return res;
}
static int lzma_decompress(unsigned char *outStream)
{
SizeT ip, op;
int ret;
lzma_state.Probs = (CProb *) workspace;
ret = LzmaDecode(&lzma_state, lzma_data, lzma_datasize, &ip, outStream,
lzma_outsize, &op);
if (ret != LZMA_RESULT_OK) {
int i;
DBG("LzmaDecode error %d at %08x, osize:%d ip:%d op:%d\n",
ret, lzma_data + ip, lzma_outsize, ip, op);
for (i = 0; i < 16; i++)
DBG("%02x ", lzma_data[ip + i]);
DBG("\n");
}
return ret;
}
static void lzma_init_data(void)
{
extern unsigned char _lzma_data_start[];
extern unsigned char _lzma_data_end[];
kernel_la = LOADADDR;
lzma_data = _lzma_data_start;
lzma_datasize = _lzma_data_end - _lzma_data_start;
}
void loader_main(unsigned long reg_a0, unsigned long reg_a1,
unsigned long reg_a2, unsigned long reg_a3)
{
void (*kernel_entry) (unsigned long, unsigned long, unsigned long,
unsigned long);
int res;
printf("\n\nOpenWrt kernel loader for BMIPS\n");
printf("Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>\n");
printf("Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>\n");
printf("Copyright (C) 2020 Alvaro Fernandez Rojas <noltari@gmail.com>\n");
lzma_init_data();
res = lzma_init_props();
if (res != LZMA_RESULT_OK) {
printf("Incorrect LZMA stream properties!\n");
halt();
}
printf("Decompressing kernel... ");
res = lzma_decompress((unsigned char *) kernel_la);
if (res != LZMA_RESULT_OK) {
printf("failed, ");
switch (res) {
case LZMA_RESULT_DATA_ERROR:
printf("data error!\n");
break;
default:
printf("unknown error %d!\n", res);
}
halt();
} else {
printf("done!\n");
}
flush_cache(kernel_la, lzma_outsize);
printf("Starting kernel at %08x...\n\n", kernel_la);
kernel_entry = (void *) kernel_la;
kernel_entry(reg_a0, reg_a1, reg_a2, reg_a3);
}

View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
OUTPUT_ARCH(mips)
SECTIONS {
.text : {
_code_start = .;
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
*(.data.lzma)
}
. = ALIGN(32);
.data : {
*(.data)
*(.data.*)
}
. = ALIGN(32);
_code_end = .;
_bss_start = .;
.bss : {
*(.bss)
*(.bss.*)
}
. = ALIGN(32);
_bss_end = .;
. = . + 8192;
_stack = .;
workspace = .;
}

View File

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
OUTPUT_ARCH(mips)
SECTIONS {
.text : {
startup = .;
*(.text)
*(.text.*)
*(.data)
*(.data.*)
}
}

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
OUTPUT_ARCH(mips)
SECTIONS {
.data.lzma : {
_lzma_data_start = .;
*(.data)
_lzma_data_end = .;
}
}

View File

@ -0,0 +1,345 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*/
#include "printf.h"
extern void board_putc(int ch);
/* this is the maximum width for a variable */
#define LP_MAX_BUF 256
/* macros */
#define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') )
#define Ctod(x) ( (x) - '0')
/* forward declaration */
static int PrintChar(char *, char, int, int);
static int PrintString(char *, char *, int, int);
static int PrintNum(char *, unsigned long, int, int, int, int, char, int);
/* private variable */
static const char theFatalMsg[] = "fatal error in lp_Print!";
/* -*-
* A low level printf() function.
*/
static void
lp_Print(void (*output)(void *, char *, int),
void * arg,
char *fmt,
va_list ap)
{
#define OUTPUT(arg, s, l) \
{ if (((l) < 0) || ((l) > LP_MAX_BUF)) { \
(*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \
} else { \
(*output)(arg, s, l); \
} \
}
char buf[LP_MAX_BUF];
char c;
char *s;
long int num;
int longFlag;
int negFlag;
int width;
int prec;
int ladjust;
char padc;
int length;
for(;;) {
{
/* scan for the next '%' */
char *fmtStart = fmt;
while ( (*fmt != '\0') && (*fmt != '%')) {
fmt ++;
}
/* flush the string found so far */
OUTPUT(arg, fmtStart, fmt-fmtStart);
/* are we hitting the end? */
if (*fmt == '\0') break;
}
/* we found a '%' */
fmt ++;
/* check for long */
if (*fmt == 'l') {
longFlag = 1;
fmt ++;
} else {
longFlag = 0;
}
/* check for other prefixes */
width = 0;
prec = -1;
ladjust = 0;
padc = ' ';
if (*fmt == '-') {
ladjust = 1;
fmt ++;
}
if (*fmt == '0') {
padc = '0';
fmt++;
}
if (IsDigit(*fmt)) {
while (IsDigit(*fmt)) {
width = 10 * width + Ctod(*fmt++);
}
}
if (*fmt == '.') {
fmt ++;
if (IsDigit(*fmt)) {
prec = 0;
while (IsDigit(*fmt)) {
prec = prec*10 + Ctod(*fmt++);
}
}
}
/* check format flag */
negFlag = 0;
switch (*fmt) {
case 'b':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'd':
case 'D':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
if (num < 0) {
num = - num;
negFlag = 1;
}
length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'o':
case 'O':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'u':
case 'U':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'x':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0);
OUTPUT(arg, buf, length);
break;
case 'X':
if (longFlag) {
num = va_arg(ap, long int);
} else {
num = va_arg(ap, int);
}
length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1);
OUTPUT(arg, buf, length);
break;
case 'c':
c = (char)va_arg(ap, int);
length = PrintChar(buf, c, width, ladjust);
OUTPUT(arg, buf, length);
break;
case 's':
s = (char*)va_arg(ap, char *);
length = PrintString(buf, s, width, ladjust);
OUTPUT(arg, buf, length);
break;
case '\0':
fmt --;
break;
default:
/* output this char as it is */
OUTPUT(arg, fmt, 1);
} /* switch (*fmt) */
fmt ++;
} /* for(;;) */
/* special termination call */
OUTPUT(arg, "\0", 1);
}
/* --------------- local help functions --------------------- */
static int
PrintChar(char * buf, char c, int length, int ladjust)
{
int i;
if (length < 1) length = 1;
if (ladjust) {
*buf = c;
for (i=1; i< length; i++) buf[i] = ' ';
} else {
for (i=0; i< length-1; i++) buf[i] = ' ';
buf[length - 1] = c;
}
return length;
}
static int
PrintString(char * buf, char* s, int length, int ladjust)
{
int i;
int len=0;
char* s1 = s;
while (*s1++) len++;
if (length < len) length = len;
if (ladjust) {
for (i=0; i< len; i++) buf[i] = s[i];
for (i=len; i< length; i++) buf[i] = ' ';
} else {
for (i=0; i< length-len; i++) buf[i] = ' ';
for (i=length-len; i < length; i++) buf[i] = s[i-length+len];
}
return length;
}
static int
PrintNum(char * buf, unsigned long u, int base, int negFlag,
int length, int ladjust, char padc, int upcase)
{
/* algorithm :
* 1. prints the number from left to right in reverse form.
* 2. fill the remaining spaces with padc if length is longer than
* the actual length
* TRICKY : if left adjusted, no "0" padding.
* if negtive, insert "0" padding between "0" and number.
* 3. if (!ladjust) we reverse the whole string including paddings
* 4. otherwise we only reverse the actual string representing the num.
*/
int actualLength =0;
char *p = buf;
int i;
do {
int tmp = u %base;
if (tmp <= 9) {
*p++ = '0' + tmp;
} else if (upcase) {
*p++ = 'A' + tmp - 10;
} else {
*p++ = 'a' + tmp - 10;
}
u /= base;
} while (u != 0);
if (negFlag) {
*p++ = '-';
}
/* figure out actual length and adjust the maximum length */
actualLength = p - buf;
if (length < actualLength) length = actualLength;
/* add padding */
if (ladjust) {
padc = ' ';
}
if (negFlag && !ladjust && (padc == '0')) {
for (i = actualLength-1; i< length-1; i++) buf[i] = padc;
buf[length -1] = '-';
} else {
for (i = actualLength; i< length; i++) buf[i] = padc;
}
/* prepare to reverse the string */
{
int begin = 0;
int end;
if (ladjust) {
end = actualLength - 1;
} else {
end = length -1;
}
while (end > begin) {
char tmp = buf[begin];
buf[begin] = buf[end];
buf[end] = tmp;
begin ++;
end --;
}
}
/* adjust the string pointer */
return length;
}
static void printf_output(void *arg, char *s, int l)
{
int i;
// special termination call
if ((l==1) && (s[0] == '\0')) return;
for (i=0; i< l; i++) {
board_putc(s[i]);
if (s[i] == '\n') board_putc('\r');
}
}
void printf(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
lp_Print(printf_output, 0, fmt, ap);
va_end(ap);
}

View File

@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*/
#ifndef _printf_h_
#define _printf_h_
#include <stdarg.h>
void printf(char *fmt, ...);
#endif /* _printf_h_ */

View File

@ -0,0 +1,31 @@
CONFIG_CRC16=y
CONFIG_CRYPTO_ACOMP2=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_JFFS2_FS_NAND=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MTD_NAND_BRCMNAND=y
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPLIT_BCM_WFI_FW=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
# CONFIG_MTD_UBI_FASTMAP is not set
# CONFIG_MTD_UBI_GLUEBI is not set
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_SGL_ALLOC=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
CONFIG_UBIFS_FS_ZSTD=y
CONFIG_XXHASH=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y

View File

@ -0,0 +1,6 @@
BOARDNAME:=nand
FEATURES+=nand
define Target/Description
BMIPS boards with NAND support
endef

View File

@ -0,0 +1,27 @@
From 29906e1aac11bf9907e26608216dc7970e73a70e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:33 +0200
Subject: [PATCH 1/9] mips: bmips: select ARCH_HAS_RESET_CONTROLLER
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This allows to add reset controllers support.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/Kconfig | 1 +
1 file changed, 1 insertion(+)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -249,6 +249,7 @@ config ATH79
config BMIPS_GENERIC
bool "Broadcom Generic BMIPS kernel"
+ select ARCH_HAS_RESET_CONTROLLER
select ARCH_HAS_SYNC_DMA_FOR_CPU_ALL
select ARCH_HAS_PHYS_TO_DMA
select BOOT_RAW

View File

@ -0,0 +1,59 @@
From 10c1e714a68b45b124157aa02d80abe244a2a61a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:34 +0200
Subject: [PATCH 2/9] dt-bindings: reset: add BCM6345 reset controller bindings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add device tree binding documentation for BCM6345 reset controller.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
.../bindings/reset/brcm,bcm6345-reset.yaml | 37 +++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.yaml
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/reset/brcm,bcm6345-reset.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: BCM6345 reset controller
+
+description: This document describes the BCM6345 reset controller.
+
+maintainers:
+ - Álvaro Fernández Rojas <noltari@gmail.com>
+
+properties:
+ compatible:
+ const: brcm,bcm6345-reset
+
+ reg:
+ maxItems: 1
+
+ "#reset-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ reset-controller@10000010 {
+ compatible = "brcm,bcm6345-reset";
+ reg = <0x10000010 0x4>;
+ #reset-cells = <1>;
+ };

View File

@ -0,0 +1,186 @@
From aac025437f14c1647dc6054b95daeebed34f6971 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:35 +0200
Subject: [PATCH 3/9] reset: add BCM6345 reset controller driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add support for resetting blocks through the Linux reset controller
subsystem for BCM63xx SoCs.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Florian Fainelli <F.fainelli@gmail.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
drivers/reset/Kconfig | 7 ++
drivers/reset/Makefile | 1 +
drivers/reset/reset-bcm6345.c | 135 ++++++++++++++++++++++++++++++++++
3 files changed, 143 insertions(+)
create mode 100644 drivers/reset/reset-bcm6345.c
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -35,6 +35,13 @@ config RESET_AXS10X
help
This enables the reset controller driver for AXS10x.
+config RESET_BCM6345
+ bool "BCM6345 Reset Controller"
+ depends on BMIPS_GENERIC || COMPILE_TEST
+ default BMIPS_GENERIC
+ help
+ This enables the reset controller driver for BCM6345 SoCs.
+
config RESET_BERLIN
bool "Berlin Reset Driver" if COMPILE_TEST
default ARCH_BERLIN
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o
+obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
--- /dev/null
+++ b/drivers/reset/reset-bcm6345.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * BCM6345 Reset Controller Driver
+ *
+ * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+#define BCM6345_RESET_NUM 32
+#define BCM6345_RESET_SLEEP_MIN_US 10000
+#define BCM6345_RESET_SLEEP_MAX_US 20000
+
+struct bcm6345_reset {
+ struct reset_controller_dev rcdev;
+ void __iomem *base;
+ spinlock_t lock;
+};
+
+static inline struct bcm6345_reset *
+to_bcm6345_reset(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct bcm6345_reset, rcdev);
+}
+
+static int bcm6345_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct bcm6345_reset *bcm6345_reset = to_bcm6345_reset(rcdev);
+ unsigned long flags;
+ uint32_t val;
+
+ spin_lock_irqsave(&bcm6345_reset->lock, flags);
+ val = __raw_readl(bcm6345_reset->base);
+ if (assert)
+ val &= ~BIT(id);
+ else
+ val |= BIT(id);
+ __raw_writel(val, bcm6345_reset->base);
+ spin_unlock_irqrestore(&bcm6345_reset->lock, flags);
+
+ return 0;
+}
+
+static int bcm6345_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return bcm6345_reset_update(rcdev, id, true);
+}
+
+static int bcm6345_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return bcm6345_reset_update(rcdev, id, false);
+}
+
+static int bcm6345_reset_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ bcm6345_reset_update(rcdev, id, true);
+ usleep_range(BCM6345_RESET_SLEEP_MIN_US,
+ BCM6345_RESET_SLEEP_MAX_US);
+
+ bcm6345_reset_update(rcdev, id, false);
+ /*
+ * Ensure component is taken out reset state by sleeping also after
+ * deasserting the reset. Otherwise, the component may not be ready
+ * for operation.
+ */
+ usleep_range(BCM6345_RESET_SLEEP_MIN_US,
+ BCM6345_RESET_SLEEP_MAX_US);
+
+ return 0;
+}
+
+static int bcm6345_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct bcm6345_reset *bcm6345_reset = to_bcm6345_reset(rcdev);
+
+ return !(__raw_readl(bcm6345_reset->base) & BIT(id));
+}
+
+static struct reset_control_ops bcm6345_reset_ops = {
+ .assert = bcm6345_reset_assert,
+ .deassert = bcm6345_reset_deassert,
+ .reset = bcm6345_reset_reset,
+ .status = bcm6345_reset_status,
+};
+
+static int bcm6345_reset_probe(struct platform_device *pdev)
+{
+ struct bcm6345_reset *bcm6345_reset;
+
+ bcm6345_reset = devm_kzalloc(&pdev->dev,
+ sizeof(*bcm6345_reset), GFP_KERNEL);
+ if (!bcm6345_reset)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, bcm6345_reset);
+
+ bcm6345_reset->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(bcm6345_reset->base))
+ return PTR_ERR(bcm6345_reset->base);
+
+ spin_lock_init(&bcm6345_reset->lock);
+ bcm6345_reset->rcdev.ops = &bcm6345_reset_ops;
+ bcm6345_reset->rcdev.owner = THIS_MODULE;
+ bcm6345_reset->rcdev.of_node = pdev->dev.of_node;
+ bcm6345_reset->rcdev.of_reset_n_cells = 1;
+ bcm6345_reset->rcdev.nr_resets = BCM6345_RESET_NUM;
+
+ return devm_reset_controller_register(&pdev->dev,
+ &bcm6345_reset->rcdev);
+}
+
+static const struct of_device_id bcm6345_reset_of_match[] = {
+ { .compatible = "brcm,bcm6345-reset" },
+ { /* sentinel */ },
+};
+
+static struct platform_driver bcm6345_reset_driver = {
+ .probe = bcm6345_reset_probe,
+ .driver = {
+ .name = "bcm6345-reset",
+ .of_match_table = bcm6345_reset_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(bcm6345_reset_driver);

View File

@ -0,0 +1,56 @@
From 83f865d7e32e40b4903b1f83537c63fc5cdf1eb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:36 +0200
Subject: [PATCH 4/9] mips: bmips: dts: add BCM6328 reset controller support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM6328 SoCs have a reset controller for certain components.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/boot/dts/brcm/bcm6328.dtsi | 6 ++++++
include/dt-bindings/reset/bcm6328-reset.h | 18 ++++++++++++++++++
2 files changed, 24 insertions(+)
create mode 100644 include/dt-bindings/reset/bcm6328-reset.h
--- a/arch/mips/boot/dts/brcm/bcm6328.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi
@@ -57,6 +57,12 @@
#clock-cells = <1>;
};
+ periph_rst: reset-controller@10000010 {
+ compatible = "brcm,bcm6345-reset";
+ reg = <0x10000010 0x4>;
+ #reset-cells = <1>;
+ };
+
periph_intc: interrupt-controller@10000020 {
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x10>,
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6328-reset.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6328_H
+#define __DT_BINDINGS_RESET_BCM6328_H
+
+#define BCM6328_RST_SPI 0
+#define BCM6328_RST_EPHY 1
+#define BCM6328_RST_SAR 2
+#define BCM6328_RST_ENETSW 3
+#define BCM6328_RST_USBS 4
+#define BCM6328_RST_USBH 5
+#define BCM6328_RST_PCM 6
+#define BCM6328_RST_PCIE_CORE 7
+#define BCM6328_RST_PCIE 8
+#define BCM6328_RST_PCIE_EXT 9
+#define BCM6328_RST_PCIE_HARD 10
+
+#endif /* __DT_BINDINGS_RESET_BCM6328_H */

View File

@ -0,0 +1,53 @@
From 8079cfba4c7b8cae900c27104b4512fa5ed1f021 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:37 +0200
Subject: [PATCH 5/9] mips: bmips: dts: add BCM6358 reset controller support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM6358 SoCs have a reset controller for certain components.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/boot/dts/brcm/bcm6358.dtsi | 6 ++++++
include/dt-bindings/reset/bcm6358-reset.h | 15 +++++++++++++++
2 files changed, 21 insertions(+)
create mode 100644 include/dt-bindings/reset/bcm6358-reset.h
--- a/arch/mips/boot/dts/brcm/bcm6358.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm6358.dtsi
@@ -82,6 +82,12 @@
interrupts = <2>, <3>;
};
+ periph_rst: reset-controller@fffe0034 {
+ compatible = "brcm,bcm6345-reset";
+ reg = <0xfffe0034 0x4>;
+ #reset-cells = <1>;
+ };
+
leds0: led-controller@fffe00d0 {
#address-cells = <1>;
#size-cells = <0>;
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6358-reset.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6358_H
+#define __DT_BINDINGS_RESET_BCM6358_H
+
+#define BCM6358_RST_SPI 0
+#define BCM6358_RST_ENET 2
+#define BCM6358_RST_MPI 3
+#define BCM6358_RST_EPHY 6
+#define BCM6358_RST_SAR 7
+#define BCM6358_RST_USBH 12
+#define BCM6358_RST_PCM 13
+#define BCM6358_RST_ADSL 14
+
+#endif /* __DT_BINDINGS_RESET_BCM6358_H */

View File

@ -0,0 +1,60 @@
From 226383600be58dcf2e070e4ac8a371640024fe54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:38 +0200
Subject: [PATCH 6/9] mips: bmips: dts: add BCM6362 reset controller support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM6362 SoCs have a reset controller for certain components.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/boot/dts/brcm/bcm6362.dtsi | 6 ++++++
include/dt-bindings/reset/bcm6362-reset.h | 22 ++++++++++++++++++++++
2 files changed, 28 insertions(+)
create mode 100644 include/dt-bindings/reset/bcm6362-reset.h
--- a/arch/mips/boot/dts/brcm/bcm6362.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm6362.dtsi
@@ -70,6 +70,12 @@
mask = <0x1>;
};
+ periph_rst: reset-controller@10000010 {
+ compatible = "brcm,bcm6345-reset";
+ reg = <0x10000010 0x4>;
+ #reset-cells = <1>;
+ };
+
periph_intc: interrupt-controller@10000020 {
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x10>,
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6362-reset.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6362_H
+#define __DT_BINDINGS_RESET_BCM6362_H
+
+#define BCM6362_RST_SPI 0
+#define BCM6362_RST_IPSEC 1
+#define BCM6362_RST_EPHY 2
+#define BCM6362_RST_SAR 3
+#define BCM6362_RST_ENETSW 4
+#define BCM6362_RST_USBD 5
+#define BCM6362_RST_USBH 6
+#define BCM6362_RST_PCM 7
+#define BCM6362_RST_PCIE_CORE 8
+#define BCM6362_RST_PCIE 9
+#define BCM6362_RST_PCIE_EXT 10
+#define BCM6362_RST_WLAN_SHIM 11
+#define BCM6362_RST_DDR_PHY 12
+#define BCM6362_RST_FAP 13
+#define BCM6362_RST_WLAN_UBUS 14
+
+#endif /* __DT_BINDINGS_RESET_BCM6362_H */

View File

@ -0,0 +1,54 @@
From 7acf84e87857721d66a1ba800c2c50669089f43d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:39 +0200
Subject: [PATCH 7/9] mips: bmips: dts: add BCM6368 reset controller support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM6368 SoCs have a reset controller for certain components.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/boot/dts/brcm/bcm6368.dtsi | 6 ++++++
include/dt-bindings/reset/bcm6368-reset.h | 16 ++++++++++++++++
2 files changed, 22 insertions(+)
create mode 100644 include/dt-bindings/reset/bcm6368-reset.h
--- a/arch/mips/boot/dts/brcm/bcm6368.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi
@@ -70,6 +70,12 @@
mask = <0x1>;
};
+ periph_rst: reset-controller@10000010 {
+ compatible = "brcm,bcm6345-reset";
+ reg = <0x10000010 0x4>;
+ #reset-cells = <1>;
+ };
+
periph_intc: interrupt-controller@10000020 {
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x10>,
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6368-reset.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6368_H
+#define __DT_BINDINGS_RESET_BCM6368_H
+
+#define BCM6368_RST_SPI 0
+#define BCM6368_RST_MPI 3
+#define BCM6368_RST_IPSEC 4
+#define BCM6368_RST_EPHY 6
+#define BCM6368_RST_SAR 7
+#define BCM6368_RST_SWITCH 10
+#define BCM6368_RST_USBD 11
+#define BCM6368_RST_USBH 12
+#define BCM6368_RST_PCM 13
+
+#endif /* __DT_BINDINGS_RESET_BCM6368_H */

View File

@ -0,0 +1,64 @@
From b7aa228813bdf014d6ad173ca3abfced30f1ed37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:40 +0200
Subject: [PATCH 8/9] mips: bmips: dts: add BCM63268 reset controller support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM63268 SoCs have a reset controller for certain components.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/boot/dts/brcm/bcm63268.dtsi | 6 +++++
include/dt-bindings/reset/bcm63268-reset.h | 26 ++++++++++++++++++++++
2 files changed, 32 insertions(+)
create mode 100644 include/dt-bindings/reset/bcm63268-reset.h
--- a/arch/mips/boot/dts/brcm/bcm63268.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm63268.dtsi
@@ -70,6 +70,12 @@
mask = <0x1>;
};
+ periph_rst: reset-controller@10000010 {
+ compatible = "brcm,bcm6345-reset";
+ reg = <0x10000010 0x4>;
+ #reset-cells = <1>;
+ };
+
periph_intc: interrupt-controller@10000020 {
compatible = "brcm,bcm6345-l1-intc";
reg = <0x10000020 0x20>,
--- /dev/null
+++ b/include/dt-bindings/reset/bcm63268-reset.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM63268_H
+#define __DT_BINDINGS_RESET_BCM63268_H
+
+#define BCM63268_RST_SPI 0
+#define BCM63268_RST_IPSEC 1
+#define BCM63268_RST_EPHY 2
+#define BCM63268_RST_SAR 3
+#define BCM63268_RST_ENETSW 4
+#define BCM63268_RST_USBS 5
+#define BCM63268_RST_USBH 6
+#define BCM63268_RST_PCM 7
+#define BCM63268_RST_PCIE_CORE 8
+#define BCM63268_RST_PCIE 9
+#define BCM63268_RST_PCIE_EXT 10
+#define BCM63268_RST_WLAN_SHIM 11
+#define BCM63268_RST_DDR_PHY 12
+#define BCM63268_RST_FAP0 13
+#define BCM63268_RST_WLAN_UBUS 14
+#define BCM63268_RST_DECT 15
+#define BCM63268_RST_FAP1 16
+#define BCM63268_RST_PCIE_HARD 17
+#define BCM63268_RST_GPHY 18
+
+#endif /* __DT_BINDINGS_RESET_BCM63268_H */

View File

@ -0,0 +1,42 @@
From 8c9e8b0a28225c46f2cca0a09a3a111bb043e874 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Wed, 17 Jun 2020 12:50:41 +0200
Subject: [PATCH 9/9] mips: bmips: add BCM6318 reset controller definitions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM6318 SoCs have a reset controller for certain components.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Acked-by: Florian Fainelli <F.fainelli@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
include/dt-bindings/reset/bcm6318-reset.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 include/dt-bindings/reset/bcm6318-reset.h
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6318-reset.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6318_H
+#define __DT_BINDINGS_RESET_BCM6318_H
+
+#define BCM6318_RST_SPI 0
+#define BCM6318_RST_EPHY 1
+#define BCM6318_RST_SAR 2
+#define BCM6318_RST_ENETSW 3
+#define BCM6318_RST_USBD 4
+#define BCM6318_RST_USBH 5
+#define BCM6318_RST_PCIE_CORE 6
+#define BCM6318_RST_PCIE 7
+#define BCM6318_RST_PCIE_EXT 8
+#define BCM6318_RST_PCIE_HARD 9
+#define BCM6318_RST_ADSL 10
+#define BCM6318_RST_PHYMIPS 11
+#define BCM6318_RST_HOSTMIPS 12
+
+#endif /* __DT_BINDINGS_RESET_BCM6318_H */

View File

@ -0,0 +1,392 @@
From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 30 Nov 2014 14:54:27 +0100
Subject: [PATCH 2/5] irqchip: add support for bcm6345-style external
interrupt controller
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
.../interrupt-controller/brcm,bcm6345-ext-intc.txt | 29 ++
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-bcm6345-ext.c | 287 ++++++++++++++++++++
include/linux/irqchip/irq-bcm6345-ext.h | 14 +
5 files changed, 335 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
create mode 100644 drivers/irqchip/irq-bcm6345-ext.c
create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
@@ -0,0 +1,29 @@
+Broadcom BCM6345-style external interrupt controller
+
+Required properties:
+
+- compatible: Should be "brcm,bcm6345-ext-intc" or "brcm,bcm6318-ext-intc".
+- reg: Specifies the base physical addresses and size of the registers.
+- interrupt-controller: identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
+ source, Should be 2.
+- interrupt-parent: Specifies the phandle to the parent interrupt controller
+ this one is cascaded from.
+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller
+ node, valid values depend on the type of parent interrupt controller.
+
+Optional properties:
+
+- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the
+ register. Defaults to 4.
+
+Example:
+
+ext_intc: interrupt-controller@10000018 {
+ compatible = "brcm,bcm6345-ext-intc";
+ interrupt-parent = <&periph_intc>;
+ #interrupt-cells = <2>;
+ reg = <0x10000018 0x4>;
+ interrupt-controller;
+ interrupts = <24>, <25>, <26>, <27>;
+};
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -113,6 +113,10 @@ config I8259
bool
select IRQ_DOMAIN
+config BCM6345_EXT_IRQ
+ bool "BCM6345 External IRQ Controller"
+ select IRQ_DOMAIN
+
config BCM6345_L1_IRQ
bool
select GENERIC_IRQ_CHIP
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_XTENSA_MX) += irq-xtensa-
obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o
obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o
+obj-$(CONFIG_BCM6345_EXT_IRQ) += irq-bcm6345-ext.o
obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o
obj-$(CONFIG_BCM7038_L1_IRQ) += irq-bcm7038-l1.o
obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-ext.c
@@ -0,0 +1,299 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqchip/irq-bcm6345-ext.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_BCM63XX
+#include <asm/mach-bcm63xx/bcm63xx_irq.h>
+
+#define VIRQ_BASE IRQ_EXTERNAL_BASE
+#else
+#define VIRQ_BASE 0
+#endif
+
+#define MAX_IRQS 4
+
+#define EXTIRQ_CFG_SENSE 0
+#define EXTIRQ_CFG_STAT 1
+#define EXTIRQ_CFG_CLEAR 2
+#define EXTIRQ_CFG_MASK 3
+#define EXTIRQ_CFG_BOTHEDGE 4
+#define EXTIRQ_CFG_LEVELSENSE 5
+
+struct intc_data {
+ struct irq_chip chip;
+ struct irq_domain *domain;
+ raw_spinlock_t lock;
+
+ int parent_irq[MAX_IRQS];
+ void __iomem *reg;
+ int shift;
+ unsigned int toggle_clear_on_ack:1;
+};
+
+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc)
+{
+ struct intc_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int irq = irq_desc_get_irq(desc);
+ unsigned int idx;
+
+ chained_irq_enter(chip, desc);
+
+ for (idx = 0; idx < MAX_IRQS; idx++) {
+ if (data->parent_irq[idx] != irq)
+ continue;
+
+ generic_handle_irq(irq_find_mapping(data->domain, idx));
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void bcm6345_ext_intc_irq_ack(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ __raw_writel(reg | (1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift)),
+ priv->reg);
+ if (priv->toggle_clear_on_ack)
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_ext_intc_irq_mask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift));
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static void bcm6345_ext_intc_irq_unmask(struct irq_data *data)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ u32 reg;
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+ reg |= 1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift);
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+static int bcm6345_ext_intc_set_type(struct irq_data *data,
+ unsigned int flow_type)
+{
+ struct intc_data *priv = data->domain->host_data;
+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
+ bool levelsense = 0, sense = 0, bothedge = 0;
+ u32 reg;
+
+ flow_type &= IRQ_TYPE_SENSE_MASK;
+
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ switch (flow_type) {
+ case IRQ_TYPE_EDGE_BOTH:
+ bothedge = 1;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ sense = 1;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ levelsense = 1;
+ sense = 1;
+ break;
+
+ case IRQ_TYPE_LEVEL_LOW:
+ levelsense = 1;
+ break;
+
+ default:
+ pr_err("bogus flow type combination given!\n");
+ return -EINVAL;
+ }
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
+
+ if (levelsense)
+ reg |= 1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift);
+ else
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift));
+ if (sense)
+ reg |= 1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift);
+ else
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift));
+ if (bothedge)
+ reg |= 1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift);
+ else
+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift));
+
+ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+
+ irqd_set_trigger_type(data, flow_type);
+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ irq_set_handler_locked(data, handle_level_irq);
+ else
+ irq_set_handler_locked(data, handle_edge_irq);
+
+ return 0;
+}
+
+static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct intc_data *priv = d->host_data;
+
+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops bcm6345_ext_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = bcm6345_ext_intc_map,
+};
+
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
+ int num_irqs, int *irqs,
+ void __iomem *reg, int shift,
+ bool toggle_clear_on_ack)
+{
+ struct intc_data *data;
+ unsigned int i;
+ int start = VIRQ_BASE;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ raw_spin_lock_init(&data->lock);
+
+ for (i = 0; i < num_irqs; i++) {
+ data->parent_irq[i] = irqs[i];
+
+ irq_set_handler_data(irqs[i], data);
+ irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle);
+ }
+
+ data->reg = reg;
+ data->shift = shift;
+ data->toggle_clear_on_ack = toggle_clear_on_ack;
+
+ data->chip.name = "bcm6345-ext-intc";
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
+ data->chip.irq_mask = bcm6345_ext_intc_irq_mask;
+ data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask;
+ data->chip.irq_set_type = bcm6345_ext_intc_set_type;
+
+ /*
+ * If we have less than 4 irqs, this is the second controller on
+ * bcm63xx. So increase the VIRQ start to not overlap with the first
+ * one, but only do so if we actually use a non-zero start.
+ *
+ * This can be removed when bcm63xx has no legacy users anymore.
+ */
+ if (start && num_irqs < 4)
+ start += 4;
+
+ data->domain = irq_domain_add_simple(node, num_irqs, start,
+ &bcm6345_ext_domain_ops, data);
+ if (!data->domain) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
+ int shift)
+{
+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift, false);
+}
+
+#ifdef CONFIG_OF
+static int __init bcm6345_ext_intc_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ int num_irqs, ret = -EINVAL;
+ unsigned i;
+ void __iomem *base;
+ int irqs[MAX_IRQS] = { 0 };
+ u32 shift;
+ bool toggle_clear_on_ack = false;
+
+ num_irqs = of_irq_count(node);
+
+ if (!num_irqs || num_irqs > MAX_IRQS)
+ return -EINVAL;
+
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
+ shift = 4;
+
+ /* on BCM6318 setting CLEAR seems to continuously mask interrupts */
+ if (of_device_is_compatible(node, "brcm,bcm6318-ext-intc"))
+ toggle_clear_on_ack = true;
+
+ for (i = 0; i < num_irqs; i++) {
+ irqs[i] = irq_of_parse_and_map(node, i);
+ if (!irqs[i])
+ return -ENOMEM;
+ }
+
+ base = of_iomap(node, 0);
+ if (!base)
+ return -ENXIO;
+
+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift,
+ toggle_clear_on_ack);
+ if (!ret)
+ return 0;
+
+ iounmap(base);
+
+ for (i = 0; i < num_irqs; i++)
+ irq_dispose_mapping(irqs[i]);
+
+ return ret;
+}
+
+IRQCHIP_DECLARE(bcm6318_ext_intc, "brcm,bcm6318-ext-intc",
+ bcm6345_ext_intc_of_init);
+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
+ bcm6345_ext_intc_of_init);
+#endif
--- /dev/null
+++ b/include/linux/irqchip/irq-bcm6345-ext.h
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
+ */
+
+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H
+
+void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift);
+
+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */

View File

@ -0,0 +1,8 @@
--- a/arch/mips/bmips/setup.c
+++ b/arch/mips/bmips/setup.c
@@ -201,4 +201,4 @@ static int __init plat_dev_init(void)
return 0;
}
-device_initcall(plat_dev_init);
+arch_initcall(plat_dev_init);

View File

@ -0,0 +1,11 @@
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -916,7 +916,7 @@ static void __exit bcm_uart_exit(void)
uart_unregister_driver(&bcm_uart_driver);
}
-module_init(bcm_uart_init);
+subsys_initcall(bcm_uart_init);
module_exit(bcm_uart_exit);
MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");

View File

@ -0,0 +1,11 @@
--- a/drivers/irqchip/irq-bcm6345-l1.c
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -121,7 +121,7 @@ static void bcm6345_l1_irq_handle(struct
unsigned int idx;
#ifdef CONFIG_SMP
- cpu = intc->cpus[cpu_logical_map(smp_processor_id())];
+ cpu = intc->cpus[smp_processor_id()];
#else
cpu = intc->cpus[0];
#endif

View File

@ -0,0 +1,34 @@
From cf0d2fbaae9e962d91a321de75e0d4f9f9ccbdfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Thu, 21 Jan 2021 18:17:37 +0100
Subject: [PATCH] nand: brcmnand: fix OOB R/W with Hamming ECC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Hamming ECC doesn't cover the OOB data, so reading or writing OOB shall
always be done without ECC enabled.
This is a problem when adding JFFS2 cleanmarkers to erased blocks. When JFFS2
clenmarkers are added to the OOB with ECC enabled, OOB bytes will be changed
from ff ff ff to 00 00 00, reporting incorrect ECC errors.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -2688,6 +2688,12 @@ static int brcmnand_attach_chip(struct n
ret = brcmstb_choose_ecc_layout(host);
+ /* If OOB is written with ECC enabled it will cause ECC errors */
+ if (is_hamming_ecc(host->ctrl, &host->hwcfg)) {
+ chip->ecc.write_oob = brcmnand_write_oob_raw;
+ chip->ecc.read_oob = brcmnand_read_oob_raw;
+ }
+
return ret;
}

View File

@ -0,0 +1,66 @@
--- a/drivers/watchdog/bcm7038_wdt.c
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -34,6 +34,24 @@ struct bcm7038_watchdog {
static bool nowayout = WATCHDOG_NOWAYOUT;
+static inline void bcm7038_wdt_write(unsigned long data, void __iomem *reg)
+{
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ iowrite32be(data, reg);
+#else
+ writel(data, reg);
+#endif
+}
+
+static inline unsigned long bcm7038_wdt_read(void __iomem *reg)
+{
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ return ioread32be(reg);
+#else
+ return readl(reg);
+#endif
+}
+
static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
{
struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
@@ -41,15 +59,15 @@ static void bcm7038_wdt_set_timeout_reg(
timeout = wdt->rate * wdog->timeout;
- writel(timeout, wdt->base + WDT_TIMEOUT_REG);
+ bcm7038_wdt_write(timeout, wdt->base + WDT_TIMEOUT_REG);
}
static int bcm7038_wdt_ping(struct watchdog_device *wdog)
{
struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
- writel(WDT_START_1, wdt->base + WDT_CMD_REG);
- writel(WDT_START_2, wdt->base + WDT_CMD_REG);
+ bcm7038_wdt_write(WDT_START_1, wdt->base + WDT_CMD_REG);
+ bcm7038_wdt_write(WDT_START_2, wdt->base + WDT_CMD_REG);
return 0;
}
@@ -66,8 +84,8 @@ static int bcm7038_wdt_stop(struct watch
{
struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
- writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
- writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
+ bcm7038_wdt_write(WDT_STOP_1, wdt->base + WDT_CMD_REG);
+ bcm7038_wdt_write(WDT_STOP_2, wdt->base + WDT_CMD_REG);
return 0;
}
@@ -88,7 +106,7 @@ static unsigned int bcm7038_wdt_get_time
struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
u32 time_left;
- time_left = readl(wdt->base + WDT_CMD_REG);
+ time_left = bcm7038_wdt_read(wdt->base + WDT_CMD_REG);
return time_left / wdt->rate;
}

View File

@ -0,0 +1,10 @@
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -574,7 +574,6 @@ static int bcm63xx_spi_probe(struct plat
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->max_transfer_size = bcm63xx_spi_max_length;
master->max_message_size = bcm63xx_spi_max_length;
- master->auto_runtime_pm = true;
bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);

View File

@ -0,0 +1,10 @@
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -417,7 +417,6 @@ static int bcm63xx_hsspi_probe(struct pl
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
SPI_RX_DUAL | SPI_TX_DUAL;
master->bits_per_word_mask = SPI_BPW_MASK(8);
- master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);

View File

@ -0,0 +1,12 @@
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl
if (of_property_read_bool(dev->dev.of_node, "big-endian"))
ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+ if (of_property_read_bool(dev->dev.of_node, "ignore-oc"))
+ ehci->ignore_oc = 1;
+
if (of_property_read_bool(dev->dev.of_node,
"needs-reset-on-resume"))
priv->reset_on_resume = true;

View File

@ -0,0 +1,226 @@
From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:07:42 +0200
Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
Setup directory and add a helper for bcm63xx pinctrl support.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/Kconfig | 1 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/bcm63xx/Kconfig | 3 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h | 14 +++
7 files changed, 163 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
create mode 100644 drivers/pinctrl/bcm63xx/Makefile
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -377,6 +377,7 @@ config PINCTRL_OCELOT
source "drivers/pinctrl/actions/Kconfig"
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"
+source "drivers/pinctrl/bcm63xx/Kconfig"
source "drivers/pinctrl/berlin/Kconfig"
source "drivers/pinctrl/freescale/Kconfig"
source "drivers/pinctrl/intel/Kconfig"
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += p
obj-y += actions/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-y += bcm/
+obj-y += bcm63xx/
obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
obj-y += freescale/
obj-$(CONFIG_X86) += intel/
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -0,0 +1,3 @@
+config PINCTRL_BCM63XX
+ bool
+ select GPIO_GENERIC
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
@@ -0,0 +1,155 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/gpio/driver.h>
+#include <linux/of_irq.h>
+
+#include "pinctrl-bcm63xx.h"
+#include "../core.h"
+
+#define BANK_SIZE sizeof(u32)
+#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
+
+#ifdef CONFIG_OF
+static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ struct gpio_chip *base = gpiochip_get_data(gc);
+ int pin = gpiospec->args[0];
+
+ if (gc != &base[pin / PINS_PER_BANK])
+ return -EINVAL;
+
+ pin = pin % PINS_PER_BANK;
+
+ if (pin >= gc->ngpio)
+ return -EINVAL;
+
+ if (flags)
+ *flags = gpiospec->args[1];
+
+ return pin;
+}
+#endif
+
+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ struct gpio_chip *base = gpiochip_get_data(chip);
+ char irq_name[7]; /* "gpioXX" */
+
+ /* FIXME: this is ugly */
+ sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
+ return of_irq_get_byname(chip->of_node, irq_name);
+}
+
+static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
+ void __iomem *dirout, void __iomem *data,
+ size_t sz, int ngpio)
+
+{
+ int banks, chips, i, ret = -EINVAL;
+
+ chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
+ banks = sz / BANK_SIZE;
+
+ for (i = 0; i < chips; i++) {
+ int offset, pins;
+ int reg_offset;
+ char *label;
+
+ label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
+ if (!label)
+ return -ENOMEM;
+
+ offset = i * PINS_PER_BANK;
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
+
+ /* the registers are treated like a huge big endian register */
+ reg_offset = (banks - i - 1) * BANK_SIZE;
+
+ ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
+ NULL, NULL, dirout + reg_offset, NULL,
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ if (ret)
+ return ret;
+
+ gc[i].request = gpiochip_generic_request;
+ gc[i].free = gpiochip_generic_free;
+
+ if (of_get_property(dev->of_node, "interrupt-names", NULL))
+ gc[i].to_irq = bcm63xx_gpio_to_irq;
+
+#ifdef CONFIG_OF
+ gc[i].of_gpio_n_cells = 2;
+ gc[i].of_xlate = bcm63xx_gpio_of_xlate;
+#endif
+
+ gc[i].label = label;
+ gc[i].ngpio = pins;
+
+ devm_gpiochip_add_data(dev, &gc[i], gc);
+ }
+
+ return 0;
+}
+
+static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
+ int ngpio)
+{
+ int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
+
+ for (i = 0; i < chips; i++) {
+ int offset, pins;
+
+ offset = i * PINS_PER_BANK;
+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
+
+ gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
+ }
+}
+
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
+ struct pinctrl_desc *desc,
+ void *priv, struct gpio_chip *gc,
+ int ngpio)
+{
+ struct pinctrl_dev *pctldev;
+ struct resource *res;
+ void __iomem *dirout, *data;
+ size_t sz;
+ int ret;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
+ dirout = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dirout))
+ return ERR_CAST(dirout);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+ data = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data))
+ return ERR_CAST(data);
+
+ sz = resource_size(res);
+
+ ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
+ if (ret)
+ return ERR_PTR(ret);
+
+ pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
+ if (IS_ERR(pctldev))
+ return pctldev;
+
+ bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
+
+ dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
+
+ return pctldev;
+}
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
@@ -0,0 +1,14 @@
+#ifndef __PINCTRL_BCM63XX
+#define __PINCTRL_BCM63XX
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
+ struct pinctrl_desc *desc,
+ void *priv, struct gpio_chip *gc,
+ int ngpio);
+
+#endif

View File

@ -0,0 +1,78 @@
From 4bdd40849632608d5cb7d3a64380cd76e7eea07b Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:33:56 +0200
Subject: [PATCH 02/16] Documentation: add BCM6328 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6328 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6328-pinctrl.txt | 61 ++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6328-pinctrl.txt
@@ -0,0 +1,61 @@
+* Broadcom BCM6328 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6328-pinctrl".
+- reg: Register specifies of dirout, dat, mode, mux registers.
+- reg-names: Must be "dirout", "dat", "mode", "mux".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6328-pinctrl";
+ reg = <0x10000080 0x8>,
+ <0x10000088 0x8>,
+ <0x10000098 0x4>,
+ <0x1000009c 0xc>;
+ reg-names = "dirout", "dat", "mode", "mux";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led
+gpio1 1 led
+gpio2 2 led
+gpio3 3 led
+gpio4 4 led
+gpio5 5 led
+gpio6 6 led, serial_led_data
+gpio7 7 led, serial_led_clk
+gpio8 8 led
+gpio9 9 led
+gpio10 10 led
+gpio11 11 led
+gpio12 12 led
+gpio13 13 led
+gpio14 14 led
+gpio15 15 led
+gpio16 16 led, pcie_clkreq
+gpio17 17 led
+gpio18 18 led
+gpio19 19 led
+gpio20 20 led
+gpio21 21 led
+gpio22 22 led
+gpio23 23 led
+gpio24 24 -
+gpio25 25 ephy0_act_led
+gpio26 26 ephy1_act_led
+gpio27 27 ephy2_act_led
+gpio28 28 ephy3_act_led
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+hsspi_cs1 - hsspi_cs1
+usb_port1 - usb_host_port, usb_device_port

View File

@ -0,0 +1,495 @@
From 393e9753f6492c1fdf55891ddee60d955ae8b119 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:12:50 +0200
Subject: [PATCH 03/16] pinctrl: add a pincontrol driver for BCM6328
Add a pincontrol driver for BCM6328. BCM628 supports muxing 32 pins as
GPIOs, as LEDs for the integrated LED controller, or various other
functions. Its pincontrol mux registers also control other aspects, like
switching the second USB port between host and device mode.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c | 456 ++++++++++++++++++++++++++++++
3 files changed, 464 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -1,3 +1,10 @@
config PINCTRL_BCM63XX
bool
select GPIO_GENERIC
+
+config PINCTRL_BCM6328
+ bool "BCM6328 pincontrol driver"
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
+obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6328.c
@@ -0,0 +1,456 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6328_MUX_LO_REG 0x4
+#define BCM6328_MUX_HI_REG 0x0
+#define BCM6328_MUX_OTHER_REG 0x8
+
+#define BCM6328_NGPIO 32
+
+struct bcm6328_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6328_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned mode_val:1;
+ unsigned mux_val:2;
+};
+
+struct bcm6328_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ void __iomem *mux[3];
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio;
+};
+
+static const struct pinctrl_pin_desc bcm6328_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+
+ /*
+ * No idea where they really are; so let's put them according
+ * to their mux offsets.
+ */
+ PINCTRL_PIN(36, "hsspi_cs1"),
+ PINCTRL_PIN(38, "usb_p2"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+
+static unsigned hsspi_cs1_pins[] = { 36 };
+static unsigned usb_port1_pins[] = { 38 };
+
+#define BCM6328_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6328_pingroup bcm6328_groups[] = {
+ BCM6328_GROUP(gpio0),
+ BCM6328_GROUP(gpio1),
+ BCM6328_GROUP(gpio2),
+ BCM6328_GROUP(gpio3),
+ BCM6328_GROUP(gpio4),
+ BCM6328_GROUP(gpio5),
+ BCM6328_GROUP(gpio6),
+ BCM6328_GROUP(gpio7),
+ BCM6328_GROUP(gpio8),
+ BCM6328_GROUP(gpio9),
+ BCM6328_GROUP(gpio10),
+ BCM6328_GROUP(gpio11),
+ BCM6328_GROUP(gpio12),
+ BCM6328_GROUP(gpio13),
+ BCM6328_GROUP(gpio14),
+ BCM6328_GROUP(gpio15),
+ BCM6328_GROUP(gpio16),
+ BCM6328_GROUP(gpio17),
+ BCM6328_GROUP(gpio18),
+ BCM6328_GROUP(gpio19),
+ BCM6328_GROUP(gpio20),
+ BCM6328_GROUP(gpio21),
+ BCM6328_GROUP(gpio22),
+ BCM6328_GROUP(gpio23),
+ BCM6328_GROUP(gpio24),
+ BCM6328_GROUP(gpio25),
+ BCM6328_GROUP(gpio26),
+ BCM6328_GROUP(gpio27),
+ BCM6328_GROUP(gpio28),
+ BCM6328_GROUP(gpio29),
+ BCM6328_GROUP(gpio30),
+ BCM6328_GROUP(gpio31),
+
+ BCM6328_GROUP(hsspi_cs1),
+ BCM6328_GROUP(usb_port1),
+};
+
+/* GPIO_MODE */
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+/* PINMUX_SEL */
+static const char * const serial_led_data_groups[] = {
+ "gpio6",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_act_led_groups[] = {
+ "gpio11",
+};
+
+static const char * const pcie_clkreq_groups[] = {
+ "gpio16",
+};
+
+static const char * const ephy0_act_led_groups[] = {
+ "gpio25",
+};
+
+static const char * const ephy1_act_led_groups[] = {
+ "gpio26",
+};
+
+static const char * const ephy2_act_led_groups[] = {
+ "gpio27",
+};
+
+static const char * const ephy3_act_led_groups[] = {
+ "gpio28",
+};
+
+static const char * const hsspi_cs1_groups[] = {
+ "hsspi_cs1"
+};
+
+static const char * const usb_host_port_groups[] = {
+ "usb_port1",
+};
+
+static const char * const usb_device_port_groups[] = {
+ "usb_port1",
+};
+
+#define BCM6328_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mode_val = 1, \
+ }
+
+#define BCM6328_MUX_FUN(n, mux) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mux_val = mux, \
+ }
+
+static const struct bcm6328_function bcm6328_funcs[] = {
+ BCM6328_MODE_FUN(led),
+ BCM6328_MUX_FUN(serial_led_data, 2),
+ BCM6328_MUX_FUN(serial_led_clk, 2),
+ BCM6328_MUX_FUN(inet_act_led, 1),
+ BCM6328_MUX_FUN(pcie_clkreq, 2),
+ BCM6328_MUX_FUN(ephy0_act_led, 1),
+ BCM6328_MUX_FUN(ephy1_act_led, 1),
+ BCM6328_MUX_FUN(ephy2_act_led, 1),
+ BCM6328_MUX_FUN(ephy3_act_led, 1),
+ BCM6328_MUX_FUN(hsspi_cs1, 2),
+ BCM6328_MUX_FUN(usb_host_port, 1),
+ BCM6328_MUX_FUN(usb_device_port, 2),
+};
+
+static int bcm6328_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6328_groups);
+}
+
+static const char *bcm6328_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6328_groups[group].name;
+}
+
+static int bcm6328_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6328_groups[group].pins;
+ *num_pins = bcm6328_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6328_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6328_funcs);
+}
+
+static const char *bcm6328_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6328_funcs[selector].name;
+}
+
+static int bcm6328_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6328_funcs[selector].groups;
+ *num_groups = bcm6328_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6328_rmw_mux(struct bcm6328_pinctrl *pctl, unsigned pin,
+ u32 mode, u32 mux)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (pin < 32) {
+ reg = __raw_readl(pctl->mode);
+ reg &= ~BIT(pin);
+ if (mode)
+ reg |= BIT(pin);
+ __raw_writel(reg, pctl->mode);
+ }
+
+ reg = __raw_readl(pctl->mux[pin / 16]);
+ reg &= ~(3UL << ((pin % 16) * 2));
+ reg |= mux << ((pin % 16) * 2);
+ __raw_writel(reg, pctl->mux[pin / 16]);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6328_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6328_pingroup *grp = &bcm6328_groups[group];
+ const struct bcm6328_function *f = &bcm6328_funcs[selector];
+
+ bcm6328_rmw_mux(pctl, grp->pins[0], f->mode_val, f->mux_val);
+
+ return 0;
+}
+
+static int bcm6328_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6328_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm6328_rmw_mux(pctl, offset, 0, 0);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6328_pctl_ops = {
+ .get_groups_count = bcm6328_pinctrl_get_group_count,
+ .get_group_name = bcm6328_pinctrl_get_group_name,
+ .get_group_pins = bcm6328_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6328_pmx_ops = {
+ .get_functions_count = bcm6328_pinctrl_get_func_count,
+ .get_function_name = bcm6328_pinctrl_get_func_name,
+ .get_function_groups = bcm6328_pinctrl_get_groups,
+ .set_mux = bcm6328_pinctrl_set_mux,
+ .gpio_request_enable = bcm6328_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6328_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6328_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode, *mux;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mux");
+ mux = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mux))
+ return PTR_ERR(mux);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+ pctl->mux[0] = mux + BCM6328_MUX_LO_REG;
+ pctl->mux[1] = mux + BCM6328_MUX_HI_REG;
+ pctl->mux[2] = mux + BCM6328_MUX_OTHER_REG;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6328_pctl_ops;
+ pctl->desc.pmxops = &bcm6328_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6328_pins);
+ pctl->desc.pins = bcm6328_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ &pctl->gpio, BCM6328_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6328_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6328-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6328_pinctrl_driver = {
+ .probe = bcm6328_pinctrl_probe,
+ .driver = {
+ .name = "bcm6328-pinctrl",
+ .of_match_table = bcm6328_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6328_pinctrl_driver);

View File

@ -0,0 +1,61 @@
From c7c8fa7f5b5ee9bea751fa7bdae8ff4acde8f26e Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:00 +0200
Subject: [PATCH 06/16] Documentation: add BCM6358 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6358 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6358-pinctrl.txt | 44 ++++++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6358-pinctrl.txt
@@ -0,0 +1,44 @@
+* Broadcom BCM6358 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6358-pinctrl".
+- reg: Register specifiers of dirout, dat registers.
+- reg-names: Must be "dirout", "dat".
+- brcm,gpiomode: Phandle to the shared gpiomode register.
+- gpio-controller: Identifies this node as a gpio-controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@fffe0080 {
+ compatible = "brcm,bcm6358-pinctrl";
+ reg = <0xfffe0080 0x8>,
+ <0xfffe0088 0x8>,
+ <0xfffe0098 0x4>;
+ reg-names = "dirout", "dat";
+ brcm,gpiomode = <&gpiomode>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+gpiomode: syscon@fffe0098 {
+ compatible = "brcm,bcm6358-gpiomode", "syscon";
+ reg = <0xfffe0098 0x4>;
+ native-endian;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+ebi_cs_grp 30-31 ebi_cs
+uart1_grp 28-31 uart1
+spi_cs_grp 32-33 spi_cs
+async_modem_grp 12-15 async_modem
+legacy_led_grp 9-15 legacy_led
+serial_led_grp 6-7 serial_led
+led_grp 0-3 led
+utopia_grp 12-15, 22-31 utopia
+pwm_syn_clk_grp 8 pwm_syn_clk
+sys_irq_grp 5 sys_irq

View File

@ -0,0 +1,432 @@
From fb00ef462f3f8b70ea8902151cc72810fe90b999 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:16:01 +0200
Subject: [PATCH 07/16] pinctrl: add a pincontrol driver for BCM6358
Add a pincotrol driver for BCM6358. BCM6358 allow overlaying different
functions onto the GPIO pins. It does not support configuring individual
pins but only whole groups. These groups may overlap, and still require
the directions to be set correctly in the GPIO register. In addition the
functions register controls other, not directly mux related functions.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 8 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c | 393 ++++++++++++++++++++++++++++++
3 files changed, 402 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -8,3 +8,11 @@ config PINCTRL_BCM6328
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6358
+ bool "BCM6358 pincontrol driver"
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+ select MFD_SYSCON
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
+obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6358.c
@@ -0,0 +1,390 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+/* GPIO_MODE register */
+#define BCM6358_MODE_MUX_NONE 0
+
+/* overlays on gpio pins */
+#define BCM6358_MODE_MUX_EBI_CS BIT(5)
+#define BCM6358_MODE_MUX_UART1 BIT(6)
+#define BCM6358_MODE_MUX_SPI_CS BIT(7)
+#define BCM6358_MODE_MUX_ASYNC_MODEM BIT(8)
+#define BCM6358_MODE_MUX_LEGACY_LED BIT(9)
+#define BCM6358_MODE_MUX_SERIAL_LED BIT(10)
+#define BCM6358_MODE_MUX_LED BIT(11)
+#define BCM6358_MODE_MUX_UTOPIA BIT(12)
+#define BCM6358_MODE_MUX_CLKRST BIT(13)
+#define BCM6358_MODE_MUX_PWM_SYN_CLK BIT(14)
+#define BCM6358_MODE_MUX_SYS_IRQ BIT(15)
+
+#define BCM6358_NGPIO 40
+
+struct bcm6358_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+
+ const u16 mode_val;
+
+ /* non-GPIO function muxes require the gpio direction to be set */
+ const u16 direction;
+};
+
+struct bcm6358_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+};
+
+struct bcm6358_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ struct regmap_field *overlays;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6358_GPIO_PIN(a, b, bit1, bit2, bit3) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(BCM6358_MODE_MUX_##bit1 | \
+ BCM6358_MODE_MUX_##bit2 | \
+ BCM6358_MODE_MUX_##bit3), \
+ }
+
+static const struct pinctrl_pin_desc bcm6358_pins[] = {
+ BCM6358_GPIO_PIN(0, "gpio0", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(1, "gpio1", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(2, "gpio2", LED, NONE, NONE),
+ BCM6358_GPIO_PIN(3, "gpio3", LED, NONE, NONE),
+ PINCTRL_PIN(4, "gpio4"),
+ BCM6358_GPIO_PIN(5, "gpio5", SYS_IRQ, NONE, NONE),
+ BCM6358_GPIO_PIN(6, "gpio6", SERIAL_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(7, "gpio7", SERIAL_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(8, "gpio8", PWM_SYN_CLK, NONE, NONE),
+ BCM6358_GPIO_PIN(9, "gpio09", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(10, "gpio10", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(11, "gpio11", LEGACY_LED, NONE, NONE),
+ BCM6358_GPIO_PIN(12, "gpio12", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(13, "gpio13", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(14, "gpio14", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ BCM6358_GPIO_PIN(15, "gpio15", LEGACY_LED, ASYNC_MODEM, UTOPIA),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ BCM6358_GPIO_PIN(22, "gpio22", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(23, "gpio23", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(24, "gpio24", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(25, "gpio25", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(26, "gpio26", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(27, "gpio27", UTOPIA, NONE, NONE),
+ BCM6358_GPIO_PIN(28, "gpio28", UTOPIA, UART1, NONE),
+ BCM6358_GPIO_PIN(29, "gpio29", UTOPIA, UART1, NONE),
+ BCM6358_GPIO_PIN(30, "gpio30", UTOPIA, UART1, EBI_CS),
+ BCM6358_GPIO_PIN(31, "gpio31", UTOPIA, UART1, EBI_CS),
+ BCM6358_GPIO_PIN(32, "gpio32", SPI_CS, NONE, NONE),
+ BCM6358_GPIO_PIN(33, "gpio33", SPI_CS, NONE, NONE),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+};
+
+static unsigned ebi_cs_grp_pins[] = { 30, 31 };
+
+static unsigned uart1_grp_pins[] = { 28, 29, 30, 31 };
+
+static unsigned spi_cs_grp_pins[] = { 32, 33 };
+
+static unsigned async_modem_grp_pins[] = { 12, 13, 14, 15 };
+
+static unsigned serial_led_grp_pins[] = { 6, 7 };
+
+static unsigned legacy_led_grp_pins[] = { 9, 10, 11, 12, 13, 14, 15 };
+
+static unsigned led_grp_pins[] = { 0, 1, 2, 3 };
+
+static unsigned utopia_grp_pins[] = {
+ 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned pwm_syn_clk_grp_pins[] = { 8 };
+
+static unsigned sys_irq_grp_pins[] = { 5 };
+
+#define BCM6358_GPIO_MUX_GROUP(n, bit, dir) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ .mode_val = BCM6358_MODE_MUX_##bit, \
+ .direction = dir, \
+ }
+
+static const struct bcm6358_pingroup bcm6358_groups[] = {
+ BCM6358_GPIO_MUX_GROUP(ebi_cs_grp, EBI_CS, 0x3),
+ BCM6358_GPIO_MUX_GROUP(uart1_grp, UART1, 0x2),
+ BCM6358_GPIO_MUX_GROUP(spi_cs_grp, SPI_CS, 0x6),
+ BCM6358_GPIO_MUX_GROUP(async_modem_grp, ASYNC_MODEM, 0x6),
+ BCM6358_GPIO_MUX_GROUP(legacy_led_grp, LEGACY_LED, 0x7f),
+ BCM6358_GPIO_MUX_GROUP(serial_led_grp, SERIAL_LED, 0x3),
+ BCM6358_GPIO_MUX_GROUP(led_grp, LED, 0xf),
+ BCM6358_GPIO_MUX_GROUP(utopia_grp, UTOPIA, 0x000f),
+ BCM6358_GPIO_MUX_GROUP(pwm_syn_clk_grp, PWM_SYN_CLK, 0x1),
+ BCM6358_GPIO_MUX_GROUP(sys_irq_grp, SYS_IRQ, 0x1),
+};
+
+static const char * const ebi_cs_groups[] = {
+ "ebi_cs_grp"
+};
+
+static const char * const uart1_groups[] = {
+ "uart1_grp"
+};
+
+static const char * const spi_cs_2_3_groups[] = {
+ "spi_cs_2_3_grp"
+};
+
+static const char * const async_modem_groups[] = {
+ "async_modem_grp"
+};
+
+static const char * const legacy_led_groups[] = {
+ "legacy_led_grp",
+};
+
+static const char * const serial_led_groups[] = {
+ "serial_led_grp",
+};
+
+static const char * const led_groups[] = {
+ "led_grp",
+};
+
+static const char * const clkrst_groups[] = {
+ "clkrst_grp",
+};
+
+static const char * const pwm_syn_clk_groups[] = {
+ "pwm_syn_clk_grp",
+};
+
+static const char * const sys_irq_groups[] = {
+ "sys_irq_grp",
+};
+
+#define BCM6358_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ }
+
+static const struct bcm6358_function bcm6358_funcs[] = {
+ BCM6358_FUN(ebi_cs),
+ BCM6358_FUN(uart1),
+ BCM6358_FUN(spi_cs_2_3),
+ BCM6358_FUN(async_modem),
+ BCM6358_FUN(legacy_led),
+ BCM6358_FUN(serial_led),
+ BCM6358_FUN(led),
+ BCM6358_FUN(clkrst),
+ BCM6358_FUN(pwm_syn_clk),
+ BCM6358_FUN(sys_irq),
+};
+
+static int bcm6358_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6358_groups);
+}
+
+static const char *bcm6358_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6358_groups[group].name;
+}
+
+static int bcm6358_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6358_groups[group].pins;
+ *num_pins = bcm6358_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6358_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6358_funcs);
+}
+
+static const char *bcm6358_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6358_funcs[selector].name;
+}
+
+static int bcm6358_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6358_funcs[selector].groups;
+ *num_groups = bcm6358_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static int bcm6358_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6358_pingroup *grp = &bcm6358_groups[group];
+ u32 val = grp->mode_val;
+ u32 mask = val;
+ unsigned pin;
+
+ for (pin = 0; pin < grp->num_pins; pin++)
+ mask |= (unsigned long)bcm6358_pins[pin].drv_data;
+
+ regmap_field_update_bits(pctl->overlays, mask, val);
+
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ int hw_gpio = bcm6358_pins[pin].number;
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
+
+ if (grp->direction & BIT(pin))
+ gc->direction_output(gc, hw_gpio % 32, 0);
+ else
+ gc->direction_input(gc, hw_gpio % 32);
+ }
+
+ return 0;
+}
+
+static int bcm6358_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6358_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ u32 mask;
+
+ mask = (unsigned long)bcm6358_pins[offset].drv_data;
+ if (!mask)
+ return 0;
+
+ /* disable all functions using this pin */
+ return regmap_field_update_bits(pctl->overlays, mask, 0);
+}
+
+static struct pinctrl_ops bcm6358_pctl_ops = {
+ .get_groups_count = bcm6358_pinctrl_get_group_count,
+ .get_group_name = bcm6358_pinctrl_get_group_name,
+ .get_group_pins = bcm6358_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6358_pmx_ops = {
+ .get_functions_count = bcm6358_pinctrl_get_func_count,
+ .get_function_name = bcm6358_pinctrl_get_func_name,
+ .get_function_groups = bcm6358_pinctrl_get_groups,
+ .set_mux = bcm6358_pinctrl_set_mux,
+ .gpio_request_enable = bcm6358_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6358_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6358_pinctrl *pctl;
+ struct regmap *mode;
+ struct reg_field overlays = REG_FIELD(0, 0, 15);
+
+ mode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "brcm,gpiomode");
+
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->overlays = devm_regmap_field_alloc(&pdev->dev, mode, overlays);
+ if (IS_ERR(pctl->overlays))
+ return PTR_ERR(pctl->overlays);
+
+ /* disable all muxes by default */
+ regmap_field_write(pctl->overlays, 0);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6358_pctl_ops;
+ pctl->desc.pmxops = &bcm6358_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6358_pins);
+ pctl->desc.pins = bcm6358_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6358_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6358_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6358-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6358_pinctrl_driver = {
+ .probe = bcm6358_pinctrl_probe,
+ .driver = {
+ .name = "bcm6358-pinctrl",
+ .of_match_table = bcm6358_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6358_pinctrl_driver);

View File

@ -0,0 +1,96 @@
From ba03ea8ada2ca71c9095d96a1e4085c2c5cf0e69 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:18 +0200
Subject: [PATCH 08/16] Documentation: add BCM6362 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6362 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6362-pinctrl.txt | 79 ++++++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6362-pinctrl.txt
@@ -0,0 +1,79 @@
+* Broadcom BCM6362 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6362-pinctrl"
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6362-pinctrl";
+ reg = <0x10000080 0x8>,
+ <0x10000088 0x8>,
+ <0x10000090 0x4>,
+ <0x10000098 0x4>,
+ <0x1000009c 0x4>,
+ <0x100000b8 0x4>;
+ reg-names = "dirout", "dat", "led",
+ "mode", "ctrl", "basemode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, usb_device_led
+gpio1 1 led, sys_irq
+gpio2 2 led, serial_led_clk
+gpio3 3 led, serial_led_data
+gpio4 4 led, robosw_led_data
+gpio5 5 led, robosw_led_clk
+gpio6 6 led, robosw_led0
+gpio7 7 led, robosw_led1
+gpio8 8 led, inet_led
+gpio9 9 led, spi_cs2
+gpio10 10 led, spi_cs3
+gpio11 11 led, ntr_pulse
+gpio12 12 led, uart1_scts
+gpio13 13 led, uart1_srts
+gpio14 14 led, uart1_sdin
+gpio15 15 led, uart1_sdout
+gpio16 16 led, adsl_spi_miso
+gpio17 17 led, adsl_spi_mosi
+gpio18 18 led, adsl_spi_clk
+gpio19 19 led, adsl_spi_cs
+gpio20 20 led, ephy0_led
+gpio21 21 led, ephy1_led
+gpio22 22 led, ephy2_led
+gpio23 23 led, ephy3_led
+gpio24 24 ext_irq0
+gpio25 25 ext_irq1
+gpio26 26 ext_irq2
+gpio27 27 ext_irq3
+gpio28 28 -
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+gpio32 32 wifi
+gpio33 33 wifi
+gpio34 34 wifi
+gpio35 35 wifi
+gpio36 36 wifi
+gpio37 37 wifi
+gpio38 38 wifi
+gpio39 39 wifi
+gpio40 40 wifi
+gpio41 41 wifi
+gpio42 42 wifi
+gpio43 43 wifi
+gpio44 44 wifi
+gpio45 45 wifi
+gpio46 46 wifi
+gpio47 47 wifi
+nand_grp 8, 12-23, 27 nand

View File

@ -0,0 +1,733 @@
From eea6b96701d734095e2f823f3a82d9b063f553ae Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:17:20 +0200
Subject: [PATCH 09/16] pinctrl: add a pincontrol driver for BCM6362
Add a pincotrol driver for BCM6362. BCM6362 allows muxing individual
GPIO pins to the LED controller, to be available by the integrated
wifi, or other functions. It also supports overlay groups, of which
only NAND is documented.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c | 692 ++++++++++++++++++++++++++++++
3 files changed, 700 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -16,3 +16,10 @@ config PINCTRL_BCM6358
select PINCTRL_BCM63XX
select GENERIC_PINCONF
select MFD_SYSCON
+
+config PINCTRL_BCM6362
+ bool "BCM6362 pincontrol driver"
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
+obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6362.c
@@ -0,0 +1,692 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6362_NGPIO 48
+
+/* GPIO_BASEMODE register */
+#define BASEMODE_NAND BIT(2)
+
+enum bcm6362_pinctrl_reg {
+ BCM6362_LEDCTRL,
+ BCM6362_MODE,
+ BCM6362_CTRL,
+ BCM6362_BASEMODE,
+};
+
+struct bcm6362_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6362_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ enum bcm6362_pinctrl_reg reg;
+ u32 basemode_mask;
+};
+
+struct bcm6362_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *led;
+ void __iomem *mode;
+ void __iomem *ctrl;
+ void __iomem *basemode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6362_PIN(a, b, mask) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(mask), \
+ }
+
+static const struct pinctrl_pin_desc bcm6362_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ BCM6362_PIN(8, "gpio8", BASEMODE_NAND),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ BCM6362_PIN(12, "gpio12", BASEMODE_NAND),
+ BCM6362_PIN(13, "gpio13", BASEMODE_NAND),
+ BCM6362_PIN(14, "gpio14", BASEMODE_NAND),
+ BCM6362_PIN(15, "gpio15", BASEMODE_NAND),
+ BCM6362_PIN(16, "gpio16", BASEMODE_NAND),
+ BCM6362_PIN(17, "gpio17", BASEMODE_NAND),
+ BCM6362_PIN(18, "gpio18", BASEMODE_NAND),
+ BCM6362_PIN(19, "gpio19", BASEMODE_NAND),
+ BCM6362_PIN(20, "gpio20", BASEMODE_NAND),
+ BCM6362_PIN(21, "gpio21", BASEMODE_NAND),
+ BCM6362_PIN(22, "gpio22", BASEMODE_NAND),
+ BCM6362_PIN(23, "gpio23", BASEMODE_NAND),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ BCM6362_PIN(27, "gpio27", BASEMODE_NAND),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+
+static unsigned nand_grp_pins[] = {
+ 8, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 27,
+};
+
+#define BCM6362_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6362_pingroup bcm6362_groups[] = {
+ BCM6362_GROUP(gpio0),
+ BCM6362_GROUP(gpio1),
+ BCM6362_GROUP(gpio2),
+ BCM6362_GROUP(gpio3),
+ BCM6362_GROUP(gpio4),
+ BCM6362_GROUP(gpio5),
+ BCM6362_GROUP(gpio6),
+ BCM6362_GROUP(gpio7),
+ BCM6362_GROUP(gpio8),
+ BCM6362_GROUP(gpio9),
+ BCM6362_GROUP(gpio10),
+ BCM6362_GROUP(gpio11),
+ BCM6362_GROUP(gpio12),
+ BCM6362_GROUP(gpio13),
+ BCM6362_GROUP(gpio14),
+ BCM6362_GROUP(gpio15),
+ BCM6362_GROUP(gpio16),
+ BCM6362_GROUP(gpio17),
+ BCM6362_GROUP(gpio18),
+ BCM6362_GROUP(gpio19),
+ BCM6362_GROUP(gpio20),
+ BCM6362_GROUP(gpio21),
+ BCM6362_GROUP(gpio22),
+ BCM6362_GROUP(gpio23),
+ BCM6362_GROUP(gpio24),
+ BCM6362_GROUP(gpio25),
+ BCM6362_GROUP(gpio26),
+ BCM6362_GROUP(gpio27),
+ BCM6362_GROUP(gpio28),
+ BCM6362_GROUP(gpio29),
+ BCM6362_GROUP(gpio30),
+ BCM6362_GROUP(gpio31),
+ BCM6362_GROUP(gpio32),
+ BCM6362_GROUP(gpio33),
+ BCM6362_GROUP(gpio34),
+ BCM6362_GROUP(gpio35),
+ BCM6362_GROUP(gpio36),
+ BCM6362_GROUP(gpio37),
+ BCM6362_GROUP(gpio38),
+ BCM6362_GROUP(gpio39),
+ BCM6362_GROUP(gpio40),
+ BCM6362_GROUP(gpio41),
+ BCM6362_GROUP(gpio42),
+ BCM6362_GROUP(gpio43),
+ BCM6362_GROUP(gpio44),
+ BCM6362_GROUP(gpio45),
+ BCM6362_GROUP(gpio46),
+ BCM6362_GROUP(gpio47),
+ BCM6362_GROUP(nand_grp),
+};
+
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio0",
+};
+
+static const char * const sys_irq_groups[] = {
+ "gpio1",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio2",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio3",
+};
+
+static const char * const robosw_led_data_groups[] = {
+ "gpio4",
+};
+
+static const char * const robosw_led_clk_groups[] = {
+ "gpio5",
+};
+
+static const char * const robosw_led0_groups[] = {
+ "gpio6",
+};
+
+static const char * const robosw_led1_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const spi_cs2_groups[] = {
+ "gpio9",
+};
+
+static const char * const spi_cs3_groups[] = {
+ "gpio10",
+};
+
+static const char * const ntr_pulse_groups[] = {
+ "gpio11",
+};
+
+static const char * const uart1_scts_groups[] = {
+ "gpio12",
+};
+
+static const char * const uart1_srts_groups[] = {
+ "gpio13",
+};
+
+static const char * const uart1_sdin_groups[] = {
+ "gpio14",
+};
+
+static const char * const uart1_sdout_groups[] = {
+ "gpio15",
+};
+
+static const char * const adsl_spi_miso_groups[] = {
+ "gpio16",
+};
+
+static const char * const adsl_spi_mosi_groups[] = {
+ "gpio17",
+};
+
+static const char * const adsl_spi_clk_groups[] = {
+ "gpio18",
+};
+
+static const char * const adsl_spi_cs_groups[] = {
+ "gpio19",
+};
+
+static const char * const ephy0_led_groups[] = {
+ "gpio20",
+};
+
+static const char * const ephy1_led_groups[] = {
+ "gpio21",
+};
+
+static const char * const ephy2_led_groups[] = {
+ "gpio22",
+};
+
+static const char * const ephy3_led_groups[] = {
+ "gpio23",
+};
+
+static const char * const ext_irq0_groups[] = {
+ "gpio24",
+};
+
+static const char * const ext_irq1_groups[] = {
+ "gpio25",
+};
+
+static const char * const ext_irq2_groups[] = {
+ "gpio26",
+};
+
+static const char * const ext_irq3_groups[] = {
+ "gpio27",
+};
+
+static const char * const wifi_groups[] = {
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+};
+
+static const char * const nand_groups[] = {
+ "nand_grp",
+};
+
+#define BCM6362_LED_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_LEDCTRL, \
+ }
+
+#define BCM6362_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_MODE, \
+ }
+
+#define BCM6362_CTRL_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_CTRL, \
+ }
+
+#define BCM6362_BASEMODE_FUN(n, mask) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM6362_BASEMODE, \
+ .basemode_mask = (mask), \
+ }
+
+static const struct bcm6362_function bcm6362_funcs[] = {
+ BCM6362_LED_FUN(led),
+ BCM6362_MODE_FUN(usb_device_led),
+ BCM6362_MODE_FUN(sys_irq),
+ BCM6362_MODE_FUN(serial_led_clk),
+ BCM6362_MODE_FUN(serial_led_data),
+ BCM6362_MODE_FUN(robosw_led_data),
+ BCM6362_MODE_FUN(robosw_led_clk),
+ BCM6362_MODE_FUN(robosw_led0),
+ BCM6362_MODE_FUN(robosw_led1),
+ BCM6362_MODE_FUN(inet_led),
+ BCM6362_MODE_FUN(spi_cs2),
+ BCM6362_MODE_FUN(spi_cs3),
+ BCM6362_MODE_FUN(ntr_pulse),
+ BCM6362_MODE_FUN(uart1_scts),
+ BCM6362_MODE_FUN(uart1_srts),
+ BCM6362_MODE_FUN(uart1_sdin),
+ BCM6362_MODE_FUN(uart1_sdout),
+ BCM6362_MODE_FUN(adsl_spi_miso),
+ BCM6362_MODE_FUN(adsl_spi_mosi),
+ BCM6362_MODE_FUN(adsl_spi_clk),
+ BCM6362_MODE_FUN(adsl_spi_cs),
+ BCM6362_MODE_FUN(ephy0_led),
+ BCM6362_MODE_FUN(ephy1_led),
+ BCM6362_MODE_FUN(ephy2_led),
+ BCM6362_MODE_FUN(ephy3_led),
+ BCM6362_MODE_FUN(ext_irq0),
+ BCM6362_MODE_FUN(ext_irq1),
+ BCM6362_MODE_FUN(ext_irq2),
+ BCM6362_MODE_FUN(ext_irq3),
+ BCM6362_CTRL_FUN(wifi),
+ BCM6362_BASEMODE_FUN(nand, BASEMODE_NAND),
+};
+
+static int bcm6362_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6362_groups);
+}
+
+static const char *bcm6362_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6362_groups[group].name;
+}
+
+static int bcm6362_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6362_groups[group].pins;
+ *num_pins = bcm6362_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6362_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6362_funcs);
+}
+
+static const char *bcm6362_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6362_funcs[selector].name;
+}
+
+static int bcm6362_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6362_funcs[selector].groups;
+ *num_groups = bcm6362_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6362_rmw_mux(struct bcm6362_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= val & mask;
+ __raw_writel(tmp, reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm6362_set_gpio(struct bcm6362_pinctrl *pctl, unsigned pin)
+{
+ const struct pinctrl_pin_desc *desc = &bcm6362_pins[pin];
+ u32 mask = BIT(pin % 32);
+
+ if (desc->drv_data)
+ bcm6362_rmw_mux(pctl, pctl->basemode, (u32)desc->drv_data, 0);
+
+ if (pin < 32) {
+ /* base mode 0 => gpio 1 => mux function */
+ bcm6362_rmw_mux(pctl, pctl->mode, mask, 0);
+
+ /* pins 0-23 might be muxed to led */
+ if (pin < 24)
+ bcm6362_rmw_mux(pctl, pctl->led, mask, 0);
+ } else {
+ /* ctrl reg 0 => wifi function 1 => gpio */
+ bcm6362_rmw_mux(pctl, pctl->ctrl, mask, mask);
+ }
+}
+
+static int bcm6362_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6362_pingroup *grp = &bcm6362_groups[group];
+ const struct bcm6362_function *f = &bcm6362_funcs[selector];
+ unsigned i;
+ void __iomem *reg;
+ u32 val, mask;
+
+ for (i = 0; i < grp->num_pins; i++)
+ bcm6362_set_gpio(pctl, grp->pins[i]);
+
+ switch (f->reg) {
+ case BCM6362_LEDCTRL:
+ reg = pctl->led;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM6362_MODE:
+ reg = pctl->mode;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM6362_CTRL:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = 0;
+ break;
+ case BCM6362_BASEMODE:
+ reg = pctl->basemode;
+ mask = f->basemode_mask;
+ val = f->basemode_mask;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ bcm6362_rmw_mux(pctl, reg, mask, val);
+
+ return 0;
+}
+
+static int bcm6362_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6362_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm6362_set_gpio(pctl, offset);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6362_pctl_ops = {
+ .get_groups_count = bcm6362_pinctrl_get_group_count,
+ .get_group_name = bcm6362_pinctrl_get_group_name,
+ .get_group_pins = bcm6362_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6362_pmx_ops = {
+ .get_functions_count = bcm6362_pinctrl_get_func_count,
+ .get_function_name = bcm6362_pinctrl_get_func_name,
+ .get_function_groups = bcm6362_pinctrl_get_groups,
+ .set_mux = bcm6362_pinctrl_set_mux,
+ .gpio_request_enable = bcm6362_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6362_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6362_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *led, *mode, *ctrl, *basemode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
+ led = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(led))
+ return PTR_ERR(led);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
+ basemode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->led = led;
+ pctl->mode = mode;
+ pctl->ctrl = ctrl;
+ pctl->basemode = basemode;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6362_pctl_ops;
+ pctl->desc.pmxops = &bcm6362_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6362_pins);
+ pctl->desc.pins = bcm6362_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6362_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6362_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6362-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6362_pinctrl_driver = {
+ .probe = bcm6362_pinctrl_probe,
+ .driver = {
+ .name = "bcm6362-pinctrl",
+ .of_match_table = bcm6362_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6362_pinctrl_driver);

View File

@ -0,0 +1,84 @@
From 30594cf9bfff176a9e4b14c50dcd8b9d0cc3edec Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:36:51 +0200
Subject: [PATCH 10/16] Documentation: add BCM6368 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6368 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6368-pinctrl.txt | 67 ++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6368-pinctrl.txt
@@ -0,0 +1,67 @@
+* Broadcom BCM6368 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6368-pinctrl".
+- reg: Register specifiers of dirout, dat, mode registers.
+- reg-names: Must be "dirout", "dat", "mode".
+- brcm,gpiobasemode: Phandle to the gpio basemode register.
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6368-pinctrl";
+ reg = <0x10000080 0x08>,
+ <0x10000088 0x08>,
+ <0x10000098 0x04>;
+ reg-names = "dirout", "dat", "mode";
+ brcm,gpiobasemode = <&gpiobasemode>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+gpiobasemode: syscon@100000b8 {
+ compatible = "brcm,bcm6368-gpiobasemode", "syscon";
+ reg = <0x100000b8 4>;
+ native-endian;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 analog_afe0
+gpio1 1 analog_afe1
+gpio2 2 sys_irq
+gpio3 3 serial_led_data
+gpio4 4 serial_led_clk
+gpio5 5 inet_led
+gpio6 6 ephy0_led
+gpio7 7 ephy1_led
+gpio8 8 ephy2_led
+gpio9 9 ephy3_led
+gpio10 10 robosw_led_data
+gpio11 11 robosw_led_clk
+gpio12 12 robosw_led0
+gpio13 13 robosw_led1
+gpio14 14 usb_device_led
+gpio15 15 -
+gpio16 16 pci_req1
+gpio17 17 pci_gnt1
+gpio18 18 pci_intb
+gpio19 19 pci_req0
+gpio20 20 pci_gnt0
+gpio21 21 -
+gpio22 22 pcmcia_cd1
+gpio23 23 pcmcia_cd2
+gpio24 24 pcmcia_vs1
+gpio25 25 pcmcia_vs2
+gpio26 26 ebi_cs2
+gpio27 27 ebi_cs3
+gpio28 28 spi_cs2
+gpio29 29 spi_cs3
+gpio30 30 spi_cs4
+gpio31 31 spi_cs5
+uart1_grp 30-33 uart1

View File

@ -0,0 +1,610 @@
From 90be3cb4f1a45b8be4a4ec264cd66c2f8e893fcb Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:18:25 +0200
Subject: [PATCH 11/16] pinctrl: add a pincontrol driver for BCM6368
Add a pincontrol driver for BCM6368. BCM6368 allows muxing the first 32
GPIOs onto alternative functions. Not all are documented.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 15 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c | 573 ++++++++++++++++++++++++++++++
3 files changed, 589 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -23,3 +23,11 @@ config PINCTRL_BCM6362
select PINCONF
select PINCTRL_BCM63XX
select GENERIC_PINCONF
+
+config PINCTRL_BCM6368
+ bool "BCM6368 pincontrol driver"
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+ select MFD_SYSCON
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
+obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6368.c
@@ -0,0 +1,570 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6368_NGPIO 38
+
+#define BCM6368_BASEMODE_MASK 0x7
+#define BCM6368_BASEMODE_GPIO 0x0
+#define BCM6368_BASEMODE_UART1 0x1
+
+struct bcm6368_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6368_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned dir_out:16;
+ unsigned basemode:3;
+};
+
+struct bcm6368_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ struct regmap_field *overlay;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM6368_BASEMODE_PIN(a, b) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)true \
+ }
+
+static const struct pinctrl_pin_desc bcm6368_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ BCM6368_BASEMODE_PIN(30, "gpio30"),
+ BCM6368_BASEMODE_PIN(31, "gpio31"),
+ BCM6368_BASEMODE_PIN(32, "gpio32"),
+ BCM6368_BASEMODE_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned uart1_grp_pins[] = { 30, 31, 32, 33 };
+
+#define BCM6368_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6368_pingroup bcm6368_groups[] = {
+ BCM6368_GROUP(gpio0),
+ BCM6368_GROUP(gpio1),
+ BCM6368_GROUP(gpio2),
+ BCM6368_GROUP(gpio3),
+ BCM6368_GROUP(gpio4),
+ BCM6368_GROUP(gpio5),
+ BCM6368_GROUP(gpio6),
+ BCM6368_GROUP(gpio7),
+ BCM6368_GROUP(gpio8),
+ BCM6368_GROUP(gpio9),
+ BCM6368_GROUP(gpio10),
+ BCM6368_GROUP(gpio11),
+ BCM6368_GROUP(gpio12),
+ BCM6368_GROUP(gpio13),
+ BCM6368_GROUP(gpio14),
+ BCM6368_GROUP(gpio15),
+ BCM6368_GROUP(gpio16),
+ BCM6368_GROUP(gpio17),
+ BCM6368_GROUP(gpio18),
+ BCM6368_GROUP(gpio19),
+ BCM6368_GROUP(gpio20),
+ BCM6368_GROUP(gpio21),
+ BCM6368_GROUP(gpio22),
+ BCM6368_GROUP(gpio23),
+ BCM6368_GROUP(gpio24),
+ BCM6368_GROUP(gpio25),
+ BCM6368_GROUP(gpio26),
+ BCM6368_GROUP(gpio27),
+ BCM6368_GROUP(gpio28),
+ BCM6368_GROUP(gpio29),
+ BCM6368_GROUP(gpio30),
+ BCM6368_GROUP(gpio31),
+ BCM6368_GROUP(uart1_grp),
+};
+
+static const char * const analog_afe_0_groups[] = {
+ "gpio0",
+};
+
+static const char * const analog_afe_1_groups[] = {
+ "gpio1",
+};
+
+static const char * const sys_irq_groups[] = {
+ "gpio2",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio3",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio4",
+};
+
+static const char * const inet_led_groups[] = {
+ "gpio5",
+};
+
+static const char * const ephy0_led_groups[] = {
+ "gpio6",
+};
+
+static const char * const ephy1_led_groups[] = {
+ "gpio7",
+};
+
+static const char * const ephy2_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const ephy3_led_groups[] = {
+ "gpio9",
+};
+
+static const char * const robosw_led_data_groups[] = {
+ "gpio10",
+};
+
+static const char * const robosw_led_clk_groups[] = {
+ "gpio11",
+};
+
+static const char * const robosw_led0_groups[] = {
+ "gpio12",
+};
+
+static const char * const robosw_led1_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio14",
+};
+
+static const char * const pci_req1_groups[] = {
+ "gpio16",
+};
+
+static const char * const pci_gnt1_groups[] = {
+ "gpio17",
+};
+
+static const char * const pci_intb_groups[] = {
+ "gpio18",
+};
+
+static const char * const pci_req0_groups[] = {
+ "gpio19",
+};
+
+static const char * const pci_gnt0_groups[] = {
+ "gpio20",
+};
+
+static const char * const pcmcia_cd1_groups[] = {
+ "gpio22",
+};
+
+static const char * const pcmcia_cd2_groups[] = {
+ "gpio23",
+};
+
+static const char * const pcmcia_vs1_groups[] = {
+ "gpio24",
+};
+
+static const char * const pcmcia_vs2_groups[] = {
+ "gpio25",
+};
+
+static const char * const ebi_cs2_groups[] = {
+ "gpio26",
+};
+
+static const char * const ebi_cs3_groups[] = {
+ "gpio27",
+};
+
+static const char * const spi_cs2_groups[] = {
+ "gpio28",
+};
+
+static const char * const spi_cs3_groups[] = {
+ "gpio29",
+};
+
+static const char * const spi_cs4_groups[] = {
+ "gpio30",
+};
+
+static const char * const spi_cs5_groups[] = {
+ "gpio31",
+};
+
+static const char * const uart1_groups[] = {
+ "uart1_grp",
+};
+
+#define BCM6368_FUN(n, out) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .dir_out = out, \
+ }
+
+#define BCM6368_BASEMODE_FUN(n, val, out) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .basemode = BCM6368_BASEMODE_##val, \
+ .dir_out = out, \
+ }
+
+static const struct bcm6368_function bcm6368_funcs[] = {
+ BCM6368_FUN(analog_afe_0, 1),
+ BCM6368_FUN(analog_afe_1, 1),
+ BCM6368_FUN(sys_irq, 1),
+ BCM6368_FUN(serial_led_data, 1),
+ BCM6368_FUN(serial_led_clk, 1),
+ BCM6368_FUN(inet_led, 1),
+ BCM6368_FUN(ephy0_led, 1),
+ BCM6368_FUN(ephy1_led, 1),
+ BCM6368_FUN(ephy2_led, 1),
+ BCM6368_FUN(ephy3_led, 1),
+ BCM6368_FUN(robosw_led_data, 1),
+ BCM6368_FUN(robosw_led_clk, 1),
+ BCM6368_FUN(robosw_led0, 1),
+ BCM6368_FUN(robosw_led1, 1),
+ BCM6368_FUN(usb_device_led, 1),
+ BCM6368_FUN(pci_req1, 0),
+ BCM6368_FUN(pci_gnt1, 0),
+ BCM6368_FUN(pci_intb, 0),
+ BCM6368_FUN(pci_req0, 0),
+ BCM6368_FUN(pci_gnt0, 0),
+ BCM6368_FUN(pcmcia_cd1, 0),
+ BCM6368_FUN(pcmcia_cd2, 0),
+ BCM6368_FUN(pcmcia_vs1, 0),
+ BCM6368_FUN(pcmcia_vs2, 0),
+ BCM6368_FUN(ebi_cs2, 1),
+ BCM6368_FUN(ebi_cs3, 1),
+ BCM6368_FUN(spi_cs2, 1),
+ BCM6368_FUN(spi_cs3, 1),
+ BCM6368_FUN(spi_cs4, 1),
+ BCM6368_FUN(spi_cs5, 1),
+ BCM6368_BASEMODE_FUN(uart1, UART1, 0x6),
+};
+
+static int bcm6368_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6368_groups);
+}
+
+static const char *bcm6368_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6368_groups[group].name;
+}
+
+static int bcm6368_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6368_groups[group].pins;
+ *num_pins = bcm6368_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6368_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6368_funcs);
+}
+
+static const char *bcm6368_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6368_funcs[selector].name;
+}
+
+static int bcm6368_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6368_funcs[selector].groups;
+ *num_groups = bcm6368_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6368_rmw_mux(struct bcm6368_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= (val & mask);
+ __raw_writel(tmp, reg);
+}
+
+static int bcm6368_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6368_pingroup *grp = &bcm6368_groups[group];
+ const struct bcm6368_function *fun = &bcm6368_funcs[selector];
+ unsigned long flags;
+ int i, pin;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (fun->basemode) {
+ u32 mask = 0;
+
+ for (i = 0; i < grp->num_pins; i++) {
+ pin = grp->pins[i];
+ if (pin < 32)
+ mask |= BIT(pin);
+ }
+
+ bcm6368_rmw_mux(pctl, pctl->mode, mask, 0);
+ regmap_field_write(pctl->overlay, fun->basemode);
+ } else {
+ pin = grp->pins[0];
+
+ if (bcm6368_pins[pin].drv_data)
+ regmap_field_write(pctl->overlay,
+ BCM6368_BASEMODE_GPIO);
+
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(pin), BIT(pin));
+ }
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ int hw_gpio = bcm6368_pins[pin].number;
+ struct gpio_chip *gc = &pctl->gpio[hw_gpio / 32];
+
+ if (fun->dir_out & BIT(pin))
+ gc->direction_output(gc, hw_gpio % 32, 0);
+ else
+ gc->direction_input(gc, hw_gpio % 32);
+ }
+
+ return 0;
+}
+
+static int bcm6368_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6368_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned long flags;
+
+ if (offset >= 32 && !bcm6368_pins[offset].drv_data)
+ return 0;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ /* disable all functions using this pin */
+ if (offset < 32)
+ bcm6368_rmw_mux(pctl, pctl->mode, BIT(offset), 0);
+
+ if (bcm6368_pins[offset].drv_data)
+ regmap_field_write(pctl->overlay, BCM6368_BASEMODE_GPIO);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6368_pctl_ops = {
+ .get_groups_count = bcm6368_pinctrl_get_group_count,
+ .get_group_name = bcm6368_pinctrl_get_group_name,
+ .get_group_pins = bcm6368_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6368_pmx_ops = {
+ .get_functions_count = bcm6368_pinctrl_get_func_count,
+ .get_function_name = bcm6368_pinctrl_get_func_name,
+ .get_function_groups = bcm6368_pinctrl_get_groups,
+ .set_mux = bcm6368_pinctrl_set_mux,
+ .gpio_request_enable = bcm6368_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6368_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6368_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode;
+ struct regmap *basemode;
+ struct reg_field overlay = REG_FIELD(0, 0, 3);
+
+ basemode = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "brcm,gpiobasemode");
+
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->overlay = devm_regmap_field_alloc(&pdev->dev, basemode, overlay);
+ if (IS_ERR(pctl->overlay))
+ return PTR_ERR(pctl->overlay);
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ /* disable all muxes by default */
+ __raw_writel(0, pctl->mode);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6368_pctl_ops;
+ pctl->desc.pmxops = &bcm6368_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6368_pins);
+ pctl->desc.pins = bcm6368_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6368_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6368_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6368-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6368_pinctrl_driver = {
+ .probe = bcm6368_pinctrl_probe,
+ .driver = {
+ .name = "bcm6368-pinctrl",
+ .of_match_table = bcm6368_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6368_pinctrl_driver);

View File

@ -0,0 +1,106 @@
From 28cc80e4ada5d73d5305fd268297825cd8d01936 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:37:08 +0200
Subject: [PATCH 12/16] Documentation: add BCM63268 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in the BCM63268
family SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm63268-pinctrl.txt | 88 ++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm63268-pinctrl.txt
@@ -0,0 +1,88 @@
+* Broadcom BCM63268 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6362-pinctrl".
+- reg: Register specifiers of dirout, dat, led, mode, ctrl, basemode registers.
+- reg-names: Must be "dirout", "dat", "led", "mode", "ctrl", "basemode".
+- gpio-controller: Identifies this node as a GPIO controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@100000c0 {
+ compatible = "brcm,bcm63268-pinctrl";
+ reg = <0x100000c0 0x8>,
+ <0x100000c8 0x8>,
+ <0x100000d0 0x4>,
+ <0x100000d8 0x4>,
+ <0x100000dc 0x4>,
+ <0x100000f8 0x4>;
+ reg-names = "dirout", "dat", "led", "mode",
+ "ctrl", "basemode";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, serial_led_clk
+gpio1 1 led, serial_led_data
+gpio2 2 led,
+gpio3 3 led,
+gpio4 4 led,
+gpio5 5 led,
+gpio6 6 led,
+gpio7 7 led,
+gpio8 8 led, hsspi_cs6
+gpio9 9 led, hsspi_cs7
+gpio10 10 led, uart1_scts
+gpio11 11 led, uart1_srts
+gpio12 12 led, uart1_sdin
+gpio13 13 led, uart1_sdout
+gpio14 14 led, ntr_pulse_in
+gpio15 15 led, dsl_ntr_pulse_out
+gpio16 16 led, hsspi_cs4
+gpio17 17 led, hsspi_cs5
+gpio18 18 led, adsl_spi_miso
+gpio19 19 led, adsl_spi_mosi
+gpio20 20 led,
+gpio21 21 led,
+gpio22 22 led, vreg_clk
+gpio23 23 led, pcie_clkreq_b
+gpio24 24 uart1_scts
+gpio25 25 uart1_srts
+gpio26 26 uart1_sdin
+gpio27 27 uart1_sdout
+gpio28 28 ntr_pulse_in
+gpio29 29 dsl_ntr_pulse_out
+gpio30 30 switch_led_clk
+gpio31 31 switch_led_data
+gpio32 32 wifi
+gpio33 33 wifi
+gpio34 34 wifi
+gpio35 35 wifi
+gpio36 36 wifi
+gpio37 37 wifi
+gpio38 38 wifi
+gpio39 39 wifi
+gpio40 40 wifi
+gpio41 41 wifi
+gpio42 42 wifi
+gpio43 43 wifi
+gpio44 44 wifi
+gpio45 45 wifi
+gpio46 46 wifi
+gpio47 47 wifi
+gpio48 48 wifi
+gpio49 49 wifi
+gpio50 50 wifi
+gpio51 51 wifi
+nand_grp 2-7,24-31 nand
+dect_pd_grp 8-9 dect_pd
+vdsl_phy0_grp 10-11 vdsl_phy0
+vdsl_phy1_grp 12-13 vdsl_phy1
+vdsl_phy2_grp 24-25 vdsl_phy2
+vdsl_phy3_grp 26-27 vdsl_phy3

View File

@ -0,0 +1,749 @@
From 8665d3ea63649cc155286c75f83f694a930580e5 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:19:12 +0200
Subject: [PATCH 13/16] pinctrl: add a pincontrol driver for BCM63268
Add a pincontrol driver for BCM63268. BCM63268 allows muxing GPIOs
to different functions. Depending on the mux, these are either single
pin configurations or whole pin groups.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c | 710 +++++++++++++++++++++++++++++
2 files changed, 711 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -31,3 +31,10 @@ config PINCTRL_BCM6368
select PINCTRL_BCM63XX
select GENERIC_PINCONF
select MFD_SYSCON
+
+config PINCTRL_BCM63268
+ bool "BCM63268 pincontrol driver"
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
obj-$(CONFIG_PINCTRL_BCM6368) += pinctrl-bcm6368.o
+obj-$(CONFIG_PINCTRL_BCM63268) += pinctrl-bcm63268.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63268.c
@@ -0,0 +1,710 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM63268_NGPIO 52
+
+/* GPIO_BASEMODE register */
+#define BASEMODE_NAND BIT(2) /* GPIOs 2-7, 24-31 */
+#define BASEMODE_GPIO35 BIT(4) /* GPIO 35 */
+#define BASEMODE_DECTPD BIT(5) /* GPIOs 8/9 */
+#define BASEMODE_VDSL_PHY_0 BIT(6) /* GPIOs 10/11 */
+#define BASEMODE_VDSL_PHY_1 BIT(7) /* GPIOs 12/13 */
+#define BASEMODE_VDSL_PHY_2 BIT(8) /* GPIOs 24/25 */
+#define BASEMODE_VDSL_PHY_3 BIT(9) /* GPIOs 26/27 */
+
+enum bcm63268_pinctrl_reg {
+ BCM63268_LEDCTRL,
+ BCM63268_MODE,
+ BCM63268_CTRL,
+ BCM63268_BASEMODE,
+};
+
+struct bcm63268_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm63268_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ enum bcm63268_pinctrl_reg reg;
+ u32 mask;
+};
+
+struct bcm63268_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *led;
+ void __iomem *mode;
+ void __iomem *ctrl;
+ void __iomem *basemode;
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+#define BCM63268_PIN(a, b, basemode) \
+ { \
+ .number = a, \
+ .name = b, \
+ .drv_data = (void *)(basemode) \
+ }
+
+static const struct pinctrl_pin_desc bcm63268_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ BCM63268_PIN(2, "gpio2", BASEMODE_NAND),
+ BCM63268_PIN(3, "gpio3", BASEMODE_NAND),
+ BCM63268_PIN(4, "gpio4", BASEMODE_NAND),
+ BCM63268_PIN(5, "gpio5", BASEMODE_NAND),
+ BCM63268_PIN(6, "gpio6", BASEMODE_NAND),
+ BCM63268_PIN(7, "gpio7", BASEMODE_NAND),
+ BCM63268_PIN(8, "gpio8", BASEMODE_DECTPD),
+ BCM63268_PIN(9, "gpio9", BASEMODE_DECTPD),
+ BCM63268_PIN(10, "gpio10", BASEMODE_VDSL_PHY_0),
+ BCM63268_PIN(11, "gpio11", BASEMODE_VDSL_PHY_0),
+ BCM63268_PIN(12, "gpio12", BASEMODE_VDSL_PHY_1),
+ BCM63268_PIN(13, "gpio13", BASEMODE_VDSL_PHY_1),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ BCM63268_PIN(24, "gpio24", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
+ BCM63268_PIN(25, "gpio25", BASEMODE_NAND | BASEMODE_VDSL_PHY_2),
+ BCM63268_PIN(26, "gpio26", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
+ BCM63268_PIN(27, "gpio27", BASEMODE_NAND | BASEMODE_VDSL_PHY_3),
+ BCM63268_PIN(28, "gpio28", BASEMODE_NAND),
+ BCM63268_PIN(29, "gpio29", BASEMODE_NAND),
+ BCM63268_PIN(30, "gpio30", BASEMODE_NAND),
+ BCM63268_PIN(31, "gpio31", BASEMODE_NAND),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
+ PINCTRL_PIN(50, "gpio50"),
+ PINCTRL_PIN(51, "gpio51"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+static unsigned gpio48_pins[] = { 48 };
+static unsigned gpio49_pins[] = { 49 };
+static unsigned gpio50_pins[] = { 50 };
+static unsigned gpio51_pins[] = { 51 };
+
+static unsigned nand_grp_pins[] = {
+ 2, 3, 4, 5, 6, 7, 24,
+ 25, 26, 27, 28, 29, 30, 31,
+};
+
+static unsigned dectpd_grp_pins[] = { 8, 9 };
+static unsigned vdsl_phy0_grp_pins[] = { 10, 11 };
+static unsigned vdsl_phy1_grp_pins[] = { 12, 13 };
+static unsigned vdsl_phy2_grp_pins[] = { 24, 25 };
+static unsigned vdsl_phy3_grp_pins[] = { 26, 27 };
+
+#define BCM63268_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm63268_pingroup bcm63268_groups[] = {
+ BCM63268_GROUP(gpio0),
+ BCM63268_GROUP(gpio1),
+ BCM63268_GROUP(gpio2),
+ BCM63268_GROUP(gpio3),
+ BCM63268_GROUP(gpio4),
+ BCM63268_GROUP(gpio5),
+ BCM63268_GROUP(gpio6),
+ BCM63268_GROUP(gpio7),
+ BCM63268_GROUP(gpio8),
+ BCM63268_GROUP(gpio9),
+ BCM63268_GROUP(gpio10),
+ BCM63268_GROUP(gpio11),
+ BCM63268_GROUP(gpio12),
+ BCM63268_GROUP(gpio13),
+ BCM63268_GROUP(gpio14),
+ BCM63268_GROUP(gpio15),
+ BCM63268_GROUP(gpio16),
+ BCM63268_GROUP(gpio17),
+ BCM63268_GROUP(gpio18),
+ BCM63268_GROUP(gpio19),
+ BCM63268_GROUP(gpio20),
+ BCM63268_GROUP(gpio21),
+ BCM63268_GROUP(gpio22),
+ BCM63268_GROUP(gpio23),
+ BCM63268_GROUP(gpio24),
+ BCM63268_GROUP(gpio25),
+ BCM63268_GROUP(gpio26),
+ BCM63268_GROUP(gpio27),
+ BCM63268_GROUP(gpio28),
+ BCM63268_GROUP(gpio29),
+ BCM63268_GROUP(gpio30),
+ BCM63268_GROUP(gpio31),
+ BCM63268_GROUP(gpio32),
+ BCM63268_GROUP(gpio33),
+ BCM63268_GROUP(gpio34),
+ BCM63268_GROUP(gpio35),
+ BCM63268_GROUP(gpio36),
+ BCM63268_GROUP(gpio37),
+ BCM63268_GROUP(gpio38),
+ BCM63268_GROUP(gpio39),
+ BCM63268_GROUP(gpio40),
+ BCM63268_GROUP(gpio41),
+ BCM63268_GROUP(gpio42),
+ BCM63268_GROUP(gpio43),
+ BCM63268_GROUP(gpio44),
+ BCM63268_GROUP(gpio45),
+ BCM63268_GROUP(gpio46),
+ BCM63268_GROUP(gpio47),
+ BCM63268_GROUP(gpio48),
+ BCM63268_GROUP(gpio49),
+ BCM63268_GROUP(gpio50),
+ BCM63268_GROUP(gpio51),
+
+ /* multi pin groups */
+ BCM63268_GROUP(nand_grp),
+ BCM63268_GROUP(dectpd_grp),
+ BCM63268_GROUP(vdsl_phy0_grp),
+ BCM63268_GROUP(vdsl_phy1_grp),
+ BCM63268_GROUP(vdsl_phy2_grp),
+ BCM63268_GROUP(vdsl_phy3_grp),
+};
+
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio0",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio1",
+};
+
+static const char * const hsspi_cs4_groups[] = {
+ "gpio16",
+};
+
+static const char * const hsspi_cs5_groups[] = {
+ "gpio17",
+};
+
+static const char * const hsspi_cs6_groups[] = {
+ "gpio8",
+};
+
+static const char * const hsspi_cs7_groups[] = {
+ "gpio9",
+};
+
+static const char * const uart1_scts_groups[] = {
+ "gpio10",
+ "gpio24",
+};
+
+static const char * const uart1_srts_groups[] = {
+ "gpio11",
+ "gpio25",
+};
+
+static const char * const uart1_sdin_groups[] = {
+ "gpio12",
+ "gpio26",
+};
+
+static const char * const uart1_sdout_groups[] = {
+ "gpio13",
+ "gpio27",
+};
+
+static const char * const ntr_pulse_in_groups[] = {
+ "gpio14",
+ "gpio28",
+};
+
+static const char * const dsl_ntr_pulse_out_groups[] = {
+ "gpio15",
+ "gpio29",
+};
+
+static const char * const adsl_spi_miso_groups[] = {
+ "gpio18",
+};
+
+static const char * const adsl_spi_mosi_groups[] = {
+ "gpio19",
+};
+
+static const char * const vreg_clk_groups[] = {
+ "gpio22",
+};
+
+static const char * const pcie_clkreq_b_groups[] = {
+ "gpio23",
+};
+
+static const char * const switch_led_clk_groups[] = {
+ "gpio30",
+};
+
+static const char * const switch_led_data_groups[] = {
+ "gpio31",
+};
+
+static const char * const wifi_groups[] = {
+ "gpio32",
+ "gpio33",
+ "gpio34",
+ "gpio35",
+ "gpio36",
+ "gpio37",
+ "gpio38",
+ "gpio39",
+ "gpio40",
+ "gpio41",
+ "gpio42",
+ "gpio43",
+ "gpio44",
+ "gpio45",
+ "gpio46",
+ "gpio47",
+ "gpio48",
+ "gpio49",
+ "gpio50",
+ "gpio51",
+};
+
+static const char * const nand_groups[] = {
+ "nand_grp",
+};
+
+static const char * const dectpd_groups[] = {
+ "dectpd_grp",
+};
+
+static const char * const vdsl_phy_override_0_groups[] = {
+ "vdsl_phy_override_0_grp",
+};
+
+static const char * const vdsl_phy_override_1_groups[] = {
+ "vdsl_phy_override_1_grp",
+};
+
+static const char * const vdsl_phy_override_2_groups[] = {
+ "vdsl_phy_override_2_grp",
+};
+
+static const char * const vdsl_phy_override_3_groups[] = {
+ "vdsl_phy_override_3_grp",
+};
+
+#define BCM63268_LED_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_LEDCTRL, \
+ }
+
+#define BCM63268_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_MODE, \
+ }
+
+#define BCM63268_CTRL_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_CTRL, \
+ }
+
+#define BCM63268_BASEMODE_FUN(n, val) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .reg = BCM63268_BASEMODE, \
+ .mask = val, \
+ }
+
+static const struct bcm63268_function bcm63268_funcs[] = {
+ BCM63268_LED_FUN(led),
+ BCM63268_MODE_FUN(serial_led_clk),
+ BCM63268_MODE_FUN(serial_led_data),
+ BCM63268_MODE_FUN(hsspi_cs6),
+ BCM63268_MODE_FUN(hsspi_cs7),
+ BCM63268_MODE_FUN(uart1_scts),
+ BCM63268_MODE_FUN(uart1_srts),
+ BCM63268_MODE_FUN(uart1_sdin),
+ BCM63268_MODE_FUN(uart1_sdout),
+ BCM63268_MODE_FUN(ntr_pulse_in),
+ BCM63268_MODE_FUN(dsl_ntr_pulse_out),
+ BCM63268_MODE_FUN(hsspi_cs4),
+ BCM63268_MODE_FUN(hsspi_cs5),
+ BCM63268_MODE_FUN(adsl_spi_miso),
+ BCM63268_MODE_FUN(adsl_spi_mosi),
+ BCM63268_MODE_FUN(vreg_clk),
+ BCM63268_MODE_FUN(pcie_clkreq_b),
+ BCM63268_MODE_FUN(switch_led_clk),
+ BCM63268_MODE_FUN(switch_led_data),
+ BCM63268_CTRL_FUN(wifi),
+ BCM63268_BASEMODE_FUN(nand, BASEMODE_NAND),
+ BCM63268_BASEMODE_FUN(dectpd, BASEMODE_DECTPD),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_0, BASEMODE_VDSL_PHY_0),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_1, BASEMODE_VDSL_PHY_1),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_2, BASEMODE_VDSL_PHY_2),
+ BCM63268_BASEMODE_FUN(vdsl_phy_override_3, BASEMODE_VDSL_PHY_3),
+};
+
+static int bcm63268_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm63268_groups);
+}
+
+static const char *bcm63268_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm63268_groups[group].name;
+}
+
+static int bcm63268_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm63268_groups[group].pins;
+ *num_pins = bcm63268_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm63268_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm63268_funcs);
+}
+
+static const char *bcm63268_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm63268_funcs[selector].name;
+}
+
+static int bcm63268_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm63268_funcs[selector].groups;
+ *num_groups = bcm63268_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm63268_rmw_mux(struct bcm63268_pinctrl *pctl, void __iomem *reg,
+ u32 mask, u32 val)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ tmp = __raw_readl(reg);
+ tmp &= ~mask;
+ tmp |= val;
+ __raw_writel(tmp, reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm63268_set_gpio(struct bcm63268_pinctrl *pctl, unsigned pin)
+{
+ const struct pinctrl_pin_desc *desc = &bcm63268_pins[pin];
+ u32 basemode = (unsigned long)desc->drv_data;
+ u32 mask = BIT(pin % 32);
+
+ if (basemode)
+ bcm63268_rmw_mux(pctl, pctl->basemode, basemode, 0);
+
+ if (pin < 32) {
+ /* base mode: 0 => gpio, 1 => mux function */
+ bcm63268_rmw_mux(pctl, pctl->mode, mask, 0);
+
+ /* pins 0-23 might be muxed to led */
+ if (pin < 24)
+ bcm63268_rmw_mux(pctl, pctl->led, mask, 0);
+ } else if (pin < 52) {
+ /* ctrl reg: 0 => wifi function, 1 => gpio */
+ bcm63268_rmw_mux(pctl, pctl->ctrl, mask, mask);
+ }
+}
+
+static int bcm63268_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm63268_pingroup *grp = &bcm63268_groups[group];
+ const struct bcm63268_function *f = &bcm63268_funcs[selector];
+ unsigned i;
+ void __iomem *reg;
+ u32 val, mask;
+
+ for (i = 0; i < grp->num_pins; i++)
+ bcm63268_set_gpio(pctl, grp->pins[i]);
+
+ switch (f->reg) {
+ case BCM63268_LEDCTRL:
+ reg = pctl->led;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM63268_MODE:
+ reg = pctl->mode;
+ mask = BIT(grp->pins[0]);
+ val = BIT(grp->pins[0]);
+ break;
+ case BCM63268_CTRL:
+ reg = pctl->ctrl;
+ mask = BIT(grp->pins[0]);
+ val = 0;
+ break;
+ case BCM63268_BASEMODE:
+ reg = pctl->basemode;
+ mask = f->mask;
+ val = f->mask;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ bcm63268_rmw_mux(pctl, reg, mask, val);
+
+ return 0;
+}
+
+static int bcm63268_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm63268_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ bcm63268_set_gpio(pctl, offset);
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm63268_pctl_ops = {
+ .get_groups_count = bcm63268_pinctrl_get_group_count,
+ .get_group_name = bcm63268_pinctrl_get_group_name,
+ .get_group_pins = bcm63268_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm63268_pmx_ops = {
+ .get_functions_count = bcm63268_pinctrl_get_func_count,
+ .get_function_name = bcm63268_pinctrl_get_func_name,
+ .get_function_groups = bcm63268_pinctrl_get_groups,
+ .set_mux = bcm63268_pinctrl_set_mux,
+ .gpio_request_enable = bcm63268_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm63268_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm63268_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *led, *mode, *ctrl, *basemode;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "led");
+ led = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(led))
+ return PTR_ERR(led);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
+ ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basemode");
+ basemode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(basemode))
+ return PTR_ERR(basemode);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->led = led;
+ pctl->mode = mode;
+ pctl->ctrl = ctrl;
+ pctl->basemode = basemode;
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm63268_pctl_ops;
+ pctl->desc.pmxops = &bcm63268_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm63268_pins);
+ pctl->desc.pins = bcm63268_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM63268_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm63268_pinctrl_match[] = {
+ { .compatible = "brcm,bcm63268-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm63268_pinctrl_driver = {
+ .probe = bcm63268_pinctrl_probe,
+ .driver = {
+ .name = "bcm63268-pinctrl",
+ .of_match_table = bcm63268_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm63268_pinctrl_driver);

View File

@ -0,0 +1,96 @@
From 8439e5d2e69f54a532bb5f8ec001b4b5a3035574 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Wed, 27 Jul 2016 11:38:05 +0200
Subject: [PATCH 14/16] Documentation: add BCM6318 pincontroller binding
documentation
Add binding documentation for the pincontrol core found in BCM6318 SoCs.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
.../bindings/pinctrl/brcm,bcm6318-pinctrl.txt | 79 ++++++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm6318-pinctrl.txt
@@ -0,0 +1,79 @@
+* Broadcom BCM6318 pin controller
+
+Required properties:
+- compatible: Must be "brcm,bcm6318-pinctrl".
+- regs: Register specifiers of dirout, dat, mode, mux, and pad registers.
+- reg-names: Must be "dirout", "dat", "mode", "mux", "pad".
+- gpio-controller: Identifies this node as a gpio controller.
+- #gpio-cells: Must be <2>.
+
+Example:
+
+pinctrl: pin-controller@10000080 {
+ compatible = "brcm,bcm6318-pinctrl";
+ reg = <0x10000080 0x08>,
+ <0x10000088 0x08>,
+ <0x10000098 0x04>,
+ <0x1000009c 0x0c>,
+ <0x100000d4 0x18>;
+ reg-names = "dirout", "dat", "mode", "mux", "pad";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+
+Available pins/groups and functions:
+
+name pins functions
+-----------------------------------------------------------
+gpio0 0 led, ephy0_spd_led
+gpio1 1 led, ephy1_spd_led
+gpio2 2 led, ephy2_spd_led
+gpio3 3 led, ephy3_spd_led
+gpio4 4 led, ephy0_act_led
+gpio5 5 led, ephy1_act_led
+gpio6 6 led, ephy2_act_led, serial_led_data
+gpio7 7 led, ephy3_act_led, serial_led_clk
+gpio8 8 led, inet_act_led
+gpio9 9 led, inet_fail_led
+gpio10 10 led, dsl_led
+gpio11 11 led, post_fail_led
+gpio12 12 led, wlan_wps_led
+gpio13 13 led, usb_pwron, usb_device_led
+gpio14 14 led
+gpio15 15 led
+gpio16 16 led
+gpio17 17 led
+gpio18 18 led
+gpio19 19 led
+gpio20 20 led
+gpio21 21 led
+gpio22 22 led
+gpio23 23 led
+gpio24 24 -
+gpio25 25 -
+gpio26 26 -
+gpio27 27 -
+gpio28 28 -
+gpio29 29 -
+gpio30 30 -
+gpio31 31 -
+gpio32 32 -
+gpio33 33 -
+gpio34 34 -
+gpio35 35 -
+gpio36 36 -
+gpio37 37 -
+gpio38 38 -
+gpio39 39 -
+gpio40 40 usb_active
+gpio41 41 -
+gpio42 42 -
+gpio43 43 -
+gpio44 44 -
+gpio45 45 -
+gpio46 46 -
+gpio47 47 -
+gpio48 48 -
+gpio49 49 -

View File

@ -0,0 +1,609 @@
From bd9c250ef85e6f99aa5d59b21abb87d0a48f2f61 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Fri, 24 Jun 2016 22:20:39 +0200
Subject: [PATCH 15/16] pinctrl: add a pincontrol driver for BCM6318
Add a pincontrol driver for BCM6318. BCM6318 allows muxing most GPIOs
to different functions. BCM6318 is similar to BCM6328 with the addition
of a pad register, and the GPIO meaning of the mux register changes
based on the GPIO number.
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
drivers/pinctrl/bcm63xx/Kconfig | 7 +
drivers/pinctrl/bcm63xx/Makefile | 1 +
drivers/pinctrl/bcm63xx/pinctrl-bcm6318.c | 564 ++++++++++++++++++++++++++++++
3 files changed, 572 insertions(+)
create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm6318.c
--- a/drivers/pinctrl/bcm63xx/Kconfig
+++ b/drivers/pinctrl/bcm63xx/Kconfig
@@ -2,6 +2,13 @@ config PINCTRL_BCM63XX
bool
select GPIO_GENERIC
+config PINCTRL_BCM6318
+ bool "BCM6318 pincontrol driver"
+ select PINMUX
+ select PINCONF
+ select PINCTRL_BCM63XX
+ select GENERIC_PINCONF
+
config PINCTRL_BCM6328
bool "BCM6328 pincontrol driver"
select PINMUX
--- a/drivers/pinctrl/bcm63xx/Makefile
+++ b/drivers/pinctrl/bcm63xx/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
+obj-$(CONFIG_PINCTRL_BCM6318) += pinctrl-bcm6318.o
obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
--- /dev/null
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm6318.c
@@ -0,0 +1,564 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-bcm63xx.h"
+
+#define BCM6318_NGPIO 50
+
+struct bcm6318_pingroup {
+ const char *name;
+ const unsigned * const pins;
+ const unsigned num_pins;
+};
+
+struct bcm6318_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+
+ unsigned mode_val:1;
+ unsigned mux_val:2;
+};
+
+struct bcm6318_pinctrl {
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+
+ void __iomem *mode;
+ void __iomem *mux[3];
+ void __iomem *pad[6];
+
+ /* register access lock */
+ spinlock_t lock;
+
+ struct gpio_chip gpio[2];
+};
+
+static const struct pinctrl_pin_desc bcm6318_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
+};
+
+static unsigned gpio0_pins[] = { 0 };
+static unsigned gpio1_pins[] = { 1 };
+static unsigned gpio2_pins[] = { 2 };
+static unsigned gpio3_pins[] = { 3 };
+static unsigned gpio4_pins[] = { 4 };
+static unsigned gpio5_pins[] = { 5 };
+static unsigned gpio6_pins[] = { 6 };
+static unsigned gpio7_pins[] = { 7 };
+static unsigned gpio8_pins[] = { 8 };
+static unsigned gpio9_pins[] = { 9 };
+static unsigned gpio10_pins[] = { 10 };
+static unsigned gpio11_pins[] = { 11 };
+static unsigned gpio12_pins[] = { 12 };
+static unsigned gpio13_pins[] = { 13 };
+static unsigned gpio14_pins[] = { 14 };
+static unsigned gpio15_pins[] = { 15 };
+static unsigned gpio16_pins[] = { 16 };
+static unsigned gpio17_pins[] = { 17 };
+static unsigned gpio18_pins[] = { 18 };
+static unsigned gpio19_pins[] = { 19 };
+static unsigned gpio20_pins[] = { 20 };
+static unsigned gpio21_pins[] = { 21 };
+static unsigned gpio22_pins[] = { 22 };
+static unsigned gpio23_pins[] = { 23 };
+static unsigned gpio24_pins[] = { 24 };
+static unsigned gpio25_pins[] = { 25 };
+static unsigned gpio26_pins[] = { 26 };
+static unsigned gpio27_pins[] = { 27 };
+static unsigned gpio28_pins[] = { 28 };
+static unsigned gpio29_pins[] = { 29 };
+static unsigned gpio30_pins[] = { 30 };
+static unsigned gpio31_pins[] = { 31 };
+static unsigned gpio32_pins[] = { 32 };
+static unsigned gpio33_pins[] = { 33 };
+static unsigned gpio34_pins[] = { 34 };
+static unsigned gpio35_pins[] = { 35 };
+static unsigned gpio36_pins[] = { 36 };
+static unsigned gpio37_pins[] = { 37 };
+static unsigned gpio38_pins[] = { 38 };
+static unsigned gpio39_pins[] = { 39 };
+static unsigned gpio40_pins[] = { 40 };
+static unsigned gpio41_pins[] = { 41 };
+static unsigned gpio42_pins[] = { 42 };
+static unsigned gpio43_pins[] = { 43 };
+static unsigned gpio44_pins[] = { 44 };
+static unsigned gpio45_pins[] = { 45 };
+static unsigned gpio46_pins[] = { 46 };
+static unsigned gpio47_pins[] = { 47 };
+static unsigned gpio48_pins[] = { 48 };
+static unsigned gpio49_pins[] = { 49 };
+
+#define BCM6318_GROUP(n) \
+ { \
+ .name = #n, \
+ .pins = n##_pins, \
+ .num_pins = ARRAY_SIZE(n##_pins), \
+ }
+
+static struct bcm6318_pingroup bcm6318_groups[] = {
+ BCM6318_GROUP(gpio0),
+ BCM6318_GROUP(gpio1),
+ BCM6318_GROUP(gpio2),
+ BCM6318_GROUP(gpio3),
+ BCM6318_GROUP(gpio4),
+ BCM6318_GROUP(gpio5),
+ BCM6318_GROUP(gpio6),
+ BCM6318_GROUP(gpio7),
+ BCM6318_GROUP(gpio8),
+ BCM6318_GROUP(gpio9),
+ BCM6318_GROUP(gpio10),
+ BCM6318_GROUP(gpio11),
+ BCM6318_GROUP(gpio12),
+ BCM6318_GROUP(gpio13),
+ BCM6318_GROUP(gpio14),
+ BCM6318_GROUP(gpio15),
+ BCM6318_GROUP(gpio16),
+ BCM6318_GROUP(gpio17),
+ BCM6318_GROUP(gpio18),
+ BCM6318_GROUP(gpio19),
+ BCM6318_GROUP(gpio20),
+ BCM6318_GROUP(gpio21),
+ BCM6318_GROUP(gpio22),
+ BCM6318_GROUP(gpio23),
+ BCM6318_GROUP(gpio24),
+ BCM6318_GROUP(gpio25),
+ BCM6318_GROUP(gpio26),
+ BCM6318_GROUP(gpio27),
+ BCM6318_GROUP(gpio28),
+ BCM6318_GROUP(gpio29),
+ BCM6318_GROUP(gpio30),
+ BCM6318_GROUP(gpio31),
+ BCM6318_GROUP(gpio32),
+ BCM6318_GROUP(gpio33),
+ BCM6318_GROUP(gpio34),
+ BCM6318_GROUP(gpio35),
+ BCM6318_GROUP(gpio36),
+ BCM6318_GROUP(gpio37),
+ BCM6318_GROUP(gpio38),
+ BCM6318_GROUP(gpio39),
+ BCM6318_GROUP(gpio40),
+ BCM6318_GROUP(gpio41),
+ BCM6318_GROUP(gpio42),
+ BCM6318_GROUP(gpio43),
+ BCM6318_GROUP(gpio44),
+ BCM6318_GROUP(gpio45),
+ BCM6318_GROUP(gpio46),
+ BCM6318_GROUP(gpio47),
+ BCM6318_GROUP(gpio48),
+ BCM6318_GROUP(gpio49),
+};
+
+/* GPIO_MODE */
+static const char * const led_groups[] = {
+ "gpio0",
+ "gpio1",
+ "gpio2",
+ "gpio3",
+ "gpio4",
+ "gpio5",
+ "gpio6",
+ "gpio7",
+ "gpio8",
+ "gpio9",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gpio15",
+ "gpio16",
+ "gpio17",
+ "gpio18",
+ "gpio19",
+ "gpio20",
+ "gpio21",
+ "gpio22",
+ "gpio23",
+};
+
+/* PINMUX_SEL */
+static const char * const ephy0_spd_led_groups[] = {
+ "gpio0",
+};
+
+static const char * const ephy1_spd_led_groups[] = {
+ "gpio1",
+};
+
+static const char * const ephy2_spd_led_groups[] = {
+ "gpio2",
+};
+
+static const char * const ephy3_spd_led_groups[] = {
+ "gpio3",
+};
+
+static const char * const ephy0_act_led_groups[] = {
+ "gpio4",
+};
+
+static const char * const ephy1_act_led_groups[] = {
+ "gpio5",
+};
+
+static const char * const ephy2_act_led_groups[] = {
+ "gpio6",
+};
+
+static const char * const ephy3_act_led_groups[] = {
+ "gpio7",
+};
+
+static const char * const serial_led_data_groups[] = {
+ "gpio6",
+};
+
+static const char * const serial_led_clk_groups[] = {
+ "gpio7",
+};
+
+static const char * const inet_act_led_groups[] = {
+ "gpio8",
+};
+
+static const char * const inet_fail_led_groups[] = {
+ "gpio9",
+};
+
+static const char * const dsl_led_groups[] = {
+ "gpio10",
+};
+
+static const char * const post_fail_led_groups[] = {
+ "gpio11",
+};
+
+static const char * const wlan_wps_led_groups[] = {
+ "gpio12",
+};
+
+static const char * const usb_pwron_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_device_led_groups[] = {
+ "gpio13",
+};
+
+static const char * const usb_active_groups[] = {
+ "gpio40",
+};
+
+#define BCM6318_MODE_FUN(n) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mode_val = 1, \
+ }
+
+#define BCM6318_MUX_FUN(n, mux) \
+ { \
+ .name = #n, \
+ .groups = n##_groups, \
+ .num_groups = ARRAY_SIZE(n##_groups), \
+ .mux_val = mux, \
+ }
+
+static const struct bcm6318_function bcm6318_funcs[] = {
+ BCM6318_MODE_FUN(led),
+ BCM6318_MUX_FUN(ephy0_spd_led, 1),
+ BCM6318_MUX_FUN(ephy1_spd_led, 1),
+ BCM6318_MUX_FUN(ephy2_spd_led, 1),
+ BCM6318_MUX_FUN(ephy3_spd_led, 1),
+ BCM6318_MUX_FUN(ephy0_act_led, 1),
+ BCM6318_MUX_FUN(ephy1_act_led, 1),
+ BCM6318_MUX_FUN(ephy2_act_led, 1),
+ BCM6318_MUX_FUN(ephy3_act_led, 1),
+ BCM6318_MUX_FUN(serial_led_data, 3),
+ BCM6318_MUX_FUN(serial_led_clk, 3),
+ BCM6318_MUX_FUN(inet_act_led, 1),
+ BCM6318_MUX_FUN(inet_fail_led, 1),
+ BCM6318_MUX_FUN(dsl_led, 1),
+ BCM6318_MUX_FUN(post_fail_led, 1),
+ BCM6318_MUX_FUN(wlan_wps_led, 1),
+ BCM6318_MUX_FUN(usb_pwron, 1),
+ BCM6318_MUX_FUN(usb_device_led, 2),
+ BCM6318_MUX_FUN(usb_active, 2),
+};
+
+static int bcm6318_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6318_groups);
+}
+
+static const char *bcm6318_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ return bcm6318_groups[group].name;
+}
+
+static int bcm6318_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group, const unsigned **pins,
+ unsigned *num_pins)
+{
+ *pins = bcm6318_groups[group].pins;
+ *num_pins = bcm6318_groups[group].num_pins;
+
+ return 0;
+}
+
+static int bcm6318_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(bcm6318_funcs);
+}
+
+static const char *bcm6318_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return bcm6318_funcs[selector].name;
+}
+
+static int bcm6318_pinctrl_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = bcm6318_funcs[selector].groups;
+ *num_groups = bcm6318_funcs[selector].num_groups;
+
+ return 0;
+}
+
+static void bcm6318_rmw_mux(struct bcm6318_pinctrl *pctl, unsigned pin,
+ u32 mode, u32 mux)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ if (pin < 32) {
+ reg = __raw_readl(pctl->mode);
+ reg &= ~BIT(pin);
+ if (mode)
+ reg |= BIT(pin);
+ __raw_writel(reg, pctl->mode);
+ }
+
+ if (pin < 48) {
+ reg = __raw_readl(pctl->mux[pin / 16]);
+ reg &= ~(3UL << ((pin % 16) * 2));
+ reg |= mux << ((pin % 16) * 2);
+ __raw_writel(reg, pctl->mux[pin / 16]);
+ }
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static void bcm6318_set_pad(struct bcm6318_pinctrl *pctl, unsigned pin, u8 val)
+{
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ reg = __raw_readl(pctl->pad[pin / 8]);
+ reg &= ~(0xfUL << ((pin % 8) * 4));
+ reg |= val << ((pin % 8) * 4);
+ __raw_writel(reg, pctl->pad[pin / 8]);
+ spin_unlock_irqrestore(&pctl->lock, flags);
+}
+
+static int bcm6318_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ struct bcm6318_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm6318_pingroup *grp = &bcm6318_groups[group];
+ const struct bcm6318_function *f = &bcm6318_funcs[selector];
+
+ bcm6318_rmw_mux(pctl, grp->pins[0], f->mode_val, f->mux_val);
+
+ return 0;
+}
+
+static int bcm6318_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm6318_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable all functions using this pin */
+ if (offset < 13) {
+ /* GPIOs 0-12 use mux 0 as GPIO function */
+ bcm6318_rmw_mux(pctl, offset, 0, 0);
+ } else if (offset < 42) {
+ /* GPIOs 13-41 use mux 3 as GPIO function */
+ bcm6318_rmw_mux(pctl, offset, 0, 3);
+
+ /* FIXME: revert to old value for non gpio? */
+ bcm6318_set_pad(pctl, offset, 0);
+ } else {
+ /* no idea, really */
+ }
+
+ return 0;
+}
+
+static struct pinctrl_ops bcm6318_pctl_ops = {
+ .get_groups_count = bcm6318_pinctrl_get_group_count,
+ .get_group_name = bcm6318_pinctrl_get_group_name,
+ .get_group_pins = bcm6318_pinctrl_get_group_pins,
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+};
+
+static struct pinmux_ops bcm6318_pmx_ops = {
+ .get_functions_count = bcm6318_pinctrl_get_func_count,
+ .get_function_name = bcm6318_pinctrl_get_func_name,
+ .get_function_groups = bcm6318_pinctrl_get_groups,
+ .set_mux = bcm6318_pinctrl_set_mux,
+ .gpio_request_enable = bcm6318_gpio_request_enable,
+ .strict = true,
+};
+
+static int bcm6318_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm6318_pinctrl *pctl;
+ struct resource *res;
+ void __iomem *mode, *mux, *pad;
+ unsigned i;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mode");
+ mode = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mode))
+ return PTR_ERR(mode);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mux");
+ mux = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mux))
+ return PTR_ERR(mux);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pad");
+ pad = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pad))
+ return PTR_ERR(pad);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ spin_lock_init(&pctl->lock);
+
+ pctl->mode = mode;
+
+ for (i = 0; i < 3; i++)
+ pctl->mux[i] = mux + (i * 4);
+
+ for (i = 0; i < 6; i++)
+ pctl->pad[i] = pad + (i * 4);
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &bcm6318_pctl_ops;
+ pctl->desc.pmxops = &bcm6318_pmx_ops;
+
+ pctl->desc.npins = ARRAY_SIZE(bcm6318_pins);
+ pctl->desc.pins = bcm6318_pins;
+
+ platform_set_drvdata(pdev, pctl);
+
+ pctl->pctldev = bcm63xx_pinctrl_register(pdev, &pctl->desc, pctl,
+ pctl->gpio, BCM6318_NGPIO);
+ if (IS_ERR(pctl->pctldev))
+ return PTR_ERR(pctl->pctldev);
+
+ return 0;
+}
+
+static const struct of_device_id bcm6318_pinctrl_match[] = {
+ { .compatible = "brcm,bcm6318-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm6318_pinctrl_driver = {
+ .probe = bcm6318_pinctrl_probe,
+ .driver = {
+ .name = "bcm6318-pinctrl",
+ .of_match_table = bcm6318_pinctrl_match,
+ },
+};
+
+builtin_platform_driver(bcm6318_pinctrl_driver);

View File

@ -0,0 +1,10 @@
define Profile/Default
NAME:=Default Profile
PRIORITY:=1
endef
define Profile/Default/Description
Default package set compatible with most boards.
endef
$(eval $(call Profile,Default))