0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/io.h>
0012 #include <linux/mm.h>
0013 #include <linux/of_address.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regmap.h>
0016
0017 #include "fsl_tcon.h"
0018
0019 void fsl_tcon_bypass_disable(struct fsl_tcon *tcon)
0020 {
0021 regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
0022 FSL_TCON_CTRL1_TCON_BYPASS, 0);
0023 }
0024
0025 void fsl_tcon_bypass_enable(struct fsl_tcon *tcon)
0026 {
0027 regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
0028 FSL_TCON_CTRL1_TCON_BYPASS,
0029 FSL_TCON_CTRL1_TCON_BYPASS);
0030 }
0031
0032 static struct regmap_config fsl_tcon_regmap_config = {
0033 .reg_bits = 32,
0034 .reg_stride = 4,
0035 .val_bits = 32,
0036
0037 .name = "tcon",
0038 };
0039
0040 static int fsl_tcon_init_regmap(struct device *dev,
0041 struct fsl_tcon *tcon,
0042 struct device_node *np)
0043 {
0044 struct resource res;
0045 void __iomem *regs;
0046
0047 if (of_address_to_resource(np, 0, &res))
0048 return -EINVAL;
0049
0050 regs = devm_ioremap_resource(dev, &res);
0051 if (IS_ERR(regs))
0052 return PTR_ERR(regs);
0053
0054 tcon->regs = devm_regmap_init_mmio(dev, regs,
0055 &fsl_tcon_regmap_config);
0056 return PTR_ERR_OR_ZERO(tcon->regs);
0057 }
0058
0059 struct fsl_tcon *fsl_tcon_init(struct device *dev)
0060 {
0061 struct fsl_tcon *tcon;
0062 struct device_node *np;
0063 int ret;
0064
0065
0066 np = of_parse_phandle(dev->of_node, "fsl,tcon", 0);
0067 if (!np)
0068 return NULL;
0069
0070 tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
0071 if (!tcon)
0072 goto err_node_put;
0073
0074 ret = fsl_tcon_init_regmap(dev, tcon, np);
0075 if (ret) {
0076 dev_err(dev, "Couldn't create the TCON regmap\n");
0077 goto err_node_put;
0078 }
0079
0080 tcon->ipg_clk = of_clk_get_by_name(np, "ipg");
0081 if (IS_ERR(tcon->ipg_clk)) {
0082 dev_err(dev, "Couldn't get the TCON bus clock\n");
0083 goto err_node_put;
0084 }
0085
0086 ret = clk_prepare_enable(tcon->ipg_clk);
0087 if (ret) {
0088 dev_err(dev, "Couldn't enable the TCON clock\n");
0089 goto err_node_put;
0090 }
0091
0092 of_node_put(np);
0093 dev_info(dev, "Using TCON in bypass mode\n");
0094
0095 return tcon;
0096
0097 err_node_put:
0098 of_node_put(np);
0099 return NULL;
0100 }
0101
0102 void fsl_tcon_free(struct fsl_tcon *tcon)
0103 {
0104 clk_disable_unprepare(tcon->ipg_clk);
0105 clk_put(tcon->ipg_clk);
0106 }
0107