On Thu, Jun 14, 2012 at 03:43:26PM +0200, Sascha Hauer wrote:
...
> +#include <linux/module.h>
> +#include <linux/export.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/err.h>
> +#include <linux/spinlock.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/list.h>
> +#include <linux/irq.h>
> +#include <mach/common.h>

This seems not needed at all.

> +#include <drm/imx-ipu-v3.h>
> +#include <linux/of_device.h>
> +#include <asm/mach/irq.h>

...

> +void ipu_ch_param_set_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 
> v)

Rename it to ipu_ch_param_write_field ...

> +{
> +     u32 bit = (wbs >> 8) % 160;
> +     u32 size = wbs & 0xff;
> +     u32 word = (wbs >> 8) / 160;
> +     u32 i = bit / 32;
> +     u32 ofs = bit % 32;
> +     u32 mask = (1 << size) - 1;
> +     u32 val;
> +
> +     pr_debug("%s %d %d %d\n", __func__, word, bit , size);
> +
> +     val = readl(&base->word[word].data[i]);
> +     val &= ~(mask << ofs);
> +     val |= v << ofs;
> +     writel(val, &base->word[word].data[i]);
> +
> +     if ((bit + size - 1) / 32 > i) {
> +             val = readl(&base->word[word].data[i + 1]);
> +             val &= ~(mask >> (mask ? (32 - ofs) : 0));
> +             val |= v >> (ofs ? (32 - ofs) : 0);
> +             writel(val, &base->word[word].data[i + 1]);
> +     }
> +}
> +EXPORT_SYMBOL_GPL(ipu_ch_param_set_field);
> +
> +u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs)

... or rename this to ipu_ch_param_get_field for a better couple?

> +{
> +     u32 bit = (wbs >> 8) % 160;
> +     u32 size = wbs & 0xff;
> +     u32 word = (wbs >> 8) / 160;
> +     u32 i = bit / 32;
> +     u32 ofs = bit % 32;
> +     u32 mask = (1 << size) - 1;
> +     u32 val = 0;
> +
> +     pr_debug("%s %d %d %d\n", __func__, word, bit , size);
> +
> +     val = (readl(&base->word[word].data[i]) >> ofs) & mask;
> +
> +     if ((bit + size - 1) / 32 > i) {
> +             u32 tmp;
> +             tmp = readl(&base->word[word].data[i + 1]);
> +             tmp &= mask >> (ofs ? (32 - ofs) : 0);
> +             val |= tmp << (ofs ? (32 - ofs) : 0);
> +     }
> +
> +     return val;
> +}
> +EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);

...

> +static int ipu_reset(struct ipu_soc *ipu)
> +{
> +     int timeout = 10000;

We may want to use a better timeout mechanism.

> +
> +     ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
> +
> +     while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
> +             if (!timeout--)
> +                     return -ETIME;
> +             udelay(100);
> +     }
> +
> +     mdelay(300);
> +
> +     return 0;
> +}

...

> +static int ipu_irq_init(struct ipu_soc *ipu)
> +{
> +     int i;
> +
> +     ipu->irq_start = irq_alloc_descs(-1, 0, IPU_NUM_IRQS, 0);

We may want to give a try on linear irqdomain, so that irqdesc will
only be allocated for those in-use irqs, and we do not have to maintain
irq_base.

> +     if (ipu->irq_start < 0)
> +             return ipu->irq_start;
> +
> +     for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) {
> +             irq_set_chip_and_handler(i, &ipu_irq_chip, handle_level_irq);
> +             set_irq_flags(i, IRQF_VALID);
> +             irq_set_chip_data(i, ipu);
> +     }
> +
> +     irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler);
> +     irq_set_handler_data(ipu->irq_sync, ipu);
> +     irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler);
> +     irq_set_handler_data(ipu->irq_err, ipu);
> +
> +     return 0;
> +}

...

