2014-10-09 22:44:44

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 0/7] Add initial support for Broadcom Cygnus SoC

This patchset contains initial support for Broadcom's Cygnus SoC based on our
iProc architecture. Initial support is minimal and includes just the mach
platform code, clock driver, and a basic device tree configuration. Peripheral
drivers will be submitted soon, as will device tree configurations for other
Cygnus board variants.

Changes from v3:
- restart functionality removed. Will be added in a different patchset
in drivers/power
- removed NEON init sequence. Will be moved to bootloader
- cleaned up Kconfigs for ARCH_BCM_CYGNUS by removing unnecessary selects
- consolidated ARCH_BCM_IPROC with select from ARCH_BCM_CYGNUS and
ARCH_BCM5301X
- removed bcm911360_entphn binding
- added documentation for SoCs currently supported in Cygnus family


Changes from v2:
- rebased to 3.17 kernel

Changes from v1:
- Address code review comments as per previous responses.
- Copyright headers updated to remove Broadcom URL.
- mach platform code still contains hard coded addresses. These address are
the same for all Cygnus variants. Could you please provide guidance on where
they should go if you would still like them changed. There does not seem to
be a reason to change them to device tree as they do not change.


Jonathan Richardson (5):
ARM: cygnus: Initial support for Broadcom Cygnus SoC
clk: Clock driver support for Broadcom Cygnus SoC
dt-bindings: Document Broadcom Cygnus SoC and clock driver
ARM: cygnus defconfig : Initial defconfig for Broadcom Cygnus SoC
ARM: dts: Enable Broadcom Cygnus SoC

Scott Branden (2):
MAINTAINERS: Entry for Cygnus/iproc arm architecture and clock
drivers
ARM: multi_v7_defconfig: Enable ARCH_BCM_CYGNUS config

.../devicetree/bindings/arm/bcm/cygnus.txt | 31 +
.../devicetree/bindings/clock/clk-cygnus.txt | 121 ++
.../devicetree/bindings/clock/clk-iproc.txt | 48 +
MAINTAINERS | 17 +-
arch/arm/Kconfig.debug | 2 +-
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/bcm-cygnus.dtsi | 349 ++++++
arch/arm/boot/dts/bcm911360_entphn.dts | 22 +
arch/arm/configs/bcm_cygnus_defconfig | 221 ++++
arch/arm/configs/multi_v7_defconfig | 1 +
arch/arm/mach-bcm/Kconfig | 68 +-
arch/arm/mach-bcm/Makefile | 3 +
arch/arm/mach-bcm/bcm_cygnus.c | 26 +
drivers/clk/Makefile | 1 +
drivers/clk/bcm/Makefile | 2 +
drivers/clk/bcm/clk-cygnus.c | 1186 ++++++++++++++++++++
drivers/clk/bcm/clk-iproc.c | 451 ++++++++
17 files changed, 2527 insertions(+), 23 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/bcm/cygnus.txt
create mode 100644 Documentation/devicetree/bindings/clock/clk-cygnus.txt
create mode 100644 Documentation/devicetree/bindings/clock/clk-iproc.txt
create mode 100644 arch/arm/boot/dts/bcm-cygnus.dtsi
create mode 100644 arch/arm/boot/dts/bcm911360_entphn.dts
create mode 100644 arch/arm/configs/bcm_cygnus_defconfig
create mode 100644 arch/arm/mach-bcm/bcm_cygnus.c
create mode 100644 drivers/clk/bcm/clk-cygnus.c
create mode 100644 drivers/clk/bcm/clk-iproc.c

--
1.7.9.5


2014-10-09 22:44:54

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 1/7] ARM: cygnus: Initial support for Broadcom Cygnus SoC

From: Jonathan Richardson <[email protected]>

Adds initial support for the Cygnus SoC based on Broadcom’s iProc series.
Move ARCH_BCM_5301x under the ARCH_BCM_IPROC architecture.

Reviewed-by: Ray Jui <[email protected]>
Reviewed-by: Desmond Liu <[email protected]>
Reviewed-by: JD (Jiandong) Zheng <[email protected]>
Tested-by: Jonathan Richardson <[email protected]>
Signed-off-by: Scott Branden <[email protected]>
---
arch/arm/Kconfig.debug | 2 +-
arch/arm/mach-bcm/Kconfig | 68 +++++++++++++++++++++++++++-------------
arch/arm/mach-bcm/Makefile | 3 ++
arch/arm/mach-bcm/bcm_cygnus.c | 26 +++++++++++++++
4 files changed, 77 insertions(+), 22 deletions(-)
create mode 100644 arch/arm/mach-bcm/bcm_cygnus.c

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b11ad54..85363de 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1051,7 +1051,7 @@ config DEBUG_UART_PL01X

# Compatibility options for 8250
config DEBUG_UART_8250
- def_bool ARCH_DOVE || ARCH_EBSA110 || \
+ def_bool ARCH_BCM_IPROC || ARCH_DOVE || ARCH_EBSA110 || \
(FOOTBRIDGE && !DEBUG_DC21285_PORT) || \
ARCH_GEMINI || ARCH_IOP13XX || ARCH_IOP32X || \
ARCH_IOP33X || ARCH_IXP4XX || \
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index fc93800..b2b6752 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -5,6 +5,53 @@ menuconfig ARCH_BCM

if ARCH_BCM

+menu "iProc SoC based Machine types"
+ config ARCH_BCM_IPROC
+ bool "Broadcom ARMv7 iProc boards" if ARCH_MULTI_V7
+ depends on ARCH_BCM_CYGNUS || ARCH_BCM_5301X
+ select ARM_GIC
+ select CACHE_L2X0
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ select ARM_GLOBAL_TIMER
+
+ select CLKSRC_MMIO
+ select ARCH_REQUIRE_GPIOLIB
+ select ARM_AMBA
+ select PINCTRL
+ help
+ This enables support for systems based on Broadcom IPROC architected SoCs.
+ The IPROC complex contains one or more ARM CPUs along with common
+ core periperals. Application specific SoCs are created by adding a
+ uArchitecture containing peripherals outside of the IPROC complex.
+ Currently supported SoCs are Cygnus.
+
+ config ARCH_BCM_CYGNUS
+ bool "Broadcom Cygnus Support" if ARCH_MULTI_V7
+ select ARCH_BCM_IPROC
+ help
+ Enable support for the Cygnus family,
+ which includes the following variants:
+ BCM11300, BCM11320, BCM11350, BCM11360,
+ BCM58300, BCM58302, BCM58303, BCM58305.
+
+ config ARCH_BCM_5301X
+ bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
+ select ARCH_BCM_IPROC
+ help
+ Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
+
+ This is a network SoC line mostly used in home routers and
+ wifi access points, it's internal name is Northstar.
+ This inclused the following SoC: BCM53010, BCM53011, BCM53012,
+ BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707,
+ BCM4708 and BCM4709.
+
+ Do not confuse this with the BCM4760 which is a totally
+ different SoC or with the older BCM47XX and BCM53XX based
+ network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
+endmenu
+
config ARCH_BCM_MOBILE
bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7
select ARCH_REQUIRE_GPIOLIB
@@ -78,27 +125,6 @@ config ARCH_BCM2835
This enables support for the Broadcom BCM2835 SoC. This SoC is
used in the Raspberry Pi and Roku 2 devices.

-config ARCH_BCM_5301X
- bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
- select ARM_GIC
- select CACHE_L2X0
- select HAVE_ARM_SCU if SMP
- select HAVE_ARM_TWD if SMP
- select ARM_GLOBAL_TIMER
- select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
- help
- Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
-
- This is a network SoC line mostly used in home routers and
- wifi access points, it's internal name is Northstar.
- This inclused the following SoC: BCM53010, BCM53011, BCM53012,
- BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707,
- BCM4708 and BCM4709.
-
- Do not confuse this with the BCM4760 which is a totally
- different SoC or with the older BCM47XX and BCM53XX based
- network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
-
config ARCH_BRCMSTB
bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
depends on MMU
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index b19a396..46e092a 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -10,6 +10,9 @@
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

+# Cygnus
+obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o
+
# BCM281XX
obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o

diff --git a/arch/arm/mach-bcm/bcm_cygnus.c b/arch/arm/mach-bcm/bcm_cygnus.c
new file mode 100644
index 0000000..41b4933
--- /dev/null
+++ b/arch/arm/mach-bcm/bcm_cygnus.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Broadcom Corporation. All rights reserved.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/mach/arch.h>
+
+static const char const *bcm_cygnus_dt_compat[] = {
+ "brcm,cygnus",
+ NULL,
+};
+
+DT_MACHINE_START(BCM_CYGNUS_DT, "Broadcom Cygnus SoC")
+ .l2c_aux_val = 0,
+ .l2c_aux_mask = ~0,
+ .dt_compat = bcm_cygnus_dt_compat,
+MACHINE_END
--
1.7.9.5

2014-10-09 22:45:01

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 4/7] ARM: cygnus defconfig : Initial defconfig for Broadcom Cygnus SoC

From: Jonathan Richardson <[email protected]>

This defconfig is utilized so a customer or developer can understand
what kernel drivers are utilized by the Cygnus SoC. It also enables
debug configs which should be disabled if optimal performance is
desired.

Tested-by: Jonathan Richardson <[email protected]>
Reviewed-by: JD (Jiandong) Zheng <[email protected]>
Signed-off-by: Scott Branden <[email protected]>
---
arch/arm/configs/bcm_cygnus_defconfig | 221 +++++++++++++++++++++++++++++++++
1 file changed, 221 insertions(+)
create mode 100644 arch/arm/configs/bcm_cygnus_defconfig

diff --git a/arch/arm/configs/bcm_cygnus_defconfig b/arch/arm/configs/bcm_cygnus_defconfig
new file mode 100644
index 0000000..cf4c107
--- /dev/null
+++ b/arch/arm/configs/bcm_cygnus_defconfig
@@ -0,0 +1,221 @@
+CONFIG_KERNEL_XZ=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=19
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM_CYGNUS=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+# CONFIG_COMPACTION is not set
+# CONFIG_ATAGS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_HTCP is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_NETFILTER=y
+# CONFIG_BRIDGE_NETFILTER is not set
+CONFIG_NF_CONNTRACK=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_EUI64=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE=y
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_UBI=y
+# CONFIG_BLK_DEV is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_BROADCOM_PHY=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_SMBUS=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_PWM=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=110
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_SG=y
+CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_DEBUG_CREDENTIALS=y
+CONFIG_PROVE_RCU=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_UART_8250=y
+CONFIG_DEBUG_UART_PHYS=0x18023000
+CONFIG_DEBUG_UART_VIRT=0xf1023000
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
--
1.7.9.5

2014-10-09 22:45:18

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 2/7] clk: Clock driver support for Broadcom Cygnus SoC

From: Jonathan Richardson <[email protected]>

The iProc clock driver controls PLLs common across iProc chips. The
cygnus driver controls cygnus specific features and variations.

Reviewed-by: Ray Jui <[email protected]>
Tested-by: Jonathan Richardson <[email protected]>
Reviewed-by: JD (Jiandong) Zheng <[email protected]>
Signed-off-by: Scott Branden <[email protected]>
---
drivers/clk/Makefile | 1 +
drivers/clk/bcm/Makefile | 2 +
drivers/clk/bcm/clk-cygnus.c | 1186 ++++++++++++++++++++++++++++++++++++++++++
drivers/clk/bcm/clk-iproc.c | 451 ++++++++++++++++
4 files changed, 1640 insertions(+)
create mode 100644 drivers/clk/bcm/clk-cygnus.c
create mode 100644 drivers/clk/bcm/clk-iproc.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f537a0b..8ac0a31 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
+obj-$(CONFIG_ARCH_BCM_IPROC) += bcm/
obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 6297d05..f803919 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -2,3 +2,5 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
+obj-$(CONFIG_ARCH_BCM_IPROC) += clk-iproc.o
+obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
diff --git a/drivers/clk/bcm/clk-cygnus.c b/drivers/clk/bcm/clk-cygnus.c
new file mode 100644
index 0000000..2a4f976
--- /dev/null
+++ b/drivers/clk/bcm/clk-cygnus.c
@@ -0,0 +1,1186 @@
+/*
+ * Copyright 2014 Broadcom Corporation. All rights reserved.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+
+/*
+ * The CRU contains two similar PLLs: LCPLL and GENPLL,
+ * both with several output channels divided from the PLL
+ * output.
+ */
+
+#define CRU_LCPLL_CONTROL1_OFFSET 0x04
+#define CRU_LCPLL_STATUS_OFFSET 0x18
+
+#define LCPLL0_PDIV_SHIFT 26
+#define LCPLL0_PDIV_MASK 0xf
+#define LCPLL0_NDIV_SHIFT 16
+#define LCPLL0_NDIV_MASK 0x3ff
+#define LCPLL_ENABLEB_CH_SHIFT 7
+#define LCPLL_ENABLEB_CH_MASK 0x3f
+#define LCPLL_MDIV_MASK 0xff
+#define LCPLL_STATUS_LOCK_SHIFT 12
+
+#define LCPLL0_CONTROL0_OFFSET 0x00
+#define LCPLL0_CONTROL1_OFFSET 0x04
+#define LCPLL0_CONTROL2_OFFSET 0x08
+#define LCPLL0_CONTROL3_OFFSET 0x0c
+
+#define GENPLL_CONTROL0_OFFSET 0x00
+#define GENPLL_CONTROL1_OFFSET 0x04
+#define GENPLL_CONTROL2_OFFSET 0x08
+#define GENPLL_CONTROL3_OFFSET 0x0c
+#define GENPLL_CONTROL4_OFFSET 0x10
+#define GENPLL_CONTROL5_OFFSET 0x14
+#define GENPLL_CONTROL6_OFFSET 0x18
+#define GENPLL_CONTROL7_OFFSET 0x1c
+#define GENPLL_CONTROL8_OFFSET 0x20
+#define GENPLL_CONTROL9_OFFSET 0x24
+#define GENPLL_STATUS_OFFSET 0x28
+
+#define GENPLL_ENABLEB_CH_SHIFT 0x6
+#define GENPLL_ENABLEB_CH_MASK 0x3f
+
+#define GENPLL_STATUS_LOCK_SHIFT 12
+#define GENPLL_STATUS_LOCK_MASK 1
+#define GENPLL_CONTROL4_NDIV_INT_SHIFT 20
+#define GENPLL_CONTROL4_NDIV_INT_MASK 0x3FF
+#define GENPLL_CONTROL4_NDIV_FRAC_SHIFT 0
+#define GENPLL_CONTROL4_NDIV_FRAC_MASK 0xFFFFF
+#define GENPLL_CONTROL5_PDIV_SHIFT 0
+#define GENPLL_CONTROL5_PDIV_MASK 0xF
+#define GENPLL_MDIV_MASK 0xff
+
+#define MIPI_DSI_GENPLL_ENABLEB_CH_SHIFT 12
+#define NDIV_FRAC_DIVISOR 0x100000
+
+#define ASIU_MIPI_GENPLL_PWRON_SHIFT 20
+#define ASIU_MIPI_GENPLL_PWRON_PLL_SHIFT 19
+#define ASIU_MIPI_GENPLL_PWRON_BG_SHIFT 18
+#define ASIU_MIPI_GENPLL_PWRON_LDO_SHIFT 17
+#define ASIU_MIPI_GENPLL_ISO_IN_SHIFT 16
+#define ASIU_AUDIO_GENPLL_PWRON_PLL_SHIFT 11
+#define ASIU_AUDIO_GENPLL_PWRON_BG_SHIFT 10
+#define ASIU_AUDIO_GENPLL_PWRON_LDO_SHIFT 9
+#define ASIU_AUDIO_GENPLL_ISO_IN 8
+
+#define CLK_RATE_NO_DIV -1
+
+/*
+ * The clock framework may call recalc even if a clock is is unused, and
+ * therefore before being prepared/enabled. State checking is done for the
+ * MIPI PLL to prevent reading from a MIPI DSI register before the PLL is
+ * powered up because it will cause corruption (imprecise external aborts)
+ * sometimer later on.
+ */
+enum clock_state {
+ CLK_ENABLED,
+ CLK_PREPARED,
+ CLK_DISABLED
+};
+
+struct cygnus_clk {
+ struct clk_hw hw;
+ void __iomem *regs_base;
+ void __iomem *pll_ctrl_reg;
+ void __iomem *clock_gate_ctrl_reg;
+ int chan;
+ int internal_div;
+ unsigned long rate;
+ enum clock_state state;
+};
+
+#define to_cygnus_clk(p) container_of(p, struct cygnus_clk, hw)
+
+/* Identifies LCPLL clock channels. */
+enum cygnus_lcpll_clk_chan {
+ LCPLL_CH0_PCIE_PHY_REF_CLK = 0,
+ LCPLL_CH1_DDR_CLK = 1,
+ LCPLL_CH2_SDIO_CLK = 2,
+ LCPLL_CH3_USB_PHY_REF_CLK = 3,
+ LCPLL_CH4_ASIU_SMART_CARD_CLK = 4,
+ LCPLL_CH5 = 5
+};
+
+/* Identifies GENPLL clock channels. */
+enum cygnus_genpll_clk_chan {
+ GENPLL_CH0_AXI21_CLK = 0,
+ GENPLL_CH1_25MHZ_CLK = 1,
+ GENPLL_CH2_SYS_CLK = 2,
+ GENPLL_CH3_ETHERNET_CLK = 3,
+ GENPLL_CH4_ASIU_AUDIO_CLK = 4,
+ GENPLL_CH5_ASIU_CAN_CLK = 5
+};
+
+/*
+ * Channels for Oscillator dervived clocks are values used to determine
+ * which clock to enable/disable from the top clock gating control.
+ */
+enum cygnus_osc_derived_clk_chan {
+ OSC_DERIVED_CH0_KEYPAD_CLK = 0,
+ OSC_DERIVED_CH1_ADC_CLK = 1,
+ OSC_DERIVED_CH2_PWM_CLK = 2,
+};
+
+enum cygnus_mipi_pll_clk_chan {
+ MIPI_PLL_CH0_MIPI_PHY_CLK = 0,
+ MIPI_PLL_CH1_LCD_CLK = 1,
+ MIPI_PLL_CH2_3D_GRAPHICS_CLK = 2,
+};
+
+/* Order of registers defined in DT. */
+enum cygnus_clk_dt_regs {
+ CYGNUS_CLK_BASE_REG = 0,
+ CYGNUS_CLK_GATE_CTRL_REG,
+ CYGNUS_PLL_CTRL_REG
+};
+
+enum cygnus_top_clk_gating_ctrl_offsets {
+ GFX_CLK_GATE_EN = 0,
+ AUD_CLK_GATE_EN,
+ CAM_CLK_GATE_EN,
+ MIPI_DSI_CLK_GATE_EN,
+ LCD_CLK_GATE_EN,
+ D1W_CLK_GATE_EN,
+ CAN_CLK_GATE_EN,
+ KEYPAD_CLK_GATE_EN,
+ SMARTCARD_CLK_GATE_EN,
+ ADC_CLK_GATE_EN,
+ CRYPTO_CLK_GATE_EN
+};
+
+/*
+ * Enable clocks controlled through the top clock gating control.
+ *
+ * @param enable true = enable clock, false = disable clock
+ */
+static void cygnus_clkgate_enable_disable(void __iomem *clkgate_reg,
+ enum cygnus_top_clk_gating_ctrl_offsets offset, bool enable)
+{
+ u32 val = readl(clkgate_reg);
+
+ /* Enable or disable the clock. */
+ if (enable)
+ val |= 1 << offset;
+ else
+ val &= ~(1 << offset);
+
+ writel(val, clkgate_reg);
+}
+
+/*
+ * Powers on/off the MIPI GENPLL using CRMU_PLL_AON_CTRL register.
+ *
+ * @param power_on true to power on PLL, false to power off
+ */
+static void cygnus_mipi_genpll_power_on_off(void __iomem *pll_ctrl_reg,
+ bool power_on)
+{
+ u32 val;
+ u32 pll_ldo_on = ((1 << ASIU_MIPI_GENPLL_PWRON_SHIFT) |
+ (1 << ASIU_MIPI_GENPLL_PWRON_PLL_SHIFT) |
+ (1 << ASIU_MIPI_GENPLL_PWRON_BG_SHIFT) |
+ (1 << ASIU_MIPI_GENPLL_PWRON_LDO_SHIFT));
+
+ val = readl(pll_ctrl_reg);
+
+ /*
+ * Set PLL on/off. Set input isolation mode to 1 when disabled, 0 when
+ * enabled.
+ */
+ if (power_on) {
+ val |= pll_ldo_on;
+ val &= ~(1 << ASIU_MIPI_GENPLL_ISO_IN_SHIFT);
+ } else {
+ val &= ~pll_ldo_on;
+ val |= 1 << ASIU_MIPI_GENPLL_ISO_IN_SHIFT;
+ }
+
+ writel(val, pll_ctrl_reg);
+}
+
+/*
+ * Powers on/off the audio PLL using CRMU_PLL_AON_CTRL register.
+ *
+ * @param power_on true to power on PLL, false to power off
+ */
+static void cygnus_audio_genpll_power_on_off(void __iomem *pll_ctrl_reg,
+ bool power_on)
+{
+ u32 val;
+ u32 pll_ldo_on = ((1 << ASIU_AUDIO_GENPLL_PWRON_PLL_SHIFT) |
+ (1 << ASIU_AUDIO_GENPLL_PWRON_BG_SHIFT) |
+ (1 << ASIU_AUDIO_GENPLL_PWRON_LDO_SHIFT));
+
+ val = readl(pll_ctrl_reg);
+
+ /*
+ * Set PLL on/off. Set input isolation mode to 1 when disabled, 0 when
+ * enabled.
+ */
+ if (power_on) {
+ val |= pll_ldo_on;
+ val &= ~(1 << ASIU_AUDIO_GENPLL_ISO_IN);
+ } else {
+ val &= ~pll_ldo_on;
+ val |= 1 << ASIU_AUDIO_GENPLL_ISO_IN;
+ }
+
+ writel(val, pll_ctrl_reg);
+}
+
+/*
+ * Get PLL running status and calculate output frequency
+ */
+static unsigned long cygnus_lcpll_status(struct cygnus_clk *clk,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ unsigned pdiv, ndiv;
+
+ /* read status register */
+ reg = readl(clk->regs_base + CRU_LCPLL_STATUS_OFFSET);
+
+ /* Must be locked for proper PLL operation. */
+ if ((reg & (1 << LCPLL_STATUS_LOCK_SHIFT)) == 0) {
+ clk->rate = 0;
+ return -EIO;
+ }
+
+ /*
+ * Calculate PLL frequency based on LCPLL divider values:
+ * pdiv = LCPLL pre-divider ratio
+ * ndiv = LCPLL feedback divider
+ *
+ * The frequency is calculated by:
+ * ndiv * (parent clock rate / pdiv)
+ */
+
+ reg = readl(clk->regs_base + CRU_LCPLL_CONTROL1_OFFSET);
+
+ /* feedback divider integer and fraction parts */
+ pdiv = (reg >> LCPLL0_PDIV_SHIFT) & LCPLL0_PDIV_MASK;
+ ndiv = (reg >> LCPLL0_NDIV_SHIFT) & LCPLL0_NDIV_MASK;
+
+ if (pdiv == 0)
+ return -EIO;
+
+ clk->rate = ndiv * (parent_rate / pdiv);
+
+ return clk->rate;
+}
+
+static unsigned long cygnus_lcpll_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ return cygnus_lcpll_status(bcm_clk, parent_rate);
+}
+
+static const struct clk_ops cygnus_lcpll_ops = {
+ .recalc_rate = cygnus_lcpll_clk_recalc_rate,
+};
+
+static int cygnus_lcpll_chan_status(struct cygnus_clk *clk,
+ unsigned long parent_rate)
+{
+ void * __iomem base;
+ u32 reg;
+ unsigned enable;
+ unsigned mdiv;
+ int offset = 0;
+ int shift = 0;
+
+ /* Register address is only stored in PLL structure */
+ base = clk->regs_base;
+ BUG_ON(base == NULL);
+
+ /* enable bit is in enableb_ch[] inversed */
+ enable = ((readl(base + LCPLL0_CONTROL0_OFFSET) >>
+ LCPLL_ENABLEB_CH_SHIFT) & LCPLL_ENABLEB_CH_MASK) ^
+ LCPLL_ENABLEB_CH_MASK;
+
+ if ((enable & (1 << clk->chan)) == 0) {
+ clk->rate = 0;
+ return -EIO;
+ }
+
+ /* MDIV for the 6 channels is spread over two registers. */
+ switch (clk->chan) {
+ case LCPLL_CH0_PCIE_PHY_REF_CLK:
+ offset = LCPLL0_CONTROL2_OFFSET; shift = 0;
+ break;
+
+ case LCPLL_CH1_DDR_CLK:
+ offset = LCPLL0_CONTROL2_OFFSET; shift = 10;
+ break;
+
+ case LCPLL_CH2_SDIO_CLK:
+ offset = LCPLL0_CONTROL2_OFFSET; shift = 20;
+ break;
+
+ case LCPLL_CH3_USB_PHY_REF_CLK:
+ offset = LCPLL0_CONTROL3_OFFSET; shift = 0;
+ break;
+
+ case LCPLL_CH4_ASIU_SMART_CARD_CLK:
+ offset = LCPLL0_CONTROL3_OFFSET; shift = 10;
+ break;
+
+ case LCPLL_CH5:
+ offset = LCPLL0_CONTROL3_OFFSET; shift = 20;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Read MDIV for requested channel. */
+ reg = readl(base + offset);
+ mdiv = (reg >> shift) & LCPLL_MDIV_MASK;
+
+ /* when divisor is 0, it behaves as max+1 */
+ if (mdiv == 0)
+ mdiv = 256;
+
+ clk->rate = parent_rate / mdiv;
+
+ pr_debug("LCPLL[%d] mdiv=%u Prate=%lu rate=%lu\n",
+ clk->chan, mdiv, parent_rate, clk->rate);
+
+ return clk->rate;
+}
+
+static unsigned long cygnus_lcpll_chan_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ return cygnus_lcpll_chan_status(bcm_clk, parent_rate);
+}
+
+static const struct clk_ops cygnus_lcpll_chan_ops = {
+ .recalc_rate = cygnus_lcpll_chan_recalc_rate,
+};
+
+/*
+ * Get PLL running status and calculate output frequency
+ */
+static unsigned long cygnus_genpll_status(struct cygnus_clk *clk,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ unsigned pdiv;
+ unsigned ndiv_int;
+ unsigned ndiv_frac;
+
+ /* Read PLL status register. It must be locked. */
+ reg = readl(clk->regs_base + GENPLL_STATUS_OFFSET);
+ if ((reg & (1 << GENPLL_STATUS_LOCK_SHIFT)) == 0) {
+ clk->rate = 0;
+ return -EIO;
+ }
+
+ /* Calculate PLL frequency */
+
+ /* Get PLL feedback divider values. */
+ reg = readl(clk->regs_base + GENPLL_CONTROL4_OFFSET);
+
+ /* feedback divider integer and fraction parts */
+ ndiv_int = reg >> GENPLL_CONTROL4_NDIV_INT_SHIFT;
+ ndiv_frac = reg & GENPLL_CONTROL4_NDIV_INT_MASK;
+ ndiv_int += ndiv_frac / NDIV_FRAC_DIVISOR;
+
+ /* Get pdiv - first 4 bits. */
+ reg = readl(clk->regs_base + GENPLL_CONTROL5_OFFSET);
+ pdiv = reg & GENPLL_CONTROL5_PDIV_MASK;
+ if (pdiv == 0)
+ return -EIO;
+
+ clk->rate = (parent_rate / pdiv) * ndiv_int;
+
+ return clk->rate;
+}
+
+static unsigned long cygnus_genpll_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ return cygnus_genpll_status(bcm_clk, parent_rate);
+}
+
+static const struct clk_ops cygnus_genpll_ops = {
+ .recalc_rate = cygnus_genpll_recalc_rate,
+};
+
+/*
+ * Calculates clock rate of the GENPLL channel requested. The clock rate is
+ * calculated as: the configured clock rate
+ * Parent clock rate / mdiv
+ */
+static unsigned long cygnus_genpll_chan_get_rate(struct cygnus_clk *clk,
+ unsigned long parent_rate, int enableb_ch_shift)
+{
+ u32 reg;
+ unsigned enable;
+ unsigned mdiv;
+ unsigned offset = 0;
+ unsigned shift = 0;
+
+ /*
+ * Read ENABLEB_CH to determine which channels are enabled. The enable
+ * bits are inversed: 0 = channel enabled, 1 = channel disabled.
+ */
+ reg = readl(clk->regs_base + GENPLL_CONTROL1_OFFSET);
+ enable = ((reg >> enableb_ch_shift) &
+ GENPLL_ENABLEB_CH_MASK) ^ GENPLL_ENABLEB_CH_MASK;
+
+ /* If channel is disabled the rate is 0. */
+ if ((enable & (1 << clk->chan)) == 0) {
+ clk->rate = 0;
+ return -EIO;
+ }
+
+ /* MDIV for the 6 channels is spread over two registers. */
+ switch (clk->chan) {
+ case 0:
+ offset = GENPLL_CONTROL8_OFFSET; shift = 0;
+ break;
+
+ case 1:
+ offset = GENPLL_CONTROL8_OFFSET; shift = 10;
+ break;
+
+ case 2:
+ offset = GENPLL_CONTROL8_OFFSET; shift = 20;
+ break;
+
+ case 3:
+ offset = GENPLL_CONTROL9_OFFSET; shift = 0;
+ break;
+
+ case 4:
+ offset = GENPLL_CONTROL9_OFFSET; shift = 10;
+ break;
+
+ case 5:
+ offset = GENPLL_CONTROL9_OFFSET; shift = 20;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Read MDIV (post divider ratio) for requested channel. */
+ reg = readl(clk->regs_base + offset);
+ mdiv = (reg >> shift) & GENPLL_MDIV_MASK;
+
+ /* When divisor is 0, it behaves as max+1. */
+ if (mdiv == 0)
+ mdiv = 256;
+
+ clk->rate = parent_rate / mdiv;
+
+ pr_debug("GENPLL[%d] mdiv=%u parent rate=%lu rate=%lu\n",
+ clk->chan, mdiv, parent_rate, clk->rate);
+
+ return clk->rate;
+}
+
+/*
+ * Powers on the audio PLL for the audio channel from the PLL. No other
+ * GENPLL channels require powering on.
+ */
+static int cygnus_genpll_chan_prepare(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+ struct clk *parent_clk = clk_get_parent(hwclk->clk);
+ struct cygnus_clk *cyg_parent_clk =
+ to_cygnus_clk(__clk_get_hw(parent_clk));
+
+ if (WARN_ON(!cyg_parent_clk->pll_ctrl_reg))
+ return -EIO;
+
+ if (clk->chan == GENPLL_CH4_ASIU_AUDIO_CLK) {
+ pr_debug("GENPLL[%d]: Powering on audio PLL/LDO\n", clk->chan);
+ cygnus_audio_genpll_power_on_off(
+ cyg_parent_clk->pll_ctrl_reg, true);
+ }
+
+ return 0;
+}
+
+/*
+ * Powers off the audio PLL for the audio channel from the PLL. No other
+ * GENPLL channels require powering off.
+ */
+static void cygnus_genpll_chan_unprepare(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+ struct clk *parent_clk = clk_get_parent(hwclk->clk);
+ struct cygnus_clk *cyg_parent_clk =
+ to_cygnus_clk(__clk_get_hw(parent_clk));
+
+ if (WARN_ON(!cyg_parent_clk->pll_ctrl_reg))
+ return;
+
+ if (clk->chan == GENPLL_CH4_ASIU_AUDIO_CLK) {
+ pr_debug("GENPLL[%d]: Powering down audio PLL and LDO\n",
+ clk->chan);
+ cygnus_audio_genpll_power_on_off(cyg_parent_clk->pll_ctrl_reg,
+ false);
+ }
+}
+
+static unsigned long cygnus_genpll_chan_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ return cygnus_genpll_chan_get_rate(bcm_clk, parent_rate,
+ GENPLL_ENABLEB_CH_SHIFT);
+}
+
+/*
+ * Enables GENPLL channels. The only PLL channel that is controlled through
+ * the top clock gating control is the audio clock which requires enabling.
+ *
+ * Individual channels aren't enabled/disabled on the PLL because they are
+ * enabled by default and drivers don't always refer to them, meaning the
+ * clock framework would disable them. This can be added later when power
+ * saving is a concern.
+ */
+static int cygnus_genpll_chan_enable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+ struct clk *parent_clk = clk_get_parent(hwclk->clk);
+ struct cygnus_clk *cyg_parent_clk =
+ to_cygnus_clk(__clk_get_hw(parent_clk));
+ int parent_rate;
+
+ if (WARN_ON(!cyg_parent_clk->clock_gate_ctrl_reg))
+ return -EIO;
+
+ pr_debug("Enable GENPLL chan %d\n", clk->chan);
+
+ if (clk->chan == GENPLL_CH4_ASIU_AUDIO_CLK) {
+ cygnus_clkgate_enable_disable(
+ cyg_parent_clk->clock_gate_ctrl_reg,
+ AUD_CLK_GATE_EN, true);
+
+ /* Ensure parent's clock rate is calculated. */
+ parent_rate = clk_get_rate(parent_clk);
+ if (WARN_ON(!parent_rate))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void cygnus_genpll_chan_disable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+ struct clk *parent_clk = clk_get_parent(hwclk->clk);
+ struct cygnus_clk *cyg_parent_clk =
+ to_cygnus_clk(__clk_get_hw(parent_clk));
+
+ if (WARN_ON(!cyg_parent_clk->clock_gate_ctrl_reg))
+ return;
+
+ pr_debug("GENPLL: disable chan %d\n", clk->chan);
+
+ /* Enable audio clock. */
+ if (clk->chan == GENPLL_CH4_ASIU_AUDIO_CLK)
+ cygnus_clkgate_enable_disable(
+ cyg_parent_clk->clock_gate_ctrl_reg,
+ AUD_CLK_GATE_EN, false);
+}
+
+static const struct clk_ops cygnus_genpll_chan_ops = {
+ .prepare = cygnus_genpll_chan_prepare,
+ .unprepare = cygnus_genpll_chan_unprepare,
+ .enable = cygnus_genpll_chan_enable,
+ .disable = cygnus_genpll_chan_disable,
+ .recalc_rate = cygnus_genpll_chan_recalc_rate,
+};
+
+static __init struct clk *cygnus_clock_init(struct device_node *node,
+ const struct clk_ops *ops)
+{
+ u32 channel = 0;
+ struct clk *clk;
+ struct cygnus_clk *cygnus_clk;
+ const char *clk_name = node->name;
+ const char *parent_name;
+ struct clk_init_data init;
+ int rc;
+
+ pr_debug("Clock name %s\n", node->name);
+
+ cygnus_clk = kzalloc(sizeof(*cygnus_clk), GFP_KERNEL);
+ if (WARN_ON(!cygnus_clk))
+ return NULL;
+
+ cygnus_clk->state = CLK_DISABLED;
+
+ /* Read base address from device tree and map to virtual address. */
+ cygnus_clk->regs_base = of_iomap(node, CYGNUS_CLK_BASE_REG);
+ if (WARN_ON(!cygnus_clk->regs_base))
+ goto err_alloc;
+
+ /* Read optional base addresses for PLL control and clock gating. */
+ cygnus_clk->clock_gate_ctrl_reg = of_iomap(node,
+ CYGNUS_CLK_GATE_CTRL_REG);
+ cygnus_clk->pll_ctrl_reg = of_iomap(node, CYGNUS_PLL_CTRL_REG);
+
+ of_property_read_u32(node, "channel", &channel);
+ cygnus_clk->chan = channel;
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ /*
+ * Internal divider is optional and used for PLL derived clocks with
+ * hardcoded dividers.
+ */
+ cygnus_clk->internal_div = CLK_RATE_NO_DIV;
+ of_property_read_u32(node, "div", &cygnus_clk->internal_div);
+
+ init.name = clk_name;
+ init.ops = ops;
+ init.flags = CLK_GET_RATE_NOCACHE;
+ parent_name = of_clk_get_parent_name(node, 0);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ cygnus_clk->hw.init = &init;
+
+ clk = clk_register(NULL, &cygnus_clk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto err_unmap;
+
+ rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ if (WARN_ON(IS_ERR_VALUE(rc)))
+ goto err_unregister;
+
+ rc = clk_register_clkdev(clk, clk_name, NULL);
+ if (WARN_ON(IS_ERR_VALUE(rc)))
+ goto err_provider;
+
+ return clk;
+
+err_provider:
+ of_clk_del_provider(node);
+
+err_unregister:
+ clk_unregister(clk);
+
+err_unmap:
+ iounmap(cygnus_clk->regs_base);
+ iounmap(cygnus_clk->clock_gate_ctrl_reg);
+ iounmap(cygnus_clk->pll_ctrl_reg);
+
+err_alloc:
+ kfree(cygnus_clk);
+
+ return NULL;
+}
+
+static void __init cygnus_lcpll_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_lcpll_ops);
+}
+CLK_OF_DECLARE(cygnus_lcpll, "brcm,cygnus-lcpll-clk", cygnus_lcpll_init);
+
+static void __init cygnus_genpll_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_genpll_ops);
+}
+CLK_OF_DECLARE(cygnus_genpll, "brcm,cygnus-genpll-clk", cygnus_genpll_init);
+
+static void __init cygnus_lcpll_ch_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_lcpll_chan_ops);
+}
+CLK_OF_DECLARE(cygnus_lcpll_ch, "brcm,cygnus-lcpll-ch", cygnus_lcpll_ch_init);
+
+static void __init cygnus_genpll_ch_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_genpll_chan_ops);
+}
+CLK_OF_DECLARE(cygnus_genpll_ch, "brcm,cygnus-genpll-ch",
+ cygnus_genpll_ch_init);
+
+/*
+ * Some clocks on Cygnus are derived from the oscillator directly without
+ * going through either the GENPLL or LCPLL. These clocks have specific
+ * registers for their dividers. The clocks included are: keypad, ADC, PWM.
+ */
+
+#define ASIU_CLK_DIV_ENABLE_SHIFT 31
+#define ASIU_CLK_DIV_ENABLE_MASK 0x1
+#define ASIU_CLK_DIV_HIGH_SHIFT 16
+#define ASIU_CLK_DIV_HIGH_MASK 0x3ff
+#define ASIU_CLK_DIV_LOW_SHIFT 0
+#define ASIU_CLK_DIV_LOW_MASK 0x3ff
+
+/*
+ * Calculate clock frequency for clocks derived from oscillator.
+ *
+ * @return The clock rate in Hz
+ */
+static int cygnus_osc_derived_clk_get_rate(struct cygnus_clk *clk,
+ unsigned long parent_rate)
+{
+ int reg_val;
+ int enabled;
+ int clk_div_high;
+ int clk_div_low;
+ unsigned long rate = 0;
+
+ reg_val = readl(clk->regs_base);
+
+ /* Ensure clock is enabled. */
+ enabled = (reg_val >> ASIU_CLK_DIV_ENABLE_SHIFT) &
+ ASIU_CLK_DIV_ENABLE_MASK;
+ if (!enabled)
+ return rate;
+
+ clk_div_high = (reg_val >> ASIU_CLK_DIV_HIGH_SHIFT) &
+ ASIU_CLK_DIV_HIGH_MASK;
+ clk_div_high += 1;
+
+ clk_div_low = (reg_val >> ASIU_CLK_DIV_LOW_SHIFT) &
+ ASIU_CLK_DIV_LOW_MASK;
+ clk_div_low += 1;
+
+ /*
+ * Rate calculated as:
+ * (oscillator rate) / ((clk high + 1) + (clk_low + 1))
+ */
+ rate = parent_rate / (clk_div_high + clk_div_low);
+
+ pr_debug("Osc derived clk: Prate=%lu div_high=%d div_low=%d rate=%lu\n",
+ parent_rate, clk_div_high, clk_div_low, rate);
+
+ return rate;
+}
+
+static unsigned long cygnus_osc_derived_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ return cygnus_osc_derived_clk_get_rate(bcm_clk, parent_rate);
+}
+
+/*
+ * Enables the top clock gating control for clocks that require it.
+ */
+static int cygnus_osc_derived_clk_enable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+ struct clk *parent_clk = clk_get_parent(hwclk->clk);
+ int parent_rate;
+ u32 val;
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return 0;
+
+ pr_debug("OSC derived clk enable chan %d\n", clk->chan);
+
+ /* Enable top clock gating control if necessary. */
+ if (clk->chan == OSC_DERIVED_CH0_KEYPAD_CLK)
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ KEYPAD_CLK_GATE_EN, true);
+ else if (clk->chan == OSC_DERIVED_CH1_ADC_CLK)
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ ADC_CLK_GATE_EN, true);
+
+ /* Set and enable divider if specified. */
+ if (clk->internal_div != CLK_RATE_NO_DIV) {
+ val = (1 << ASIU_CLK_DIV_ENABLE_SHIFT) |
+ ((clk->internal_div & ASIU_CLK_DIV_HIGH_MASK) <<
+ ASIU_CLK_DIV_HIGH_SHIFT) |
+ ((clk->internal_div & ASIU_CLK_DIV_LOW_MASK) <<
+ ASIU_CLK_DIV_LOW_SHIFT);
+ writel(val, clk->regs_base);
+ }
+
+ /* Ensure parent's clock rate is calculated. */
+ parent_rate = clk_get_rate(parent_clk);
+ if (WARN_ON(!parent_rate))
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * Disables top clock gating control for clocks that were enabled.
+ */
+static void cygnus_osc_derived_clk_disable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return;
+
+ pr_debug("OSC derived clk disable chan %d\n", clk->chan);
+
+ /* Disable top clock gating control if necessary. */
+ if (clk->chan == OSC_DERIVED_CH0_KEYPAD_CLK)
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ KEYPAD_CLK_GATE_EN, false);
+ else if (clk->chan == OSC_DERIVED_CH1_ADC_CLK)
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ ADC_CLK_GATE_EN, false);
+}
+
+static const struct clk_ops cygnus_osc_derived_clk_ops = {
+ .enable = cygnus_osc_derived_clk_enable,
+ .disable = cygnus_osc_derived_clk_disable,
+ .recalc_rate = cygnus_osc_derived_clk_recalc_rate,
+};
+
+static void __init cygnus_osc_derived_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_osc_derived_clk_ops);
+}
+
+CLK_OF_DECLARE(cygnus_osc_derived, "brcm,cygnus-osc-derived",
+ cygnus_osc_derived_init);
+
+/*
+ * Some clocks are derived from a PLL. The dividers are internal and can't
+ * be read from a register. If the parent clock rate changes then the derived
+ * clock rates scale accordingly.
+ */
+
+ /*
+ * Calculate clock frequency for clocks derived from oscillator.
+ * Rate calculated as: parent rate / internal divider
+ * The internal divider must be specified in DT.
+ *
+ * @return The clock rate in Hz.
+ */
+static unsigned long cygnus_pll_derived_clk_get_rate(struct cygnus_clk *clk,
+ unsigned long parent_rate)
+{
+ unsigned long rate = parent_rate / clk->internal_div;
+
+ pr_debug("PLL derived clk: Prate=%lu rate=%lu\n", parent_rate, rate);
+
+ return rate;
+}
+
+static unsigned long cygnus_pll_derived_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ return cygnus_pll_derived_clk_get_rate(bcm_clk, parent_rate);
+}
+
+static const struct clk_ops cygnus_pll_derived_clk_ops = {
+ .recalc_rate = cygnus_pll_derived_clk_recalc_rate,
+};
+
+static void __init cygnus_pll_derived_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_pll_derived_clk_ops);
+}
+
+CLK_OF_DECLARE(cygnus_pll_derived, "brcm,cygnus-pll-derived",
+ cygnus_pll_derived_init);
+
+/*
+ * MIPI DSI GENPLL
+ */
+
+/*
+ * Get PLL running status and calculate output frequency.
+ */
+static unsigned long cygnus_mipipll_get_rate(struct cygnus_clk *clk,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ u32 rate;
+ u32 pdiv;
+ u32 ndiv_int;
+ u32 ndiv_frac;
+ int pll_locked;
+
+ /* Read lock field from PLL status register. It must be unlocked. */
+ reg = readl(clk->regs_base + GENPLL_STATUS_OFFSET);
+
+ pll_locked = (reg >> GENPLL_STATUS_LOCK_SHIFT) &
+ GENPLL_STATUS_LOCK_MASK;
+ if (pll_locked) {
+ clk->rate = 0;
+ return -EIO;
+ }
+ /*
+ * Calculate PLL frequency:
+ * PLL freq = ((crystal clock / pdiv) * ndiv ) / mdiv
+ */
+
+ /* Get PLL feedback divider values. */
+ reg = readl(clk->regs_base + GENPLL_CONTROL4_OFFSET);
+
+ /* Feedback divider integer and fractional parts. */
+ ndiv_int = (reg >> GENPLL_CONTROL4_NDIV_INT_SHIFT) &
+ GENPLL_CONTROL4_NDIV_INT_MASK;
+ ndiv_frac = (reg >> GENPLL_CONTROL4_NDIV_FRAC_SHIFT) &
+ GENPLL_CONTROL4_NDIV_FRAC_MASK;
+ ndiv_int += ndiv_frac / NDIV_FRAC_DIVISOR;
+
+ /* Get pdiv. */
+ reg = readl(clk->regs_base + GENPLL_CONTROL5_OFFSET);
+ pdiv = (reg >> GENPLL_CONTROL5_PDIV_SHIFT) &
+ GENPLL_CONTROL5_PDIV_MASK;
+
+ /* If pdiv is 0, divide by 0.5 - doubler. */
+ if (pdiv == 0)
+ rate = parent_rate * 2;
+ else
+ rate = parent_rate / pdiv;
+
+ clk->rate = rate * ndiv_int;
+
+ pr_debug("[MIPI PLL] parent rate=%lu, ndiv int=%d, pdiv=%d, rate=%lu\n",
+ parent_rate, ndiv_int, pdiv, clk->rate);
+
+ return clk->rate;
+}
+
+/*
+ * Powers on the necessary PLL's and LDO for MIPI GEN PLL.
+ */
+static int cygnus_mipipll_prepare(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->pll_ctrl_reg))
+ return -EIO;
+
+ pr_debug("Powering up MIPI PLL and LDO\n");
+
+ /* Power on the PLL. */
+ cygnus_mipi_genpll_power_on_off(clk->pll_ctrl_reg, true);
+
+ clk->state = CLK_PREPARED;
+
+ return 0;
+}
+
+/*
+ * Powers off the PLL's and LDO for MIPI GEN PLL.
+ */
+static void cygnus_mipipll_unprepare(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->pll_ctrl_reg))
+ return;
+
+ pr_debug("Powering down MIPI PLL and LDO\n");
+
+ /* Power off the PLL. */
+ cygnus_mipi_genpll_power_on_off(clk->pll_ctrl_reg, false);
+
+ clk->state = CLK_DISABLED;
+}
+
+static unsigned long cygnus_mipipll_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *bcm_clk = to_cygnus_clk(hwclk);
+
+ if (bcm_clk->state != CLK_ENABLED)
+ return 0;
+
+ return cygnus_mipipll_get_rate(bcm_clk, parent_rate);
+}
+
+/*
+ * Enables the MIPI DSI clock gate through the top clock gating control.
+ */
+static int cygnus_mipipll_enable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return -EIO;
+
+ pr_debug("Enable MIPI PLL\n");
+
+ /* Enable MIPI DSI clock. */
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ MIPI_DSI_CLK_GATE_EN, true);
+
+ clk->state = CLK_ENABLED;
+
+ return 0;
+}
+
+/*
+ * Turns off the MIPI PLL clock.
+ */
+static void cygnus_mipipll_disable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return;
+
+ pr_debug("Disabling MIPI PLL and LDO\n");
+
+ /* Disable MIPI DSI clock through top clock gating control. */
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ MIPI_DSI_CLK_GATE_EN, false);
+
+ clk->state = CLK_DISABLED;
+}
+
+static const struct clk_ops cygnus_mipipll_ops = {
+ .prepare = cygnus_mipipll_prepare,
+ .unprepare = cygnus_mipipll_unprepare,
+ .enable = cygnus_mipipll_enable,
+ .disable = cygnus_mipipll_disable,
+ .recalc_rate = cygnus_mipipll_recalc_rate,
+};
+
+static void __init cygnus_mipipll_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_mipipll_ops);
+}
+CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll-clk", cygnus_mipipll_init);
+
+/*
+ * MIPI PLL clock channel management.
+ */
+
+/*
+ * Enables a MIPI PLL channel.
+ */
+static void mipi_pll_enable_chan(void __iomem *base, int chan, bool state)
+{
+ u32 val;
+
+ val = readl(base + GENPLL_CONTROL1_OFFSET);
+
+ /* ENABLEB_CH bit set to 0 to enable channel, 1 to disable. */
+ if (state)
+ val &= ~(1 << (chan + MIPI_DSI_GENPLL_ENABLEB_CH_SHIFT));
+ else
+ val |= (1 << (chan + MIPI_DSI_GENPLL_ENABLEB_CH_SHIFT));
+
+ writel(val, base + GENPLL_CONTROL1_OFFSET);
+}
+
+static unsigned long cygnus_mipipll_chan_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return 0;
+
+ if (clk->state != CLK_ENABLED)
+ return 0;
+
+ return cygnus_genpll_chan_get_rate(clk, parent_rate,
+ MIPI_DSI_GENPLL_ENABLEB_CH_SHIFT);
+}
+
+/*
+ * Enables the PLL channel and the top clock gating control for clocks that
+ * are controlled through it.
+ */
+static int cygnus_mipipll_chan_enable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+ struct clk *parent_clk = clk_get_parent(hwclk->clk);
+ int parent_rate;
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return -EIO;
+
+ pr_debug("Enable MIPI PLL chan %d\n", clk->chan);
+
+ /*
+ * Some MIPI PLL channels have to be enabled through the top clock
+ * gating ctrl. Add support for other channels here.
+ */
+ if (clk->chan == MIPI_PLL_CH1_LCD_CLK) {
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ LCD_CLK_GATE_EN, true);
+ }
+
+ /* Enable the PLL channel. */
+ mipi_pll_enable_chan(clk->regs_base, clk->chan, true);
+
+ clk->state = CLK_ENABLED;
+
+ /* Ensure parent's clock rate is calculated. */
+ parent_rate = clk_get_rate(parent_clk);
+ if (WARN_ON(!parent_rate))
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * Disables the PLL channel. Some channels also have to be shut down through
+ * the top clock gating control.
+ */
+static void cygnus_mipipll_chan_disable(struct clk_hw *hwclk)
+{
+ struct cygnus_clk *clk = to_cygnus_clk(hwclk);
+
+ if (WARN_ON(!clk->clock_gate_ctrl_reg))
+ return;
+
+ pr_debug("Disable MIPI PLL chan %d\n", clk->chan);
+
+ /* Disable LCD clock through top clock gating control. */
+ if (clk->chan == MIPI_PLL_CH1_LCD_CLK) {
+ cygnus_clkgate_enable_disable(clk->clock_gate_ctrl_reg,
+ LCD_CLK_GATE_EN, false);
+ }
+
+ /* Disable the PLL channel. */
+ mipi_pll_enable_chan(clk->regs_base, clk->chan, false);
+
+ clk->state = CLK_DISABLED;
+}
+
+static const struct clk_ops cygnus_mipipll_chan_ops = {
+ .enable = cygnus_mipipll_chan_enable,
+ .disable = cygnus_mipipll_chan_disable,
+ .recalc_rate = cygnus_mipipll_chan_recalc_rate,
+};
+
+static void __init cygnus_mipipll_ch_init(struct device_node *node)
+{
+ cygnus_clock_init(node, &cygnus_mipipll_chan_ops);
+}
+
+CLK_OF_DECLARE(cygnus_mipipll_ch, "brcm,cygnus-mipipll-ch",
+ cygnus_mipipll_ch_init);
diff --git a/drivers/clk/bcm/clk-iproc.c b/drivers/clk/bcm/clk-iproc.c
new file mode 100644
index 0000000..aca4851
--- /dev/null
+++ b/drivers/clk/bcm/clk-iproc.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2014 Broadcom Corporation. All rights reserved.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+
+#define IPROC_CLK_POLICY_FREQ_OFFSET 0x008
+#define IPROC_CLK_POLICY0_MSK_OFFSET 0x010
+#define IPROC_CLK_APB_SW_DIV_OFFSET 0xA10
+#define IPROC_CLK_PLL_ARMA_OFFSET 0xC00
+#define IPROC_CLK_PLL_ARMB_OFFSET 0xC04
+#define IPROC_CLK_PLL_ARMC_OFFSET 0xC08
+#define IPROC_CLK_PLL_ARMCTL5_OFFSET 0xC20
+#define IPROC_CLK_PLL_ARM_OFFSET_OFFSET 0xC24
+#define IPROC_CLK_ARM_DIV_OFFSET 0xE00
+#define IPROC_CLK_POLICY_DBG_OFFSET 0xEC0
+
+#define IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_OVERRIDE_SHIFT 4
+#define IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_MASK 0xf
+#define IPROC_CLK_POLICY_FREQ_OFFSET_POLICY_FREQ_MASK 0xf
+#define IPROC_CLK_POLICY_FREQ_OFFSET_POLICY_FREQ_SHIFT 8
+#define IPROC_CLK_POLICY_DBG_OFFSET_ACT_FREQ_SHIFT 12
+#define IPROC_CLK_POLICY_DBG_OFFSET_ACT_FREQ_MASK 7
+#define IPROC_CLK_PLL_ARM_OFFSET_PLLARM_OFFSET_SW_CTL_SHIFT 29
+#define CLK_PLL_ARM_OFFSET_PLLARM_NDIV_INT_OFFSET 20
+#define CLK_PLL_ARM_OFFSET_PLLARM_NDIV_INT_MASK 0xff
+#define CLK_PLL_ARM_OFFSET_PLLARM_NDIV_FRAC_OFFSET 0xfffff
+#define CLK_PLL_ARMA_PLLARM_NDIV_INT_SHIFT 8
+#define CLK_PLL_ARMA_PLLARM_NDIV_INT_MASK 0x3ff
+#define CLK_PLL_ARMB_PLLARM_NDIV_FRAC_MASK 0xfffff
+#define CLK_PLL_ARMC_PLLARM_MDIV_MASK 0xff
+#define CLK_PLL_ARMCTL5_PLLARM_H_MDIV_MASK 0xff
+#define CLK_PLL_ARMC_PLLARM_BYPCLK_EN_SHIFT 8
+#define CLK_PLL_ARMA_PLLARM_PDIV_SHIFT 24
+#define CLK_PLL_ARMA_PLLARM_PDIV_MASK 0xf
+#define CLK_PLL_ARMA_PLLARM_LOCK_SHIFT 28
+#define CLK_ARM_DIV_APB0_FREE_DIV_SHIFT 8
+#define CLK_ARM_DIV_APB0_FREE_DIV_MASK 0x7
+#define CLK_ARM_DIV_ARM_SWITCH_DIV_SHIFT 8
+#define CLK_ARM_DIV_ARM_SWITCH_DIV_MASK 0x3
+#define CLK_APB_SW_DIV_APB_CLK_DIV_MASK 0x3
+
+struct brcm_clk {
+ struct clk_hw hw;
+ void __iomem *regs_base;
+ int chan;
+ unsigned long rate;
+};
+
+/* Identifies derived clocks from ARM PLL. */
+enum {
+ ARMPLL_APB0_FREE_CLK = 0,
+ ARMPLL_ARM_SWITCH_CLK = 1,
+ ARMPLL_ARM_APB_CLK = 2,
+ ARMPLL_ARM_PERIPH_CLK = 3
+};
+
+/* Frequency id's from policy0_freq field of POLICY_FREQ register. */
+enum a9pll_policy_freq {
+ PLL_CRYSTAL_CLK = 0,
+ PLL_SYS_CLK = 2,
+ PLL_CH0_SLOW_CLK = 6,
+ PLL_CH1_FAST_CLK = 7
+};
+
+#define to_brcm_clk(p) container_of(p, struct brcm_clk, hw)
+
+static int iproc_cru_arm_freq_id(void __iomem *regs_base)
+{
+ u32 reg_f, reg;
+ unsigned policy = 0;
+ unsigned fid;
+ unsigned active_freq;
+
+ /* Read policy frequency. */
+ reg_f = readl(regs_base + IPROC_CLK_POLICY_FREQ_OFFSET);
+
+ /* Check for PLL policy software override. */
+ reg = readl(regs_base + IPROC_CLK_ARM_DIV_OFFSET);
+ if (reg & (1 << IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_OVERRIDE_SHIFT))
+ policy = reg & IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_MASK;
+
+ /* Get frequency ID based on policy. */
+ fid = (reg_f >>
+ (IPROC_CLK_POLICY_FREQ_OFFSET_POLICY_FREQ_SHIFT * policy)) &
+ IPROC_CLK_POLICY_FREQ_OFFSET_POLICY_FREQ_MASK;
+
+ /* Verify freq id from debug register. */
+ reg = readl(regs_base + IPROC_CLK_POLICY_DBG_OFFSET);
+ /* Read current active frequency id. */
+ active_freq = IPROC_CLK_POLICY_DBG_OFFSET_ACT_FREQ_MASK &
+ (reg >> IPROC_CLK_POLICY_DBG_OFFSET_ACT_FREQ_SHIFT);
+
+ if (fid != active_freq) {
+ pr_debug("IPROC CRU clock frequency id override %d->%d\n",
+ fid, active_freq);
+
+ fid = active_freq;
+ }
+
+ pr_debug("Active frequency ID %d\n", fid);
+
+ return fid;
+}
+
+/*
+ * Get ndiv integer and combine with fractional part to create 64 bit
+ * value.
+ */
+static u64 a9pll_get_ndiv(struct brcm_clk *clk)
+{
+ u32 arm_offset_reg;
+ u32 pllarma_reg;
+ u32 pllarmb_reg;
+ u32 ndiv_int;
+ u32 ndiv_frac;
+ u64 ndiv;
+
+ arm_offset_reg = readl(clk->regs_base +
+ IPROC_CLK_PLL_ARM_OFFSET_OFFSET);
+
+ /*
+ * Check if offset mode is active to determine which register to
+ * get ndiv from.
+ */
+ if (arm_offset_reg &
+ (1 << IPROC_CLK_PLL_ARM_OFFSET_PLLARM_OFFSET_SW_CTL_SHIFT)) {
+ /* Offset mode active. Get integer divide from offset reg. */
+ ndiv_int = (arm_offset_reg >>
+ CLK_PLL_ARM_OFFSET_PLLARM_NDIV_INT_OFFSET) &
+ CLK_PLL_ARM_OFFSET_PLLARM_NDIV_INT_MASK;
+
+ if (ndiv_int == 0)
+ ndiv_int = 256;
+
+ /* Get ndiv fractional divider. */
+ ndiv_frac = arm_offset_reg &
+ CLK_PLL_ARM_OFFSET_PLLARM_NDIV_FRAC_OFFSET;
+ } else {
+ /* Offset mode not active so read PLL ndiv from PLLARMA. */
+ pllarma_reg = readl(clk->regs_base + IPROC_CLK_PLL_ARMA_OFFSET);
+ ndiv_int = (pllarma_reg >> CLK_PLL_ARMA_PLLARM_NDIV_INT_SHIFT) &
+ CLK_PLL_ARMA_PLLARM_NDIV_INT_MASK;
+
+ if (ndiv_int == 0)
+ ndiv_int = 1024;
+
+ /* Get ndiv fractional divider. */
+ pllarmb_reg = readl(clk->regs_base + IPROC_CLK_PLL_ARMB_OFFSET);
+ ndiv_frac = pllarmb_reg & CLK_PLL_ARMB_PLLARM_NDIV_FRAC_MASK;
+ }
+
+ ndiv = ((u64) ndiv_int << 20) | ndiv_frac;
+
+ return ndiv;
+}
+
+/*
+ * Determine mdiv (post divider) based on the frequency id being used.
+ * There are 4 clocks that can be used to derive the output clock rate:
+ * - 25 MHz crystal
+ * - sys_clk
+ * - channel 0 (slow clock)
+ * - channel 1 (fast clock)
+ *
+ * If the slow clock is being used then mdiv is read from PLLARMC. If
+ * the fast clock is being used then the channel 1 mdiv is used.
+ * Otherwise there is no post divider.
+ *
+ * @return The mdiv value. -EIO if an error occurred.
+ */
+static int a9pll_get_mdiv(struct brcm_clk *clk)
+{
+ u32 mdiv;
+ u32 pllarmc_reg;
+ u32 armctl5_reg;
+ u32 freq_id;
+
+ /* Get the policy frequency. */
+ freq_id = iproc_cru_arm_freq_id(clk->regs_base);
+
+ switch (freq_id) {
+ /* There is no divider for these frequency id's. */
+ case PLL_CRYSTAL_CLK:
+ case PLL_SYS_CLK:
+ mdiv = 1;
+ break;
+
+ case PLL_CH0_SLOW_CLK: {
+ /* Read mdiv (post-divider) from PLLARMC bits 0:7 */
+ pllarmc_reg = readl(clk->regs_base + IPROC_CLK_PLL_ARMC_OFFSET);
+ mdiv = pllarmc_reg & CLK_PLL_ARMC_PLLARM_MDIV_MASK;
+ if (mdiv == 0)
+ mdiv = 256;
+ break;
+ }
+
+ case PLL_CH1_FAST_CLK: {
+ /* Post divider for channel 1 is in CTL5 (pllarm_h_mdiv). */
+ armctl5_reg = readl(clk->regs_base +
+ IPROC_CLK_PLL_ARMCTL5_OFFSET);
+ mdiv = armctl5_reg & CLK_PLL_ARMCTL5_PLLARM_H_MDIV_MASK;
+ if (mdiv == 0)
+ mdiv = 256;
+ break;
+ }
+
+ default:
+ return -EIO;
+ }
+
+ return mdiv;
+}
+
+/*
+ * Calculate the output frequency of the ARM PLL. The main output clock
+ * is 'arm_clk'.
+ *
+ * The frequency is calculated based on the ARM PLL divider values:
+ * pdiv = ARM PLL input pre-divider
+ * ndiv = ARM PLL feedback divider
+ * mdiv = ARM PLL post divider
+ *
+ * The frequency is calculated by:
+ * ((ndiv * parent clock rate) / pdiv) / mdiv
+ */
+static int a9pll_status(struct brcm_clk *clk, unsigned long parent_rate)
+{
+ u32 pllarma_reg;
+ u32 pllarmc_reg;
+ u32 pdiv;
+ u32 mdiv;
+ u64 ndiv;
+ u32 arm_clk_freq;
+
+ pr_debug("a9pll_status: clk 0x%x\n", (unsigned int)clk);
+
+ BUG_ON(!clk->regs_base);
+
+ pllarma_reg = readl(clk->regs_base + IPROC_CLK_PLL_ARMA_OFFSET);
+ pllarmc_reg = readl(clk->regs_base + IPROC_CLK_PLL_ARMC_OFFSET);
+
+ /* Check if PLL is in bypass mode - input frequency to output */
+ if (pllarmc_reg & (1 << CLK_PLL_ARMC_PLLARM_BYPCLK_EN_SHIFT)) {
+ clk->rate = parent_rate;
+ return 0;
+ }
+
+ /* Check if PLL is locked. It must be unlocked. */
+ if ((pllarma_reg &
+ (1 << CLK_PLL_ARMA_PLLARM_LOCK_SHIFT)) == 0) {
+ clk->rate = 0;
+ return -EIO;
+ }
+
+ /* Read pdiv from PLLARMA. */
+ pdiv = (pllarma_reg >> CLK_PLL_ARMA_PLLARM_PDIV_SHIFT) &
+ CLK_PLL_ARMA_PLLARM_PDIV_MASK;
+ if (pdiv == 0)
+ pdiv = 16;
+
+ /* Determine ndiv. */
+ ndiv = a9pll_get_ndiv(clk);
+
+ /* Determine mdiv (post divider). */
+ mdiv = a9pll_get_mdiv(clk);
+ if (mdiv == -EIO) {
+ clk->rate = 0;
+ return -EIO;
+ }
+
+ /* Calculate clock frequency. */
+ arm_clk_freq = (ndiv * parent_rate) >> 20;
+ arm_clk_freq = (arm_clk_freq / pdiv) / mdiv;
+
+ clk->rate = arm_clk_freq;
+
+ pr_debug("ARM PLL (arm_clk) rate %lu. parent rate = %lu, ",
+ clk->rate, parent_rate);
+ pr_debug("ndiv_int = %d, pdiv = %d, mdiv = %d\n",
+ (u32)ndiv >> 20, pdiv, mdiv);
+
+ return clk->rate;
+}
+
+static unsigned long clk_a9pll_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct brcm_clk *bcm_clk = to_brcm_clk(hwclk);
+
+ return a9pll_status(bcm_clk, parent_rate);
+}
+
+static const struct clk_ops a9pll_ops = {
+ .recalc_rate = clk_a9pll_recalc_rate,
+};
+
+/*
+ * Get status of any of the ARMPLL output channels
+ */
+static int a9pll_chan_status(struct brcm_clk *clk, unsigned long parent_rate)
+{
+ u32 reg;
+ unsigned div;
+
+ BUG_ON(!clk->regs_base);
+
+ reg = readl(clk->regs_base + IPROC_CLK_ARM_DIV_OFFSET);
+ pr_debug("Clock Div = %#x\n", reg);
+
+ switch (clk->chan) {
+ case ARMPLL_APB0_FREE_CLK:
+ /* apb0_free_div bits 10:8 */
+ div = (reg >> CLK_ARM_DIV_APB0_FREE_DIV_SHIFT) &
+ CLK_ARM_DIV_APB0_FREE_DIV_MASK;
+ div++;
+ break;
+
+ case ARMPLL_ARM_SWITCH_CLK:
+ /* arm_switch_div bits 6:5 */
+ div = (reg >> CLK_ARM_DIV_ARM_SWITCH_DIV_SHIFT) &
+ CLK_ARM_DIV_ARM_SWITCH_DIV_MASK;
+ div++;
+ break;
+
+ case ARMPLL_ARM_APB_CLK:
+ /* IPROC_CLK_APB_SW_DIV_REG apb_clk_div bits 1:0 */
+ reg = readl(clk->regs_base + IPROC_CLK_APB_SW_DIV_OFFSET);
+ div = reg & CLK_APB_SW_DIV_APB_CLK_DIV_MASK;
+ div++;
+ break;
+
+ case ARMPLL_ARM_PERIPH_CLK: /* periph_clk */
+ div = 2;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ clk->rate = parent_rate / div;
+ pr_debug("Clock rate A9PLL chan 0x%x: %lu, div: %d\n",
+ clk->chan, clk->rate, div);
+
+ return clk->rate;
+}
+
+static unsigned long clk_a9pll_chan_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct brcm_clk *bcm_clk = to_brcm_clk(hwclk);
+
+ return a9pll_chan_status(bcm_clk, parent_rate);
+}
+
+static const struct clk_ops a9pll_chan_ops = {
+ .recalc_rate = clk_a9pll_chan_recalc_rate,
+};
+
+static __init struct clk *iproc_clock_init(struct device_node *node,
+ const struct clk_ops *ops)
+{
+ u32 channel = 0;
+ struct clk *clk;
+ struct brcm_clk *brcm_clk;
+ const char *clk_name = node->name;
+ const char *parent_name;
+ struct clk_init_data init;
+ int rc;
+
+ pr_debug("Clock name %s\n", node->name);
+
+ rc = of_property_read_u32(node, "channel", &channel);
+ brcm_clk = kzalloc(sizeof(*brcm_clk), GFP_KERNEL);
+ if (WARN_ON(!brcm_clk))
+ return NULL;
+
+ /* Read base address from device tree and map to virtual address. */
+ brcm_clk->regs_base = of_iomap(node, 0);
+ if (WARN_ON(!brcm_clk->regs_base))
+ goto err_alloc;
+
+ brcm_clk->chan = channel;
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ init.name = clk_name;
+ init.ops = ops;
+ init.flags = 0;
+ parent_name = of_clk_get_parent_name(node, 0);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ brcm_clk->hw.init = &init;
+
+ clk = clk_register(NULL, &brcm_clk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto err_unmap;
+
+ rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ if (WARN_ON(IS_ERR_VALUE(rc)))
+ goto err_unregister;
+
+ rc = clk_register_clkdev(clk, clk_name, NULL);
+ if (WARN_ON(IS_ERR_VALUE(rc)))
+ goto err_provider;
+
+ return clk;
+
+err_provider:
+ of_clk_del_provider(node);
+
+err_unregister:
+ clk_unregister(clk);
+
+err_unmap:
+ iounmap(brcm_clk->regs_base);
+
+err_alloc:
+ kfree(brcm_clk);
+
+ return NULL;
+}
+
+static void __init iproc_armpll_init(struct device_node *node)
+{
+ iproc_clock_init(node, &a9pll_ops);
+}
+CLK_OF_DECLARE(iproc_armpllx, "brcm,iproc-arm-a9pll", iproc_armpll_init);
+
+static void __init iproc_arm_ch_init(struct device_node *node)
+{
+ iproc_clock_init(node, &a9pll_chan_ops);
+}
+CLK_OF_DECLARE(iproc_arm_ch, "brcm,iproc-arm-ch", iproc_arm_ch_init);
--
1.7.9.5

2014-10-09 22:45:23

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 3/7] dt-bindings: Document Broadcom Cygnus SoC and clock driver

