Merge branch 'clk-iproc' into clk-next

* clk-iproc:
  clk: iproc: define Broadcom NS2 iProc clock binding
  clk: iproc: define Broadcom NSP iProc clock binding
  clk: ns2: add clock support for Broadcom Northstar 2 SoC
  clk: iproc: Separate status and control variables
  clk: iproc: Split off dig_filter
  clk: iproc: Add PLL base write function
  clk: nsp: add clock support for Broadcom Northstar Plus SoC
  clk: iproc: Add PWRCTRL support
  clk: cygnus: Convert all macros to all caps
  ARM: cygnus: fix link failures when CONFIG_COMMON_CLK_IPROC is disabled
This commit is contained in:
Stephen Boyd 2015-10-21 17:28:19 -07:00
commit f63d19ef52
12 changed files with 840 additions and 159 deletions

View File

@ -130,3 +130,81 @@ These clock IDs are defined in:
ch3_unused mipipll 4 BCM_CYGNUS_MIPIPLL_CH3_UNUSED ch3_unused mipipll 4 BCM_CYGNUS_MIPIPLL_CH3_UNUSED
ch4_unused mipipll 5 BCM_CYGNUS_MIPIPLL_CH4_UNUSED ch4_unused mipipll 5 BCM_CYGNUS_MIPIPLL_CH4_UNUSED
ch5_unused mipipll 6 BCM_CYGNUS_MIPIPLL_CH5_UNUSED ch5_unused mipipll 6 BCM_CYGNUS_MIPIPLL_CH5_UNUSED
Northstar and Northstar Plus
------
PLL and leaf clock compatible strings for Northstar and Northstar Plus are:
"brcm,nsp-armpll"
"brcm,nsp-genpll"
"brcm,nsp-lcpll0"
The following table defines the set of PLL/clock index and ID for Northstar and
Northstar Plus. These clock IDs are defined in:
"include/dt-bindings/clock/bcm-nsp.h"
Clock Source Index ID
--- ----- ----- ---------
crystal N/A N/A N/A
armpll crystal N/A N/A
genpll crystal 0 BCM_NSP_GENPLL
phy genpll 1 BCM_NSP_GENPLL_PHY_CLK
ethernetclk genpll 2 BCM_NSP_GENPLL_ENET_SW_CLK
usbclk genpll 3 BCM_NSP_GENPLL_USB_PHY_REF_CLK
iprocfast genpll 4 BCM_NSP_GENPLL_IPROCFAST_CLK
sata1 genpll 5 BCM_NSP_GENPLL_SATA1_CLK
sata2 genpll 6 BCM_NSP_GENPLL_SATA2_CLK
lcpll0 crystal 0 BCM_NSP_LCPLL0
pcie_phy lcpll0 1 BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK
sdio lcpll0 2 BCM_NSP_LCPLL0_SDIO_CLK
ddr_phy lcpll0 3 BCM_NSP_LCPLL0_DDR_PHY_CLK
Northstar 2
-----------
PLL and leaf clock compatible strings for Northstar 2 are:
"brcm,ns2-genpll-scr"
"brcm,ns2-genpll-sw"
"brcm,ns2-lcpll-ddr"
"brcm,ns2-lcpll-ports"
The following table defines the set of PLL/clock index and ID for Northstar 2.
These clock IDs are defined in:
"include/dt-bindings/clock/bcm-ns2.h"
Clock Source Index ID
--- ----- ----- ---------
crystal N/A N/A N/A
genpll_scr crystal 0 BCM_NS2_GENPLL_SCR
scr genpll_scr 1 BCM_NS2_GENPLL_SCR_SCR_CLK
fs genpll_scr 2 BCM_NS2_GENPLL_SCR_FS_CLK
audio_ref genpll_scr 3 BCM_NS2_GENPLL_SCR_AUDIO_CLK
ch3_unused genpll_scr 4 BCM_NS2_GENPLL_SCR_CH3_UNUSED
ch4_unused genpll_scr 5 BCM_NS2_GENPLL_SCR_CH4_UNUSED
ch5_unused genpll_scr 6 BCM_NS2_GENPLL_SCR_CH5_UNUSED
genpll_sw crystal 0 BCM_NS2_GENPLL_SW
rpe genpll_sw 1 BCM_NS2_GENPLL_SW_RPE_CLK
250 genpll_sw 2 BCM_NS2_GENPLL_SW_250_CLK
nic genpll_sw 3 BCM_NS2_GENPLL_SW_NIC_CLK
chimp genpll_sw 4 BCM_NS2_GENPLL_SW_CHIMP_CLK
port genpll_sw 5 BCM_NS2_GENPLL_SW_PORT_CLK
sdio genpll_sw 6 BCM_NS2_GENPLL_SW_SDIO_CLK
lcpll_ddr crystal 0 BCM_NS2_LCPLL_DDR
pcie_sata_usb lcpll_ddr 1 BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK
ddr lcpll_ddr 2 BCM_NS2_LCPLL_DDR_DDR_CLK
ch2_unused lcpll_ddr 3 BCM_NS2_LCPLL_DDR_CH2_UNUSED
ch3_unused lcpll_ddr 4 BCM_NS2_LCPLL_DDR_CH3_UNUSED
ch4_unused lcpll_ddr 5 BCM_NS2_LCPLL_DDR_CH4_UNUSED
ch5_unused lcpll_ddr 6 BCM_NS2_LCPLL_DDR_CH5_UNUSED
lcpll_ports crystal 0 BCM_NS2_LCPLL_PORTS
wan lcpll_ports 1 BCM_NS2_LCPLL_PORTS_WAN_CLK
rgmii lcpll_ports 2 BCM_NS2_LCPLL_PORTS_RGMII_CLK
ch2_unused lcpll_ports 3 BCM_NS2_LCPLL_PORTS_CH2_UNUSED
ch3_unused lcpll_ports 4 BCM_NS2_LCPLL_PORTS_CH3_UNUSED
ch4_unused lcpll_ports 5 BCM_NS2_LCPLL_PORTS_CH4_UNUSED
ch5_unused lcpll_ports 6 BCM_NS2_LCPLL_PORTS_CH5_UNUSED

View File

@ -14,7 +14,7 @@ config ARCH_BCM_IPROC
select HAVE_ARM_SCU if SMP select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP select HAVE_ARM_TWD if SMP
select ARM_GLOBAL_TIMER select ARM_GLOBAL_TIMER
select COMMON_CLK_IPROC
select CLKSRC_MMIO select CLKSRC_MMIO
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select ARM_AMBA select ARM_AMBA

View File

@ -48,7 +48,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_COMMON_CLK_AT91) += at91/
obj-$(CONFIG_ARCH_BCM) += bcm/ obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_ARCH_MXC) += imx/ obj-$(CONFIG_ARCH_MXC) += imx/

View File

