1 // SPDX-License-Identifier: GPL-2.0
3 * camss-csiphy-2ph-1-0.c
5 * Qualcomm MSM Camera Subsystem - CSIPHY Module 2phase v1.0
7 * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
8 * Copyright (C) 2016-2018 Linaro Ltd.
11 #include "camss-csiphy.h"
13 #include <linux/delay.h>
14 #include <linux/interrupt.h>
17 #define CAMSS_CSI_PHY_LNn_CFG2(n) (0x004 + 0x40 * (n))
18 #define CAMSS_CSI_PHY_LNn_CFG3(n) (0x008 + 0x40 * (n))
19 #define CAMSS_CSI_PHY_LN_CLK 1
20 #define CAMSS_CSI_PHY_GLBL_RESET 0x140
21 #define CAMSS_CSI_PHY_GLBL_PWR_CFG 0x144
22 #define CAMSS_CSI_PHY_GLBL_IRQ_CMD 0x164
23 #define CAMSS_CSI_PHY_HW_VERSION 0x188
24 #define CAMSS_CSI_PHY_INTERRUPT_STATUSn(n) (0x18c + 0x4 * (n))
25 #define CAMSS_CSI_PHY_INTERRUPT_MASKn(n) (0x1ac + 0x4 * (n))
26 #define CAMSS_CSI_PHY_INTERRUPT_CLEARn(n) (0x1cc + 0x4 * (n))
27 #define CAMSS_CSI_PHY_GLBL_T_INIT_CFG0 0x1ec
28 #define CAMSS_CSI_PHY_T_WAKEUP_CFG0 0x1f4
30 static u8
csiphy_get_lane_mask(struct csiphy_lanes_cfg
*lane_cfg
)
35 lane_mask
= 1 << CAMSS_CSI_PHY_LN_CLK
;
37 for (i
= 0; i
< lane_cfg
->num_data
; i
++)
38 lane_mask
|= 1 << lane_cfg
->data
[i
].pos
;
43 static void csiphy_hw_version_read(struct csiphy_device
*csiphy
,
46 u8 hw_version
= readl_relaxed(csiphy
->base
+
47 CAMSS_CSI_PHY_HW_VERSION
);
49 dev_dbg(dev
, "CSIPHY HW Version = 0x%02x\n", hw_version
);
53 * csiphy_reset - Perform software reset on CSIPHY module
54 * @csiphy: CSIPHY device
56 static void csiphy_reset(struct csiphy_device
*csiphy
)
58 writel_relaxed(0x1, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_RESET
);
59 usleep_range(5000, 8000);
60 writel_relaxed(0x0, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_RESET
);
64 * csiphy_settle_cnt_calc - Calculate settle count value
66 * Helper function to calculate settle count value. This is
67 * based on the CSI2 T_hs_settle parameter which in turn
68 * is calculated based on the CSI2 transmitter link frequency.
70 * Return settle count value or 0 if the CSI2 link frequency
73 static u8
csiphy_settle_cnt_calc(s64 link_freq
, u32 timer_clk_rate
)
76 u32 timer_period
; /* ps */
77 u32 t_hs_prepare_max
; /* ps */
78 u32 t_hs_prepare_zero_min
; /* ps */
79 u32 t_hs_settle
; /* ps */
85 ui
= div_u64(1000000000000LL, link_freq
);
87 t_hs_prepare_max
= 85000 + 6 * ui
;
88 t_hs_prepare_zero_min
= 145000 + 10 * ui
;
89 t_hs_settle
= (t_hs_prepare_max
+ t_hs_prepare_zero_min
) / 2;
91 timer_period
= div_u64(1000000000000LL, timer_clk_rate
);
92 settle_cnt
= t_hs_settle
/ timer_period
- 1;
97 static void csiphy_lanes_enable(struct csiphy_device
*csiphy
,
98 struct csiphy_config
*cfg
,
99 s64 link_freq
, u8 lane_mask
)
101 struct csiphy_lanes_cfg
*c
= &cfg
->csi2
->lane_cfg
;
106 settle_cnt
= csiphy_settle_cnt_calc(link_freq
, csiphy
->timer_clk_rate
);
108 writel_relaxed(0x1, csiphy
->base
+
109 CAMSS_CSI_PHY_GLBL_T_INIT_CFG0
);
110 writel_relaxed(0x1, csiphy
->base
+
111 CAMSS_CSI_PHY_T_WAKEUP_CFG0
);
114 val
|= lane_mask
<< 1;
115 writel_relaxed(val
, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_PWR_CFG
);
117 val
= cfg
->combo_mode
<< 4;
118 writel_relaxed(val
, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_RESET
);
120 for (i
= 0; i
<= c
->num_data
; i
++) {
121 if (i
== c
->num_data
)
122 l
= CAMSS_CSI_PHY_LN_CLK
;
126 writel_relaxed(0x10, csiphy
->base
+
127 CAMSS_CSI_PHY_LNn_CFG2(l
));
128 writel_relaxed(settle_cnt
, csiphy
->base
+
129 CAMSS_CSI_PHY_LNn_CFG3(l
));
130 writel_relaxed(0x3f, csiphy
->base
+
131 CAMSS_CSI_PHY_INTERRUPT_MASKn(l
));
132 writel_relaxed(0x3f, csiphy
->base
+
133 CAMSS_CSI_PHY_INTERRUPT_CLEARn(l
));
137 static void csiphy_lanes_disable(struct csiphy_device
*csiphy
,
138 struct csiphy_config
*cfg
)
140 struct csiphy_lanes_cfg
*c
= &cfg
->csi2
->lane_cfg
;
144 for (i
= 0; i
<= c
->num_data
; i
++) {
145 if (i
== c
->num_data
)
146 l
= CAMSS_CSI_PHY_LN_CLK
;
150 writel_relaxed(0x0, csiphy
->base
+
151 CAMSS_CSI_PHY_LNn_CFG2(l
));
154 writel_relaxed(0x0, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_PWR_CFG
);
158 * csiphy_isr - CSIPHY module interrupt handler
159 * @irq: Interrupt line
160 * @dev: CSIPHY device
162 * Return IRQ_HANDLED on success
164 static irqreturn_t
csiphy_isr(int irq
, void *dev
)
166 struct csiphy_device
*csiphy
= dev
;
169 for (i
= 0; i
< 8; i
++) {
170 u8 val
= readl_relaxed(csiphy
->base
+
171 CAMSS_CSI_PHY_INTERRUPT_STATUSn(i
));
172 writel_relaxed(val
, csiphy
->base
+
173 CAMSS_CSI_PHY_INTERRUPT_CLEARn(i
));
174 writel_relaxed(0x1, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_IRQ_CMD
);
175 writel_relaxed(0x0, csiphy
->base
+ CAMSS_CSI_PHY_GLBL_IRQ_CMD
);
176 writel_relaxed(0x0, csiphy
->base
+
177 CAMSS_CSI_PHY_INTERRUPT_CLEARn(i
));
183 const struct csiphy_hw_ops csiphy_ops_2ph_1_0
= {
184 .get_lane_mask
= csiphy_get_lane_mask
,
185 .hw_version_read
= csiphy_hw_version_read
,
186 .reset
= csiphy_reset
,
187 .lanes_enable
= csiphy_lanes_enable
,
188 .lanes_disable
= csiphy_lanes_disable
,