From: Jonathan Richardson <[email protected]>

Reviewed-by: Arun Parameswaran <[email protected]>
Tested-by: Jonathan Richardson <[email protected]>
Reviewed-by: JD (Jiandong) Zheng <[email protected]>
Signed-off-by: Scott Branden <[email protected]>
---
.../devicetree/bindings/arm/bcm/cygnus.txt | 31 +++++
.../devicetree/bindings/clock/clk-cygnus.txt | 121 ++++++++++++++++++++
.../devicetree/bindings/clock/clk-iproc.txt | 48 ++++++++
3 files changed, 200 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/bcm/cygnus.txt
create mode 100644 Documentation/devicetree/bindings/clock/clk-cygnus.txt
create mode 100644 Documentation/devicetree/bindings/clock/clk-iproc.txt

diff --git a/Documentation/devicetree/bindings/arm/bcm/cygnus.txt b/Documentation/devicetree/bindings/arm/bcm/cygnus.txt
new file mode 100644
index 0000000..4c77169
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/cygnus.txt
@@ -0,0 +1,31 @@
+Broadcom Cygnus device tree bindings
+------------------------------------
+
+
+Boards with Cygnus SoCs shall have the following properties:
+
+Required root node property:
+
+BCM11300
+compatible = "brcm,bcm11300", "brcm,cygnus";
+
+BCM11320
+compatible = "brcm,bcm11320", "brcm,cygnus";
+
+BCM11350
+compatible = "brcm,bcm11350", "brcm,cygnus";
+
+BCM11360
+compatible = "brcm,bcm11360", "brcm,cygnus";
+
+BCM58300
+compatible = "brcm,bcm58300", "brcm,cygnus";
+
+BCM58302
+compatible = "brcm,bcm58302", "brcm,cygnus";
+
+BCM58303
+compatible = "brcm,bcm58303", "brcm,cygnus";
+
+BCM58305
+compatible = "brcm,bcm58305", "brcm,cygnus";
diff --git a/Documentation/devicetree/bindings/clock/clk-cygnus.txt b/Documentation/devicetree/bindings/clock/clk-cygnus.txt
new file mode 100644
index 0000000..7e03837
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clk-cygnus.txt
@@ -0,0 +1,121 @@
+Broadcom Cygnus Clock Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The Cygnus clock controller manages several PLL's and their channels, found only
+on the Cygnus chip. Clocks that are common to iProc can be found in the iProc
+clock controller. The controllers are split into a parent-child relationship
+where the parent is the PLL and the child controls the PLL's channels.
+
+All PLL's are derived from a 25MHz oscillator. The PLL's controlled are the
+GENPLL, LCPLL, the MIPI PLL. In addition, there are two clocks derived from
+GENPLL channel 0, and three that are derived directly from the oscillator.
+
+Required properties:
+- compatible: Must be one of the following:
+ "brcm,cygnus-lcpll-clk" - Controls LCPLL.
+ "brcm,cygnus-lcpll-ch" - Controls LCPLL (parent) channels
+ "brcm,cygnus-genpll-clk" - Controls parent GENPLL
+ "brcm,cygnus-genpll-ch" - Controls GENPLL (parent) channels
+ "brcm,cygnus-mipipll-clk" - Controls MIPI PLL
+ "brcm,cygnus-mipipll-ch" - Controls parent MIPI PLL (parent) channels
+ "brcm,cygnus-osc-derived" - Controls oscillator (parent) derived channels
+ not controlled by any PLL.
+ "brcm,cygnus-pll-derived" - Controls clocks derived from GENPLL channel 0.
+ These clocks have hard wired internal dividers and their clock rates
+ scale according to the GENPLL channel.
+
+- reg: First register is the base address of the PLL. Register 2 and 3 are
+ required by some clocks. They are the top clock gating control used to
+ enable/disable clocks (ch 1), and the CRMU PLL AON CONTROL register which
+ powers on PLL/LDO's (ch 2).
+
+- clocks: The input parent clock phandle for the clock. This is either a PLL,
+ oscillator, or GENPLL channel 0.
+
+- channel: The PLL channel that the clock belongs to. This is used for
+ "brcm,cygnus-lcpll-ch", "brcm,cygnus-genpll-ch", "brcm,cygnus-mipipll-ch",
+ "brcm,cygnus-osc-derived" only.
+
+- div: Used by "brcm,cygnus-pll-derived" to define the hard coded internal
+ divider value. Used by "brcm,cygnus-osc-derived" to specify the programmable
+ divider.
+
+- #clock-cells: From common clock binding; shall be set to 0.
+
+Examples:
+
+ osc: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <25000000>;
+ };
+
+ lcpll: lcpll@0301d02c {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-lcpll-clk";
+ reg = <0x0301d02c 0x1c>;
+ clocks = <&osc>;
+ };
+
+ genpll: genpll@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-clk";
+ reg = <0x0301d000 0x2c>,
+ <0x180AA024 0x4>,
+ <0x0301C020 0x4>;
+ clocks = <&osc>;
+ };
+
+ axi21_clk: genpll_ch0@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <0>;
+ };
+
+ pcie_clk: lcpll_ch0@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <0>;
+ };
+
+ axi41_clk: axi41_clk {
+ reg = <0x0301d000 0x2c>;
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-pll-derived";
+ clocks = <&axi21_clk>;
+ div = <2>;
+ };
+
+ keypad_clk: keypad_clk@0301D048 {
+ compatible = "brcm,cygnus-osc-derived";
+ reg = <0x0301D048 0x4>,
+ <0x180AA024 0x4>;
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ channel = <0>;
+ div = <392>;
+ };
+
+ mipipll: mipipll@180a9800 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-mipipll-clk";
+ reg = <0x180a9800 0x2c>,
+ top_clk_gating_ctrl: <0x180AA024 0x4>,
+ crmu_pll_aon_ctrl: <0x0301C020 0x4>;
+ clocks = <&osc>;
+ };
+
+ lcd_clk: mipipll_ch1@180a9800 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-mipipll-ch";
+ reg = <0x180a9800 0x2c>,
+ <0x180AA024 0x4>;
+ clocks = <&mipipll>;
+ channel = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/clk-iproc.txt b/Documentation/devicetree/bindings/clock/clk-iproc.txt
new file mode 100644
index 0000000..b5d4f08
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clk-iproc.txt
@@ -0,0 +1,48 @@
+Broadcom iProc Clock Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The iProc clock controller manages clocks that are common to iProc chips.
+The controllers are split into a parent-child relationship where the parent is
+the PLL and the child controls the PLL's channels.
+
+The only PLL controlled is the ARM PLL which is derived from a 25MHz crystal.
+
+Required properties:
+- compatible: Must be one of the following:
+ "brcm,iproc-arm-a9pll" - Controls ARM PLL.
+ "brcm,iproc-arm-ch" - Controls ARM PLL (parent) channels
+
+- reg: The base address of the PLL.
+
+- clocks: The input parent clock phandle for the clock. This is either a PLL,
+ or oscillator.
+
+- channel: The PLL channel that the clock belongs to. This is used for
+ "brcm,iproc-arm-ch" only.
+
+- #clock-cells: From common clock binding; shall be set to 0.
+
+Example:
+
+ osc: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <25000000>;
+ };
+
+ a9pll: arm_clk@19000000 {
+ compatible = "brcm,iproc-arm-a9pll";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ };
+
+ periph_clk: periph_clk@19000000 {
+ compatible = "brcm,iproc-arm-ch";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&a9pll>;
+ channel = <3>;
+ };
--
1.7.9.5