@ -9,10 +9,8 @@ config CLK_BCM_KONA
in the BCM281xx and BCM21664 families. in the BCM281xx and BCM21664 families.
config COMMON_CLK_IPROC config COMMON_CLK_IPROC
bool "Broadcom iProc clock support" bool
depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on COMMON_CLK depends on COMMON_CLK
default ARCH_BCM_IPROC
help help
Enable common clock framework support for Broadcom SoCs Enable common clock framework support for Broadcom SoCs
based on the iProc architecture based on the iProc architecture

View File

@ -4,4 +4,7 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o
obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o
obj-$(CONFIG_ARCH_BCM_5301X) += clk-nsp.o

View File

@ -23,28 +23,30 @@
#include <dt-bindings/clock/bcm-cygnus.h> #include <dt-bindings/clock/bcm-cygnus.h>
#include "clk-iproc.h" #include "clk-iproc.h"
#define reg_val(o, s, w) { .offset = o, .shift = s, .width = w, } #define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
#define aon_val(o, pw, ps, is) { .offset = o, .pwr_width = pw, \ #define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
.pwr_shift = ps, .iso_shift = is } .pwr_shift = ps, .iso_shift = is }
#define sw_ctrl_val(o, s) { .offset = o, .shift = s, } #define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
#define asiu_div_val(o, es, hs, hw, ls, lw) \ #define ASIU_DIV_VAL(o, es, hs, hw, ls, lw) \
{ .offset = o, .en_shift = es, .high_shift = hs, \ { .offset = o, .en_shift = es, .high_shift = hs, \
.high_width = hw, .low_shift = ls, .low_width = lw } .high_width = hw, .low_shift = ls, .low_width = lw }
#define reset_val(o, rs, prs, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \ #define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
.reset_shift = rs, .p_reset_shift = prs, .ki_shift = kis, \ .p_reset_shift = prs }
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
.ka_width = kaw } .ka_width = kaw }
#define vco_ctrl_val(uo, lo) { .u_offset = uo, .l_offset = lo } #define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
#define enable_val(o, es, hs, bs) { .offset = o, .enable_shift = es, \ #define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
.hold_shift = hs, .bypass_shift = bs } .hold_shift = hs, .bypass_shift = bs }
#define asiu_gate_val(o, es) { .offset = o, .en_shift = es } #define ASIU_GATE_VAL(o, es) { .offset = o, .en_shift = es }
static void __init cygnus_armpll_init(struct device_node *node) static void __init cygnus_armpll_init(struct device_node *node)
{ {
@ -55,52 +57,53 @@ CLK_OF_DECLARE(cygnus_armpll, "brcm,cygnus-armpll", cygnus_armpll_init);
static const struct iproc_pll_ctrl genpll = { static const struct iproc_pll_ctrl genpll = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC | .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_PLL_NEEDS_SW_CFG, IPROC_CLK_PLL_NEEDS_SW_CFG,
.aon = aon_val(0x0, 2, 1, 0), .aon = AON_VAL(0x0, 2, 1, 0),
.reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 3), .reset = RESET_VAL(0x0, 11, 10),
.sw_ctrl = sw_ctrl_val(0x10, 31), .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
.ndiv_int = reg_val(0x10, 20, 10), .sw_ctrl = SW_CTRL_VAL(0x10, 31),
.ndiv_frac = reg_val(0x10, 0, 20), .ndiv_int = REG_VAL(0x10, 20, 10),
.pdiv = reg_val(0x14, 0, 4), .ndiv_frac = REG_VAL(0x10, 0, 20),
.vco_ctrl = vco_ctrl_val(0x18, 0x1c), .pdiv = REG_VAL(0x14, 0, 4),
.status = reg_val(0x28, 12, 1), .vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
.status = REG_VAL(0x28, 12, 1),
}; };
static const struct iproc_clk_ctrl genpll_clk[] = { static const struct iproc_clk_ctrl genpll_clk[] = {
[BCM_CYGNUS_GENPLL_AXI21_CLK] = { [BCM_CYGNUS_GENPLL_AXI21_CLK] = {
.channel = BCM_CYGNUS_GENPLL_AXI21_CLK, .channel = BCM_CYGNUS_GENPLL_AXI21_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x4, 6, 0, 12), .enable = ENABLE_VAL(0x4, 6, 0, 12),
.mdiv = reg_val(0x20, 0, 8), .mdiv = REG_VAL(0x20, 0, 8),
}, },
[BCM_CYGNUS_GENPLL_250MHZ_CLK] = { [BCM_CYGNUS_GENPLL_250MHZ_CLK] = {
.channel = BCM_CYGNUS_GENPLL_250MHZ_CLK, .channel = BCM_CYGNUS_GENPLL_250MHZ_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x4, 7, 1, 13), .enable = ENABLE_VAL(0x4, 7, 1, 13),
.mdiv = reg_val(0x20, 10, 8), .mdiv = REG_VAL(0x20, 10, 8),
}, },
[BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = { [BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = {
.channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK, .channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x4, 8, 2, 14), .enable = ENABLE_VAL(0x4, 8, 2, 14),
.mdiv = reg_val(0x20, 20, 8), .mdiv = REG_VAL(0x20, 20, 8),
}, },
[BCM_CYGNUS_GENPLL_ENET_SW_CLK] = { [BCM_CYGNUS_GENPLL_ENET_SW_CLK] = {
.channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK, .channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x4, 9, 3, 15), .enable = ENABLE_VAL(0x4, 9, 3, 15),
.mdiv = reg_val(0x24, 0, 8), .mdiv = REG_VAL(0x24, 0, 8),
}, },
[BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = { [BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = {
.channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK, .channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x4, 10, 4, 16), .enable = ENABLE_VAL(0x4, 10, 4, 16),
.mdiv = reg_val(0x24, 10, 8), .mdiv = REG_VAL(0x24, 10, 8),
}, },
[BCM_CYGNUS_GENPLL_CAN_CLK] = { [BCM_CYGNUS_GENPLL_CAN_CLK] = {
.channel = BCM_CYGNUS_GENPLL_CAN_CLK, .channel = BCM_CYGNUS_GENPLL_CAN_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x4, 11, 5, 17), .enable = ENABLE_VAL(0x4, 11, 5, 17),
.mdiv = reg_val(0x24, 20, 8), .mdiv = REG_VAL(0x24, 20, 8),
}, },
}; };
@ -113,51 +116,52 @@ CLK_OF_DECLARE(cygnus_genpll, "brcm,cygnus-genpll", cygnus_genpll_clk_init);
static const struct iproc_pll_ctrl lcpll0 = { static const struct iproc_pll_ctrl lcpll0 = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG, .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
.aon = aon_val(0x0, 2, 5, 4), .aon = AON_VAL(0x0, 2, 5, 4),
.reset = reset_val(0x0, 31, 30, 27, 3, 23, 4, 19, 4), .reset = RESET_VAL(0x0, 31, 30),
.sw_ctrl = sw_ctrl_val(0x4, 31), .dig_filter = DF_VAL(0x0, 27, 3, 23, 4, 19, 4),
.ndiv_int = reg_val(0x4, 16, 10), .sw_ctrl = SW_CTRL_VAL(0x4, 31),
.pdiv = reg_val(0x4, 26, 4), .ndiv_int = REG_VAL(0x4, 16, 10),
.vco_ctrl = vco_ctrl_val(0x10, 0x14), .pdiv = REG_VAL(0x4, 26, 4),
.status = reg_val(0x18, 12, 1), .vco_ctrl = VCO_CTRL_VAL(0x10, 0x14),
.status = REG_VAL(0x18, 12, 1),
}; };
static const struct iproc_clk_ctrl lcpll0_clk[] = { static const struct iproc_clk_ctrl lcpll0_clk[] = {
[BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = { [BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK, .channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x0, 7, 1, 13), .enable = ENABLE_VAL(0x0, 7, 1, 13),
.mdiv = reg_val(0x8, 0, 8), .mdiv = REG_VAL(0x8, 0, 8),
}, },
[BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = { [BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK, .channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x0, 8, 2, 14), .enable = ENABLE_VAL(0x0, 8, 2, 14),
.mdiv = reg_val(0x8, 10, 8), .mdiv = REG_VAL(0x8, 10, 8),
}, },
[BCM_CYGNUS_LCPLL0_SDIO_CLK] = { [BCM_CYGNUS_LCPLL0_SDIO_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_SDIO_CLK, .channel = BCM_CYGNUS_LCPLL0_SDIO_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x0, 9, 3, 15), .enable = ENABLE_VAL(0x0, 9, 3, 15),
.mdiv = reg_val(0x8, 20, 8), .mdiv = REG_VAL(0x8, 20, 8),
}, },
[BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = { [BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK, .channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x0, 10, 4, 16), .enable = ENABLE_VAL(0x0, 10, 4, 16),
.mdiv = reg_val(0xc, 0, 8), .mdiv = REG_VAL(0xc, 0, 8),
}, },
[BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = { [BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = {
.channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK, .channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x0, 11, 5, 17), .enable = ENABLE_VAL(0x0, 11, 5, 17),
.mdiv = reg_val(0xc, 10, 8), .mdiv = REG_VAL(0xc, 10, 8),
}, },
[BCM_CYGNUS_LCPLL0_CH5_UNUSED] = { [BCM_CYGNUS_LCPLL0_CH5_UNUSED] = {
.channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED, .channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED,
.flags = IPROC_CLK_AON, .flags = IPROC_CLK_AON,
.enable = enable_val(0x0, 12, 6, 18), .enable = ENABLE_VAL(0x0, 12, 6, 18),
.mdiv = reg_val(0xc, 20, 8), .mdiv = REG_VAL(0xc, 20, 8),
}, },
}; };
@ -189,52 +193,53 @@ static const struct iproc_pll_vco_param mipipll_vco_params[] = {
static const struct iproc_pll_ctrl mipipll = { static const struct iproc_pll_ctrl mipipll = {
.flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC | .flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_NEEDS_READ_BACK, IPROC_CLK_NEEDS_READ_BACK,
.aon = aon_val(0x0, 4, 17, 16), .aon = AON_VAL(0x0, 4, 17, 16),
.asiu = asiu_gate_val(0x0, 3), .asiu = ASIU_GATE_VAL(0x0, 3),
.reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 4), .reset = RESET_VAL(0x0, 11, 10),
.ndiv_int = reg_val(0x10, 20, 10), .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 4),
.ndiv_frac = reg_val(0x10, 0, 20), .ndiv_int = REG_VAL(0x10, 20, 10),
.pdiv = reg_val(0x14, 0, 4), .ndiv_frac = REG_VAL(0x10, 0, 20),
.vco_ctrl = vco_ctrl_val(0x18, 0x1c), .pdiv = REG_VAL(0x14, 0, 4),
.status = reg_val(0x28, 12, 1), .vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
.status = REG_VAL(0x28, 12, 1),
}; };
static const struct iproc_clk_ctrl mipipll_clk[] = { static const struct iproc_clk_ctrl mipipll_clk[] = {
[BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = { [BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED, .channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK, .flags = IPROC_CLK_NEEDS_READ_BACK,
.enable = enable_val(0x4, 12, 6, 18), .enable = ENABLE_VAL(0x4, 12, 6, 18),
.mdiv = reg_val(0x20, 0, 8), .mdiv = REG_VAL(0x20, 0, 8),
}, },
[BCM_CYGNUS_MIPIPLL_CH1_LCD] = { [BCM_CYGNUS_MIPIPLL_CH1_LCD] = {
.channel = BCM_CYGNUS_MIPIPLL_CH1_LCD, .channel = BCM_CYGNUS_MIPIPLL_CH1_LCD,
.flags = IPROC_CLK_NEEDS_READ_BACK, .flags = IPROC_CLK_NEEDS_READ_BACK,
.enable = enable_val(0x4, 13, 7, 19), .enable = ENABLE_VAL(0x4, 13, 7, 19),
.mdiv = reg_val(0x20, 10, 8), .mdiv = REG_VAL(0x20, 10, 8),
}, },
[BCM_CYGNUS_MIPIPLL_CH2_V3D] = { [BCM_CYGNUS_MIPIPLL_CH2_V3D] = {
.channel = BCM_CYGNUS_MIPIPLL_CH2_V3D, .channel = BCM_CYGNUS_MIPIPLL_CH2_V3D,
.flags = IPROC_CLK_NEEDS_READ_BACK, .flags = IPROC_CLK_NEEDS_READ_BACK,
.enable = enable_val(0x4, 14, 8, 20), .enable = ENABLE_VAL(0x4, 14, 8, 20),
.mdiv = reg_val(0x20, 20, 8), .mdiv = REG_VAL(0x20, 20, 8),
}, },
[BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = { [BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED, .channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK, .flags = IPROC_CLK_NEEDS_READ_BACK,
.enable = enable_val(0x4, 15, 9, 21), .enable = ENABLE_VAL(0x4, 15, 9, 21),
.mdiv = reg_val(0x24, 0, 8), .mdiv = REG_VAL(0x24, 0, 8),
}, },
[BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = { [BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED, .channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK, .flags = IPROC_CLK_NEEDS_READ_BACK,
.enable = enable_val(0x4, 16, 10, 22), .enable = ENABLE_VAL(0x4, 16, 10, 22),
.mdiv = reg_val(0x24, 10, 8), .mdiv = REG_VAL(0x24, 10, 8),
}, },
[BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = { [BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = {
.channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED, .channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED,
.flags = IPROC_CLK_NEEDS_READ_BACK, .flags = IPROC_CLK_NEEDS_READ_BACK,
.enable = enable_val(0x4, 17, 11, 23), .enable = ENABLE_VAL(0x4, 17, 11, 23),
.mdiv = reg_val(0x24, 20, 8), .mdiv = REG_VAL(0x24, 20, 8),
}, },
}; };
@ -247,15 +252,15 @@ static void __init cygnus_mipipll_clk_init(struct device_node *node)
CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init); CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init);
static const struct iproc_asiu_div asiu_div[] = { static const struct iproc_asiu_div asiu_div[] = {
[BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_div_val(0x0, 31, 16, 10, 0, 10), [BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_DIV_VAL(0x0, 31, 16, 10, 0, 10),
[BCM_CYGNUS_ASIU_ADC_CLK] = asiu_div_val(0x4, 31, 16, 10, 0, 10), [BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_DIV_VAL(0x4, 31, 16, 10, 0, 10),
[BCM_CYGNUS_ASIU_PWM_CLK] = asiu_div_val(0x8, 31, 16, 10, 0, 10), [BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_DIV_VAL(0x8, 31, 16, 10, 0, 10),
}; };
static const struct iproc_asiu_gate asiu_gate[] = { static const struct iproc_asiu_gate asiu_gate[] = {
[BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_gate_val(0x0, 7), [BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_GATE_VAL(0x0, 7),
[BCM_CYGNUS_ASIU_ADC_CLK] = asiu_gate_val(0x0, 9), [BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_GATE_VAL(0x0, 9),
[BCM_CYGNUS_ASIU_PWM_CLK] = asiu_gate_val(IPROC_CLK_INVALID_OFFSET, 0), [BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_GATE_VAL(IPROC_CLK_INVALID_OFFSET, 0),
}; };
static void __init cygnus_asiu_init(struct device_node *node) static void __init cygnus_asiu_init(struct device_node *node)

View File

@ -74,7 +74,8 @@ struct iproc_clk {
}; };
struct iproc_pll { struct iproc_pll {
void __iomem *pll_base; void __iomem *status_base;
void __iomem *control_base;
void __iomem *pwr_base; void __iomem *pwr_base;
void __iomem *asiu_base; void __iomem *asiu_base;
@ -127,7 +128,7 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
const struct iproc_pll_ctrl *ctrl = pll->ctrl; const struct iproc_pll_ctrl *ctrl = pll->ctrl;
for (i = 0; i < LOCK_DELAY; i++) { for (i = 0; i < LOCK_DELAY; i++) {
u32 val = readl(pll->pll_base + ctrl->status.offset); u32 val = readl(pll->status_base + ctrl->status.offset);
if (val & (1 << ctrl->status.shift)) if (val & (1 << ctrl->status.shift))
return 0; return 0;
@ -137,6 +138,18 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
return -EIO; return -EIO;
} }
static void iproc_pll_write(const struct iproc_pll *pll, void __iomem *base,
const u32 offset, u32 val)
{
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
writel(val, base + offset);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
(base == pll->status_base || base == pll->control_base)))
val = readl(base + offset);
}
static void __pll_disable(struct iproc_pll *pll) static void __pll_disable(struct iproc_pll *pll)
{ {
const struct iproc_pll_ctrl *ctrl = pll->ctrl; const struct iproc_pll_ctrl *ctrl = pll->ctrl;
@ -145,17 +158,25 @@ static void __pll_disable(struct iproc_pll *pll)
if (ctrl->flags & IPROC_CLK_PLL_ASIU) { if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
val = readl(pll->asiu_base + ctrl->asiu.offset); val = readl(pll->asiu_base + ctrl->asiu.offset);
val &= ~(1 << ctrl->asiu.en_shift); val &= ~(1 << ctrl->asiu.en_shift);
writel(val, pll->asiu_base + ctrl->asiu.offset); iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
} }
/* latch input value so core power can be shut down */ if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
val = readl(pll->pwr_base + ctrl->aon.offset); val = readl(pll->control_base + ctrl->aon.offset);
val |= (1 << ctrl->aon.iso_shift); val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
writel(val, pll->pwr_base + ctrl->aon.offset); iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
}
/* power down the core */ if (pll->pwr_base) {
val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift); /* latch input value so core power can be shut down */
writel(val, pll->pwr_base + ctrl->aon.offset); val = readl(pll->pwr_base + ctrl->aon.offset);
val |= 1 << ctrl->aon.iso_shift;
iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
/* power down the core */
val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
}
} }
static int __pll_enable(struct iproc_pll *pll) static int __pll_enable(struct iproc_pll *pll)
@ -163,17 +184,25 @@ static int __pll_enable(struct iproc_pll *pll)
const struct iproc_pll_ctrl *ctrl = pll->ctrl; const struct iproc_pll_ctrl *ctrl = pll->ctrl;
u32 val; u32 val;
/* power up the PLL and make sure it's not latched */ if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
val = readl(pll->pwr_base + ctrl->aon.offset); val = readl(pll->control_base + ctrl->aon.offset);
val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift; val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
val &= ~(1 << ctrl->aon.iso_shift); iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
writel(val, pll->pwr_base + ctrl->aon.offset); }
if (pll->pwr_base) {
/* power up the PLL and make sure it's not latched */
val = readl(pll->pwr_base + ctrl->aon.offset);
val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
val &= ~(1 << ctrl->aon.iso_shift);
iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
}
/* certain PLLs also need to be ungated from the ASIU top level */ /* certain PLLs also need to be ungated from the ASIU top level */
if (ctrl->flags & IPROC_CLK_PLL_ASIU) { if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
val = readl(pll->asiu_base + ctrl->asiu.offset); val = readl(pll->asiu_base + ctrl->asiu.offset);
val |= (1 << ctrl->asiu.en_shift); val |= (1 << ctrl->asiu.en_shift);
writel(val, pll->asiu_base + ctrl->asiu.offset); iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
} }
return 0; return 0;
@ -185,11 +214,9 @@ static void __pll_put_in_reset(struct iproc_pll *pll)
const struct iproc_pll_ctrl *ctrl = pll->ctrl; const struct iproc_pll_ctrl *ctrl = pll->ctrl;
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
val = readl(pll->pll_base + reset->offset); val = readl(pll->control_base + reset->offset);
val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift); val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
writel(val, pll->pll_base + reset->offset); iproc_pll_write(pll, pll->control_base, reset->offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + reset->offset);
} }
static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp, static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
@ -198,17 +225,19 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
u32 val; u32 val;
const struct iproc_pll_ctrl *ctrl = pll->ctrl; const struct iproc_pll_ctrl *ctrl = pll->ctrl;
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter;
val = readl(pll->pll_base + reset->offset); val = readl(pll->control_base + dig_filter->offset);
val &= ~(bit_mask(reset->ki_width) << reset->ki_shift | val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift |
bit_mask(reset->kp_width) << reset->kp_shift | bit_mask(dig_filter->kp_width) << dig_filter->kp_shift |
bit_mask(reset->ka_width) << reset->ka_shift); bit_mask(dig_filter->ka_width) << dig_filter->ka_shift);
val |= ki << reset->ki_shift | kp << reset->kp_shift | val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift |
ka << reset->ka_shift; ka << dig_filter->ka_shift;
iproc_pll_write(pll, pll->control_base, dig_filter->offset, val);
val = readl(pll->control_base + reset->offset);
val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift; val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
writel(val, pll->pll_base + reset->offset); iproc_pll_write(pll, pll->control_base, reset->offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + reset->offset);
} }
static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
@ -263,10 +292,9 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
/* put PLL in reset */ /* put PLL in reset */
__pll_put_in_reset(pll); __pll_put_in_reset(pll);
writel(0, pll->pll_base + ctrl->vco_ctrl.u_offset); iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->vco_ctrl.u_offset); val = readl(pll->control_base + ctrl->vco_ctrl.l_offset);
val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
if (rate >= VCO_LOW && rate < VCO_MID) if (rate >= VCO_LOW && rate < VCO_MID)
val |= (1 << PLL_VCO_LOW_SHIFT); val |= (1 << PLL_VCO_LOW_SHIFT);
@ -276,36 +304,29 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
else else
val |= (1 << PLL_VCO_HIGH_SHIFT); val |= (1 << PLL_VCO_HIGH_SHIFT);
writel(val, pll->pll_base + ctrl->vco_ctrl.l_offset); iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
/* program integer part of NDIV */ /* program integer part of NDIV */
val = readl(pll->pll_base + ctrl->ndiv_int.offset); val = readl(pll->control_base + ctrl->ndiv_int.offset);
val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift); val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
val |= vco->ndiv_int << ctrl->ndiv_int.shift; val |= vco->ndiv_int << ctrl->ndiv_int.shift;
writel(val, pll->pll_base + ctrl->ndiv_int.offset); iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->ndiv_int.offset);
/* program fractional part of NDIV */ /* program fractional part of NDIV */
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
val = readl(pll->pll_base + ctrl->ndiv_frac.offset); val = readl(pll->control_base + ctrl->ndiv_frac.offset);
val &= ~(bit_mask(ctrl->ndiv_frac.width) << val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
ctrl->ndiv_frac.shift); ctrl->ndiv_frac.shift);
val |= vco->ndiv_frac << ctrl->ndiv_frac.shift; val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
writel(val, pll->pll_base + ctrl->ndiv_frac.offset); iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset,
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK)) val);
readl(pll->pll_base + ctrl->ndiv_frac.offset);
} }
/* program PDIV */ /* program PDIV */
val = readl(pll->pll_base + ctrl->pdiv.offset); val = readl(pll->control_base + ctrl->pdiv.offset);
val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift); val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
val |= vco->pdiv << ctrl->pdiv.shift; val |= vco->pdiv << ctrl->pdiv.shift;
writel(val, pll->pll_base + ctrl->pdiv.offset); iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->pdiv.offset);
__pll_bring_out_reset(pll, kp, ka, ki); __pll_bring_out_reset(pll, kp, ka, ki);
@ -352,7 +373,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
return 0; return 0;
/* PLL needs to be locked */ /* PLL needs to be locked */
val = readl(pll->pll_base + ctrl->status.offset); val = readl(pll->status_base + ctrl->status.offset);
if ((val & (1 << ctrl->status.shift)) == 0) { if ((val & (1 << ctrl->status.shift)) == 0) {
clk->rate = 0; clk->rate = 0;
return 0; return 0;
@ -363,19 +384,19 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
* *
* ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv) * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
*/ */
val = readl(pll->pll_base + ctrl->ndiv_int.offset); val = readl(pll->control_base + ctrl->ndiv_int.offset);
ndiv_int = (val >> ctrl->ndiv_int.shift) & ndiv_int = (val >> ctrl->ndiv_int.shift) &
bit_mask(ctrl->ndiv_int.width); bit_mask(ctrl->ndiv_int.width);
ndiv = ndiv_int << 20; ndiv = ndiv_int << 20;
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
val = readl(pll->pll_base + ctrl->ndiv_frac.offset); val = readl(pll->control_base + ctrl->ndiv_frac.offset);
ndiv_frac = (val >> ctrl->ndiv_frac.shift) & ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
bit_mask(ctrl->ndiv_frac.width); bit_mask(ctrl->ndiv_frac.width);
ndiv += ndiv_frac; ndiv += ndiv_frac;
} }
val = readl(pll->pll_base + ctrl->pdiv.offset); val = readl(pll->control_base + ctrl->pdiv.offset);
pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
clk->rate = (ndiv * parent_rate) >> 20; clk->rate = (ndiv * parent_rate) >> 20;
@ -440,16 +461,14 @@ static int iproc_clk_enable(struct clk_hw *hw)
u32 val; u32 val;
/* channel enable is active low */ /* channel enable is active low */
val = readl(pll->pll_base + ctrl->enable.offset); val = readl(pll->control_base + ctrl->enable.offset);
val &= ~(1 << ctrl->enable.enable_shift); val &= ~(1 << ctrl->enable.enable_shift);
writel(val, pll->pll_base + ctrl->enable.offset); iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
/* also make sure channel is not held */ /* also make sure channel is not held */
val = readl(pll->pll_base + ctrl->enable.offset); val = readl(pll->control_base + ctrl->enable.offset);
val &= ~(1 << ctrl->enable.hold_shift); val &= ~(1 << ctrl->enable.hold_shift);
writel(val, pll->pll_base + ctrl->enable.offset); iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->enable.offset);
return 0; return 0;
} }
@ -464,11 +483,9 @@ static void iproc_clk_disable(struct clk_hw *hw)
if (ctrl->flags & IPROC_CLK_AON) if (ctrl->flags & IPROC_CLK_AON)
return; return;
val = readl(pll->pll_base + ctrl->enable.offset); val = readl(pll->control_base + ctrl->enable.offset);
val |= 1 << ctrl->enable.enable_shift; val |= 1 << ctrl->enable.enable_shift;
writel(val, pll->pll_base + ctrl->enable.offset); iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->enable.offset);
} }
static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
@ -483,7 +500,7 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
if (parent_rate == 0) if (parent_rate == 0)
return 0; return 0;
val = readl(pll->pll_base + ctrl->mdiv.offset); val = readl(pll->control_base + ctrl->mdiv.offset);
mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width); mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
if (mdiv == 0) if (mdiv == 0)
mdiv = 256; mdiv = 256;
@ -530,16 +547,14 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
if (div > 256) if (div > 256)
return -EINVAL; return -EINVAL;
val = readl(pll->pll_base + ctrl->mdiv.offset); val = readl(pll->control_base + ctrl->mdiv.offset);
if (div == 256) { if (div == 256) {
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
} else { } else {
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
val |= div << ctrl->mdiv.shift; val |= div << ctrl->mdiv.shift;
} }
writel(val, pll->pll_base + ctrl->mdiv.offset); iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val);
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
readl(pll->pll_base + ctrl->mdiv.offset);
clk->rate = parent_rate / div; clk->rate = parent_rate / div;
return 0; return 0;
@ -564,11 +579,10 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) { if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
u32 val; u32 val;
val = readl(pll->pll_base + ctrl->sw_ctrl.offset); val = readl(pll->control_base + ctrl->sw_ctrl.offset);
val |= BIT(ctrl->sw_ctrl.shift); val |= BIT(ctrl->sw_ctrl.shift);
writel(val, pll->pll_base + ctrl->sw_ctrl.offset); iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset,
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK)) val);
readl(pll->pll_base + ctrl->sw_ctrl.offset);
} }
} }
@ -603,13 +617,12 @@ void __init iproc_pll_clk_setup(struct device_node *node,
if (WARN_ON(!pll->clks)) if (WARN_ON(!pll->clks))
goto err_clks; goto err_clks;
pll->pll_base = of_iomap(node, 0); pll->control_base = of_iomap(node, 0);
if (WARN_ON(!pll->pll_base)) if (WARN_ON(!pll->control_base))
goto err_pll_iomap; goto err_pll_iomap;
/* Some SoCs do not require the pwr_base, thus failing is not fatal */
pll->pwr_base = of_iomap(node, 1); pll->pwr_base = of_iomap(node, 1);
if (WARN_ON(!pll->pwr_base))
goto err_pwr_iomap;
/* some PLLs require gating control at the top ASIU level */ /* some PLLs require gating control at the top ASIU level */
if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) { if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
@ -618,6 +631,16 @@ void __init iproc_pll_clk_setup(struct device_node *node,
goto err_asiu_iomap; goto err_asiu_iomap;
} }
if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) {
/* Some SoCs have a split status/control. If this does not
* exist, assume they are unified.
*/
pll->status_base = of_iomap(node, 2);
if (!pll->status_base)
goto err_status_iomap;
} else
pll->status_base = pll->control_base;
/* initialize and register the PLL itself */ /* initialize and register the PLL itself */
pll->ctrl = pll_ctrl; pll->ctrl = pll_ctrl;
@ -688,14 +711,18 @@ err_clk_register:
clk_unregister(pll->clk_data.clks[i]); clk_unregister(pll->clk_data.clks[i]);
err_pll_register: err_pll_register:
if (pll->status_base != pll->control_base)
iounmap(pll->status_base);
err_status_iomap:
if (pll->asiu_base) if (pll->asiu_base)
iounmap(pll->asiu_base); iounmap(pll->asiu_base);
err_asiu_iomap: err_asiu_iomap:
iounmap(pll->pwr_base); if (pll->pwr_base)
iounmap(pll->pwr_base);
err_pwr_iomap: iounmap(pll->control_base);
iounmap(pll->pll_base);
err_pll_iomap: err_pll_iomap:
kfree(pll->clks); kfree(pll->clks);

