treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
[sfrench/cifs-2.6.git] / drivers / media / platform / omap3isp / ispcsiphy.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ispcsiphy.c
4  *
5  * TI OMAP3 ISP - CSI PHY module
6  *
7  * Copyright (C) 2010 Nokia Corporation
8  * Copyright (C) 2009 Texas Instruments, Inc.
9  *
10  * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11  *           Sakari Ailus <sakari.ailus@iki.fi>
12  */
13
14 #include <linux/delay.h>
15 #include <linux/device.h>
16 #include <linux/regmap.h>
17 #include <linux/regulator/consumer.h>
18
19 #include "isp.h"
20 #include "ispreg.h"
21 #include "ispcsiphy.h"
22
23 static void csiphy_routing_cfg_3630(struct isp_csiphy *phy,
24                                     enum isp_interface_type iface,
25                                     bool ccp2_strobe)
26 {
27         u32 reg;
28         u32 shift, mode;
29
30         regmap_read(phy->isp->syscon, phy->isp->syscon_offset, &reg);
31
32         switch (iface) {
33         default:
34         /* Should not happen in practice, but let's keep the compiler happy. */
35         case ISP_INTERFACE_CCP2B_PHY1:
36                 reg &= ~OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2;
37                 shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT;
38                 break;
39         case ISP_INTERFACE_CSI2C_PHY1:
40                 shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY1_SHIFT;
41                 mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY;
42                 break;
43         case ISP_INTERFACE_CCP2B_PHY2:
44                 reg |= OMAP3630_CONTROL_CAMERA_PHY_CTRL_CSI1_RX_SEL_PHY2;
45                 shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT;
46                 break;
47         case ISP_INTERFACE_CSI2A_PHY2:
48                 shift = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_PHY2_SHIFT;
49                 mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_DPHY;
50                 break;
51         }
52
53         /* Select data/clock or data/strobe mode for CCP2 */
54         if (iface == ISP_INTERFACE_CCP2B_PHY1 ||
55             iface == ISP_INTERFACE_CCP2B_PHY2) {
56                 if (ccp2_strobe)
57                         mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_STROBE;
58                 else
59                         mode = OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_CCP2_DATA_CLOCK;
60         }
61
62         reg &= ~(OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK << shift);
63         reg |= mode << shift;
64
65         regmap_write(phy->isp->syscon, phy->isp->syscon_offset, reg);
66 }
67
68 static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on,
69                                     bool ccp2_strobe)
70 {
71         u32 csirxfe = OMAP343X_CONTROL_CSIRXFE_PWRDNZ
72                 | OMAP343X_CONTROL_CSIRXFE_RESET;
73
74         /* Only the CCP2B on PHY1 is configurable. */
75         if (iface != ISP_INTERFACE_CCP2B_PHY1)
76                 return;
77
78         if (!on) {
79                 regmap_write(phy->isp->syscon, phy->isp->syscon_offset, 0);
80                 return;
81         }
82
83         if (ccp2_strobe)
84                 csirxfe |= OMAP343X_CONTROL_CSIRXFE_SELFORM;
85
86         regmap_write(phy->isp->syscon, phy->isp->syscon_offset, csirxfe);
87 }
88
89 /*
90  * Configure OMAP 3 CSI PHY routing.
91  * @phy: relevant phy device
92  * @iface: ISP_INTERFACE_*
93  * @on: power on or off
94  * @ccp2_strobe: false: data/clock, true: data/strobe
95  *
96  * Note that the underlying routing configuration registers are part of the
97  * control (SCM) register space and part of the CORE power domain on both 3430
98  * and 3630, so they will not hold their contents in off-mode. This isn't an
99  * issue since the MPU power domain is forced on whilst the ISP is in use.
100  */
101 static void csiphy_routing_cfg(struct isp_csiphy *phy,
102                                enum isp_interface_type iface, bool on,
103                                bool ccp2_strobe)
104 {
105         if (phy->isp->phy_type == ISP_PHY_TYPE_3630 && on)
106                 return csiphy_routing_cfg_3630(phy, iface, ccp2_strobe);
107         if (phy->isp->phy_type == ISP_PHY_TYPE_3430)
108                 return csiphy_routing_cfg_3430(phy, iface, on, ccp2_strobe);
109 }
110
111 /*
112  * csiphy_power_autoswitch_enable
113  * @enable: Sets or clears the autoswitch function enable flag.
114  */
115 static void csiphy_power_autoswitch_enable(struct isp_csiphy *phy, bool enable)
116 {
117         isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
118                         ISPCSI2_PHY_CFG_PWR_AUTO,
119                         enable ? ISPCSI2_PHY_CFG_PWR_AUTO : 0);
120 }
121
122 /*
123  * csiphy_set_power
124  * @power: Power state to be set.
125  *
126  * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
127  */
128 static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
129 {
130         u32 reg;
131         u8 retry_count;
132
133         isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
134                         ISPCSI2_PHY_CFG_PWR_CMD_MASK, power);
135
136         retry_count = 0;
137         do {
138                 udelay(50);
139                 reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG) &
140                                     ISPCSI2_PHY_CFG_PWR_STATUS_MASK;
141
142                 if (reg != power >> 2)
143                         retry_count++;
144
145         } while ((reg != power >> 2) && (retry_count < 100));
146
147         if (retry_count == 100) {
148                 dev_err(phy->isp->dev, "CSI2 CIO set power failed!\n");
149                 return -EBUSY;
150         }
151
152         return 0;
153 }
154
155 /*
156  * TCLK values are OK at their reset values
157  */
158 #define TCLK_TERM       0
159 #define TCLK_MISS       1
160 #define TCLK_SETTLE     14
161
162 static int omap3isp_csiphy_config(struct isp_csiphy *phy)
163 {
164         struct isp_pipeline *pipe = to_isp_pipeline(phy->entity);
165         struct isp_bus_cfg *buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
166         struct isp_csiphy_lanes_cfg *lanes;
167         int csi2_ddrclk_khz;
168         unsigned int num_data_lanes, used_lanes = 0;
169         unsigned int i;
170         u32 reg;
171
172         if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1
173             || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2) {
174                 lanes = &buscfg->bus.ccp2.lanecfg;
175                 num_data_lanes = 1;
176         } else {
177                 lanes = &buscfg->bus.csi2.lanecfg;
178                 num_data_lanes = buscfg->bus.csi2.num_data_lanes;
179         }
180
181         if (num_data_lanes > phy->num_data_lanes)
182                 return -EINVAL;
183
184         /* Clock and data lanes verification */
185         for (i = 0; i < num_data_lanes; i++) {
186                 if (lanes->data[i].pol > 1 || lanes->data[i].pos > 3)
187                         return -EINVAL;
188
189                 if (used_lanes & (1 << lanes->data[i].pos))
190                         return -EINVAL;
191
192                 used_lanes |= 1 << lanes->data[i].pos;
193         }
194
195         if (lanes->clk.pol > 1 || lanes->clk.pos > 3)
196                 return -EINVAL;
197
198         if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
199                 return -EINVAL;
200
201         /*
202          * The PHY configuration is lost in off mode, that's not an
203          * issue since the MPU power domain is forced on whilst the
204          * ISP is in use.
205          */
206         csiphy_routing_cfg(phy, buscfg->interface, true,
207                            buscfg->bus.ccp2.phy_layer);
208
209         /* DPHY timing configuration */
210         /* CSI-2 is DDR and we only count used lanes. */
211         csi2_ddrclk_khz = pipe->external_rate / 1000
212                 / (2 * hweight32(used_lanes)) * pipe->external_width;
213
214         reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG0);
215
216         reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
217                  ISPCSIPHY_REG0_THS_SETTLE_MASK);
218         /* THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1. */
219         reg |= (DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1)
220                 << ISPCSIPHY_REG0_THS_TERM_SHIFT;
221         /* THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3. */
222         reg |= (DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3)
223                 << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
224
225         isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
226
227         reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG1);
228
229         reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
230                  ISPCSIPHY_REG1_TCLK_MISS_MASK |
231                  ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
232         reg |= TCLK_TERM << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
233         reg |= TCLK_MISS << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
234         reg |= TCLK_SETTLE << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
235
236         isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
237
238         /* DPHY lane configuration */
239         reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
240
241         for (i = 0; i < num_data_lanes; i++) {
242                 reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
243                          ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
244                 reg |= (lanes->data[i].pol <<
245                         ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
246                 reg |= (lanes->data[i].pos <<
247                         ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
248         }
249
250         reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
251                  ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
252         reg |= lanes->clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
253         reg |= lanes->clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
254
255         isp_reg_writel(phy->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
256
257         return 0;
258 }
259
260 int omap3isp_csiphy_acquire(struct isp_csiphy *phy, struct media_entity *entity)
261 {
262         int rval;
263
264         if (phy->vdd == NULL) {
265                 dev_err(phy->isp->dev,
266                         "Power regulator for CSI PHY not available\n");
267                 return -ENODEV;
268         }
269
270         mutex_lock(&phy->mutex);
271
272         rval = regulator_enable(phy->vdd);
273         if (rval < 0)
274                 goto done;
275
276         rval = omap3isp_csi2_reset(phy->csi2);
277         if (rval < 0)
278                 goto done;
279
280         phy->entity = entity;
281
282         rval = omap3isp_csiphy_config(phy);
283         if (rval < 0)
284                 goto done;
285
286         if (phy->isp->revision == ISP_REVISION_15_0) {
287                 rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
288                 if (rval) {
289                         regulator_disable(phy->vdd);
290                         goto done;
291                 }
292
293                 csiphy_power_autoswitch_enable(phy, true);
294         }
295 done:
296         if (rval < 0)
297                 phy->entity = NULL;
298
299         mutex_unlock(&phy->mutex);
300         return rval;
301 }
302
303 void omap3isp_csiphy_release(struct isp_csiphy *phy)
304 {
305         mutex_lock(&phy->mutex);
306         if (phy->entity) {
307                 struct isp_pipeline *pipe = to_isp_pipeline(phy->entity);
308                 struct isp_bus_cfg *buscfg =
309                         v4l2_subdev_to_bus_cfg(pipe->external);
310
311                 csiphy_routing_cfg(phy, buscfg->interface, false,
312                                    buscfg->bus.ccp2.phy_layer);
313                 if (phy->isp->revision == ISP_REVISION_15_0) {
314                         csiphy_power_autoswitch_enable(phy, false);
315                         csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
316                 }
317                 regulator_disable(phy->vdd);
318                 phy->entity = NULL;
319         }
320         mutex_unlock(&phy->mutex);
321 }
322
323 /*
324  * omap3isp_csiphy_init - Initialize the CSI PHY frontends
325  */
326 int omap3isp_csiphy_init(struct isp_device *isp)
327 {
328         struct isp_csiphy *phy1 = &isp->isp_csiphy1;
329         struct isp_csiphy *phy2 = &isp->isp_csiphy2;
330
331         phy2->isp = isp;
332         phy2->csi2 = &isp->isp_csi2a;
333         phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;
334         phy2->cfg_regs = OMAP3_ISP_IOMEM_CSI2A_REGS1;
335         phy2->phy_regs = OMAP3_ISP_IOMEM_CSIPHY2;
336         mutex_init(&phy2->mutex);
337
338         phy1->isp = isp;
339         mutex_init(&phy1->mutex);
340
341         if (isp->revision == ISP_REVISION_15_0) {
342                 phy1->csi2 = &isp->isp_csi2c;
343                 phy1->num_data_lanes = ISP_CSIPHY1_NUM_DATA_LANES;
344                 phy1->cfg_regs = OMAP3_ISP_IOMEM_CSI2C_REGS1;
345                 phy1->phy_regs = OMAP3_ISP_IOMEM_CSIPHY1;
346         }
347
348         return 0;
349 }
350
351 void omap3isp_csiphy_cleanup(struct isp_device *isp)
352 {
353         mutex_destroy(&isp->isp_csiphy1.mutex);
354         mutex_destroy(&isp->isp_csiphy2.mutex);
355 }