2014-10-09 22:45:28

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 6/7] MAINTAINERS: Entry for Cygnus/iproc arm architecture and clock drivers

Acked-by: Jonathan Richardson <[email protected]>
Signed-off-by: Scott Branden <[email protected]>
---
MAINTAINERS | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index a12edf2..0900082 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2071,9 +2071,24 @@ L: [email protected]
S: Supported
F: drivers/scsi/bnx2i/

-BROADCOM KONA GPIO DRIVER
+BROADCOM CYGNUS/IPROC ARM ARCHITECTURE
M: Ray Jui <[email protected]>
+M: Scott Branden <[email protected]>
+L: [email protected] (moderated for non-subscribers)
L: [email protected]
+S: Maintained
+F: Documentation/devicetree/bindings/arm/bcm/cygnus.txt
+F: arch/arm/boot/dts/bcm-cygnus.dtsi
+F: arch/arm/boot/dts/bcm911360_entphn.dts
+F: arch/arm/configs/bcm_cygnus_defconfig
+F: arch/arm/mach-bcm/bcm_cygnus.c
+F: Documentation/devicetree/bindings/clock/clk-cygnus.txt
+F: Documentation/devicetree/bindings/clock/clk-iproc.txt
+F: drivers/clk/bcm/clk-cygnus.c
+F: drivers/clk/bcm/clk-iproc.c
+
+BROADCOM KONA GPIO DRIVER
+M: Ray Jui <[email protected]>
S: Supported
F: drivers/gpio/gpio-bcm-kona.c
F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
--
1.7.9.5

