1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 NVIDIA Corporation
* Copyright (C) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/tegra-mipi-cal.h>
/* only need to support one provider */
static struct {
struct device_node *np;
const struct tegra_mipi_ops *ops;
} provider;
/**
* tegra_mipi_enable - Enable the Tegra MIPI calibration device.
* @device: Handle to the Tegra MIPI calibration device.
*
* This calls the enable sequence for the Tegra MIPI calibration device.
*
* Returns 0 on success or a negative error code on failure.
*/
int tegra_mipi_enable(struct tegra_mipi_device *device)
{
if (device->ops->enable)
return device->ops->enable(device);
return 0;
}
EXPORT_SYMBOL(tegra_mipi_enable);
/**
* tegra_mipi_disable - Disable the Tegra MIPI calibration device.
* @device: Handle to the Tegra MIPI calibration device.
*
* This calls the disable sequence for the Tegra MIPI calibration device.
*
* Returns 0 on success or a negative error code on failure.
*/
int tegra_mipi_disable(struct tegra_mipi_device *device)
{
if (device->ops->disable)
return device->ops->disable(device);
return 0;
}
EXPORT_SYMBOL(tegra_mipi_disable);
/**
* tegra_mipi_start_calibration - Start the Tegra MIPI calibration sequence.
* @device: Handle to the Tegra MIPI calibration device.
*
* This initiates the calibration of CSI/DSI interfaces via the Tegra MIPI
* calibration device.
*
* Returns 0 on success or a negative error code on failure.
*/
int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
{
if (device->ops->start_calibration)
return device->ops->start_calibration(device);
return 0;
}
EXPORT_SYMBOL(tegra_mipi_start_calibration);
/**
* tegra_mipi_finish_calibration - Finish the Tegra MIPI calibration sequence.
* @device: Handle to the Tegra MIPI calibration device.
*
* This completes the calibration of CSI/DSI interfaces via the Tegra MIPI
* calibration device.
*
* Returns 0 on success or a negative error code on failure.
*/
int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
{
if (device->ops->finish_calibration)
return device->ops->finish_calibration(device);
return 0;
}
EXPORT_SYMBOL(tegra_mipi_finish_calibration);
/**
* tegra_mipi_request - Request a Tegra MIPI calibration device.
* @device: Handle of the device requesting the MIPI calibration function.
* @np: Device node pointer of the device requesting the MIPI calibration
* function.
*
* This function requests a reference to a Tegra MIPI calibration device.
*
* Returns a pointer to the Tegra MIPI calibration device on success,
* or an ERR_PTR-encoded error code on failure.
*/
struct tegra_mipi_device *tegra_mipi_request(struct device *device,
struct device_node *np)
{
struct tegra_mipi_device *mipidev;
struct of_phandle_args args;
int err;
err = of_parse_phandle_with_args(np, "nvidia,mipi-calibrate",
"#nvidia,mipi-calibrate-cells", 0,
&args);
if (err < 0)
return ERR_PTR(err);
if (provider.np != args.np)
return ERR_PTR(-ENODEV);
mipidev = kzalloc_obj(*mipidev);
if (!mipidev) {
err = -ENOMEM;
goto out;
}
mipidev->pdev = of_find_device_by_node(args.np);
if (!mipidev->pdev) {
err = -ENODEV;
goto free;
}
of_node_put(args.np);
mipidev->ops = provider.ops;
mipidev->pads = args.args[0];
return mipidev;
free:
kfree(mipidev);
out:
of_node_put(args.np);
return ERR_PTR(err);
}
EXPORT_SYMBOL(tegra_mipi_request);
/**
* tegra_mipi_free - Free a Tegra MIPI calibration device.
* @mipidev: Handle to the Tegra MIPI calibration device.
*
* This function releases a reference to a Tegra MIPI calibration device
* previously requested by tegra_mipi_request().
*/
void tegra_mipi_free(struct tegra_mipi_device *mipidev)
{
platform_device_put(mipidev->pdev);
kfree(mipidev);
}
EXPORT_SYMBOL(tegra_mipi_free);
static void tegra_mipi_remove_provider(void *data)
{
provider.np = NULL;
provider.ops = NULL;
}
/**
* devm_tegra_mipi_add_provider - Managed registration of a Tegra MIPI
* calibration function provider.
* @device: Handle to the device providing the MIPI calibration function.
* @np: Device node pointer of the device providing the MIPI calibration
* function.
* @ops: Operations supported by the MIPI calibration device.
*
* This registers a device that provides MIPI calibration functions.
* For Tegra20 and Tegra30, this is the CSI block, while Tegra114 and
* newer SoC generations have a dedicated hardware block for these
* functions.
*
* Returns 0 on success or a negative error code on failure.
*/
int devm_tegra_mipi_add_provider(struct device *device, struct device_node *np,
const struct tegra_mipi_ops *ops)
{
if (provider.np)
return -EBUSY;
provider.np = np;
provider.ops = ops;
return devm_add_action_or_reset(device, tegra_mipi_remove_provider, NULL);
}
EXPORT_SYMBOL(devm_tegra_mipi_add_provider);
|