···118118119119struct tegra_mipi {120120 const struct tegra_mipi_soc *soc;121121+ struct device *dev;121122 void __iomem *regs;122123 struct mutex lock;123124 struct clk *clk;125125+126126+ unsigned long usage_count;124127};125128126129struct tegra_mipi_device {···143140 unsigned long offset)144141{145142 writel(value, mipi->regs + (offset << 2));143143+}144144+145145+static int tegra_mipi_power_up(struct tegra_mipi *mipi)146146+{147147+ u32 value;148148+ int err;149149+150150+ err = clk_enable(mipi->clk);151151+ if (err < 0)152152+ return err;153153+154154+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);155155+ value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;156156+157157+ if (mipi->soc->needs_vclamp_ref)158158+ value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;159159+160160+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);161161+162162+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);163163+ value &= ~MIPI_CAL_BIAS_PAD_PDVREG;164164+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);165165+166166+ clk_disable(mipi->clk);167167+168168+ return 0;169169+}170170+171171+static int tegra_mipi_power_down(struct tegra_mipi *mipi)172172+{173173+ u32 value;174174+ int err;175175+176176+ err = clk_enable(mipi->clk);177177+ if (err < 0)178178+ return err;179179+180180+ /*181181+ * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that182182+ * supplies the DSI pads. This must be kept enabled until none of the183183+ * DSI lanes are used anymore.184184+ */185185+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);186186+ value |= MIPI_CAL_BIAS_PAD_PDVREG;187187+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);188188+189189+ /*190190+ * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF191191+ * control a regulator that supplies current to the pre-driver logic.192192+ * Powering down this regulator causes DSI to fail, so it must remain193193+ * powered on until none of the DSI lanes are used anymore.194194+ */195195+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);196196+197197+ if (mipi->soc->needs_vclamp_ref)198198+ value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;199199+200200+ value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;201201+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);202202+203203+ return 0;146204}147205148206struct tegra_mipi_device *tegra_mipi_request(struct device *device)···242178 dev->pads = args.args[0];243179 dev->device = device;244180181181+ mutex_lock(&dev->mipi->lock);182182+183183+ if (dev->mipi->usage_count++ == 0) {184184+ err = tegra_mipi_power_up(dev->mipi);185185+ if (err < 0) {186186+ dev_err(dev->mipi->dev,187187+ "failed to power up MIPI bricks: %d\n",188188+ err);189189+ return ERR_PTR(err);190190+ }191191+ }192192+193193+ mutex_unlock(&dev->mipi->lock);194194+245195 return dev;246196247197put:···270192271193void tegra_mipi_free(struct tegra_mipi_device *device)272194{195195+ int err;196196+197197+ mutex_lock(&device->mipi->lock);198198+199199+ if (--device->mipi->usage_count == 0) {200200+ err = tegra_mipi_power_down(device->mipi);201201+ if (err < 0) {202202+ /*203203+ * Not much that can be done here, so an error message204204+ * will have to do.205205+ */206206+ dev_err(device->mipi->dev,207207+ "failed to power down MIPI bricks: %d\n",208208+ err);209209+ }210210+ }211211+212212+ mutex_unlock(&device->mipi->lock);213213+273214 platform_device_put(device->pdev);274215 kfree(device);275216}···324227325228 mutex_lock(&device->mipi->lock);326229327327- value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0);328328- value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;329329-330330- if (soc->needs_vclamp_ref)331331- value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;332332-333333- tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);334334-335230 value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |336231 MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);337232 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG1);338338-339339- value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);340340- value &= ~MIPI_CAL_BIAS_PAD_PDVREG;341341- tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);342233343234 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);344235 value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);···511426 return -ENOMEM;512427513428 mipi->soc = match->data;429429+ mipi->dev = &pdev->dev;514430515431 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);516432 mipi->regs = devm_ioremap_resource(&pdev->dev, res);