2014-10-09 22:45:50

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 7/7] ARM: multi_v7_defconfig: Enable ARCH_BCM_CYGNUS config

Enabled Broadcom Cygnus SoC family in multi_v7_defconfig by using
CONFIG_ARCH_BCM_CYGNUS=y.

Signed-off-by: Scott Branden <[email protected]>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 5fb95fb..d02f56d 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -17,6 +17,7 @@ CONFIG_MACH_ARMADA_38X=y
CONFIG_MACH_ARMADA_XP=y
CONFIG_MACH_DOVE=y
CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM_CYGNUS=y
CONFIG_ARCH_BCM_MOBILE=y
CONFIG_ARCH_BCM_5301X=y
CONFIG_ARCH_BRCMSTB=y
--
1.7.9.5

2014-10-09 22:46:35

by Scott Branden

[permalink] [raw]
Subject: [PATCH V4 5/7] ARM: dts: Enable Broadcom Cygnus SoC

From: Jonathan Richardson <[email protected]>

DT files to enable cygnus consisting of the enterprise phone board
variant and cygnus core configuration.

Reviewed-by: Ray Jui <[email protected]>
Reviewed-by: Arun Parameswaran <[email protected]>
Tested-by: Jonathan Richardson <[email protected]>
Reviewed-by: JD (Jiandong) Zheng <[email protected]>
Signed-off-by: Scott Branden <[email protected]>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/bcm-cygnus.dtsi | 349 ++++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm911360_entphn.dts | 22 ++
3 files changed, 372 insertions(+)
create mode 100644 arch/arm/boot/dts/bcm-cygnus.dtsi
create mode 100644 arch/arm/boot/dts/bcm911360_entphn.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b8c5cd3..b95d41d 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -52,6 +52,7 @@ dtb-$(CONFIG_ARCH_AT91) += sama5d36ek.dtb
dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
+dtb-$(CONFIG_ARCH_BCM_CYGNUS) += bcm911360_entphn.dtb
dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb
dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \
bcm21664-garnet.dtb
diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi
new file mode 100644
index 0000000..81da0d8
--- /dev/null
+++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2014 Broadcom Corporation. All rights reserved.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "skeleton.dtsi"
+
+/ {
+ compatible = "brcm,cygnus";
+ model = "Broadcom Cygnus SoC";
+ interrupt-parent = <&gic>;
+
+ aliases {
+ serial0 = &uart3;
+ serial1 = &uart0;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200 earlyprintk debug";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ next-level-cache = <&L2>;
+ reg = <0x0>;
+ };
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ osc: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <25000000>;
+ };
+
+ lcpll: lcpll@0301d02c {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-lcpll-clk";
+ reg = <0x0301d02c 0x1c>;
+ clocks = <&osc>;
+ };
+
+ genpll: genpll@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-clk";
+ reg = <0x0301d000 0x2c>,
+ <0x180AA024 0x4>,
+ <0x0301C020 0x4>;
+ clocks = <&osc>;
+ };
+
+ axi21_clk: genpll_ch0@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <0>;
+ };
+
+ clk_25MHz: genpll_ch1@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <1>;
+ };
+
+ sys_clk: genpll_ch2@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <2>;
+ };
+
+ ethernet_clk: genpll_ch3@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <3>;
+ };
+
+ asiu_audio_clk: genpll_ch4@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <4>;
+ };
+
+ asiu_can_clk: genpll_ch5@0301d000 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-genpll-ch";
+ reg = <0x0301d000 0x2c>;
+ clocks = <&genpll>;
+ channel = <5>;
+ };
+
+ pcie_clk: lcpll_ch0@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <0>;
+ };
+
+ ddr_clk: lcpll_ch1@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <1>;
+ };
+
+ sdio_clk: lcpll_ch2@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <2>;
+ };
+
+ usb_clk: lcpll_ch3@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <3>;
+ };
+
+ smart_card_clk: lcpll_ch4@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <4>;
+ };
+
+ ch5_unknown_clk: lcpll_ch5@0301d02c {
+ compatible = "brcm,cygnus-lcpll-ch";
+ reg = <0x0301d02c 0x1c>;
+ #clock-cells = <0>;
+ clocks = <&lcpll>;
+ channel = <5>;
+ };
+
+ /*
+ * There are 2 clocks derived from genpll ch0 (axi21) which are
+ * divided internally by 2 and 4. If axi21 clock rate changes, these
+ * derived clock rates scale accordingly.
+ */
+
+ axi41_clk: axi41_clk {
+ reg = <0x0301d000 0x2c>;
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-pll-derived";
+ clocks = <&axi21_clk>;
+ div = <2>;
+ };
+
+ axi81_clk: axi81_clk {
+ reg = <0x0301d000 0x2c>;
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-pll-derived";
+ clocks = <&axi21_clk>;
+ div = <4>;
+ };
+
+ /*
+ * The main output of the ARM PLL is arm_clk with several derived
+ * child clocks:
+ * periph_clk
+ * apb_clk
+ * arm_switch
+ * apb0_free
+ */
+ a9pll: arm_clk@19000000 {
+ compatible = "brcm,iproc-arm-a9pll";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ };
+
+ periph_clk: periph_clk@19000000 {
+ compatible = "brcm,iproc-arm-ch";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&a9pll>;
+ channel = <3>;
+ };
+
+ apb0_free: apb0_free@19000000 {
+ compatible = "brcm,iproc-arm-ch";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&a9pll>;
+ channel = <0>;
+ };
+
+ arm_switch: arm_switch@19000000 {
+ compatible = "brcm,iproc-arm-ch";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&a9pll>;
+ channel = <1>;
+ };
+
+ apb_clk: apb_clk@19000000 {
+ compatible = "brcm,iproc-arm-ch";
+ reg = <0x19000000 0x1000>;
+ #clock-cells = <0>;
+ clocks = <&a9pll>;
+ channel = <2>;
+ };
+
+ /*
+ * Clocks derived from oscillator.
+ */
+ keypad_clk: keypad_clk@0301D048 {
+ compatible = "brcm,cygnus-osc-derived";
+ reg = <0x0301D048 0x4>,
+ <0x180AA024 0x4>;
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ channel = <0>;
+ div = <392>;
+ };
+
+ adc_clk: adc_clk@0301D04C {
+ compatible = "brcm,cygnus-osc-derived";
+ reg = <0x0301D04C 0x4>,
+ <0x180AA024 0x4>;
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ channel = <1>;
+ };
+
+ pwm_clk: pwm_clk@0301D050 {
+ compatible = "brcm,cygnus-osc-derived";
+ reg = <0x0301D050 0x4>,
+ <0x180AA024 0x4>;
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ channel = <2>;
+ };
+
+ mipipll: mipipll@180a9800 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-mipipll-clk";
+ reg = <0x180a9800 0x2c>,
+ top_clk_gating_ctrl: <0x180AA024 0x4>,
+ crmu_pll_aon_ctrl: <0x0301C020 0x4>;
+ clocks = <&osc>;
+ };
+
+ lcd_clk: mipipll_ch1@180a9800 {
+ #clock-cells = <0>;
+ compatible = "brcm,cygnus-mipipll-ch";
+ reg = <0x180a9800 0x2c>,
+ <0x180AA024 0x4>;
+ clocks = <&mipipll>;
+ channel = <1>;
+ };
+ };
+
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus", "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ wdt@18009000 {
+ compatible = "arm,sp805" , "arm,primecell";
+ reg = <0x18009000 0x1000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&axi81_clk>;
+ clock-names = "apb_pclk";
+ };
+ };
+
+ uart3: serial@18023000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x18023000 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <100000000>;
+ clocks = <&axi81_clk>;
+ status = "okay";
+ };
+
+ uart0: serial@18020000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x18020000 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&axi81_clk>;
+ clock-frequency = <100000000>;
+ status = "okay";
+ };
+
+ gic: interrupt-controller@19021000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x19021000 0x1000>,
+ <0x19020100 0x100>;
+ };
+
+ L2: l2-cache {
+ compatible = "arm,pl310-cache";
+ reg = <0x19022000 0x1000>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ timer@19020200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x19020200 0x100>;
+ interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&periph_clk>;
+ };
+
+};
diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/bcm911360_entphn.dts
new file mode 100644
index 0000000..c5188d7
--- /dev/null
+++ b/arch/arm/boot/dts/bcm911360_entphn.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014 Broadcom Corporation. All rights reserved.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "bcm-cygnus.dtsi"
+
+/ {
+ model = "Cygnus Enterprise Phone (BCM911360_ENTPHN)";
+ compatible = "brcm,bcm11360", "brcm,cygnus";
+};
--
1.7.9.5

