518b98dd3087d15d36c75f695f0189e3be255ed6
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / gpu / host1x / mipi.c
1 /*
2  * Copyright (C) 2013 NVIDIA Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <linux/clk.h>
24 #include <linux/delay.h>
25 #include <linux/io.h>
26 #include <linux/of_platform.h>
27 #include <linux/platform_device.h>
28 #include <linux/slab.h>
29
30 #define MIPI_CAL_CTRL                   0x00
31 #define MIPI_CAL_CTRL_START             (1 << 0)
32
33 #define MIPI_CAL_AUTOCAL_CTRL           0x01
34
35 #define MIPI_CAL_STATUS                 0x02
36 #define MIPI_CAL_STATUS_DONE            (1 << 16)
37 #define MIPI_CAL_STATUS_ACTIVE          (1 <<  0)
38
39 #define MIPI_CAL_CONFIG_CSIA            0x05
40 #define MIPI_CAL_CONFIG_CSIB            0x06
41 #define MIPI_CAL_CONFIG_CSIC            0x07
42 #define MIPI_CAL_CONFIG_CSID            0x08
43 #define MIPI_CAL_CONFIG_CSIE            0x09
44 #define MIPI_CAL_CONFIG_DSIA            0x0e
45 #define MIPI_CAL_CONFIG_DSIB            0x0f
46 #define MIPI_CAL_CONFIG_DSIC            0x10
47 #define MIPI_CAL_CONFIG_DSID            0x11
48
49 #define MIPI_CAL_CONFIG_SELECT          (1 << 21)
50 #define MIPI_CAL_CONFIG_HSPDOS(x)       (((x) & 0x1f) << 16)
51 #define MIPI_CAL_CONFIG_HSPUOS(x)       (((x) & 0x1f) <<  8)
52 #define MIPI_CAL_CONFIG_TERMOS(x)       (((x) & 0x1f) <<  0)
53
54 #define MIPI_CAL_BIAS_PAD_CFG0          0x16
55 #define MIPI_CAL_BIAS_PAD_PDVCLAMP      (1 << 1)
56 #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF  (1 << 0)
57
58 #define MIPI_CAL_BIAS_PAD_CFG1          0x17
59
60 #define MIPI_CAL_BIAS_PAD_CFG2          0x18
61 #define MIPI_CAL_BIAS_PAD_PDVREG        (1 << 1)
62
63 static const struct module {
64         unsigned long reg;
65 } modules[] = {
66         { .reg = MIPI_CAL_CONFIG_CSIA },
67         { .reg = MIPI_CAL_CONFIG_CSIB },
68         { .reg = MIPI_CAL_CONFIG_CSIC },
69         { .reg = MIPI_CAL_CONFIG_CSID },
70         { .reg = MIPI_CAL_CONFIG_CSIE },
71         { .reg = MIPI_CAL_CONFIG_DSIA },
72         { .reg = MIPI_CAL_CONFIG_DSIB },
73         { .reg = MIPI_CAL_CONFIG_DSIC },
74         { .reg = MIPI_CAL_CONFIG_DSID },
75 };
76
77 struct tegra_mipi {
78         void __iomem *regs;
79         struct mutex lock;
80         struct clk *clk;
81 };
82
83 struct tegra_mipi_device {
84         struct platform_device *pdev;
85         struct tegra_mipi *mipi;
86         struct device *device;
87         unsigned long pads;
88 };
89
90 static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi,
91                                              unsigned long reg)
92 {
93         return readl(mipi->regs + (reg << 2));
94 }
95
96 static inline void tegra_mipi_writel(struct tegra_mipi *mipi,
97                                      unsigned long value, unsigned long reg)
98 {
99         writel(value, mipi->regs + (reg << 2));
100 }
101
102 struct tegra_mipi_device *tegra_mipi_request(struct device *device)
103 {
104         struct device_node *np = device->of_node;
105         struct tegra_mipi_device *dev;
106         struct of_phandle_args args;
107         int err;
108
109         err = of_parse_phandle_with_args(np, "nvidia,mipi-calibrate",
110                                          "#nvidia,mipi-calibrate-cells", 0,
111                                          &args);
112         if (err < 0)
113                 return ERR_PTR(err);
114
115         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
116         if (!dev) {
117                 of_node_put(args.np);
118                 err = -ENOMEM;
119                 goto out;
120         }
121
122         dev->pdev = of_find_device_by_node(args.np);
123         if (!dev->pdev) {
124                 of_node_put(args.np);
125                 err = -ENODEV;
126                 goto free;
127         }
128
129         of_node_put(args.np);
130
131         dev->mipi = platform_get_drvdata(dev->pdev);
132         if (!dev->mipi) {
133                 err = -EPROBE_DEFER;
134                 goto pdev_put;
135         }
136
137         dev->pads = args.args[0];
138         dev->device = device;
139
140         return dev;
141
142 pdev_put:
143         platform_device_put(dev->pdev);
144 free:
145         kfree(dev);
146 out:
147         return ERR_PTR(err);
148 }
149 EXPORT_SYMBOL(tegra_mipi_request);
150
151 void tegra_mipi_free(struct tegra_mipi_device *device)
152 {
153         platform_device_put(device->pdev);
154         kfree(device);
155 }
156 EXPORT_SYMBOL(tegra_mipi_free);
157
158 static int tegra_mipi_wait(struct tegra_mipi *mipi)
159 {
160         unsigned long timeout = jiffies + msecs_to_jiffies(250);
161         unsigned long value;
162
163         while (time_before(jiffies, timeout)) {
164                 value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
165                 if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 &&
166                     (value & MIPI_CAL_STATUS_DONE) != 0)
167                         return 0;
168
169                 usleep_range(10, 50);
170         }
171
172         return -ETIMEDOUT;
173 }
174
175 int tegra_mipi_calibrate(struct tegra_mipi_device *device)
176 {
177         unsigned long value;
178         unsigned int i;
179         int err;
180
181         err = clk_enable(device->mipi->clk);
182         if (err < 0)
183                 return err;
184
185         mutex_lock(&device->mipi->lock);
186
187         value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0);
188         value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
189         value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
190         tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
191
192         value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
193         value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
194         tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
195
196         for (i = 0; i < ARRAY_SIZE(modules); i++) {
197                 if (device->pads & BIT(i))
198                         value = MIPI_CAL_CONFIG_SELECT |
199                                 MIPI_CAL_CONFIG_HSPDOS(0) |
200                                 MIPI_CAL_CONFIG_HSPUOS(4) |
201                                 MIPI_CAL_CONFIG_TERMOS(5);
202                 else
203                         value = 0;
204
205                 tegra_mipi_writel(device->mipi, value, modules[i].reg);
206         }
207
208         tegra_mipi_writel(device->mipi, MIPI_CAL_CTRL_START, MIPI_CAL_CTRL);
209
210         err = tegra_mipi_wait(device->mipi);
211
212         mutex_unlock(&device->mipi->lock);
213         clk_disable(device->mipi->clk);
214
215         return err;
216 }
217 EXPORT_SYMBOL(tegra_mipi_calibrate);
218
219 static int tegra_mipi_probe(struct platform_device *pdev)
220 {
221         struct tegra_mipi *mipi;
222         struct resource *res;
223         int err;
224
225         mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
226         if (!mipi)
227                 return -ENOMEM;
228
229         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
230         mipi->regs = devm_ioremap_resource(&pdev->dev, res);
231         if (IS_ERR(mipi->regs))
232                 return PTR_ERR(mipi->regs);
233
234         mutex_init(&mipi->lock);
235
236         mipi->clk = devm_clk_get(&pdev->dev, NULL);
237         if (IS_ERR(mipi->clk)) {
238                 dev_err(&pdev->dev, "failed to get clock\n");
239                 return PTR_ERR(mipi->clk);
240         }
241
242         err = clk_prepare(mipi->clk);
243         if (err < 0)
244                 return err;
245
246         platform_set_drvdata(pdev, mipi);
247
248         return 0;
249 }
250
251 static int tegra_mipi_remove(struct platform_device *pdev)
252 {
253         struct tegra_mipi *mipi = platform_get_drvdata(pdev);
254
255         clk_unprepare(mipi->clk);
256
257         return 0;
258 }
259
260 static struct of_device_id tegra_mipi_of_match[] = {
261         { .compatible = "nvidia,tegra114-mipi", },
262         { },
263 };
264
265 struct platform_driver tegra_mipi_driver = {
266         .driver = {
267                 .name = "tegra-mipi",
268                 .of_match_table = tegra_mipi_of_match,
269         },
270         .probe = tegra_mipi_probe,
271         .remove = tegra_mipi_remove,
272 };