View File

@ -48,6 +48,18 @@
*/ */
#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4) #define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
/*
* Some PLLs use a different way to control clock power, via the PWRDWN bit in
* the PLL control register
*/
#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
/*
* Some PLLs have separate registers for Status and Control. Identify this to
* let the driver know if additional registers need to be used
*/
#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
/* /*
* Parameters for VCO frequency configuration * Parameters for VCO frequency configuration
* *
@ -88,12 +100,19 @@ struct iproc_pll_aon_pwr_ctrl {
}; };
/* /*
* Control of the PLL reset, with Ki, Kp, and Ka parameters * Control of the PLL reset
*/ */
struct iproc_pll_reset_ctrl { struct iproc_pll_reset_ctrl {
unsigned int offset; unsigned int offset;
unsigned int reset_shift; unsigned int reset_shift;
unsigned int p_reset_shift; unsigned int p_reset_shift;
};
/*
* Control of the Ki, Kp, and Ka parameters
*/
struct iproc_pll_dig_filter_ctrl {
unsigned int offset;
unsigned int ki_shift; unsigned int ki_shift;
unsigned int ki_width; unsigned int ki_width;
unsigned int kp_shift; unsigned int kp_shift;
@ -123,6 +142,7 @@ struct iproc_pll_ctrl {
struct iproc_pll_aon_pwr_ctrl aon; struct iproc_pll_aon_pwr_ctrl aon;
struct iproc_asiu_gate asiu; struct iproc_asiu_gate asiu;
struct iproc_pll_reset_ctrl reset; struct iproc_pll_reset_ctrl reset;
struct iproc_pll_dig_filter_ctrl dig_filter;
struct iproc_pll_sw_ctrl sw_ctrl; struct iproc_pll_sw_ctrl sw_ctrl;
struct iproc_clk_reg_op ndiv_int; struct iproc_clk_reg_op ndiv_int;
struct iproc_clk_reg_op ndiv_frac; struct iproc_clk_reg_op ndiv_frac;

288
drivers/clk/bcm/clk-ns2.c Normal file
View File

@ -0,0 +1,288 @@
/*
* Copyright (C) 2015 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it 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/of_address.h>
#include <dt-bindings/clock/bcm-ns2.h>
#include "clk-iproc.h"
#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
.pwr_shift = ps, .iso_shift = is }
#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
.p_reset_shift = prs }
#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
.ka_width = kaw }
#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
.hold_shift = hs, .bypass_shift = bs }
static const struct iproc_pll_ctrl genpll_scr = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
.aon = AON_VAL(0x0, 1, 15, 12),
.reset = RESET_VAL(0x4, 2, 1),
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
.ndiv_int = REG_VAL(0x8, 4, 10),
.pdiv = REG_VAL(0x8, 0, 4),
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
.status = REG_VAL(0x0, 27, 1),
};
static const struct iproc_clk_ctrl genpll_scr_clk[] = {
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
* in NS2. However, it doesn't appear to be used anywhere, so setting
* it to 0.
*/
[BCM_NS2_GENPLL_SCR_SCR_CLK] = {
.channel = BCM_NS2_GENPLL_SCR_SCR_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 18, 12, 0),
.mdiv = REG_VAL(0x18, 0, 8),
},
[BCM_NS2_GENPLL_SCR_FS_CLK] = {
.channel = BCM_NS2_GENPLL_SCR_FS_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 19, 13, 0),
.mdiv = REG_VAL(0x18, 8, 8),
},
[BCM_NS2_GENPLL_SCR_AUDIO_CLK] = {
.channel = BCM_NS2_GENPLL_SCR_AUDIO_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 20, 14, 0),
.mdiv = REG_VAL(0x14, 0, 8),
},
[BCM_NS2_GENPLL_SCR_CH3_UNUSED] = {
.channel = BCM_NS2_GENPLL_SCR_CH3_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 21, 15, 0),
.mdiv = REG_VAL(0x14, 8, 8),
},
[BCM_NS2_GENPLL_SCR_CH4_UNUSED] = {
.channel = BCM_NS2_GENPLL_SCR_CH4_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 22, 16, 0),
.mdiv = REG_VAL(0x14, 16, 8),
},
[BCM_NS2_GENPLL_SCR_CH5_UNUSED] = {
.channel = BCM_NS2_GENPLL_SCR_CH5_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 23, 17, 0),
.mdiv = REG_VAL(0x14, 24, 8),
},
};
static void __init ns2_genpll_scr_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &genpll_scr, NULL, 0, genpll_scr_clk,
ARRAY_SIZE(genpll_scr_clk));
}
CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
ns2_genpll_scr_clk_init);
static const struct iproc_pll_ctrl genpll_sw = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
.aon = AON_VAL(0x0, 2, 9, 8),
.reset = RESET_VAL(0x4, 2, 1),
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
.ndiv_int = REG_VAL(0x8, 4, 10),
.pdiv = REG_VAL(0x8, 0, 4),
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
.status = REG_VAL(0x0, 13, 1),
};
static const struct iproc_clk_ctrl genpll_sw_clk[] = {
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
* in NS2. However, it doesn't appear to be used anywhere, so setting
* it to 0.
*/
[BCM_NS2_GENPLL_SW_RPE_CLK] = {
.channel = BCM_NS2_GENPLL_SW_RPE_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 18, 12, 0),
.mdiv = REG_VAL(0x18, 0, 8),
},
[BCM_NS2_GENPLL_SW_250_CLK] = {
.channel = BCM_NS2_GENPLL_SW_250_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 19, 13, 0),
.mdiv = REG_VAL(0x18, 8, 8),
},
[BCM_NS2_GENPLL_SW_NIC_CLK] = {
.channel = BCM_NS2_GENPLL_SW_NIC_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 20, 14, 0),
.mdiv = REG_VAL(0x14, 0, 8),
},
[BCM_NS2_GENPLL_SW_CHIMP_CLK] = {
.channel = BCM_NS2_GENPLL_SW_CHIMP_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 21, 15, 0),
.mdiv = REG_VAL(0x14, 8, 8),
},
[BCM_NS2_GENPLL_SW_PORT_CLK] = {
.channel = BCM_NS2_GENPLL_SW_PORT_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 22, 16, 0),
.mdiv = REG_VAL(0x14, 16, 8),
},
[BCM_NS2_GENPLL_SW_SDIO_CLK] = {
.channel = BCM_NS2_GENPLL_SW_SDIO_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 23, 17, 0),
.mdiv = REG_VAL(0x14, 24, 8),
},
};
static void __init ns2_genpll_sw_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &genpll_sw, NULL, 0, genpll_sw_clk,
ARRAY_SIZE(genpll_sw_clk));
}
CLK_OF_DECLARE(ns2_genpll_sw_clk, "brcm,ns2-genpll-sw",
ns2_genpll_sw_clk_init);
static const struct iproc_pll_ctrl lcpll_ddr = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
.aon = AON_VAL(0x0, 2, 1, 0),
.reset = RESET_VAL(0x4, 2, 1),
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
.ndiv_int = REG_VAL(0x8, 4, 10),
.pdiv = REG_VAL(0x8, 0, 4),
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
.status = REG_VAL(0x0, 0, 1),
};
static const struct iproc_clk_ctrl lcpll_ddr_clk[] = {
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
* in NS2. However, it doesn't appear to be used anywhere, so setting
* it to 0.
*/
[BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK] = {
.channel = BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 18, 12, 0),
.mdiv = REG_VAL(0x14, 0, 8),
},
[BCM_NS2_LCPLL_DDR_DDR_CLK] = {
.channel = BCM_NS2_LCPLL_DDR_DDR_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 19, 13, 0),
.mdiv = REG_VAL(0x14, 8, 8),
},
[BCM_NS2_LCPLL_DDR_CH2_UNUSED] = {
.channel = BCM_NS2_LCPLL_DDR_CH2_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 20, 14, 0),
.mdiv = REG_VAL(0x10, 0, 8),
},
[BCM_NS2_LCPLL_DDR_CH3_UNUSED] = {
.channel = BCM_NS2_LCPLL_DDR_CH3_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 21, 15, 0),
.mdiv = REG_VAL(0x10, 8, 8),
},
[BCM_NS2_LCPLL_DDR_CH4_UNUSED] = {
.channel = BCM_NS2_LCPLL_DDR_CH4_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 22, 16, 0),
.mdiv = REG_VAL(0x10, 16, 8),
},
[BCM_NS2_LCPLL_DDR_CH5_UNUSED] = {
.channel = BCM_NS2_LCPLL_DDR_CH5_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 23, 17, 0),
.mdiv = REG_VAL(0x10, 24, 8),
},
};
static void __init ns2_lcpll_ddr_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &lcpll_ddr, NULL, 0, lcpll_ddr_clk,
ARRAY_SIZE(lcpll_ddr_clk));
}
CLK_OF_DECLARE(ns2_lcpll_ddr_clk, "brcm,ns2-lcpll-ddr",
ns2_lcpll_ddr_clk_init);
static const struct iproc_pll_ctrl lcpll_ports = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
.aon = AON_VAL(0x0, 2, 5, 4),
.reset = RESET_VAL(0x4, 2, 1),
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
.ndiv_int = REG_VAL(0x8, 4, 10),
.pdiv = REG_VAL(0x8, 0, 4),
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
.status = REG_VAL(0x0, 0, 1),
};
static const struct iproc_clk_ctrl lcpll_ports_clk[] = {
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
* in NS2. However, it doesn't appear to be used anywhere, so setting
* it to 0.
*/
[BCM_NS2_LCPLL_PORTS_WAN_CLK] = {
.channel = BCM_NS2_LCPLL_PORTS_WAN_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 18, 12, 0),
.mdiv = REG_VAL(0x14, 0, 8),
},
[BCM_NS2_LCPLL_PORTS_RGMII_CLK] = {
.channel = BCM_NS2_LCPLL_PORTS_RGMII_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 19, 13, 0),
.mdiv = REG_VAL(0x14, 8, 8),
},
[BCM_NS2_LCPLL_PORTS_CH2_UNUSED] = {
.channel = BCM_NS2_LCPLL_PORTS_CH2_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 20, 14, 0),
.mdiv = REG_VAL(0x10, 0, 8),
},
[BCM_NS2_LCPLL_PORTS_CH3_UNUSED] = {
.channel = BCM_NS2_LCPLL_PORTS_CH3_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 21, 15, 0),
.mdiv = REG_VAL(0x10, 8, 8),
},
[BCM_NS2_LCPLL_PORTS_CH4_UNUSED] = {
.channel = BCM_NS2_LCPLL_PORTS_CH4_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 22, 16, 0),
.mdiv = REG_VAL(0x10, 16, 8),
},
[BCM_NS2_LCPLL_PORTS_CH5_UNUSED] = {
.channel = BCM_NS2_LCPLL_PORTS_CH5_UNUSED,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 23, 17, 0),
.mdiv = REG_VAL(0x10, 24, 8),
},
};
static void __init ns2_lcpll_ports_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &lcpll_ports, NULL, 0, lcpll_ports_clk,
ARRAY_SIZE(lcpll_ports_clk));
}
CLK_OF_DECLARE(ns2_lcpll_ports_clk, "brcm,ns2-lcpll-ports",
ns2_lcpll_ports_clk_init);