2014-10-09 23:01:00

by Joe Perches

[permalink] [raw]
Subject: Re: [PATCH V4 6/7] MAINTAINERS: Entry for Cygnus/iproc arm architecture and clock drivers

On Thu, 2014-10-09 at 15:44 -0700, Scott Branden wrote:
> Acked-by: Jonathan Richardson <[email protected]>
> Signed-off-by: Scott Branden <[email protected]>
> ---
> MAINTAINERS | 17 ++++++++++++++++-
> 1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a12edf2..0900082 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2071,9 +2071,24 @@ L: [email protected]
> S: Supported
> F: drivers/scsi/bnx2i/
>
> -BROADCOM KONA GPIO DRIVER
> +BROADCOM CYGNUS/IPROC ARM ARCHITECTURE
> M: Ray Jui <[email protected]>
> +M: Scott Branden <[email protected]>
> +L: [email protected] (moderated for non-subscribers)
> L: [email protected]
> +S: Maintained
> +F: Documentation/devicetree/bindings/arm/bcm/cygnus.txt
> +F: arch/arm/boot/dts/bcm-cygnus.dtsi
> +F: arch/arm/boot/dts/bcm911360_entphn.dts
> +F: arch/arm/configs/bcm_cygnus_defconfig
> +F: arch/arm/mach-bcm/bcm_cygnus.c
> +F: Documentation/devicetree/bindings/clock/clk-cygnus.txt
> +F: Documentation/devicetree/bindings/clock/clk-iproc.txt
> +F: drivers/clk/bcm/clk-cygnus.c
> +F: drivers/clk/bcm/clk-iproc.c
> +
> +BROADCOM KONA GPIO DRIVER
> +M: Ray Jui <[email protected]>
> S: Supported
> F: drivers/gpio/gpio-bcm-kona.c
> F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt

