1*ea9c2605SLucas Stach /* 2*ea9c2605SLucas Stach * Copyright (c) 2016-2017 Lucas Stach, Pengutronix 3*ea9c2605SLucas Stach * 4*ea9c2605SLucas Stach * This program is free software; you can redistribute it and/or modify it 5*ea9c2605SLucas Stach * under the terms and conditions of the GNU General Public License, 6*ea9c2605SLucas Stach * version 2, as published by the Free Software Foundation. 7*ea9c2605SLucas Stach * 8*ea9c2605SLucas Stach * This program is distributed in the hope it will be useful, but WITHOUT 9*ea9c2605SLucas Stach * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10*ea9c2605SLucas Stach * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11*ea9c2605SLucas Stach * more details. 12*ea9c2605SLucas Stach */ 13*ea9c2605SLucas Stach 14*ea9c2605SLucas Stach #include <drm/drm_fourcc.h> 15*ea9c2605SLucas Stach #include <linux/clk.h> 16*ea9c2605SLucas Stach #include <linux/err.h> 17*ea9c2605SLucas Stach #include <linux/mfd/syscon.h> 18*ea9c2605SLucas Stach #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 19*ea9c2605SLucas Stach #include <linux/module.h> 20*ea9c2605SLucas Stach #include <linux/of.h> 21*ea9c2605SLucas Stach #include <linux/platform_device.h> 22*ea9c2605SLucas Stach #include <linux/regmap.h> 23*ea9c2605SLucas Stach #include <video/imx-ipu-v3.h> 24*ea9c2605SLucas Stach 25*ea9c2605SLucas Stach #include "ipu-prv.h" 26*ea9c2605SLucas Stach 27*ea9c2605SLucas Stach #define IPU_PRG_CTL 0x00 28*ea9c2605SLucas Stach #define IPU_PRG_CTL_BYPASS(i) (1 << (0 + i)) 29*ea9c2605SLucas Stach #define IPU_PRG_CTL_SOFT_ARID_MASK 0x3 30*ea9c2605SLucas Stach #define IPU_PRG_CTL_SOFT_ARID_SHIFT(i) (8 + i * 2) 31*ea9c2605SLucas Stach #define IPU_PRG_CTL_SOFT_ARID(i, v) ((v & 0x3) << (8 + 2 * i)) 32*ea9c2605SLucas Stach #define IPU_PRG_CTL_SO(i) (1 << (16 + i)) 33*ea9c2605SLucas Stach #define IPU_PRG_CTL_VFLIP(i) (1 << (19 + i)) 34*ea9c2605SLucas Stach #define IPU_PRG_CTL_BLOCK_MODE(i) (1 << (22 + i)) 35*ea9c2605SLucas Stach #define IPU_PRG_CTL_CNT_LOAD_EN(i) (1 << (25 + i)) 36*ea9c2605SLucas Stach #define IPU_PRG_CTL_SOFTRST (1 << 30) 37*ea9c2605SLucas Stach #define IPU_PRG_CTL_SHADOW_EN (1 << 31) 38*ea9c2605SLucas Stach 39*ea9c2605SLucas Stach #define IPU_PRG_STATUS 0x04 40*ea9c2605SLucas Stach #define IPU_PRG_STATUS_BUFFER0_READY(i) (1 << (0 + i * 2)) 41*ea9c2605SLucas Stach #define IPU_PRG_STATUS_BUFFER1_READY(i) (1 << (1 + i * 2)) 42*ea9c2605SLucas Stach 43*ea9c2605SLucas Stach #define IPU_PRG_QOS 0x08 44*ea9c2605SLucas Stach #define IPU_PRG_QOS_ARID_MASK 0xf 45*ea9c2605SLucas Stach #define IPU_PRG_QOS_ARID_SHIFT(i) (0 + i * 4) 46*ea9c2605SLucas Stach 47*ea9c2605SLucas Stach #define IPU_PRG_REG_UPDATE 0x0c 48*ea9c2605SLucas Stach #define IPU_PRG_REG_UPDATE_REG_UPDATE (1 << 0) 49*ea9c2605SLucas Stach 50*ea9c2605SLucas Stach #define IPU_PRG_STRIDE(i) (0x10 + i * 0x4) 51*ea9c2605SLucas Stach #define IPU_PRG_STRIDE_STRIDE_MASK 0x3fff 52*ea9c2605SLucas Stach 53*ea9c2605SLucas Stach #define IPU_PRG_CROP_LINE 0x1c 54*ea9c2605SLucas Stach 55*ea9c2605SLucas Stach #define IPU_PRG_THD 0x20 56*ea9c2605SLucas Stach 57*ea9c2605SLucas Stach #define IPU_PRG_BADDR(i) (0x24 + i * 0x4) 58*ea9c2605SLucas Stach 59*ea9c2605SLucas Stach #define IPU_PRG_OFFSET(i) (0x30 + i * 0x4) 60*ea9c2605SLucas Stach 61*ea9c2605SLucas Stach #define IPU_PRG_ILO(i) (0x3c + i * 0x4) 62*ea9c2605SLucas Stach 63*ea9c2605SLucas Stach #define IPU_PRG_HEIGHT(i) (0x48 + i * 0x4) 64*ea9c2605SLucas Stach #define IPU_PRG_HEIGHT_PRE_HEIGHT_MASK 0xfff 65*ea9c2605SLucas Stach #define IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT 0 66*ea9c2605SLucas Stach #define IPU_PRG_HEIGHT_IPU_HEIGHT_MASK 0xfff 67*ea9c2605SLucas Stach #define IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT 16 68*ea9c2605SLucas Stach 69*ea9c2605SLucas Stach struct ipu_prg_channel { 70*ea9c2605SLucas Stach bool enabled; 71*ea9c2605SLucas Stach int used_pre; 72*ea9c2605SLucas Stach }; 73*ea9c2605SLucas Stach 74*ea9c2605SLucas Stach struct ipu_prg { 75*ea9c2605SLucas Stach struct list_head list; 76*ea9c2605SLucas Stach struct device *dev; 77*ea9c2605SLucas Stach int id; 78*ea9c2605SLucas Stach 79*ea9c2605SLucas Stach void __iomem *regs; 80*ea9c2605SLucas Stach struct clk *clk_ipg, *clk_axi; 81*ea9c2605SLucas Stach struct regmap *iomuxc_gpr; 82*ea9c2605SLucas Stach struct ipu_pre *pres[3]; 83*ea9c2605SLucas Stach 84*ea9c2605SLucas Stach struct ipu_prg_channel chan[3]; 85*ea9c2605SLucas Stach }; 86*ea9c2605SLucas Stach 87*ea9c2605SLucas Stach static DEFINE_MUTEX(ipu_prg_list_mutex); 88*ea9c2605SLucas Stach static LIST_HEAD(ipu_prg_list); 89*ea9c2605SLucas Stach 90*ea9c2605SLucas Stach struct ipu_prg * 91*ea9c2605SLucas Stach ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id) 92*ea9c2605SLucas Stach { 93*ea9c2605SLucas Stach struct device_node *prg_node = of_parse_phandle(dev->of_node, 94*ea9c2605SLucas Stach name, 0); 95*ea9c2605SLucas Stach struct ipu_prg *prg; 96*ea9c2605SLucas Stach 97*ea9c2605SLucas Stach mutex_lock(&ipu_prg_list_mutex); 98*ea9c2605SLucas Stach list_for_each_entry(prg, &ipu_prg_list, list) { 99*ea9c2605SLucas Stach if (prg_node == prg->dev->of_node) { 100*ea9c2605SLucas Stach mutex_unlock(&ipu_prg_list_mutex); 101*ea9c2605SLucas Stach device_link_add(dev, prg->dev, DL_FLAG_AUTOREMOVE); 102*ea9c2605SLucas Stach prg->id = ipu_id; 103*ea9c2605SLucas Stach return prg; 104*ea9c2605SLucas Stach } 105*ea9c2605SLucas Stach } 106*ea9c2605SLucas Stach mutex_unlock(&ipu_prg_list_mutex); 107*ea9c2605SLucas Stach 108*ea9c2605SLucas Stach return NULL; 109*ea9c2605SLucas Stach } 110*ea9c2605SLucas Stach 111*ea9c2605SLucas Stach int ipu_prg_max_active_channels(void) 112*ea9c2605SLucas Stach { 113*ea9c2605SLucas Stach return ipu_pre_get_available_count(); 114*ea9c2605SLucas Stach } 115*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels); 116*ea9c2605SLucas Stach 117*ea9c2605SLucas Stach bool ipu_prg_present(struct ipu_soc *ipu) 118*ea9c2605SLucas Stach { 119*ea9c2605SLucas Stach if (ipu->prg_priv) 120*ea9c2605SLucas Stach return true; 121*ea9c2605SLucas Stach 122*ea9c2605SLucas Stach return false; 123*ea9c2605SLucas Stach } 124*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_present); 125*ea9c2605SLucas Stach 126*ea9c2605SLucas Stach bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format, 127*ea9c2605SLucas Stach uint64_t modifier) 128*ea9c2605SLucas Stach { 129*ea9c2605SLucas Stach const struct drm_format_info *info = drm_format_info(format); 130*ea9c2605SLucas Stach 131*ea9c2605SLucas Stach if (info->num_planes != 1) 132*ea9c2605SLucas Stach return false; 133*ea9c2605SLucas Stach 134*ea9c2605SLucas Stach return true; 135*ea9c2605SLucas Stach } 136*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_format_supported); 137*ea9c2605SLucas Stach 138*ea9c2605SLucas Stach int ipu_prg_enable(struct ipu_soc *ipu) 139*ea9c2605SLucas Stach { 140*ea9c2605SLucas Stach struct ipu_prg *prg = ipu->prg_priv; 141*ea9c2605SLucas Stach int ret; 142*ea9c2605SLucas Stach 143*ea9c2605SLucas Stach if (!prg) 144*ea9c2605SLucas Stach return 0; 145*ea9c2605SLucas Stach 146*ea9c2605SLucas Stach ret = clk_prepare_enable(prg->clk_axi); 147*ea9c2605SLucas Stach if (ret) 148*ea9c2605SLucas Stach goto fail_disable_ipg; 149*ea9c2605SLucas Stach 150*ea9c2605SLucas Stach return 0; 151*ea9c2605SLucas Stach 152*ea9c2605SLucas Stach fail_disable_ipg: 153*ea9c2605SLucas Stach clk_disable_unprepare(prg->clk_ipg); 154*ea9c2605SLucas Stach 155*ea9c2605SLucas Stach return ret; 156*ea9c2605SLucas Stach } 157*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_enable); 158*ea9c2605SLucas Stach 159*ea9c2605SLucas Stach void ipu_prg_disable(struct ipu_soc *ipu) 160*ea9c2605SLucas Stach { 161*ea9c2605SLucas Stach struct ipu_prg *prg = ipu->prg_priv; 162*ea9c2605SLucas Stach 163*ea9c2605SLucas Stach if (!prg) 164*ea9c2605SLucas Stach return; 165*ea9c2605SLucas Stach 166*ea9c2605SLucas Stach clk_disable_unprepare(prg->clk_axi); 167*ea9c2605SLucas Stach } 168*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_disable); 169*ea9c2605SLucas Stach 170*ea9c2605SLucas Stach /* 171*ea9c2605SLucas Stach * The channel configuartion functions below are not thread safe, as they 172*ea9c2605SLucas Stach * must be only called from the atomic commit path in the DRM driver, which 173*ea9c2605SLucas Stach * is properly serialized. 174*ea9c2605SLucas Stach */ 175*ea9c2605SLucas Stach static int ipu_prg_ipu_to_prg_chan(int ipu_chan) 176*ea9c2605SLucas Stach { 177*ea9c2605SLucas Stach /* 178*ea9c2605SLucas Stach * This isn't clearly documented in the RM, but IPU to PRG channel 179*ea9c2605SLucas Stach * assignment is fixed, as only with this mapping the control signals 180*ea9c2605SLucas Stach * match up. 181*ea9c2605SLucas Stach */ 182*ea9c2605SLucas Stach switch (ipu_chan) { 183*ea9c2605SLucas Stach case IPUV3_CHANNEL_MEM_BG_SYNC: 184*ea9c2605SLucas Stach return 0; 185*ea9c2605SLucas Stach case IPUV3_CHANNEL_MEM_FG_SYNC: 186*ea9c2605SLucas Stach return 1; 187*ea9c2605SLucas Stach case IPUV3_CHANNEL_MEM_DC_SYNC: 188*ea9c2605SLucas Stach return 2; 189*ea9c2605SLucas Stach default: 190*ea9c2605SLucas Stach return -EINVAL; 191*ea9c2605SLucas Stach } 192*ea9c2605SLucas Stach } 193*ea9c2605SLucas Stach 194*ea9c2605SLucas Stach static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan) 195*ea9c2605SLucas Stach { 196*ea9c2605SLucas Stach int i, ret; 197*ea9c2605SLucas Stach 198*ea9c2605SLucas Stach /* channel 0 is special as it is hardwired to one of the PREs */ 199*ea9c2605SLucas Stach if (prg_chan == 0) { 200*ea9c2605SLucas Stach ret = ipu_pre_get(prg->pres[0]); 201*ea9c2605SLucas Stach if (ret) 202*ea9c2605SLucas Stach goto fail; 203*ea9c2605SLucas Stach prg->chan[prg_chan].used_pre = 0; 204*ea9c2605SLucas Stach return 0; 205*ea9c2605SLucas Stach } 206*ea9c2605SLucas Stach 207*ea9c2605SLucas Stach for (i = 1; i < 3; i++) { 208*ea9c2605SLucas Stach ret = ipu_pre_get(prg->pres[i]); 209*ea9c2605SLucas Stach if (!ret) { 210*ea9c2605SLucas Stach u32 val, mux; 211*ea9c2605SLucas Stach int shift; 212*ea9c2605SLucas Stach 213*ea9c2605SLucas Stach prg->chan[prg_chan].used_pre = i; 214*ea9c2605SLucas Stach 215*ea9c2605SLucas Stach /* configure the PRE to PRG channel mux */ 216*ea9c2605SLucas Stach shift = (i == 1) ? 12 : 14; 217*ea9c2605SLucas Stach mux = (prg->id << 1) | (prg_chan - 1); 218*ea9c2605SLucas Stach regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5, 219*ea9c2605SLucas Stach 0x3 << shift, mux << shift); 220*ea9c2605SLucas Stach 221*ea9c2605SLucas Stach /* check other mux, must not point to same channel */ 222*ea9c2605SLucas Stach shift = (i == 1) ? 14 : 12; 223*ea9c2605SLucas Stach regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val); 224*ea9c2605SLucas Stach if (((val >> shift) & 0x3) == mux) { 225*ea9c2605SLucas Stach regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5, 226*ea9c2605SLucas Stach 0x3 << shift, 227*ea9c2605SLucas Stach (mux ^ 0x1) << shift); 228*ea9c2605SLucas Stach } 229*ea9c2605SLucas Stach 230*ea9c2605SLucas Stach return 0; 231*ea9c2605SLucas Stach } 232*ea9c2605SLucas Stach } 233*ea9c2605SLucas Stach 234*ea9c2605SLucas Stach fail: 235*ea9c2605SLucas Stach dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan); 236*ea9c2605SLucas Stach return ret; 237*ea9c2605SLucas Stach } 238*ea9c2605SLucas Stach 239*ea9c2605SLucas Stach static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan) 240*ea9c2605SLucas Stach { 241*ea9c2605SLucas Stach struct ipu_prg_channel *chan = &prg->chan[prg_chan]; 242*ea9c2605SLucas Stach 243*ea9c2605SLucas Stach ipu_pre_put(prg->pres[chan->used_pre]); 244*ea9c2605SLucas Stach chan->used_pre = -1; 245*ea9c2605SLucas Stach } 246*ea9c2605SLucas Stach 247*ea9c2605SLucas Stach void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan) 248*ea9c2605SLucas Stach { 249*ea9c2605SLucas Stach int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); 250*ea9c2605SLucas Stach struct ipu_prg *prg = ipu_chan->ipu->prg_priv; 251*ea9c2605SLucas Stach struct ipu_prg_channel *chan = &prg->chan[prg_chan]; 252*ea9c2605SLucas Stach u32 val; 253*ea9c2605SLucas Stach 254*ea9c2605SLucas Stach if (!chan->enabled || prg_chan < 0) 255*ea9c2605SLucas Stach return; 256*ea9c2605SLucas Stach 257*ea9c2605SLucas Stach clk_prepare_enable(prg->clk_ipg); 258*ea9c2605SLucas Stach 259*ea9c2605SLucas Stach val = readl(prg->regs + IPU_PRG_CTL); 260*ea9c2605SLucas Stach val |= IPU_PRG_CTL_BYPASS(prg_chan); 261*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_CTL); 262*ea9c2605SLucas Stach 263*ea9c2605SLucas Stach val = IPU_PRG_REG_UPDATE_REG_UPDATE; 264*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_REG_UPDATE); 265*ea9c2605SLucas Stach 266*ea9c2605SLucas Stach clk_disable_unprepare(prg->clk_ipg); 267*ea9c2605SLucas Stach 268*ea9c2605SLucas Stach ipu_prg_put_pre(prg, prg_chan); 269*ea9c2605SLucas Stach 270*ea9c2605SLucas Stach chan->enabled = false; 271*ea9c2605SLucas Stach } 272*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_channel_disable); 273*ea9c2605SLucas Stach 274*ea9c2605SLucas Stach int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan, 275*ea9c2605SLucas Stach unsigned int axi_id, unsigned int width, 276*ea9c2605SLucas Stach unsigned int height, unsigned int stride, 277*ea9c2605SLucas Stach u32 format, unsigned long *eba) 278*ea9c2605SLucas Stach { 279*ea9c2605SLucas Stach int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); 280*ea9c2605SLucas Stach struct ipu_prg *prg = ipu_chan->ipu->prg_priv; 281*ea9c2605SLucas Stach struct ipu_prg_channel *chan = &prg->chan[prg_chan]; 282*ea9c2605SLucas Stach u32 val; 283*ea9c2605SLucas Stach int ret; 284*ea9c2605SLucas Stach 285*ea9c2605SLucas Stach if (prg_chan < 0) 286*ea9c2605SLucas Stach return prg_chan; 287*ea9c2605SLucas Stach 288*ea9c2605SLucas Stach if (chan->enabled) { 289*ea9c2605SLucas Stach ipu_pre_update(prg->pres[chan->used_pre], *eba); 290*ea9c2605SLucas Stach return 0; 291*ea9c2605SLucas Stach } 292*ea9c2605SLucas Stach 293*ea9c2605SLucas Stach ret = ipu_prg_get_pre(prg, prg_chan); 294*ea9c2605SLucas Stach if (ret) 295*ea9c2605SLucas Stach return ret; 296*ea9c2605SLucas Stach 297*ea9c2605SLucas Stach ipu_pre_configure(prg->pres[chan->used_pre], 298*ea9c2605SLucas Stach width, height, stride, format, *eba); 299*ea9c2605SLucas Stach 300*ea9c2605SLucas Stach 301*ea9c2605SLucas Stach ret = clk_prepare_enable(prg->clk_ipg); 302*ea9c2605SLucas Stach if (ret) { 303*ea9c2605SLucas Stach ipu_prg_put_pre(prg, prg_chan); 304*ea9c2605SLucas Stach return ret; 305*ea9c2605SLucas Stach } 306*ea9c2605SLucas Stach 307*ea9c2605SLucas Stach val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK; 308*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan)); 309*ea9c2605SLucas Stach 310*ea9c2605SLucas Stach val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) << 311*ea9c2605SLucas Stach IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) | 312*ea9c2605SLucas Stach ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) << 313*ea9c2605SLucas Stach IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT); 314*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan)); 315*ea9c2605SLucas Stach 316*ea9c2605SLucas Stach val = ipu_pre_get_baddr(prg->pres[chan->used_pre]); 317*ea9c2605SLucas Stach *eba = val; 318*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_BADDR(prg_chan)); 319*ea9c2605SLucas Stach 320*ea9c2605SLucas Stach val = readl(prg->regs + IPU_PRG_CTL); 321*ea9c2605SLucas Stach /* counter load enable */ 322*ea9c2605SLucas Stach val |= IPU_PRG_CTL_CNT_LOAD_EN(prg_chan); 323*ea9c2605SLucas Stach /* config AXI ID */ 324*ea9c2605SLucas Stach val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK << 325*ea9c2605SLucas Stach IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan)); 326*ea9c2605SLucas Stach val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id); 327*ea9c2605SLucas Stach /* enable channel */ 328*ea9c2605SLucas Stach val &= ~IPU_PRG_CTL_BYPASS(prg_chan); 329*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_CTL); 330*ea9c2605SLucas Stach 331*ea9c2605SLucas Stach val = IPU_PRG_REG_UPDATE_REG_UPDATE; 332*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_REG_UPDATE); 333*ea9c2605SLucas Stach 334*ea9c2605SLucas Stach clk_disable_unprepare(prg->clk_ipg); 335*ea9c2605SLucas Stach 336*ea9c2605SLucas Stach chan->enabled = true; 337*ea9c2605SLucas Stach return 0; 338*ea9c2605SLucas Stach } 339*ea9c2605SLucas Stach EXPORT_SYMBOL_GPL(ipu_prg_channel_configure); 340*ea9c2605SLucas Stach 341*ea9c2605SLucas Stach static int ipu_prg_probe(struct platform_device *pdev) 342*ea9c2605SLucas Stach { 343*ea9c2605SLucas Stach struct device *dev = &pdev->dev; 344*ea9c2605SLucas Stach struct resource *res; 345*ea9c2605SLucas Stach struct ipu_prg *prg; 346*ea9c2605SLucas Stach u32 val; 347*ea9c2605SLucas Stach int i, ret; 348*ea9c2605SLucas Stach 349*ea9c2605SLucas Stach prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL); 350*ea9c2605SLucas Stach if (!prg) 351*ea9c2605SLucas Stach return -ENOMEM; 352*ea9c2605SLucas Stach 353*ea9c2605SLucas Stach res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 354*ea9c2605SLucas Stach prg->regs = devm_ioremap_resource(&pdev->dev, res); 355*ea9c2605SLucas Stach if (IS_ERR(prg->regs)) 356*ea9c2605SLucas Stach return PTR_ERR(prg->regs); 357*ea9c2605SLucas Stach 358*ea9c2605SLucas Stach 359*ea9c2605SLucas Stach prg->clk_ipg = devm_clk_get(dev, "ipg"); 360*ea9c2605SLucas Stach if (IS_ERR(prg->clk_ipg)) 361*ea9c2605SLucas Stach return PTR_ERR(prg->clk_ipg); 362*ea9c2605SLucas Stach 363*ea9c2605SLucas Stach prg->clk_axi = devm_clk_get(dev, "axi"); 364*ea9c2605SLucas Stach if (IS_ERR(prg->clk_axi)) 365*ea9c2605SLucas Stach return PTR_ERR(prg->clk_axi); 366*ea9c2605SLucas Stach 367*ea9c2605SLucas Stach prg->iomuxc_gpr = 368*ea9c2605SLucas Stach syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); 369*ea9c2605SLucas Stach if (IS_ERR(prg->iomuxc_gpr)) 370*ea9c2605SLucas Stach return PTR_ERR(prg->iomuxc_gpr); 371*ea9c2605SLucas Stach 372*ea9c2605SLucas Stach for (i = 0; i < 3; i++) { 373*ea9c2605SLucas Stach prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i); 374*ea9c2605SLucas Stach if (!prg->pres[i]) 375*ea9c2605SLucas Stach return -EPROBE_DEFER; 376*ea9c2605SLucas Stach } 377*ea9c2605SLucas Stach 378*ea9c2605SLucas Stach ret = clk_prepare_enable(prg->clk_ipg); 379*ea9c2605SLucas Stach if (ret) 380*ea9c2605SLucas Stach return ret; 381*ea9c2605SLucas Stach 382*ea9c2605SLucas Stach /* init to free running mode */ 383*ea9c2605SLucas Stach val = readl(prg->regs + IPU_PRG_CTL); 384*ea9c2605SLucas Stach val |= IPU_PRG_CTL_SHADOW_EN; 385*ea9c2605SLucas Stach writel(val, prg->regs + IPU_PRG_CTL); 386*ea9c2605SLucas Stach 387*ea9c2605SLucas Stach /* disable address threshold */ 388*ea9c2605SLucas Stach writel(0xffffffff, prg->regs + IPU_PRG_THD); 389*ea9c2605SLucas Stach 390*ea9c2605SLucas Stach clk_disable_unprepare(prg->clk_ipg); 391*ea9c2605SLucas Stach 392*ea9c2605SLucas Stach prg->dev = dev; 393*ea9c2605SLucas Stach platform_set_drvdata(pdev, prg); 394*ea9c2605SLucas Stach mutex_lock(&ipu_prg_list_mutex); 395*ea9c2605SLucas Stach list_add(&prg->list, &ipu_prg_list); 396*ea9c2605SLucas Stach mutex_unlock(&ipu_prg_list_mutex); 397*ea9c2605SLucas Stach 398*ea9c2605SLucas Stach return 0; 399*ea9c2605SLucas Stach } 400*ea9c2605SLucas Stach 401*ea9c2605SLucas Stach static int ipu_prg_remove(struct platform_device *pdev) 402*ea9c2605SLucas Stach { 403*ea9c2605SLucas Stach struct ipu_prg *prg = platform_get_drvdata(pdev); 404*ea9c2605SLucas Stach 405*ea9c2605SLucas Stach mutex_lock(&ipu_prg_list_mutex); 406*ea9c2605SLucas Stach list_del(&prg->list); 407*ea9c2605SLucas Stach mutex_unlock(&ipu_prg_list_mutex); 408*ea9c2605SLucas Stach 409*ea9c2605SLucas Stach return 0; 410*ea9c2605SLucas Stach } 411*ea9c2605SLucas Stach 412*ea9c2605SLucas Stach static const struct of_device_id ipu_prg_dt_ids[] = { 413*ea9c2605SLucas Stach { .compatible = "fsl,imx6qp-prg", }, 414*ea9c2605SLucas Stach { /* sentinel */ }, 415*ea9c2605SLucas Stach }; 416*ea9c2605SLucas Stach 417*ea9c2605SLucas Stach struct platform_driver ipu_prg_drv = { 418*ea9c2605SLucas Stach .probe = ipu_prg_probe, 419*ea9c2605SLucas Stach .remove = ipu_prg_remove, 420*ea9c2605SLucas Stach .driver = { 421*ea9c2605SLucas Stach .name = "imx-ipu-prg", 422*ea9c2605SLucas Stach .of_match_table = ipu_prg_dt_ids, 423*ea9c2605SLucas Stach }, 424*ea9c2605SLucas Stach }; 425