139
drivers/clk/bcm/clk-nsp.c Normal file
View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2015 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it 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/of_address.h>
#include <dt-bindings/clock/bcm-nsp.h>
#include "clk-iproc.h"
#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
.pwr_shift = ps, .iso_shift = is }
#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
.p_reset_shift = prs }
#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
.ka_width = kaw }
#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
.hold_shift = hs, .bypass_shift = bs }
static void __init nsp_armpll_init(struct device_node *node)
{
iproc_armpll_setup(node);
}
CLK_OF_DECLARE(nsp_armpll, "brcm,nsp-armpll", nsp_armpll_init);
static const struct iproc_pll_ctrl genpll = {
.flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
.aon = AON_VAL(0x0, 1, 12, 0),
.reset = RESET_VAL(0x0, 11, 10),
.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
.ndiv_int = REG_VAL(0x14, 20, 10),
.ndiv_frac = REG_VAL(0x14, 0, 20),
.pdiv = REG_VAL(0x18, 24, 3),
.status = REG_VAL(0x20, 12, 1),
};
static const struct iproc_clk_ctrl genpll_clk[] = {
[BCM_NSP_GENPLL_PHY_CLK] = {
.channel = BCM_NSP_GENPLL_PHY_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 12, 6, 18),
.mdiv = REG_VAL(0x18, 16, 8),
},
[BCM_NSP_GENPLL_ENET_SW_CLK] = {
.channel = BCM_NSP_GENPLL_ENET_SW_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 13, 7, 19),
.mdiv = REG_VAL(0x18, 8, 8),
},
[BCM_NSP_GENPLL_USB_PHY_REF_CLK] = {
.channel = BCM_NSP_GENPLL_USB_PHY_REF_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 14, 8, 20),
.mdiv = REG_VAL(0x18, 0, 8),
},
[BCM_NSP_GENPLL_IPROCFAST_CLK] = {
.channel = BCM_NSP_GENPLL_IPROCFAST_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 15, 9, 21),
.mdiv = REG_VAL(0x1c, 16, 8),
},
[BCM_NSP_GENPLL_SATA1_CLK] = {
.channel = BCM_NSP_GENPLL_SATA1_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 16, 10, 22),
.mdiv = REG_VAL(0x1c, 8, 8),
},
[BCM_NSP_GENPLL_SATA2_CLK] = {
.channel = BCM_NSP_GENPLL_SATA2_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 17, 11, 23),
.mdiv = REG_VAL(0x1c, 0, 8),
},
};
static void __init nsp_genpll_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &genpll, NULL, 0, genpll_clk,
ARRAY_SIZE(genpll_clk));
}
CLK_OF_DECLARE(nsp_genpll_clk, "brcm,nsp-genpll", nsp_genpll_clk_init);
static const struct iproc_pll_ctrl lcpll0 = {
.flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
.aon = AON_VAL(0x0, 1, 24, 0),
.reset = RESET_VAL(0x0, 23, 22),
.dig_filter = DF_VAL(0x0, 16, 3, 12, 4, 19, 4),
.ndiv_int = REG_VAL(0x4, 20, 8),
.ndiv_frac = REG_VAL(0x4, 0, 20),
.pdiv = REG_VAL(0x4, 28, 3),
.status = REG_VAL(0x10, 12, 1),
};
static const struct iproc_clk_ctrl lcpll0_clk[] = {
[BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK] = {
.channel = BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 6, 3, 9),
.mdiv = REG_VAL(0x8, 24, 8),
},
[BCM_NSP_LCPLL0_SDIO_CLK] = {
.channel = BCM_NSP_LCPLL0_SDIO_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 7, 4, 10),
.mdiv = REG_VAL(0x8, 16, 8),
},
[BCM_NSP_LCPLL0_DDR_PHY_CLK] = {
.channel = BCM_NSP_LCPLL0_DDR_PHY_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 8, 5, 11),
.mdiv = REG_VAL(0x8, 8, 8),
},
};
static void __init nsp_lcpll0_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &lcpll0, NULL, 0, lcpll0_clk,
ARRAY_SIZE(lcpll0_clk));
}
CLK_OF_DECLARE(nsp_lcpll0_clk, "brcm,nsp-lcpll0", nsp_lcpll0_clk_init);

View File

@ -0,0 +1,72 @@
/*
* BSD LICENSE
*
* Copyright(c) 2015 Broadcom Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Broadcom Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CLOCK_BCM_NS2_H
#define _CLOCK_BCM_NS2_H
/* GENPLL SCR clock channel ID */
#define BCM_NS2_GENPLL_SCR 0
#define BCM_NS2_GENPLL_SCR_SCR_CLK 1
#define BCM_NS2_GENPLL_SCR_FS_CLK 2
#define BCM_NS2_GENPLL_SCR_AUDIO_CLK 3
#define BCM_NS2_GENPLL_SCR_CH3_UNUSED 4
#define BCM_NS2_GENPLL_SCR_CH4_UNUSED 5
#define BCM_NS2_GENPLL_SCR_CH5_UNUSED 6
/* GENPLL SW clock channel ID */
#define BCM_NS2_GENPLL_SW 0
#define BCM_NS2_GENPLL_SW_RPE_CLK 1
#define BCM_NS2_GENPLL_SW_250_CLK 2
#define BCM_NS2_GENPLL_SW_NIC_CLK 3
#define BCM_NS2_GENPLL_SW_CHIMP_CLK 4
#define BCM_NS2_GENPLL_SW_PORT_CLK 5
#define BCM_NS2_GENPLL_SW_SDIO_CLK 6
/* LCPLL DDR clock channel ID */
#define BCM_NS2_LCPLL_DDR 0
#define BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK 1
#define BCM_NS2_LCPLL_DDR_DDR_CLK 2
#define BCM_NS2_LCPLL_DDR_CH2_UNUSED 3
#define BCM_NS2_LCPLL_DDR_CH3_UNUSED 4
#define BCM_NS2_LCPLL_DDR_CH4_UNUSED 5
#define BCM_NS2_LCPLL_DDR_CH5_UNUSED 6
/* LCPLL PORTS clock channel ID */
#define BCM_NS2_LCPLL_PORTS 0
#define BCM_NS2_LCPLL_PORTS_WAN_CLK 1
#define BCM_NS2_LCPLL_PORTS_RGMII_CLK 2
#define BCM_NS2_LCPLL_PORTS_CH2_UNUSED 3
#define BCM_NS2_LCPLL_PORTS_CH3_UNUSED 4
#define BCM_NS2_LCPLL_PORTS_CH4_UNUSED 5
#define BCM_NS2_LCPLL_PORTS_CH5_UNUSED 6
#endif /* _CLOCK_BCM_NS2_H */

View File

@ -0,0 +1,51 @@
/*
* BSD LICENSE
*
* Copyright(c) 2015 Broadcom Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Broadcom Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CLOCK_BCM_NSP_H
#define _CLOCK_BCM_NSP_H
/* GENPLL clock channel ID */
#define BCM_NSP_GENPLL 0
#define BCM_NSP_GENPLL_PHY_CLK 1
#define BCM_NSP_GENPLL_ENET_SW_CLK 2
#define BCM_NSP_GENPLL_USB_PHY_REF_CLK 3
#define BCM_NSP_GENPLL_IPROCFAST_CLK 4
#define BCM_NSP_GENPLL_SATA1_CLK 5
#define BCM_NSP_GENPLL_SATA2_CLK 6
/* LCPLL0 clock channel ID */
#define BCM_NSP_LCPLL0 0
#define BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK 1
#define BCM_NSP_LCPLL0_SDIO_CLK 2
#define BCM_NSP_LCPLL0_DDR_PHY_CLK 3
#endif /* _CLOCK_BCM_NSP_H */