This drops this L line from BROADCOM KONA GPIO DRIVER
L: [email protected]

Is that what you want?

2014-10-09 23:18:15

by Scott Branden

[permalink] [raw]
Subject: Re: [PATCH V4 6/7] MAINTAINERS: Entry for Cygnus/iproc arm architecture and clock drivers

On 14-10-09 04:00 PM, Joe Perches wrote:
> On Thu, 2014-10-09 at 15:44 -0700, Scott Branden wrote:
>> Acked-by: Jonathan Richardson <[email protected]>
>> Signed-off-by: Scott Branden <[email protected]>
>> ---
>> MAINTAINERS | 17 ++++++++++++++++-
>> 1 file changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index a12edf2..0900082 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -2071,9 +2071,24 @@ L: [email protected]
>> S: Supported
>> F: drivers/scsi/bnx2i/
>>
>> -BROADCOM KONA GPIO DRIVER
>> +BROADCOM CYGNUS/IPROC ARM ARCHITECTURE
>> M: Ray Jui <[email protected]>
>> +M: Scott Branden <[email protected]>
>> +L: [email protected] (moderated for non-subscribers)
>> L: [email protected]
>> +S: Maintained
>> +F: Documentation/devicetree/bindings/arm/bcm/cygnus.txt
>> +F: arch/arm/boot/dts/bcm-cygnus.dtsi
>> +F: arch/arm/boot/dts/bcm911360_entphn.dts
>> +F: arch/arm/configs/bcm_cygnus_defconfig
>> +F: arch/arm/mach-bcm/bcm_cygnus.c
>> +F: Documentation/devicetree/bindings/clock/clk-cygnus.txt
>> +F: Documentation/devicetree/bindings/clock/clk-iproc.txt
>> +F: drivers/clk/bcm/clk-cygnus.c
>> +F: drivers/clk/bcm/clk-iproc.c
>> +
>> +BROADCOM KONA GPIO DRIVER
>> +M: Ray Jui <[email protected]>
>> S: Supported
>> F: drivers/gpio/gpio-bcm-kona.c
>> F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
>
> This drops this L line from BROADCOM KONA GPIO DRIVER
> L: [email protected]
>
> Is that what you want?
Wow, sorry. I'll correct after further comments.
>

