2 * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
4 * The code contained herein is licensed under the GNU General Public
5 * License. You may obtain a copy of the GNU General Public License
6 * Version 2 or later at the following locations:
8 * http://www.opensource.org/licenses/gpl-license.html
9 * http://www.gnu.org/copyleft/gpl.html
11 #include <linux/export.h>
12 #include <linux/types.h>
13 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/spinlock.h>
17 #include <linux/delay.h>
18 #include <linux/clk.h>
19 #include <video/imx-ipu-v3.h>
24 struct ipu_smfc_priv *priv;
29 struct ipu_smfc_priv {
33 struct ipu_smfc channel[4];
38 #define SMFC_MAP 0x0000
39 #define SMFC_WMC 0x0004
40 #define SMFC_BS 0x0008
42 int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
44 struct ipu_smfc_priv *priv = smfc->priv;
48 spin_lock_irqsave(&priv->lock, flags);
50 shift = smfc->chno * 4;
51 val = readl(priv->base + SMFC_BS);
52 val &= ~(0xf << shift);
53 val |= burstsize << shift;
54 writel(val, priv->base + SMFC_BS);
56 spin_unlock_irqrestore(&priv->lock, flags);
60 EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
62 int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
64 struct ipu_smfc_priv *priv = smfc->priv;
68 spin_lock_irqsave(&priv->lock, flags);
70 shift = smfc->chno * 3;
71 val = readl(priv->base + SMFC_MAP);
72 val &= ~(0x7 << shift);
73 val |= ((csi_id << 2) | mipi_id) << shift;
74 writel(val, priv->base + SMFC_MAP);
76 spin_unlock_irqrestore(&priv->lock, flags);
80 EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
82 int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
84 struct ipu_smfc_priv *priv = smfc->priv;
88 spin_lock_irqsave(&priv->lock, flags);
90 shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
91 val = readl(priv->base + SMFC_WMC);
92 val &= ~(0x3f << shift);
93 val |= ((clr_level << 3) | set_level) << shift;
94 writel(val, priv->base + SMFC_WMC);
96 spin_unlock_irqrestore(&priv->lock, flags);
100 EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
102 int ipu_smfc_enable(struct ipu_smfc *smfc)
104 struct ipu_smfc_priv *priv = smfc->priv;
107 spin_lock_irqsave(&priv->lock, flags);
109 if (!priv->use_count)
110 ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
114 spin_unlock_irqrestore(&priv->lock, flags);
118 EXPORT_SYMBOL_GPL(ipu_smfc_enable);
120 int ipu_smfc_disable(struct ipu_smfc *smfc)
122 struct ipu_smfc_priv *priv = smfc->priv;
125 spin_lock_irqsave(&priv->lock, flags);
129 if (!priv->use_count)
130 ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
132 if (priv->use_count < 0)
135 spin_unlock_irqrestore(&priv->lock, flags);
139 EXPORT_SYMBOL_GPL(ipu_smfc_disable);
141 struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
143 struct ipu_smfc_priv *priv = ipu->smfc_priv;
144 struct ipu_smfc *smfc, *ret;
148 return ERR_PTR(-EINVAL);
150 smfc = &priv->channel[chno];
153 spin_lock_irqsave(&priv->lock, flags);
156 ret = ERR_PTR(-EBUSY);
162 spin_unlock_irqrestore(&priv->lock, flags);
165 EXPORT_SYMBOL_GPL(ipu_smfc_get);
167 void ipu_smfc_put(struct ipu_smfc *smfc)
169 struct ipu_smfc_priv *priv = smfc->priv;
172 spin_lock_irqsave(&priv->lock, flags);
174 spin_unlock_irqrestore(&priv->lock, flags);
176 EXPORT_SYMBOL_GPL(ipu_smfc_put);
178 int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
181 struct ipu_smfc_priv *priv;
184 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
188 ipu->smfc_priv = priv;
189 spin_lock_init(&priv->lock);
192 priv->base = devm_ioremap(dev, base, PAGE_SIZE);
196 for (i = 0; i < 4; i++) {
197 priv->channel[i].priv = priv;
198 priv->channel[i].chno = i;
201 pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
206 void ipu_smfc_exit(struct ipu_soc *ipu)