* Re: [PATCH v8 0/5] Add intial support to DW MMC host on ZTE SoC
From: Jun Nie @ 2016-12-26 2:24 UTC (permalink / raw)
To: jh80.chung, shawn.guo, xie.baoyou, devicetree
Cc: ulf.hansson, jason.liu, chen.chaokai, lai.binz, linux-mmc,
robh+dt, mark.rutland
In-Reply-To: <1482382657-16681-1-git-send-email-jun.nie@linaro.org>
On 2016年12月22日 12:57, Jun Nie wrote:
> Add intial support to DW MMC host on ZTE SoC. It include platform
> specific wrapper driver and workarounds for fifo quirk.
>
> Changes vs version 7:
> - Re-order patches sequence so that new dts property is introduced before usage.
> - Remove unecessary property in zx mmc dts.
>
> Changes vs version 6:
> - Resolve confilict when rebase to latest dw-mmc.git for-ulf branch.
> - Add Shawn Lin's review tag.
>
> Changes vs version 5:
> - Add clock delay lock status check to save CPU cycle in timing tuning CMD.
>
> Changes vs version 4:
> - Fix missing empty dts compatible element in the end of compatible array.
>
> Changes vs version 3:
> - Fix brace error in document.
>
> Changes vs version 2:
> - Change dt property fifo-addr to data-addr and fifo-watermark-quirk to
> fifo-watermark-aligned.
> - Polish ZX MMC driver on minor coding style issues.
>
> Changes vs version 1:
> - Change fifo-addr-override to fifo-addr and remove its workaround tag in comments.
> - Remove ZX DW MMC driver reset cap in driver, which can be added in dt nodes.
>
>
> Jun Nie (5):
> Documentation: synopsys-dw-mshc: add binding for fifo quirks
> mmc: dw: Add fifo address property
> mmc: dw: Add fifo watermark alignment property
> mmc: dt-bindings: add ZTE ZX296718 MMC bindings
> mmc: zx: Initial support for ZX mmc controller
>
> .../devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 ++
> .../devicetree/bindings/mmc/zx-dw-mshc.txt | 33 +++
> drivers/mmc/host/Kconfig | 9 +
> drivers/mmc/host/Makefile | 1 +
> drivers/mmc/host/dw_mmc-zx.c | 242 +++++++++++++++++++++
> drivers/mmc/host/dw_mmc-zx.h | 31 +++
> drivers/mmc/host/dw_mmc.c | 17 +-
> include/linux/mmc/dw_mmc.h | 5 +
> 8 files changed, 348 insertions(+), 3 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt
> create mode 100644 drivers/mmc/host/dw_mmc-zx.c
> create mode 100644 drivers/mmc/host/dw_mmc-zx.h
>
Jaehoon,
Could you help add this patch set to your branch that for next merge
window? Thank you very much!
Jun
^ permalink raw reply
* [PATCH v3 0/4] clk: rockchip: support clk controller for rk3328 SoC
From: Elaine Zhang @ 2016-12-26 3:45 UTC (permalink / raw)
To: heiko, mturquette, sboyd, xf
Cc: robh+dt, mark.rutland, linux-clk, huangtao, xxx, cl,
linux-rockchip, linux-kernel, devicetree, linux-arm-kernel,
Elaine Zhang
Changes in v3:
fix up the pll type pll_rk3328 description and use.
Changes in v2:
add bindings for rk3328 clock controller
Elaine Zhang (4):
clk: rockchip: add dt-binding header for rk3328
dt-bindings: add bindings for rk3328 clock controller
clk: rockchip: add clock controller for rk3328
clk: rockchip: add new pll-type for rk3328
.../bindings/clock/rockchip,rk3328-cru.txt | 57 ++
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-pll.c | 16 +-
drivers/clk/rockchip/clk-rk3328.c | 1068 ++++++++++++++++++++
drivers/clk/rockchip/clk.h | 23 +
include/dt-bindings/clock/rk3328-cru.h | 403 ++++++++
6 files changed, 1565 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
create mode 100644 drivers/clk/rockchip/clk-rk3328.c
create mode 100644 include/dt-bindings/clock/rk3328-cru.h
--
1.9.1
^ permalink raw reply
* [PATCH v3 1/4] clk: rockchip: add dt-binding header for rk3328
From: Elaine Zhang @ 2016-12-26 3:45 UTC (permalink / raw)
To: heiko, mturquette, sboyd, xf
Cc: robh+dt, mark.rutland, linux-clk, huangtao, xxx, cl,
linux-rockchip, linux-kernel, devicetree, linux-arm-kernel,
Elaine Zhang
In-Reply-To: <1482723930-5876-1-git-send-email-zhangqing@rock-chips.com>
Add the dt-bindings header for the rk3328, that gets shared between
the clock controller and the clock references in the dts.
Add softreset ID for rk3328.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
include/dt-bindings/clock/rk3328-cru.h | 403 +++++++++++++++++++++++++++++++++
1 file changed, 403 insertions(+)
create mode 100644 include/dt-bindings/clock/rk3328-cru.h
diff --git a/include/dt-bindings/clock/rk3328-cru.h b/include/dt-bindings/clock/rk3328-cru.h
new file mode 100644
index 000000000000..545ed7541316
--- /dev/null
+++ b/include/dt-bindings/clock/rk3328-cru.h
@@ -0,0 +1,403 @@
+/*
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3328_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3328_H
+
+/* core clocks */
+#define PLL_APLL 1
+#define PLL_DPLL 2
+#define PLL_CPLL 3
+#define PLL_GPLL 4
+#define PLL_NPLL 5
+#define ARMCLK 6
+
+/* sclk gates (special clocks) */
+#define SCLK_RTC32K 30
+#define SCLK_SDMMC_EXT 31
+#define SCLK_SPI 32
+#define SCLK_SDMMC 33
+#define SCLK_SDIO 34
+#define SCLK_EMMC 35
+#define SCLK_TSADC 36
+#define SCLK_SARADC 37
+#define SCLK_UART0 38
+#define SCLK_UART1 39
+#define SCLK_UART2 40
+#define SCLK_I2S0 41
+#define SCLK_I2S1 42
+#define SCLK_I2S2 43
+#define SCLK_I2S1_OUT 44
+#define SCLK_I2S2_OUT 45
+#define SCLK_SPDIF 46
+#define SCLK_TIMER0 47
+#define SCLK_TIMER1 48
+#define SCLK_TIMER2 49
+#define SCLK_TIMER3 50
+#define SCLK_TIMER4 51
+#define SCLK_TIMER5 52
+#define SCLK_WIFI 53
+#define SCLK_CIF_OUT 54
+#define SCLK_I2C0 55
+#define SCLK_I2C1 56
+#define SCLK_I2C2 57
+#define SCLK_I2C3 58
+#define SCLK_CRYPTO 59
+#define SCLK_PWM 60
+#define SCLK_PDM 61
+#define SCLK_EFUSE 62
+#define SCLK_OTP 63
+#define SCLK_DDRCLK 64
+#define SCLK_VDEC_CABAC 65
+#define SCLK_VDEC_CORE 66
+#define SCLK_VENC_DSP 67
+#define SCLK_VENC_CORE 68
+#define SCLK_RGA 69
+#define SCLK_HDMI_SFC 70
+#define SCLK_HDMI_CEC 71
+#define SCLK_USB3_REF 72
+#define SCLK_USB3_SUSPEND 73
+#define SCLK_SDMMC_DRV 74
+#define SCLK_SDIO_DRV 75
+#define SCLK_EMMC_DRV 76
+#define SCLK_SDMMC_EXT_DRV 77
+#define SCLK_SDMMC_SAMPLE 78
+#define SCLK_SDIO_SAMPLE 79
+#define SCLK_EMMC_SAMPLE 80
+#define SCLK_SDMMC_EXT_SAMPLE 81
+#define SCLK_VOP 82
+#define SCLK_MAC2PHY_RXTX 83
+#define SCLK_MAC2PHY_SRC 84
+#define SCLK_MAC2PHY_REF 85
+#define SCLK_MAC2PHY_OUT 86
+#define SCLK_MAC2IO_RX 87
+#define SCLK_MAC2IO_TX 88
+#define SCLK_MAC2IO_REFOUT 89
+#define SCLK_MAC2IO_REF 90
+#define SCLK_MAC2IO_OUT 91
+#define SCLK_TSP 92
+#define SCLK_HSADC_TSP 93
+#define SCLK_USB3PHY_REF 94
+#define SCLK_REF_USB3OTG 95
+#define SCLK_USB3OTG_REF 96
+#define SCLK_USB3OTG_SUSPEND 97
+#define SCLK_REF_USB3OTG_SRC 98
+#define SCLK_MAC2IO_SRC 99
+
+/* dclk gates */
+#define DCLK_LCDC 180
+#define DCLK_HDMIPHY 181
+#define HDMIPHY 182
+#define USB480M 183
+#define DCLK_LCDC_SRC 184
+
+/* aclk gates */
+#define ACLK_AXISRAM 190
+#define ACLK_VOP_PRE 191
+#define ACLK_USB3OTG 192
+#define ACLK_RGA_PRE 193
+#define ACLK_DMAC 194
+#define ACLK_GPU 195
+#define ACLK_BUS_PRE 196
+#define ACLK_PERI_PRE 197
+#define ACLK_RKVDEC_PRE 198
+#define ACLK_RKVDEC 199
+#define ACLK_RKVENC 200
+#define ACLK_VPU_PRE 201
+#define ACLK_VIO_PRE 202
+#define ACLK_VPU 203
+#define ACLK_VIO 204
+#define ACLK_VOP 205
+#define ACLK_GMAC 206
+#define ACLK_H265 207
+#define ACLK_H264 208
+#define ACLK_MAC2PHY 209
+#define ACLK_MAC2IO 210
+#define ACLK_DCF 211
+#define ACLK_TSP 212
+#define ACLK_PERI 213
+#define ACLK_RGA 214
+#define ACLK_IEP 215
+#define ACLK_CIF 216
+#define ACLK_HDCP 217
+
+/* pclk gates */
+#define PCLK_GPIO0 300
+#define PCLK_GPIO1 301
+#define PCLK_GPIO2 302
+#define PCLK_GPIO3 303
+#define PCLK_GRF 304
+#define PCLK_I2C0 305
+#define PCLK_I2C1 306
+#define PCLK_I2C2 307
+#define PCLK_I2C3 308
+#define PCLK_SPI 309
+#define PCLK_UART0 310
+#define PCLK_UART1 311
+#define PCLK_UART2 312
+#define PCLK_TSADC 313
+#define PCLK_PWM 314
+#define PCLK_TIMER 315
+#define PCLK_BUS_PRE 316
+#define PCLK_PERI_PRE 317
+#define PCLK_HDMI_CTRL 318
+#define PCLK_HDMI_PHY 319
+#define PCLK_GMAC 320
+#define PCLK_H265 321
+#define PCLK_MAC2PHY 322
+#define PCLK_MAC2IO 323
+#define PCLK_USB3PHY_OTG 324
+#define PCLK_USB3PHY_PIPE 325
+#define PCLK_USB3_GRF 326
+#define PCLK_USB2_GRF 327
+#define PCLK_HDMIPHY 328
+#define PCLK_DDR 329
+#define PCLK_PERI 330
+#define PCLK_HDMI 331
+#define PCLK_HDCP 332
+#define PCLK_DCF 333
+#define PCLK_SARADC 334
+
+/* hclk gates */
+#define HCLK_PERI 408
+#define HCLK_TSP 409
+#define HCLK_GMAC 410
+#define HCLK_I2S0_8CH 411
+#define HCLK_I2S1_8CH 413
+#define HCLK_I2S2_2CH 413
+#define HCLK_SPDIF_8CH 414
+#define HCLK_VOP 415
+#define HCLK_NANDC 416
+#define HCLK_SDMMC 417
+#define HCLK_SDIO 418
+#define HCLK_EMMC 419
+#define HCLK_SDMMC_EXT 420
+#define HCLK_RKVDEC_PRE 421
+#define HCLK_RKVDEC 422
+#define HCLK_RKVENC 423
+#define HCLK_VPU_PRE 424
+#define HCLK_VIO_PRE 425
+#define HCLK_VPU 426
+#define HCLK_VIO 427
+#define HCLK_BUS_PRE 428
+#define HCLK_PERI_PRE 429
+#define HCLK_H264 430
+#define HCLK_CIF 431
+#define HCLK_OTG_PMU 432
+#define HCLK_OTG 433
+#define HCLK_HOST0 434
+#define HCLK_HOST0_ARB 435
+#define HCLK_CRYPTO_MST 436
+#define HCLK_CRYPTO_SLV 437
+#define HCLK_PDM 438
+#define HCLK_IEP 439
+#define HCLK_RGA 440
+#define HCLK_HDCP 441
+
+#define CLK_NR_CLKS (HCLK_HDCP + 1)
+
+#define SCLK_MAC2IO 0
+#define SCLK_MAC2PHY 1
+
+#define CLKGRF_NR_CLKS (SCLK_MAC2PHY + 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_NIU 13
+#define SRST_STRC_A 14
+#define SRST_L2C 15
+
+#define SRST_A53_GIC 18
+#define SRST_DAP 19
+#define SRST_PMU_P 21
+#define SRST_EFUSE 22
+#define SRST_BUSSYS_H 23
+#define SRST_BUSSYS_P 24
+#define SRST_SPDIF 25
+#define SRST_INTMEM 26
+#define SRST_ROM 27
+#define SRST_GPIO0 28
+#define SRST_GPIO1 29
+#define SRST_GPIO2 30
+#define SRST_GPIO3 31
+
+#define SRST_I2S0 32
+#define SRST_I2S1 33
+#define SRST_I2S2 34
+#define SRST_I2S0_H 35
+#define SRST_I2S1_H 36
+#define SRST_I2S2_H 37
+#define SRST_UART0 38
+#define SRST_UART1 39
+#define SRST_UART2 40
+#define SRST_UART0_P 41
+#define SRST_UART1_P 42
+#define SRST_UART2_P 43
+#define SRST_I2C0 44
+#define SRST_I2C1 45
+#define SRST_I2C2 46
+#define SRST_I2C3 47
+
+#define SRST_I2C0_P 48
+#define SRST_I2C1_P 49
+#define SRST_I2C2_P 50
+#define SRST_I2C3_P 51
+#define SRST_EFUSE_SE_P 52
+#define SRST_EFUSE_NS_P 53
+#define SRST_PWM0 54
+#define SRST_PWM0_P 55
+#define SRST_DMA 56
+#define SRST_TSP_A 57
+#define SRST_TSP_H 58
+#define SRST_TSP 59
+#define SRST_TSP_HSADC 60
+#define SRST_DCF_A 61
+#define SRST_DCF_P 62
+
+#define SRST_SCR 64
+#define SRST_SPI 65
+#define SRST_TSADC 66
+#define SRST_TSADC_P 67
+#define SRST_CRYPTO 68
+#define SRST_SGRF 69
+#define SRST_GRF 70
+#define SRST_USB_GRF 71
+#define SRST_TIMER_6CH_P 72
+#define SRST_TIMER0 73
+#define SRST_TIMER1 74
+#define SRST_TIMER2 75
+#define SRST_TIMER3 76
+#define SRST_TIMER4 77
+#define SRST_TIMER5 78
+#define SRST_USB3GRF 79
+
+#define SRST_PHYNIU 80
+#define SRST_HDMIPHY 81
+#define SRST_VDAC 82
+#define SRST_ACODEC_p 83
+#define SRST_SARADC 85
+#define SRST_SARADC_P 86
+#define SRST_GRF_DDR 87
+#define SRST_DFIMON 88
+#define SRST_MSCH 89
+#define SRST_DDRMSCH 91
+#define SRST_DDRCTRL 92
+#define SRST_DDRCTRL_P 93
+#define SRST_DDRPHY 94
+#define SRST_DDRPHY_P 95
+
+#define SRST_GMAC_NIU_A 96
+#define SRST_GMAC_NIU_P 97
+#define SRST_GMAC2PHY_A 98
+#define SRST_GMAC2IO_A 99
+#define SRST_MACPHY 100
+#define SRST_OTP_PHY 101
+#define SRST_GPU_A 102
+#define SRST_GPU_NIU_A 103
+#define SRST_SDMMCEXT 104
+#define SRST_PERIPH_NIU_A 105
+#define SRST_PERIHP_NIU_H 106
+#define SRST_PERIHP_P 107
+#define SRST_PERIPHSYS_H 108
+#define SRST_MMC0 109
+#define SRST_SDIO 110
+#define SRST_EMMC 111
+
+#define SRST_USB2OTG_H 112
+#define SRST_USB2OTG 113
+#define SRST_USB2OTG_ADP 114
+#define SRST_USB2HOST_H 115
+#define SRST_USB2HOST_ARB 116
+#define SRST_USB2HOST_AUX 117
+#define SRST_USB2HOST_EHCIPHY 118
+#define SRST_USB2HOST_UTMI 119
+#define SRST_USB3OTG 120
+#define SRST_USBPOR 121
+#define SRST_USB2OTG_UTMI 122
+#define SRST_USB2HOST_PHY_UTMI 123
+#define SRST_USB3OTG_UTMI 124
+#define SRST_USB3PHY_U2 125
+#define SRST_USB3PHY_U3 126
+#define SRST_USB3PHY_PIPE 127
+
+#define SRST_VIO_A 128
+#define SRST_VIO_BUS_H 129
+#define SRST_VIO_H2P_H 130
+#define SRST_VIO_ARBI_H 131
+#define SRST_VOP_NIU_A 132
+#define SRST_VOP_A 133
+#define SRST_VOP_H 134
+#define SRST_VOP_D 135
+#define SRST_RGA 136
+#define SRST_RGA_NIU_A 137
+#define SRST_RGA_A 138
+#define SRST_RGA_H 139
+#define SRST_IEP_A 140
+#define SRST_IEP_H 141
+#define SRST_HDMI 142
+#define SRST_HDMI_P 143
+
+#define SRST_HDCP_A 144
+#define SRST_HDCP 145
+#define SRST_HDCP_H 146
+#define SRST_CIF_A 147
+#define SRST_CIF_H 148
+#define SRST_CIF_P 149
+#define SRST_OTP_P 150
+#define SRST_OTP_SBPI 151
+#define SRST_OTP_USER 152
+#define SRST_DDRCTRL_A 153
+#define SRST_DDRSTDY_P 154
+#define SRST_DDRSTDY 155
+#define SRST_PDM_H 156
+#define SRST_PDM 157
+#define SRST_USB3PHY_OTG_P 158
+#define SRST_USB3PHY_PIPE_P 159
+
+#define SRST_VCODEC_A 160
+#define SRST_VCODEC_NIU_A 161
+#define SRST_VCODEC_H 162
+#define SRST_VCODEC_NIU_H 163
+#define SRST_VDEC_A 164
+#define SRST_VDEC_NIU_A 165
+#define SRST_VDEC_H 166
+#define SRST_VDEC_NIU_H 167
+#define SRST_VDEC_CORE 168
+#define SRST_VDEC_CABAC 169
+#define SRST_DDRPHYDIV 175
+
+#define SRST_RKVENC_NIU_A 176
+#define SRST_RKVENC_NIU_H 177
+#define SRST_RKVENC_H265_A 178
+#define SRST_RKVENC_H265_P 179
+#define SRST_RKVENC_H265_CORE 180
+#define SRST_RKVENC_H265_DSP 181
+#define SRST_RKVENC_H264_A 182
+#define SRST_RKVENC_H264_H 183
+#define SRST_RKVENC_INTMEM 184
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v3 2/4] dt-bindings: add bindings for rk3328 clock controller
From: Elaine Zhang @ 2016-12-26 3:45 UTC (permalink / raw)
To: heiko, mturquette, sboyd, xf
Cc: robh+dt, mark.rutland, linux-clk, huangtao, xxx, cl,
linux-rockchip, linux-kernel, devicetree, linux-arm-kernel,
Elaine Zhang
In-Reply-To: <1482723930-5876-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,rk3328-cru.txt | 57 ++++++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
new file mode 100644
index 000000000000..20053494d49f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
@@ -0,0 +1,57 @@
+* Rockchip RK3328 Clock and Reset Unit
+
+The RK3328 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3328-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/rk3328-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,
+ - "clkin_i2s" - external I2S clock - optional,
+ - "gmac_clkin" - external GMAC clock - optional
+ - "phy_50m_out" - output clock of the pll in the mac phy
+
+Example: Clock controller node:
+
+ cru: clock-controller@ff440000 {
+ compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon";
+ reg = <0x0 0xff440000 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@ff120000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0xff120000 0x100>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART0>;
+ };
--
1.9.1
^ permalink raw reply related
* [PATCH v3 3/4] clk: rockchip: add clock controller for rk3328
From: Elaine Zhang @ 2016-12-26 3:45 UTC (permalink / raw)
To: heiko-4mtYJXux2i+zQB+pC5nmwQ, mturquette-rdvid1DuHRBWk0Htik3J/w,
sboyd-sgV2jX0FEOL9JmXXK+q4OQ, xf-TNX95d0MmH7DzftRWevZcw
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-clk-u79uwXL29TY76Z2rM5mHXA, huangtao-TNX95d0MmH7DzftRWevZcw,
xxx-TNX95d0MmH7DzftRWevZcw, cl-TNX95d0MmH7DzftRWevZcw,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Elaine Zhang
In-Reply-To: <1482723930-5876-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add the clock tree definition for the new rk3328 SoC.
Changes in v3:
fix up the pll parent only xin24m.
Changes in v2:
fix up these *_sample error description.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-rk3328.c | 1068 +++++++++++++++++++++++++++++++++++++
drivers/clk/rockchip/clk.h | 23 +
3 files changed, 1092 insertions(+)
create mode 100644 drivers/clk/rockchip/clk-rk3328.c
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 16e098c36f90..68b04bfca282 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -16,5 +16,6 @@ obj-y += clk-rk3036.o
obj-y += clk-rk3188.o
obj-y += clk-rk3228.o
obj-y += clk-rk3288.o
+obj-y += clk-rk3328.o
obj-y += clk-rk3368.o
obj-y += clk-rk3399.o
diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c
new file mode 100644
index 000000000000..9958ce7d0dcd
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3328.c
@@ -0,0 +1,1068 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Elaine <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+ *
+ * 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/rk3328-cru.h>
+#include "clk.h"
+
+#define RK3328_GRF_SOC_STATUS0 0x480
+#define RK3328_GRF_MAC_CON1 0x904
+#define RK3328_GRF_MAC_CON2 0x908
+
+enum rk3328_plls {
+ apll, dpll, cpll, gpll, npll,
+};
+
+static struct rockchip_pll_rate_table rk3328_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(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 */ },
+};
+
+static struct rockchip_pll_rate_table rk3328_pll_frac_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(1016064000, 3, 127, 1, 1, 0, 134217),
+ /* vco = 1016064000 */
+ RK3036_PLL_RATE(983040000, 24, 983, 1, 1, 0, 671088),
+ /* vco = 983040000 */
+ RK3036_PLL_RATE(491520000, 24, 983, 2, 1, 0, 671088),
+ /* vco = 983040000 */
+ RK3036_PLL_RATE(61440000, 6, 215, 7, 2, 0, 671088),
+ /* vco = 860156000 */
+ RK3036_PLL_RATE(56448000, 12, 451, 4, 4, 0, 9797894),
+ /* vco = 903168000 */
+ RK3036_PLL_RATE(40960000, 12, 409, 4, 5, 0, 10066329),
+ /* vco = 819200000 */
+ { /* sentinel */ },
+};
+
+#define RK3328_DIV_CPU_MASK 0x1f
+#define RK3328_DIV_CPU_SHIFT 8
+
+#define RK3328_DIV_PERI_MASK 0xf
+#define RK3328_DIV_PERI_SHIFT 0
+#define RK3328_DIV_ACLK_MASK 0x7
+#define RK3328_DIV_ACLK_SHIFT 4
+#define RK3328_DIV_HCLK_MASK 0x3
+#define RK3328_DIV_HCLK_SHIFT 8
+#define RK3328_DIV_PCLK_MASK 0x7
+#define RK3328_DIV_PCLK_SHIFT 12
+
+#define RK3328_CLKSEL1(_aclk_core, _pclk_dbg) \
+{ \
+ .reg = RK3328_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_aclk_core, RK3328_DIV_ACLKM_MASK, \
+ RK3328_DIV_ACLKM_SHIFT) | \
+ HIWORD_UPDATE(_pclk_dbg, RK3328_DIV_PCLK_DBG_MASK, \
+ RK3328_DIV_PCLK_DBG_SHIFT), \
+}
+
+#define RK3328_CPUCLK_RATE(_prate, _aclk_core, _pclk_dbg) \
+{ \
+ .prate = _prate, \
+ .divs = { \
+ RK3328_CLKSEL1(_aclk_core, _pclk_dbg), \
+ }, \
+}
+
+static struct rockchip_cpuclk_rate_table rk3328_cpuclk_rates[] __initdata = {
+ RK3328_CPUCLK_RATE(1800000000, 1, 7),
+ RK3328_CPUCLK_RATE(1704000000, 1, 7),
+ RK3328_CPUCLK_RATE(1608000000, 1, 7),
+ RK3328_CPUCLK_RATE(1512000000, 1, 7),
+ RK3328_CPUCLK_RATE(1488000000, 1, 5),
+ RK3328_CPUCLK_RATE(1416000000, 1, 5),
+ RK3328_CPUCLK_RATE(1392000000, 1, 5),
+ RK3328_CPUCLK_RATE(1296000000, 1, 5),
+ RK3328_CPUCLK_RATE(1200000000, 1, 5),
+ RK3328_CPUCLK_RATE(1104000000, 1, 5),
+ RK3328_CPUCLK_RATE(1008000000, 1, 5),
+ RK3328_CPUCLK_RATE(912000000, 1, 5),
+ RK3328_CPUCLK_RATE(816000000, 1, 3),
+ RK3328_CPUCLK_RATE(696000000, 1, 3),
+ RK3328_CPUCLK_RATE(600000000, 1, 3),
+ RK3328_CPUCLK_RATE(408000000, 1, 1),
+ RK3328_CPUCLK_RATE(312000000, 1, 1),
+ RK3328_CPUCLK_RATE(216000000, 1, 1),
+ RK3328_CPUCLK_RATE(96000000, 1, 1),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3328_cpuclk_data = {
+ .core_reg = RK3328_CLKSEL_CON(0),
+ .div_core_shift = 0,
+ .div_core_mask = 0x1f,
+ .mux_core_alt = 1,
+ .mux_core_main = 3,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+PNAME(mux_pll_p) = { "xin24m" };
+
+PNAME(mux_2plls_p) = { "cpll", "gpll" };
+PNAME(mux_gpll_cpll_p) = { "gpll", "cpll" };
+PNAME(mux_cpll_gpll_apll_p) = { "cpll", "gpll", "apll" };
+PNAME(mux_2plls_xin24m_p) = { "cpll", "gpll", "xin24m" };
+PNAME(mux_2plls_hdmiphy_p) = { "cpll", "gpll",
+ "dummy_hdmiphy" };
+PNAME(mux_4plls_p) = { "cpll", "gpll",
+ "dummy_hdmiphy",
+ "usb480m" };
+PNAME(mux_2plls_u480m_p) = { "cpll", "gpll",
+ "usb480m" };
+PNAME(mux_2plls_24m_u480m_p) = { "cpll", "gpll",
+ "xin24m", "usb480m" };
+
+PNAME(mux_ddrphy_p) = { "dpll", "apll", "cpll" };
+PNAME(mux_armclk_p) = { "apll_core",
+ "gpll_core",
+ "dpll_core",
+ "npll_core"};
+PNAME(mux_hdmiphy_p) = { "hdmi_phy", "xin24m" };
+PNAME(mux_usb480m_p) = { "usb480m_phy",
+ "xin24m" };
+
+PNAME(mux_i2s0_p) = { "clk_i2s0_div",
+ "clk_i2s0_frac",
+ "xin12m",
+ "xin12m" };
+PNAME(mux_i2s1_p) = { "clk_i2s1_div",
+ "clk_i2s1_frac",
+ "clkin_i2s1",
+ "xin12m" };
+PNAME(mux_i2s2_p) = { "clk_i2s2_div",
+ "clk_i2s2_frac",
+ "clkin_i2s2",
+ "xin12m" };
+PNAME(mux_i2s1out_p) = { "clk_i2s1", "xin12m"};
+PNAME(mux_i2s2out_p) = { "clk_i2s2", "xin12m" };
+PNAME(mux_spdif_p) = { "clk_spdif_div",
+ "clk_spdif_frac",
+ "xin12m",
+ "xin12m" };
+PNAME(mux_uart0_p) = { "clk_uart0_div",
+ "clk_uart0_frac",
+ "xin24m" };
+PNAME(mux_uart1_p) = { "clk_uart1_div",
+ "clk_uart1_frac",
+ "xin24m" };
+PNAME(mux_uart2_p) = { "clk_uart2_div",
+ "clk_uart2_frac",
+ "xin24m" };
+
+PNAME(mux_sclk_cif_p) = { "clk_cif_src",
+ "xin24m" };
+PNAME(mux_dclk_lcdc_p) = { "hdmiphy",
+ "dclk_lcdc_src" };
+PNAME(mux_aclk_peri_pre_p) = { "cpll_peri",
+ "gpll_peri",
+ "hdmiphy_peri" };
+PNAME(mux_ref_usb3otg_src_p) = { "xin24m",
+ "clk_usb3otg_ref" };
+PNAME(mux_xin24m_32k_p) = { "xin24m",
+ "clk_rtc32k" };
+PNAME(mux_mac2io_src_p) = { "clk_mac2io_src",
+ "gmac_clkin" };
+PNAME(mux_mac2phy_src_p) = { "clk_mac2phy_src",
+ "phy_50m_out" };
+
+static struct rockchip_pll_clock rk3328_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p,
+ 0, RK3328_PLL_CON(0),
+ RK3328_MODE_CON, 0, 4, 0, rk3328_pll_frac_rates),
+ [dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p,
+ 0, RK3328_PLL_CON(8),
+ RK3328_MODE_CON, 4, 3, 0, NULL),
+ [cpll] = PLL(pll_rk3328, PLL_CPLL, "cpll", mux_pll_p,
+ 0, RK3328_PLL_CON(16),
+ RK3328_MODE_CON, 8, 2, 0, rk3328_pll_rates),
+ [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p,
+ 0, RK3328_PLL_CON(24),
+ RK3328_MODE_CON, 12, 1, 0, rk3328_pll_frac_rates),
+ [npll] = PLL(pll_rk3328, PLL_NPLL, "npll", mux_pll_p,
+ 0, RK3328_PLL_CON(40),
+ RK3328_MODE_CON, 1, 0, 0, rk3328_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 rk3328_i2s0_fracmux __initdata =
+ MUX(0, "i2s0_pre", mux_i2s0_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(6), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_i2s1_fracmux __initdata =
+ MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(8), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_i2s2_fracmux __initdata =
+ MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(10), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_spdif_fracmux __initdata =
+ MUX(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(12), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_uart0_fracmux __initdata =
+ MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_uart1_fracmux __initdata =
+ MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(16), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_uart2_fracmux __initdata =
+ MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(18), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
+ /*
+ * Clock-Architecture Diagram 1
+ */
+
+ DIV(0, "clk_24m", "xin24m", CLK_IGNORE_UNUSED,
+ RK3328_CLKSEL_CON(2), 8, 5, DFLAGS),
+ COMPOSITE(SCLK_RTC32K, "clk_rtc32k", mux_2plls_xin24m_p, 0,
+ RK3328_CLKSEL_CON(38), 14, 2, MFLAGS, 0, 14, DFLAGS,
+ RK3328_CLKGATE_CON(0), 11, GFLAGS),
+ /* PD_MISC */
+ MUX(HDMIPHY, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
+ RK3328_MISC_CON, 13, 1, MFLAGS),
+ MUX(USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
+ RK3328_MISC_CON, 15, 1, MFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 2
+ */
+
+ /* PD_CORE */
+ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(0), 0, GFLAGS),
+ GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(0), 2, GFLAGS),
+ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "npll_core", "npll", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(0), 12, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
+ RK3328_CLKSEL_CON(1), 0, 4,
+ DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3328_CLKGATE_CON(7), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
+ RK3328_CLKSEL_CON(1), 4, 3,
+ DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3328_CLKGATE_CON(7), 1, GFLAGS),
+ GATE(0, "aclk_core_niu", "aclk_core", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(13), 0, GFLAGS),
+ GATE(0, "aclk_gic400", "aclk_core", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(13), 1, GFLAGS),
+
+ GATE(0, "clk_jtag", "jtag_clkin", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(7), 2, GFLAGS),
+
+ /* PD_GPU */
+ COMPOSITE(0, "aclk_gpu_pre", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(44), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 6, GFLAGS),
+ GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(14), 0, GFLAGS),
+ GATE(0, "aclk_gpu_niu", "aclk_gpu_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(14), 1, GFLAGS),
+
+ /* PD_DDR */
+ COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+ RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3,
+ DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK3328_CLKGATE_CON(0), 4, GFLAGS),
+ GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 6, GFLAGS),
+ GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 5, GFLAGS),
+ GATE(0, "aclk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 4, GFLAGS),
+ GATE(0, "clk_ddrmon", "xin24m", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(0), 6, GFLAGS),
+
+ COMPOSITE(PCLK_DDR, "pclk_ddr", mux_2plls_hdmiphy_p, 0,
+ RK3328_CLKSEL_CON(4), 13, 2, MFLAGS, 8, 3, DFLAGS,
+ RK3328_CLKGATE_CON(7), 4, GFLAGS),
+ GATE(0, "pclk_ddrupctl", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 1, GFLAGS),
+ GATE(0, "pclk_ddr_msch", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 2, GFLAGS),
+ GATE(0, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 3, GFLAGS),
+ GATE(0, "pclk_ddrstdby", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 7, GFLAGS),
+ GATE(0, "pclk_ddr_grf", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(18), 9, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 3
+ */
+ /* PD_BUS */
+ COMPOSITE(ACLK_BUS_PRE, "aclk_bus_pre", mux_2plls_hdmiphy_p, 0,
+ RK3328_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(8), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_BUS_PRE, "hclk_bus_pre", "aclk_bus_pre", 0,
+ RK3328_CLKSEL_CON(1), 8, 2, DFLAGS,
+ RK3328_CLKGATE_CON(8), 1, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_BUS_PRE, "pclk_bus_pre", "aclk_bus_pre", 0,
+ RK3328_CLKSEL_CON(1), 12, 3, DFLAGS,
+ RK3328_CLKGATE_CON(8), 2, GFLAGS),
+ GATE(0, "pclk_bus", "pclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(8), 3, GFLAGS),
+ GATE(0, "pclk_phy_pre", "pclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(8), 4, GFLAGS),
+
+ COMPOSITE(SCLK_TSP, "clk_tsp", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(21), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(2), 5, GFLAGS),
+ GATE(0, "clk_hsadc_tsp", "ext_gpio3a2", 0,
+ RK3328_CLKGATE_CON(17), 13, GFLAGS),
+
+ /* PD_I2S */
+ COMPOSITE(0, "clk_i2s0_div", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(6), 15, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(1), 1, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(7), 0,
+ RK3328_CLKGATE_CON(1), 2, GFLAGS,
+ &rk3328_i2s0_fracmux),
+ GATE(SCLK_I2S0, "clk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(1), 3, GFLAGS),
+
+ COMPOSITE(0, "clk_i2s1_div", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(8), 15, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(1), 4, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(9), 0,
+ RK3328_CLKGATE_CON(1), 5, GFLAGS,
+ &rk3328_i2s1_fracmux),
+ GATE(SCLK_I2S1, "clk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(0), 6, GFLAGS),
+ COMPOSITE_NODIV(SCLK_I2S1_OUT, "i2s1_out", mux_i2s1out_p, 0,
+ RK3328_CLKSEL_CON(8), 12, 1, MFLAGS,
+ RK3328_CLKGATE_CON(1), 7, GFLAGS),
+
+ COMPOSITE(0, "clk_i2s2_div", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(1), 8, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(11), 0,
+ RK3328_CLKGATE_CON(1), 9, GFLAGS,
+ &rk3328_i2s2_fracmux),
+ GATE(SCLK_I2S2, "clk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(1), 10, GFLAGS),
+ COMPOSITE_NODIV(SCLK_I2S2_OUT, "i2s2_out", mux_i2s2out_p, 0,
+ RK3328_CLKSEL_CON(10), 12, 1, MFLAGS,
+ RK3328_CLKGATE_CON(1), 11, GFLAGS),
+
+ COMPOSITE(0, "clk_spdif_div", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(12), 15, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(13), 0,
+ RK3328_CLKGATE_CON(1), 13, GFLAGS,
+ &rk3328_spdif_fracmux),
+
+ /* PD_UART */
+ COMPOSITE(0, "clk_uart0_div", mux_2plls_u480m_p, 0,
+ RK3328_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(1), 14, GFLAGS),
+ COMPOSITE(0, "clk_uart1_div", mux_2plls_u480m_p, 0,
+ RK3328_CLKSEL_CON(16), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 0, GFLAGS),
+ COMPOSITE(0, "clk_uart2_div", mux_2plls_u480m_p,
+ 0, RK3328_CLKSEL_CON(18), 12, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(15), 0,
+ RK3328_CLKGATE_CON(1), 15, GFLAGS,
+ &rk3328_uart0_fracmux),
+ COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(17), 0,
+ RK3328_CLKGATE_CON(2), 1, GFLAGS,
+ &rk3328_uart1_fracmux),
+ COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div",
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(19), 0,
+ RK3328_CLKGATE_CON(2), 3, GFLAGS,
+ &rk3328_uart2_fracmux),
+
+ /*
+ * Clock-Architecture Diagram 4
+ */
+ COMPOSITE(SCLK_I2C0, "clk_i2c0", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(34), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 9, GFLAGS),
+ COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(34), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 10, GFLAGS),
+ COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(35), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 11, GFLAGS),
+ COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(35), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 12, GFLAGS),
+ COMPOSITE(SCLK_CRYPTO, "clk_crypto", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 4, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_TSADC, "clk_tsadc", "clk_24m", 0,
+ RK3328_CLKSEL_CON(22), 0, 10, DFLAGS,
+ RK3328_CLKGATE_CON(2), 6, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "clk_24m", 0,
+ RK3328_CLKSEL_CON(23), 0, 10, DFLAGS,
+ RK3328_CLKGATE_CON(2), 14, GFLAGS),
+ COMPOSITE(SCLK_SPI, "clk_spi", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(24), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 7, GFLAGS),
+ COMPOSITE(SCLK_PWM, "clk_pwm", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(24), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3328_CLKGATE_CON(2), 8, GFLAGS),
+ COMPOSITE(SCLK_OTP, "clk_otp", mux_2plls_xin24m_p, 0,
+ RK3328_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3328_CLKGATE_CON(3), 8, GFLAGS),
+ COMPOSITE(SCLK_EFUSE, "clk_efuse", mux_2plls_xin24m_p, 0,
+ RK3328_CLKSEL_CON(5), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(2), 13, GFLAGS),
+ COMPOSITE(SCLK_PDM, "clk_pdm", mux_cpll_gpll_apll_p,
+ CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(2), 15, GFLAGS),
+
+ GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
+ RK3328_CLKGATE_CON(8), 5, GFLAGS),
+ GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
+ RK3328_CLKGATE_CON(8), 6, GFLAGS),
+ GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
+ RK3328_CLKGATE_CON(8), 7, GFLAGS),
+ GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
+ RK3328_CLKGATE_CON(8), 8, GFLAGS),
+ GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
+ RK3328_CLKGATE_CON(8), 9, GFLAGS),
+ GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
+ RK3328_CLKGATE_CON(8), 10, GFLAGS),
+
+ COMPOSITE(SCLK_WIFI, "clk_wifi", mux_2plls_u480m_p, 0,
+ RK3328_CLKSEL_CON(52), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3328_CLKGATE_CON(0), 10, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 5
+ */
+ /* PD_VIDEO */
+ COMPOSITE(ACLK_RKVDEC_PRE, "aclk_rkvdec_pre", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 0, GFLAGS),
+ FACTOR_GATE(HCLK_RKVDEC_PRE, "hclk_rkvdec_pre", "aclk_rkvdec_pre",
+ 0, 1, 4,
+ RK3328_CLKGATE_CON(11), 0, GFLAGS),
+ GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(24), 0, GFLAGS),
+ GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(24), 1, GFLAGS),
+ GATE(0, "aclk_rkvdec_niu", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(24), 2, GFLAGS),
+ GATE(0, "hclk_rkvdec_niu", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(24), 3, GFLAGS),
+
+ COMPOSITE(SCLK_VDEC_CABAC, "sclk_vdec_cabac", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(48), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 1, GFLAGS),
+
+ COMPOSITE(SCLK_VDEC_CORE, "sclk_vdec_core", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(49), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 2, GFLAGS),
+
+ COMPOSITE(ACLK_VPU_PRE, "aclk_vpu_pre", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(50), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 5, GFLAGS),
+ FACTOR_GATE(HCLK_VPU_PRE, "hclk_vpu_pre", "aclk_vpu_pre", 0, 1, 4,
+ RK3328_CLKGATE_CON(11), 8, GFLAGS),
+ GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(23), 0, GFLAGS),
+ GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(23), 1, GFLAGS),
+ GATE(0, "aclk_vpu_niu", "aclk_vpu_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(23), 2, GFLAGS),
+ GATE(0, "hclk_vpu_niu", "hclk_vpu_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(23), 3, GFLAGS),
+
+ COMPOSITE(ACLK_RKVENC, "aclk_rkvenc", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 3, GFLAGS),
+ FACTOR_GATE(HCLK_RKVENC, "hclk_rkvenc", "aclk_rkvenc", 0, 1, 4,
+ RK3328_CLKGATE_CON(11), 4, GFLAGS),
+ GATE(0, "aclk_rkvenc_niu", "aclk_rkvenc", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(25), 0, GFLAGS),
+ GATE(0, "hclk_rkvenc_niu", "hclk_rkvenc", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(25), 1, GFLAGS),
+ GATE(ACLK_H265, "aclk_h265", "aclk_rkvenc", 0,
+ RK3328_CLKGATE_CON(25), 0, GFLAGS),
+ GATE(PCLK_H265, "pclk_h265", "hclk_rkvenc", 0,
+ RK3328_CLKGATE_CON(25), 1, GFLAGS),
+ GATE(ACLK_H264, "aclk_h264", "aclk_rkvenc", 0,
+ RK3328_CLKGATE_CON(25), 0, GFLAGS),
+ GATE(HCLK_H264, "hclk_h264", "hclk_rkvenc", 0,
+ RK3328_CLKGATE_CON(25), 1, GFLAGS),
+ GATE(ACLK_AXISRAM, "aclk_axisram", "aclk_rkvenc", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(25), 0, GFLAGS),
+
+ COMPOSITE(SCLK_VENC_CORE, "sclk_venc_core", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(51), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 4, GFLAGS),
+
+ COMPOSITE(SCLK_VENC_DSP, "sclk_venc_dsp", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(52), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(6), 7, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 6
+ */
+ /* PD_VIO */
+ COMPOSITE(ACLK_VIO_PRE, "aclk_vio_pre", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(37), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(5), 2, GFLAGS),
+ DIV(HCLK_VIO_PRE, "hclk_vio_pre", "aclk_vio_pre", 0,
+ RK3328_CLKSEL_CON(37), 8, 5, DFLAGS),
+
+ COMPOSITE(ACLK_RGA_PRE, "aclk_rga_pre", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(36), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(5), 0, GFLAGS),
+ COMPOSITE(SCLK_RGA, "clk_rga", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(36), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(5), 1, GFLAGS),
+ COMPOSITE(ACLK_VOP_PRE, "aclk_vop_pre", mux_4plls_p, 0,
+ RK3328_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(5), 5, GFLAGS),
+ GATE(0, "clk_hdmi_sfc", "xin24m", 0,
+ RK3328_CLKGATE_CON(5), 4, GFLAGS),
+
+ COMPOSITE_NODIV(0, "clk_cif_src", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(42), 7, 1, MFLAGS,
+ RK3328_CLKGATE_CON(5), 3, GFLAGS),
+ COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cif_out", mux_sclk_cif_p,
+ CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(42), 5, 1, MFLAGS, 0, 5, DFLAGS),
+
+ COMPOSITE(DCLK_LCDC_SRC, "dclk_lcdc_src", mux_gpll_cpll_p, 0,
+ RK3328_CLKSEL_CON(40), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK3328_CLKGATE_CON(5), 6, GFLAGS),
+ DIV(DCLK_HDMIPHY, "dclk_hdmiphy", "dclk_lcdc_src", 0,
+ RK3328_CLKSEL_CON(40), 3, 3, DFLAGS),
+ MUX(DCLK_LCDC, "dclk_lcdc", mux_dclk_lcdc_p, 0,
+ RK3328_CLKSEL_CON(40), 1, 1, MFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 7
+ */
+ /* PD_PERI */
+ GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(4), 0, GFLAGS),
+ GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(4), 1, GFLAGS),
+ GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(4), 2, GFLAGS),
+ COMPOSITE_NOGATE(ACLK_PERI_PRE, "aclk_peri_pre", mux_aclk_peri_pre_p, 0,
+ RK3328_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS),
+ COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre",
+ CLK_IGNORE_UNUSED,
+ RK3328_CLKSEL_CON(29), 0, 2, DFLAGS,
+ RK3328_CLKGATE_CON(10), 2, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre",
+ CLK_IGNORE_UNUSED,
+ RK3328_CLKSEL_CON(29), 4, 3, DFLAGS,
+ RK3328_CLKGATE_CON(10), 1, GFLAGS),
+ GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre",
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT,
+ RK3328_CLKGATE_CON(10), 0, GFLAGS),
+
+ COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_2plls_24m_u480m_p, 0,
+ RK3328_CLKSEL_CON(30), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3328_CLKGATE_CON(4), 3, GFLAGS),
+
+ COMPOSITE(SCLK_SDIO, "clk_sdio", mux_2plls_24m_u480m_p, 0,
+ RK3328_CLKSEL_CON(31), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3328_CLKGATE_CON(4), 4, GFLAGS),
+
+ COMPOSITE(SCLK_EMMC, "clk_emmc", mux_2plls_24m_u480m_p, 0,
+ RK3328_CLKSEL_CON(32), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3328_CLKGATE_CON(4), 5, GFLAGS),
+
+ COMPOSITE(SCLK_SDMMC_EXT, "clk_sdmmc_ext",
+ mux_2plls_24m_u480m_p, 0,
+ RK3328_CLKSEL_CON(43), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3328_CLKGATE_CON(4), 10, GFLAGS),
+
+ COMPOSITE(SCLK_REF_USB3OTG_SRC, "clk_ref_usb3otg_src", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(45), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3328_CLKGATE_CON(4), 9, GFLAGS),
+
+ MUX(SCLK_REF_USB3OTG, "clk_ref_usb3otg",
+ mux_ref_usb3otg_src_p, CLK_SET_RATE_PARENT,
+ RK3328_CLKSEL_CON(45), 8, 1, MFLAGS),
+
+ GATE(SCLK_USB3OTG_REF, "clk_usb3otg_ref", "xin24m", 0,
+ RK3328_CLKGATE_CON(4), 7, GFLAGS),
+
+ COMPOSITE(SCLK_USB3OTG_SUSPEND, "clk_usb3otg_suspend",
+ mux_xin24m_32k_p, 0,
+ RK3328_CLKSEL_CON(33), 15, 1, MFLAGS, 0, 10, DFLAGS,
+ RK3328_CLKGATE_CON(4), 8, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 8
+ */
+ /* PD_GMAC */
+
+ COMPOSITE(ACLK_GMAC, "aclk_gmac", mux_2plls_hdmiphy_p, 0,
+ RK3328_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(3), 2, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_GMAC, "pclk_gmac", "aclk_gmac", 0,
+ RK3328_CLKSEL_CON(25), 8, 3, DFLAGS,
+ RK3328_CLKGATE_CON(9), 0, GFLAGS),
+
+ COMPOSITE(SCLK_MAC2IO_SRC, "clk_mac2io_src", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(27), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(3), 1, GFLAGS),
+ GATE(SCLK_MAC2IO_REF, "clk_mac2io_ref", "clk_mac2io", 0,
+ RK3328_CLKGATE_CON(9), 7, GFLAGS),
+ GATE(SCLK_MAC2IO_RX, "clk_mac2io_rx", "clk_mac2io", 0,
+ RK3328_CLKGATE_CON(9), 4, GFLAGS),
+ GATE(SCLK_MAC2IO_TX, "clk_mac2io_tx", "clk_mac2io", 0,
+ RK3328_CLKGATE_CON(9), 5, GFLAGS),
+ GATE(SCLK_MAC2IO_REFOUT, "clk_mac2io_refout", "clk_mac2io", 0,
+ RK3328_CLKGATE_CON(9), 6, GFLAGS),
+ COMPOSITE(SCLK_MAC2IO_OUT, "clk_mac2io_out", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3328_CLKGATE_CON(3), 5, GFLAGS),
+
+ COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0,
+ RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3328_CLKGATE_CON(3), 0, GFLAGS),
+ GATE(SCLK_MAC2PHY_REF, "clk_mac2phy_ref", "clk_mac2phy", 0,
+ RK3328_CLKGATE_CON(9), 3, GFLAGS),
+ GATE(SCLK_MAC2PHY_RXTX, "clk_mac2phy_rxtx", "clk_mac2phy", 0,
+ RK3328_CLKGATE_CON(9), 1, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_MAC2PHY_OUT, "clk_mac2phy_out", "clk_mac2phy", 0,
+ RK3328_CLKSEL_CON(26), 8, 2, DFLAGS,
+ RK3328_CLKGATE_CON(9), 2, GFLAGS),
+
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+ /*
+ * Clock-Architecture Diagram 9
+ */
+
+ /* PD_VOP */
+ GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0,
+ RK3328_CLKGATE_CON(21), 10, GFLAGS),
+ GATE(0, "aclk_rga_niu", "aclk_rga_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(22), 3, GFLAGS),
+ GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0,
+ RK3328_CLKGATE_CON(21), 2, GFLAGS),
+ GATE(0, "aclk_vop_niu", "aclk_vop_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(21), 4, GFLAGS),
+
+ GATE(ACLK_IEP, "aclk_iep", "aclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 6, GFLAGS),
+ GATE(ACLK_CIF, "aclk_cif", "aclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 8, GFLAGS),
+ GATE(ACLK_HDCP, "aclk_hdcp", "aclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 15, GFLAGS),
+ GATE(0, "aclk_vio_niu", "aclk_vio_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(22), 2, GFLAGS),
+
+ GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 3, GFLAGS),
+ GATE(0, "hclk_vop_niu", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 5, GFLAGS),
+ GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 7, GFLAGS),
+ GATE(HCLK_CIF, "hclk_cif", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 9, GFLAGS),
+ GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(21), 11, GFLAGS),
+ GATE(0, "hclk_ahb1tom", "hclk_vio_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(21), 12, GFLAGS),
+ GATE(0, "pclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(21), 13, GFLAGS),
+ GATE(0, "hclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(21), 14, GFLAGS),
+ GATE(HCLK_HDCP, "hclk_hdcp", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(22), 0, GFLAGS),
+ GATE(HCLK_VIO, "hclk_vio", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(22), 1, GFLAGS),
+ GATE(PCLK_HDMI, "pclk_hdmi", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(22), 4, GFLAGS),
+ GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0,
+ RK3328_CLKGATE_CON(22), 5, GFLAGS),
+
+ /* PD_PERI */
+ GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(19), 11, GFLAGS),
+ GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 4, GFLAGS),
+
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 0, GFLAGS),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 1, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 2, GFLAGS),
+ GATE(HCLK_SDMMC_EXT, "hclk_sdmmc_ext", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 15, GFLAGS),
+ GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 6, GFLAGS),
+ GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_peri", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(19), 7, GFLAGS),
+ GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 8, GFLAGS),
+ GATE(HCLK_OTG_PMU, "hclk_otg_pmu", "hclk_peri", 0,
+ RK3328_CLKGATE_CON(19), 9, GFLAGS),
+ GATE(0, "hclk_peri_niu", "hclk_peri", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(19), 12, GFLAGS),
+ GATE(0, "pclk_peri_niu", "hclk_peri", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(19), 13, GFLAGS),
+
+ /* PD_GMAC */
+ GATE(ACLK_MAC2PHY, "aclk_mac2phy", "aclk_gmac", 0,
+ RK3328_CLKGATE_CON(26), 0, GFLAGS),
+ GATE(ACLK_MAC2IO, "aclk_mac2io", "aclk_gmac", 0,
+ RK3328_CLKGATE_CON(26), 2, GFLAGS),
+ GATE(0, "aclk_gmac_niu", "aclk_gmac", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(26), 4, GFLAGS),
+ GATE(PCLK_MAC2PHY, "pclk_mac2phy", "pclk_gmac", 0,
+ RK3328_CLKGATE_CON(26), 1, GFLAGS),
+ GATE(PCLK_MAC2IO, "pclk_mac2io", "pclk_gmac", 0,
+ RK3328_CLKGATE_CON(26), 3, GFLAGS),
+ GATE(0, "pclk_gmac_niu", "pclk_gmac", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(26), 5, GFLAGS),
+
+ /* PD_BUS */
+ GATE(0, "aclk_bus_niu", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 12, GFLAGS),
+ GATE(ACLK_DCF, "aclk_dcf", "aclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 11, GFLAGS),
+ GATE(ACLK_TSP, "aclk_tsp", "aclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(17), 12, GFLAGS),
+ GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 1, GFLAGS),
+
+ GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 2, GFLAGS),
+ GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 3, GFLAGS),
+ GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 4, GFLAGS),
+ GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(HCLK_SPDIF_8CH, "hclk_spdif_8ch", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 6, GFLAGS),
+ GATE(HCLK_TSP, "hclk_tsp", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(17), 11, GFLAGS),
+ GATE(HCLK_CRYPTO_MST, "hclk_crypto_mst", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 7, GFLAGS),
+ GATE(HCLK_CRYPTO_SLV, "hclk_crypto_slv", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(15), 8, GFLAGS),
+ GATE(0, "hclk_bus_niu", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 13, GFLAGS),
+ GATE(HCLK_PDM, "hclk_pdm", "hclk_bus_pre", 0,
+ RK3328_CLKGATE_CON(28), 0, GFLAGS),
+
+ GATE(0, "pclk_bus_niu", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 14, GFLAGS),
+ GATE(0, "pclk_efuse", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 9, GFLAGS),
+ GATE(0, "pclk_otp", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(28), 4, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(15), 10, GFLAGS),
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 0, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 1, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(PCLK_TIMER, "pclk_timer0", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 3, GFLAGS),
+ GATE(0, "pclk_stimer", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 4, GFLAGS),
+ GATE(PCLK_SPI, "pclk_spi", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 5, GFLAGS),
+ GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 6, GFLAGS),
+ GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 7, GFLAGS),
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 8, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 9, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 10, GFLAGS),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 11, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 12, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 13, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 14, GFLAGS),
+ GATE(PCLK_DCF, "pclk_dcf", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(16), 15, GFLAGS),
+ GATE(PCLK_GRF, "pclk_grf", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 0, GFLAGS),
+ GATE(0, "pclk_cru", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 4, GFLAGS),
+ GATE(0, "pclk_sgrf", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 6, GFLAGS),
+ GATE(0, "pclk_sim", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 10, GFLAGS),
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 0,
+ RK3328_CLKGATE_CON(17), 15, GFLAGS),
+ GATE(0, "pclk_pmu", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(28), 3, GFLAGS),
+
+ GATE(PCLK_USB3PHY_OTG, "pclk_usb3phy_otg", "pclk_phy_pre", 0,
+ RK3328_CLKGATE_CON(28), 1, GFLAGS),
+ GATE(PCLK_USB3PHY_PIPE, "pclk_usb3phy_pipe", "pclk_phy_pre", 0,
+ RK3328_CLKGATE_CON(28), 2, GFLAGS),
+ GATE(PCLK_USB3_GRF, "pclk_usb3_grf", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 2, GFLAGS),
+ GATE(PCLK_USB2_GRF, "pclk_usb2_grf", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 14, GFLAGS),
+ GATE(0, "pclk_ddrphy", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 13, GFLAGS),
+ GATE(0, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 5, GFLAGS),
+ GATE(PCLK_HDMIPHY, "pclk_hdmiphy", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 7, GFLAGS),
+ GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(17), 8, GFLAGS),
+ GATE(0, "pclk_phy_niu", "pclk_phy_pre", CLK_IGNORE_UNUSED,
+ RK3328_CLKGATE_CON(15), 15, GFLAGS),
+
+ /* PD_MMC */
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc",
+ RK3328_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc",
+ RK3328_SDMMC_CON1, 1),
+
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio",
+ RK3328_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio",
+ RK3328_SDIO_CON1, 1),
+
+ MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc",
+ RK3328_EMMC_CON0, 1),
+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc",
+ RK3328_EMMC_CON1, 1),
+
+ MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "sclk_sdmmc_ext",
+ RK3328_SDMMC_EXT_CON0, 1),
+ MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "sclk_sdmmc_ext",
+ RK3328_SDMMC_EXT_CON1, 1),
+};
+
+static struct rockchip_clk_branch rk3328_clk_grf_branches[] __initdata = {
+ /*
+ * GRF CRU Clock-Architecture
+ */
+ MUX(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, 0,
+ RK3328_GRF_MAC_CON1, 10, 1, MFLAGS),
+ MUX(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, 0,
+ RK3328_GRF_MAC_CON2, 10, 1, MFLAGS),
+};
+
+static const char *const rk3328_critical_clocks[] __initconst = {
+ "aclk_bus",
+ "pclk_bus",
+ "hclk_bus",
+ "aclk_peri",
+ "hclk_peri",
+ "pclk_peri",
+ "pclk_dbg",
+ "aclk_core_niu",
+ "aclk_gic400",
+ "aclk_intmem",
+ "hclk_rom",
+ "pclk_grf",
+ "pclk_cru",
+ "pclk_sgrf",
+ "pclk_timer0",
+ "clk_timer0",
+ "pclk_ddr_msch",
+ "pclk_ddr_mon",
+ "pclk_ddr_grf",
+ "clk_ddrupctl",
+ "clk_ddrmsch",
+ "hclk_ahb1tom",
+ "clk_jtag",
+ "pclk_ddrphy",
+ "pclk_pmu",
+ "hclk_otg_pmu",
+ "aclk_rga_niu",
+ "pclk_vio_h2p",
+ "hclk_vio_h2p",
+};
+
+static void __iomem *rk3328_cru_base;
+
+void rk3328_dump_cru(void)
+{
+ if (rk3328_cru_base) {
+ pr_warn("CRU:\n");
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET,
+ 32, 4, rk3328_cru_base,
+ 0x400, false);
+ }
+}
+EXPORT_SYMBOL_GPL(rk3328_dump_cru);
+
+static int rk3328_clk_panic(struct notifier_block *this,
+ unsigned long ev, void *ptr)
+{
+ rk3328_dump_cru();
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rk3328_clk_panic_block = {
+ .notifier_call = rk3328_clk_panic,
+};
+
+static void __init rk3328_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 region\n", __func__);
+ return;
+ }
+
+ rk3328_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;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3328_pll_clks,
+ ARRAY_SIZE(rk3328_pll_clks),
+ RK3328_GRF_SOC_STATUS0);
+ rockchip_clk_register_branches(ctx, rk3328_clk_branches,
+ ARRAY_SIZE(rk3328_clk_branches));
+ rockchip_clk_protect_critical(rk3328_critical_clocks,
+ ARRAY_SIZE(rk3328_critical_clocks));
+
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+ mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+ &rk3328_cpuclk_data, rk3328_cpuclk_rates,
+ ARRAY_SIZE(rk3328_cpuclk_rates));
+
+ rockchip_register_softrst(np, 11, reg_base + RK3328_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_register_restart_notifier(ctx, RK3328_GLB_SRST_FST, NULL);
+
+ rockchip_clk_of_add_provider(np, ctx);
+
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &rk3328_clk_panic_block);
+}
+
+CLK_OF_DECLARE(rk3328_cru, "rockchip,rk3328-cru", rk3328_clk_init);
+
+static void __init rk3328_grf_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;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLKGRF_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip pmu clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_branches(ctx, rk3328_clk_grf_branches,
+ ARRAY_SIZE(rk3328_clk_grf_branches));
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+CLK_OF_DECLARE(rk3328_cru_grf, "rockchip,rk3328-grf", rk3328_grf_clk_init);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index d67eecc4ade9..7225997f8d52 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -91,6 +91,28 @@
#define RK3288_EMMC_CON0 0x218
#define RK3288_EMMC_CON1 0x21c
+#define RK3328_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
+#define RK3328_GRFCLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3328_GLB_SRST_FST 0x9c
+#define RK3328_GLB_SRST_SND 0x98
+#define RK3328_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
+#define RK3328_MODE_CON 0x80
+#define RK3328_MISC_CON 0x84
+#define RK3328_DIV_ACLKM_MASK 0x7
+#define RK3328_DIV_ACLKM_SHIFT 4
+#define RK3328_DIV_PCLK_DBG_MASK 0xf
+#define RK3328_DIV_PCLK_DBG_SHIFT 0
+#define RK3328_SDMMC_CON0 0x380
+#define RK3328_SDMMC_CON1 0x384
+#define RK3328_SDIO_CON0 0x388
+#define RK3328_SDIO_CON1 0x38c
+#define RK3328_EMMC_CON0 0x390
+#define RK3328_EMMC_CON1 0x394
+#define RK3328_SDMMC_EXT_CON0 0x398
+#define RK3328_SDMMC_EXT_CON1 0x39C
+
#define RK3368_PLL_CON(x) RK2928_PLL_CON(x)
#define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
#define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
@@ -130,6 +152,7 @@
enum rockchip_pll_type {
pll_rk3036,
pll_rk3066,
+ pll_rk3328,
pll_rk3399,
};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 4/4] clk: rockchip: add new pll-type for rk3328
From: Elaine Zhang @ 2016-12-26 3:45 UTC (permalink / raw)
To: heiko-4mtYJXux2i+zQB+pC5nmwQ, mturquette-rdvid1DuHRBWk0Htik3J/w,
sboyd-sgV2jX0FEOL9JmXXK+q4OQ, xf-TNX95d0MmH7DzftRWevZcw
Cc: mark.rutland-5wv7dgnIgG8, huangtao-TNX95d0MmH7DzftRWevZcw,
devicetree-u79uwXL29TY76Z2rM5mHXA, xxx-TNX95d0MmH7DzftRWevZcw,
Elaine Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA, cl-TNX95d0MmH7DzftRWevZcw
In-Reply-To: <1482723930-5876-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
The rk3328's pll and clock are similar with rk3036's,
it different with pll_mode_mask, the rk3328 soc
pll mode only one bit(rk3036 soc have two bits)
so these should be independent and separate from
the series of rk3328s.
Changes in v3:
fix up the pll type pll_rk3328 description and use
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
drivers/clk/rockchip/clk-pll.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 6ed605776abd..eec51893a7e6 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -29,6 +29,7 @@
#define PLL_MODE_SLOW 0x0
#define PLL_MODE_NORM 0x1
#define PLL_MODE_DEEP 0x2
+#define PLL_RK3328_MODE_MASK 0x1
struct rockchip_clk_pll {
struct clk_hw hw;
@@ -848,7 +849,8 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
struct clk *pll_clk, *mux_clk;
char pll_name[20];
- if (num_parents != 2) {
+ if ((pll_type != pll_rk3328 && num_parents != 2) ||
+ (pll_type == pll_rk3328 && num_parents != 1)) {
pr_err("%s: needs two parent clocks\n", __func__);
return ERR_PTR(-EINVAL);
}
@@ -865,13 +867,17 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
pll_mux = &pll->pll_mux;
pll_mux->reg = ctx->reg_base + mode_offset;
pll_mux->shift = mode_shift;
- pll_mux->mask = PLL_MODE_MASK;
+ if (pll_type == pll_rk3328)
+ pll_mux->mask = PLL_RK3328_MODE_MASK;
+ else
+ pll_mux->mask = PLL_MODE_MASK;
pll_mux->flags = 0;
pll_mux->lock = &ctx->lock;
pll_mux->hw.init = &init;
if (pll_type == pll_rk3036 ||
pll_type == pll_rk3066 ||
+ pll_type == pll_rk3328 ||
pll_type == pll_rk3399)
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
@@ -884,7 +890,10 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
init.flags = CLK_SET_RATE_PARENT;
init.ops = pll->pll_mux_ops;
init.parent_names = pll_parents;
- init.num_parents = ARRAY_SIZE(pll_parents);
+ if (pll_type == pll_rk3328)
+ init.num_parents = 2;
+ else
+ init.num_parents = ARRAY_SIZE(pll_parents);
mux_clk = clk_register(NULL, &pll_mux->hw);
if (IS_ERR(mux_clk))
@@ -918,6 +927,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
switch (pll_type) {
case pll_rk3036:
+ case pll_rk3328:
if (!pll->rate_table || IS_ERR(ctx->grf))
init.ops = &rockchip_rk3036_pll_clk_norate_ops;
else
--
1.9.1
^ permalink raw reply related
* [RFC PATCH 0/6] Support the PCIe for TM2(exynos5433)
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci
Cc: devicetree, linux-kernel, linux-samsung-soc, bhelgaas, robh+dt,
mark.rutland, kgene, krzk, javier, kishon, will.deacon,
catalin.marinas, cpgs, Jaehoon Chung
In-Reply-To: <CGME20161226052030epcas1p45f543765960d14ccf9cd40c2b9cca84b@epcas1p4.samsung.com>
This patchset is for supporting PCIe exynos5433.
TM2(exynos5433) supports the PCIe for WiFi. In driver/pci/host/, there is pci-exynos.c.
But i can't touch anything. The below reasons are why i added the new file.
1. Don't have the exynos5440 TRM
- I can't check anything for exynso5440.
- So i can't touch anything for using PHY generic framework.
2. Can't test the exynos5440 board.
- If used the phy generic framework, can't ensure whether it's working fine or not.
3. There is no maintiain for exynos5440.
- i don't know anywhere pci-exynos5440 is used.
As i know, Bjorn(PCIe Maintainer) agreed about adding the new file.
So i added the new pci-exynos5433 file in driver/pci/host/.
And adds the phy-exynos-pcie.c for using PHY generic framework.
When use the PHY generic framework, controlling pcie is more easier than now.
There are future works,
- Supporting MSI
- If possible, combine the one file to pci-exynos.c
This is based on httt://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git (for-next branch)
(Because PCI git repository doesn't snycrhonize yet.)
The below is working messesage
[ 0.817081] OF: PCI: host bridge /soc/pcie@15700000 ranges:
[ 0.817264] OF: PCI: No bus range found for /soc/pcie@15700000, using [bus 00-ff]
[ 0.821377] OF: PCI: IO 0x0c001000..0x0c010fff -> 0x00000000
[ 0.827270] OF: PCI: MEM 0x0c011000..0x0ffffffe -> 0x0c011000
[ 0.934306] exynos5433-pcie 156b0000.pcie: link up
[ 0.934649] exynos5433-pcie 156b0000.pcie: PCI host bridge to bus 0000:00
[ 0.934867] pci_bus 0000:00: root bus resource [bus 00-ff]
[ 0.935045] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
[ 0.935243] pci_bus 0000:00: root bus resource [mem 0x0c011000-0x0ffffffe]
[ 0.953719] pci 0000:00:00.0: BAR 8: assigned [mem 0x0c200000-0x0c7fffff]
[ 0.953941] pci 0000:01:00.0: BAR 2: assigned [mem 0x0c400000-0x0c7fffff 64bit]
[ 0.956672] pci 0000:01:00.0: BAR 0: assigned [mem 0x0c200000-0x0c207fff 64bit]
[ 0.963959] pci 0000:00:00.0: PCI bridge to [bus 01]
[ 0.968368] pci 0000:00:00.0: bridge window [mem 0x0c200000-0x0c7fffff]
[ 0.975241] pcieport 0000:00:00.0: of_irq_parse_pci() failed with rc=-22
[ 0.982124] pcieport 0000:00:00.0: Signaling PME through PCIe PME interrupt
Jaehoon Chung (6):
phy: exynos-pcie: Add support for Exynos PCIe phy
Documetation: samsung-phy: add the exynos-pcie-phy binding
ARM64: dts: exynos5433: add the pcie_phy node for PCIe
PCI: exynos5433: Add new exynos pci host controller for Exynos5433
Documentation: pci: add the exynos5433-pcie binding
ARM64: exynos: add the pcie node for TM2
.../devicetree/bindings/pci/exynos5433-pcie.txt | 36 +++
.../devicetree/bindings/phy/samsung-phy.txt | 21 ++
arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi | 7 +
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 11 +-
arch/arm64/boot/dts/exynos/exynos5433.dtsi | 37 +++
drivers/pci/host/Kconfig | 9 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pci-exynos5433.c | 338 +++++++++++++++++++++
drivers/phy/Kconfig | 9 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-exynos-pcie.c | 227 ++++++++++++++
11 files changed, 695 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/exynos5433-pcie.txt
create mode 100644 drivers/pci/host/pci-exynos5433.c
create mode 100644 drivers/phy/phy-exynos-pcie.c
--
2.10.2
^ permalink raw reply
* [RFC PATCH 1/6] phy: exynos-pcie: Add support for Exynos PCIe phy
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci
Cc: devicetree, linux-kernel, linux-samsung-soc, bhelgaas, robh+dt,
mark.rutland, kgene, krzk, javier, kishon, will.deacon,
catalin.marinas, cpgs, Jaehoon Chung
In-Reply-To: <20161226052029.10552-1-jh80.chung@samsung.com>
This patch supports to use Generic Phy framework for Exynos PCIe phy.
When Exynos that supported the pcie want to use the PCIe,
it needs to control the phy resgister.
But it should be more complex to control in their own PCIe device drivers.
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
---
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-exynos-pcie.c | 227 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 237 insertions(+)
create mode 100644 drivers/phy/phy-exynos-pcie.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index fe00f91..94b0433 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -341,6 +341,15 @@ config PHY_EXYNOS5_USBDRD
This driver provides PHY interface for USB 3.0 DRD controller
present on Exynos5 SoC series.
+config PHY_EXYNOS_PCIE
+ bool "Exynos PCIe PHY driver"
+ depends on ARCH_EXYNOS && OF
+ depends on PCI_EXYNOS5433
+ select GENERIC_PHY
+ help
+ Enable PCIe PHY support for Exynos SoC series.
+ This driver provides PHY interface for Exynos PCIe controller.
+
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MACH_PISTACHIO
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a534cf5..586344d 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -38,6 +38,7 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
+obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
diff --git a/drivers/phy/phy-exynos-pcie.c b/drivers/phy/phy-exynos-pcie.c
new file mode 100644
index 0000000..0f5eefd
--- /dev/null
+++ b/drivers/phy/phy-exynos-pcie.c
@@ -0,0 +1,227 @@
+/*
+ * Samsung EXYNOS SoC series PCIe PHY driver
+ *
+ * Phy provider for PCIe controller on Exynos SoC series
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#define PCIE_EXYNOS5433_PMU_PHY_OFFSET 0x730
+#define PCIE_PHY_OFFSET(x) ((x) * 0x4)
+
+/* Sysreg Fsys register offset and bit for Exynos5433 */
+#define PCIE_PHY_MAC_RESET 0x208
+#define PCIE_MAC_RESET_MASK 0xFF
+#define PCIE_MAC_RESET BIT(4)
+#define PCIE_L1SUB_CM_CON 0x1010
+#define PCIE_REFCLK_GATING_EN BIT(0)
+#define PCIE_PHY_COMMON_RESET 0x1020
+#define PCIE_PHY_RESET BIT(0)
+#define PCIE_PHY_GLOBAL_RESET 0x1040
+#define PCIE_GLOBAL_RESET BIT(0)
+#define PCIE_REFCLK BIT(1)
+#define PCIE_REFCLK_MASK 0x16
+#define PCIE_APP_REQ_EXIT_L1_MODE BIT(5)
+
+enum exynos_pcie_phy_data_type {
+ PCIE_PHY_TYPE_EXYNOS5433,
+};
+
+struct exynos_pcie_phy_data {
+ enum exynos_pcie_phy_data_type ctrl_type;
+ u32 pmureg_offset; /* PMU_REG offset */
+ struct phy_ops *ops;
+};
+
+/* for Exynos pcie phy */
+struct exynos_pcie_phy {
+ const struct exynos_pcie_phy_data *drv_data;
+ struct regmap *pmureg;
+ struct regmap *fsysreg;
+ void __iomem *phy_base;
+};
+
+static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset)
+{
+ writel(val, base + offset);
+}
+
+static int exynos_pcie_phy_init(struct phy *phy)
+{
+ struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
+
+ if (ep->fsysreg) {
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_COMMON_RESET,
+ PCIE_PHY_RESET, 1);
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_MAC_RESET,
+ PCIE_MAC_RESET, 0);
+ /* PHY refclk 24MHz */
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_GLOBAL_RESET,
+ PCIE_REFCLK_MASK, PCIE_REFCLK);
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_GLOBAL_RESET,
+ PCIE_GLOBAL_RESET, 0);
+ }
+
+ exynos_pcie_phy_writel(ep->phy_base, 0x11, PCIE_PHY_OFFSET(0x3));
+
+ /* band gap reference on */
+ exynos_pcie_phy_writel(ep->phy_base, 0, PCIE_PHY_OFFSET(0x20));
+ exynos_pcie_phy_writel(ep->phy_base, 0, PCIE_PHY_OFFSET(0x4b));
+
+ /* jitter tunning */
+ exynos_pcie_phy_writel(ep->phy_base, 0x34, PCIE_PHY_OFFSET(0x4));
+ exynos_pcie_phy_writel(ep->phy_base, 0x02, PCIE_PHY_OFFSET(0x7));
+ exynos_pcie_phy_writel(ep->phy_base, 0x41, PCIE_PHY_OFFSET(0x21));
+ exynos_pcie_phy_writel(ep->phy_base, 0x7F, PCIE_PHY_OFFSET(0x14));
+ exynos_pcie_phy_writel(ep->phy_base, 0xC0, PCIE_PHY_OFFSET(0x15));
+ exynos_pcie_phy_writel(ep->phy_base, 0x61, PCIE_PHY_OFFSET(0x36));
+
+ /* D0 uninit.. */
+ exynos_pcie_phy_writel(ep->phy_base, 0x44, PCIE_PHY_OFFSET(0x3D));
+
+ /* 24MHz */
+ exynos_pcie_phy_writel(ep->phy_base, 0x94, PCIE_PHY_OFFSET(0x8));
+ exynos_pcie_phy_writel(ep->phy_base, 0xA7, PCIE_PHY_OFFSET(0x9));
+ exynos_pcie_phy_writel(ep->phy_base, 0x93, PCIE_PHY_OFFSET(0xA));
+ exynos_pcie_phy_writel(ep->phy_base, 0x6B, PCIE_PHY_OFFSET(0xC));
+ exynos_pcie_phy_writel(ep->phy_base, 0xA5, PCIE_PHY_OFFSET(0xF));
+ exynos_pcie_phy_writel(ep->phy_base, 0x34, PCIE_PHY_OFFSET(0x16));
+ exynos_pcie_phy_writel(ep->phy_base, 0xA3, PCIE_PHY_OFFSET(0x17));
+ exynos_pcie_phy_writel(ep->phy_base, 0xA7, PCIE_PHY_OFFSET(0x1A));
+ exynos_pcie_phy_writel(ep->phy_base, 0x71, PCIE_PHY_OFFSET(0x23));
+ exynos_pcie_phy_writel(ep->phy_base, 0x4C, PCIE_PHY_OFFSET(0x24));
+
+ exynos_pcie_phy_writel(ep->phy_base, 0x0E, PCIE_PHY_OFFSET(0x26));
+ exynos_pcie_phy_writel(ep->phy_base, 0x14, PCIE_PHY_OFFSET(0x7));
+ exynos_pcie_phy_writel(ep->phy_base, 0x48, PCIE_PHY_OFFSET(0x43));
+ exynos_pcie_phy_writel(ep->phy_base, 0x44, PCIE_PHY_OFFSET(0x44));
+ exynos_pcie_phy_writel(ep->phy_base, 0x03, PCIE_PHY_OFFSET(0x45));
+ exynos_pcie_phy_writel(ep->phy_base, 0xA7, PCIE_PHY_OFFSET(0x48));
+ exynos_pcie_phy_writel(ep->phy_base, 0x13, PCIE_PHY_OFFSET(0x54));
+ exynos_pcie_phy_writel(ep->phy_base, 0x04, PCIE_PHY_OFFSET(0x31));
+ exynos_pcie_phy_writel(ep->phy_base, 0, PCIE_PHY_OFFSET(0x32));
+
+ if (ep->fsysreg) {
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_COMMON_RESET,
+ PCIE_PHY_RESET, 0);
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_MAC_RESET,
+ PCIE_MAC_RESET_MASK, PCIE_MAC_RESET);
+ }
+
+ return 0;
+}
+
+static int exynos_pcie_phy_power_on(struct phy *phy)
+{
+ struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
+
+ if (ep->pmureg) {
+ if (regmap_update_bits(ep->pmureg, ep->drv_data->pmureg_offset,
+ BIT(0), 1))
+ dev_warn(&phy->dev, "Failed to update regmap bit.\n");
+ }
+
+ if (ep->fsysreg) {
+ regmap_update_bits(ep->fsysreg, PCIE_PHY_GLOBAL_RESET,
+ PCIE_APP_REQ_EXIT_L1_MODE, 0);
+ regmap_update_bits(ep->fsysreg, PCIE_L1SUB_CM_CON,
+ PCIE_REFCLK_GATING_EN, 0);
+ }
+
+ return 0;
+}
+
+static struct phy_ops exynos_phy_ops = {
+ .init = exynos_pcie_phy_init,
+ .power_on = exynos_pcie_phy_power_on,
+};
+
+static const struct exynos_pcie_phy_data exynos5433_pcie_phy_data = {
+ .ctrl_type = PCIE_PHY_TYPE_EXYNOS5433,
+ .pmureg_offset = PCIE_EXYNOS5433_PMU_PHY_OFFSET,
+ .ops = &exynos_phy_ops,
+};
+
+static const struct of_device_id exynos_pcie_phy_match[] = {
+ {
+ .compatible = "samsung,exynos5433-pcie-phy",
+ .data = &exynos5433_pcie_phy_data,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, exynos_pcie_phy_match);
+
+static int exynos_pcie_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct exynos_pcie_phy *exynos_phy;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
+ struct resource *res;
+ const struct exynos_pcie_phy_data *drv_data;
+ const struct of_device_id *match;
+
+ exynos_phy = devm_kzalloc(dev, sizeof(*exynos_phy), GFP_KERNEL);
+ if (!exynos_phy)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ exynos_phy->phy_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(exynos_phy->phy_base))
+ return PTR_ERR(exynos_phy->phy_base);
+
+ exynos_phy->pmureg = syscon_regmap_lookup_by_phandle(np,
+ "samsung,pmureg-phandle");
+ if (IS_ERR(exynos_phy->pmureg)) {
+ dev_warn(&pdev->dev, "pmureg syscon regmap lookup failed.\n");
+ exynos_phy->pmureg = NULL;
+ }
+
+ match = of_match_node(exynos_pcie_phy_match, pdev->dev.of_node);
+ drv_data = match->data;
+ exynos_phy->drv_data = drv_data;
+
+ exynos_phy->fsysreg = syscon_regmap_lookup_by_phandle(np,
+ "samsung,fsys-sysreg");
+ if (IS_ERR(exynos_phy->fsysreg)) {
+ dev_warn(&pdev->dev, "Fsysreg syscon regmap lookup failed.\n");
+ exynos_phy->fsysreg = NULL;
+ }
+
+ generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops);
+ if (IS_ERR(generic_phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(generic_phy);
+ }
+
+ phy_set_drvdata(generic_phy, exynos_phy);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver exynos_pcie_phy_driver = {
+ .probe = exynos_pcie_phy_probe,
+ .driver = {
+ .of_match_table = exynos_pcie_phy_match,
+ .name = "exynos_pcie_phy",
+ }
+};
+module_platform_driver(exynos_pcie_phy_driver);
--
2.10.2
^ permalink raw reply related
* [RFC PATCH 2/6] Documetation: samsung-phy: add the exynos-pcie-phy binding
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci
Cc: devicetree, linux-kernel, linux-samsung-soc, bhelgaas, robh+dt,
mark.rutland, kgene, krzk, javier, kishon, will.deacon,
catalin.marinas, cpgs, Jaehoon Chung
In-Reply-To: <20161226052029.10552-1-jh80.chung@samsung.com>
Adds the exynos-pcie-phy binding for Exynos PCIe PHY.
This is for using generic PHY framework.
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
---
.../devicetree/bindings/phy/samsung-phy.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 9872ba8..eb1085e 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -191,3 +191,24 @@ Example:
usbdrdphy0 = &usb3_phy0;
usbdrdphy1 = &usb3_phy1;
};
+
+Samsung Exynos SoC series PCIe PHY controller
+--------------------------------------------------
+Required properties:
+- compatible : Should be set to "samsung,exynos5433-pcie-phy"
+- #phy-cells : must be zero
+- reg : a list of registers usd by phy driver
+
+Optional properites:
+-samsung,pmureg-phandle - handle to syscon used to control PMU registers
+-samsung,fsys-sysreg - handle to syscon used to control the system registers
+
+Example:
+ pcie_phy: pcie-phy@15680000 {
+ #phy-cells = <0>;
+ compatible = "samsung,exynos5433-pcie-phy";
+ reg = <0x15680000 0x1000>;
+ samsung,pmureg-phandle = <&pmu_system_controller>;
+ samsung,fsys-sysreg = <&syscon_fsys>;
+ status = "okay";
+ };
--
2.10.2
^ permalink raw reply related
* [RFC PATCH 3/6] ARM64: dts: exynos5433: add the pcie_phy node for PCIe
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, kgene-DgEjT+Ai2ygdnm+yROfE0A,
krzk-DgEjT+Ai2ygdnm+yROfE0A, javier-JPH+aEBZ4P+UEJcrhfAQsw,
kishon-l0cyMroinI0, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, cpgs-Sze3O3UU22JBDgjK7y7TUQ,
Jaehoon Chung
In-Reply-To: <20161226052029.10552-1-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
To use the generic PHY framework, adds the pcie_phy node.
Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
arch/arm64/boot/dts/exynos/exynos5433.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
index 64226d5..2a15f18 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -805,6 +805,11 @@
reg = <0x145f0000 0x1038>;
};
+ syscon_fsys: syscon@156f0000 {
+ compatible = "syscon";
+ reg = <0x156f0000 0x1044>;
+ };
+
gsc_0: video-scaler@13C00000 {
compatible = "samsung,exynos5433-gsc";
reg = <0x13c00000 0x1000>;
@@ -1443,6 +1448,15 @@
status = "disabled";
};
};
+
+ pcie_phy: pcie-phy@15680000 {
+ #phy-cells = <0>;
+ compatible = "samsung,exynos5433-pcie-phy";
+ reg = <0x15680000 0x1000>;
+ samsung,pmureg-phandle = <&pmu_system_controller>;
+ samsung,fsys-sysreg = <&syscon_fsys>;
+ status = "okay";
+ };
};
timer: timer {
--
2.10.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [RFC PATCH 4/6] PCI: exynos5433: Add new exynos pci host controller for Exynos5433
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, kgene-DgEjT+Ai2ygdnm+yROfE0A,
krzk-DgEjT+Ai2ygdnm+yROfE0A, javier-JPH+aEBZ4P+UEJcrhfAQsw,
kishon-l0cyMroinI0, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, cpgs-Sze3O3UU22JBDgjK7y7TUQ,
Jaehoon Chung
In-Reply-To: <20161226052029.10552-1-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Exynos5433 supports the PCIe.
This patch adds new pci-exynos5433.c file for Exynos ARM64.
Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
drivers/pci/host/Kconfig | 9 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pci-exynos5433.c | 338 ++++++++++++++++++++++++++++++++++++++
3 files changed, 348 insertions(+)
create mode 100644 drivers/pci/host/pci-exynos5433.c
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index d7e7c0a..3d77d0b 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -60,6 +60,15 @@ config PCI_EXYNOS
select PCIEPORTBUS
select PCIE_DW
+config PCI_EXYNOS5433
+ bool "Samsung Exynos5433 PCIe controller"
+ depends on ARCH_EXYNOS && ARM64
+ depends on PCI_MSI_IRQ_DOMAIN
+ select PCIEPORTBUS
+ select PCIE_DW
+ help
+ If you want support for Exynos5433 PCIe host controller, say Y.
+
config PCI_IMX6
bool "Freescale i.MX6 PCIe controller"
depends on SOC_IMX6Q
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 084cb49..2168de2 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
+obj-$(CONFIG_PCI_EXYNOS5433) += pci-exynos5433.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
diff --git a/drivers/pci/host/pci-exynos5433.c b/drivers/pci/host/pci-exynos5433.c
new file mode 100644
index 0000000..ff254ca
--- /dev/null
+++ b/drivers/pci/host/pci-exynos5433.c
@@ -0,0 +1,338 @@
+/*
+ * PCIe host controller driver for Samsung EXYNOS5433 SoCs
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/resource.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+
+#include "pcie-designware.h"
+
+#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp)
+
+/* Pcie structure for Exynos specific data */
+struct exynos_pcie {
+ void __iomem *elbi_base;
+ struct clk *clk;
+ struct clk *bus_clk;
+ struct pcie_port pp;
+ struct phy *phy;
+};
+
+/* PCIe ELBI registers */
+#define PCIE_IRQ_PULSE 0x000
+#define IRQ_INTA_ASSERT BIT(0)
+#define IRQ_INTB_ASSERT BIT(2)
+#define IRQ_INTC_ASSERT BIT(4)
+#define IRQ_INTD_ASSERT BIT(6)
+#define IRQ_INTX_ASSERT (IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | \
+ IRQ_INTC_ASSERT | IRQ_INTD_ASSERT)
+#define PCIE_IRQ_EN_PULSE 0x00c
+#define PCIE_IRQ_EN_LEVEL 0x010
+#define PCIE_SW_WAKE 0x018
+#define PCIE_BUS_EN BIT(1)
+#define PCIE_APP_LTSSM_ENABLE 0x02c
+#define PCIE_ELBI_LTSSM_ENABLE 0x1
+#define PCIE_ELBI_DEBUG_L 0x074
+#define PCIE_ELBI_XMLH_LINK_UP BIT(4)
+#define PCIE_ELBI_SLV_AWMISC 0x11c
+#define PCIE_ELBI_SLV_ARMISC 0x120
+#define PCIE_ELBI_SLV_DBI_ENABLE BIT(21)
+
+/* DBI register */
+#define PCIE_MISC_CONTROL_1_OFF 0x8BC
+#define DBI_RO_WR_EN BIT(0)
+
+static inline void exynos_pcie_writel(void __iomem *base, u32 val, u32 offset)
+{
+ writel(val, base + offset);
+}
+
+static inline u32 exynos_pcie_readl(void __iomem *base, u32 offset)
+{
+ return readl(base + offset);
+}
+
+static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)
+{
+ u32 val;
+
+ val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE);
+ val &= ~IRQ_INTX_ASSERT;
+ exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE);
+}
+
+static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
+{
+ exynos_pcie_writel(ep->elbi_base, IRQ_INTX_ASSERT, PCIE_IRQ_EN_PULSE);
+
+ /* Clear PCIE_IRQ_EN_LEVEL register */
+ exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_LEVEL);
+}
+
+static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
+{
+ struct pcie_port *pp = arg;
+ struct exynos_pcie *ep = to_exynos_pcie(pp);
+
+ exynos_pcie_clear_irq_pulse(ep);
+
+ return IRQ_HANDLED;
+}
+
+static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
+{
+ u32 val;
+
+ val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC);
+ if (on)
+ val |= PCIE_ELBI_SLV_DBI_ENABLE;
+ else
+ val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
+ exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
+}
+
+static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)
+{
+ u32 val;
+
+ val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC);
+ if (on)
+ val |= PCIE_ELBI_SLV_DBI_ENABLE;
+ else
+ val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
+ exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
+}
+
+static int exynos_pcie_establish_link(struct exynos_pcie *ep)
+{
+ struct pcie_port *pp = &ep->pp;
+ u32 val;
+
+ if (dw_pcie_link_up(pp)) {
+ dev_info(pp->dev, "Link already up\n");
+ return 0;
+ }
+
+ phy_power_on(ep->phy);
+
+ /* Exynos Pcie assert PHY reset and init */
+ phy_init(ep->phy);
+
+ val = exynos_pcie_readl(ep->elbi_base, PCIE_SW_WAKE);
+ val &= ~PCIE_BUS_EN;
+ exynos_pcie_writel(ep->elbi_base, val, PCIE_SW_WAKE);
+
+ /*
+ * Enable DBI_RO_WR_EN bit.
+ * - When set to 1, some RO and HWinit bits are wriatble from
+ * the local application through the DBI.
+ */
+ dw_pcie_writel_rc(pp, PCIE_MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
+
+ /* Setup root complex */
+ dw_pcie_setup_rc(pp);
+
+ /* assert LTSSM enable */
+ exynos_pcie_writel(ep->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
+ PCIE_APP_LTSSM_ENABLE);
+
+ return dw_pcie_wait_for_link(pp);
+}
+
+
+static int exynos_pcie_link_up(struct pcie_port *pp)
+{
+ struct exynos_pcie *ep = to_exynos_pcie(pp);
+ u32 val;
+
+ /* Check the Receive Transaction Layer Handler */
+ val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_DEBUG_L);
+
+ return (val & PCIE_ELBI_XMLH_LINK_UP);
+}
+
+static void exynos_pcie_host_init(struct pcie_port *pp)
+{
+ struct exynos_pcie *ep = to_exynos_pcie(pp);
+
+ exynos_pcie_enable_irq_pulse(ep);
+ exynos_pcie_establish_link(ep);
+}
+
+static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
+{
+ struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+ u32 val;
+
+ exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
+ val = readl(pp->dbi_base + reg);
+ exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
+ return val;
+}
+
+static void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
+{
+ struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+
+ exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
+ writel(val, pp->dbi_base + reg);
+ exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
+}
+
+static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
+ u32 *val)
+{
+ struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+ int ret;
+
+ exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
+ ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
+ exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
+ return ret;
+}
+
+static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
+ u32 val)
+{
+ struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
+ int ret;
+
+ exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
+ ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
+ exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
+ return ret;
+}
+
+static struct pcie_host_ops exynos_pcie_host_ops = {
+ .readl_rc = exynos_pcie_readl_rc,
+ .writel_rc = exynos_pcie_writel_rc,
+ .rd_own_conf = exynos_pcie_rd_own_conf,
+ .wr_own_conf = exynos_pcie_wr_own_conf,
+ .host_init = exynos_pcie_host_init,
+ .link_up = exynos_pcie_link_up,
+};
+
+static int __init exynos_pcie_probe(struct platform_device *pdev)
+{
+ struct exynos_pcie *exynos_pcie;
+ struct pcie_port *pp;
+ struct resource *res;
+ int ret;
+
+ exynos_pcie = devm_kzalloc(&pdev->dev, sizeof(*exynos_pcie),
+ GFP_KERNEL);
+ if (!exynos_pcie)
+ return -ENOMEM;
+
+ pp = &exynos_pcie->pp;
+ pp->dev = &pdev->dev;
+
+ exynos_pcie->clk = devm_clk_get(&pdev->dev, "pcie");
+ if (IS_ERR(exynos_pcie->clk)) {
+ dev_err(&pdev->dev, "Failed to get pcie rc clock\n");
+ return PTR_ERR(exynos_pcie->clk);
+ }
+ ret = clk_prepare_enable(exynos_pcie->clk);
+ if (ret)
+ return ret;
+
+ exynos_pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus");
+ if (IS_ERR(exynos_pcie->bus_clk)) {
+ dev_err(&pdev->dev, "Failed to get pcie bus clock\n");
+ ret = PTR_ERR(exynos_pcie->bus_clk);
+ goto fail_clk;
+ }
+ ret = clk_prepare_enable(exynos_pcie->bus_clk);
+ if (ret)
+ goto fail_clk;
+
+ /* External Local Bus interface(ELBI) Register */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
+ exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(exynos_pcie->elbi_base)) {
+ ret = PTR_ERR(exynos_pcie->elbi_base);
+ goto fail_bus_clk;
+ }
+
+ /* Data Bus Interface(DBI) Register */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
+ pp->dbi_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pp->dbi_base)) {
+ ret = PTR_ERR(pp->dbi_base);
+ goto fail_bus_clk;
+ }
+
+ exynos_pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy");
+ if (IS_ERR(exynos_pcie->phy)) {
+ if (PTR_ERR(exynos_pcie->phy) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Can't find the pcie-phy\n");
+ return PTR_ERR(exynos_pcie->phy);
+ }
+
+ pp->irq = platform_get_irq_byname(pdev, "intr");
+ if (!pp->irq) {
+ dev_err(&pdev->dev, "failed to get irq\n");
+ ret = -ENODEV;
+ goto fail_bus_clk;
+ }
+ ret = devm_request_irq(&pdev->dev, pp->irq, exynos_pcie_irq_handler,
+ IRQF_SHARED, "exynos-pcie", exynos_pcie);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request irq\n");
+ goto fail_bus_clk;
+ }
+
+ pp->root_bus_nr = -1;
+ pp->ops = &exynos_pcie_host_ops;
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize host\n");
+ goto fail_bus_clk;
+ }
+
+ platform_set_drvdata(pdev, exynos_pcie);
+
+ return 0;
+
+fail_bus_clk:
+ clk_disable_unprepare(exynos_pcie->bus_clk);
+fail_clk:
+ clk_disable_unprepare(exynos_pcie->clk);
+ return ret;
+}
+
+static const struct of_device_id exynos_pcie_of_match[] = {
+ { .compatible = "samsung,exynos5433-pcie", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_pcie_of_match);
+
+static struct platform_driver exynos_pcie_driver = {
+ .probe = exynos_pcie_probe,
+ .driver = {
+ .name = "exynos5433-pcie",
+ .of_match_table = exynos_pcie_of_match,
+ },
+};
+builtin_platform_driver(exynos_pcie_driver);
--
2.10.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [RFC PATCH 5/6] Documentation: pci: add the exynos5433-pcie binding
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci
Cc: devicetree, linux-kernel, linux-samsung-soc, bhelgaas, robh+dt,
mark.rutland, kgene, krzk, javier, kishon, will.deacon,
catalin.marinas, cpgs, Jaehoon Chung
In-Reply-To: <20161226052029.10552-1-jh80.chung@samsung.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
---
.../devicetree/bindings/pci/exynos5433-pcie.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/exynos5433-pcie.txt
diff --git a/Documentation/devicetree/bindings/pci/exynos5433-pcie.txt b/Documentation/devicetree/bindings/pci/exynos5433-pcie.txt
new file mode 100644
index 0000000..932a847
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/exynos5433-pcie.txt
@@ -0,0 +1,36 @@
+* Samsung Exynos5433 PCIe interface
+
+This PCIe host controller is based on the Synopsis Designware PCIe IP
+and thus inherits all the common properties defined in designware-pcie.txt.
+
+Required properties:
+- compatible: "samsung,exynos5433-pcie"
+- reg: base addresses and lengths of the pcie controller,
+ the phy controller, additional register for the phy controller.
+- reg-names: Must be "elbi", "phy" and "dbi" for each regs
+- interrupt-names: Must be "intr" for legacy interrupt pin.
+
+Other common properites refer to
+ Documentation/devicetree/binding/pci/designware-pcie.txt
+
+Example:
+
+ pcie: pcie@15700000 {
+ compatible ="samsung,exynos5433-pcie", "snps,dw-pcie";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+ clocks = <&cmu_fsys CLK_PCIE>, <&cmu_fsys CLK_PCLK_PCIE_PHY>;
+ clock-names = "pcie", "pcie_bus";
+ num-lanes = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_bus>;
+ reg = <0x156b0000 0x1000>, <0x15680000 0x1000>,
+ <0x15700000 0x1000>, <0x0c000000 0x1000>;
+ reg-names = "elbi", "phy", "dbi", "config";
+ ranges = <0x81000000 0 0 0x0c001000 0 0x00010000
+ 0x82000000 0 0x0c011000 0x0c011000 0 0x3feefff>;
+ status = "disabled";
+ };
--
2.10.2
^ permalink raw reply related
* [RFC PATCH 6/6] ARM64: exynos: add the pcie node for TM2
From: Jaehoon Chung @ 2016-12-26 5:20 UTC (permalink / raw)
To: linux-pci
Cc: devicetree, linux-kernel, linux-samsung-soc, bhelgaas, robh+dt,
mark.rutland, kgene, krzk, javier, kishon, will.deacon,
catalin.marinas, cpgs, Jaehoon Chung
In-Reply-To: <20161226052029.10552-1-jh80.chung@samsung.com>
Add the Exxynos5433 pcie node for TM2.
This pcie device is used for supporting WiFi.
And some gpios are already requested from pinctrl. so it doesn't need to
initialize.
GPJ2-0 is used for supplying to WiFi PCIe chip.
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
---
arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi | 7 +++++++
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 11 +++++++++--
arch/arm64/boot/dts/exynos/exynos5433.dtsi | 23 ++++++++++++++++++++++
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi
index ad71247..3e8b728 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi
@@ -183,6 +183,13 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ pcie_wlanen: pcie-wlanen {
+ samsung,pins = "gpj2-0";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
};
&pinctrl_finger {
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
index f21bdc2..c84a2ad 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
@@ -737,6 +737,15 @@
bus-width = <4>;
};
+&pcie {
+ assigned-clocks = <&cmu_fsys CLK_MOUT_SCLK_PCIE_100_USER>,
+ <&cmu_top CLK_MOUT_SCLK_PCIE_100>;
+ assigned-clock-parents = <&cmu_top CLK_SCLK_PCIE_100_FSYS>,
+ <&cmu_top CLK_MOUT_BUS_PLL_USER>;
+ assigned-clock-rates = <0>, <100000000>;
+ status = "okay";
+};
+
&pinctrl_alive {
pinctrl-names = "default";
pinctrl-0 = <&initial_alive>;
@@ -836,7 +845,6 @@
pinctrl-0 = <&initial_ese>;
initial_ese: initial-state {
- PIN(IN, gpj2-0, DOWN, LV1);
PIN(IN, gpj2-1, DOWN, LV1);
PIN(IN, gpj2-2, DOWN, LV1);
};
@@ -851,7 +859,6 @@
PIN(IN, gpr3-1, DOWN, LV1);
PIN(IN, gpr3-2, DOWN, LV1);
PIN(IN, gpr3-3, DOWN, LV1);
- PIN(IN, gpr3-7, NONE, LV1);
};
};
diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
index 2a15f18..da287f4 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -1457,6 +1457,29 @@
samsung,fsys-sysreg = <&syscon_fsys>;
status = "okay";
};
+
+ pcie: pcie@15700000 {
+ compatible = "samsung,exynos5433-pcie", "snps,dw-pcie";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "intr";
+ clocks = <&cmu_fsys CLK_PCIE>,
+ <&cmu_fsys CLK_PCLK_PCIE_PHY>;
+ clock-names = "pcie", "pcie_bus";
+ num-lanes = <1>;
+ pinctrl-names = "default";
+ phys = <&pcie_phy>;
+ phy-names = "pcie-phy";
+ pinctrl-0 = <&pcie_bus &pcie_wlanen>;
+ reg = <0x156b0000 0x1000>, <0x15700000 0x1000>,
+ <0x0c000000 0x1000>;
+ reg-names = "elbi", "dbi", "config";
+ ranges = <0x81000000 0 0 0x0c001000 0 0x00010000
+ 0x82000000 0 0x0c011000 0x0c011000 0 0x3feefff>;
+ status = "disabled";
+ };
};
timer: timer {
--
2.10.2
^ permalink raw reply related
* [PATCH 0/3] power: bq27xxx: add support for NVRAM R/W access
From: Matt Ranostay @ 2016-12-26 5:44 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pm-u79uwXL29TY76Z2rM5mHXA
Cc: Sebastian Reichel, Tony Lindgren, Matt Ranostay
Enable access to the NVRAM for the bq27425 chipset which allows to
update the battery metrics that are used in the state machine.
This allows adjustments of a termination voltage, design energy, and
design voltage.
Matt Ranostay (3):
bq27xxx_battery: add BQ27425 chip id
devicetree: bq27425: add documentation for bq27425 fuel gauge
power: bq27xxx: add support for NVRAM R/W access
.../devicetree/bindings/power/bq27425.txt | 25 ++
drivers/power/supply/bq27xxx_battery.c | 24 +-
drivers/power/supply/bq27xxx_battery_i2c.c | 336 ++++++++++++++++++++-
include/linux/power/bq27xxx_battery.h | 7 +-
4 files changed, 388 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/power/bq27425.txt
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/3] bq27xxx_battery: add BQ27425 chip id
From: Matt Ranostay @ 2016-12-26 5:44 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pm-u79uwXL29TY76Z2rM5mHXA
Cc: Sebastian Reichel, Tony Lindgren, Matt Ranostay
In-Reply-To: <20161226054442.23599-1-matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
---
drivers/power/supply/bq27xxx_battery.c | 24 ++++++++++++++++++++++--
drivers/power/supply/bq27xxx_battery_i2c.c | 2 +-
include/linux/power/bq27xxx_battery.h | 3 ++-
3 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index 08c36b8e04bd..721cf6f67874 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -259,6 +259,25 @@ static u8 bq27xxx_regs[][BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = 0x18,
},
+ [BQ27425] = {
+ [BQ27XXX_REG_CTRL] = 0x00,
+ [BQ27XXX_REG_TEMP] = 0x02,
+ [BQ27XXX_REG_INT_TEMP] = 0x1e,
+ [BQ27XXX_REG_VOLT] = 0x04,
+ [BQ27XXX_REG_AI] = 0x10,
+ [BQ27XXX_REG_FLAGS] = 0x06,
+ [BQ27XXX_REG_TTE] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_TTF] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_NAC] = 0x08,
+ [BQ27XXX_REG_FCC] = 0x0e,
+ [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_AE] = INVALID_REG_ADDR,
+ [BQ27XXX_REG_SOC] = 0x1c,
+ [BQ27XXX_REG_DCAP] = 0x3c,
+ [BQ27XXX_REG_AP] = 0x18,
+ },
};
static enum power_supply_property bq27000_battery_props[] = {
@@ -427,6 +446,7 @@ static struct {
BQ27XXX_PROP(BQ27541, bq27541_battery_props),
BQ27XXX_PROP(BQ27545, bq27545_battery_props),
BQ27XXX_PROP(BQ27421, bq27421_battery_props),
+ BQ27XXX_PROP(BQ27425, bq27421_battery_props),
};
static DEFINE_MUTEX(bq27xxx_list_lock);
@@ -677,7 +697,7 @@ static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
if (di->chip == BQ27500 || di->chip == BQ27510 ||
di->chip == BQ27541 || di->chip == BQ27545)
return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD);
- if (di->chip == BQ27530 || di->chip == BQ27421)
+ if (di->chip == BQ27530 || di->chip == BQ27421 || di->chip == BQ27425)
return flags & BQ27XXX_FLAG_OT;
return false;
@@ -688,7 +708,7 @@ static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
*/
static bool bq27xxx_battery_undertemp(struct bq27xxx_device_info *di, u16 flags)
{
- if (di->chip == BQ27530 || di->chip == BQ27421)
+ if (di->chip == BQ27530 || di->chip == BQ27421 || di->chip == BQ27425)
return flags & BQ27XXX_FLAG_UT;
return false;
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 5c5c3a6f9923..27143230839a 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -159,9 +159,9 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27742", BQ27541 },
{ "bq27545", BQ27545 },
{ "bq27421", BQ27421 },
- { "bq27425", BQ27421 },
{ "bq27441", BQ27421 },
{ "bq27621", BQ27421 },
+ { "bq27425", BQ27425 },
{},
};
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index bed9557b69e7..14ecac158150 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -9,7 +9,8 @@ enum bq27xxx_chip {
BQ27530, /* bq27530, bq27531 */
BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
BQ27545, /* bq27545 */
- BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
+ BQ27421, /* bq27421, bq27441, bq27621 */
+ BQ27425, /* bq27425 */
};
/**
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 2/3] devicetree: bq27425: add documentation for bq27425 fuel gauge
From: Matt Ranostay @ 2016-12-26 5:44 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pm-u79uwXL29TY76Z2rM5mHXA
Cc: Sebastian Reichel, Tony Lindgren, Matt Ranostay
In-Reply-To: <20161226054442.23599-1-matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
---
.../devicetree/bindings/power/bq27425.txt | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/bq27425.txt
diff --git a/Documentation/devicetree/bindings/power/bq27425.txt b/Documentation/devicetree/bindings/power/bq27425.txt
new file mode 100644
index 000000000000..f09f787a9378
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/bq27425.txt
@@ -0,0 +1,25 @@
+* TI BQ27425 Fuel Gauge
+
+http://www.ti.com/lit/ds/symlink/bq27425-g2a.pdf
+
+Please note that if any of the optional properties are defined
+then all settings must be.
+
+Required properties:
+- compatible: Should be "ti,bq27425"
+- reg: integer, i2c of the device
+
+Optional properties:
+- ti,design-capacity: integer of mAh of the battery
+- ti,design-energy: integer of the mWh of the battery
+- ti,terminate-voltage: integer of mV of the dead voltage of
+ the battery
+
+bq27425 {
+ compatible = "ti,bq27425";
+ reg = <0x55>;
+
+ ti,design-capacity = <1360>;
+ ti,design-energy = <4970>;
+ ti,terminate-voltage = <3200>;
+};
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 3/3] power: bq27xxx: add support for NVRAM R/W access
From: Matt Ranostay @ 2016-12-26 5:44 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pm-u79uwXL29TY76Z2rM5mHXA
Cc: Sebastian Reichel, Tony Lindgren, Matt Ranostay
In-Reply-To: <20161226054442.23599-1-matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
Initial support for access and modification of the non-volatile regions
of the bq27425 fuel gauge DesignEnergy, DesignCapacity, and
TerminateVoltage settings.
This is intended for fine tuning the fuel gauge state machine for the
respective battery specifications.
Cc: Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
---
drivers/power/supply/bq27xxx_battery_i2c.c | 334 +++++++++++++++++++++++++++++
include/linux/power/bq27xxx_battery.h | 4 +
2 files changed, 338 insertions(+)
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 27143230839a..c6f641cd3940 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -14,9 +14,11 @@
* GNU General Public License for more details.
*/
+#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <asm/unaligned.h>
#include <linux/power/bq27xxx_battery.h>
@@ -24,6 +26,48 @@
static DEFINE_IDR(battery_id);
static DEFINE_MUTEX(battery_mutex);
+#define BQ27XXX_TERM_V_MIN 2800
+#define BQ27XXX_TERM_V_MAX 3700
+
+#define BQ27XXX_REG_CTRL 0
+
+#define BQ27XXX_BLOCK_DATA_CLASS 0x3E
+#define BQ27XXX_DATA_BLOCK 0x3F
+#define BQ27XXX_BLOCK_DATA 0x40
+#define BQ27XXX_BLOCK_DATA_CHECKSUM 0x60
+#define BQ27XXX_BLOCK_DATA_CONTROL 0x61
+#define BQ27XXX_SET_CFGUPDATE 0x13
+#define BQ27XXX_SOFT_RESET 0x42
+
+enum bq27xxx_dm_subclass_index {
+ BQ27XXX_DM_DESIGN_CAP = 0,
+ BQ27XXX_DM_DESIGN_ENERGY,
+ BQ27XXX_DM_TERMINATE_VOLTAGE,
+ BQ27XXX_NUM_IDX,
+};
+
+struct bq27xxx_dm_regs {
+ unsigned int subclass_id;
+ unsigned int offset;
+ char *name;
+};
+
+#define BQ27XXX_GAS_GAUGING_STATE_SUBCLASS 82
+
+static struct bq27xxx_dm_regs bq27425_dm_subclass_regs[] = {
+ { BQ27XXX_GAS_GAUGING_STATE_SUBCLASS, 12, "design-capacity" },
+ { BQ27XXX_GAS_GAUGING_STATE_SUBCLASS, 14, "design-energy" },
+ { BQ27XXX_GAS_GAUGING_STATE_SUBCLASS, 18, "terminate-voltage" },
+};
+
+static struct bq27xxx_dm_regs *bq27xxx_dm_subclass_regs[] = {
+ [BQ27425] = bq27425_dm_subclass_regs,
+};
+
+static unsigned int bq27xxx_unseal_keys[] = {
+ [BQ27425] = 0x04143672,
+};
+
static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
{
struct bq27xxx_device_info *di = data;
@@ -68,6 +112,288 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
return ret;
}
+static int bq27xxx_battery_i2c_write(struct bq27xxx_device_info *di, u8 reg,
+ int value, bool single)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ struct i2c_msg msg;
+ unsigned char data[4];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ data[0] = reg;
+ if (single) {
+ data[1] = (unsigned char) value;
+ msg.len = 2;
+ } else {
+ put_unaligned_le16(value, &data[1]);
+ msg.len = 3;
+ }
+
+ msg.buf = data;
+ msg.addr = client->addr;
+ msg.flags = 0;
+
+ return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EINVAL;
+}
+
+static int bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info *di, u8 reg,
+ u8 *data, int len)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ return i2c_smbus_read_i2c_block_data(client, reg, len, data);
+}
+
+static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
+ u8 reg, u8 *data, int len)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ struct i2c_msg msg;
+ u8 buf[33];
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ buf[0] = reg;
+ memcpy(&buf[1], data, len);
+
+ msg.buf = buf;
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = len + 1;
+
+ return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EINVAL;
+}
+
+static int bq27xxx_battery_i2c_set_seal_state(struct bq27xxx_device_info *di,
+ bool state)
+{
+ unsigned int key = bq27xxx_unseal_keys[di->chip];
+ int ret;
+
+ if (state)
+ return di->bus.write(di, BQ27XXX_REG_CTRL, 0x20, false);
+
+ ret = di->bus.write(di, BQ27XXX_REG_CTRL, (key >> 16) & 0xffff, false);
+ if (ret < 0)
+ return ret;
+
+ return di->bus.write(di, BQ27XXX_REG_CTRL, key & 0xffff, false);
+}
+
+static int bq27xxx_battery_i2c_read_dm_block(struct bq27xxx_device_info *di,
+ int subclass)
+{
+ int ret = di->bus.write(di, BQ27XXX_REG_CTRL, 0, false);
+
+ if (ret < 0)
+ return ret;
+
+ ret = di->bus.write(di, BQ27XXX_BLOCK_DATA_CONTROL, 0, true);
+ if (ret < 0)
+ return ret;
+
+ ret = di->bus.write(di, BQ27XXX_BLOCK_DATA_CLASS, subclass, true);
+ if (ret < 0)
+ return ret;
+
+ ret = di->bus.write(di, BQ27XXX_DATA_BLOCK, 0, true);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(1000, 1500);
+
+ return di->bus.read_bulk(di, BQ27XXX_BLOCK_DATA,
+ (u8 *) &di->buffer, sizeof(di->buffer));
+}
+
+static int bq27xxx_battery_i2c_print_config(struct bq27xxx_device_info *di)
+{
+ struct bq27xxx_dm_regs *reg = bq27xxx_dm_subclass_regs[di->chip];
+ int ret, i;
+
+ ret = bq27xxx_battery_i2c_read_dm_block(di,
+ BQ27XXX_GAS_GAUGING_STATE_SUBCLASS);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < BQ27XXX_NUM_IDX; i++) {
+ int val;
+
+ if (reg->subclass_id != BQ27XXX_GAS_GAUGING_STATE_SUBCLASS)
+ continue;
+
+ val = be16_to_cpup((u16 *) &di->buffer[reg->offset]);
+
+ dev_info(di->dev, "settings for %s set at %d\n", reg->name, val);
+
+ reg++;
+ }
+
+ return 0;
+}
+
+static bool bq27xxx_battery_update_dm_setting(struct bq27xxx_device_info *di,
+ unsigned int reg, unsigned int val)
+{
+ struct bq27xxx_dm_regs *dm_reg = &bq27xxx_dm_subclass_regs[di->chip][reg];
+ u16 *prev = (u16 *) &di->buffer[dm_reg->offset];
+
+ if (be16_to_cpup(prev) == val)
+ return false;
+
+ *prev = cpu_to_be16(val);
+
+ return true;
+}
+
+static u8 bq27xxx_battery_checksum(struct bq27xxx_device_info *di)
+{
+ u8 *data = (u8 *) &di->buffer;
+ u16 sum = 0;
+ int i;
+
+ for (i = 0; i < sizeof(di->buffer); i++) {
+ sum += data[i];
+ sum &= 0xff;
+ }
+
+ return 0xff - sum;
+}
+
+static int bq27xxx_battery_i2c_write_nvram(struct bq27xxx_device_info *di,
+ unsigned int subclass)
+{
+ int ret;
+
+ ret = di->bus.write(di, BQ27XXX_REG_CTRL, BQ27XXX_SET_CFGUPDATE, false);
+ if (ret)
+ return ret;
+
+ ret = di->bus.write(di, BQ27XXX_BLOCK_DATA_CONTROL, 0, true);
+ if (ret)
+ return ret;
+
+ ret = di->bus.write(di, BQ27XXX_BLOCK_DATA_CLASS, subclass, true);
+ if (ret)
+ return ret;
+
+ ret = di->bus.write(di, BQ27XXX_DATA_BLOCK, 0, true);
+ if (ret)
+ return ret;
+
+ ret = di->bus.write_bulk(di, BQ27XXX_BLOCK_DATA,
+ (u8 *) &di->buffer, sizeof(di->buffer));
+ if (ret < 0)
+ return ret;
+
+ usleep_range(1000, 1500);
+
+ di->bus.write(di, BQ27XXX_BLOCK_DATA_CHECKSUM,
+ bq27xxx_battery_checksum(di), true);
+
+ usleep_range(1000, 1500);
+
+ di->bus.write(di, BQ27XXX_REG_CTRL, BQ27XXX_SOFT_RESET, false);
+
+ return 0;
+}
+
+static int bq27xxx_battery_i2c_set_config(struct bq27xxx_device_info *di,
+ unsigned int cap, unsigned int energy,
+ unsigned int voltage)
+{
+ int ret = bq27xxx_battery_i2c_read_dm_block(di,
+ BQ27XXX_GAS_GAUGING_STATE_SUBCLASS);
+
+ if (ret < 0)
+ return ret;
+
+ ret = bq27xxx_battery_update_dm_setting(di, BQ27XXX_DM_DESIGN_CAP, cap);
+ ret |= bq27xxx_battery_update_dm_setting(di, BQ27XXX_DM_DESIGN_ENERGY,
+ energy);
+ ret |= bq27xxx_battery_update_dm_setting(di, BQ27XXX_DM_TERMINATE_VOLTAGE,
+ voltage);
+
+ if (ret) {
+ dev_info(di->dev, "updating NVM settings\n");
+ return bq27xxx_battery_i2c_write_nvram(di,
+ BQ27XXX_GAS_GAUGING_STATE_SUBCLASS);
+ }
+
+ return 0;
+}
+
+static int bq27xxx_battery_i2c_parse_dt(struct bq27xxx_device_info *di)
+{
+ struct device_node *np = di->dev->of_node;
+ int cap, energy, voltage = -EINVAL;
+ int ret = 0;
+
+ /* no settings to be set for this chipset so abort */
+ if (!bq27xxx_dm_subclass_regs[di->chip])
+ return 0;
+
+ bq27xxx_battery_i2c_set_seal_state(di, false);
+
+ if (np) {
+ ret = of_property_read_u32(np, "ti,design-capacity", &cap);
+ if (ret < 0 || cap > 0x7fff) {
+ if (!ret)
+ dev_err(di->dev,
+ "invalid ti,design-capacity %d\n",
+ cap);
+ cap = -EINVAL;
+ }
+
+ ret = of_property_read_u32(np, "ti,design-energy", &energy);
+ if (ret < 0 || energy > 0x7fff) {
+ if (!ret)
+ dev_err(di->dev,
+ "invalid ti,design-energy %d\n",
+ energy);
+ energy = -EINVAL;
+ }
+
+ ret = of_property_read_u32(np, "ti,terminate-voltage", &voltage);
+ if (ret < 0 || voltage < BQ27XXX_TERM_V_MIN
+ || voltage > BQ27XXX_TERM_V_MAX) {
+ if (!ret)
+ dev_err(di->dev,
+ "invalid ti,terminate-voltage %d\n",
+ voltage);
+ voltage = -EINVAL;
+ }
+
+ /* assume that we want the defaults */
+ if (cap < 0 && energy < 0 && voltage < 0) {
+ ret = 0;
+ goto out;
+ }
+
+ /* we need all three settings for safety reasons */
+ if (cap < 0 || energy < 0 || voltage < 0) {
+ dev_err(di->dev,
+ "missing or invalid devicetree values; NVM not updated\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = bq27xxx_battery_i2c_set_config(di, cap, energy, voltage);
+ }
+
+out:
+ bq27xxx_battery_i2c_print_config(di);
+ bq27xxx_battery_i2c_set_seal_state(di, true);
+
+ return ret;
+}
+
static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -95,7 +421,15 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
di->dev = &client->dev;
di->chip = id->driver_data;
di->name = name;
+
di->bus.read = bq27xxx_battery_i2c_read;
+ di->bus.write = bq27xxx_battery_i2c_write;
+ di->bus.read_bulk = bq27xxx_battery_i2c_bulk_read;
+ di->bus.write_bulk = bq27xxx_battery_i2c_bulk_write;
+
+ ret = bq27xxx_battery_i2c_parse_dt(di);
+ if (ret)
+ goto err_failed;
ret = bq27xxx_battery_setup(di);
if (ret)
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index 14ecac158150..22b4cfc3acab 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -33,6 +33,9 @@ struct bq27xxx_platform_data {
struct bq27xxx_device_info;
struct bq27xxx_access_methods {
int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
+ int (*write)(struct bq27xxx_device_info *di, u8 reg, int value, bool single);
+ int (*read_bulk)(struct bq27xxx_device_info *di, u8 reg, u8 *data, int len);
+ int (*write_bulk)(struct bq27xxx_device_info *di, u8 reg, u8 *data, int len);
};
struct bq27xxx_reg_cache {
@@ -62,6 +65,7 @@ struct bq27xxx_device_info {
struct power_supply *bat;
struct list_head list;
struct mutex lock;
+ u8 buffer[32];
u8 *regs;
};
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [RESEND 1/2] document: dt: add binding for Hi3660 SoC
From: Chen Feng @ 2016-12-26 9:36 UTC (permalink / raw)
To: puck.chen, xuwei5, robh+dt, mark.rutland, catalin.marinas,
will.deacon, linux-arm-kernel, devicetree, linux-kernel
Cc: suzhuangluan, xuyiping
Add binding for hisilicon Hi3660 SoC and HiKey960 Board.
Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
---
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 3f81575..7cf2847 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -8,6 +8,10 @@ Hi6220 SoC
Required root node properties:
- compatible = "hisilicon,hi6220";
+Hi3660 SoC
+Required root node properties:
+ - compatible = "hisilicon,hi3660";
+
HiKey Board
Required root node properties:
- compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220";
--
1.9.1
^ permalink raw reply related
* [RESEND 2/2] arm64: dts: Add dts files for Hisilicon Hi3660 SoC
From: Chen Feng @ 2016-12-26 9:36 UTC (permalink / raw)
To: puck.chen, xuwei5, robh+dt, mark.rutland, catalin.marinas,
will.deacon, linux-arm-kernel, devicetree, linux-kernel
Cc: suzhuangluan, xuyiping
In-Reply-To: <1482744972-56622-1-git-send-email-puck.chen@hisilicon.com>
Add initial dtsi file to support Hisilicon Hi3660 SoC with
support of Octal core CPUs in two clusters(4 * A53 & 4 * A73).
Also add dts file to support HiKey960 development board which
based on Hi3660 SoC.
The output console is earlycon "earlycon=pl011,0xfdf05000".
And the con_init uart5 with a fixed clock, which already
configured at bootloader.
When clock is available, the uart5 will be modified.
Tested on HiKey960 Board.
Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
---
arch/arm64/boot/dts/hisilicon/Makefile | 1 +
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 34 +++++
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 156 ++++++++++++++++++++++
3 files changed, 191 insertions(+)
create mode 100644 arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
create mode 100644 arch/arm64/boot/dts/hisilicon/hi3660.dtsi
diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile
index d5f43a0..b633b5d 100644
--- a/arch/arm64/boot/dts/hisilicon/Makefile
+++ b/arch/arm64/boot/dts/hisilicon/Makefile
@@ -1,4 +1,5 @@
dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
+dtb-$(CONFIG_ARCH_HISI) += hi3660-hikey960.dtb
dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
new file mode 100644
index 0000000..3d7aead
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -0,0 +1,34 @@
+/*
+ * dts file for Hisilicon HiKey960 Development Board
+ *
+ * Copyright (C) 2016, Hisilicon Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include "hi3660.dtsi"
+
+/ {
+ model = "HiKey960";
+ compatible = "hisilicon,hi3660";
+
+ aliases {
+ serial5 = &uart5; /* console UART */
+ };
+
+ chosen {
+ stdout-path = "serial5:115200n8";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x00400000 0x0 0xBFE00000>;
+ };
+
+ soc {
+ uart5: uart@fdf05000 {
+ status = "ok";
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
new file mode 100644
index 0000000..7f9805c
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -0,0 +1,156 @@
+/*
+ * dts file for Hisilicon Hi3660 SoC
+ *
+ * Copyright (C) 2016, Hisilicon Ltd.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "hisilicon,hi3660";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ core2 {
+ cpu = <&cpu2>;
+ };
+ core3 {
+ cpu = <&cpu3>;
+ };
+ };
+ cluster1 {
+ core0 {
+ cpu = <&cpu4>;
+ };
+ core1 {
+ cpu = <&cpu5>;
+ };
+ core2 {
+ cpu = <&cpu6>;
+ };
+ core3 {
+ cpu = <&cpu7>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x2>;
+ enable-method = "psci";
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x3>;
+ enable-method = "psci";
+ };
+
+ cpu4: cpu@100 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ };
+
+ cpu5: cpu@101 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x101>;
+ enable-method = "psci";
+ };
+
+ cpu6: cpu@102 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x102>;
+ enable-method = "psci";
+ };
+
+ cpu7: cpu@103 {
+ compatible = "arm,armv8";
+ device_type = "cpu";
+ reg = <0x0 0x103>;
+ enable-method = "psci";
+ };
+ };
+
+ gic: interrupt-controller@e82b0000 {
+ compatible = "arm,gic-400";
+ reg = <0x0 0xe82b1000 0 0x1000>, /* GICD */
+ <0x0 0xe82b2000 0 0x2000>, /* GICC */
+ <0x0 0xe82b4000 0 0x2000>, /* GICH */
+ <0x0 0xe82b6000 0 0x2000>; /* GICV */
+ #address-cells = <0>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <1920000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ fixed_uart5: fixed_19_2M {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <19200000>;
+ clock-output-names = "fixed:uart5";
+ };
+
+ uart5: uart@fdf05000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0 0xfdf05000 0x0 0x1000>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&fixed_uart5 &fixed_uart5>;
+ clock-names = "uartclk", "apb_pclk";
+ status = "ok";
+ };
+ };
+};
--
1.9.1
^ permalink raw reply related
* Re: [RFC PATCH v2 3/4] hwmon: adc128d818: Trivial code style fixup
From: Guenter Roeck @ 2016-12-26 10:47 UTC (permalink / raw)
To: Alexander Koch, linux-kernel, linux-hwmon, devicetree
Cc: Rob Herring, Mark Rutland, Jean Delvare, Jiri Kosina
In-Reply-To: <20161223221205.8825-4-mail@alexanderkoch.net>
On 12/23/2016 02:12 PM, Alexander Koch wrote:
> Replace sysfs symbolic file permissions, e.g. 'S_IRUGO', by octal
> permissions. This fixes checkpatch.pl warnings.
>
> Signed-off-by: Alexander Koch <mail@alexanderkoch.net>
Please do not bother with those warnings and ignore checkpatch.
We are in the process of doing an automated conversion.
Thanks,
Guenter
> ---
> drivers/hwmon/adc128d818.c | 99 ++++++++++++++++++----------------------------
> 1 file changed, 39 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c
> index 8667f454ea11..cbb3bc5e5229 100644
> --- a/drivers/hwmon/adc128d818.c
> +++ b/drivers/hwmon/adc128d818.c
> @@ -242,69 +242,48 @@ static ssize_t adc128_show_alarm(struct device *dev,
> return sprintf(buf, "%u\n", !!(alarms & mask));
> }
>
> -static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO,
> - adc128_show_in, NULL, 0, 0);
> -static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 0, 1);
> -static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 0, 2);
> -
> -static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO,
> - adc128_show_in, NULL, 1, 0);
> -static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 1, 1);
> -static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 1, 2);
> -
> -static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO,
> - adc128_show_in, NULL, 2, 0);
> -static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 2, 1);
> -static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 2, 2);
> -
> -static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO,
> - adc128_show_in, NULL, 3, 0);
> -static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 3, 1);
> -static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 3, 2);
> -
> -static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO,
> - adc128_show_in, NULL, 4, 0);
> -static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 4, 1);
> -static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 4, 2);
> -
> -static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO,
> - adc128_show_in, NULL, 5, 0);
> -static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 5, 1);
> -static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 5, 2);
> -
> -static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO,
> - adc128_show_in, NULL, 6, 0);
> -static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 6, 1);
> -static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO,
> - adc128_show_in, adc128_set_in, 6, 2);
> -
> -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adc128_show_temp, NULL, 0);
> -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
> +static SENSOR_DEVICE_ATTR_2(in0_input, 0444, adc128_show_in, NULL, 0, 0);
> +static SENSOR_DEVICE_ATTR_2(in0_min, 0644, adc128_show_in, adc128_set_in, 0, 1);
> +static SENSOR_DEVICE_ATTR_2(in0_max, 0644, adc128_show_in, adc128_set_in, 0, 2);
> +
> +static SENSOR_DEVICE_ATTR_2(in1_input, 0444, adc128_show_in, NULL, 1, 0);
> +static SENSOR_DEVICE_ATTR_2(in1_min, 0644, adc128_show_in, adc128_set_in, 1, 1);
> +static SENSOR_DEVICE_ATTR_2(in1_max, 0644, adc128_show_in, adc128_set_in, 1, 2);
> +
> +static SENSOR_DEVICE_ATTR_2(in2_input, 0444, adc128_show_in, NULL, 2, 0);
> +static SENSOR_DEVICE_ATTR_2(in2_min, 0644, adc128_show_in, adc128_set_in, 2, 1);
> +static SENSOR_DEVICE_ATTR_2(in2_max, 0644, adc128_show_in, adc128_set_in, 2, 2);
> +
> +static SENSOR_DEVICE_ATTR_2(in3_input, 0444, adc128_show_in, NULL, 3, 0);
> +static SENSOR_DEVICE_ATTR_2(in3_min, 0644, adc128_show_in, adc128_set_in, 3, 1);
> +static SENSOR_DEVICE_ATTR_2(in3_max, 0644, adc128_show_in, adc128_set_in, 3, 2);
> +
> +static SENSOR_DEVICE_ATTR_2(in4_input, 0444, adc128_show_in, NULL, 4, 0);
> +static SENSOR_DEVICE_ATTR_2(in4_min, 0644, adc128_show_in, adc128_set_in, 4, 1);
> +static SENSOR_DEVICE_ATTR_2(in4_max, 0644, adc128_show_in, adc128_set_in, 4, 2);
> +
> +static SENSOR_DEVICE_ATTR_2(in5_input, 0444, adc128_show_in, NULL, 5, 0);
> +static SENSOR_DEVICE_ATTR_2(in5_min, 0644, adc128_show_in, adc128_set_in, 5, 1);
> +static SENSOR_DEVICE_ATTR_2(in5_max, 0644, adc128_show_in, adc128_set_in, 5, 2);
> +
> +static SENSOR_DEVICE_ATTR_2(in6_input, 0444, adc128_show_in, NULL, 6, 0);
> +static SENSOR_DEVICE_ATTR_2(in6_min, 0644, adc128_show_in, adc128_set_in, 6, 1);
> +static SENSOR_DEVICE_ATTR_2(in6_max, 0644, adc128_show_in, adc128_set_in, 6, 2);
> +
> +static SENSOR_DEVICE_ATTR(temp1_input, 0444, adc128_show_temp, NULL, 0);
> +static SENSOR_DEVICE_ATTR(temp1_max, 0644,
> adc128_show_temp, adc128_set_temp, 1);
> -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, 0644,
> adc128_show_temp, adc128_set_temp, 2);
>
> -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, adc128_show_alarm, NULL, 0);
> -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, adc128_show_alarm, NULL, 1);
> -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, adc128_show_alarm, NULL, 2);
> -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, adc128_show_alarm, NULL, 3);
> -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, adc128_show_alarm, NULL, 4);
> -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, adc128_show_alarm, NULL, 5);
> -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, adc128_show_alarm, NULL, 6);
> -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adc128_show_alarm, NULL, 7);
> +static SENSOR_DEVICE_ATTR(in0_alarm, 0444, adc128_show_alarm, NULL, 0);
> +static SENSOR_DEVICE_ATTR(in1_alarm, 0444, adc128_show_alarm, NULL, 1);
> +static SENSOR_DEVICE_ATTR(in2_alarm, 0444, adc128_show_alarm, NULL, 2);
> +static SENSOR_DEVICE_ATTR(in3_alarm, 0444, adc128_show_alarm, NULL, 3);
> +static SENSOR_DEVICE_ATTR(in4_alarm, 0444, adc128_show_alarm, NULL, 4);
> +static SENSOR_DEVICE_ATTR(in5_alarm, 0444, adc128_show_alarm, NULL, 5);
> +static SENSOR_DEVICE_ATTR(in6_alarm, 0444, adc128_show_alarm, NULL, 6);
> +static SENSOR_DEVICE_ATTR(temp1_max_alarm, 0444, adc128_show_alarm, NULL, 7);
>
> static struct attribute *adc128_attrs[] = {
> &sensor_dev_attr_in0_min.dev_attr.attr,
>
^ permalink raw reply
* RE: [PATCH] adc: add adc driver for Hisilicon BVT SOCs
From: liurenzhong @ 2016-12-26 11:05 UTC (permalink / raw)
To: Jonathan Cameron, jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
knaack.h-Mmb7MZpHnFY@public.gmane.org,
lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org,
pmeerw-jW+XmwGofnusTnJN9+BGXg@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org
Cc: akinobu.mita-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
ludovic.desroches-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org,
krzk-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
vilhelm.gray-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
ksenija.stanojevic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
zhiyong.tao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
daniel.baluta-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
leonard.crestez-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
ray.jui-dY08KVG/lbpWk0Htik3J/w@public.gmane.org,
raveendra.padasalagi-dY08KVG/lbpWk0Htik3J/w@public.gmane.org,
mranostay-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
amsfield22-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel
In-Reply-To: <951BC246-0676-4DBF-856B-832E0F977ACB-tko9wxEg+fIOOJlXag/Snyp2UmYkHbXO@public.gmane.org>
Hi Jonathan,
Thanks very much for your reply , it get me great courage to continue this upstreaming .
we will make a careful analysis of your suggestion and update a new patch after a few days.
Best regards
/Allen
/---------------------/
From: Jonathan Cameron [mailto:jic23@jic23.retrosnub.co.uk]
Sent: 24 December 2016 19:46
To: liurenzhong; jic23@kernel.org; knaack.h@gmx.de; lars@metafoo.de; pmeerw@pmeerw.net; robh+dt@kernel.org; mark.rutland@arm.com
Cc: akinobu.mita@gmail.com; ludovic.desroches@atmel.com; krzk@kernel.org; vilhelm.gray@gmail.com; ksenija.stanojevic@gmail.com; zhiyong.tao@mediatek.com; daniel.baluta@intel.com; leonard.crestez@intel.com; ray.jui@broadcom.com; raveendra.padasalagi@broadcom.com; mranostay@gmail.com; amsfield22@gmail.com; linux-iio@vger.kernel.org; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Xuejiancheng; Lixu (kevin)
Subject: Re: [PATCH] adc: add adc driver for Hisilicon BVT SOCs
On 24 December 2016 01:54:57 GMT+00:00, Allen Liu <liurenzhong@hisilicon.com> wrote:
>Add ADC driver for the ADC controller found on HiSilicon BVT SOCs, like
>Hi3516CV300, etc.
>The ADC controller is primarily in charge of detecting voltage.
>
>Reviewed-by: Jiancheng Xue <xuejiancheng@hisilicon.com>
>Signed-off-by: Allen Liu <liurenzhong@hisilicon.com>
Reading on phone so may not be that thorough!
Looks pretty good. The device abstraction makes it slightly more complicated than it needs to be. If you aren't going to follow up quickly with other device support please drop the abstraction. It can be easily readded when needed.
Various little things inline.
Thanks
Jonathan
>---
> .../devicetree/bindings/iio/adc/hibvt-lsadc.txt | 26 ++
> drivers/iio/adc/Kconfig | 10 +
> drivers/iio/adc/Makefile | 1 +
>drivers/iio/adc/hibvt_lsadc.c | 344
>+++++++++++++++++++++
> 4 files changed, 381 insertions(+)
>create mode 100644
>Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
> create mode 100644 drivers/iio/adc/hibvt_lsadc.c
>
>diff --git a/Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
>b/Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
>new file mode 100644
>index 0000000..63de46e
>--- /dev/null
>+++ b/Documentation/devicetree/bindings/iio/adc/hibvt-lsadc.txt
>@@ -0,0 +1,26 @@
>+Hisilicon BVT Low Speed (LS) A/D Converter bindings
>+
>+Required properties:
>+- compatible: should be "hisilicon,<name>-lsadc"
>+ - "hisilicon,hibvt-lsadc": for hi3516cv300
>+
>+- reg: physical base address of the controller and length of memory
>mapped
>+ region.
>+- interrupts: The interrupt number to the cpu. The interrupt specifier
>format
>+ depends on the interrupt controller.
A cross reference to the interrupt bindings doc always good to add.
>+- #io-channel-cells: Should be 1, see ../iio-bindings.txt
>+
>+Optional properties:
>+- resets: Must contain an entry for each entry in reset-names if need
>support
>+ this option. See ../reset/reset.txt for details.
>+- reset-names: Must include the name "saradc-apb".
>+
>+Example:
>+ lsadc: hibvt-lsadc@120e0000 {
>+ compatible = "hisilicon,hibvt-lsadc";
>+ reg = <0x120e0000 0x1000>;
>+ interrupts = <19>;
>+ resets = <&crg 0x7c 3>;
>+ reset-names = "lsadc-crg";
Doesn't contain saradc-apb which docs say it must...
>+ status = "disabled";
Not documented...
>+ };
>diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index
>99c0514..0443f51 100644
>--- a/drivers/iio/adc/Kconfig
>+++ b/drivers/iio/adc/Kconfig
>@@ -225,6 +225,16 @@ config HI8435
> This driver can also be built as a module. If so, the module will be
> called hi8435.
>
>+config HIBVT_LSADC
>+ tristate "HIBVT LSADC driver"
>+ depends on ARCH_HISI || COMPILE_TEST
>+ help
>+ Say yes here to build support for the LSADC found in SoCs from
>+ hisilicon BVT chip.
>+
>+ To compile this driver as a module, choose M here: the
>+ module will be called hibvt_lsadc.
>+
> config INA2XX_ADC
> tristate "Texas Instruments INA2xx Power Monitors IIO driver"
> depends on I2C && !SENSORS_INA2XX
>diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index
>7a40c04..6554d92 100644
>--- a/drivers/iio/adc/Makefile
>+++ b/drivers/iio/adc/Makefile
>@@ -23,6 +23,7 @@ obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
> obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
> obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
> obj-$(CONFIG_HI8435) += hi8435.o
>+obj-$(CONFIG_HIBVT_LSADC) += hibvt_lsadc.o
> obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
> obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
> obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o diff --git
>a/drivers/iio/adc/hibvt_lsadc.c b/drivers/iio/adc/hibvt_lsadc.c new
>file mode 100644 index 0000000..a20afe8
>--- /dev/null
>+++ b/drivers/iio/adc/hibvt_lsadc.c
>@@ -0,0 +1,344 @@
>+/*
>+ * Hisilicon BVT Low Speed (LS) A/D Converter
>+ * Copyright (C) 2016 HiSilicon Technologies Co., Ltd.
>+ *
>+ * 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/module.h>
>+#include <linux/platform_device.h>
>+#include <linux/interrupt.h>
>+#include <linux/io.h>
>+#include <linux/of.h>
>+#include <linux/of_device.h>
>+#include <linux/clk.h>
>+#include <linux/completion.h>
>+#include <linux/delay.h>
>+#include <linux/reset.h>
>+#include <linux/regulator/consumer.h>
>+#include <linux/iio/iio.h>
>+
>+/* hisilicon bvt adc registers definitions */
>+#define LSADC_CONFIG 0x00
>+#define CONFIG_DEGLITCH BIT(17)
Please add a driver specific prefix to all defines to keep them in their own namespace.
>+#define CONFIG_RESET BIT(15)
>+#define CONFIG_POWERDOWN BIT(14)
>+#define CONFIG_MODE BIT(13)
>+#define CONFIG_CHC_VALID BIT(10)
>+#define CONFIG_CHB_VALID BIT(9)
>+#define CONFIG_CHA_VALID BIT(8)
>+
>+#define LSADC_TIMESCAN 0x08
Lsadc is perhaps to generic a prefix. Clash chances are a bit high
>+#define LSADC_INTEN 0x10
>+#define LSADC_INTSTATUS 0x14
>+#define LSADC_INTCLR 0x18
>+#define LSADC_START 0x1C
>+#define LSADC_STOP 0x20
>+#define LSADC_ACTBIT 0x24
>+#define LSADC_CHNDATA 0x2C
>+
>+#define ADC_CON_EN (1u << 0)
>+#define ADC_CON_DEN (0u << 0)
>+
>+#define ADC_NUM_BITS 10
>+
>+/* fix clk:3000000, default tscan set 10ms */
>+#define DEF_ADC_TSCAN_MS (10*3000)
>+
>+#define LSADC_CHN_MASK 0x7
>+
>+#define LSADC_TIMEOUT msecs_to_jiffies(100)
>+
>+/* default voltage scale for every channel <mv> */ static int
>+g_voltage[] = {
>+ 3300, 3300, 3300
>+};
Prefix these as well.
>+
>+struct hibvt_lsadc {
>+ void __iomem *regs;
>+ struct completion completion;
>+ struct reset_control *reset;
>+ const struct hibvt_lsadc_data *data;
>+ unsigned int cur_chn;
>+ unsigned int value;
>+};
>+
>+struct hibvt_lsadc_data {
>+ int num_bits;
>+ const struct iio_chan_spec *channels;
>+ int num_channels;
>+
>+ void (*clear_irq)(struct hibvt_lsadc *info, int mask);
>+ void (*start_conv)(struct hibvt_lsadc *info);
>+ void (*stop_conv)(struct hibvt_lsadc *info); };
>+
>+static int hibvt_lsadc_read_raw(struct iio_dev *indio_dev,
>+ struct iio_chan_spec const *chan,
>+ int *val, int *val2, long mask) {
>+ struct hibvt_lsadc *info = iio_priv(indio_dev);
>+
>+ switch (mask) {
>+ case IIO_CHAN_INFO_RAW:
>+ mutex_lock(&indio_dev->mlock);
>+
>+ reinit_completion(&info->completion);
>+
>+ /* Select the channel to be used */
>+ info->cur_chn = chan->channel;
>+
>+ if (info->data->start_conv)
>+ info->data->start_conv(info);
>+
>+ if (!wait_for_completion_timeout(&info->completion,
>+ LSADC_TIMEOUT)) {
>+ if (info->data->stop_conv)
>+ info->data->stop_conv(info);
>+ mutex_unlock(&indio_dev->mlock);
>+ return -ETIMEDOUT;
>+ }
>+
>+ *val = info->value;
>+ mutex_unlock(&indio_dev->mlock);
>+ return IIO_VAL_INT;
>+ case IIO_CHAN_INFO_SCALE:
>+ *val = g_voltage[chan->channel];
>+ *val2 = info->data->num_bits;
>+ return IIO_VAL_FRACTIONAL_LOG2;
>+ default:
>+ return -EINVAL;
>+ }
>+}
>+
>+static irqreturn_t hibvt_lsadc_isr(int irq, void *dev_id) {
>+ struct hibvt_lsadc *info = (struct hibvt_lsadc *)dev_id;
>+ int mask;
>+
>+ mask = readl(info->regs + LSADC_INTSTATUS);
>+ mask &= LSADC_CHN_MASK;
>+
>+ /* Clear irq */
>+ if (info->data->clear_irq)
>+ info->data->clear_irq(info, mask);
>+
>+ /* Read value */
>+ info->value = readl(info->regs + LSADC_CHNDATA + (info->cur_chn <<
>2));
>+ info->value &= GENMASK(info->data->num_bits - 1, 0);
>+
>+ /* stop adc */
>+ if (info->data->stop_conv)
>+ info->data->stop_conv(info);
>+
>+ complete(&info->completion);
>+
>+ return IRQ_HANDLED;
>+}
>+
>+static const struct iio_info hibvt_lsadc_iio_info = {
>+ .read_raw = hibvt_lsadc_read_raw,
>+ .driver_module = THIS_MODULE,
>+};
>+
>+#define ADC_CHANNEL(_index, _id) { \
Prefix this define.
>+ .type = IIO_VOLTAGE, \
>+ .indexed = 1, \
>+ .channel = _index, \
>+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
>+ BIT(IIO_CHAN_INFO_SCALE), \
>+ .datasheet_name = _id, \
>+}
>+
>+static const struct iio_chan_spec hibvt_lsadc_iio_channels[] = {
>+ ADC_CHANNEL(0, "adc0"),
>+ ADC_CHANNEL(1, "adc1"),
>+ ADC_CHANNEL(2, "adc2"),
>+};
>+
>+static void hibvt_lsadc_clear_irq(struct hibvt_lsadc *info, int mask)
>+{
>+ writel(mask, info->regs + LSADC_INTCLR); }
>+
>+static void hibvt_lsadc_start_conv(struct hibvt_lsadc *info) {
>+ unsigned int con;
>+
>+ /* set number bit */
>+ con = GENMASK(info->data->num_bits - 1, 0);
>+ writel(con, (info->regs + LSADC_ACTBIT));
>+
>+ /* config */
>+ con = readl(info->regs + LSADC_CONFIG);
>+ con &= ~CONFIG_RESET;
>+ con |= (CONFIG_POWERDOWN | CONFIG_DEGLITCH | CONFIG_MODE);
>+ con &= ~(CONFIG_CHA_VALID | CONFIG_CHB_VALID | CONFIG_CHC_VALID);
>+ con |= (CONFIG_CHA_VALID << info->cur_chn);
>+ writel(con, (info->regs + LSADC_CONFIG));
>+
>+ /* set timescan */
>+ writel(DEF_ADC_TSCAN_MS, (info->regs + LSADC_TIMESCAN));
>+
>+ /* clear interrupt */
>+ writel(LSADC_CHN_MASK, info->regs + LSADC_INTCLR);
>+
>+ /* enable interrupt */
>+ writel(ADC_CON_EN, (info->regs + LSADC_INTEN));
>+
>+ /* start scan */
>+ writel(ADC_CON_EN, (info->regs + LSADC_START)); }
>+
>+static void hibvt_lsadc_stop_conv(struct hibvt_lsadc *info) {
>+ /* reset the timescan */
>+ writel(ADC_CON_DEN, (info->regs + LSADC_TIMESCAN));
>+
>+ /* disable interrupt */
>+ writel(ADC_CON_DEN, (info->regs + LSADC_INTEN));
>+
>+ /* stop scan */
>+ writel(ADC_CON_EN, (info->regs + LSADC_STOP)); }
>+
>+static const struct hibvt_lsadc_data lsadc_data = {
>+ .num_bits = ADC_NUM_BITS,
>+ .channels = hibvt_lsadc_iio_channels,
>+ .num_channels = ARRAY_SIZE(hibvt_lsadc_iio_channels),
>+
>+ .clear_irq = hibvt_lsadc_clear_irq,
>+ .start_conv = hibvt_lsadc_start_conv,
>+ .stop_conv = hibvt_lsadc_stop_conv,
>+};
Usual convention is to only introduce a device type specific structure when more than one device is supported. If you are going to follow up shortly with more device support then leave it but add a note to the patch description. If not please drop this abstraction.
>+
>+static const struct of_device_id hibvt_lsadc_match[] = {
>+ {
>+ .compatible = "hisilicon,hibvt-lsadc",
>+ .data = &lsadc_data,
>+ },
>+ {},
>+};
>+MODULE_DEVICE_TABLE(of, hibvt_lsadc_match);
>+
>+/**
>+ * Reset LSADC Controller.
Single line comment syntax please.
>+ */
>+static void hibvt_lsadc_reset_controller(struct reset_control *reset)
>+{
>+ reset_control_assert(reset);
>+ usleep_range(10, 20);
>+ reset_control_deassert(reset);
>+}
>+
>+static int hibvt_lsadc_probe(struct platform_device *pdev) {
>+ struct hibvt_lsadc *info = NULL;
>+ struct device_node *np = pdev->dev.of_node;
>+ struct iio_dev *indio_dev = NULL;
>+ struct resource *mem;
>+ const struct of_device_id *match;
>+ int ret;
>+ int irq;
>+
>+ if (!np)
>+ return -ENODEV;
>+
>+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
>+ if (!indio_dev) {
>+ dev_err(&pdev->dev, "failed allocating iio device\n");
>+ return -ENOMEM;
>+ }
>+ info = iio_priv(indio_dev);
>+
>+ match = of_match_device(hibvt_lsadc_match, &pdev->dev);
>+ info->data = match->data;
>+
>+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>+ info->regs = devm_ioremap_resource(&pdev->dev, mem);
>+ if (IS_ERR(info->regs))
>+ return PTR_ERR(info->regs);
>+
>+ /*
>+ * The reset should be an optional property, as it should work
>+ * with old devicetrees as well
>+ */
>+ info->reset = devm_reset_control_get(&pdev->dev, "lsadc-crg");
>+ if (IS_ERR(info->reset)) {
>+ ret = PTR_ERR(info->reset);
>+ if (ret != -ENOENT)
>+ return ret;
>+
>+ dev_dbg(&pdev->dev, "no reset control found\n");
>+ info->reset = NULL;
>+ }
>+
>+ init_completion(&info->completion);
>+
>+ irq = platform_get_irq(pdev, 0);
>+ if (irq < 0) {
>+ dev_err(&pdev->dev, "no irq resource?\n");
>+ return irq;
>+ }
>+
>+ ret = devm_request_irq(&pdev->dev, irq, hibvt_lsadc_isr,
>+ 0, dev_name(&pdev->dev), info);
>+ if (ret < 0) {
>+ dev_err(&pdev->dev, "failed requesting irq %d\n", irq);
>+ return ret;
>+ }
>+
>+ if (info->reset)
>+ hibvt_lsadc_reset_controller(info->reset);
>+
>+ platform_set_drvdata(pdev, indio_dev);
>+
>+ indio_dev->name = dev_name(&pdev->dev);
>+ indio_dev->dev.parent = &pdev->dev;
>+ indio_dev->dev.of_node = pdev->dev.of_node;
>+ indio_dev->info = &hibvt_lsadc_iio_info;
>+ indio_dev->modes = INDIO_DIRECT_MODE;
>+
>+ indio_dev->channels = info->data->channels;
>+ indio_dev->num_channels = info->data->num_channels;
>+
>+ ret = iio_device_register(indio_dev);
>+ if (ret < 0) {
>+ dev_err(&pdev->dev, "failed register iio device\n");
>+ return ret;
>+ }
>+
>+ return 0;
>+}
>+
>+static int hibvt_lsadc_remove(struct platform_device *pdev) {
>+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>+
>+ iio_device_unregister(indio_dev);
As nothing else here can use devm version of register and drop remove entirely.
>+
>+ return 0;
>+}
>+
>+static struct platform_driver hibvt_lsadc_driver = {
>+ .probe = hibvt_lsadc_probe,
>+ .remove = hibvt_lsadc_remove,
>+ .driver = {
>+ .name = "hibvt-lsadc",
>+ .of_match_table = hibvt_lsadc_match,
>+ },
>+};
>+
>+module_platform_driver(hibvt_lsadc_driver);
>+
>+MODULE_AUTHOR("Allen Liu <liurenzhong@hisilicon.com>");
>+MODULE_DESCRIPTION("hisilicon BVT LSADC driver"); MODULE_LICENSE("GPL
>+v2");
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
^ permalink raw reply
* Re: [PATCH v3 2/4] dt-bindings: add bindings for rk3328 clock controller
From: Heiko Stuebner @ 2016-12-26 11:13 UTC (permalink / raw)
To: Elaine Zhang
Cc: mturquette, sboyd, xf, robh+dt, mark.rutland, linux-clk, huangtao,
xxx, cl, linux-rockchip, linux-kernel, devicetree,
linux-arm-kernel
In-Reply-To: <1482723930-5876-3-git-send-email-zhangqing@rock-chips.com>
Hi Elaine,
Am Montag, 26. Dezember 2016, 11:45:28 CET schrieb Elaine Zhang:
> Add devicetree bindings for Rockchip cru which found on
> Rockchip SoCs.
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
> .../bindings/clock/rockchip,rk3328-cru.txt | 57
> ++++++++++++++++++++++ 1 file changed, 57 insertions(+)
> create mode 100644
> Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt new file
> mode 100644
> index 000000000000..20053494d49f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
> @@ -0,0 +1,57 @@
> +* Rockchip RK3328 Clock and Reset Unit
> +
> +The RK3328 clock controller generates and supplies clock to various
> +controllers within the SoC and also implements a reset controller for SoC
> +peripherals.
> +
> +Required Properties:
> +
> +- compatible: should be "rockchip,rk3328-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/rk3328-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,
> + - "clkin_i2s" - external I2S clock - optional,
> + - "gmac_clkin" - external GMAC clock - optional
> + - "phy_50m_out" - output clock of the pll in the mac phy
> +
> +Example: Clock controller node:
> +
> + cru: clock-controller@ff440000 {
> + compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon";
Rob suggested dropping the "rockchip,cru" and "syscon" properties from the
example and I definitly agree with that.
Otherwise look ok to me.
Heiko
^ permalink raw reply
* Re: [PATCH v3 4/4] clk: rockchip: add new pll-type for rk3328
From: Heiko Stuebner @ 2016-12-26 11:17 UTC (permalink / raw)
To: Elaine Zhang
Cc: mturquette-rdvid1DuHRBWk0Htik3J/w, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
xf-TNX95d0MmH7DzftRWevZcw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, linux-clk-u79uwXL29TY76Z2rM5mHXA,
huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
cl-TNX95d0MmH7DzftRWevZcw,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1482723930-5876-5-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Am Montag, 26. Dezember 2016, 11:45:30 CET schrieb Elaine Zhang:
> The rk3328's pll and clock are similar with rk3036's,
> it different with pll_mode_mask, the rk3328 soc
> pll mode only one bit(rk3036 soc have two bits)
> so these should be independent and separate from
> the series of rk3328s.
>
> Changes in v3:
> fix up the pll type pll_rk3328 description and use
>
> Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
pll-specific code looks good now, but please make this patch before the clock
controller in the series and move the
@@ -130,6 +152,7 @@
enum rockchip_pll_type {
pll_rk3036,
pll_rk3066,
+ pll_rk3328,
pll_rk3399,
};
from patch3 into this one.
Thanks
Heiko
PS: I will have some comments for the clock controller patch, but it's xmas,
so that may take bit still.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH 4/6] PCI: exynos5433: Add new exynos pci host controller for Exynos5433
From: Joao Pinto @ 2016-12-26 11:49 UTC (permalink / raw)
To: Jaehoon Chung, linux-pci-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, kgene-DgEjT+Ai2ygdnm+yROfE0A,
krzk-DgEjT+Ai2ygdnm+yROfE0A, javier-JPH+aEBZ4P+UEJcrhfAQsw,
kishon-l0cyMroinI0, will.deacon-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8, cpgs-Sze3O3UU22JBDgjK7y7TUQ
In-Reply-To: <20161226052029.10552-5-jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Hello Jaehoon,
Às 5:20 AM de 12/26/2016, Jaehoon Chung escreveu:
> Exynos5433 supports the PCIe.
> This patch adds new pci-exynos5433.c file for Exynos ARM64.
>
> Signed-off-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
> drivers/pci/host/Kconfig | 9 +
> drivers/pci/host/Makefile | 1 +
> drivers/pci/host/pci-exynos5433.c | 338 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 348 insertions(+)
> create mode 100644 drivers/pci/host/pci-exynos5433.c
>
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index d7e7c0a..3d77d0b 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -60,6 +60,15 @@ config PCI_EXYNOS
> select PCIEPORTBUS
> select PCIE_DW
>
> +config PCI_EXYNOS5433
> + bool "Samsung Exynos5433 PCIe controller"
> + depends on ARCH_EXYNOS && ARM64
> + depends on PCI_MSI_IRQ_DOMAIN
> + select PCIEPORTBUS
> + select PCIE_DW
> + help
> + If you want support for Exynos5433 PCIe host controller, say Y.
> +
> config PCI_IMX6
> bool "Freescale i.MX6 PCIe controller"
> depends on SOC_IMX6Q
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 084cb49..2168de2 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -2,6 +2,7 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o
> obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
> obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
> obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
> +obj-$(CONFIG_PCI_EXYNOS5433) += pci-exynos5433.o
> obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
> obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
> obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> diff --git a/drivers/pci/host/pci-exynos5433.c b/drivers/pci/host/pci-exynos5433.c
> new file mode 100644
> index 0000000..ff254ca
> --- /dev/null
> +++ b/drivers/pci/host/pci-exynos5433.c
> @@ -0,0 +1,338 @@
> +/*
> + * PCIe host controller driver for Samsung EXYNOS5433 SoCs
> + *
> + * Copyright (C) 2016 Samsung Electronics Co., Ltd.
> + * https://urldefense.proofpoint.com/v2/url?u=http-3A__www.samsung.com&d=DgIBAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=s2fO0hii0OGNOv9qQy_HRXy-xAJUD1NNoEcc3io_kx0&m=fUwnZks1U2AwaOxMkLdSnE700sfQXpB3WAg_EJw7NaE&s=IwRYD8maTuXG57Q0qlAmFNh3_TSfUTE27xq8p13FFKI&e=
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/gpio.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_gpio.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/resource.h>
> +#include <linux/signal.h>
> +#include <linux/types.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/phy/phy.h>
> +
> +#include "pcie-designware.h"
> +
> +#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp)
> +
> +/* Pcie structure for Exynos specific data */
> +struct exynos_pcie {
> + void __iomem *elbi_base;
> + struct clk *clk;
> + struct clk *bus_clk;
> + struct pcie_port pp;
> + struct phy *phy;
> +};
> +
> +/* PCIe ELBI registers */
> +#define PCIE_IRQ_PULSE 0x000
> +#define IRQ_INTA_ASSERT BIT(0)
> +#define IRQ_INTB_ASSERT BIT(2)
> +#define IRQ_INTC_ASSERT BIT(4)
> +#define IRQ_INTD_ASSERT BIT(6)
> +#define IRQ_INTX_ASSERT (IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | \
> + IRQ_INTC_ASSERT | IRQ_INTD_ASSERT)
> +#define PCIE_IRQ_EN_PULSE 0x00c
> +#define PCIE_IRQ_EN_LEVEL 0x010
> +#define PCIE_SW_WAKE 0x018
> +#define PCIE_BUS_EN BIT(1)
> +#define PCIE_APP_LTSSM_ENABLE 0x02c
> +#define PCIE_ELBI_LTSSM_ENABLE 0x1
> +#define PCIE_ELBI_DEBUG_L 0x074
> +#define PCIE_ELBI_XMLH_LINK_UP BIT(4)
> +#define PCIE_ELBI_SLV_AWMISC 0x11c
> +#define PCIE_ELBI_SLV_ARMISC 0x120
> +#define PCIE_ELBI_SLV_DBI_ENABLE BIT(21)
> +
> +/* DBI register */
> +#define PCIE_MISC_CONTROL_1_OFF 0x8BC
> +#define DBI_RO_WR_EN BIT(0)
> +
> +static inline void exynos_pcie_writel(void __iomem *base, u32 val, u32 offset)
> +{
> + writel(val, base + offset);
> +}
> +
> +static inline u32 exynos_pcie_readl(void __iomem *base, u32 offset)
> +{
> + return readl(base + offset);
> +}
> +
> +static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)
> +{
> + u32 val;
> +
> + val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE);
> + val &= ~IRQ_INTX_ASSERT;
> + exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE);
> +}
> +
> +static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
> +{
> + exynos_pcie_writel(ep->elbi_base, IRQ_INTX_ASSERT, PCIE_IRQ_EN_PULSE);
> +
> + /* Clear PCIE_IRQ_EN_LEVEL register */
> + exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_LEVEL);
> +}
> +
> +static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
> +{
> + struct pcie_port *pp = arg;
> + struct exynos_pcie *ep = to_exynos_pcie(pp);
> +
> + exynos_pcie_clear_irq_pulse(ep);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
> +{
> + u32 val;
> +
> + val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC);
> + if (on)
> + val |= PCIE_ELBI_SLV_DBI_ENABLE;
> + else
> + val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
> + exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
> +}
> +
> +static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)
> +{
> + u32 val;
> +
> + val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC);
> + if (on)
> + val |= PCIE_ELBI_SLV_DBI_ENABLE;
> + else
> + val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
> + exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
> +}
> +
> +static int exynos_pcie_establish_link(struct exynos_pcie *ep)
> +{
> + struct pcie_port *pp = &ep->pp;
> + u32 val;
> +
> + if (dw_pcie_link_up(pp)) {
> + dev_info(pp->dev, "Link already up\n");
> + return 0;
> + }
> +
> + phy_power_on(ep->phy);
> +
> + /* Exynos Pcie assert PHY reset and init */
> + phy_init(ep->phy);
> +
> + val = exynos_pcie_readl(ep->elbi_base, PCIE_SW_WAKE);
> + val &= ~PCIE_BUS_EN;
> + exynos_pcie_writel(ep->elbi_base, val, PCIE_SW_WAKE);
> +
> + /*
> + * Enable DBI_RO_WR_EN bit.
> + * - When set to 1, some RO and HWinit bits are wriatble from
> + * the local application through the DBI.
> + */
> + dw_pcie_writel_rc(pp, PCIE_MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
> +
> + /* Setup root complex */
> + dw_pcie_setup_rc(pp);
> +
> + /* assert LTSSM enable */
> + exynos_pcie_writel(ep->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
> + PCIE_APP_LTSSM_ENABLE);
> +
> + return dw_pcie_wait_for_link(pp);
> +}
> +
> +
> +static int exynos_pcie_link_up(struct pcie_port *pp)
> +{
> + struct exynos_pcie *ep = to_exynos_pcie(pp);
> + u32 val;
> +
> + /* Check the Receive Transaction Layer Handler */
> + val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_DEBUG_L);
> +
> + return (val & PCIE_ELBI_XMLH_LINK_UP);
> +}
> +
> +static void exynos_pcie_host_init(struct pcie_port *pp)
> +{
> + struct exynos_pcie *ep = to_exynos_pcie(pp);
> +
> + exynos_pcie_enable_irq_pulse(ep);
> + exynos_pcie_establish_link(ep);
> +}
Your *_host_init callback should return to pci-designware its error/success
status. There is a recent patch that added this capability to all vendor
specific drivers that use pcie-designware. Please check it out and follow the
same approach:
https://patchwork.kernel.org/patch/9464223/
Thanks,
Joao
> +
> +static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
> +{
> + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
> + u32 val;
> +
> + exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
> + val = readl(pp->dbi_base + reg);
> + exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
> + return val;
> +}
> +
> +static void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
> +{
> + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
> +
> + exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
> + writel(val, pp->dbi_base + reg);
> + exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
> +}
> +
> +static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
> + u32 *val)
> +{
> + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
> + int ret;
> +
> + exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
> + ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
> + exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
> + return ret;
> +}
> +
> +static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
> + u32 val)
> +{
> + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
> + int ret;
> +
> + exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
> + ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
> + exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
> + return ret;
> +}
> +
> +static struct pcie_host_ops exynos_pcie_host_ops = {
> + .readl_rc = exynos_pcie_readl_rc,
> + .writel_rc = exynos_pcie_writel_rc,
> + .rd_own_conf = exynos_pcie_rd_own_conf,
> + .wr_own_conf = exynos_pcie_wr_own_conf,
> + .host_init = exynos_pcie_host_init,
> + .link_up = exynos_pcie_link_up,
> +};
> +
> +static int __init exynos_pcie_probe(struct platform_device *pdev)
> +{
> + struct exynos_pcie *exynos_pcie;
> + struct pcie_port *pp;
> + struct resource *res;
> + int ret;
> +
> + exynos_pcie = devm_kzalloc(&pdev->dev, sizeof(*exynos_pcie),
> + GFP_KERNEL);
> + if (!exynos_pcie)
> + return -ENOMEM;
> +
> + pp = &exynos_pcie->pp;
> + pp->dev = &pdev->dev;
> +
> + exynos_pcie->clk = devm_clk_get(&pdev->dev, "pcie");
> + if (IS_ERR(exynos_pcie->clk)) {
> + dev_err(&pdev->dev, "Failed to get pcie rc clock\n");
> + return PTR_ERR(exynos_pcie->clk);
> + }
> + ret = clk_prepare_enable(exynos_pcie->clk);
> + if (ret)
> + return ret;
> +
> + exynos_pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus");
> + if (IS_ERR(exynos_pcie->bus_clk)) {
> + dev_err(&pdev->dev, "Failed to get pcie bus clock\n");
> + ret = PTR_ERR(exynos_pcie->bus_clk);
> + goto fail_clk;
> + }
> + ret = clk_prepare_enable(exynos_pcie->bus_clk);
> + if (ret)
> + goto fail_clk;
> +
> + /* External Local Bus interface(ELBI) Register */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
> + exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(exynos_pcie->elbi_base)) {
> + ret = PTR_ERR(exynos_pcie->elbi_base);
> + goto fail_bus_clk;
> + }
> +
> + /* Data Bus Interface(DBI) Register */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
> + pp->dbi_base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(pp->dbi_base)) {
> + ret = PTR_ERR(pp->dbi_base);
> + goto fail_bus_clk;
> + }
> +
> + exynos_pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy");
> + if (IS_ERR(exynos_pcie->phy)) {
> + if (PTR_ERR(exynos_pcie->phy) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "Can't find the pcie-phy\n");
> + return PTR_ERR(exynos_pcie->phy);
> + }
> +
> + pp->irq = platform_get_irq_byname(pdev, "intr");
> + if (!pp->irq) {
> + dev_err(&pdev->dev, "failed to get irq\n");
> + ret = -ENODEV;
> + goto fail_bus_clk;
> + }
> + ret = devm_request_irq(&pdev->dev, pp->irq, exynos_pcie_irq_handler,
> + IRQF_SHARED, "exynos-pcie", exynos_pcie);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to request irq\n");
> + goto fail_bus_clk;
> + }
> +
> + pp->root_bus_nr = -1;
> + pp->ops = &exynos_pcie_host_ops;
> +
> + ret = dw_pcie_host_init(pp);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to initialize host\n");
> + goto fail_bus_clk;
> + }
> +
> + platform_set_drvdata(pdev, exynos_pcie);
> +
> + return 0;
> +
> +fail_bus_clk:
> + clk_disable_unprepare(exynos_pcie->bus_clk);
> +fail_clk:
> + clk_disable_unprepare(exynos_pcie->clk);
> + return ret;
> +}
> +
> +static const struct of_device_id exynos_pcie_of_match[] = {
> + { .compatible = "samsung,exynos5433-pcie", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, exynos_pcie_of_match);
> +
> +static struct platform_driver exynos_pcie_driver = {
> + .probe = exynos_pcie_probe,
> + .driver = {
> + .name = "exynos5433-pcie",
> + .of_match_table = exynos_pcie_of_match,
> + },
> +};
> +builtin_platform_driver(exynos_pcie_driver);
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2] power: reset: add linkstation-reset driver
From: Roger Shimizu @ 2016-12-26 16:13 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Andrew Lunn, Rob Herring, linux-pm, Ryan Tandy, Martin Michlmayr,
Sylver Bruneau, Herbert Valerio Riedel, Mark Rutland, devicetree
In-Reply-To: <20161222144924.gidgzk2ujpvlti3t@earth>
Dear Sebastian,
Thanks for your feedback!
On Thu, Dec 22, 2016 at 11:49 PM, Sebastian Reichel <sre@kernel.org> wrote:
>
> I'm talking about the special case, where it also sends only a
> single byte:
>
>> + /* send the power-off command to PIC */
>> + if(cfg->cmd[0][0] == 1 && cfg->cmd[1][0] == 0) {
>> + /* if it's simply one-byte command, send it directly */
>> + writel(cfg->cmd[0][1], UART1_REG(TX));
>> + }
>
> The configuration is different, but
>
> a) probably it can just use the config from the qnap driver, since
> it just sends a single byte.
> b) making the 4 config registers configurable in the qnap driver does
> not add much complexity.
>
> So this case should be removed from the linkstation-reset driver. If
> any board needs it, it should use the qnap-poweroff driver instead.
Yes, if other board need sending one-byte command to UART1, it should
make use of qnap-poweroff driver.
However, one model of Linkstation need such kind of command, I would
like to add it in linkstation-reset driver.
Currently, there's no such usage, so if you don't like the redundant
code which sending one-byte command, I can remove in my next patch
series.
Merry Xmas and happy new year!
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ 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