* [PATCH v1 1/4] dt-bindings: add bindings for px30 clock controller
From: Elaine Zhang @ 2018-06-07 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528340786-462-1-git-send-email-zhangqing@rock-chips.com>
Add devicetree bindings for Rockchip cru which found on
Rockchip SoCs.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
.../bindings/clock/rockchip,px30-cru.txt | 67 ++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt
diff --git a/Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt
new file mode 100644
index 000000000000..af5a45b680d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt
@@ -0,0 +1,67 @@
+* Rockchip PX30 Clock and Reset Unit
+
+The PX30 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: PMU for CRU should be "rockchip,px30-pmu-cru"
+- compatible: CRU should be "rockchip,px30-cru"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+ If missing, pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/px30-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "i2sx_clkin" - external I2S clock - optional,
+ - "gmac_clkin" - external GMAC clock - optional
+
+Example: Clock controller node:
+
+ pmucru: pmu-clock-controller at ff2bc000 {
+ compatible = "rockchip,px30-pmucru";
+ reg = <0x0 0xff2bc000 0x0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ cru: clock-controller at ff2b0000 {
+ compatible = "rockchip,px30-cru";
+ reg = <0x0 0xff2b0000 0x0 0x1000>;
+ rockchip,grf = <&grf>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller:
+
+ uart0: serial at ff030000 {
+ compatible = "rockchip,px30-uart", "snps,dw-apb-uart";
+ reg = <0x0 0xff030000 0x0 0x100>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmucru SCLK_UART0_PMU>, <&pmucru PCLK_UART0_PMU>;
+ clock-names = "baudclk", "apb_pclk";
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
--
1.9.1
^ permalink raw reply related
* [PATCH v1 2/4] clk: rockchip: add dt-binding header for px30
From: Elaine Zhang @ 2018-06-07 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528340786-462-1-git-send-email-zhangqing@rock-chips.com>
Add the dt-bindings header for the px30, that gets shared between
the clock controller and the clock references in the dts.
Add softreset ID for px30.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
include/dt-bindings/clock/px30-cru.h | 402 +++++++++++++++++++++++++++++++++++
1 file changed, 402 insertions(+)
create mode 100644 include/dt-bindings/clock/px30-cru.h
diff --git a/include/dt-bindings/clock/px30-cru.h b/include/dt-bindings/clock/px30-cru.h
new file mode 100644
index 000000000000..db9fc2a0bb21
--- /dev/null
+++ b/include/dt-bindings/clock/px30-cru.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Author: Elaine <zhangqing@rock-chips.com>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_PX30_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_PX30_H
+
+/* core clocks */
+#define PLL_APLL 1
+#define PLL_DPLL 2
+#define PLL_CPLL 3
+#define PLL_NPLL 4
+#define APLL_BOOST_H 5
+#define APLL_BOOST_L 6
+#define ARMCLK 7
+
+/* sclk gates (special clocks) */
+#define USB480M 14
+#define SCLK_PDM 15
+#define SCLK_I2S0_TX 16
+#define SCLK_I2S0_TX_OUT 17
+#define SCLK_I2S0_RX 18
+#define SCLK_I2S0_RX_OUT 19
+#define SCLK_I2S1 20
+#define SCLK_I2S1_OUT 21
+#define SCLK_I2S2 22
+#define SCLK_I2S2_OUT 23
+#define SCLK_UART1 24
+#define SCLK_UART2 25
+#define SCLK_UART3 26
+#define SCLK_UART4 27
+#define SCLK_UART5 28
+#define SCLK_I2C0 29
+#define SCLK_I2C1 30
+#define SCLK_I2C2 31
+#define SCLK_I2C3 32
+#define SCLK_I2C4 33
+#define SCLK_PWM0 34
+#define SCLK_PWM1 35
+#define SCLK_SPI0 36
+#define SCLK_SPI1 37
+#define SCLK_TIMER0 38
+#define SCLK_TIMER1 39
+#define SCLK_TIMER2 40
+#define SCLK_TIMER3 41
+#define SCLK_TIMER4 42
+#define SCLK_TIMER5 43
+#define SCLK_TSADC 44
+#define SCLK_SARADC 45
+#define SCLK_OTP 46
+#define SCLK_OTP_USR 47
+#define SCLK_CRYPTO 48
+#define SCLK_CRYPTO_APK 49
+#define SCLK_DDRC 50
+#define SCLK_ISP 51
+#define SCLK_CIF_OUT 52
+#define SCLK_RGA_CORE 53
+#define SCLK_VOPB_PWM 54
+#define SCLK_NANDC 55
+#define SCLK_SDIO 56
+#define SCLK_EMMC 57
+#define SCLK_SFC 58
+#define SCLK_SDMMC 59
+#define SCLK_OTG_ADP 60
+#define SCLK_GMAC_SRC 61
+#define SCLK_GMAC 62
+#define SCLK_GMAC_RX_TX 63
+#define SCLK_MAC_REF 64
+#define SCLK_MAC_REFOUT 65
+#define SCLK_MAC_OUT 66
+#define SCLK_SDMMC_DRV 67
+#define SCLK_SDMMC_SAMPLE 68
+#define SCLK_SDIO_DRV 69
+#define SCLK_SDIO_SAMPLE 70
+#define SCLK_EMMC_DRV 71
+#define SCLK_EMMC_SAMPLE 72
+#define SCLK_GPU 73
+#define SCLK_PVTM 74
+#define SCLK_CORE_VPU 75
+#define SCLK_GMAC_RMII 76
+#define SCLK_UART2_SRC 77
+#define SCLK_NANDC_DIV 78
+#define SCLK_NANDC_DIV50 79
+#define SCLK_SDIO_DIV 80
+#define SCLK_SDIO_DIV50 81
+#define SCLK_EMMC_DIV 82
+#define SCLK_EMMC_DIV50 83
+#define SCLK_DDRCLK 84
+#define SCLK_UART1_SRC 85
+
+/* dclk gates */
+#define DCLK_VOPB 150
+#define DCLK_VOPL 151
+
+/* aclk gates */
+#define ACLK_GPU 170
+#define ACLK_BUS_PRE 171
+#define ACLK_CRYPTO 172
+#define ACLK_VI_PRE 173
+#define ACLK_VO_PRE 174
+#define ACLK_VPU 175
+#define ACLK_PERI_PRE 176
+#define ACLK_GMAC 178
+#define ACLK_CIF 179
+#define ACLK_ISP 180
+#define ACLK_VOPB 181
+#define ACLK_VOPL 182
+#define ACLK_RGA 183
+#define ACLK_GIC 184
+#define ACLK_DCF 186
+#define ACLK_DMAC 187
+#define ACLK_BUS_SRC 188
+#define ACLK_PERI_SRC 189
+
+/* hclk gates */
+#define HCLK_BUS_PRE 240
+#define HCLK_CRYPTO 241
+#define HCLK_VI_PRE 242
+#define HCLK_VO_PRE 243
+#define HCLK_VPU 244
+#define HCLK_PERI_PRE 245
+#define HCLK_MMC_NAND 246
+#define HCLK_SDMMC 247
+#define HCLK_USB 248
+#define HCLK_CIF 249
+#define HCLK_ISP 250
+#define HCLK_VOPB 251
+#define HCLK_VOPL 252
+#define HCLK_RGA 253
+#define HCLK_NANDC 254
+#define HCLK_SDIO 255
+#define HCLK_EMMC 256
+#define HCLK_SFC 257
+#define HCLK_OTG 258
+#define HCLK_HOST 259
+#define HCLK_HOST_ARB 260
+#define HCLK_PDM 261
+#define HCLK_I2S0 262
+#define HCLK_I2S1 263
+#define HCLK_I2S2 264
+
+/* pclk gates */
+#define PCLK_BUS_PRE 320
+#define PCLK_DDR 321
+#define PCLK_VO_PRE 322
+#define PCLK_GMAC 323
+#define PCLK_MIPI_DSI 324
+#define PCLK_MIPIDSIPHY 325
+#define PCLK_MIPICSIPHY 326
+#define PCLK_USB_GRF 327
+#define PCLK_DCF 328
+#define PCLK_UART1 329
+#define PCLK_UART2 330
+#define PCLK_UART3 331
+#define PCLK_UART4 332
+#define PCLK_UART5 333
+#define PCLK_I2C0 334
+#define PCLK_I2C1 335
+#define PCLK_I2C2 336
+#define PCLK_I2C3 337
+#define PCLK_I2C4 338
+#define PCLK_PWM0 339
+#define PCLK_PWM1 340
+#define PCLK_SPI0 341
+#define PCLK_SPI1 342
+#define PCLK_SARADC 343
+#define PCLK_TSADC 344
+#define PCLK_TIMER 345
+#define PCLK_OTP_NS 346
+#define PCLK_WDT_NS 347
+#define PCLK_GPIO1 348
+#define PCLK_GPIO2 349
+#define PCLK_GPIO3 350
+#define PCLK_ISP 351
+#define PCLK_CIF 352
+#define PCLK_OTP_PHY 353
+
+#define CLK_NR_CLKS (PCLK_OTP_PHY + 1)
+
+/* pmu-clocks indices */
+
+#define PLL_GPLL 1
+
+#define SCLK_RTC32K_PMU 4
+#define SCLK_WIFI_PMU 5
+#define SCLK_UART0_PMU 6
+#define SCLK_PVTM_PMU 7
+#define PCLK_PMU_PRE 8
+#define SCLK_REF24M_PMU 9
+#define SCLK_USBPHY_REF 10
+#define SCLK_MIPIDSIPHY_REF 11
+
+#define XIN24M_DIV 12
+
+#define PCLK_GPIO0_PMU 20
+#define PCLK_UART0_PMU 21
+
+#define CLKPMU_NR_CLKS (PCLK_UART0_PMU + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0_PO 0
+#define SRST_CORE1_PO 1
+#define SRST_CORE2_PO 2
+#define SRST_CORE3_PO 3
+#define SRST_CORE0 4
+#define SRST_CORE1 5
+#define SRST_CORE2 6
+#define SRST_CORE3 7
+#define SRST_CORE0_DBG 8
+#define SRST_CORE1_DBG 9
+#define SRST_CORE2_DBG 10
+#define SRST_CORE3_DBG 11
+#define SRST_TOPDBG 12
+#define SRST_CORE_NOC 13
+#define SRST_STRC_A 14
+#define SRST_L2C 15
+
+#define SRST_DAP 16
+#define SRST_CORE_PVTM 17
+#define SRST_GPU 18
+#define SRST_GPU_NIU 19
+#define SRST_UPCTL2 20
+#define SRST_UPCTL2_A 21
+#define SRST_UPCTL2_P 22
+#define SRST_MSCH 23
+#define SRST_MSCH_P 24
+#define SRST_DDRMON_P 25
+#define SRST_DDRSTDBY_P 26
+#define SRST_DDRSTDBY 27
+#define SRST_DDRGRF_p 28
+#define SRST_AXI_SPLIT_A 29
+#define SRST_AXI_CMD_A 30
+#define SRST_AXI_CMD_P 31
+
+#define SRST_DDRPHY 32
+#define SRST_DDRPHYDIV 33
+#define SRST_DDRPHY_P 34
+#define SRST_VPU_A 36
+#define SRST_VPU_NIU_A 37
+#define SRST_VPU_H 38
+#define SRST_VPU_NIU_H 39
+#define SRST_VI_NIU_A 40
+#define SRST_VI_NIU_H 41
+#define SRST_ISP_H 42
+#define SRST_ISP 43
+#define SRST_CIF_A 44
+#define SRST_CIF_H 45
+#define SRST_CIF_PCLKIN 46
+#define SRST_MIPICSIPHY_P 47
+
+#define SRST_VO_NIU_A 48
+#define SRST_VO_NIU_H 49
+#define SRST_VO_NIU_P 50
+#define SRST_VOPB_A 51
+#define SRST_VOPB_H 52
+#define SRST_VOPB 53
+#define SRST_PWM_VOPB 54
+#define SRST_VOPL_A 55
+#define SRST_VOPL_H 56
+#define SRST_VOPL 57
+#define SRST_RGA_A 58
+#define SRST_RGA_H 59
+#define SRST_RGA 60
+#define SRST_MIPIDSI_HOST_P 61
+#define SRST_MIPIDSIPHY_P 62
+#define SRST_VPU_CORE 63
+
+#define SRST_PERI_NIU_A 64
+#define SRST_USB_NIU_H 65
+#define SRST_USB2OTG_H 66
+#define SRST_USB2OTG 67
+#define SRST_USB2OTG_ADP 68
+#define SRST_USB2HOST_H 69
+#define SRST_USB2HOST_ARB_H 70
+#define SRST_USB2HOST_AUX_H 71
+#define SRST_USB2HOST_EHCI 72
+#define SRST_USB2HOST 73
+#define SRST_USBPHYPOR 74
+#define SRST_USBPHY_OTG_PORT 75
+#define SRST_USBPHY_HOST_PORT 76
+#define SRST_USBPHY_GRF 77
+#define SRST_CPU_BOOST_P 78
+#define SRST_CPU_BOOST 79
+
+#define SRST_MMC_NAND_NIU_H 80
+#define SRST_SDIO_H 81
+#define SRST_EMMC_H 82
+#define SRST_SFC_H 83
+#define SRST_SFC 84
+#define SRST_SDCARD_NIU_H 85
+#define SRST_SDMMC_H 86
+#define SRST_NANDC_H 89
+#define SRST_NANDC 90
+#define SRST_GMAC_NIU_A 92
+#define SRST_GMAC_NIU_P 93
+#define SRST_GMAC_A 94
+
+#define SRST_PMU_NIU_P 96
+#define SRST_PMU_SGRF_P 97
+#define SRST_PMU_GRF_P 98
+#define SRST_PMU 99
+#define SRST_PMU_MEM_P 100
+#define SRST_PMU_GPIO0_P 101
+#define SRST_PMU_UART0_P 102
+#define SRST_PMU_CRU_P 103
+#define SRST_PMU_PVTM 104
+#define SRST_PMU_UART 105
+#define SRST_PMU_NIU_H 106
+#define SRST_PMU_DDR_FAIL_SAVE 107
+#define SRST_PMU_CORE_PERF_A 108
+#define SRST_PMU_CORE_GRF_P 109
+#define SRST_PMU_GPU_PERF_A 110
+#define SRST_PMU_GPU_GRF_P 111
+
+#define SRST_CRYPTO_NIU_A 112
+#define SRST_CRYPTO_NIU_H 113
+#define SRST_CRYPTO_A 114
+#define SRST_CRYPTO_H 115
+#define SRST_CRYPTO 116
+#define SRST_CRYPTO_APK 117
+#define SRST_BUS_NIU_H 120
+#define SRST_USB_NIU_P 121
+#define SRST_BUS_TOP_NIU_P 122
+#define SRST_INTMEM_A 123
+#define SRST_GIC_A 124
+#define SRST_ROM_H 126
+#define SRST_DCF_A 127
+
+#define SRST_DCF_P 128
+#define SRST_PDM_H 129
+#define SRST_PDM 130
+#define SRST_I2S0_H 131
+#define SRST_I2S0_TX 132
+#define SRST_I2S1_H 133
+#define SRST_I2S1 134
+#define SRST_I2S2_H 135
+#define SRST_I2S2 136
+#define SRST_UART1_P 137
+#define SRST_UART1 138
+#define SRST_UART2_P 139
+#define SRST_UART2 140
+#define SRST_UART3_P 141
+#define SRST_UART3 142
+#define SRST_UART4_P 143
+
+#define SRST_UART4 144
+#define SRST_UART5_P 145
+#define SRST_UART5 146
+#define SRST_I2C0_P 147
+#define SRST_I2C0 148
+#define SRST_I2C1_P 149
+#define SRST_I2C1 150
+#define SRST_I2C2_P 151
+#define SRST_I2C2 152
+#define SRST_I2C3_P 153
+#define SRST_I2C3 154
+#define SRST_PWM0_P 157
+#define SRST_PWM0 158
+#define SRST_PWM1_P 159
+
+#define SRST_PWM1 160
+#define SRST_SPI0_P 161
+#define SRST_SPI0 162
+#define SRST_SPI1_P 163
+#define SRST_SPI1 164
+#define SRST_SARADC_P 165
+#define SRST_SARADC 166
+#define SRST_TSADC_P 167
+#define SRST_TSADC 168
+#define SRST_TIMER_P 169
+#define SRST_TIMER0 170
+#define SRST_TIMER1 171
+#define SRST_TIMER2 172
+#define SRST_TIMER3 173
+#define SRST_TIMER4 174
+#define SRST_TIMER5 175
+
+#define SRST_OTP_NS_P 176
+#define SRST_OTP_NS_SBPI 177
+#define SRST_OTP_NS_USR 178
+#define SRST_OTP_PHY_P 179
+#define SRST_OTP_PHY 180
+#define SRST_WDT_NS_P 181
+#define SRST_GPIO1_P 182
+#define SRST_GPIO2_P 183
+#define SRST_GPIO3_P 184
+#define SRST_SGRF_P 185
+#define SRST_GRF_P 186
+#define SRST_I2S0_RX 191
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v1 3/4] clk: rockchip: add support for half divider
From: Elaine Zhang @ 2018-06-07 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528340786-462-1-git-send-email-zhangqing@rock-chips.com>
The new Rockchip socs have optional half divider,
so we use "branch_half_divider" + "COMPOSITE_NOMUX_HALFDIV \ DIV_HALF"
to hook that special divider clock-type into our clock-tree.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-half-divider.c | 235 ++++++++++++++++++++++++++++++++
drivers/clk/rockchip/clk.c | 10 ++
drivers/clk/rockchip/clk.h | 45 ++++++
4 files changed, 291 insertions(+)
create mode 100644 drivers/clk/rockchip/clk-half-divider.c
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 59b8d320960a..023f83ad3429 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -7,6 +7,7 @@ obj-y += clk-rockchip.o
obj-y += clk.o
obj-y += clk-pll.o
obj-y += clk-cpu.o
+obj-y += clk-half-divider.o
obj-y += clk-inverter.o
obj-y += clk-mmc-phase.o
obj-y += clk-muxgrf.o
diff --git a/drivers/clk/rockchip/clk-half-divider.c b/drivers/clk/rockchip/clk-half-divider.c
new file mode 100644
index 000000000000..23830de254ec
--- /dev/null
+++ b/drivers/clk/rockchip/clk-half-divider.c
@@ -0,0 +1,235 @@
+/*
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include "clk.h"
+
+#define div_mask(width) ((1 << (width)) - 1)
+
+static bool _is_best_half_div(unsigned long rate, unsigned long now,
+ unsigned long best, unsigned long flags)
+{
+ if (flags & CLK_DIVIDER_ROUND_CLOSEST)
+ return abs(rate - now) < abs(rate - best);
+
+ return now <= rate && now > best;
+}
+
+static unsigned long clk_half_divider_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned int val;
+
+ val = clk_readl(divider->reg) >> divider->shift;
+ val &= div_mask(divider->width);
+ val = val * 2 + 3;
+
+ return DIV_ROUND_UP_ULL((u64)(parent_rate * 2), val);
+}
+
+static int clk_half_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate, u8 width,
+ unsigned long flags)
+{
+ int i, bestdiv = 0;
+ unsigned long parent_rate, best = 0, now, maxdiv;
+ unsigned long parent_rate_saved = *best_parent_rate;
+
+ if (!rate)
+ rate = 1;
+
+ maxdiv = div_mask(width);
+
+ if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+ parent_rate = *best_parent_rate;
+ bestdiv = DIV_ROUND_UP_ULL((u64)(parent_rate * 2), rate);
+ if (bestdiv < 3)
+ bestdiv = 0;
+ else
+ bestdiv = (bestdiv - 3) / 2;
+ bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+ return bestdiv;
+ }
+
+ /*
+ * The maximum divider we can use without overflowing
+ * unsigned long in rate * i below
+ */
+ maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+ for (i = 0; i <= maxdiv; i++) {
+ if ((rate * (i * 2 + 3)) == (parent_rate_saved * 2)) {
+ /*
+ * It's the most ideal case if the requested rate can be
+ * divided from parent clock without needing to change
+ * parent rate, so return the divider immediately.
+ */
+ *best_parent_rate = parent_rate_saved;
+ return i;
+ }
+ parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+ (rate * (i * 2 + 3)) / 2);
+ now = DIV_ROUND_UP_ULL((u64)(parent_rate * 2), (i * 2 + 3));
+ if (_is_best_half_div(rate, now, best, flags)) {
+ bestdiv = i;
+ best = now;
+ *best_parent_rate = parent_rate;
+ }
+ }
+
+ if (!bestdiv) {
+ bestdiv = div_mask(width);
+ *best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
+ }
+
+ return bestdiv;
+}
+
+static long clk_half_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ int div;
+
+ div = clk_half_divider_bestdiv(hw, rate, prate,
+ divider->width,
+ divider->flags);
+
+ return DIV_ROUND_UP_ULL((u64)(*prate * 2), div * 2 + 3);
+}
+
+static int clk_half_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned int value;
+ unsigned long flags = 0;
+ u32 val;
+
+ value = DIV_ROUND_UP_ULL((u64)(2 * parent_rate), rate);
+ value = (value - 3) / 2;
+ value = min_t(unsigned int, value, div_mask(divider->width));
+
+ if (divider->lock)
+ spin_lock_irqsave(divider->lock, flags);
+ else
+ __acquire(divider->lock);
+
+ if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
+ val = div_mask(divider->width) << (divider->shift + 16);
+ } else {
+ val = clk_readl(divider->reg);
+ val &= ~(div_mask(divider->width) << divider->shift);
+ }
+ val |= value << divider->shift;
+ clk_writel(val, divider->reg);
+
+ if (divider->lock)
+ spin_unlock_irqrestore(divider->lock, flags);
+ else
+ __release(divider->lock);
+
+ return 0;
+}
+
+const struct clk_ops clk_half_divider_ops = {
+ .recalc_rate = clk_half_divider_recalc_rate,
+ .round_rate = clk_half_divider_round_rate,
+ .set_rate = clk_half_divider_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_half_divider_ops);
+
+/**
+ * Register a clock branch.
+ * Most clock branches have a form like
+ *
+ * src1 --|--\
+ * |M |--[GATE]-[DIV]-
+ * src2 --|--/
+ *
+ * sometimes without one of those components.
+ */
+struct clk *rockchip_clk_register_halfdiv(const char *name,
+ const char *const *parent_names,
+ u8 num_parents, void __iomem *base,
+ int muxdiv_offset, u8 mux_shift,
+ u8 mux_width, u8 mux_flags,
+ u8 div_shift, u8 div_width,
+ u8 div_flags, int gate_offset,
+ u8 gate_shift, u8 gate_flags,
+ unsigned long flags,
+ spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk_mux *mux = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_divider *div = NULL;
+ const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
+ *gate_ops = NULL;
+
+ if (num_parents > 1) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = base + muxdiv_offset;
+ mux->shift = mux_shift;
+ mux->mask = BIT(mux_width) - 1;
+ mux->flags = mux_flags;
+ mux->lock = lock;
+ mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
+ : &clk_mux_ops;
+ }
+
+ if (gate_offset >= 0) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ goto err_gate;
+
+ gate->flags = gate_flags;
+ gate->reg = base + gate_offset;
+ gate->bit_idx = gate_shift;
+ gate->lock = lock;
+ gate_ops = &clk_gate_ops;
+ }
+
+ if (div_width > 0) {
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ goto err_div;
+
+ div->flags = div_flags;
+ div->reg = base + muxdiv_offset;
+ div->shift = div_shift;
+ div->width = div_width;
+ div->lock = lock;
+ div_ops = &clk_half_divider_ops;
+ }
+
+ clk = clk_register_composite(NULL, name, parent_names, num_parents,
+ mux ? &mux->hw : NULL, mux_ops,
+ div ? &div->hw : NULL, div_ops,
+ gate ? &gate->hw : NULL, gate_ops,
+ flags);
+
+ return clk;
+err_div:
+ kfree(gate);
+err_gate:
+ kfree(mux);
+ return ERR_PTR(-ENOMEM);
+}
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 3cd8ad59e0b7..cd1474c05c91 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -498,6 +498,16 @@ void __init rockchip_clk_register_branches(
list->gate_flags, flags, list->child,
&ctx->lock);
break;
+ case branch_half_divider:
+ clk = rockchip_clk_register_halfdiv(list->name,
+ list->parent_names, list->num_parents,
+ ctx->reg_base, list->muxdiv_offset,
+ list->mux_shift, list->mux_width,
+ list->mux_flags, list->div_shift,
+ list->div_width, list->div_flags,
+ list->gate_offset, list->gate_shift,
+ list->gate_flags, flags, &ctx->lock);
+ break;
case branch_gate:
flags |= CLK_SET_RATE_PARENT;
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index ef601dded32c..7a3660c2bbb5 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -354,6 +354,7 @@ enum rockchip_clk_branch_type {
branch_inverter,
branch_factor,
branch_ddrclk,
+ branch_half_divider,
};
struct rockchip_clk_branch {
@@ -684,6 +685,39 @@ struct rockchip_clk_branch {
.gate_flags = gf, \
}
+#define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, \
+ go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_half_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+#define DIV_HALF(_id, cname, pname, f, o, s, w, df) \
+ { \
+ .id = _id, \
+ .branch_type = branch_half_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = o, \
+ .div_shift = s, \
+ .div_width = w, \
+ .div_flags = df, \
+ .gate_offset = -1, \
+ }
+
struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
void __iomem *base, unsigned long nr_clks);
void rockchip_clk_of_add_provider(struct device_node *np,
@@ -708,6 +742,17 @@ void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
+struct clk *rockchip_clk_register_halfdiv(const char *name,
+ const char *const *parent_names,
+ u8 num_parents, void __iomem *base,
+ int muxdiv_offset, u8 mux_shift,
+ u8 mux_width, u8 mux_flags,
+ u8 div_shift, u8 div_width,
+ u8 div_flags, int gate_offset,
+ u8 gate_shift, u8 gate_flags,
+ unsigned long flags,
+ spinlock_t *lock);
+
#ifdef CONFIG_RESET_CONTROLLER
void rockchip_register_softrst(struct device_node *np,
unsigned int num_regs,
--
1.9.1
^ permalink raw reply related
* [PATCH v1 4/4] clk: rockchip: add clock controller for px30
From: Elaine Zhang @ 2018-06-07 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528340786-462-1-git-send-email-zhangqing@rock-chips.com>
Add the clock tree definition for the new px30 SoC.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-px30.c | 1080 +++++++++++++++++++++++++++++++++++++++
drivers/clk/rockchip/clk.h | 41 +-
3 files changed, 1121 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/rockchip/clk-px30.c
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 023f83ad3429..82ab6f515179 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -14,6 +14,7 @@ obj-y += clk-muxgrf.o
obj-y += clk-ddr.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
+obj-y += clk-px30.o
obj-y += clk-rv1108.o
obj-y += clk-rk3036.o
obj-y += clk-rk3128.o
diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
new file mode 100644
index 000000000000..07105fe1ff6c
--- /dev/null
+++ b/drivers/clk/rockchip/clk-px30.c
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Elaine <zhangqing@rock-chips.com>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/px30-cru.h>
+#include "clk.h"
+
+#define PX30_GRF_SOC_STATUS0 0x480
+
+enum px30_plls {
+ apll, dpll, cpll, npll, apll_b_h, apll_b_l,
+};
+
+enum px30_pmu_plls {
+ gpll,
+};
+
+static struct rockchip_pll_rate_table px30_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+ RK3036_PLL_RATE(984000000, 1, 82, 2, 1, 1, 0),
+ RK3036_PLL_RATE(960000000, 1, 80, 2, 1, 1, 0),
+ RK3036_PLL_RATE(936000000, 1, 78, 2, 1, 1, 0),
+ RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
+ RK3036_PLL_RATE(900000000, 4, 300, 2, 1, 1, 0),
+ RK3036_PLL_RATE(888000000, 1, 74, 2, 1, 1, 0),
+ RK3036_PLL_RATE(864000000, 1, 72, 2, 1, 1, 0),
+ RK3036_PLL_RATE(840000000, 1, 70, 2, 1, 1, 0),
+ RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE(800000000, 6, 400, 2, 1, 1, 0),
+ RK3036_PLL_RATE(700000000, 6, 350, 2, 1, 1, 0),
+ RK3036_PLL_RATE(696000000, 1, 58, 2, 1, 1, 0),
+ RK3036_PLL_RATE(624000000, 1, 52, 2, 1, 1, 0),
+ RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
+ RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
+ RK3036_PLL_RATE(504000000, 1, 63, 3, 1, 1, 0),
+ RK3036_PLL_RATE(500000000, 6, 250, 2, 1, 1, 0),
+ RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
+ RK3036_PLL_RATE(312000000, 1, 52, 2, 2, 1, 0),
+ RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
+ RK3036_PLL_RATE(96000000, 1, 64, 4, 4, 1, 0),
+ { /* sentinel */ },
+};
+
+#define PX30_DIV_ACLKM_MASK 0x7
+#define PX30_DIV_ACLKM_SHIFT 12
+#define PX30_DIV_PCLK_DBG_MASK 0xf
+#define PX30_DIV_PCLK_DBG_SHIFT 8
+
+#define PX30_CLKSEL0(_aclk_core, _pclk_dbg) \
+{ \
+ .reg = PX30_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_aclk_core, PX30_DIV_ACLKM_MASK, \
+ PX30_DIV_ACLKM_SHIFT) | \
+ HIWORD_UPDATE(_pclk_dbg, PX30_DIV_PCLK_DBG_MASK, \
+ PX30_DIV_PCLK_DBG_SHIFT), \
+}
+
+#define PX30_CPUCLK_RATE(_prate, _aclk_core, _pclk_dbg) \
+{ \
+ .prate = _prate, \
+ .divs = { \
+ PX30_CLKSEL0(_aclk_core, _pclk_dbg), \
+ }, \
+}
+
+static struct rockchip_cpuclk_rate_table px30_cpuclk_rates[] __initdata = {
+ PX30_CPUCLK_RATE(1608000000, 1, 7),
+ PX30_CPUCLK_RATE(1584000000, 1, 7),
+ PX30_CPUCLK_RATE(1560000000, 1, 7),
+ PX30_CPUCLK_RATE(1536000000, 1, 7),
+ PX30_CPUCLK_RATE(1512000000, 1, 7),
+ PX30_CPUCLK_RATE(1488000000, 1, 5),
+ PX30_CPUCLK_RATE(1464000000, 1, 5),
+ PX30_CPUCLK_RATE(1440000000, 1, 5),
+ PX30_CPUCLK_RATE(1416000000, 1, 5),
+ PX30_CPUCLK_RATE(1392000000, 1, 5),
+ PX30_CPUCLK_RATE(1368000000, 1, 5),
+ PX30_CPUCLK_RATE(1344000000, 1, 5),
+ PX30_CPUCLK_RATE(1320000000, 1, 5),
+ PX30_CPUCLK_RATE(1296000000, 1, 5),
+ PX30_CPUCLK_RATE(1272000000, 1, 5),
+ PX30_CPUCLK_RATE(1248000000, 1, 5),
+ PX30_CPUCLK_RATE(1224000000, 1, 5),
+ PX30_CPUCLK_RATE(1200000000, 1, 5),
+ PX30_CPUCLK_RATE(1104000000, 1, 5),
+ PX30_CPUCLK_RATE(1008000000, 1, 5),
+ PX30_CPUCLK_RATE(912000000, 1, 5),
+ PX30_CPUCLK_RATE(816000000, 1, 3),
+ PX30_CPUCLK_RATE(696000000, 1, 3),
+ PX30_CPUCLK_RATE(600000000, 1, 3),
+ PX30_CPUCLK_RATE(408000000, 1, 1),
+ PX30_CPUCLK_RATE(312000000, 1, 1),
+ PX30_CPUCLK_RATE(216000000, 1, 1),
+ PX30_CPUCLK_RATE(96000000, 1, 1),
+};
+
+static const struct rockchip_cpuclk_reg_data px30_cpuclk_data = {
+ .core_reg = PX30_CLKSEL_CON(0),
+ .div_core_shift = 0,
+ .div_core_mask = 0xf,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
+ .mux_core_shift = 7,
+ .mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p) = { "xin24m"};
+PNAME(mux_usb480m_p) = { "xin24m", "usb480m_phy", "clk_rtc32k_pmu" };
+PNAME(mux_armclk_p) = { "apll_core", "gpll_core" };
+PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_ddrstdby_p) = { "clk_ddrphy1x", "clk_stdby_2wrap" };
+PNAME(mux_4plls_p) = { "gpll", "dummy_cpll", "usb480m", "npll" };
+PNAME(mux_cpll_npll_p) = { "cpll", "npll" };
+PNAME(mux_npll_cpll_p) = { "npll", "cpll" };
+PNAME(mux_gpll_cpll_p) = { "gpll", "dummy_cpll" };
+PNAME(mux_gpll_npll_p) = { "gpll", "npll" };
+PNAME(mux_gpll_xin24m_p) = { "gpll", "xin24m"};
+PNAME(mux_gpll_cpll_npll_p) = { "gpll", "dummy_cpll", "npll" };
+PNAME(mux_gpll_cpll_npll_xin24m_p) = { "gpll", "dummy_cpll", "npll", "xin24m" };
+PNAME(mux_gpll_xin24m_npll_p) = { "gpll", "xin24m", "npll"};
+PNAME(mux_pdm_p) = { "clk_pdm_src", "clk_pdm_frac" };
+PNAME(mux_i2s0_tx_p) = { "clk_i2s0_tx_src", "clk_i2s0_tx_frac", "mclk_i2s0_tx_in", "xin12m"};
+PNAME(mux_i2s0_rx_p) = { "clk_i2s0_rx_src", "clk_i2s0_rx_frac", "mclk_i2s0_rx_in", "xin12m"};
+PNAME(mux_i2s1_p) = { "clk_i2s1_src", "clk_i2s1_frac", "i2s1_clkin", "xin12m"};
+PNAME(mux_i2s2_p) = { "clk_i2s2_src", "clk_i2s2_frac", "i2s2_clkin", "xin12m"};
+PNAME(mux_i2s0_tx_out_p) = { "clk_i2s0_tx", "xin12m", "clk_i2s0_rx"};
+PNAME(mux_i2s0_rx_out_p) = { "clk_i2s0_rx", "xin12m", "clk_i2s0_tx"};
+PNAME(mux_i2s1_out_p) = { "clk_i2s1", "xin12m"};
+PNAME(mux_i2s2_out_p) = { "clk_i2s2", "xin12m"};
+PNAME(mux_i2s0_tx_rx_p) = { "clk_i2s0_tx_mux", "clk_i2s0_rx_mux"};
+PNAME(mux_i2s0_rx_tx_p) = { "clk_i2s0_rx_mux", "clk_i2s0_tx_mux"};
+PNAME(mux_uart_src_p) = { "gpll", "xin24m", "usb480m", "npll" };
+PNAME(mux_uart1_p) = { "clk_uart1_src", "clk_uart1_np5", "clk_uart1_frac" };
+PNAME(mux_uart2_p) = { "clk_uart2_src", "clk_uart2_np5", "clk_uart2_frac" };
+PNAME(mux_uart3_p) = { "clk_uart3_src", "clk_uart3_np5", "clk_uart3_frac" };
+PNAME(mux_uart4_p) = { "clk_uart4_src", "clk_uart4_np5", "clk_uart4_frac" };
+PNAME(mux_uart5_p) = { "clk_uart5_src", "clk_uart5_np5", "clk_uart5_frac" };
+PNAME(mux_cif_out_p) = { "xin24m", "dummy_cpll", "npll", "usb480m" };
+PNAME(mux_dclk_vopb_p) = { "dclk_vopb_src", "dclk_vopb_frac", "xin24m" };
+PNAME(mux_dclk_vopl_p) = { "dclk_vopl_src", "dclk_vopl_frac", "xin24m" };
+PNAME(mux_gmac_p) = { "clk_gmac_src", "gmac_clkin" };
+PNAME(mux_gmac_rmii_sel_p) = { "clk_gmac_rx_tx_div20", "clk_gmac_rx_tx_div2" };
+PNAME(mux_rtc32k_pmu_p) = { "xin32k", "pmu_pvtm_32k", "clk_rtc32k_frac", };
+PNAME(mux_wifi_pmu_p) = { "xin24m", "clk_wifi_pmu_src" };
+PNAME(mux_uart0_pmu_p) = { "clk_uart0_pmu_src", "clk_uart0_np5", "clk_uart0_frac" };
+PNAME(mux_usbphy_ref_p) = { "xin24m", "clk_ref24m_pmu" };
+PNAME(mux_mipidsiphy_ref_p) = { "xin24m", "clk_ref24m_pmu" };
+PNAME(mux_gpu_p) = { "clk_gpu_div", "clk_gpu_np5" };
+
+static struct rockchip_pll_clock px30_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p,
+ 0, PX30_PLL_CON(0),
+ PX30_MODE_CON, 0, 0, 0, px30_pll_rates),
+ [dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p,
+ 0, PX30_PLL_CON(8),
+ PX30_MODE_CON, 4, 1, 0, NULL),
+ [cpll] = PLL(pll_rk3328, PLL_CPLL, "cpll", mux_pll_p,
+ 0, PX30_PLL_CON(16),
+ PX30_MODE_CON, 2, 2, 0, px30_pll_rates),
+ [npll] = PLL(pll_rk3328, PLL_NPLL, "npll", mux_pll_p,
+ 0, PX30_PLL_CON(24),
+ PX30_MODE_CON, 6, 4, 0, px30_pll_rates),
+};
+
+static struct rockchip_pll_clock px30_pmu_pll_clks[] __initdata = {
+ [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p, 0, PX30_PMU_PLL_CON(0),
+ PX30_PMU_MODE, 0, 3, 0, px30_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch px30_pdm_fracmux __initdata =
+ MUX(0, "clk_pdm_mux", mux_pdm_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(26), 15, 1, MFLAGS);
+
+static struct rockchip_clk_branch px30_i2s0_tx_fracmux __initdata =
+ MUX(0, "clk_i2s0_tx_mux", mux_i2s0_tx_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(28), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_i2s0_rx_fracmux __initdata =
+ MUX(0, "clk_i2s0_rx_mux", mux_i2s0_rx_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(58), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_i2s1_fracmux __initdata =
+ MUX(0, "clk_i2s1_mux", mux_i2s1_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(30), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_i2s2_fracmux __initdata =
+ MUX(0, "clk_i2s2_mux", mux_i2s2_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(32), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_uart1_fracmux __initdata =
+ MUX(0, "clk_uart1_mux", mux_uart1_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(35), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_uart2_fracmux __initdata =
+ MUX(0, "clk_uart2_mux", mux_uart2_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(38), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_uart3_fracmux __initdata =
+ MUX(0, "clk_uart3_mux", mux_uart3_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(41), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_uart4_fracmux __initdata =
+ MUX(0, "clk_uart4_mux", mux_uart4_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(44), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_uart5_fracmux __initdata =
+ MUX(0, "clk_uart5_mux", mux_uart5_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(47), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_dclk_vopb_fracmux __initdata =
+ MUX(0, "dclk_vopb_mux", mux_dclk_vopb_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(5), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_dclk_vopl_fracmux __initdata =
+ MUX(0, "dclk_vopl_mux", mux_dclk_vopl_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(8), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_rtc32k_pmu_fracmux __initdata =
+ MUX(SCLK_RTC32K_PMU, "clk_rtc32k_pmu", mux_rtc32k_pmu_p, CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKSEL_CON(0), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_uart0_pmu_fracmux __initdata =
+ MUX(0, "clk_uart0_pmu_mux", mux_uart0_pmu_p, CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKSEL_CON(4), 14, 2, MFLAGS);
+
+static struct rockchip_clk_branch px30_clk_branches[] __initdata = {
+ /*
+ * Clock-Architecture Diagram 1
+ */
+
+ MUX(USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
+ PX30_MODE_CON, 8, 2, MFLAGS),
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+ /*
+ * Clock-Architecture Diagram 3
+ */
+
+ /* PD_CORE */
+ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 0, GFLAGS),
+ GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(0), 8, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ PX30_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(0), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ PX30_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "aclk_core_niu", "aclk_core", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 4, GFLAGS),
+ GATE(0, "aclk_core_prf", "aclk_core", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(17), 5, GFLAGS),
+ GATE(0, "pclk_dbg_niu", "pclk_dbg", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 5, GFLAGS),
+ GATE(0, "pclk_core_dbg", "pclk_dbg", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(0, "pclk_core_grf", "pclk_dbg", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(17), 6, GFLAGS),
+
+ GATE(0, "clk_jtag", "jtag_clkin", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 3, GFLAGS),
+ GATE(SCLK_PVTM, "clk_pvtm", "xin24m", 0,
+ PX30_CLKGATE_CON(17), 4, GFLAGS),
+
+ /* PD_GPU */
+ COMPOSITE_NODIV(0, "clk_gpu_src", mux_4plls_p, 0,
+ PX30_CLKSEL_CON(1), 6, 2, MFLAGS,
+ PX30_CLKGATE_CON(0), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "clk_gpu_div", "clk_gpu_src", 0,
+ PX30_CLKSEL_CON(1), 0, 4, DFLAGS,
+ PX30_CLKGATE_CON(0), 12, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_gpu_np5", "clk_gpu_src", 0,
+ PX30_CLKSEL_CON(1), 8, 4, DFLAGS,
+ PX30_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_NODIV(SCLK_GPU, "clk_gpu", mux_gpu_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(1), 15, 1, MFLAGS,
+ PX30_CLKGATE_CON(0), 10, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclk_gpu", "clk_gpu", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(1), 13, 2, DFLAGS,
+ PX30_CLKGATE_CON(17), 10, GFLAGS),
+ GATE(0, "aclk_gpu_niu", "aclk_gpu", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 11, GFLAGS),
+ GATE(0, "aclk_gpu_prf", "aclk_gpu", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(17), 8, GFLAGS),
+ GATE(0, "pclk_gpu_grf", "aclk_gpu", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(17), 9, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 4
+ */
+
+ /* PD_DDR */
+ GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE_NOGATE(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(2), 7, 1, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+ COMPOSITE_NOGATE(0, "clk_ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(2), 7, 1, MFLAGS, 0, 3, DFLAGS),
+ FACTOR_GATE(0, "clk_ddrphy1x", "clk_ddrphy4x", CLK_IGNORE_UNUSED, 1, 4,
+ PX30_CLKGATE_CON(0), 14, GFLAGS),
+ FACTOR_GATE(0, "clk_stdby_2wrap", "clk_ddrphy4x", CLK_IGNORE_UNUSED, 1, 4,
+ PX30_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NODIV(0, "clk_ddrstdby", mux_ddrstdby_p, CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(2), 4, 1, MFLAGS,
+ PX30_CLKGATE_CON(1), 13, GFLAGS),
+ GATE(0, "aclk_split", "clk_ddrphy1x", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 15, GFLAGS),
+ GATE(0, "clk_msch", "clk_ddrphy1x", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(0, "aclk_ddrc", "clk_ddrphy1x", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(0, "clk_core_ddrc", "clk_ddrphy1x", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(0, "aclk_cmd_buff", "clk_ddrphy1x", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(0, "clk_ddrmon", "clk_ddrphy1x", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 11, GFLAGS),
+
+ GATE(0, "clk_ddrmon_timer", "xin24m", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(0), 15, GFLAGS),
+
+ COMPOSITE_NOMUX(PCLK_DDR, "pclk_ddr", "gpll", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(2), 8, 5, DFLAGS,
+ PX30_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(0, "pclk_ddrmon", "pclk_ddr", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(0, "pclk_ddrc", "pclk_ddr", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(0, "pclk_msch", "pclk_ddr", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(0, "pclk_stdby", "pclk_ddr", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 12, GFLAGS),
+ GATE(0, "pclk_ddr_grf", "pclk_ddr", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 14, GFLAGS),
+ GATE(0, "pclk_cmdbuff", "pclk_ddr", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(1), 3, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 5
+ */
+
+ /* PD_VI */
+ COMPOSITE(ACLK_VI_PRE, "aclk_vi_pre", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(4), 8, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_VI_PRE, "hclk_vi_pre", "aclk_vi_pre", 0,
+ PX30_CLKSEL_CON(11), 8, 4, DFLAGS,
+ PX30_CLKGATE_CON(4), 12, GFLAGS),
+ COMPOSITE(SCLK_ISP, "clk_isp", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(4), 9, GFLAGS),
+ COMPOSITE(SCLK_CIF_OUT, "clk_cif_out", mux_cif_out_p, 0,
+ PX30_CLKSEL_CON(13), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ PX30_CLKGATE_CON(4), 11, GFLAGS),
+ GATE(PCLK_ISP, "pclkin_isp", "ext_pclkin", 0,
+ PX30_CLKGATE_CON(4), 13, GFLAGS),
+ GATE(PCLK_CIF, "pclkin_cif", "ext_pclkin", 0,
+ PX30_CLKGATE_CON(4), 14, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 6
+ */
+
+ /* PD_VO */
+ COMPOSITE(ACLK_VO_PRE, "aclk_vo_pre", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(3), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(2), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_VO_PRE, "hclk_vo_pre", "aclk_vo_pre", 0,
+ PX30_CLKSEL_CON(3), 8, 4, DFLAGS,
+ PX30_CLKGATE_CON(2), 12, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_VO_PRE, "pclk_vo_pre", "aclk_vo_pre", 0,
+ PX30_CLKSEL_CON(3), 12, 4, DFLAGS,
+ PX30_CLKGATE_CON(2), 13, GFLAGS),
+ COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(2), 1, GFLAGS),
+
+ COMPOSITE(SCLK_VOPB_PWM, "clk_vopb_pwm", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(7), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(2), 5, GFLAGS),
+ COMPOSITE(0, "dclk_vopb_src", mux_cpll_npll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ PX30_CLKSEL_CON(5), 11, 1, MFLAGS, 0, 8, DFLAGS,
+ PX30_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE_FRACMUX(0, "dclk_vopb_frac", "dclk_vopb_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(6), 0,
+ PX30_CLKGATE_CON(2), 3, GFLAGS,
+ &px30_dclk_vopb_fracmux),
+ GATE(DCLK_VOPB, "dclk_vopb", "dclk_vopb_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(2), 4, GFLAGS),
+ COMPOSITE(0, "dclk_vopl_src", mux_npll_cpll_p, 0,
+ PX30_CLKSEL_CON(8), 11, 1, MFLAGS, 0, 8, DFLAGS,
+ PX30_CLKGATE_CON(2), 6, GFLAGS),
+ COMPOSITE_FRACMUX(0, "dclk_vopl_frac", "dclk_vopl_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(9), 0,
+ PX30_CLKGATE_CON(2), 7, GFLAGS,
+ &px30_dclk_vopl_fracmux),
+ GATE(DCLK_VOPL, "dclk_vopl", "dclk_vopl_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(2), 8, GFLAGS),
+
+ /* PD_VPU */
+ COMPOSITE(0, "aclk_vpu_pre", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(10), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(4), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vpu_pre", "aclk_vpu_pre", 0,
+ PX30_CLKSEL_CON(10), 8, 4, DFLAGS,
+ PX30_CLKGATE_CON(4), 2, GFLAGS),
+ COMPOSITE(SCLK_CORE_VPU, "sclk_core_vpu", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(13), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ PX30_CLKGATE_CON(4), 1, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 7
+ */
+
+ COMPOSITE_NODIV(ACLK_PERI_SRC, "aclk_peri_src", mux_gpll_cpll_p, 0,
+ PX30_CLKSEL_CON(14), 15, 1, MFLAGS,
+ PX30_CLKGATE_CON(5), 7, GFLAGS),
+ COMPOSITE_NOMUX(ACLK_PERI_PRE, "aclk_peri_pre", "aclk_peri_src", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(14), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(5), 8, GFLAGS),
+ DIV(HCLK_PERI_PRE, "hclk_peri_pre", "aclk_peri_src", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(14), 8, 5, DFLAGS),
+
+ /* PD_MMC_NAND */
+ GATE(HCLK_MMC_NAND, "hclk_mmc_nand", "hclk_peri_pre", 0,
+ PX30_CLKGATE_CON(6), 0, GFLAGS),
+ COMPOSITE(SCLK_NANDC, "clk_nandc", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(5), 13, GFLAGS),
+
+ COMPOSITE(SCLK_SDIO, "clk_sdio", mux_gpll_cpll_npll_xin24m_p, 0,
+ PX30_CLKSEL_CON(18), 14, 2, MFLAGS, 0, 8, DFLAGS,
+ PX30_CLKGATE_CON(6), 3, GFLAGS),
+
+ COMPOSITE(SCLK_EMMC, "clk_emmc", mux_gpll_cpll_npll_xin24m_p, 0,
+ PX30_CLKSEL_CON(20), 14, 2, MFLAGS, 0, 8, DFLAGS,
+ PX30_CLKGATE_CON(6), 6, GFLAGS),
+
+ COMPOSITE(SCLK_SFC, "clk_sfc", mux_gpll_cpll_p, 0,
+ PX30_CLKSEL_CON(22), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(6), 7, GFLAGS),
+
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc",
+ PX30_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc",
+ PX30_SDMMC_CON1, 1),
+
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio",
+ PX30_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio",
+ PX30_SDIO_CON1, 1),
+
+ MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc",
+ PX30_EMMC_CON0, 1),
+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc",
+ PX30_EMMC_CON1, 1),
+
+ /* PD_SDCARD */
+ GATE(0, "hclk_sdmmc_pre", "hclk_peri_pre", 0,
+ PX30_CLKGATE_CON(6), 12, GFLAGS),
+ COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_gpll_cpll_npll_xin24m_p, 0,
+ PX30_CLKSEL_CON(16), 14, 2, MFLAGS, 0, 8, DFLAGS,
+ PX30_CLKGATE_CON(6), 15, GFLAGS),
+
+ /* PD_USB */
+ GATE(HCLK_USB, "hclk_usb", "hclk_peri_pre", 0,
+ PX30_CLKGATE_CON(7), 2, GFLAGS),
+ GATE(SCLK_OTG_ADP, "clk_otg_adp", "clk_rtc32k_pmu", 0,
+ PX30_CLKGATE_CON(7), 3, GFLAGS),
+
+ /* PD_GMAC */
+ COMPOSITE(SCLK_GMAC_SRC, "clk_gmac_src", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(22), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ PX30_CLKGATE_CON(7), 11, GFLAGS),
+ MUX(SCLK_GMAC, "clk_gmac", mux_gmac_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(23), 6, 1, MFLAGS),
+ GATE(SCLK_MAC_REF, "clk_mac_ref", "clk_gmac", 0,
+ PX30_CLKGATE_CON(7), 15, GFLAGS),
+ GATE(SCLK_GMAC_RX_TX, "clk_gmac_rx_tx", "clk_gmac", 0,
+ PX30_CLKGATE_CON(7), 13, GFLAGS),
+ FACTOR(0, "clk_gmac_rx_tx_div2", "clk_gmac_rx_tx", 0, 1, 2),
+ FACTOR(0, "clk_gmac_rx_tx_div20", "clk_gmac_rx_tx", 0, 1, 20),
+ MUX(SCLK_GMAC_RMII, "clk_gmac_rmii_sel", mux_gmac_rmii_sel_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(23), 7, 1, MFLAGS),
+
+ GATE(0, "aclk_gmac_pre", "aclk_peri_pre", 0,
+ PX30_CLKGATE_CON(7), 10, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", 0,
+ PX30_CLKSEL_CON(23), 0, 4, DFLAGS,
+ PX30_CLKGATE_CON(7), 12, GFLAGS),
+
+ COMPOSITE(SCLK_MAC_OUT, "clk_mac_out", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ PX30_CLKGATE_CON(8), 5, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 8
+ */
+
+ /* PD_BUS */
+ COMPOSITE_NODIV(ACLK_BUS_SRC, "aclk_bus_src", mux_gpll_cpll_p, CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(23), 15, 1, MFLAGS,
+ PX30_CLKGATE_CON(8), 6, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_BUS_PRE, "hclk_bus_pre", "aclk_bus_src", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(24), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(8), 8, GFLAGS),
+ COMPOSITE_NOMUX(ACLK_BUS_PRE, "aclk_bus_pre", "aclk_bus_src", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(23), 8, 5, DFLAGS,
+ PX30_CLKGATE_CON(8), 7, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_BUS_PRE, "pclk_bus_pre", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+ PX30_CLKSEL_CON(24), 8, 2, DFLAGS,
+ PX30_CLKGATE_CON(8), 9, GFLAGS),
+ GATE(0, "pclk_top_pre", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(8), 10, GFLAGS),
+
+ COMPOSITE(0, "clk_pdm_src", mux_gpll_xin24m_npll_p, 0,
+ PX30_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(9), 9, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_pdm_frac", "clk_pdm_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(27), 0,
+ PX30_CLKGATE_CON(9), 10, GFLAGS,
+ &px30_pdm_fracmux),
+ GATE(SCLK_PDM, "clk_pdm", "clk_pdm_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(9), 11, GFLAGS),
+
+ COMPOSITE(0, "clk_i2s0_tx_src", mux_gpll_npll_p, 0,
+ PX30_CLKSEL_CON(28), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(9), 12, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s0_tx_frac", "clk_i2s0_tx_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(29), 0,
+ PX30_CLKGATE_CON(9), 13, GFLAGS,
+ &px30_i2s0_tx_fracmux),
+ COMPOSITE_NODIV(SCLK_I2S0_TX, "clk_i2s0_tx", mux_i2s0_tx_rx_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(28), 12, 1, MFLAGS,
+ PX30_CLKGATE_CON(9), 14, GFLAGS),
+ COMPOSITE_NODIV(0, "clk_i2s0_tx_out_pre", mux_i2s0_tx_out_p, 0,
+ PX30_CLKSEL_CON(28), 14, 2, MFLAGS,
+ PX30_CLKGATE_CON(9), 15, GFLAGS),
+ GATE(SCLK_I2S0_TX_OUT, "clk_i2s0_tx_out", "clk_i2s0_tx_out_pre", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 8, CLK_GATE_HIWORD_MASK),
+
+ COMPOSITE(0, "clk_i2s0_rx_src", mux_gpll_npll_p, 0,
+ PX30_CLKSEL_CON(58), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(17), 0, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s0_rx_frac", "clk_i2s0_rx_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(59), 0,
+ PX30_CLKGATE_CON(17), 1, GFLAGS,
+ &px30_i2s0_rx_fracmux),
+ COMPOSITE_NODIV(SCLK_I2S0_RX, "clk_i2s0_rx", mux_i2s0_rx_tx_p, CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(58), 12, 1, MFLAGS,
+ PX30_CLKGATE_CON(17), 2, GFLAGS),
+ COMPOSITE_NODIV(0, "clk_i2s0_rx_out_pre", mux_i2s0_rx_out_p, 0,
+ PX30_CLKSEL_CON(58), 14, 2, MFLAGS,
+ PX30_CLKGATE_CON(17), 3, GFLAGS),
+ GATE(SCLK_I2S0_RX_OUT, "clk_i2s0_rx_out", "clk_i2s0_rx_out_pre", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 11, CLK_GATE_HIWORD_MASK),
+
+ COMPOSITE(0, "clk_i2s1_src", mux_gpll_npll_p, 0,
+ PX30_CLKSEL_CON(30), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(10), 0, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(31), 0,
+ PX30_CLKGATE_CON(10), 1, GFLAGS,
+ &px30_i2s1_fracmux),
+ GATE(SCLK_I2S1, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 2, GFLAGS),
+ COMPOSITE_NODIV(0, "clk_i2s1_out_pre", mux_i2s1_out_p, 0,
+ PX30_CLKSEL_CON(30), 15, 1, MFLAGS,
+ PX30_CLKGATE_CON(10), 3, GFLAGS),
+ GATE(SCLK_I2S1_OUT, "clk_i2s1_out", "clk_i2s1_out_pre", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 9, CLK_GATE_HIWORD_MASK),
+
+ COMPOSITE(0, "clk_i2s2_src", mux_gpll_npll_p, 0,
+ PX30_CLKSEL_CON(32), 8, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(10), 4, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(33), 0,
+ PX30_CLKGATE_CON(10), 5, GFLAGS,
+ &px30_i2s2_fracmux),
+ GATE(SCLK_I2S2, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 6, GFLAGS),
+ COMPOSITE_NODIV(0, "clk_i2s2_out_pre", mux_i2s2_out_p, 0,
+ PX30_CLKSEL_CON(32), 15, 1, MFLAGS,
+ PX30_CLKGATE_CON(10), 7, GFLAGS),
+ GATE(SCLK_I2S2_OUT, "clk_i2s2_out", "clk_i2s2_out_pre", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 10, CLK_GATE_HIWORD_MASK),
+
+ COMPOSITE(SCLK_UART1_SRC, "clk_uart1_src", mux_uart_src_p, CLK_SET_RATE_NO_REPARENT,
+ PX30_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(10), 12, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_uart1_np5", "clk_uart1_src", 0,
+ PX30_CLKSEL_CON(35), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(10), 13, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(36), 0,
+ PX30_CLKGATE_CON(10), 14, GFLAGS,
+ &px30_uart1_fracmux),
+ GATE(SCLK_UART1, "clk_uart1", "clk_uart1_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(10), 15, GFLAGS),
+
+ COMPOSITE(SCLK_UART2_SRC, "clk_uart2_src", mux_uart_src_p, 0,
+ PX30_CLKSEL_CON(37), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 0, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_uart2_np5", "clk_uart2_src", 0,
+ PX30_CLKSEL_CON(38), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 1, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(39), 0,
+ PX30_CLKGATE_CON(11), 2, GFLAGS,
+ &px30_uart2_fracmux),
+ GATE(SCLK_UART2, "clk_uart2", "clk_uart2_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(11), 3, GFLAGS),
+
+ COMPOSITE(0, "clk_uart3_src", mux_uart_src_p, 0,
+ PX30_CLKSEL_CON(40), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 4, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_uart3_np5", "clk_uart3_src", 0,
+ PX30_CLKSEL_CON(41), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 5, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(42), 0,
+ PX30_CLKGATE_CON(11), 6, GFLAGS,
+ &px30_uart3_fracmux),
+ GATE(SCLK_UART3, "clk_uart3", "clk_uart3_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(11), 7, GFLAGS),
+
+ COMPOSITE(0, "clk_uart4_src", mux_uart_src_p, 0,
+ PX30_CLKSEL_CON(43), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 8, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_uart4_np5", "clk_uart4_src", 0,
+ PX30_CLKSEL_CON(44), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 9, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(45), 0,
+ PX30_CLKGATE_CON(11), 10, GFLAGS,
+ &px30_uart4_fracmux),
+ GATE(SCLK_UART4, "clk_uart4", "clk_uart4_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(11), 11, GFLAGS),
+
+ COMPOSITE(0, "clk_uart5_src", mux_uart_src_p, 0,
+ PX30_CLKSEL_CON(46), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 12, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_uart5_np5", "clk_uart5_src", 0,
+ PX30_CLKSEL_CON(47), 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(11), 13, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT,
+ PX30_CLKSEL_CON(48), 0,
+ PX30_CLKGATE_CON(11), 14, GFLAGS,
+ &px30_uart5_fracmux),
+ GATE(SCLK_UART5, "clk_uart5", "clk_uart5_mux", CLK_SET_RATE_PARENT,
+ PX30_CLKGATE_CON(11), 15, GFLAGS),
+
+ COMPOSITE(SCLK_I2C0, "clk_i2c0", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(49), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 0, GFLAGS),
+ COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(49), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 1, GFLAGS),
+ COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(50), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 2, GFLAGS),
+ COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(50), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 3, GFLAGS),
+ COMPOSITE(SCLK_PWM0, "clk_pwm0", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(52), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 5, GFLAGS),
+ COMPOSITE(SCLK_PWM1, "clk_pwm1", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(52), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 6, GFLAGS),
+ COMPOSITE(SCLK_SPI0, "clk_spi0", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(53), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 7, GFLAGS),
+ COMPOSITE(SCLK_SPI1, "clk_spi1", mux_gpll_xin24m_p, 0,
+ PX30_CLKSEL_CON(53), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ PX30_CLKGATE_CON(12), 8, GFLAGS),
+
+ GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
+ PX30_CLKGATE_CON(13), 0, GFLAGS),
+ GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
+ PX30_CLKGATE_CON(13), 1, GFLAGS),
+ GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
+ PX30_CLKGATE_CON(13), 2, GFLAGS),
+ GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
+ PX30_CLKGATE_CON(13), 3, GFLAGS),
+ GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
+ PX30_CLKGATE_CON(13), 4, GFLAGS),
+ GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
+ PX30_CLKGATE_CON(13), 5, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_TSADC, "clk_tsadc", "xin24m", 0,
+ PX30_CLKSEL_CON(54), 0, 11, DFLAGS,
+ PX30_CLKGATE_CON(12), 9, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 0,
+ PX30_CLKSEL_CON(55), 0, 11, DFLAGS,
+ PX30_CLKGATE_CON(12), 10, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_OTP, "clk_otp", "xin24m", 0,
+ PX30_CLKSEL_CON(56), 0, 3, DFLAGS,
+ PX30_CLKGATE_CON(12), 11, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_OTP_USR, "clk_otp_usr", "clk_otp", 0,
+ PX30_CLKSEL_CON(56), 4, 2, DFLAGS,
+ PX30_CLKGATE_CON(13), 6, GFLAGS),
+
+ GATE(0, "clk_cpu_boost", "xin24m", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(12), 12, GFLAGS),
+
+ /* PD_CRYPTO */
+ GATE(0, "aclk_crypto_pre", "aclk_bus_pre", 0,
+ PX30_CLKGATE_CON(8), 12, GFLAGS),
+ GATE(0, "hclk_crypto_pre", "hclk_bus_pre", 0,
+ PX30_CLKGATE_CON(8), 13, GFLAGS),
+ COMPOSITE(SCLK_CRYPTO, "clk_crypto", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(25), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_CLKGATE_CON(8), 14, GFLAGS),
+ COMPOSITE(SCLK_CRYPTO_APK, "clk_crypto_apk", mux_gpll_cpll_npll_p, 0,
+ PX30_CLKSEL_CON(25), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ PX30_CLKGATE_CON(8), 15, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 9
+ */
+
+ /* PD_BUS_TOP */
+ GATE(0, "pclk_top_niu", "pclk_top_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(16), 0, GFLAGS),
+ GATE(0, "pclk_top_cru", "pclk_top_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(16), 1, GFLAGS),
+ GATE(PCLK_OTP_PHY, "pclk_otp_phy", "pclk_top_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(0, "pclk_ddrphy", "pclk_top_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(16), 3, GFLAGS),
+ GATE(PCLK_MIPIDSIPHY, "pclk_mipidsiphy", "pclk_top_pre", 0, PX30_CLKGATE_CON(16), 4, GFLAGS),
+ GATE(PCLK_MIPICSIPHY, "pclk_mipicsiphy", "pclk_top_pre", 0, PX30_CLKGATE_CON(16), 5, GFLAGS),
+ GATE(PCLK_USB_GRF, "pclk_usb_grf", "pclk_top_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(16), 6, GFLAGS),
+ GATE(0, "pclk_cpu_hoost", "pclk_top_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(16), 7, GFLAGS),
+
+ /* PD_VI */
+ GATE(0, "aclk_vi_niu", "aclk_vi_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(4), 15, GFLAGS),
+ GATE(ACLK_CIF, "aclk_cif", "aclk_vi_pre", 0, PX30_CLKGATE_CON(5), 1, GFLAGS),
+ GATE(ACLK_ISP, "aclk_isp", "aclk_vi_pre", 0, PX30_CLKGATE_CON(5), 3, GFLAGS),
+ GATE(0, "hclk_vi_niu", "hclk_vi_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(5), 0, GFLAGS),
+ GATE(HCLK_CIF, "hclk_cif", "hclk_vi_pre", 0, PX30_CLKGATE_CON(5), 2, GFLAGS),
+ GATE(HCLK_ISP, "hclk_isp", "hclk_vi_pre", 0, PX30_CLKGATE_CON(5), 4, GFLAGS),
+
+ /* PD_VO */
+ GATE(0, "aclk_vo_niu", "aclk_vo_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(3), 0, GFLAGS),
+ GATE(ACLK_VOPB, "aclk_vopb", "aclk_vo_pre", 0, PX30_CLKGATE_CON(3), 3, GFLAGS),
+ GATE(ACLK_RGA, "aclk_rga", "aclk_vo_pre", 0, PX30_CLKGATE_CON(3), 7, GFLAGS),
+ GATE(ACLK_VOPL, "aclk_vopl", "aclk_vo_pre", 0, PX30_CLKGATE_CON(3), 5, GFLAGS),
+
+ GATE(0, "hclk_vo_niu", "hclk_vo_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(3), 1, GFLAGS),
+ GATE(HCLK_VOPB, "hclk_vopb", "hclk_vo_pre", 0, PX30_CLKGATE_CON(3), 4, GFLAGS),
+ GATE(HCLK_RGA, "hclk_rga", "hclk_vo_pre", 0, PX30_CLKGATE_CON(3), 8, GFLAGS),
+ GATE(HCLK_VOPL, "hclk_vopl", "hclk_vo_pre", 0, PX30_CLKGATE_CON(3), 6, GFLAGS),
+
+ GATE(0, "pclk_vo_niu", "pclk_vo_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(3), 2, GFLAGS),
+ GATE(PCLK_MIPI_DSI, "pclk_mipi_dsi", "pclk_vo_pre", 0, PX30_CLKGATE_CON(3), 9, GFLAGS),
+
+ /* PD_BUS */
+ GATE(0, "aclk_bus_niu", "aclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 8, GFLAGS),
+ GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 11, GFLAGS),
+ GATE(ACLK_GIC, "aclk_gic", "aclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 12, GFLAGS),
+ GATE(ACLK_DCF, "aclk_dcf", "aclk_bus_pre", 0, PX30_CLKGATE_CON(13), 15, GFLAGS),
+
+ GATE(0, "hclk_bus_niu", "hclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 9, GFLAGS),
+ GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 14, GFLAGS),
+ GATE(HCLK_PDM, "hclk_pdm", "hclk_bus_pre", 0, PX30_CLKGATE_CON(14), 1, GFLAGS),
+ GATE(HCLK_I2S0, "hclk_i2s0", "hclk_bus_pre", 0, PX30_CLKGATE_CON(14), 2, GFLAGS),
+ GATE(HCLK_I2S1, "hclk_i2s1", "hclk_bus_pre", 0, PX30_CLKGATE_CON(14), 3, GFLAGS),
+ GATE(HCLK_I2S2, "hclk_i2s2", "hclk_bus_pre", 0, PX30_CLKGATE_CON(14), 4, GFLAGS),
+
+ GATE(0, "pclk_bus_niu", "pclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 10, GFLAGS),
+ GATE(PCLK_DCF, "pclk_dcf", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 0, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 5, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 6, GFLAGS),
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 7, GFLAGS),
+ GATE(PCLK_UART4, "pclk_uart4", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 8, GFLAGS),
+ GATE(PCLK_UART5, "pclk_uart5", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 9, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 10, GFLAGS),
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 11, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 12, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 13, GFLAGS),
+ GATE(PCLK_I2C4, "pclk_i2c4", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 14, GFLAGS),
+ GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus_pre", 0, PX30_CLKGATE_CON(14), 15, GFLAGS),
+ GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 1, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 2, GFLAGS),
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 3, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 4, GFLAGS),
+ GATE(PCLK_TIMER, "pclk_timer", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(PCLK_OTP_NS, "pclk_otp_ns", "pclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(15), 6, GFLAGS),
+ GATE(PCLK_WDT_NS, "pclk_wdt_ns", "pclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(15), 7, GFLAGS),
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 8, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 9, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus_pre", 0, PX30_CLKGATE_CON(15), 10, GFLAGS),
+ GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(15), 11, GFLAGS),
+ GATE(0, "pclk_sgrf", "pclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(15), 12, GFLAGS),
+
+ /* PD_VPU */
+ GATE(0, "hclk_vpu_niu", "hclk_vpu_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(4), 7, GFLAGS),
+ GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, PX30_CLKGATE_CON(4), 6, GFLAGS),
+ GATE(0, "aclk_vpu_niu", "aclk_vpu_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(4), 5, GFLAGS),
+ GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, PX30_CLKGATE_CON(4), 4, GFLAGS),
+
+ /* PD_CRYPTO */
+ GATE(0, "hclk_crypto_niu", "hclk_crypto_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(9), 3, GFLAGS),
+ GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_crypto_pre", 0, PX30_CLKGATE_CON(9), 5, GFLAGS),
+ GATE(0, "aclk_crypto_niu", "aclk_crypto_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(9), 2, GFLAGS),
+ GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_crypto_pre", 0, PX30_CLKGATE_CON(9), 4, GFLAGS),
+
+ /* PD_SDCARD */
+ GATE(0, "hclk_sdmmc_niu", "hclk_sdmmc_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(7), 0, GFLAGS),
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sdmmc_pre", 0, PX30_CLKGATE_CON(7), 1, GFLAGS),
+
+ /* PD_PERI */
+ GATE(0, "aclk_peri_niu", "aclk_peri_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(5), 9, GFLAGS),
+
+ /* PD_MMC_NAND */
+ GATE(HCLK_NANDC, "hclk_nandc", "hclk_mmc_nand", 0, PX30_CLKGATE_CON(5), 15, GFLAGS),
+ GATE(0, "hclk_mmc_nand_niu", "hclk_mmc_nand", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(6), 8, GFLAGS),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_mmc_nand", 0, PX30_CLKGATE_CON(6), 9, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_mmc_nand", 0, PX30_CLKGATE_CON(6), 10, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_mmc_nand", 0, PX30_CLKGATE_CON(6), 11, GFLAGS),
+
+ /* PD_USB */
+ GATE(0, "hclk_usb_niu", "hclk_usb", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(7), 4, GFLAGS),
+ GATE(HCLK_OTG, "hclk_otg", "hclk_usb", 0, PX30_CLKGATE_CON(7), 5, GFLAGS),
+ GATE(HCLK_HOST, "hclk_host", "hclk_usb", 0, PX30_CLKGATE_CON(7), 6, GFLAGS),
+ GATE(HCLK_HOST_ARB, "hclk_host_arb", "hclk_usb", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(7), 8, GFLAGS),
+
+ /* PD_GMAC */
+ GATE(0, "aclk_gmac_niu", "aclk_gmac_pre", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(8), 0, GFLAGS),
+ GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", 0,
+ PX30_CLKGATE_CON(8), 2, GFLAGS),
+ GATE(0, "pclk_gmac_niu", "pclk_gmac_pre", CLK_IGNORE_UNUSED,
+ PX30_CLKGATE_CON(8), 1, GFLAGS),
+ GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", 0,
+ PX30_CLKGATE_CON(8), 3, GFLAGS),
+};
+
+static struct rockchip_clk_branch px30_clk_pmu_branches[] __initdata = {
+ /*
+ * Clock-Architecture Diagram 2
+ */
+
+ COMPOSITE_FRACMUX(0, "clk_rtc32k_frac", "xin24m", CLK_IGNORE_UNUSED,
+ PX30_PMU_CLKSEL_CON(1), 0,
+ PX30_PMU_CLKGATE_CON(0), 13, GFLAGS,
+ &px30_rtc32k_pmu_fracmux),
+
+ COMPOSITE_NOMUX(XIN24M_DIV, "xin24m_div", "xin24m", CLK_IGNORE_UNUSED,
+ PX30_PMU_CLKSEL_CON(0), 8, 5, DFLAGS,
+ PX30_PMU_CLKGATE_CON(0), 12, GFLAGS),
+
+ COMPOSITE_NOMUX(0, "clk_wifi_pmu_src", "gpll", 0,
+ PX30_PMU_CLKSEL_CON(2), 8, 6, DFLAGS,
+ PX30_PMU_CLKGATE_CON(0), 14, GFLAGS),
+ COMPOSITE_NODIV(SCLK_WIFI_PMU, "clk_wifi_pmu", mux_wifi_pmu_p, CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKSEL_CON(2), 15, 1, MFLAGS,
+ PX30_PMU_CLKGATE_CON(0), 15, GFLAGS),
+
+ COMPOSITE(0, "clk_uart0_pmu_src", mux_uart_src_p, 0,
+ PX30_PMU_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ PX30_PMU_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NOMUX_HALFDIV(0, "clk_uart0_np5", "clk_uart0_pmu_src", 0,
+ PX30_PMU_CLKSEL_CON(4), 0, 5, DFLAGS,
+ PX30_PMU_CLKGATE_CON(1), 1, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_pmu_src", CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKSEL_CON(5), 0,
+ PX30_PMU_CLKGATE_CON(1), 2, GFLAGS,
+ &px30_uart0_pmu_fracmux),
+ GATE(SCLK_UART0_PMU, "clk_uart0_pmu", "clk_uart0_pmu_mux", CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKGATE_CON(1), 3, GFLAGS),
+
+ GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", 0,
+ PX30_PMU_CLKGATE_CON(1), 4, GFLAGS),
+
+ COMPOSITE_NOMUX(PCLK_PMU_PRE, "pclk_pmu_pre", "gpll", 0,
+ PX30_PMU_CLKSEL_CON(0), 0, 5, DFLAGS,
+ PX30_PMU_CLKGATE_CON(0), 0, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_REF24M_PMU, "clk_ref24m_pmu", "gpll", 0,
+ PX30_PMU_CLKSEL_CON(2), 0, 6, DFLAGS,
+ PX30_PMU_CLKGATE_CON(1), 8, GFLAGS),
+ COMPOSITE_NODIV(SCLK_USBPHY_REF, "clk_usbphy_ref", mux_usbphy_ref_p, CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKSEL_CON(2), 6, 1, MFLAGS,
+ PX30_PMU_CLKGATE_CON(1), 9, GFLAGS),
+ COMPOSITE_NODIV(SCLK_MIPIDSIPHY_REF, "clk_mipidsiphy_ref", mux_mipidsiphy_ref_p, CLK_SET_RATE_PARENT,
+ PX30_PMU_CLKSEL_CON(2), 7, 1, MFLAGS,
+ PX30_PMU_CLKGATE_CON(1), 10, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 9
+ */
+
+ /* PD_PMU */
+ GATE(0, "pclk_pmu_niu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "pclk_pmu_sgrf", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 2, GFLAGS),
+ GATE(0, "pclk_pmu_grf", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 3, GFLAGS),
+ GATE(0, "pclk_pmu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 4, GFLAGS),
+ GATE(0, "pclk_pmu_mem", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 5, GFLAGS),
+ GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_pre", 0, PX30_PMU_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(PCLK_UART0_PMU, "pclk_uart0_pmu", "pclk_pmu_pre", 0, PX30_PMU_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(0, "pclk_cru_pmu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, PX30_PMU_CLKGATE_CON(0), 8, GFLAGS),
+};
+
+static const char *const px30_pmucru_critical_clocks[] __initconst = {
+ "aclk_bus_pre",
+ "pclk_bus_pre",
+ "hclk_bus_pre",
+ "aclk_peri_pre",
+ "hclk_peri_pre",
+ "aclk_gpu_niu",
+ "pclk_top_pre",
+ "pclk_pmu_pre",
+ "hclk_usb_niu",
+ "pll_npll",
+ "usb480m",
+ "clk_uart2",
+ "pclk_uart2",
+};
+
+static void __iomem *px30_cru_base;
+static void __iomem *px30_pmucru_base;
+
+void px30_dump_cru(void)
+{
+ if (px30_cru_base) {
+ pr_warn("CRU:\n");
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET,
+ 32, 4, px30_cru_base,
+ 0x400, false);
+ }
+ if (px30_pmucru_base) {
+ pr_warn("PMU CRU:\n");
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET,
+ 32, 4, px30_pmucru_base,
+ 0x90, false);
+ }
+}
+EXPORT_SYMBOL_GPL(px30_dump_cru);
+
+static int px30_clk_panic(struct notifier_block *this,
+ unsigned long ev, void *ptr)
+{
+ px30_dump_cru();
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block px30_clk_panic_block = {
+ .notifier_call = px30_clk_panic,
+};
+
+static void __init px30_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+ struct clk *clk;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ px30_cru_base = reg_base;
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ iounmap(reg_base);
+ return;
+ }
+
+ /* aclk_dmac is controlled by sgrf_soc_con1[11]. */
+ clk = clk_register_fixed_factor(NULL, "aclk_dmac", "aclk_bus_pre", 0, 1, 1);
+ if (IS_ERR(clk))
+ pr_warn("%s: could not register clock aclk_dmac: %ld\n",
+ __func__, PTR_ERR(clk));
+ else
+ rockchip_clk_add_lookup(ctx, clk, ACLK_DMAC);
+
+ rockchip_clk_register_plls(ctx, px30_pll_clks,
+ ARRAY_SIZE(px30_pll_clks),
+ PX30_GRF_SOC_STATUS0);
+ rockchip_clk_register_branches(ctx, px30_clk_branches,
+ ARRAY_SIZE(px30_clk_branches));
+
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+ mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+ &px30_cpuclk_data, px30_cpuclk_rates,
+ ARRAY_SIZE(px30_cpuclk_rates));
+
+ rockchip_register_softrst(np, 12, reg_base + PX30_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_register_restart_notifier(ctx, PX30_GLB_SRST_FST, NULL);
+
+ rockchip_clk_of_add_provider(np, ctx);
+
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &px30_clk_panic_block);
+}
+
+CLK_OF_DECLARE(px30_cru, "rockchip,px30-cru", px30_clk_init);
+
+static void __init px30_pmu_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru pmu region\n", __func__);
+ return;
+ }
+
+ px30_pmucru_base = reg_base;
+
+ ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip pmu clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, px30_pmu_pll_clks,
+ ARRAY_SIZE(px30_pmu_pll_clks), PX30_GRF_SOC_STATUS0);
+
+ rockchip_clk_register_branches(ctx, px30_clk_pmu_branches,
+ ARRAY_SIZE(px30_clk_pmu_branches));
+
+ rockchip_clk_protect_critical(px30_pmucru_critical_clocks,
+ ARRAY_SIZE(px30_pmucru_critical_clocks));
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+CLK_OF_DECLARE(px30_cru_pmu, "rockchip,px30-pmucru", px30_pmu_clk_init);
+
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 7a3660c2bbb5..6b480b9921e3 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -34,7 +34,46 @@
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
-/* register positions shared by RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+/* register positions shared by PX30, RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define BOOST_PLL_H_CON(x) ((x) * 0x4)
+#define BOOST_CLK_CON 0x0008
+#define BOOST_BOOST_CON 0x000c
+#define BOOST_SWITCH_CNT 0x0010
+#define BOOST_HIGH_PERF_CNT0 0x0014
+#define BOOST_HIGH_PERF_CNT1 0x0018
+#define BOOST_STATIS_THRESHOLD 0x001c
+#define BOOST_SHORT_SWITCH_CNT 0x0020
+#define BOOST_SWITCH_THRESHOLD 0x0024
+#define BOOST_FSM_STATUS 0x0028
+#define BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x2c)
+#define BOOST_RECOVERY_MASK 0x1
+#define BOOST_RECOVERY_SHIFT 1
+#define BOOST_SW_CTRL_MASK 0x1
+#define BOOST_SW_CTRL_SHIFT 2
+#define BOOST_LOW_FREQ_EN_MASK 0x1
+#define BOOST_LOW_FREQ_EN_SHIFT 3
+#define BOOST_BUSY_STATE BIT(8)
+
+#define PX30_PLL_CON(x) ((x) * 0x4)
+#define PX30_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define PX30_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
+#define PX30_GLB_SRST_FST 0xb8
+#define PX30_GLB_SRST_SND 0xbc
+#define PX30_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
+#define PX30_MODE_CON 0xa0
+#define PX30_MISC_CON 0xa4
+#define PX30_SDMMC_CON0 0x380
+#define PX30_SDMMC_CON1 0x384
+#define PX30_SDIO_CON0 0x388
+#define PX30_SDIO_CON1 0x38c
+#define PX30_EMMC_CON0 0x390
+#define PX30_EMMC_CON1 0x394
+
+#define PX30_PMU_PLL_CON(x) ((x) * 0x4)
+#define PX30_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x40)
+#define PX30_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x80)
+#define PX30_PMU_MODE 0x0020
+
#define RV1108_PLL_CON(x) ((x) * 0x4)
#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
--
1.9.1
^ permalink raw reply related
* [v2, 00/10] Support DPAA PTP clock and timestamping
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
This patchset is to support DPAA FMAN PTP clock and HW timestamping.
- The patch #1 to patch #5 are to support DPAA FMAN 1588 timer in
ptp_qoriq driver.
- The patch #6 to patch #10 are to add HW timestamping support in
DPAA ethernet driver.
Yangbo Lu (10):
fsl/fman: share the event interrupt
ptp: support DPAA FMan 1588 timer in ptp_qoriq
dt-binding: ptp_qoriq: add DPAA FMan support
powerpc/mpc85xx: move ptp timer out of fman in dts
arm64: dts: fsl: move ptp timer out of fman
fsl/fman: add set_tstamp interface
fsl/fman_port: support getting timestamp field
fsl/fman: define frame description command UPD
dpaa_eth: add support for hardware timestamping
dpaa_eth: add the get_ts_info interface for ethtool
Documentation/devicetree/bindings/net/fsl-fman.txt | 25 +-----
.../devicetree/bindings/ptp/ptp-qoriq.txt | 15 +++-
arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi | 14 ++-
arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi | 14 ++-
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 101 ++++++++++++++++++-
drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 +
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 39 ++++++++
drivers/net/ethernet/freescale/fman/fman.c | 3 +-
drivers/net/ethernet/freescale/fman/fman.h | 1 +
drivers/net/ethernet/freescale/fman/fman_dtsec.c | 27 +++++
drivers/net/ethernet/freescale/fman/fman_dtsec.h | 1 +
drivers/net/ethernet/freescale/fman/fman_memac.c | 5 +
drivers/net/ethernet/freescale/fman/fman_memac.h | 1 +
drivers/net/ethernet/freescale/fman/fman_port.c | 12 +++
drivers/net/ethernet/freescale/fman/fman_port.h | 3 +
drivers/net/ethernet/freescale/fman/fman_tgec.c | 21 ++++
drivers/net/ethernet/freescale/fman/fman_tgec.h | 1 +
drivers/net/ethernet/freescale/fman/mac.c | 3 +
drivers/net/ethernet/freescale/fman/mac.h | 1 +
drivers/ptp/Kconfig | 2 +-
drivers/ptp/ptp_qoriq.c | 104 ++++++++++++-------
include/linux/fsl/ptp_qoriq.h | 38 ++++++--
26 files changed, 375 insertions(+), 115 deletions(-)
^ permalink raw reply
* [v2, 01/10] fsl/fman: share the event interrupt
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to share fman event interrupt because
the 1588 timer driver will also use this interrupt.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index 9530405..c415ac6 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -2801,7 +2801,8 @@ static irqreturn_t fman_irq(int irq, void *handle)
of_node_put(muram_node);
of_node_put(fm_node);
- err = devm_request_irq(&of_dev->dev, irq, fman_irq, 0, "fman", fman);
+ err = devm_request_irq(&of_dev->dev, irq, fman_irq, IRQF_SHARED,
+ "fman", fman);
if (err < 0) {
dev_err(&of_dev->dev, "%s: irq %d allocation failed (error = %d)\n",
__func__, irq, err);
--
1.7.1
^ permalink raw reply related
* [v2, 02/10] ptp: support DPAA FMan 1588 timer in ptp_qoriq
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to support DPAA (Data Path Acceleration Architecture)
1588 timer by adding "fsl,fman-ptp-timer" compatible, sharing
interrupt with FMan, adding FSL_DPAA_ETH dependency, and fixing
up register offset.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
drivers/ptp/Kconfig | 2 +-
drivers/ptp/ptp_qoriq.c | 104 ++++++++++++++++++++++++++---------------
include/linux/fsl/ptp_qoriq.h | 38 ++++++++++++---
3 files changed, 98 insertions(+), 46 deletions(-)
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 474c988..d137c48 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -43,7 +43,7 @@ config PTP_1588_CLOCK_DTE
config PTP_1588_CLOCK_QORIQ
tristate "Freescale QorIQ 1588 timer as PTP clock"
- depends on GIANFAR
+ depends on GIANFAR || FSL_DPAA_ETH
depends on PTP_1588_CLOCK
default y
help
diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index 1468a16..c4e3545 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -39,11 +39,12 @@
/* Caller must hold qoriq_ptp->lock. */
static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u64 ns;
u32 lo, hi;
- lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l);
- hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h);
+ lo = qoriq_read(®s->ctrl_regs->tmr_cnt_l);
+ hi = qoriq_read(®s->ctrl_regs->tmr_cnt_h);
ns = ((u64) hi) << 32;
ns |= lo;
return ns;
@@ -52,16 +53,18 @@ static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
/* Caller must hold qoriq_ptp->lock. */
static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u32 hi = ns >> 32;
u32 lo = ns & 0xffffffff;
- qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo);
- qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi);
+ qoriq_write(®s->ctrl_regs->tmr_cnt_l, lo);
+ qoriq_write(®s->ctrl_regs->tmr_cnt_h, hi);
}
/* Caller must hold qoriq_ptp->lock. */
static void set_alarm(struct qoriq_ptp *qoriq_ptp)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u64 ns;
u32 lo, hi;
@@ -70,16 +73,18 @@ static void set_alarm(struct qoriq_ptp *qoriq_ptp)
ns -= qoriq_ptp->tclk_period;
hi = ns >> 32;
lo = ns & 0xffffffff;
- qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo);
- qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi);
+ qoriq_write(®s->alarm_regs->tmr_alarm1_l, lo);
+ qoriq_write(®s->alarm_regs->tmr_alarm1_h, hi);
}
/* Caller must hold qoriq_ptp->lock. */
static void set_fipers(struct qoriq_ptp *qoriq_ptp)
{
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
+
set_alarm(qoriq_ptp);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
+ qoriq_write(®s->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
+ qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
}
/*
@@ -89,16 +94,17 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp)
static irqreturn_t isr(int irq, void *priv)
{
struct qoriq_ptp *qoriq_ptp = priv;
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
struct ptp_clock_event event;
u64 ns;
u32 ack = 0, lo, hi, mask, val;
- val = qoriq_read(&qoriq_ptp->regs->tmr_tevent);
+ val = qoriq_read(®s->ctrl_regs->tmr_tevent);
if (val & ETS1) {
ack |= ETS1;
- hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h);
- lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l);
+ hi = qoriq_read(®s->etts_regs->tmr_etts1_h);
+ lo = qoriq_read(®s->etts_regs->tmr_etts1_l);
event.type = PTP_CLOCK_EXTTS;
event.index = 0;
event.timestamp = ((u64) hi) << 32;
@@ -108,8 +114,8 @@ static irqreturn_t isr(int irq, void *priv)
if (val & ETS2) {
ack |= ETS2;
- hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h);
- lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l);
+ hi = qoriq_read(®s->etts_regs->tmr_etts2_h);
+ lo = qoriq_read(®s->etts_regs->tmr_etts2_l);
event.type = PTP_CLOCK_EXTTS;
event.index = 1;
event.timestamp = ((u64) hi) << 32;
@@ -130,16 +136,16 @@ static irqreturn_t isr(int irq, void *priv)
hi = ns >> 32;
lo = ns & 0xffffffff;
spin_lock(&qoriq_ptp->lock);
- qoriq_write(&qoriq_ptp->regs->tmr_alarm2_l, lo);
- qoriq_write(&qoriq_ptp->regs->tmr_alarm2_h, hi);
+ qoriq_write(®s->alarm_regs->tmr_alarm2_l, lo);
+ qoriq_write(®s->alarm_regs->tmr_alarm2_h, hi);
spin_unlock(&qoriq_ptp->lock);
qoriq_ptp->alarm_value = ns;
} else {
- qoriq_write(&qoriq_ptp->regs->tmr_tevent, ALM2);
+ qoriq_write(®s->ctrl_regs->tmr_tevent, ALM2);
spin_lock(&qoriq_ptp->lock);
- mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
+ mask = qoriq_read(®s->ctrl_regs->tmr_temask);
mask &= ~ALM2EN;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
+ qoriq_write(®s->ctrl_regs->tmr_temask, mask);
spin_unlock(&qoriq_ptp->lock);
qoriq_ptp->alarm_value = 0;
qoriq_ptp->alarm_interval = 0;
@@ -153,7 +159,7 @@ static irqreturn_t isr(int irq, void *priv)
}
if (ack) {
- qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack);
+ qoriq_write(®s->ctrl_regs->tmr_tevent, ack);
return IRQ_HANDLED;
} else
return IRQ_NONE;
@@ -169,6 +175,7 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
u32 tmr_add;
int neg_adj = 0;
struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
if (scaled_ppm < 0) {
neg_adj = 1;
@@ -186,7 +193,7 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
- qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add);
+ qoriq_write(®s->ctrl_regs->tmr_add, tmr_add);
return 0;
}
@@ -250,6 +257,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
unsigned long flags;
u32 bit, mask;
@@ -266,23 +274,23 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
return -EINVAL;
}
spin_lock_irqsave(&qoriq_ptp->lock, flags);
- mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
+ mask = qoriq_read(®s->ctrl_regs->tmr_temask);
if (on)
mask |= bit;
else
mask &= ~bit;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
+ qoriq_write(®s->ctrl_regs->tmr_temask, mask);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;
case PTP_CLK_REQ_PPS:
spin_lock_irqsave(&qoriq_ptp->lock, flags);
- mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
+ mask = qoriq_read(®s->ctrl_regs->tmr_temask);
if (on)
mask |= PP1EN;
else
mask &= ~PP1EN;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
+ qoriq_write(®s->ctrl_regs->tmr_temask, mask);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;
@@ -313,10 +321,12 @@ static int qoriq_ptp_probe(struct platform_device *dev)
{
struct device_node *node = dev->dev.of_node;
struct qoriq_ptp *qoriq_ptp;
+ struct qoriq_ptp_registers *regs;
struct timespec64 now;
int err = -ENOMEM;
u32 tmr_ctrl;
unsigned long flags;
+ void __iomem *base;
qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
if (!qoriq_ptp)
@@ -351,7 +361,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
pr_err("irq not in device tree\n");
goto no_node;
}
- if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) {
+ if (request_irq(qoriq_ptp->irq, isr, IRQF_SHARED, DRIVER, qoriq_ptp)) {
pr_err("request_irq failed\n");
goto no_node;
}
@@ -368,12 +378,27 @@ static int qoriq_ptp_probe(struct platform_device *dev)
spin_lock_init(&qoriq_ptp->lock);
- qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start,
- resource_size(qoriq_ptp->rsrc));
- if (!qoriq_ptp->regs) {
+ base = ioremap(qoriq_ptp->rsrc->start,
+ resource_size(qoriq_ptp->rsrc));
+ if (!base) {
pr_err("ioremap ptp registers failed\n");
goto no_ioremap;
}
+
+ qoriq_ptp->base = base;
+
+ if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) {
+ qoriq_ptp->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET;
+ qoriq_ptp->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET;
+ qoriq_ptp->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET;
+ qoriq_ptp->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET;
+ } else {
+ qoriq_ptp->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
+ qoriq_ptp->regs.alarm_regs = base + ALARM_REGS_OFFSET;
+ qoriq_ptp->regs.fiper_regs = base + FIPER_REGS_OFFSET;
+ qoriq_ptp->regs.etts_regs = base + ETTS_REGS_OFFSET;
+ }
+
getnstimeofday64(&now);
ptp_qoriq_settime(&qoriq_ptp->caps, &now);
@@ -383,13 +408,14 @@ static int qoriq_ptp_probe(struct platform_device *dev)
spin_lock_irqsave(&qoriq_ptp->lock, flags);
- qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl);
- qoriq_write(&qoriq_ptp->regs->tmr_add, qoriq_ptp->tmr_add);
- qoriq_write(&qoriq_ptp->regs->tmr_prsc, qoriq_ptp->tmr_prsc);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
- qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
+ regs = &qoriq_ptp->regs;
+ qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl);
+ qoriq_write(®s->ctrl_regs->tmr_add, qoriq_ptp->tmr_add);
+ qoriq_write(®s->ctrl_regs->tmr_prsc, qoriq_ptp->tmr_prsc);
+ qoriq_write(®s->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
+ qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
set_alarm(qoriq_ptp);
- qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
+ qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
@@ -405,7 +431,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
return 0;
no_clock:
- iounmap(qoriq_ptp->regs);
+ iounmap(qoriq_ptp->base);
no_ioremap:
release_resource(qoriq_ptp->rsrc);
no_resource:
@@ -419,12 +445,13 @@ static int qoriq_ptp_probe(struct platform_device *dev)
static int qoriq_ptp_remove(struct platform_device *dev)
{
struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
+ struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
- qoriq_write(&qoriq_ptp->regs->tmr_temask, 0);
- qoriq_write(&qoriq_ptp->regs->tmr_ctrl, 0);
+ qoriq_write(®s->ctrl_regs->tmr_temask, 0);
+ qoriq_write(®s->ctrl_regs->tmr_ctrl, 0);
ptp_clock_unregister(qoriq_ptp->clock);
- iounmap(qoriq_ptp->regs);
+ iounmap(qoriq_ptp->base);
release_resource(qoriq_ptp->rsrc);
free_irq(qoriq_ptp->irq, qoriq_ptp);
kfree(qoriq_ptp);
@@ -434,6 +461,7 @@ static int qoriq_ptp_remove(struct platform_device *dev)
static const struct of_device_id match_table[] = {
{ .compatible = "fsl,etsec-ptp" },
+ { .compatible = "fsl,fman-ptp-timer" },
{},
};
MODULE_DEVICE_TABLE(of, match_table);
diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h
index b462d9e..dc3dac4 100644
--- a/include/linux/fsl/ptp_qoriq.h
+++ b/include/linux/fsl/ptp_qoriq.h
@@ -11,9 +11,8 @@
/*
* qoriq ptp registers
- * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
*/
-struct qoriq_ptp_registers {
+struct ctrl_regs {
u32 tmr_ctrl; /* Timer control register */
u32 tmr_tevent; /* Timestamp event register */
u32 tmr_temask; /* Timer event mask register */
@@ -28,22 +27,47 @@ struct qoriq_ptp_registers {
u8 res1[4];
u32 tmroff_h; /* Timer offset high */
u32 tmroff_l; /* Timer offset low */
- u8 res2[8];
+};
+
+struct alarm_regs {
u32 tmr_alarm1_h; /* Timer alarm 1 high register */
u32 tmr_alarm1_l; /* Timer alarm 1 high register */
u32 tmr_alarm2_h; /* Timer alarm 2 high register */
u32 tmr_alarm2_l; /* Timer alarm 2 high register */
- u8 res3[48];
+};
+
+struct fiper_regs {
u32 tmr_fiper1; /* Timer fixed period interval */
u32 tmr_fiper2; /* Timer fixed period interval */
u32 tmr_fiper3; /* Timer fixed period interval */
- u8 res4[20];
+};
+
+struct etts_regs {
u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */
u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */
u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */
u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */
};
+struct qoriq_ptp_registers {
+ struct ctrl_regs __iomem *ctrl_regs;
+ struct alarm_regs __iomem *alarm_regs;
+ struct fiper_regs __iomem *fiper_regs;
+ struct etts_regs __iomem *etts_regs;
+};
+
+/* Offset definitions for the four register groups */
+#define CTRL_REGS_OFFSET 0x0
+#define ALARM_REGS_OFFSET 0x40
+#define FIPER_REGS_OFFSET 0x80
+#define ETTS_REGS_OFFSET 0xa0
+
+#define FMAN_CTRL_REGS_OFFSET 0x80
+#define FMAN_ALARM_REGS_OFFSET 0xb8
+#define FMAN_FIPER_REGS_OFFSET 0xd0
+#define FMAN_ETTS_REGS_OFFSET 0xe0
+
+
/* Bit definitions for the TMR_CTRL register */
#define ALM1P (1<<31) /* Alarm1 output polarity */
#define ALM2P (1<<30) /* Alarm2 output polarity */
@@ -105,10 +129,10 @@ struct qoriq_ptp_registers {
#define DRIVER "ptp_qoriq"
#define DEFAULT_CKSEL 1
#define N_EXT_TS 2
-#define REG_SIZE sizeof(struct qoriq_ptp_registers)
struct qoriq_ptp {
- struct qoriq_ptp_registers __iomem *regs;
+ void __iomem *base;
+ struct qoriq_ptp_registers regs;
spinlock_t lock; /* protects regs */
struct ptp_clock *clock;
struct ptp_clock_info caps;
--
1.7.1
^ permalink raw reply related
* [v2, 03/10] dt-binding: ptp_qoriq: add DPAA FMan support
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to add bindings description for DPAA
FMan 1588 timer, and also remove its description in
fsl-fman dt-bindings document.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
Documentation/devicetree/bindings/net/fsl-fman.txt | 25 +-------------------
.../devicetree/bindings/ptp/ptp-qoriq.txt | 15 +++++++++--
2 files changed, 13 insertions(+), 27 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/fsl-fman.txt b/Documentation/devicetree/bindings/net/fsl-fman.txt
index df873d1..74603dd 100644
--- a/Documentation/devicetree/bindings/net/fsl-fman.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fman.txt
@@ -356,30 +356,7 @@ ethernet at e0000 {
============================================================================
FMan IEEE 1588 Node
-DESCRIPTION
-
-The FMan interface to support IEEE 1588
-
-
-PROPERTIES
-
-- compatible
- Usage: required
- Value type: <stringlist>
- Definition: A standard property.
- Must include "fsl,fman-ptp-timer".
-
-- reg
- Usage: required
- Value type: <prop-encoded-array>
- Definition: A standard property.
-
-EXAMPLE
-
-ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
-};
+Refer to Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
=============================================================================
FMan MDIO Node
diff --git a/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt b/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
index 0f569d8..c5d0e79 100644
--- a/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
+++ b/Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
@@ -2,7 +2,8 @@
General Properties:
- - compatible Should be "fsl,etsec-ptp"
+ - compatible Should be "fsl,etsec-ptp" for eTSEC
+ Should be "fsl,fman-ptp-timer" for DPAA FMan
- reg Offset and length of the register set for the device
- interrupts There should be at least two interrupts. Some devices
have as many as four PTP related interrupts.
@@ -43,14 +44,22 @@ Clock Properties:
value, which will be directly written in those bits, that is why,
according to reference manual, the next clock sources can be used:
+ For eTSEC,
<0> - external high precision timer reference clock (TSEC_TMR_CLK
input is used for this purpose);
<1> - eTSEC system clock;
<2> - eTSEC1 transmit clock;
<3> - RTC clock input.
- When this attribute is not used, eTSEC system clock will serve as
- IEEE 1588 timer reference clock.
+ For DPAA FMan,
+ <0> - external high precision timer reference clock (TMR_1588_CLK)
+ <1> - MAC system clock (1/2 FMan clock)
+ <2> - reserved
+ <3> - RTC clock oscillator
+
+ When this attribute is not used, the IEEE 1588 timer reference clock
+ will use the eTSEC system clock (for Gianfar) or the MAC system
+ clock (for DPAA).
Example:
--
1.7.1
^ permalink raw reply related
* [v2, 04/10] powerpc/mpc85xx: move ptp timer out of fman in dts
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to move ptp timer node out of fman.
Because ptp timer will be probed by ptp_qoriq driver,
it should be an independent device in case of conflict
memory mapping.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi | 14 ++++++++------
arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi | 14 ++++++++------
5 files changed, 40 insertions(+), 30 deletions(-)
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
index abd01d4..6b124f7 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman at 400000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0 0x400000 0x100000>;
- reg = <0x400000 0x100000>;
+ ranges = <0 0x400000 0xfe000>;
+ reg = <0x400000 0xfe000>;
interrupts = <96 2 0 0>, <16 2 1 1>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x40 0xc>;
+ ptimer-handle = <&ptp_timer0>;
muram at 0 {
compatible = "fsl,fman-muram";
@@ -93,9 +94,10 @@ fman0: fman at 400000 {
reg = <0x87000 0x1000>;
status = "disabled";
};
+};
- ptp_timer0: ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer at 4fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x4fe000 0x1000>;
+ interrupts = <96 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
index debea75..b80aaf5 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
@@ -37,12 +37,13 @@ fman1: fman at 500000 {
#size-cells = <1>;
cell-index = <1>;
compatible = "fsl,fman";
- ranges = <0 0x500000 0x100000>;
- reg = <0x500000 0x100000>;
+ ranges = <0 0x500000 0xfe000>;
+ reg = <0x500000 0xfe000>;
interrupts = <97 2 0 0>, <16 2 1 0>;
clocks = <&clockgen 3 1>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x60 0xc>;
+ ptimer-handle = <&ptp_timer1>;
muram at 0 {
compatible = "fsl,fman-muram";
@@ -93,9 +94,10 @@ fman1: fman at 500000 {
reg = <0x87000 0x1000>;
status = "disabled";
};
+};
- ptp_timer1: ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer1: ptp-timer at 5fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x5fe000 0x1000>;
+ interrupts = <97 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
index 3a20e0d..d3720fd 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman at 400000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0 0x400000 0x100000>;
- reg = <0x400000 0x100000>;
+ ranges = <0 0x400000 0xfe000>;
+ reg = <0x400000 0xfe000>;
interrupts = <96 2 0 0>, <16 2 1 1>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x800 0x10>;
+ ptimer-handle = <&ptp_timer0>;
muram at 0 {
compatible = "fsl,fman-muram";
@@ -98,9 +99,10 @@ fman0: fman at 400000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};
- ptp_timer0: ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer at 4fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x4fe000 0x1000>;
+ interrupts = <96 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
index 82750ac..ae34c20 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
@@ -37,12 +37,13 @@ fman1: fman at 500000 {
#size-cells = <1>;
cell-index = <1>;
compatible = "fsl,fman";
- ranges = <0 0x500000 0x100000>;
- reg = <0x500000 0x100000>;
+ ranges = <0 0x500000 0xfe000>;
+ reg = <0x500000 0xfe000>;
interrupts = <97 2 0 0>, <16 2 1 0>;
clocks = <&clockgen 3 1>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x820 0x10>;
+ ptimer-handle = <&ptp_timer1>;
muram at 0 {
compatible = "fsl,fman-muram";
@@ -98,9 +99,10 @@ fman1: fman at 500000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};
- ptp_timer1: ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer1: ptp-timer at 5fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x5fe000 0x1000>;
+ interrupts = <97 2 0 0>;
};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
index 7f60b60..02f2755 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman at 400000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0 0x400000 0x100000>;
- reg = <0x400000 0x100000>;
+ ranges = <0 0x400000 0xfe000>;
+ reg = <0x400000 0xfe000>;
interrupts = <96 2 0 0>, <16 2 1 1>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x800 0x10>;
+ ptimer-handle = <&ptp_timer0>;
muram at 0 {
compatible = "fsl,fman-muram";
@@ -86,9 +87,10 @@ fman0: fman at 400000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};
- ptp_timer0: ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer at 4fe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x4fe000 0x1000>;
+ interrupts = <96 2 0 0>;
};
--
1.7.1
^ permalink raw reply related
* [v2, 05/10] arm64: dts: fsl: move ptp timer out of fman
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to move ptp timer node out of fman.
Because ptp timer will be probed by ptp_qoriq driver,
it should be an independent device in case of conflict
memory mapping.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- Fixed address-cells for ptp-timer.
---
arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
index 4dd0676..a56a408 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
@@ -11,13 +11,14 @@ fman0: fman at 1a00000 {
#size-cells = <1>;
cell-index = <0>;
compatible = "fsl,fman";
- ranges = <0x0 0x0 0x1a00000 0x100000>;
- reg = <0x0 0x1a00000 0x0 0x100000>;
+ ranges = <0x0 0x0 0x1a00000 0xfe000>;
+ reg = <0x0 0x1a00000 0x0 0xfe000>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen 3 0>;
clock-names = "fmanclk";
fsl,qman-channel-range = <0x800 0x10>;
+ ptimer-handle = <&ptp_timer0>;
muram at 0 {
compatible = "fsl,fman-muram";
@@ -73,9 +74,10 @@ fman0: fman at 1a00000 {
compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
reg = <0xfd000 0x1000>;
};
+};
- ptp_timer0: ptp-timer at fe000 {
- compatible = "fsl,fman-ptp-timer";
- reg = <0xfe000 0x1000>;
- };
+ptp_timer0: ptp-timer at 1afe000 {
+ compatible = "fsl,fman-ptp-timer";
+ reg = <0x0 0x1afe000 0x0 0x1000>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
};
--
1.7.1
^ permalink raw reply related
* [v2, 06/10] fsl/fman: add set_tstamp interface
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to add set_tstamp interface for memac,
dtsec, and 10GEC controllers to configure HW timestamping.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman_dtsec.c | 27 ++++++++++++++++++++++
drivers/net/ethernet/freescale/fman/fman_dtsec.h | 1 +
drivers/net/ethernet/freescale/fman/fman_memac.c | 5 ++++
drivers/net/ethernet/freescale/fman/fman_memac.h | 1 +
drivers/net/ethernet/freescale/fman/fman_tgec.c | 21 +++++++++++++++++
drivers/net/ethernet/freescale/fman/fman_tgec.h | 1 +
drivers/net/ethernet/freescale/fman/mac.c | 3 ++
drivers/net/ethernet/freescale/fman/mac.h | 1 +
8 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 57b1e2b..1ca543a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -123,11 +123,13 @@
#define DTSEC_ECNTRL_R100M 0x00000008
#define DTSEC_ECNTRL_QSGMIIM 0x00000001
+#define TCTRL_TTSE 0x00000040
#define TCTRL_GTS 0x00000020
#define RCTRL_PAL_MASK 0x001f0000
#define RCTRL_PAL_SHIFT 16
#define RCTRL_GHTX 0x00000400
+#define RCTRL_RTSE 0x00000040
#define RCTRL_GRS 0x00000020
#define RCTRL_MPROM 0x00000008
#define RCTRL_RSF 0x00000004
@@ -1136,6 +1138,31 @@ int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
return 0;
}
+int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable)
+{
+ struct dtsec_regs __iomem *regs = dtsec->regs;
+ u32 rctrl, tctrl;
+
+ if (!is_init_done(dtsec->dtsec_drv_param))
+ return -EINVAL;
+
+ rctrl = ioread32be(®s->rctrl);
+ tctrl = ioread32be(®s->tctrl);
+
+ if (enable) {
+ rctrl |= RCTRL_RTSE;
+ tctrl |= TCTRL_TTSE;
+ } else {
+ rctrl &= ~RCTRL_RTSE;
+ tctrl &= ~TCTRL_TTSE;
+ }
+
+ iowrite32be(rctrl, ®s->rctrl);
+ iowrite32be(tctrl, ®s->tctrl);
+
+ return 0;
+}
+
int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
{
struct dtsec_regs __iomem *regs = dtsec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index 1a689ad..5149d96 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -56,5 +56,6 @@ int dtsec_set_exception(struct fman_mac *dtsec,
int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version);
int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable);
+int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable);
#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 446a97b..bc6eb30 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -964,6 +964,11 @@ int memac_set_allmulti(struct fman_mac *memac, bool enable)
return 0;
}
+int memac_set_tstamp(struct fman_mac *memac, bool enable)
+{
+ return 0; /* Always enabled. */
+}
+
int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
{
struct memac_regs __iomem *regs = memac->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index b5a5033..b2c671e 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -58,5 +58,6 @@ int memac_set_exception(struct fman_mac *memac,
int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
int memac_set_allmulti(struct fman_mac *memac, bool enable);
+int memac_set_tstamp(struct fman_mac *memac, bool enable);
#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 284735d..4070593 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -44,6 +44,7 @@
#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff
/* Command and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_EN_TIMESTAMP 0x00100000
#define CMD_CFG_NO_LEN_CHK 0x00020000
#define CMD_CFG_PAUSE_IGNORE 0x00000100
#define CMF_CFG_CRC_FWD 0x00000040
@@ -588,6 +589,26 @@ int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
return 0;
}
+int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
+{
+ struct tgec_regs __iomem *regs = tgec->regs;
+ u32 tmp;
+
+ if (!is_init_done(tgec->cfg))
+ return -EINVAL;
+
+ tmp = ioread32be(®s->command_config);
+
+ if (enable)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ else
+ tmp &= ~CMD_CFG_EN_TIMESTAMP;
+
+ iowrite32be(tmp, ®s->command_config);
+
+ return 0;
+}
+
int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
{
struct tgec_regs __iomem *regs = tgec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index cbbd3b4..3bfd106 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -52,5 +52,6 @@ int tgec_set_exception(struct fman_mac *tgec,
int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
int tgec_get_version(struct fman_mac *tgec, u32 *mac_version);
int tgec_set_allmulti(struct fman_mac *tgec, bool enable);
+int tgec_set_tstamp(struct fman_mac *tgec, bool enable);
#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 7b5b95f..a847b9c 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -471,6 +471,7 @@ static void setup_dtsec(struct mac_device *mac_dev)
mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames;
mac_dev->set_exception = dtsec_set_exception;
mac_dev->set_allmulti = dtsec_set_allmulti;
+ mac_dev->set_tstamp = dtsec_set_tstamp;
mac_dev->set_multi = set_multi;
mac_dev->start = start;
mac_dev->stop = stop;
@@ -490,6 +491,7 @@ static void setup_tgec(struct mac_device *mac_dev)
mac_dev->set_rx_pause = tgec_accept_rx_pause_frames;
mac_dev->set_exception = tgec_set_exception;
mac_dev->set_allmulti = tgec_set_allmulti;
+ mac_dev->set_tstamp = tgec_set_tstamp;
mac_dev->set_multi = set_multi;
mac_dev->start = start;
mac_dev->stop = stop;
@@ -509,6 +511,7 @@ static void setup_memac(struct mac_device *mac_dev)
mac_dev->set_rx_pause = memac_accept_rx_pause_frames;
mac_dev->set_exception = memac_set_exception;
mac_dev->set_allmulti = memac_set_allmulti;
+ mac_dev->set_tstamp = memac_set_tstamp;
mac_dev->set_multi = set_multi;
mac_dev->start = start;
mac_dev->stop = stop;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index b520cec..824a81a 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -68,6 +68,7 @@ struct mac_device {
int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
int (*change_addr)(struct fman_mac *mac_dev, enet_addr_t *enet_addr);
int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
+ int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
int (*set_multi)(struct net_device *net_dev,
struct mac_device *mac_dev);
int (*set_rx_pause)(struct fman_mac *mac_dev, bool en);
--
1.7.1
^ permalink raw reply related
* [v2, 07/10] fsl/fman_port: support getting timestamp field
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to add fman_port_get_tstamp_field() interface
to get timestamp field data.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman_port.c | 12 ++++++++++++
drivers/net/ethernet/freescale/fman/fman_port.h | 3 +++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c
index ce6e24c..86f0094 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1731,6 +1731,18 @@ int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset)
}
EXPORT_SYMBOL(fman_port_get_hash_result_offset);
+int fman_port_get_tstamp_field(struct fman_port *port, const void *data,
+ u64 *tstamp)
+{
+ if (port->buffer_offsets.time_stamp_offset == ILLEGAL_BASE)
+ return -EINVAL;
+
+ *tstamp = *(u64 *)(data + port->buffer_offsets.time_stamp_offset);
+
+ return 0;
+}
+EXPORT_SYMBOL(fman_port_get_tstamp_field);
+
static int fman_port_probe(struct platform_device *of_dev)
{
struct fman_port *port;
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h b/drivers/net/ethernet/freescale/fman/fman_port.h
index e86ca6a..d10e48d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.h
+++ b/drivers/net/ethernet/freescale/fman/fman_port.h
@@ -153,6 +153,9 @@ int fman_port_cfg_buf_prefix_content(struct fman_port *port,
int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset);
+int fman_port_get_tstamp_field(struct fman_port *port, const void *data,
+ u64 *tstamp);
+
struct fman_port *fman_port_bind(struct device *dev);
#endif /* __FMAN_PORT_H */
--
1.7.1
^ permalink raw reply related
* [v2, 08/10] fsl/fman: define frame description command UPD
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
Defined frame description command FM_FD_CMD_UPD for
prepended data updating.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- None.
---
drivers/net/ethernet/freescale/fman/fman.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h
index bfa02e0..935c317 100644
--- a/drivers/net/ethernet/freescale/fman/fman.h
+++ b/drivers/net/ethernet/freescale/fman/fman.h
@@ -41,6 +41,7 @@
/* Frame queue Context Override */
#define FM_FD_CMD_FCO 0x80000000
#define FM_FD_CMD_RPD 0x40000000 /* Read Prepended Data */
+#define FM_FD_CMD_UPD 0x20000000 /* Update Prepended Data */
#define FM_FD_CMD_DTC 0x10000000 /* Do L4 Checksum */
/* TX-Port: Unsupported Format */
--
1.7.1
^ permalink raw reply related
* [v2, 09/10] dpaa_eth: add support for hardware timestamping
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
This patch is to add hardware timestamping support
for dpaa_eth. On Rx, timestamping is enabled for
all frames. On Tx, we only instruct the hardware
to timestamp the frames marked accordingly by the
stack.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- Removed ifdef for timestamp code.
- Minor fixes for code style.
---
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 101 ++++++++++++++++++++++-
drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 +
2 files changed, 99 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index fd43f98..bd589ac 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1168,7 +1168,7 @@ static int dpaa_eth_init_tx_port(struct fman_port *port, struct dpaa_fq *errq,
buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
buf_prefix_content.pass_prs_result = true;
buf_prefix_content.pass_hash_result = true;
- buf_prefix_content.pass_time_stamp = false;
+ buf_prefix_content.pass_time_stamp = true;
buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
params.specific_params.non_rx_params.err_fqid = errq->fqid;
@@ -1210,7 +1210,7 @@ static int dpaa_eth_init_rx_port(struct fman_port *port, struct dpaa_bp **bps,
buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
buf_prefix_content.pass_prs_result = true;
buf_prefix_content.pass_hash_result = true;
- buf_prefix_content.pass_time_stamp = false;
+ buf_prefix_content.pass_time_stamp = true;
buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
rx_p = ¶ms.specific_params.rx_params;
@@ -1592,6 +1592,16 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
return 0;
}
+static int dpaa_get_tstamp_ns(struct net_device *net_dev, u64 *ns,
+ struct fman_port *port, const void *data)
+{
+ if (!fman_port_get_tstamp_field(port, data, ns)) {
+ be64_to_cpus(ns);
+ return 0;
+ }
+ return -EINVAL;
+}
+
/* Cleanup function for outgoing frame descriptors that were built on Tx path,
* either contiguous frames or scatter/gather ones.
* Skb freeing is not handled here.
@@ -1607,14 +1617,29 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
{
const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
struct device *dev = priv->net_dev->dev.parent;
+ struct skb_shared_hwtstamps shhwtstamps;
dma_addr_t addr = qm_fd_addr(fd);
const struct qm_sg_entry *sgt;
struct sk_buff **skbh, *skb;
int nr_frags, i;
+ u64 ns;
skbh = (struct sk_buff **)phys_to_virt(addr);
skb = *skbh;
+ if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+
+ if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
+ priv->mac_dev->port[TX],
+ (void *)skbh)) {
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ } else {
+ dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
+ }
+ }
+
if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
nr_frags = skb_shinfo(skb)->nr_frags;
dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
@@ -2086,6 +2111,11 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
if (unlikely(err < 0))
goto skb_to_fd_failed;
+ if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+ fd.cmd |= FM_FD_CMD_UPD;
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ }
+
if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
return NETDEV_TX_OK;
@@ -2227,6 +2257,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
struct qman_fq *fq,
const struct qm_dqrr_entry *dq)
{
+ struct skb_shared_hwtstamps *shhwtstamps;
struct rtnl_link_stats64 *percpu_stats;
struct dpaa_percpu_priv *percpu_priv;
const struct qm_fd *fd = &dq->fd;
@@ -2240,6 +2271,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
struct sk_buff *skb;
int *count_ptr;
void *vaddr;
+ u64 ns;
fd_status = be32_to_cpu(fd->status);
fd_format = qm_fd_get_format(fd);
@@ -2304,6 +2336,18 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
if (!skb)
return qman_cb_dqrr_consume;
+ if (priv->rx_tstamp) {
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+ if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
+ priv->mac_dev->port[RX],
+ vaddr))
+ shhwtstamps->hwtstamp = ns_to_ktime(ns);
+ else
+ dev_warn(net_dev->dev.parent, "dpaa_get_tstamp_ns failed!\n");
+ }
+
skb->protocol = eth_type_trans(skb, net_dev);
if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use &&
@@ -2523,11 +2567,58 @@ static int dpaa_eth_stop(struct net_device *net_dev)
return err;
}
+static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct dpaa_priv *priv = netdev_priv(dev);
+ struct hwtstamp_config config;
+
+ if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ /* Couldn't disable rx/tx timestamping separately.
+ * Do nothing here.
+ */
+ priv->tx_tstamp = false;
+ break;
+ case HWTSTAMP_TX_ON:
+ priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac, true);
+ priv->tx_tstamp = true;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
+ /* Couldn't disable rx/tx timestamping separately.
+ * Do nothing here.
+ */
+ priv->rx_tstamp = false;
+ } else {
+ priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac, true);
+ priv->rx_tstamp = true;
+ /* TS is set for all frame types, not only those requested */
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ }
+
+ return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+
static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
{
- if (!net_dev->phydev)
- return -EINVAL;
- return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+ int ret = -EINVAL;
+
+ if (cmd == SIOCGMIIREG) {
+ if (net_dev->phydev)
+ return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+ }
+
+ if (cmd == SIOCSHWTSTAMP)
+ return dpaa_ts_ioctl(net_dev, rq, cmd);
+
+ return ret;
}
static const struct net_device_ops dpaa_ops = {
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
index bd94220..af320f8 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
@@ -182,6 +182,9 @@ struct dpaa_priv {
struct dpaa_buffer_layout buf_layout[2];
u16 rx_headroom;
+
+ bool tx_tstamp; /* Tx timestamping enabled */
+ bool rx_tstamp; /* Rx timestamping enabled */
};
/* from dpaa_ethtool.c */
--
1.7.1
^ permalink raw reply related
* [v2, 10/10] dpaa_eth: add the get_ts_info interface for ethtool
From: Yangbo Lu @ 2018-06-07 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>
Added the get_ts_info interface for ethtool to check
the timestamping capability.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
- Removed ifdef for hw timestamp.
---
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 39 ++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
index 2f933b6..3184c8f 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -32,6 +32,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/string.h>
+#include <linux/of_platform.h>
+#include <linux/net_tstamp.h>
+#include <linux/fsl/ptp_qoriq.h>
#include "dpaa_eth.h"
#include "mac.h"
@@ -515,6 +518,41 @@ static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
return ret;
}
+static int dpaa_get_ts_info(struct net_device *net_dev,
+ struct ethtool_ts_info *info)
+{
+ struct device *dev = net_dev->dev.parent;
+ struct device_node *mac_node = dev->of_node;
+ struct device_node *fman_node = NULL, *ptp_node = NULL;
+ struct platform_device *ptp_dev = NULL;
+ struct qoriq_ptp *ptp = NULL;
+
+ info->phc_index = -1;
+
+ fman_node = of_get_parent(mac_node);
+ if (fman_node)
+ ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0);
+
+ if (ptp_node)
+ ptp_dev = of_find_device_by_node(ptp_node);
+
+ if (ptp_dev)
+ ptp = platform_get_drvdata(ptp_dev);
+
+ if (ptp)
+ info->phc_index = ptp->phc_index;
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
const struct ethtool_ops dpaa_ethtool_ops = {
.get_drvinfo = dpaa_get_drvinfo,
.get_msglevel = dpaa_get_msglevel,
@@ -530,4 +568,5 @@ static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
.set_link_ksettings = dpaa_set_link_ksettings,
.get_rxnfc = dpaa_get_rxnfc,
.set_rxnfc = dpaa_set_rxnfc,
+ .get_ts_info = dpaa_get_ts_info,
};
--
1.7.1
^ permalink raw reply related
* [PATCH v5 2/4] kernel hacking: new config NO_AUTO_INLINE to disable compiler auto-inline optimizations
From: Viresh Kumar @ 2018-06-07 4:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180606142622.2338abf6@vmware.local.home>
+Greg/Alex,
@Fegguang/build-bot: I do see mention of Greg and /me in your initial email's
body saying TO: Viresh, CC: Greg, but I don't see any of us getting cc'd in your
email. Bug ?
On 06-06-18, 14:26, Steven Rostedt wrote:
> On Wed, 6 Jun 2018 16:26:00 +0200
> Johan Hovold <johan@kernel.org> wrote:
>
> > Looks like the greybus code above is working as intended by checking for
> > unterminated string after the strncpy, even if this does now triggers
> > the truncation warning.
So why exactly are we generating a warning here ? Is it because it is possible
that the first n bytes of src may not have the null terminating byte and the
dest may not be null terminated eventually ?
Maybe I should just use memcpy here then ?
But AFAIR, I used strncpy() specifically because it also sets all the remaining
bytes after the null terminating byte with the null terminating byte. And so it
is pretty easy for me to check if the final string is null terminated by
checking [max - 1] byte against '\0', which the code is doing right now.
I am not sure what would the best way to get around this incorrect-warning.
And I am wondering on why buildbot reported the warning only for two instances
in that file, while I have done the same thing at 4 places.
> Ah, yes I now see that. Thanks for pointing it out. But perhaps it
> should also add the "- 1" to the strncpy() so that gcc doesn't think
> it's a mistake.
The src string is passed on from a firmware entity and we need to make sure the
protocol (greybus) is implemented properly by the other end. For example, in the
current case if the firmware sends "HELLOWORLD", its an error as it should have
sent "HELLWORLD\0". But with what you are saying we will forcefully make dest as
"HELLWORLD\0", which wouldn't be the right thing to do as we will miss the bug
present in firmware.
--
viresh
^ permalink raw reply
* [PATCH 4/4] soc: imx: add SC firmware IPC and APIs
From: A.s. Dong @ 2018-06-07 4:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180606141501.6prypkkxgsk3e7ee@pengutronix.de>
Hi Sascha,
> -----Original Message-----
> From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> Sent: Wednesday, June 6, 2018 10:15 PM
> To: A.s. Dong <aisheng.dong@nxp.com>
> Cc: dongas86 at gmail.com; dl-linux-imx <linux-imx@nxp.com>;
> kernel at pengutronix.de; Fabio Estevam <fabio.estevam@nxp.com>;
> shawnguo at kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 4/4] soc: imx: add SC firmware IPC and APIs
>
> On Thu, May 24, 2018 at 08:56:15AM +0000, A.s. Dong wrote:
> > Hi Sascha,
> >
> > > -----Original Message-----
> > > From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> > > Sent: Thursday, May 3, 2018 8:41 PM
> > > To: A.s. Dong <aisheng.dong@nxp.com>
> > > Cc: linux-arm-kernel at lists.infradead.org; dongas86 at gmail.com;
> > > dl-linux-imx <linux-imx@nxp.com>; kernel at pengutronix.de; Fabio
> > > Estevam <fabio.estevam@nxp.com>; shawnguo at kernel.org
> > > Subject: Re: [PATCH 4/4] soc: imx: add SC firmware IPC and APIs
> > >
> > > On Thu, May 03, 2018 at 12:29:40PM +0000, A.s. Dong wrote:
> > > > > -----Original Message-----
> > > > > From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> > > > > Sent: Thursday, May 3, 2018 7:06 PM
> > > > > To: A.s. Dong <aisheng.dong@nxp.com>
> > > > > Cc: linux-arm-kernel at lists.infradead.org; dongas86 at gmail.com;
> > > > > dl-linux-imx <linux-imx@nxp.com>; kernel at pengutronix.de; Fabio
> > > > > Estevam <fabio.estevam@nxp.com>; shawnguo at kernel.org
> > > > > Subject: Re: [PATCH 4/4] soc: imx: add SC firmware IPC and APIs
> > > > >
> > > > > On Wed, May 02, 2018 at 06:40:03PM +0000, A.s. Dong wrote:
> > > > > > > -----Original Message-----
> > > > > > > From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
> > > > > > > Sent: Wednesday, May 2, 2018 6:04 PM
> > > > > > > To: A.s. Dong <aisheng.dong@nxp.com>
> > > > > > > Cc: linux-arm-kernel at lists.infradead.org;
> > > > > > > dongas86 at gmail.com; dl-linux-imx <linux-imx@nxp.com>;
> > > > > > > kernel at pengutronix.de; Fabio Estevam
> > > > > > > <fabio.estevam@nxp.com>; shawnguo at kernel.org
> > > > > > > Subject: Re: [PATCH 4/4] soc: imx: add SC firmware IPC and
> > > > > > > APIs
> > > > > > >
> > > > > > > On Sat, Apr 28, 2018 at 02:46:16AM +0800, Dong Aisheng wrote:
> > > > > > > > +/* Initialization of the MU code. */ int __init
> > > > > > > > +imx8_scu_init(void) {
> > > > > > > > + struct device_node *np, *mu_np;
> > > > > > > > + struct resource mu_res;
> > > > > > > > + sc_err_t sci_err;
> > > > > > > > + int ret;
> > > > > > > > +
> > > > > > > > + if (!of_machine_is_compatible("fsl,imx8qxp"))
> > > > > > > > + return 0;
> > > > > > > > +
> > > > > > > > + np = of_find_compatible_node(NULL, NULL, "nxp,imx8qxp-
> > > scu");
> > > > > > > > + if (!np)
> > > > > > > > + return -ENODEV;
> > > > > > > > +
> > > > > > > > + mu_np = of_parse_phandle(np, "fsl,mu", 0);
> > > > > > > > + if (WARN_ON(!mu_np))
> > > > > > > > + return -EINVAL;
> > > > > > > > +
> > > > > > > > + ret = of_address_to_resource(mu_np, 0, &mu_res);
> > > > > > > > + if (WARN_ON(ret))
> > > > > > > > + return -EINVAL;
> > > > > > > > +
> > > > > > > > + /* we use mu physical address as IPC communication
> > > > > > > > +channel
> > > ID */
> > > > > > > > + sci_err = sc_ipc_open(&scu_ipc_handle,
> > > (sc_ipc_id_t)(mu_res.start));
> > > > > > > > + if (sci_err != SC_ERR_NONE) {
> > > > > > > > + pr_err("Cannot open MU channel to SCU\n");
> > > > > > > > + return sci_err;
> > > > > > > > + };
> > > > > > >
> > > > > > > Introducing private error codes always has the risk of just
> > > > > > > forwarding them as errno codes as done here.
> > > > > > >
> > > > > >
> > > > > > Yes, you're right.
> > > > > > We probably could do the same as scpi_to_linux_errno in
> > > > > > drivers/firmware/arm_scpi.c.
> > > > > > However, may can't fix the issue permanently.
> > > > > >
> > > > > > > > +
> > > > > > > > + of_node_put(mu_np);
> > > > > > > > +
> > > > > > > > + pr_info("NXP i.MX SCU Initialized (scu_ipc %u)\n",
> > > > > > > > +scu_ipc_handle);
> > > > > > > > +
> > > > > > > > + return 0;
> > > > > > > > +}
> > > > > > > > +early_initcall(imx8_scu_init);
> > > > > > >
> > > > > > > This code shows that the separate 'scu' device node shouldn't
> exist.
> > > > > > > It is only used as a stepping stone to find the 'mu' node.
> > > > > > > Instead of providing a proper driver for the 'mu' node the
> > > > > > > scu code registers it
> > > > > with its physical address.
> > > > > > > I don't think it makes sense to separate mu and scu code in this
> way.
> > > > > > >
> > > > > >
> > > > > > I agree that may not look quite well.
> > > > > > It mainly because we want to use the MU physical address as a MU
> ID.
> > > > > > (can't use virtual address as sc_ipc_id_t is u32 defined by SCU
> firmware.
> > > > > >
> > > > > > If you have any better suggestion please let me know.
> > > > >
> > > > > What I'm suggesting is a single node:
> > > > >
> > > > > scu at 5d1b0000 {
> > > > > compatible = "fsl,imx8qxp-scu";
> > > > > reg = <0x0 0x5d1b0000 0x0 0x10000>;
> > > > > };
> > > > >
> > > > > Attach your code to this one, without any further separation
> > > > > between mu and scu code.
> > > > >
> > > >
> > > > A bit confused. You're suggesting a single node here without mu or
> > > > mailbox node phandle in it? Then how SCU use MU?
> > >
> > > ioremap the address and mu_receive_msg()/mu_send_msg() on it, just
> > > like you do already.
> > >
> > > >
> > > > > We discussed this internally and came to the conclusion that the
> > > > > SCU is not a generic user of a MU. The MU is designed to work
> > > > > together with a piece of SRAM to form a mailbox system. Instead
> > > > > of working as designed the SCU morses the messages through the
> > > > > doorbell (what the MU really is). For anything that uses the MU
> > > > > in the way it is designed I would suggest using the mailbox
> > > > > interface from drivers/mailbox/ along with the binding from
> > > Documentation/devicetree/bindings/mailbox/mailbox.txt.
> > > > >
> > > > > In the way I suggest there is no need for any MU ID.
> > > > >
> > > >
> > > > So you're suggesting switch to use mailbox instead of private MU
> > > > library function calls?
> > > > Something like:
> > > > scu {
> > > > compatible = "nxp,imx8qxp-scu", "simple-bus";
> > > > mboxes = <&mailbox 0>;
> > > > }
> > > > Then IPC is implemented based on mailbox?
> > > >
> > > > As I replied Oleksij Rempel in another mail in this thread, we've
> > > > tried mailbox but got performance regression issue and need more
> > > > time to investigate whether it's really quite suitable for i.MX
> > > > SCU firmware as SCU handling message quite fast in micro seconds.
> > > > (Mailbox polling method has much more latency than current MU
> > > > sample polling we
> > > > used) and we want to avoid the SCU firmware API changes.
> > >
> > > I am not suggesting to do mailboxing (using shared memory) for the SCU.
> > > I am also not suggesting any API update for the SCU communication.
> > > I am just mentioning that doing mailboxing is the way the MU was
> > > originally designed for. Looking at the reference manual I see many MUs
> on the i.MX8.
> > > I guess most of them are for communication between the different
> > > cores on the system. For these it's probably worth writing some generic
> MU driver.
> > > The way the MU is used for communication with the SCU though is so
> > > special that it's not worth writing a generic driver, so just
> > > integrate the MU access functions in the SCU code.
> > >
> >
> > I understand it.
> >
> > One problem of the way you suggested may be that:
> > If we doing like below, we may lose flexibility to change the MU used
> > for SCU firmware communication.
> > scu at 5d1b0000 {
> > compatible = "fsl,imx8qxp-scu";
> > reg = <0x0 0x5d1b0000 0x0 0x10000>;
> > };
> >
> > And current design is that the system supports multiple MU channels
> > used by various users at the same time, e.g. SCU, Power Domain, Clock and
> others.
> > User can flexibly change it under their nodes: And each MU channel is
> > protected by their private lock and not affect each others.
> >
> > e.g.
> > scu {
> > compatible = "nxp,imx8qxp-scu", "simple-bus";
> > fsl,mu = <&lsio_mu0>;
> >
> > clk: clk {
> > compatible = "fsl,imx8qxp-clk";
> > #clock-cells = <1>;
> > };
> >
> > iomuxc: iomuxc {
> > compatible = "fsl,imx8qxp-iomuxc";
> > fsl,mu = <&lsio_mu3>;
> > };
> >
> > imx8qx-pm {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > fsl,mu = <&lsio_mu4>;
> > .............
> > }
> >
> > The default code only uses MU0 which is used by SCU.
> >
> > The change may affect this design. Any ideas?
>
> Sorry for the delay.
>
> You can add the child nodes to the mu nodes they should use:
>
> scu1 {
> compatible = "nxp,imx8qxp-scu";
> reg = <0x0 0x5d1b0000 0x0 0x10000>;
>
> clk: clk {
> compatible = "fsl,imx8qxp-clk";
> #clock-cells = <1>;
> };
>
> ...
> };
>
> scu2 {
> compatible = "nxp,imx8qxp-scu";
> reg = <0x0 someothermu 0x0 0x10000>;
>
> iomuxc: iomuxc {
> compatible = "fsl,imx8qxp-iomuxc";
> };
>
> ...
> };
>
> So instead of adding all possible children to a single mu and phandle to other
> mu's, just add the right children to each mu.
>
I got your point now. But sorry i'm still a bit hestitate to it....
This way increases complexity and looks more like a per-channel binding.
But we normally have only one (abstract) SCU firmware node in a system which may
use different channels to implement different functions like clk, pd and etc.
Multiple faked SCU nodes make people a bit confusing.
Furthermore, it's still lose the flexibility for user to changing a MU to use.
Looking at all exist users in kernel, seems no one to use like this.
See:
Documentation/devicetree/bindings/arm/arm,scpi.txt
Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
All are similar like:
xxx: protocol-node {
compatible = "xxx-protocal";
channel = ...
...
clk_node: clk_node {
...
};
pd_node: pd_node {
...
};
};
The protocol node work is selecting the correct channel, do necessary initialization
and populate the all child function device nodes.
IMHO I'm still a bit like to this common way used in kernel if no stronger objection.
Do you think we can choose this way to go step forward?
Regards
Dong Aisheng
> Sascha
>
>
> --
> Pengutronix e.K. | |
> Industrial Linux Solutions |
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fww
> w.pengutronix.de%2F&data=02%7C01%7Caisheng.dong%40nxp.com%7Cec7
> bf490d73542f736a408d5cbb7e5af%7C686ea1d3bc2b4c6fa92cd99c5c301635%7
> C0%7C0%7C636638913057159824&sdata=m24oKIKeP1sxGOq9gGShs8Y%2BiB
> Rg4NymKKJEF0IHpGc%3D&reserved=0 |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH] pwm: stm32: fix build warning with CONFIG_DMA_ENGINE disabled
From: Lee Jones @ 2018-06-07 5:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180606081827.GD11810@ulmo>
On Wed, 06 Jun 2018, Thierry Reding wrote:
> On Fri, May 25, 2018 at 11:08:30PM +0200, Arnd Bergmann wrote:
> > Without dmaengine support, we get a harmless warning about an
> > unused function:
> >
> > drivers/pwm/pwm-stm32.c:166:12: error: 'stm32_pwm_capture' defined but not used [-Werror=unused-function]
> >
> > Changing the #ifdef to an IS_ENABLED() check shuts up that warning
> > and is slightly nicer to read.
> >
> > Fixes: 53e38fe73f94 ("pwm: stm32: Add capture support")
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > ---
> > drivers/pwm/pwm-stm32.c | 4 +---
> > 1 file changed, 1 insertion(+), 3 deletions(-)
>
> Applied, thanks.
>
> Lee, I applied this on top of your immutable MFD/PWM branch because it
> depends on the capture support that you applied. I wasn't sure what your
> PR timing was going to be, so I thought I'd do it this way since I'm
> pulling in some last minute fixes for v4.18.
I don't see a problem with that.
--
Lee Jones [???]
Linaro Services Technical Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v4 2/3] arm: shmobile: Add the R9A06G032 SMP enabler driver
From: Michel Pollet @ 2018-06-07 6:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <79c0899e-7df1-1fe7-9681-ad3bd51feda7@gmail.com>
On 06 June 2018 22:53, Frank wrote:
> On 06/06/18 14:48, Frank Rowand wrote:
> > On 06/05/18 23:36, Michel Pollet wrote:
> >> Hi Frank,
> >>
> >> On 05 June 2018 18:34, Frank wrote:
> >>> On 06/05/18 04:28, Michel Pollet wrote:
> >>>> The Renesas R9A06G032 second CA7 is parked in a ROM pen at boot
> >>>> time, it requires a special enable method to get it started.
> >>>>
> >>>> Signed-off-by: Michel Pollet <michel.pollet@bp.renesas.com>
> >>>> ---
> >>>> arch/arm/mach-shmobile/Makefile | 1 +
> >>>> arch/arm/mach-shmobile/smp-r9a06g032.c | 79
> >>>> ++++++++++++++++++++++++++++++++++
> >>>> 2 files changed, 80 insertions(+)
> >>>> create mode 100644 arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>>
> >>>> diff --git a/arch/arm/mach-shmobile/Makefile
> >>>> b/arch/arm/mach-shmobile/Makefile index 1939f52..d7fc98f 100644
> >>>> --- a/arch/arm/mach-shmobile/Makefile
> >>>> +++ b/arch/arm/mach-shmobile/Makefile
> >>>> @@ -34,6 +34,7 @@ smp-$(CONFIG_ARCH_SH73A0)+= smp-sh73a0.o
> >>> headsmp-scu.o platsmp-scu.o
> >>>> smp-$(CONFIG_ARCH_R8A7779)+= smp-r8a7779.o headsmp-scu.o
> >>> platsmp-scu.o
> >>>> smp-$(CONFIG_ARCH_R8A7790)+= smp-r8a7790.o
> >>>> smp-$(CONFIG_ARCH_R8A7791)+= smp-r8a7791.o
> >>>> +smp-$(CONFIG_ARCH_R9A06G032)+= smp-r9a06g032.o
> >>>> smp-$(CONFIG_ARCH_EMEV2)+= smp-emev2.o headsmp-scu.o
> >>> platsmp-scu.o
> >>>>
> >>>> # PM objects
> >>>> diff --git a/arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>> b/arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>> new file mode 100644
> >>>> index 0000000..cd40e6e
> >>>> --- /dev/null
> >>>> +++ b/arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>> @@ -0,0 +1,79 @@
> >>>> +// SPDX-License-Identifier: GPL-2.0
> >>>> +/*
> >>>> + * R9A06G032 Second CA7 enabler.
> >>>> + *
> >>>> + * Copyright (C) 2018 Renesas Electronics Europe Limited
> >>>> + *
> >>>> + * Michel Pollet <michel.pollet@bp.renesas.com>,
> >>> <buserror@gmail.com>
> >>>> + * Derived from action,s500-smp
> >>>> + */
> >>>> +
> >>>> +#include <linux/io.h>
> >>>> +#include <linux/of.h>
> >>>> +#include <linux/of_address.h>
> >>>> +#include <linux/smp.h>
> >>>> +
> >>>> +/*
> >>>> + * The second CPU is parked in ROM at boot time. It requires
> >>>> +waking it after
> >>>> + * writing an address into the BOOTADDR register of sysctrl.
> >>>> + *
> >>>> + * So the default value of the "cpu-release-addr" corresponds to
> >>> BOOTADDR...
> >>>> + *
> >>>> + * *However* the BOOTADDR register is not available when the
> >>>> +kernel
> >>>> + * starts in NONSEC mode.
> >>>> + *
> >>>> + * So for NONSEC mode, the bootloader re-parks the second CPU into
> >>>> +a pen
> >>>> + * in SRAM, and changes the "cpu-release-addr" of linux's DT to a
> >>>> +SRAM address,
> >>>> + * which is not restricted.
> >>>
> >>> The binding document for cpu-release-addr does not have a definition
> >>> for 32 bit arm. The existing definition is only 64 bit arm. Please
> >>> add the definition for 32 bit arm to patch 1.
> >>
> >> Hmmm I do find a definition in
> >> Documentation/devicetree/bindings/arm/cpus.txt -- just under where I
> >> added my 'enable-method' -- And it is already used as 32 bits in at
> >> least arch/arm/boot/dts/stih407-family.dtsi.
> >
> > If the correct answer is for cpu-release-addr to be 64 bits in certain
> > cases (that discussion is ongoing further downthread) then one
> > approach to maintain compatibility _and_ to fix the devicetree source
> > files is to change the source code that currently gets
> > cpu-release-addr as a
> > 32 bit object to check the size of the property and get it as either a
> > 32 bit or 64 bit object, based on the actual size of the property in
> > the device tree and then change the value in the devicetree source
> > files to be two cells. BUT this does not consider the bootloader
> > complication. arch/arm/boot/dts/axm5516-cpus.dtsi has a note "//
> > Fixed by the boot loader", so the boot loader also has to be modified
> > to be able to handle the possibility that the property could be either
> > 32 bits or 64 bits. I don't know how to maintain compatibility with
> > the boot loader since we can't force it to change synchronously with
> > changes in the kernel.
> >
> > You can consider this comment to be a drive-by observation. I think
> > Rob and Geert and people like that are likely to be more helpful with
> > what to actually do, and you can treat my comment more as pointing out
> > the issue than as providing the perfect solution.
>
> Darn it, hit <send> too quickly.
>
> I meant to mention that there are several devicetree source files that have a
> single cell value for cpu-release-addr, and thus potentially face the same
> situation, depending on what the final decision is on the proper size for cpu-
> release-addr. As of v4.17, a git grep shows one cell values in:
>
> arch/arm/boot/dts/axm5516-cpus.dtsi
> arch/arm/boot/dts/stih407-family.dtsi
> arch/arm/boot/dts/stih418.dtsi
Yes, I had grepped before I used 32 bits on mine...
Now, what is the decision here? Our bootloader is already modified to set it to 32 bits, so I propose that
+ I change the driver to handle 32 and 64 bits properties
+ I add this to the cpu.txt, as a separate patch:
# On other systems, the property can be either
32 bits or 64 bits, it is the driver's responsibility
to deal with either sizes.
Michel
>
> -Frank
>
> > -Frnak
> >
> >
> >>
> >> What do you want me to add to this exactly? Do you want me to just
> >> change "required for systems that have an "enable-method" property
> >> value of "spin-table" to also specify renesas,r9a06g032 ?
> >>
> >> Thanks!
> >> Michel
> >>
> >>>
> >>> -Frank
> >>>
> >>>
> >>>> + */
> >>>> +
> >>>> +static void __iomem *cpu_bootaddr;
> >>>> +
> >>>> +static DEFINE_SPINLOCK(cpu_lock);
> >>>> +
> >>>> +static int r9a06g032_smp_boot_secondary(unsigned int cpu, struct
> >>>> +task_struct *idle) { if (!cpu_bootaddr) return -ENODEV;
> >>>> +
> >>>> +spin_lock(&cpu_lock);
> >>>> +
> >>>> +writel(__pa_symbol(secondary_startup), cpu_bootaddr);
> >>>> +arch_send_wakeup_ipi_mask(cpumask_of(cpu));
> >>>> +
> >>>> +spin_unlock(&cpu_lock);
> >>>> +
> >>>> +return 0;
> >>>> +}
> >>>> +
> >>>> +static void __init r9a06g032_smp_prepare_cpus(unsigned int
> >>>> +max_cpus) { struct device_node *dn; int ret;
> >>>> +u32 bootaddr;
> >>>> +
> >>>> +dn = of_get_cpu_node(1, NULL);
> >>>> +if (!dn) {
> >>>> +pr_err("CPU#1: missing device tree node\n"); return; }
> >>>> +/*
> >>>> + * Determine the address from which the CPU is polling.
> >>>> + * The bootloader *does* change this property */ ret =
> >>>> +of_property_read_u32(dn, "cpu-release-addr", &bootaddr);
> >>>> +of_node_put(dn); if (ret) {
> >>>> +pr_err("CPU#1: invalid cpu-release-addr property\n"); return; }
> >>>> +pr_info("CPU#1: cpu-release-addr %08x\n", bootaddr);
> >>>> +
> >>>> +cpu_bootaddr = ioremap(bootaddr, sizeof(bootaddr)); }
> >>>> +
> >>>> +static const struct smp_operations r9a06g032_smp_ops __initconst =
> >>>> +{ .smp_prepare_cpus = r9a06g032_smp_prepare_cpus,
> >>>> +.smp_boot_secondary = r9a06g032_smp_boot_secondary, };
> >>>> +CPU_METHOD_OF_DECLARE(r9a06g032_smp, "renesas,r9a06g032-
> smp",
> >>>> +&r9a06g032_smp_ops);
> >>>>
> >>
> >>
> >>
> >>
> >> Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne
> End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under
> Registered No. 04586709.
> >>
> >
> >
Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered No. 04586709.
^ permalink raw reply
* [PATCH 4/4] soc: imx: add SC firmware IPC and APIs
From: Sascha Hauer @ 2018-06-07 7:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AM0PR04MB4211E378DCBB769AB2C06BCF80640@AM0PR04MB4211.eurprd04.prod.outlook.com>
On Thu, Jun 07, 2018 at 04:18:54AM +0000, A.s. Dong wrote:
> Hi Sascha,
>
> > > One problem of the way you suggested may be that:
> > > If we doing like below, we may lose flexibility to change the MU used
> > > for SCU firmware communication.
> > > scu at 5d1b0000 {
> > > compatible = "fsl,imx8qxp-scu";
> > > reg = <0x0 0x5d1b0000 0x0 0x10000>;
> > > };
> > >
> > > And current design is that the system supports multiple MU channels
> > > used by various users at the same time, e.g. SCU, Power Domain, Clock and
> > others.
> > > User can flexibly change it under their nodes: And each MU channel is
> > > protected by their private lock and not affect each others.
> > >
> > > e.g.
> > > scu {
> > > compatible = "nxp,imx8qxp-scu", "simple-bus";
> > > fsl,mu = <&lsio_mu0>;
> > >
> > > clk: clk {
> > > compatible = "fsl,imx8qxp-clk";
> > > #clock-cells = <1>;
> > > };
> > >
> > > iomuxc: iomuxc {
> > > compatible = "fsl,imx8qxp-iomuxc";
> > > fsl,mu = <&lsio_mu3>;
> > > };
> > >
> > > imx8qx-pm {
> > > #address-cells = <1>;
> > > #size-cells = <0>;
> > > fsl,mu = <&lsio_mu4>;
> > > .............
> > > }
> > >
> > > The default code only uses MU0 which is used by SCU.
> > >
> > > The change may affect this design. Any ideas?
> >
> > Sorry for the delay.
> >
> > You can add the child nodes to the mu nodes they should use:
> >
> > scu1 {
> > compatible = "nxp,imx8qxp-scu";
> > reg = <0x0 0x5d1b0000 0x0 0x10000>;
> >
> > clk: clk {
> > compatible = "fsl,imx8qxp-clk";
> > #clock-cells = <1>;
> > };
> >
> > ...
> > };
> >
> > scu2 {
> > compatible = "nxp,imx8qxp-scu";
> > reg = <0x0 someothermu 0x0 0x10000>;
> >
> > iomuxc: iomuxc {
> > compatible = "fsl,imx8qxp-iomuxc";
> > };
> >
> > ...
> > };
> >
> > So instead of adding all possible children to a single mu and phandle to other
> > mu's, just add the right children to each mu.
> >
>
> I got your point now. But sorry i'm still a bit hestitate to it....
>
> This way increases complexity and looks more like a per-channel binding.
> But we normally have only one (abstract) SCU firmware node in a system which may
> use different channels to implement different functions like clk, pd and etc.
> Multiple faked SCU nodes make people a bit confusing.
They are not faked, indeed that's the MU units that physically exist.
> Furthermore, it's still lose the flexibility for user to changing a MU to use.
>
> Looking at all exist users in kernel, seems no one to use like this.
> See:
> Documentation/devicetree/bindings/arm/arm,scpi.txt
> Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
>
> All are similar like:
> xxx: protocol-node {
> compatible = "xxx-protocal";
> channel = ...
> ...
>
> clk_node: clk_node {
> ...
> };
>
> pd_node: pd_node {
> ...
> };
> };
> The protocol node work is selecting the correct channel, do necessary initialization
> and populate the all child function device nodes.
>
> IMHO I'm still a bit like to this common way used in kernel if no stronger objection.
> Do you think we can choose this way to go step forward?
I'm not convinced, but go ahead if you think this is the better way to
proceed.
I think my original point that led to this discussion is the muddled way
the MUs are handled in the code.
To start with in the system controller code you ioremap the physical
address of the MU and later on pass this address as a reference to
the MU library code. There's no way for the MU code to ever create a
private data. It would be much better if you would pass mu_init a
pointer to the device node it shall initialize, let mu_init allocate
a private data struct, ioremap the base and put it in the private data
struct, and return the private data struct.
Then there is this sc_ipc_get_handle() thing that your consumers shall
use to get a handle to the SCU. Instead of returning a struct sc_ipc *
there you return a ida which you first have to search for each time
a consumer wants to do something on the SCU. Please just return a
pointer there (which can be a cookie, i.e. the struct definition is
unknown to the consumer but privately to the SCU code).
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH][next] pinctrl: pinctrl-single: add allocation failure checking of saved_vals
From: Johan Hovold @ 2018-06-07 7:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180606134338.4645-1-colin.king@canonical.com>
On Wed, Jun 06, 2018 at 02:43:38PM +0100, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> Currently saved_vals is being allocated and there is no check for
> failed allocation (which is more likely than normal when using
> GFP_ATOMIC). Fix this by checking for a failed allocation and
> propagating this error return down the the caller chain.
>
> Detected by CoverityScan, CID#1469841 ("Dereference null return value")
> Fixes: 88a1dbdec682 ("pinctrl: pinctrl-single: Add functions to save and restore pinctrl context")
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
> drivers/pinctrl/pinctrl-single.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> index 9c3c00515aa0..0905ee002041 100644
> --- a/drivers/pinctrl/pinctrl-single.c
> +++ b/drivers/pinctrl/pinctrl-single.c
> @@ -1588,8 +1588,11 @@ static int pcs_save_context(struct pcs_device *pcs)
>
> mux_bytes = pcs->width / BITS_PER_BYTE;
>
> - if (!pcs->saved_vals)
> + if (!pcs->saved_vals) {
> pcs->saved_vals = devm_kzalloc(pcs->dev, pcs->size, GFP_ATOMIC);
> + if (!pcs->saved_vals)
> + return -ENOMEM;
> + }
>
> switch (pcs->width) {
> case 64:
> @@ -1649,8 +1652,13 @@ static int pinctrl_single_suspend(struct platform_device *pdev,
> if (!pcs)
> return -EINVAL;
>
> - if (pcs->flags & PCS_CONTEXT_LOSS_OFF)
> - pcs_save_context(pcs);
> + if (pcs->flags & PCS_CONTEXT_LOSS_OFF) {
> + int ret;
> +
> + ret = pcs_save_context(pcs);
> + if (ret < 0)
> + return ret;
> + }
This appears to be the right fix (along the lines of what the author may
have intended by having the helper return an int), but as a follow-up
patch, why not move the allocation to probe() instead?
Also this doesn't look like something that requires atomic allocation in
the first place, GFP_KERNEL should do for the legacy suspend callback.
> return pinctrl_force_sleep(pcs->pctl);
> }
But for this fix, feel free to add:
Reviewed-by: Johan Hovold <johan@kernel.org>
Thanks,
Johan
^ permalink raw reply
* [PATCH v2 3/5] arm_pmu: Add support for 64bit event counters
From: Suzuki K Poulose @ 2018-06-07 7:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180606164838.zeuygsp4teq64zor@lakrids.cambridge.arm.com>
On 06/06/2018 05:48 PM, Mark Rutland wrote:
> On Tue, May 29, 2018 at 11:55:54AM +0100, Suzuki K Poulose wrote:
>> Each PMU has a set of 32bit event counters. But in some
>> special cases, the events could be counted using counters
>> which are effectively 64bit wide.
>>
>> e.g, Arm V8 PMUv3 has a 64 bit cycle counter which can count
>> only the CPU cycles. Also, the PMU can chain the event counters
>> to effectively count as a 64bit counter.
>>
>> Add support for tracking the events that uses 64bit counters.
>> This only affects the periods set for each counter in the core
>> driver.
>>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> Changes since v1:
>> - Rename ARMPMU_EVT_LONG => ARMPMU_EVT_64BIT
>> ---
>> drivers/perf/arm_pmu.c | 14 ++++++++------
>> include/linux/perf/arm_pmu.h | 6 ++++++
>> 2 files changed, 14 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
>> index 8962d26..ff858e6 100644
>> --- a/drivers/perf/arm_pmu.c
>> +++ b/drivers/perf/arm_pmu.c
>> @@ -28,9 +28,10 @@
>> static DEFINE_PER_CPU(struct arm_pmu *, cpu_armpmu);
>> static DEFINE_PER_CPU(int, cpu_irq);
>>
>> -static inline u64 arm_pmu_max_period(void)
>> +static inline u64 arm_pmu_event_max_period(struct perf_event *event)
>> {
>> - return (1ULL << 32) - 1;
>> + return (event->hw.flags & ARMPMU_EVT_64BIT) ?
>> + ~0ULL : (1ULL << 32) - 1;
>> }
>
> Could we please have:
>
> static inline u64 arm_pmu_event_max_period(struct perf_event *event)
> {
> if (event->hw.flags & ARMPMU_EVT_64BIT)
> return GENMASK_ULL(63, 0);
> else
> return GENMASK_ULL(31, 0);
> }
>
> ... since that's obviously balanced, with both values generated in the
> same way.
>
Sure, will do
Suzuki
^ permalink raw reply
* [PATCH v3 4/6] bus: ti-sysc: Add support for software reset
From: Tony Lindgren @ 2018-06-07 7:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180606060826.14671-5-faiz_abbas@ti.com>
* Faiz Abbas <faiz_abbas@ti.com> [180606 06:14]:
> +static int sysc_reset(struct sysc *ddata)
> +{
> + int offset = ddata->offsets[SYSC_SYSCONFIG];
> + int val = sysc_read(ddata, offset);
> +
> + val |= (0x1 << ddata->cap->regbits->srst_shift);
> + sysc_write(ddata, offset, val);
> +
> + /* Poll on reset status */
> + if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
> + offset = ddata->offsets[SYSC_SYSSTATUS];
> +
> + return readl_poll_timeout(ddata->module_va + offset, val,
> + (val & ddata->cfg.syss_mask) == 0x0,
> + 100, MAX_MODULE_SOFTRESET_WAIT);
> + }
> +
> + return 0;
> +}
I wonder if we should also add SYSS_QUIRK_RESET_STATUS in
addition to SYSC_QUIRK_RESET status to make it easy to
read the right register?
Then we can add support for SYSC_QUIRK_RESET_STATUS later on
when tested and return error for now.
Regards,
Tony
^ permalink raw reply
* [PATCH][next] pinctrl: pinctrl-single: add allocation failure checking of saved_vals
From: Johan Hovold @ 2018-06-07 7:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHp75Vd0Djw+nDN7u=-CLEfdDGA5QTsMueOb9EZLNnCDgso5fA@mail.gmail.com>
On Wed, Jun 06, 2018 at 07:02:03PM +0300, Andy Shevchenko wrote:
> On Wed, Jun 6, 2018 at 4:43 PM, Colin King <colin.king@canonical.com> wrote:
> > From: Colin Ian King <colin.king@canonical.com>
> >
> > Currently saved_vals is being allocated and there is no check for
> > failed allocation (which is more likely than normal when using
> > GFP_ATOMIC). Fix this by checking for a failed allocation and
> > propagating this error return down the the caller chain.
> >
> > Detected by CoverityScan, CID#1469841 ("Dereference null return value")
> >
> > Fixes: 88a1dbdec682 ("pinctrl: pinctrl-single: Add functions to save and restore pinctrl context")
> > Signed-off-by: Colin Ian King <colin.king@canonical.com>
> > ---
> > drivers/pinctrl/pinctrl-single.c | 14 +++++++++++---
> > 1 file changed, 11 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> > index 9c3c00515aa0..0905ee002041 100644
> > --- a/drivers/pinctrl/pinctrl-single.c
> > +++ b/drivers/pinctrl/pinctrl-single.c
> > @@ -1588,8 +1588,11 @@ static int pcs_save_context(struct pcs_device *pcs)
> >
> > mux_bytes = pcs->width / BITS_PER_BYTE;
> >
> > - if (!pcs->saved_vals)
> > + if (!pcs->saved_vals) {
> > pcs->saved_vals = devm_kzalloc(pcs->dev, pcs->size, GFP_ATOMIC);
>
> > + if (!pcs->saved_vals)
> > + return -ENOMEM;
>
> Wouldn't make sense to move it out of the first condition?
>
> Something like
>
> if (!foo)
> foo = ...malloc(...);
> if (!foo)
> return ...
No, checking for NULL immediately after the allocation is more obvious
and easier to parse.
Johan
^ permalink raw reply
* [PATCH v5 2/4] kernel hacking: new config NO_AUTO_INLINE to disable compiler auto-inline optimizations
From: Du, Changbin @ 2018-06-07 7:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607041718.qpqucjzlvcm5h3gn@vireshk-i7>
Hi,
On Thu, Jun 07, 2018 at 09:47:18AM +0530, Viresh Kumar wrote:
> +Greg/Alex,
>
> @Fegguang/build-bot: I do see mention of Greg and /me in your initial email's
> body saying TO: Viresh, CC: Greg, but I don't see any of us getting cc'd in your
> email. Bug ?
>
> On 06-06-18, 14:26, Steven Rostedt wrote:
> > On Wed, 6 Jun 2018 16:26:00 +0200
> > Johan Hovold <johan@kernel.org> wrote:
> >
> > > Looks like the greybus code above is working as intended by checking for
> > > unterminated string after the strncpy, even if this does now triggers
> > > the truncation warning.
>
> So why exactly are we generating a warning here ? Is it because it is possible
> that the first n bytes of src may not have the null terminating byte and the
> dest may not be null terminated eventually ?
>
> Maybe I should just use memcpy here then ?
>
I think if the destination is not a null terminated string (If I understand your
description below), memcpy can be used to get rid of such warning. The warning
makes sense in general as explained in mannual. Thanks!
> But AFAIR, I used strncpy() specifically because it also sets all the remaining
> bytes after the null terminating byte with the null terminating byte. And so it
> is pretty easy for me to check if the final string is null terminated by
> checking [max - 1] byte against '\0', which the code is doing right now.
>
> I am not sure what would the best way to get around this incorrect-warning.
>
> And I am wondering on why buildbot reported the warning only for two instances
> in that file, while I have done the same thing at 4 places.
>
> > Ah, yes I now see that. Thanks for pointing it out. But perhaps it
> > should also add the "- 1" to the strncpy() so that gcc doesn't think
> > it's a mistake.
>
> The src string is passed on from a firmware entity and we need to make sure the
> protocol (greybus) is implemented properly by the other end. For example, in the
> current case if the firmware sends "HELLOWORLD", its an error as it should have
> sent "HELLWORLD\0". But with what you are saying we will forcefully make dest as
> "HELLWORLD\0", which wouldn't be the right thing to do as we will miss the bug
> present in firmware.
>
> --
> viresh
--
Thanks,
Changbin Du
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox