linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
To: David Sin <davidsin@ti.com>
Cc: linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony Lindgren <tony@atomide.com>,
	Hari Kanigeri <h-kanigeri2@ti.com>,
	Ohad Ben-Cohen <ohad@wizery.com>,
	Vaibhav Hiremath <hvaibhav@ti.com>,
	Santosh Shilimkar <santosh.shilimkar@ti.com>,
	Lajos Molnar <molnar@ti.com>
Subject: Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
Date: Sat, 24 Jul 2010 11:15:48 +0100	[thread overview]
Message-ID: <20100724101548.GA16238@n2100.arm.linux.org.uk> (raw)
In-Reply-To: <20100724080915.GC15064@n2100.arm.linux.org.uk>

This is what I'd expect to see.  This uses a hardware-upwards registration
scheme, so by registering a 'dmm' device, when the driver for 'dmm' gets
registered, it automatically registers with the next level up.

However, you should think carefully about this kind of layered approach.
Would it be more appropriate to turn the 'tmm' and higher layers into a
set of library calls for this driver to use, so that they can be reused
with less modifications when other hardware comes along?

#include <linux/errno.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

/* RMK: or whatever path to this... */
#include "tmm.h"
/*
 * RMK: which contains at least something like:
 *
 * struct tmm;
 * int tmm_register(struct tmm **tmm, int (*refill)(struct pat *, enum pat_mode, void *), void *priv);
 * void tmm_unregister(struct tmm *tmm);
 */

#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
#define SET_FLD(reg, msb, lsb, val) \
(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb))))

struct dmm {
	void __iomem *base;
	struct tmm *tmm;
};

static int dmm_wait(void __iomem *reg, unsigned mask, unsigned val, unsigned long timeout)
{
	while ((readl(reg) & mask) != val) {
		if (timeout-- == 0)
			return -ETIMEDOUT;
		udelay(1);
	}
	return 0;
}

static int dmm_refill(struct pat *pat, enum pat_mode mode, void *priv)
{
	struct dmm *dmm = priv;
	int ret;
	u32 v;

	if (mode != PAT_MODE_MANUAL || pat->data & 0x0000000f)
		/* RMK: and maybe check the range of other args */
		return -EINVAL;

	/* Check that the DMM_PAT_STATUS register has not reported an error */
	v = readl(dmm->base + DMM_PAT_STATUS__0);
	if (v & 0xfc00)
		return -EIO;

	/* Set "next" register to 0 */
	/* RMK: not null - hardware doesn't take virtual addresses */
	v = readl(dmm->base + DMM_PAT_DESCR__0);
	v = SET_FLD(v, 31, 4, 0);
	writel(v, dmm->base + DMM_PAT_DESCR__0);

	/* Set area to be refilled */
	v = readl(dmm->base + DMM_PAT_AREA__0) & 0xc000c000;
	v = (pat->area.y1 << 24) | (pat->area.x1 << 16) |
	    (pat->area.y0 << 8) | pat->area.x0;
	writel(v, dmm->base + DMM_PAT_AREA__0);

	/* Clear the DMM_PAT_IRQSTATUS register */
	writel(~0, dmm->base + DMM_PAT_IRQSTATUS);

	ret = dmm_wait(dmm->base + DMM_PAT_IRQSTATUS_RAW), ~0, 0, timeout);
	if (ret)
		return ret;

	/* Fill data register */
	v = readl(dmm->base + DMM_PAT_DATA__0) & 0x0000000f;
	v |= pat->data;
	writel(v, dmm->base + DMM_PAT_DATA__0);

	/*
	 * Read back PAT_DATA__0 to see if write was successful
	 * RMK: shouldn't this just check bits 31-4 ?  Is this just
	 * trying to ensure that the value is written before the next one?
	 * if so, writes to devices are ordered with each other, so this
	 * should not be necessary.
	 */
	ret = dmm_wait(dmm->base + DMM_PAT_DATA__0, ~0, pat->data, timeout);
	if (ret)
		return ret;

	v = readl(dmm->base + DMM_PAT_CTRL__0) & 0x0ffefc8e;
	v |= (pat->ctrl.ini << 28) | (pat->ctrl.sync << 16) |
	     (pat->ctrl.lut_id << 8) | (pat->ctrl.dir << 4) | pat->ctrl.start;
	writel(v, dmm->base + DMM_PAT_CTRL__0);

	/* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled */
	ret = dmm_wait(dmm->base + DMM_PAT_IRQSTATUS_RAW, 3, 3, timeout);
	if (ret)
		return ret;

	/* Clear the DMM_PAT_IRQSTATUS register */
	writel(~0, dmm->base + DMM_PAT_IRQSTATUS);

	ret = dmm_wait(dmm->base + DMM_PAT_IRQSTATUS_RAW, ~0, 0, timeout);
	if (ret)
		return ret;	

	/* Set "next" register to 0 to clear any PAT STATUS errors */
	v = readl(dmm->base + DMM_PAT_DESCR__0);
	v = SET_FLD(v, 31, 4, 0);
	writel(v, dmm->base + DMM_PAT_DESCR__0);

	/*
	 * Now check that the DMM_PAT_STATUS register has not reported an error
	 */
	v = readl(dmm->base + DMM_PAT_STATUS__0);
	if (v & 0xfc00)
		return -EIO;

	return 0;
}

