linux/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2015 Toradex AG
   4 *
   5 * Stefan Agner <stefan@agner.ch>
   6 *
   7 * Freescale TCON device driver
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/io.h>
  12#include <linux/mm.h>
  13#include <linux/of_address.h>
  14#include <linux/platform_device.h>
  15#include <linux/regmap.h>
  16
  17#include "fsl_tcon.h"
  18
  19void fsl_tcon_bypass_disable(struct fsl_tcon *tcon)
  20{
  21        regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
  22                           FSL_TCON_CTRL1_TCON_BYPASS, 0);
  23}
  24
  25void fsl_tcon_bypass_enable(struct fsl_tcon *tcon)
  26{
  27        regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
  28                           FSL_TCON_CTRL1_TCON_BYPASS,
  29                           FSL_TCON_CTRL1_TCON_BYPASS);
  30}
  31
  32static struct regmap_config fsl_tcon_regmap_config = {
  33        .reg_bits = 32,
  34        .reg_stride = 4,
  35        .val_bits = 32,
  36
  37        .name = "tcon",
  38};
  39
  40static int fsl_tcon_init_regmap(struct device *dev,
  41                                struct fsl_tcon *tcon,
  42                                struct device_node *np)
  43{
  44        struct resource res;
  45        void __iomem *regs;
  46
  47        if (of_address_to_resource(np, 0, &res))
  48                return -EINVAL;
  49
  50        regs = devm_ioremap_resource(dev, &res);
  51        if (IS_ERR(regs))
  52                return PTR_ERR(regs);
  53
  54        tcon->regs = devm_regmap_init_mmio(dev, regs,
  55                                           &fsl_tcon_regmap_config);
  56        return PTR_ERR_OR_ZERO(tcon->regs);
  57}
  58
  59struct fsl_tcon *fsl_tcon_init(struct device *dev)
  60{
  61        struct fsl_tcon *tcon;
  62        struct device_node *np;
  63        int ret;
  64
  65        /* TCON node is not mandatory, some devices do not provide TCON */
  66        np = of_parse_phandle(dev->of_node, "fsl,tcon", 0);
  67        if (!np)
  68                return NULL;
  69
  70        tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
  71        if (!tcon)
  72                goto err_node_put;
  73
  74        ret = fsl_tcon_init_regmap(dev, tcon, np);
  75        if (ret) {
  76                dev_err(dev, "Couldn't create the TCON regmap\n");
  77                goto err_node_put;
  78        }
  79
  80        tcon->ipg_clk = of_clk_get_by_name(np, "ipg");
  81        if (IS_ERR(tcon->ipg_clk)) {
  82                dev_err(dev, "Couldn't get the TCON bus clock\n");
  83                goto err_node_put;
  84        }
  85
  86        ret = clk_prepare_enable(tcon->ipg_clk);
  87        if (ret) {
  88                dev_err(dev, "Couldn't enable the TCON clock\n");
  89                goto err_node_put;
  90        }
  91
  92        of_node_put(np);
  93        dev_info(dev, "Using TCON in bypass mode\n");
  94
  95        return tcon;
  96
  97err_node_put:
  98        of_node_put(np);
  99        return NULL;
 100}
 101
 102void fsl_tcon_free(struct fsl_tcon *tcon)
 103{
 104        clk_disable_unprepare(tcon->ipg_clk);
 105        clk_put(tcon->ipg_clk);
 106}
 107
 108