root/drivers/gpu/host1x/mipi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tegra_mipi_readl
  2. tegra_mipi_writel
  3. tegra_mipi_power_up
  4. tegra_mipi_power_down
  5. tegra_mipi_request
  6. tegra_mipi_free
  7. tegra_mipi_enable
  8. tegra_mipi_disable
  9. tegra_mipi_wait
  10. tegra_mipi_calibrate
  11. tegra_mipi_probe
  12. tegra_mipi_remove

   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/host1x.h>
  26 #include <linux/io.h>
  27 #include <linux/of_platform.h>
  28 #include <linux/platform_device.h>
  29 #include <linux/slab.h>
  30 
  31 #include "dev.h"
  32 
  33 #define MIPI_CAL_CTRL                   0x00
  34 #define MIPI_CAL_CTRL_NOISE_FILTER(x)   (((x) & 0xf) << 26)
  35 #define MIPI_CAL_CTRL_PRESCALE(x)       (((x) & 0x3) << 24)
  36 #define MIPI_CAL_CTRL_CLKEN_OVR         (1 << 4)
  37 #define MIPI_CAL_CTRL_START             (1 << 0)
  38 
  39 #define MIPI_CAL_AUTOCAL_CTRL           0x01
  40 
  41 #define MIPI_CAL_STATUS                 0x02
  42 #define MIPI_CAL_STATUS_DONE            (1 << 16)
  43 #define MIPI_CAL_STATUS_ACTIVE          (1 <<  0)
  44 
  45 #define MIPI_CAL_CONFIG_CSIA            0x05
  46 #define MIPI_CAL_CONFIG_CSIB            0x06
  47 #define MIPI_CAL_CONFIG_CSIC            0x07
  48 #define MIPI_CAL_CONFIG_CSID            0x08
  49 #define MIPI_CAL_CONFIG_CSIE            0x09
  50 #define MIPI_CAL_CONFIG_CSIF            0x0a
  51 #define MIPI_CAL_CONFIG_DSIA            0x0e
  52 #define MIPI_CAL_CONFIG_DSIB            0x0f
  53 #define MIPI_CAL_CONFIG_DSIC            0x10
  54 #define MIPI_CAL_CONFIG_DSID            0x11
  55 
  56 #define MIPI_CAL_CONFIG_DSIA_CLK        0x19
  57 #define MIPI_CAL_CONFIG_DSIB_CLK        0x1a
  58 #define MIPI_CAL_CONFIG_CSIAB_CLK       0x1b
  59 #define MIPI_CAL_CONFIG_DSIC_CLK        0x1c
  60 #define MIPI_CAL_CONFIG_CSICD_CLK       0x1c
  61 #define MIPI_CAL_CONFIG_DSID_CLK        0x1d
  62 #define MIPI_CAL_CONFIG_CSIE_CLK        0x1d
  63 
  64 /* for data and clock lanes */
  65 #define MIPI_CAL_CONFIG_SELECT          (1 << 21)
  66 
  67 /* for data lanes */
  68 #define MIPI_CAL_CONFIG_HSPDOS(x)       (((x) & 0x1f) << 16)
  69 #define MIPI_CAL_CONFIG_HSPUOS(x)       (((x) & 0x1f) <<  8)
  70 #define MIPI_CAL_CONFIG_TERMOS(x)       (((x) & 0x1f) <<  0)
  71 
  72 /* for clock lanes */
  73 #define MIPI_CAL_CONFIG_HSCLKPDOSD(x)   (((x) & 0x1f) <<  8)
  74 #define MIPI_CAL_CONFIG_HSCLKPUOSD(x)   (((x) & 0x1f) <<  0)
  75 
  76 #define MIPI_CAL_BIAS_PAD_CFG0          0x16
  77 #define MIPI_CAL_BIAS_PAD_PDVCLAMP      (1 << 1)
  78 #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF  (1 << 0)
  79 
  80 #define MIPI_CAL_BIAS_PAD_CFG1          0x17
  81 #define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)
  82 #define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8)
  83 
  84 #define MIPI_CAL_BIAS_PAD_CFG2          0x18
  85 #define MIPI_CAL_BIAS_PAD_VCLAMP(x)     (((x) & 0x7) << 16)
  86 #define MIPI_CAL_BIAS_PAD_VAUXP(x)      (((x) & 0x7) << 4)
  87 #define MIPI_CAL_BIAS_PAD_PDVREG        (1 << 1)
  88 
  89 struct tegra_mipi_pad {
  90         unsigned long data;
  91         unsigned long clk;
  92 };
  93 
  94 struct tegra_mipi_soc {
  95         bool has_clk_lane;
  96         const struct tegra_mipi_pad *pads;
  97         unsigned int num_pads;
  98 
  99         bool clock_enable_override;
 100         bool needs_vclamp_ref;
 101 
 102         /* bias pad configuration settings */
 103         u8 pad_drive_down_ref;
 104         u8 pad_drive_up_ref;
 105 
 106         u8 pad_vclamp_level;
 107         u8 pad_vauxp_level;
 108 
 109         /* calibration settings for data lanes */
 110         u8 hspdos;
 111         u8 hspuos;
 112         u8 termos;
 113 
 114         /* calibration settings for clock lanes */
 115         u8 hsclkpdos;
 116         u8 hsclkpuos;
 117 };
 118 
 119 struct tegra_mipi {
 120         const struct tegra_mipi_soc *soc;
 121         struct device *dev;
 122         void __iomem *regs;
 123         struct mutex lock;
 124         struct clk *clk;
 125 
 126         unsigned long usage_count;
 127 };
 128 
 129 struct tegra_mipi_device {
 130         struct platform_device *pdev;
 131         struct tegra_mipi *mipi;
 132         struct device *device;
 133         unsigned long pads;
 134 };
 135 
 136 static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
 137                                    unsigned long offset)
 138 {
 139         return readl(mipi->regs + (offset << 2));
 140 }
 141 
 142 static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
 143                                      unsigned long offset)
 144 {
 145         writel(value, mipi->regs + (offset << 2));
 146 }
 147 
 148 static int tegra_mipi_power_up(struct tegra_mipi *mipi)
 149 {
 150         u32 value;
 151         int err;
 152 
 153         err = clk_enable(mipi->clk);
 154         if (err < 0)
 155                 return err;
 156 
 157         value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
 158         value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
 159 
 160         if (mipi->soc->needs_vclamp_ref)
 161                 value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
 162 
 163         tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
 164 
 165         value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
 166         value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
 167         tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
 168 
 169         clk_disable(mipi->clk);
 170 
 171         return 0;
 172 }
 173 
 174 static int tegra_mipi_power_down(struct tegra_mipi *mipi)
 175 {
 176         u32 value;
 177         int err;
 178 
 179         err = clk_enable(mipi->clk);
 180         if (err < 0)
 181                 return err;
 182 
 183         /*
 184          * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that
 185          * supplies the DSI pads. This must be kept enabled until none of the
 186          * DSI lanes are used anymore.
 187          */
 188         value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
 189         value |= MIPI_CAL_BIAS_PAD_PDVREG;
 190         tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
 191 
 192         /*
 193          * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF
 194          * control a regulator that supplies current to the pre-driver logic.
 195          * Powering down this regulator causes DSI to fail, so it must remain
 196          * powered on until none of the DSI lanes are used anymore.
 197          */
 198         value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
 199 
 200         if (mipi->soc->needs_vclamp_ref)
 201                 value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
 202 
 203         value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;
 204         tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
 205 
 206         return 0;
 207 }
 208 
 209 struct tegra_mipi_device *tegra_mipi_request(struct device *device)
 210 {
 211         struct device_node *np = device->of_node;
 212         struct tegra_mipi_device *dev;
 213         struct of_phandle_args args;
 214         int err;
 215 
 216         err = of_parse_phandle_with_args(np, "nvidia,mipi-calibrate",
 217                                          "#nvidia,mipi-calibrate-cells", 0,
 218                                          &args);
 219         if (err < 0)
 220                 return ERR_PTR(err);
 221 
 222         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 223         if (!dev) {
 224                 err = -ENOMEM;
 225                 goto out;
 226         }
 227 
 228         dev->pdev = of_find_device_by_node(args.np);
 229         if (!dev->pdev) {
 230                 err = -ENODEV;
 231                 goto free;
 232         }
 233 
 234         dev->mipi = platform_get_drvdata(dev->pdev);
 235         if (!dev->mipi) {
 236                 err = -EPROBE_DEFER;
 237                 goto put;
 238         }
 239 
 240         of_node_put(args.np);
 241 
 242         dev->pads = args.args[0];
 243         dev->device = device;
 244 
 245         return dev;
 246 
 247 put:
 248         platform_device_put(dev->pdev);
 249 free:
 250         kfree(dev);
 251 out:
 252         of_node_put(args.np);
 253         return ERR_PTR(err);
 254 }
 255 EXPORT_SYMBOL(tegra_mipi_request);
 256 
 257 void tegra_mipi_free(struct tegra_mipi_device *device)
 258 {
 259         platform_device_put(device->pdev);
 260         kfree(device);
 261 }
 262 EXPORT_SYMBOL(tegra_mipi_free);
 263 
 264 int tegra_mipi_enable(struct tegra_mipi_device *dev)
 265 {
 266         int err = 0;
 267 
 268         mutex_lock(&dev->mipi->lock);
 269 
 270         if (dev->mipi->usage_count++ == 0)
 271                 err = tegra_mipi_power_up(dev->mipi);
 272 
 273         mutex_unlock(&dev->mipi->lock);
 274 
 275         return err;
 276 
 277 }
 278 EXPORT_SYMBOL(tegra_mipi_enable);
 279 
 280 int tegra_mipi_disable(struct tegra_mipi_device *dev)
 281 {
 282         int err = 0;
 283 
 284         mutex_lock(&dev->mipi->lock);
 285 
 286         if (--dev->mipi->usage_count == 0)
 287                 err = tegra_mipi_power_down(dev->mipi);
 288 
 289         mutex_unlock(&dev->mipi->lock);
 290 
 291         return err;
 292 
 293 }
 294 EXPORT_SYMBOL(tegra_mipi_disable);
 295 
 296 static int tegra_mipi_wait(struct tegra_mipi *mipi)
 297 {
 298         unsigned long timeout = jiffies + msecs_to_jiffies(250);
 299         u32 value;
 300 
 301         while (time_before(jiffies, timeout)) {
 302                 value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
 303                 if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 &&
 304                     (value & MIPI_CAL_STATUS_DONE) != 0)
 305                         return 0;
 306 
 307                 usleep_range(10, 50);
 308         }
 309 
 310         return -ETIMEDOUT;
 311 }
 312 
 313 int tegra_mipi_calibrate(struct tegra_mipi_device *device)
 314 {
 315         const struct tegra_mipi_soc *soc = device->mipi->soc;
 316         unsigned int i;
 317         u32 value;
 318         int err;
 319 
 320         err = clk_enable(device->mipi->clk);
 321         if (err < 0)
 322                 return err;
 323 
 324         mutex_lock(&device->mipi->lock);
 325 
 326         value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
 327                 MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
 328         tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG1);
 329 
 330         value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
 331         value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
 332         value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
 333         value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level);
 334         value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level);
 335         tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
 336 
 337         for (i = 0; i < soc->num_pads; i++) {
 338                 u32 clk = 0, data = 0;
 339 
 340                 if (device->pads & BIT(i)) {
 341                         data = MIPI_CAL_CONFIG_SELECT |
 342                                MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
 343                                MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) |
 344                                MIPI_CAL_CONFIG_TERMOS(soc->termos);
 345                         clk = MIPI_CAL_CONFIG_SELECT |
 346                               MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) |
 347                               MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos);
 348                 }
 349 
 350                 tegra_mipi_writel(device->mipi, data, soc->pads[i].data);
 351 
 352                 if (soc->has_clk_lane && soc->pads[i].clk != 0)
 353                         tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk);
 354         }
 355 
 356         value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
 357         value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
 358         value &= ~MIPI_CAL_CTRL_PRESCALE(0x3);
 359         value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa);
 360         value |= MIPI_CAL_CTRL_PRESCALE(0x2);
 361 
 362         if (!soc->clock_enable_override)
 363                 value &= ~MIPI_CAL_CTRL_CLKEN_OVR;
 364         else
 365                 value |= MIPI_CAL_CTRL_CLKEN_OVR;
 366 
 367         tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
 368 
 369         /* clear any pending status bits */
 370         value = tegra_mipi_readl(device->mipi, MIPI_CAL_STATUS);
 371         tegra_mipi_writel(device->mipi, value, MIPI_CAL_STATUS);
 372 
 373         value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
 374         value |= MIPI_CAL_CTRL_START;
 375         tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
 376 
 377         err = tegra_mipi_wait(device->mipi);
 378 
 379         mutex_unlock(&device->mipi->lock);
 380         clk_disable(device->mipi->clk);
 381 
 382         return err;
 383 }
 384 EXPORT_SYMBOL(tegra_mipi_calibrate);
 385 
 386 static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
 387         { .data = MIPI_CAL_CONFIG_CSIA },
 388         { .data = MIPI_CAL_CONFIG_CSIB },
 389         { .data = MIPI_CAL_CONFIG_CSIC },
 390         { .data = MIPI_CAL_CONFIG_CSID },
 391         { .data = MIPI_CAL_CONFIG_CSIE },
 392         { .data = MIPI_CAL_CONFIG_DSIA },
 393         { .data = MIPI_CAL_CONFIG_DSIB },
 394         { .data = MIPI_CAL_CONFIG_DSIC },
 395         { .data = MIPI_CAL_CONFIG_DSID },
 396 };
 397 
 398 static const struct tegra_mipi_soc tegra114_mipi_soc = {
 399         .has_clk_lane = false,
 400         .pads = tegra114_mipi_pads,
 401         .num_pads = ARRAY_SIZE(tegra114_mipi_pads),
 402         .clock_enable_override = true,
 403         .needs_vclamp_ref = true,
 404         .pad_drive_down_ref = 0x2,
 405         .pad_drive_up_ref = 0x0,
 406         .pad_vclamp_level = 0x0,
 407         .pad_vauxp_level = 0x0,
 408         .hspdos = 0x0,
 409         .hspuos = 0x4,
 410         .termos = 0x5,
 411         .hsclkpdos = 0x0,
 412         .hsclkpuos = 0x4,
 413 };
 414 
 415 static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
 416         { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
 417         { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
 418         { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
 419         { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
 420         { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK  },
 421         { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK  },
 422         { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK  },
 423 };
 424 
 425 static const struct tegra_mipi_soc tegra124_mipi_soc = {
 426         .has_clk_lane = true,
 427         .pads = tegra124_mipi_pads,
 428         .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
 429         .clock_enable_override = true,
 430         .needs_vclamp_ref = true,
 431         .pad_drive_down_ref = 0x2,
 432         .pad_drive_up_ref = 0x0,
 433         .pad_vclamp_level = 0x0,
 434         .pad_vauxp_level = 0x0,
 435         .hspdos = 0x0,
 436         .hspuos = 0x0,
 437         .termos = 0x0,
 438         .hsclkpdos = 0x1,
 439         .hsclkpuos = 0x2,
 440 };
 441 
 442 static const struct tegra_mipi_soc tegra132_mipi_soc = {
 443         .has_clk_lane = true,
 444         .pads = tegra124_mipi_pads,
 445         .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
 446         .clock_enable_override = false,
 447         .needs_vclamp_ref = false,
 448         .pad_drive_down_ref = 0x0,
 449         .pad_drive_up_ref = 0x3,
 450         .pad_vclamp_level = 0x0,
 451         .pad_vauxp_level = 0x0,
 452         .hspdos = 0x0,
 453         .hspuos = 0x0,
 454         .termos = 0x0,
 455         .hsclkpdos = 0x3,
 456         .hsclkpuos = 0x2,
 457 };
 458 
 459 static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
 460         { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 },
 461         { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 },
 462         { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 },
 463         { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 },
 464         { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 },
 465         { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 },
 466         { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
 467         { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
 468         { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK },
 469         { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK },
 470 };
 471 
 472 static const struct tegra_mipi_soc tegra210_mipi_soc = {
 473         .has_clk_lane = true,
 474         .pads = tegra210_mipi_pads,
 475         .num_pads = ARRAY_SIZE(tegra210_mipi_pads),
 476         .clock_enable_override = true,
 477         .needs_vclamp_ref = false,
 478         .pad_drive_down_ref = 0x0,
 479         .pad_drive_up_ref = 0x3,
 480         .pad_vclamp_level = 0x1,
 481         .pad_vauxp_level = 0x1,
 482         .hspdos = 0x0,
 483         .hspuos = 0x2,
 484         .termos = 0x0,
 485         .hsclkpdos = 0x0,
 486         .hsclkpuos = 0x2,
 487 };
 488 
 489 static const struct of_device_id tegra_mipi_of_match[] = {
 490         { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
 491         { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
 492         { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc },
 493         { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc },
 494         { },
 495 };
 496 
 497 static int tegra_mipi_probe(struct platform_device *pdev)
 498 {
 499         const struct of_device_id *match;
 500         struct tegra_mipi *mipi;
 501         struct resource *res;
 502         int err;
 503 
 504         match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node);
 505         if (!match)
 506                 return -ENODEV;
 507 
 508         mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
 509         if (!mipi)
 510                 return -ENOMEM;
 511 
 512         mipi->soc = match->data;
 513         mipi->dev = &pdev->dev;
 514 
 515         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 516         mipi->regs = devm_ioremap_resource(&pdev->dev, res);
 517         if (IS_ERR(mipi->regs))
 518                 return PTR_ERR(mipi->regs);
 519 
 520         mutex_init(&mipi->lock);
 521 
 522         mipi->clk = devm_clk_get(&pdev->dev, NULL);
 523         if (IS_ERR(mipi->clk)) {
 524                 dev_err(&pdev->dev, "failed to get clock\n");
 525                 return PTR_ERR(mipi->clk);
 526         }
 527 
 528         err = clk_prepare(mipi->clk);
 529         if (err < 0)
 530                 return err;
 531 
 532         platform_set_drvdata(pdev, mipi);
 533 
 534         return 0;
 535 }
 536 
 537 static int tegra_mipi_remove(struct platform_device *pdev)
 538 {
 539         struct tegra_mipi *mipi = platform_get_drvdata(pdev);
 540 
 541         clk_unprepare(mipi->clk);
 542 
 543         return 0;
 544 }
 545 
 546 struct platform_driver tegra_mipi_driver = {
 547         .driver = {
 548                 .name = "tegra-mipi",
 549                 .of_match_table = tegra_mipi_of_match,
 550         },
 551         .probe = tegra_mipi_probe,
 552         .remove = tegra_mipi_remove,
 553 };

/* [<][>][^][v][top][bottom][index][help] */