> +static int __devinit ipu_probe(struct platform_device *pdev)
> +{
> +     const struct of_device_id *of_id =
> +                     of_match_device(imx_ipu_dt_ids, &pdev->dev);
> +     struct ipu_soc *ipu;
> +     struct resource *res;
> +     unsigned long ipu_base;
> +     int i, ret, irq_sync, irq_err;
> +     struct ipu_devtype *devtype;
> +
> +     devtype = of_id->data;
> +
> +     dev_info(&pdev->dev, "Initializing %s\n", devtype->name);
> +
> +     irq_sync = platform_get_irq(pdev, 0);
> +     irq_err = platform_get_irq(pdev, 1);
> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +     dev_info(&pdev->dev, "irq_sync: %d irq_err: %d\n",
> +                     irq_sync, irq_err);
> +
> +     if (!res || irq_sync < 0 || irq_err < 0)
> +             return -ENODEV;
> +
> +     ipu_base = res->start;
> +
> +     ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
> +     if (!ipu)
> +             return -ENODEV;
> +
> +     for (i = 0; i < 64; i++)
> +             ipu->channel[i].ipu = ipu;
> +     ipu->devtype = devtype;
> +     ipu->ipu_type = devtype->type;
> +
> +     spin_lock_init(&ipu->lock);
> +     mutex_init(&ipu->channel_lock);
> +
> +     dev_info(&pdev->dev, "cm_reg:   0x%08lx\n",
> +                     ipu_base + devtype->cm_ofs);
> +     dev_info(&pdev->dev, "idmac:    0x%08lx\n",
> +                     ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
> +     dev_info(&pdev->dev, "cpmem:    0x%08lx\n",
> +                     ipu_base + devtype->cpmem_ofs);
> +     dev_info(&pdev->dev, "disp0:    0x%08lx\n",
> +                     ipu_base + devtype->disp0_ofs);
> +     dev_info(&pdev->dev, "disp1:    0x%08lx\n",
> +                     ipu_base + devtype->disp1_ofs);
> +     dev_info(&pdev->dev, "srm:      0x%08lx\n",
> +                     ipu_base + devtype->srm_ofs);
> +     dev_info(&pdev->dev, "tpm:      0x%08lx\n",
> +                     ipu_base + devtype->tpm_ofs);
> +     dev_info(&pdev->dev, "dc:       0x%08lx\n",
> +                     ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
> +     dev_info(&pdev->dev, "ic:       0x%08lx\n",
> +                     ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
> +     dev_info(&pdev->dev, "dmfc:     0x%08lx\n",
> +                     ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
> +
> +     ipu->cm_reg = devm_ioremap(&pdev->dev,
> +                     ipu_base + devtype->cm_ofs, PAGE_SIZE);
> +     ipu->idmac_reg = devm_ioremap(&pdev->dev,
> +                     ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
> +                     PAGE_SIZE);
> +     ipu->cpmem_base = devm_ioremap(&pdev->dev,
> +                     ipu_base + devtype->cpmem_ofs, PAGE_SIZE);
> +
> +     if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) {
> +             ret = -ENOMEM;
> +             goto failed_ioremap;
> +     }
> +
> +     ipu->clk = devm_clk_get(&pdev->dev, "bus");
> +     if (IS_ERR(ipu->clk)) {
> +             ret = PTR_ERR(ipu->clk);
> +             dev_err(&pdev->dev, "clk_get failed with %d", ret);
> +             goto failed_clk_get;
> +     }
> +
> +     platform_set_drvdata(pdev, ipu);
> +
> +     clk_prepare_enable(ipu->clk);
> +
> +     ipu->dev = &pdev->dev;
> +     ipu->irq_sync = irq_sync;
> +     ipu->irq_err = irq_err;
> +
> +     ret = ipu_irq_init(ipu);
> +     if (ret)
> +             goto out_failed_irq;
> +
> +     ipu_reset(ipu);
> +
> +     /* Set MCU_T to divide MCU access window into 2 */
> +     ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
> +                     IPU_DISP_GEN);
> +
> +     ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
> +     if (ret)
> +             goto failed_submodules_init;
> +
> +     ret = ipu_add_client_devices(ipu);
> +     if (ret) {
> +             dev_err(&pdev->dev, "adding client devices failed with %d\n",
> +                             ret);
> +             goto failed_add_clients;
> +     }
> +
> +     return 0;
> +
> +failed_add_clients:
> +     ipu_submodules_exit(ipu);
> +failed_submodules_init:
> +     ipu_irq_exit(ipu);
> +out_failed_irq:

clk_disable_unprepare(ipu->clk);

> +failed_clk_get:
> +failed_ioremap:
> +     return ret;
> +}

-- 
Regards,
Shawn

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to