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
)