static int dmm_probe(struct platform_device *pdev)
{
	struct resource *res = platform_get_resource(pdev, 0, IORESOURCE_MEM);
	struct dmm *dmm;
	int ret;

	if (!res)
		return -EINVAL;

	if (request_mem_region(res->start, resource_size(res), "dmm")) {
		ret = -EBUSY;
		goto err_region;
	}

	dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
	if (!dmm) {
		ret = -ENOMEM;
		goto err_kzalloc;
	}

	dmm->base = ioremap(res->start, resource_size(res));
	if (!dmm->base) {
		ret = -ENOMEM;
		goto err_ioremap;
	}

	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
	__raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
	__raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);

	/* register with the tiler memory manager */
	ret = tmm_register(&dmm->tmm, dmm_refill, dmm);
	if (ret)
		goto err_tmm_register;

	return 0;

err_tmm_register:
	iounmap(dmm->base);
err_iounmap:
	kfree(dmm);
err_kzalloc:
	release_mem_region(res->start, resource_size(res));
err_region:
	return ret;
}

static void dmm_remove(struct platform_device *pdev)
{
	struct resource *res = platform_get_resource(pdev, 0, IORESOURCE_MEM);
	struct dmm *dmm = platform_get_drvdata(pdev);

	tmm_unregister(dmm->tmm);
	iounmap(dmm->base);
	kfree(dmm);
	release_mem_region(res->start, resource_size(res));
}

static struct platform_driver dmm_driver = {
	.driver = {
		.owner = THIS_MODULE,
		.name = "dmm",
	},
	.probe	= dmm_probe,
	.remove	= dmm_remove,
};

static int __init dmm_init(void)
{
	return platform_driver_register(&dmm_driver);
}
module_init(dmm_init);

static void __exit dmm_exit(void)
{
	platform_driver_unregister(&dmm_driver);
}
module_exit(dmm_exit);

MODULE_AUTHOR("Name <email>");
MODULE_DESCRIPTION("TI OMAP4 tiler hardware driver");
MODULE_LICENSE("GPL v2");


  reply	other threads:[~2010-07-24 10:16 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-23 23:22 [RFC 0/8] TI TILER-DMM driver David Sin
2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
2010-07-23 23:22           ` [RFC 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
2010-07-23 23:22             ` [RFC 7/8] TILER-DMM: Main TILER driver implementation David Sin
2010-07-23 23:22               ` [RFC 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
2010-07-24  7:32               ` [RFC 7/8] TILER-DMM: Main TILER driver implementation Shilimkar, Santosh
2010-07-24 13:41                 ` Hari Kanigeri
2010-07-24 13:53                   ` Shilimkar, Santosh
2010-07-24  7:55               ` Russell King - ARM Linux
2010-07-24  7:21           ` [RFC 5/8] TILER-DMM: TILER interface file and documentation Shilimkar, Santosh
2010-07-24  8:01         ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation Russell King - ARM Linux
2010-07-26 19:34           ` Sin, David
2010-08-02 14:40           ` Sin, David
2010-08-02 14:44             ` Shilimkar, Santosh
2010-08-02 14:49               ` Sin, David
2010-08-02 14:52                 ` Shilimkar, Santosh
2010-08-02 14:55                   ` Sin, David
     [not found]                   ` <9DCA1E44C5805D4EB7C1626D5FD1739E048EDA223B@dlee02.ent.ti.com>
2010-08-03 19:49                     ` Sin, David
2010-07-28  5:53         ` Hiremath, Vaibhav
2010-07-24  7:13       ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator Shilimkar, Santosh
2010-07-25 15:45         ` Molnar, Lajos
2010-07-26 19:33         ` Sin, David
2010-07-27 20:41       ` Hiremath, Vaibhav
2010-07-24  6:56     ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons Shilimkar, Santosh
2010-07-27 20:21     ` Hiremath, Vaibhav
2010-07-24  6:51   ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER Shilimkar, Santosh
2010-07-24  8:09   ` Russell King - ARM Linux
2010-07-24 10:15     ` Russell King - ARM Linux [this message]
2010-07-26 19:28     ` Sin, David
2010-07-27 18:37   ` Hiremath, Vaibhav
2010-07-27 19:05     ` Sin, David
2010-07-27 19:53       ` Hiremath, Vaibhav
2010-07-28 10:00         ` Laurent Pinchart
2010-07-28 14:39           ` Sin, David
2010-07-28 15:46             ` Hiremath, Vaibhav
2010-07-28  9:45       ` Laurent Pinchart
2010-07-24  7:44 ` [RFC 0/8] TI TILER-DMM driver Shilimkar, Santosh
2010-07-26 19:20   ` Sin, David
2010-07-24 11:12 ` Hans Verkuil
2010-07-28 15:23   ` Sin, David
2010-07-28 17:30     ` Hiremath, Vaibhav
2010-07-28 19:15       ` Sin, David
     [not found] <1279927694-26138-1-git-send-email-davidsin@ti.com>
     [not found] ` <1279927694-26138-2-git-send-email-davidsin@ti.com>
     [not found]   ` <201007261013.16666.laurent.pinchart@ideasonboard.com>
2010-07-26 19:59     ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER Sin, David

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100724101548.GA16238@n2100.arm.linux.org.uk \
    --to=linux@arm.linux.org.uk \
    --cc=davidsin@ti.com \
    --cc=h-kanigeri2@ti.com \
    --cc=hvaibhav@ti.com \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-omap@vger.kernel.org \
    --cc=molnar@ti.com \
    --cc=ohad@wizery.com \
    --cc=santosh.shilimkar@ti.com \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).