2014-10-10 09:51:32

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH V4 1/7] ARM: cygnus: Initial support for Broadcom Cygnus SoC

On Thursday 09 October 2014 15:44:25 Scott Branden wrote:
> From: Jonathan Richardson <[email protected]>
>
> Adds initial support for the Cygnus SoC based on Broadcom’s iProc series.
> Move ARCH_BCM_5301x under the ARCH_BCM_IPROC architecture.
>
> Reviewed-by: Ray Jui <[email protected]>
> Reviewed-by: Desmond Liu <[email protected]>
> Reviewed-by: JD (Jiandong) Zheng <[email protected]>
> Tested-by: Jonathan Richardson <[email protected]>
> Signed-off-by: Scott Branden <[email protected]>

No signoff from the Author?

> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index b11ad54..85363de 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -1051,7 +1051,7 @@ config DEBUG_UART_PL01X
>
> # Compatibility options for 8250
> config DEBUG_UART_8250
> - def_bool ARCH_DOVE || ARCH_EBSA110 || \
> + def_bool ARCH_BCM_IPROC || ARCH_DOVE || ARCH_EBSA110 || \
> (FOOTBRIDGE && !DEBUG_DC21285_PORT) || \
> ARCH_GEMINI || ARCH_IOP13XX || ARCH_IOP32X || \
> ARCH_IOP33X || ARCH_IXP4XX || \

As I mentioned before, this is the wrong option. Please use
DEBUG_LL_UART_8250 like all the modern platforms do.

> diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
> index fc93800..b2b6752 100644
> --- a/arch/arm/mach-bcm/Kconfig
> +++ b/arch/arm/mach-bcm/Kconfig
> @@ -5,6 +5,53 @@ menuconfig ARCH_BCM
>
> if ARCH_BCM
>
> +menu "iProc SoC based Machine types"
> + config ARCH_BCM_IPROC
> + bool "Broadcom ARMv7 iProc boards" if ARCH_MULTI_V7
> + depends on ARCH_BCM_CYGNUS || ARCH_BCM_5301X

Please make this a silent option by dropping the text after 'bool',
and the 'depends on' line.

> + select ARM_GIC
> + select CACHE_L2X0
> + select HAVE_ARM_SCU if SMP
> + select HAVE_ARM_TWD if SMP
> + select ARM_GLOBAL_TIMER
> +
> + select CLKSRC_MMIO
> + select ARCH_REQUIRE_GPIOLIB
> + select ARM_AMBA
> + select PINCTRL

> +
> +static const char const *bcm_cygnus_dt_compat[] = {
> + "brcm,cygnus",
> + NULL,
> +};
> +
> +DT_MACHINE_START(BCM_CYGNUS_DT, "Broadcom Cygnus SoC")
> + .l2c_aux_val = 0,
> + .l2c_aux_mask = ~0,
> + .dt_compat = bcm_cygnus_dt_compat,
> +MACHINE_END
>

This looks good now.

Arnd

2014-10-10 09:59:59

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH V4 7/7] ARM: multi_v7_defconfig: Enable ARCH_BCM_CYGNUS config

On Thursday 09 October 2014 15:44:31 Scott Branden wrote:
> Enabled Broadcom Cygnus SoC family in multi_v7_defconfig by using
> CONFIG_ARCH_BCM_CYGNUS=y.
>
> Signed-off-by: Scott Branden <[email protected]>
> ---
> arch/arm/configs/multi_v7_defconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index 5fb95fb..d02f56d 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -17,6 +17,7 @@ CONFIG_MACH_ARMADA_38X=y
> CONFIG_MACH_ARMADA_XP=y
> CONFIG_MACH_DOVE=y
> CONFIG_ARCH_BCM=y
> +CONFIG_ARCH_BCM_CYGNUS=y
> CONFIG_ARCH_BCM_MOBILE=y
> CONFIG_ARCH_BCM_5301X=y
> CONFIG_ARCH_BRCMSTB=y
>

Does this contain all the drivers you need that are enabled in cygnus_defconfig?

Arnd

2014-10-10 10:09:03

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH V4 5/7] ARM: dts: Enable Broadcom Cygnus SoC

On Thursday 09 October 2014 15:44:29 Scott Branden wrote:
> +
> + lcpll: lcpll@0301d02c {
> + #clock-cells = <0>;
> + compatible = "brcm,cygnus-lcpll-clk";
> + reg = <0x0301d02c 0x1c>;
> + clocks = <&osc>;
> + };
> +
> + genpll: genpll@0301d000 {
> + #clock-cells = <0>;
> + compatible = "brcm,cygnus-genpll-clk";
> + reg = <0x0301d000 0x2c>,
> + <0x180AA024 0x4>,
> + <0x0301C020 0x4>;
> + clocks = <&osc>;
> + };
> +

To be honest, I'm not too happy about the way you specify a single
register for each clock as a global 'reg' property.

Presumably each of these registers is part of an IP block that does
multiple things, so it would be better to start out with a binding
for each IP block. How many of these blocks are used for clocks, and
what do they do?

Arnd

2014-10-10 19:08:40

by Scott Branden

[permalink] [raw]
Subject: Re: [PATCH V4 1/7] ARM: cygnus: Initial support for Broadcom Cygnus SoC

On 14-10-10 02:50 AM, Arnd Bergmann wrote:
> On Thursday 09 October 2014 15:44:25 Scott Branden wrote:
>> From: Jonathan Richardson <[email protected]>
>>
>> Adds initial support for the Cygnus SoC based on Broadcom’s iProc series.
>> Move ARCH_BCM_5301x under the ARCH_BCM_IPROC architecture.
>>
>> Reviewed-by: Ray Jui <[email protected]>
>> Reviewed-by: Desmond Liu <[email protected]>
>> Reviewed-by: JD (Jiandong) Zheng <[email protected]>
>> Tested-by: Jonathan Richardson <[email protected]>
>> Signed-off-by: Scott Branden <[email protected]>
>
> No signoff from the Author?
It is a collaborative effort. Jonathan is on 2 month leave so I have
taken over pushing this through or change Author.
>
>> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
>> index b11ad54..85363de 100644
>> --- a/arch/arm/Kconfig.debug
>> +++ b/arch/arm/Kconfig.debug
>> @@ -1051,7 +1051,7 @@ config DEBUG_UART_PL01X
>>
>> # Compatibility options for 8250
>> config DEBUG_UART_8250
>> - def_bool ARCH_DOVE || ARCH_EBSA110 || \
>> + def_bool ARCH_BCM_IPROC || ARCH_DOVE || ARCH_EBSA110 || \
>> (FOOTBRIDGE && !DEBUG_DC21285_PORT) || \
>> ARCH_GEMINI || ARCH_IOP13XX || ARCH_IOP32X || \
>> ARCH_IOP33X || ARCH_IXP4XX || \
>
> As I mentioned before, this is the wrong option. Please use
> DEBUG_LL_UART_8250 like all the modern platforms do.
ok, will remove
>
>> diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
>> index fc93800..b2b6752 100644
>> --- a/arch/arm/mach-bcm/Kconfig
>> +++ b/arch/arm/mach-bcm/Kconfig
>> @@ -5,6 +5,53 @@ menuconfig ARCH_BCM
>>
>> if ARCH_BCM
>>
>> +menu "iProc SoC based Machine types"
>> + config ARCH_BCM_IPROC
>> + bool "Broadcom ARMv7 iProc boards" if ARCH_MULTI_V7
>> + depends on ARCH_BCM_CYGNUS || ARCH_BCM_5301X
>
> Please make this a silent option by dropping the text after 'bool',
> and the 'depends on' line.
>
ok, will change, thanks
>> + select ARM_GIC
>> + select CACHE_L2X0
>> + select HAVE_ARM_SCU if SMP
>> + select HAVE_ARM_TWD if SMP
>> + select ARM_GLOBAL_TIMER
>> +
>> + select CLKSRC_MMIO
>> + select ARCH_REQUIRE_GPIOLIB
>> + select ARM_AMBA
>> + select PINCTRL
>
>> +
>> +static const char const *bcm_cygnus_dt_compat[] = {
>> + "brcm,cygnus",
>> + NULL,
>> +};
>> +
>> +DT_MACHINE_START(BCM_CYGNUS_DT, "Broadcom Cygnus SoC")
>> + .l2c_aux_val = 0,
>> + .l2c_aux_mask = ~0,
>> + .dt_compat = bcm_cygnus_dt_compat,
>> +MACHINE_END
>>
>
> This looks good now.
>
> Arnd
>

2014-10-10 19:11:45

by Scott Branden

[permalink] [raw]
Subject: Re: [PATCH V4 5/7] ARM: dts: Enable Broadcom Cygnus SoC

On 14-10-10 03:08 AM, Arnd Bergmann wrote:
> On Thursday 09 October 2014 15:44:29 Scott Branden wrote:
>> +
>> + lcpll: lcpll@0301d02c {
>> + #clock-cells = <0>;
>> + compatible = "brcm,cygnus-lcpll-clk";
>> + reg = <0x0301d02c 0x1c>;
>> + clocks = <&osc>;
>> + };
>> +
>> + genpll: genpll@0301d000 {
>> + #clock-cells = <0>;
>> + compatible = "brcm,cygnus-genpll-clk";
>> + reg = <0x0301d000 0x2c>,
>> + <0x180AA024 0x4>,
>> + <0x0301C020 0x4>;
>> + clocks = <&osc>;
>> + };
>> +
>
> To be honest, I'm not too happy about the way you specify a single
> register for each clock as a global 'reg' property.
I'm not happy with this either. Will rework.
>
> Presumably each of these registers is part of an IP block that does
> multiple things, so it would be better to start out with a binding
> for each IP block. How many of these blocks are used for clocks, and
> what do they do?
Clocks are a little scattered in the chip and don't make a lot of sense
for easy software programming. Will look at how to change bindings so
they are flexible to work on other generations.
>
> Arnd
>

2014-10-10 19:12:39

by Scott Branden

[permalink] [raw]
Subject: Re: [PATCH V4 7/7] ARM: multi_v7_defconfig: Enable ARCH_BCM_CYGNUS config

On 14-10-10 02:59 AM, Arnd Bergmann wrote:
> On Thursday 09 October 2014 15:44:31 Scott Branden wrote:
>> Enabled Broadcom Cygnus SoC family in multi_v7_defconfig by using
>> CONFIG_ARCH_BCM_CYGNUS=y.
>>
>> Signed-off-by: Scott Branden <[email protected]>
>> ---
>> arch/arm/configs/multi_v7_defconfig | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
>> index 5fb95fb..d02f56d 100644
>> --- a/arch/arm/configs/multi_v7_defconfig
>> +++ b/arch/arm/configs/multi_v7_defconfig
>> @@ -17,6 +17,7 @@ CONFIG_MACH_ARMADA_38X=y
>> CONFIG_MACH_ARMADA_XP=y
>> CONFIG_MACH_DOVE=y
>> CONFIG_ARCH_BCM=y
>> +CONFIG_ARCH_BCM_CYGNUS=y
>> CONFIG_ARCH_BCM_MOBILE=y
>> CONFIG_ARCH_BCM_5301X=y
>> CONFIG_ARCH_BRCMSTB=y
>>
>
> Does this contain all the drivers you need that are enabled in cygnus_defconfig?
Will enable more - thanks for reminding.
>
> Arnd
>