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