From ralf@linux-mips.org Tue Jun  1 00:36:19 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 00:36:22 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:56272 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491892Ab0EaWgT (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 00:36:19 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o4VMaFba002915;
        Mon, 31 May 2010 23:36:16 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o4VMaFu3002913;
        Mon, 31 May 2010 23:36:15 +0100
Date:   Mon, 31 May 2010 23:36:14 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     Manuel Lauss <manuel.lauss@googlemail.com>,
        linux-mips <linux-mips@linux-mips.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: Re: [PATCH] mips: fix build with O=...
Message-ID: <20100531223614.GA2789@linux-mips.org>
References: <20100530141939.GA22153@merkur.ravnborg.org>
 <AANLkTilwqYZc9-vtHsdBg1JwIOiYEPBtuRG-Rqg6nxNC@mail.gmail.com>
 <20100531180321.GA27518@merkur.ravnborg.org>
 <AANLkTimRi4FOtJA8xKfD78dBK4rWfFawOsZkACZfhe4g@mail.gmail.com>
 <20100531190011.GA32397@merkur.ravnborg.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100531190011.GA32397@merkur.ravnborg.org>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26949
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
Content-Length: 483
Lines: 14

On Mon, May 31, 2010 at 09:00:11PM +0200, Sam Ravnborg wrote:

> > > Note: On top of my tree since git did not see the
> > > git tree posted by Ralf as a git tree?!?
> > 
> > git://git.linux-mips.org/pub/scm/linux-queue.git works
> color me stupid :-(
> I used git pull xxx instead of git clone xxx.

Be careful - that tree is frequently rebased.  This is also why I keep
it a separate tree - a branch that is rebased has the potencial to
confuse less experienced git users.

  Ralf

From ralf@linux-mips.org Tue Jun  1 00:47:02 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 00:47:05 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:45362 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491892Ab0EaWrC (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 00:47:02 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o4VMkx9F003483;
        Mon, 31 May 2010 23:46:59 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o4VMkwCw003481;
        Mon, 31 May 2010 23:46:58 +0100
Date:   Mon, 31 May 2010 23:46:58 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     Manuel Lauss <manuel.lauss@googlemail.com>,
        linux-mips <linux-mips@linux-mips.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: Re: [PATCH] mips: fix build with O=...
Message-ID: <20100531224658.GB2789@linux-mips.org>
References: <20100530141939.GA22153@merkur.ravnborg.org>
 <AANLkTilwqYZc9-vtHsdBg1JwIOiYEPBtuRG-Rqg6nxNC@mail.gmail.com>
 <20100531180321.GA27518@merkur.ravnborg.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100531180321.GA27518@merkur.ravnborg.org>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26950
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
Content-Length: 487
Lines: 15

On Mon, May 31, 2010 at 08:03:21PM +0200, Sam Ravnborg wrote:

> >From b96ea542b6786a44ab1a70d53a2796bd0d60b521 Mon Sep 17 00:00:00 2001
> From: Sam Ravnborg <sam@ravnborg.org>
> Date: Mon, 31 May 2010 19:58:18 +0200
> Subject: [PATCH] mips: fix build with O=...
> 
> The newly added platform support introduced
> a regression so build with O=... failed.
> 
> Fix this by prefixing Makefile include paths with $(srctree).

Thanks, I've folded this patch into the original patch.

  Ralf

From cernekee@gmail.com Tue Jun  1 02:07:41 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 02:07:44 +0200 (CEST)
Received: from [69.28.251.93] ([69.28.251.93]:41975 "EHLO b32.net"
        rhost-flags-FAIL-FAIL-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492410Ab0FAAHl (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 02:07:41 +0200
Received: (qmail 13323 invoked from network); 1 Jun 2010 00:07:35 -0000
Received: from unknown (HELO vps-1001064-677.cp.jvds.com) (127.0.0.1)
  by 127.0.0.1 with (DHE-RSA-AES128-SHA encrypted) SMTP; 1 Jun 2010 00:07:35 -0000
Received: by vps-1001064-677.cp.jvds.com (sSMTP sendmail emulation); Mon, 31 May 2010 17:07:34 -0700
From:   Kevin Cernekee <cernekee@gmail.com>
To:     <mingo@elte.hu>, <akpm@linux-foundation.org>,
        <simon.kagstrom@netinsight.net>, <David.Woodhouse@intel.com>,
        <rgetz@analog.com>, <lethal@linux-sh.org>
Cc:     <linux-kernel@vger.kernel.org>, <linux-mips@linux-mips.org>
Date:   Mon, 31 May 2010 16:57:15 -0700
Subject: [PATCH v2] printk: fix delayed messages from CPU hotplug events
Message-Id: <ede63b5a20af951c755736f035d1e787772d7c28@localhost>
User-Agent: vim 7.2
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
X-archive-position: 26951
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: cernekee@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
Content-Length: 2380
Lines: 79

When a secondary CPU is being brought up, it is not uncommon for
printk() to be invoked when cpu_online(smp_processor_id()) == 0.  The
case that I witnessed personally was on MIPS:

http://lkml.org/lkml/2010/5/30/4

If (can_use_console() == 0), printk() will spool its output to log_buf
and it will be visible in "dmesg", but that output will NOT be echoed to
the console until somebody calls release_console_sem() from a CPU that
is online.  Therefore, the boot time messages from the new CPU can get
stuck in "limbo" for a long time, and might suddenly appear on the
screen when a completely unrelated event (e.g. "eth0: link is down")
occurs.

This patch modifies the console code so that any pending messages are
automatically flushed out to the console whenever a CPU hotplug
operation completes successfully or aborts.

The issue was seen on 2.6.34.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 kernel/printk.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index 444b770..9c04719 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -37,6 +37,8 @@
 #include <linux/ratelimit.h>
 #include <linux/kmsg_dump.h>
 #include <linux/syslog.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 
@@ -985,6 +987,37 @@ void resume_console(void)
 }
 
 /**
+ * console_cpu_notify - print deferred console messages after CPU hotplug
+ *
+ * If printk() is called from a CPU that is not online yet, the messages
+ * will be spooled but will not show up on the console.  This function is
+ * called when a new CPU comes online and ensures that any such output
+ * gets printed.
+ */
+static int __cpuinit console_cpu_notify(struct notifier_block *self,
+	unsigned long action, void *hcpu)
+{
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_UP_CANCELED:
+		if (try_acquire_console_sem() == 0)
+			release_console_sem();
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata console_nb = {
+	.notifier_call		= console_cpu_notify,
+};
+
+static int __init console_notifier_init(void)
+{
+	register_cpu_notifier(&console_nb);
+	return 0;
+}
+late_initcall(console_notifier_init);
+
+/**
  * acquire_console_sem - lock the console system for exclusive use.
  *
  * Acquires a semaphore which guarantees that the caller has
-- 
1.7.0.4


From lethal@linux-sh.org Tue Jun  1 05:15:51 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 05:15:54 +0200 (CEST)
Received: from 124x34x33x190.ap124.ftth.ucom.ne.jp ([124.34.33.190]:33810 "EHLO
        master.linux-sh.org" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1490966Ab0FADPv (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 05:15:51 +0200
Received: from localhost (unknown [127.0.0.1])
        by master.linux-sh.org (Postfix) with ESMTP id B0F7B636A5;
        Tue,  1 Jun 2010 03:15:28 +0000 (UTC)
X-Virus-Scanned: amavisd-new at linux-sh.org
Received: from master.linux-sh.org ([127.0.0.1])
        by localhost (master.linux-sh.org [127.0.0.1]) (amavisd-new, port 10024)
        with ESMTP id yx52S3st8dNe; Tue,  1 Jun 2010 12:15:28 +0900 (JST)
Received: by master.linux-sh.org (Postfix, from userid 500)
        id 52FC8636AA; Tue,  1 Jun 2010 12:15:28 +0900 (JST)
Date:   Tue, 1 Jun 2010 12:15:28 +0900
From:   Paul Mundt <lethal@linux-sh.org>
To:     Kevin Cernekee <cernekee@gmail.com>
Cc:     mingo@elte.hu, akpm@linux-foundation.org,
        simon.kagstrom@netinsight.net, David.Woodhouse@intel.com,
        rgetz@analog.com, linux-kernel@vger.kernel.org,
        linux-mips@linux-mips.org
Subject: Re: [PATCH v2] printk: fix delayed messages from CPU hotplug events
Message-ID: <20100601031528.GC15411@linux-sh.org>
References: <ede63b5a20af951c755736f035d1e787772d7c28@localhost>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <ede63b5a20af951c755736f035d1e787772d7c28@localhost>
User-Agent: Mutt/1.5.13 (2006-08-11)
X-archive-position: 26952
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lethal@linux-sh.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 9
Content-Length: 1172
Lines: 35

On Mon, May 31, 2010 at 04:57:15PM -0700, Kevin Cernekee wrote:
>  /**
> + * console_cpu_notify - print deferred console messages after CPU hotplug
> + *
> + * If printk() is called from a CPU that is not online yet, the messages
> + * will be spooled but will not show up on the console.  This function is
> + * called when a new CPU comes online and ensures that any such output
> + * gets printed.
> + */
> +static int __cpuinit console_cpu_notify(struct notifier_block *self,
> +	unsigned long action, void *hcpu)
> +{
> +	switch (action) {
> +	case CPU_ONLINE:
> +	case CPU_UP_CANCELED:
> +		if (try_acquire_console_sem() == 0)
> +			release_console_sem();
> +	}
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block __cpuinitdata console_nb = {
> +	.notifier_call		= console_cpu_notify,
> +};
> +
> +static int __init console_notifier_init(void)
> +{
> +	register_cpu_notifier(&console_nb);
> +	return 0;
> +}

If this is to be entirely restricted to CPU hotplug then you could use
the hotcpu notifier here instead of the open-coded cpu notifier directly,
the former wraps to the latter in the CPU hotplug case and is simply a
nop for the regular SMP case.

From cernekee@gmail.com Tue Jun  1 06:04:48 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 06:04:52 +0200 (CEST)
Received: from mail-gw0-f49.google.com ([74.125.83.49]:55629 "EHLO
        mail-gw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1490966Ab0FAEEs (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 06:04:48 +0200
Received: by gwj18 with SMTP id 18so3332645gwj.36
        for <linux-mips@linux-mips.org>; Mon, 31 May 2010 21:04:42 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type;
        bh=FTPEMqlbshwvxP8nhoSIuosdzkPyqrAq2UpG+K3bx54=;
        b=yGHCXY5RY05itXg74s1aTrayPwGvfuc9+X7wmq0izqcslFZu8WIKCYqmsKQH2uD6Eh
         PyDTXkpD8eNntFrwkBqsqfkvqGRT1Ydp9JRbVa8fgnbHvMo8Rmq7S7pFkMBxqLfXOo/F
         VFJgVebLpVEehDehOY83WgjKtail8FOG9zuxE=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type;
        b=NmVK81IWSgYiFmOXAYE7qyDdzZCk7eZPurKR1enPq7KiypjrzDQrMDCISh5M6Nnvus
         G+ZxW2C41jOtI9FY1zrkgDiNCSy3EWsV2YrchVM97y2U4APk3XolJfGy5ymVDo3o0YKJ
         Kq7a/yAKQcOyMDgE9pQo+C+eWwHtmVdqsvFJQ=
MIME-Version: 1.0
Received: by 10.151.3.25 with SMTP id f25mr6003489ybi.183.1275365082679; Mon, 
        31 May 2010 21:04:42 -0700 (PDT)
Received: by 10.150.158.2 with HTTP; Mon, 31 May 2010 21:04:42 -0700 (PDT)
In-Reply-To: <20100601031528.GC15411@linux-sh.org>
References: <ede63b5a20af951c755736f035d1e787772d7c28@localhost>
        <20100601031528.GC15411@linux-sh.org>
Date:   Mon, 31 May 2010 21:04:42 -0700
Message-ID: <AANLkTinY8Htz2bb2I_oN5iWtAjxuDkGzAvX_4TbtmKBh@mail.gmail.com>
Subject: Re: [PATCH v2] printk: fix delayed messages from CPU hotplug events
From:   Kevin Cernekee <cernekee@gmail.com>
To:     Paul Mundt <lethal@linux-sh.org>
Cc:     mingo@elte.hu, akpm@linux-foundation.org,
        simon.kagstrom@netinsight.net, David.Woodhouse@intel.com,
        rgetz@analog.com, linux-kernel@vger.kernel.org,
        linux-mips@linux-mips.org
Content-Type: text/plain; charset=UTF-8
X-archive-position: 26953
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: cernekee@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 42
Content-Length: 1068
Lines: 20

On Mon, May 31, 2010 at 8:15 PM, Paul Mundt <lethal@linux-sh.org> wrote:
> If this is to be entirely restricted to CPU hotplug then you could use
> the hotcpu notifier here instead of the open-coded cpu notifier directly,
> the former wraps to the latter in the CPU hotplug case and is simply a
> nop for the regular SMP case.

I ran some tests and saw the same problem during the regular MIPS SMP
boot.  i.e. adding "while (1) { }" at the end of __cpu_up() prevents
any of the probing/calibration messages originating on CPU1 from ever
being echoed to the console.  Adding the semaphore code before the
while loop caused the CPU1 messages to reappear.

Under normal circumstances you won't ever notice the problem at boot
time, because printing "Brought up %ld CPUs" has the undocumented side
effect of flushing out any messages that got stuck during SMP init.
And if that printk() wasn't there, the next one (from NET, PCI, SCSI,
...) would surely take its place.

But in the case of MIPS CPU hotplug, there is no such printk() at the
end, and so our luck runs out.

From manuel.lauss@googlemail.com Tue Jun  1 08:23:30 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 08:23:35 +0200 (CEST)
Received: from mail-gy0-f177.google.com ([209.85.160.177]:55993 "EHLO
        mail-gy0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492272Ab0FAGXa convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 08:23:30 +0200
Received: by gyb11 with SMTP id 11so3401178gyb.36
        for <linux-mips@linux-mips.org>; Mon, 31 May 2010 23:23:23 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=googlemail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=pYnWup1x8h9RmxGpohV8/ahMYJyWhK1vzu09B9nMgEs=;
        b=lyxqWtC3HFfywp8rM+KZT0olzjeMfrXrWLsyNXtHDFac6d4m0gFRX2E4U3K2+6Qp2G
         LNTESU8tJM0MEo+HMtfs0me3KzktlJvHfJOkYvnDpDf2wel/vsT+l/vK0Tc2kUP1N7TG
         bsLjBeQso9VrAKU+3mcZvvXGfx4aEa+Avr8gU=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=googlemail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=uPc1Th2R7ZUAGJpfw2Ruo25p3OOTprYh5X4QYAssiLanQMHckbQRLwtJGDOqu0ZPsO
         ZHOpJYySOKowfHYVUmtj55+m7Q1GUOSNrKwPGnn1fg7zHI8gRSp/VQzY/zj1vsQ0weRY
         oAa52JlIFGgad21fXAlN6Q4RtpR518Gi8qUWo=
MIME-Version: 1.0
Received: by 10.231.148.143 with SMTP id p15mr7200232ibv.15.1275373401998; 
        Mon, 31 May 2010 23:23:21 -0700 (PDT)
Received: by 10.231.183.74 with HTTP; Mon, 31 May 2010 23:23:21 -0700 (PDT)
In-Reply-To: <20100531211842.GA795@merkur.ravnborg.org>
References: <1275332878-19762-1-git-send-email-manuel.lauss@googlemail.com>
        <20100531211842.GA795@merkur.ravnborg.org>
Date:   Tue, 1 Jun 2010 08:23:21 +0200
Message-ID: <AANLkTilUtwCpTjAdUxLJSjnwUe3i2aKlIrdnQ_ZBH6j5@mail.gmail.com>
Subject: Re: [PATCH -queue] MIPS: Move Alchemy Makefile parts to their own 
        Platform file.
From:   Manuel Lauss <manuel.lauss@googlemail.com>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26954
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: manuel.lauss@googlemail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 96
Content-Length: 1165
Lines: 47

Hi Sam,
On Mon, May 31, 2010 at 11:18 PM, Sam Ravnborg <sam@ravnborg.org> wrote:

>> --- a/arch/mips/Kbuild.platforms
>> +++ b/arch/mips/Kbuild.platforms
>> @@ -1,6 +1,6 @@
>>  # All platforms listed in alphabetic order
>>
>> -platforms += ar7
>> +platforms += alchemy ar7
>
> One line per paltform is better.
> Then the risk for conflicts are less and merging in easier.
> Like this:
>
> platforms += ar7
> platforms += alchemy

Done,


>> diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
>> new file mode 100644
>> index 0000000..1994fdc
>> --- /dev/null
>> +++ b/arch/mips/alchemy/Platform
>> @@ -0,0 +1,103 @@
>> +#
>> +# Common Alchemy Au1x00 stuff
>> +#
>> +core-$(CONFIG_SOC_AU1X00)    += arch/mips/alchemy/common/
>
> The above is actually wrong - despite that it works.
> You are supposed to use:
>
> platform-$(CONFIG_SOC_AU1X00) += alchemy/common/
>
> Then arch/mips/Kbuild will pick it up.
> And then subdirs-ccflags-y := -Werror will also take effect.

Ah, interesting.  I shall look at the full commandline in the future.

I'll do a build of all alchemy boards and resend when there are
no breakages.

Thank you!
     Manuel Lauss

From ralf@linux-mips.org Tue Jun  1 12:28:28 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 12:28:32 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:59417 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492446Ab0FAK22 (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 12:28:28 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o51ASNMN020098;
        Tue, 1 Jun 2010 11:28:24 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o51ASMem020096;
        Tue, 1 Jun 2010 11:28:22 +0100
Date:   Tue, 1 Jun 2010 11:28:22 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     linux-mips <linux-mips@linux-mips.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: Re: [PATCH 0/6] mips: diverse Makefile updates
Message-ID: <20100601102822.GA20578@linux-mips.org>
References: <20100530141939.GA22153@merkur.ravnborg.org>
 <20100530153939.GA22352@merkur.ravnborg.org>
 <20100530231954.GA318@linux-mips.org>
 <20100531102954.GA12669@linux-mips.org>
 <20100531105550.GA15995@merkur.ravnborg.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100531105550.GA15995@merkur.ravnborg.org>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26955
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 243
Content-Length: 3194
Lines: 89

On Mon, May 31, 2010 at 12:55:50PM +0200, Sam Ravnborg wrote:

> > I played with it for a bit.  The warning is present in all gcc 4.1.0 to
> > 4.1.2 and it is bogus.  When I first looked into this years ago I just
> > gave up on gcc 4.1 as a newer version was already available.
> > 
> > The variable returned by get_user is undefined in case of an error, so
> > what get_user() is doing is entirely legitimate.  This is different from
> > copy_from_user() which in case of an error will clear the remainder of
> > the destination area which couldn't not be copied from userspace.
> 
> What I looked at:
> 
> 1)	u32 word;
> 2)	if (unlikely(get_user(word, header)))
> 3)		word = 0;
> 4)	if (word == magic.cmp)
> 5)		return PAGE_SIZE;
> 
> If gcc does not see an assignment to word in line 2) then
> it complains about the use line 4).
> 
> If we look at the implementation of get_user it is more or less the
> following:
> ({
> 	int err = -EFAULT;
> 	if (access_ok(VERIFY_READ, header))
> 		switch (sizeof(word)) {
> 		case 4:
> 			word = *(u32 *)header;
> 			err = 0;
> 			break;
> 		default:
> 			__get_user_unknown();
> 			break;
> 		}
> 	err;
> })
> 
> Simplified a lot - I know. But it shows my point.
> (And simplifying the code also helped me understand the macros).
> 
> gcc needs to be smart enough to deduce that we always return != 0
> in the cases where word is not assigned - in which case line 3)
> will do the assignment.
> 
> So gcc is indeed wrong when is sas "uninitialized" but considering
> the complexity of these macros I think it is excused.
> 
> The x86 version has the following assignment
> 
>     (val) = (__typeof__(*(addr))) __gu_tmp; 
> 
> unconditionally - so they avoid the " = 0" thing.
> sparc has explicit "= 0" assignments.
> 
> So refactoring the macros may do the trick too.
> But I do not think it is worth the effort.

One reason for the being written as they are is also that this allows a
compiler to generate some useful warnings such as:

	get_user(var, ptr);
	printk("var is %d\n", var);

Where var indeed can be used uninitialzed.  The return value of get_user()
being ignored is really a separate problem which should be attacked as
well.  __must_check would be the obvious way of doing this but it can only
be used as a function attribute.  Will have to experiment to see if it's
possible to use it within get_user / put_user in something like:

static inline int __must_check __gu_must_check(int __gu_err)
{
	return __gu_err
}

#define __get_user_check(x, ptr, size)                                  \
({                                                                      \
        int __gu_err = -EFAULT;                                         \
        const __typeof__(*(ptr)) __user * __gu_ptr = (ptr);             \
                                                                        \
        might_fault();                                                  \
        if (likely(access_ok(VERIFY_READ,  __gu_ptr, size)))            \
                __get_user_common((x), size, __gu_ptr);                 \
                                                                        \
        __gu_must_check(__gu_err);					\
})

  Ralf

From wuzhangjin@gmail.com Tue Jun  1 12:29:26 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 12:29:31 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:39762 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492446Ab0FAK30 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 12:29:26 +0200
Received: by pvb32 with SMTP id 32so272261pvb.36
        for <multiple recipients>; Tue, 01 Jun 2010 03:29:19 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=7RkLAXuKIo4YJyC8BZN6L4kqn1Uxz5zp+LzdXdzUumE=;
        b=J20+H5TYzFcECGNKjl2jIlWvy4U9arjQ39ivNpEpCfOaAFrOcERkpRCRPDesqTCU0+
         OeKe1e9L9QE43zeyspvG/g3rNsv59PXgzncMmybfh9qQqeni0ckpk9KkKfS7Z3JeQomp
         Dv4rV81QlatsXfnayZEJDvskRgDpVauGj5lhA=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=P5x9qKr3AK/ahtevLaOZ7WCoce8EkJv8JQFBiRm8ydY517UD0ys52y73WatjW0WsMa
         BqlDA3F6UFkppvu6YcffIqCXn/9ywcztID0LQXX1HBUSE/iQrxLqST1dKXQvzghILIsK
         m/axuON4ZB2X6kUg6PlqJCW9O5Z4+jMifC/wE=
Received: by 10.142.152.18 with SMTP id z18mr3904649wfd.230.1275388159243;
        Tue, 01 Jun 2010 03:29:19 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id s21sm1917785wff.0.2010.06.01.03.29.16
        (version=SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 03:29:18 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH] MIPS: arch/mips/boot/compressed/Makefile: Unify the suffix of compressed vmlinux.bin
Date:   Tue,  1 Jun 2010 18:29:02 +0800
Message-Id: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26956
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 247
Content-Length: 1661
Lines: 43

The compressed vmlinux.{gz,bz2,lzo,lzma} are only temp files, we can use the
same suffix for them to remove several lines and simpify the maintaining.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/boot/compressed/Makefile |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 74a52d7..7204dfc 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -48,23 +48,19 @@ OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
 $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
 	$(call if_changed,objcopy)
 
-suffix_$(CONFIG_KERNEL_GZIP)  = gz
-suffix_$(CONFIG_KERNEL_BZIP2) = bz2
-suffix_$(CONFIG_KERNEL_LZMA)  = lzma
-suffix_$(CONFIG_KERNEL_LZO)   = lzo
 tool_$(CONFIG_KERNEL_GZIP)    = gzip
 tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
 tool_$(CONFIG_KERNEL_LZMA)    = lzma
 tool_$(CONFIG_KERNEL_LZO)     = lzo
 
-targets += vmlinux.gz vmlinux.bz2 vmlinux.lzma vmlinux.lzo
-$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin FORCE
+targets += vmlinux.z
+$(obj)/vmlinux.z: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,$(tool_y))
 
 targets += piggy.o
-OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.$(suffix_y) \
+OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.z \
                         --set-section-flags=.image=contents,alloc,load,readonly,data
-$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.$(suffix_y) FORCE
+$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.z FORCE
 	$(call if_changed,objcopy)
 
 LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
-- 
1.6.5


From wuzhangjin@gmail.com Tue Jun  1 12:29:30 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 12:29:56 +0200 (CEST)
Received: from mail-pw0-f49.google.com ([209.85.160.49]:63434 "EHLO
        mail-pw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492452Ab0FAK3a (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 12:29:30 +0200
Received: by pwi2 with SMTP id 2so2057080pwi.36
        for <multiple recipients>; Tue, 01 Jun 2010 03:29:22 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer:in-reply-to:references;
        bh=emctOUKEn+iy1TkXJRdM+dlh3SpjtNeoDxNEFkn6qNU=;
        b=ti20Es49VjjAoG3uyoFUek3jdS8sNqKdxASSNo7KQ5Qt10rHj6eWT5WcHCslgy90yr
         1ER2t0i+T0o3HjtSMCdLd4plCMo2ghk60igHQUFxDKU5c0kCLavb8yERjQjAPo+6vRZH
         J3K2ZGOg9pOPIyFYXCbXYFOieYhia7df2keck=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;
        b=KisT23J6ZjpHpPyAHPmsohu7Vl/5iP7MxRRZGuy4qD73IDHzi8rYTrUeuGVRfhcTP7
         lMEZ50ENgqb1C65ubldtL9A5aPq9Gs92Jz8f8Y9Y/u9WIQKp+1nZgHJ3D1tXEykoFgWj
         QLWSLfsyg8OnohVoyrfU3JC6IUEujX4HWF2fk=
Received: by 10.143.20.39 with SMTP id x39mr3884508wfi.236.1275388162178;
        Tue, 01 Jun 2010 03:29:22 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id s21sm1917785wff.0.2010.06.01.03.29.19
        (version=SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 03:29:21 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
Date:   Tue,  1 Jun 2010 18:29:03 +0800
Message-Id: <1275388144-5998-2-git-send-email-wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
In-Reply-To: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
X-archive-position: 26957
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 248
Content-Length: 4346
Lines: 128

We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is awful. This patch
rewrites it in C.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/boot/.gitignore                          |    1 +
 arch/mips/boot/compressed/Makefile                 |   22 ++++-----
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   52 ++++++++++++++++++++
 3 files changed, 63 insertions(+), 12 deletions(-)
 create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c

diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
index 4667a5f..f210b09 100644
--- a/arch/mips/boot/.gitignore
+++ b/arch/mips/boot/.gitignore
@@ -3,3 +3,4 @@ elf2ecoff
 vmlinux.*
 zImage
 zImage.tmp
+calc_vmlinuz_load_addr
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 7204dfc..cd9ee04 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -12,14 +12,6 @@
 # Author: Wu Zhangjin <wuzhangjin@gmail.com>
 #
 
-# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
-VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
-VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
-# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE"
-HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10)))
-LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8)
-VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32))))
-
 # set the default size of the mallocing area for decompressing
 BOOT_HEAP_SIZE := 0x400000
 
@@ -63,9 +55,15 @@ OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.z \
 $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.z FORCE
 	$(call if_changed,objcopy)
 
-LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
-vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
-	$(call cmd,ld)
+# Calculate the load address of the compressed kernel
+hostprogs-y := calc_vmlinuz_load_addr
+
+vmlinuzobjs-y += $(obj)/piggy.o
+
+quiet_cmd_zld = LD      $@
+      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(shell $(obj)/calc_vmlinuz_load_addr $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -T $< $(vmlinuzobjs-y) -o $@
+vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
+	$(call cmd,zld)
 	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@
 
 #
@@ -76,7 +74,7 @@ ifdef CONFIG_MACH_DECSTATION
 endif
 
 # elf2ecoff can only handle 32bit image
-hostprogs-y := ../elf2ecoff
+hostprogs-y += ../elf2ecoff
 
 ifdef CONFIG_32BIT
 	VMLINUZ = vmlinuz
diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
new file mode 100644
index 0000000..1787dce
--- /dev/null
+++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 "Wu Zhangjin" <wuzhangjin@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+	int n;
+	struct stat sb;
+	unsigned long long vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
+				argv[0]);
+		return -1;
+	}
+
+	if (stat(argv[1], &sb) == -1) {
+		perror("stat");
+		return -1;
+	}
+
+	/* Convert hex characters to dec number */
+	errno = 0;
+	n = sscanf(argv[2], "%llx", &vmlinux_load_addr);
+	if (n != 1) {
+		if (errno != 0)
+			perror("sscanf");
+		else
+			fprintf(stderr, "No matching characters\n");
+	}
+
+	vmlinux_size = (unsigned long long)sb.st_size;
+	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
+
+	/* Align with 65536 */
+	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);
+
+	printf("0x%llx\n", vmlinuz_load_addr);
+
+	return 0;
+}
-- 
1.6.5


From wuzhangjin@gmail.com Tue Jun  1 12:29:32 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 12:30:21 +0200 (CEST)
Received: from mail-pw0-f49.google.com ([209.85.160.49]:59983 "EHLO
        mail-pw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492455Ab0FAK3c (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 12:29:32 +0200
Received: by pwi2 with SMTP id 2so2057117pwi.36
        for <multiple recipients>; Tue, 01 Jun 2010 03:29:25 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer:in-reply-to:references;
        bh=DTRM7Z0rUHfTz4mm2pdrcJAfbOb89zG6CKiwcsBUivI=;
        b=GYoZvKHmYVDVB8v/bQQiB4aL8xYiR/Dff9ATa60bI8LYxnjyCaO+dJftD7Nc1T2V/W
         vgIQLR6msznspFvRGe4F9v9sr1h30BvGzOLQxnWfZby6xvO2PzedZ1qUcJMckJfC/akB
         1Ukmr54PMBBI8xNqgPrc4qMaaHCzpoHz1SWs8=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;
        b=qJLIu7lY9JB8j9PEsv8AWk6nSU7Ymi5fFASftp/BsTeAwUm4woyS43FcF0eBwnAg7H
         6MVYVwBVrRnwfZ2slagRD6MxqAaefwXF+7sFgFGq1nqinteMb2QLI1qKgbr7iWbvjF2W
         V/UveauXKblvbqEahKmGa2o1EwmqwAqZ+7Ifo=
Received: by 10.142.74.3 with SMTP id w3mr3847482wfa.243.1275388165934;
        Tue, 01 Jun 2010 03:29:25 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id s21sm1917785wff.0.2010.06.01.03.29.22
        (version=SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 03:29:24 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH] MIPS: Move Loongson Makefile parts to their own Platform file
Date:   Tue,  1 Jun 2010 18:29:04 +0800
Message-Id: <1275388144-5998-3-git-send-email-wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
In-Reply-To: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
X-archive-position: 26958
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 249
Content-Length: 4089
Lines: 108

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/Kbuild.platforms  |    1 +
 arch/mips/Makefile          |   29 -----------------------------
 arch/mips/loongson/Platform |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 33 insertions(+), 29 deletions(-)
 create mode 100644 arch/mips/loongson/Platform

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 681b2d4..9784c49 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -1,6 +1,7 @@
 # All platforms listed in alphabetic order
 
 platforms += ar7
+platforms += loongson
 
 # include the platform specific files
 include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index ff71a54..14b755d 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -130,26 +130,6 @@ cflags-$(CONFIG_CPU_R4300)	+= -march=r4300 -Wa,--trap
 cflags-$(CONFIG_CPU_VR41XX)	+= -march=r4100 -Wa,--trap
 cflags-$(CONFIG_CPU_R4X00)	+= -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_TX49XX)	+= -march=r4600 -Wa,--trap
-# only gcc >= 4.4 have the loongson-specific support
-cflags-$(CONFIG_CPU_LOONGSON2)	+= -Wa,--trap
-cflags-$(CONFIG_CPU_LOONGSON2E) += \
-	$(call cc-option,-march=loongson2e,-march=r4600)
-cflags-$(CONFIG_CPU_LOONGSON2F) += \
-	$(call cc-option,-march=loongson2f,-march=r4600)
-# enable the workarounds for loongson2f
-ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
-  ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-nop,),)
-    $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-nop)
-  else
-    cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-nop
-  endif
-  ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-jump,),)
-    $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-jump)
-  else
-    cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-jump
-  endif
-endif
-
 cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
@@ -346,15 +326,6 @@ cflags-$(CONFIG_WR_PPMC)		+= -I$(srctree)/arch/mips/include/asm/mach-wrppmc
 load-$(CONFIG_WR_PPMC)		+= 0xffffffff80100000
 
 #
-# Loongson family
-#
-core-$(CONFIG_MACH_LOONGSON) += arch/mips/loongson/
-cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson \
-                    -mno-branch-likely
-load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
-load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
-
-#
 # MIPS Malta board
 #
 core-$(CONFIG_MIPS_MALTA)	+= arch/mips/mti-malta/
diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
new file mode 100644
index 0000000..29692e5
--- /dev/null
+++ b/arch/mips/loongson/Platform
@@ -0,0 +1,32 @@
+#
+# Loongson Processors' Support
+#
+
+# Only gcc >= 4.4 have Loongson specific support
+cflags-$(CONFIG_CPU_LOONGSON2)	+= -Wa,--trap
+cflags-$(CONFIG_CPU_LOONGSON2E) += \
+	$(call cc-option,-march=loongson2e,-march=r4600)
+cflags-$(CONFIG_CPU_LOONGSON2F) += \
+	$(call cc-option,-march=loongson2f,-march=r4600)
+# Enable the workarounds for Loongson2f
+ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
+  ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-nop,),)
+    $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-nop)
+  else
+    cflags-$(CONFIG_CPU_NOP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-nop
+  endif
+  ifeq ($(call as-option,-Wa$(comma)-mfix-loongson2f-jump,),)
+    $(error only binutils >= 2.20.2 have needed option -mfix-loongson2f-jump)
+  else
+    cflags-$(CONFIG_CPU_JUMP_WORKAROUNDS) += -Wa$(comma)-mfix-loongson2f-jump
+  endif
+endif
+
+#
+# Loongson Machines' Support
+#
+
+platform-$(CONFIG_MACH_LOONGSON) += loongson/
+cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
+load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
+load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
-- 
1.6.5


From alex@digriz.org.uk Tue Jun  1 12:56:08 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 12:56:12 +0200 (CEST)
Received: from chipmunk.wormnet.eu ([195.195.131.226]:49007 "EHLO
        chipmunk.wormnet.eu" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1492309Ab0FAK4I (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 12:56:08 +0200
Received: by chipmunk.wormnet.eu (Postfix, from userid 1000)
        id F087383871; Tue,  1 Jun 2010 11:56:06 +0100 (BST)
Date:   Tue, 1 Jun 2010 11:56:06 +0100
From:   Alexander Clouter <alex@digriz.org.uk>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: Re: [PATCH] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
Message-ID: <20100601105606.GD2519@chipmunk>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com> <1275388144-5998-2-git-send-email-wuzhangjin@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275388144-5998-2-git-send-email-wuzhangjin@gmail.com>
Organization: diGriz
X-URL:  http://www.digriz.org.uk/
X-JabberID: alex@digriz.org.uk
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26959
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: alex@digriz.org.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 265
Content-Length: 5669
Lines: 158

Hi,

* Wu Zhangjin <wuzhangjin@gmail.com> [2010-06-01 18:29:03+0800]:
>
> We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is awful. This patch
> rewrites it in C.
> 
I really feel that going down the C route is even worse....what's more 
this implementation is broken as it always returns with zero, even when 
sscanf() fails....and 'return -1' is just plain wrong too (look at 
sysexits.h for wisdom[1]).

What is so 'awful' about the shell code version?

The shell lump is shorter in implementation size and I am personally not 
convinced any reasons hinting towards 'clarity' even apply as the shell 
code is well documented plus it is trivial to step through on any POSIX 
shell implementation; which cannot be said for the C code.  I am also 
not too confident 'unsigned long long' is a great idea...maybe 'u64' or 
'uint64_t' if you are relying on C99[1]?

Wise man says, do not use cannonball to kill mosquito :)

Cheers

[1] http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
[2] http://gcc.gnu.org/onlinedocs/gcc/Long-Long.html

> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> ---
>  arch/mips/boot/.gitignore                          |    1 +
>  arch/mips/boot/compressed/Makefile                 |   22 ++++-----
>  arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   52 ++++++++++++++++++++
>  3 files changed, 63 insertions(+), 12 deletions(-)
>  create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
> 
> diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
> index 4667a5f..f210b09 100644
> --- a/arch/mips/boot/.gitignore
> +++ b/arch/mips/boot/.gitignore
> @@ -3,3 +3,4 @@ elf2ecoff
>  vmlinux.*
>  zImage
>  zImage.tmp
> +calc_vmlinuz_load_addr
> diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
> index 7204dfc..cd9ee04 100644
> --- a/arch/mips/boot/compressed/Makefile
> +++ b/arch/mips/boot/compressed/Makefile
> @@ -12,14 +12,6 @@
>  # Author: Wu Zhangjin <wuzhangjin@gmail.com>
>  #
>  
> -# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
> -VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
> -VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
> -# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE"
> -HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10)))
> -LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8)
> -VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32))))
> -
>  # set the default size of the mallocing area for decompressing
>  BOOT_HEAP_SIZE := 0x400000
>  
> @@ -63,9 +55,15 @@ OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.z \
>  $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.z FORCE
>  	$(call if_changed,objcopy)
>  
> -LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
> -vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
> -	$(call cmd,ld)
> +# Calculate the load address of the compressed kernel
> +hostprogs-y := calc_vmlinuz_load_addr
> +
> +vmlinuzobjs-y += $(obj)/piggy.o
> +
> +quiet_cmd_zld = LD      $@
> +      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(shell $(obj)/calc_vmlinuz_load_addr $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -T $< $(vmlinuzobjs-y) -o $@
> +vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
> +	$(call cmd,zld)
>  	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@
>  
>  #
> @@ -76,7 +74,7 @@ ifdef CONFIG_MACH_DECSTATION
>  endif
>  
>  # elf2ecoff can only handle 32bit image
> -hostprogs-y := ../elf2ecoff
> +hostprogs-y += ../elf2ecoff
>  
>  ifdef CONFIG_32BIT
>  	VMLINUZ = vmlinuz
> diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
> new file mode 100644
> index 0000000..1787dce
> --- /dev/null
> +++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (C) 2010 "Wu Zhangjin" <wuzhangjin@gmail.com>
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +int main(int argc, char *argv[])
> +{
> +	int n;
> +	struct stat sb;
> +	unsigned long long vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
> +
> +	if (argc != 3) {
> +		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
> +				argv[0]);
> +		return -1;
> +	}
> +
> +	if (stat(argv[1], &sb) == -1) {
> +		perror("stat");
> +		return -1;
> +	}
> +
> +	/* Convert hex characters to dec number */
> +	errno = 0;
> +	n = sscanf(argv[2], "%llx", &vmlinux_load_addr);
> +	if (n != 1) {
> +		if (errno != 0)
> +			perror("sscanf");
> +		else
> +			fprintf(stderr, "No matching characters\n");
> +	}
> +
> +	vmlinux_size = (unsigned long long)sb.st_size;
> +	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
> +
> +	/* Align with 65536 */
> +	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);
> +
> +	printf("0x%llx\n", vmlinuz_load_addr);
> +
> +	return 0;
> +}
> -- 
> 1.6.5
> 

-- 
Alexander Clouter
.sigmonster says: To teach is to learn twice.
                  		-- Joseph Joubert

From wuzhangjin@gmail.com Tue Jun  1 14:41:26 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 14:41:29 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:42939 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492343Ab0FAMl0 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 14:41:26 +0200
Received: by pvb32 with SMTP id 32so315436pvb.36
        for <multiple recipients>; Tue, 01 Jun 2010 05:41:18 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type;
        bh=0dhJQ0YSJZUrzGK930jFriY0BmyXHCur8EFPHilL0kI=;
        b=Hud5kIHOgJZ/7SImi25O1nYriFmvhEmuslBaQDRLibZRqE+Tw3+wkB1NW2ktZc+SnO
         wC2eoOlNvZOQi4apSj/7IZhHeAjIjBBHSc5Tsufd7M8iek3eu+E9Tis7rUopZdJhJmWq
         YZB5hcxGm4HslOGLoytFL5Ja+72SHLgLKVn6c=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type;
        b=Nqoacu3v1c2uvCPpskq4lneIoUmsnzbZwTKu5vhMLd+8mx8AI+WXn4NcxsIvm9/5Yz
         cEy2snsZl6OwElnh9vXh9hCVCqaCtqwJvHVr8KxCirqbiZyz08FNruz5hYwOdHs4vLFL
         uFe7LCnr613eA/bWdgR1W0zS8zn91YKSYxiS0=
MIME-Version: 1.0
Received: by 10.142.10.39 with SMTP id 39mr4044802wfj.63.1275396078512; Tue, 
        01 Jun 2010 05:41:18 -0700 (PDT)
Received: by 10.142.179.7 with HTTP; Tue, 1 Jun 2010 05:41:18 -0700 (PDT)
In-Reply-To: <AANLkTikxHLWSoUFQItXnULP-pF1-us7FgAP_GkkoCMeO@mail.gmail.com>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
        <1275388144-5998-2-git-send-email-wuzhangjin@gmail.com>
        <20100601105606.GD2519@chipmunk>
        <AANLkTikxHLWSoUFQItXnULP-pF1-us7FgAP_GkkoCMeO@mail.gmail.com>
Date:   Tue, 1 Jun 2010 20:41:18 +0800
Message-ID: <AANLkTila1Lb360v9XaeKJxBqcPR6wZ_kIbEm7k_23UFs@mail.gmail.com>
Subject: Re: [PATCH] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
From:   wu zhangjin <wuzhangjin@gmail.com>
To:     Alexander Clouter <alex@digriz.org.uk>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Content-Type: text/plain; charset=ISO-8859-1
X-archive-position: 26960
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 322
Content-Length: 257
Lines: 14

Hi,

[...]
>> I am also
>> not too confident 'unsigned long long' is a great idea...maybe 'u64' or
>> 'uint64_t' if you are relying on C99[1]?
>
> good idea, which c header file defines u64 and uint64_t?
>

Just found it in <stdint.h>

Regards,
Wu Zhangjin

From alex@digriz.org.uk Tue Jun  1 14:42:29 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 14:42:35 +0200 (CEST)
Received: from chipmunk.wormnet.eu ([195.195.131.226]:47665 "EHLO
        chipmunk.wormnet.eu" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1492343Ab0FAMm3 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 14:42:29 +0200
Received: by chipmunk.wormnet.eu (Postfix, from userid 1000)
        id B7B7883871; Tue,  1 Jun 2010 13:42:28 +0100 (BST)
Date:   Tue, 1 Jun 2010 13:42:28 +0100
From:   Alexander Clouter <alex@digriz.org.uk>
To:     wu zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: Re: [PATCH] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
Message-ID: <20100601124228.GI2519@chipmunk>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com> <1275388144-5998-2-git-send-email-wuzhangjin@gmail.com> <20100601105606.GD2519@chipmunk> <AANLkTikxHLWSoUFQItXnULP-pF1-us7FgAP_GkkoCMeO@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <AANLkTikxHLWSoUFQItXnULP-pF1-us7FgAP_GkkoCMeO@mail.gmail.com>
Organization: diGriz
X-URL:  http://www.digriz.org.uk/
X-JabberID: alex@digriz.org.uk
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26961
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: alex@digriz.org.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 323
Content-Length: 2257
Lines: 57

Hi,

* wu zhangjin <wuzhangjin@gmail.com> [2010-06-01 20:26:23+0800]:
>
> On Tue, Jun 1, 2010 at 6:56 PM, Alexander Clouter <alex@digriz.org.uk> wrote:
> >
> > * Wu Zhangjin <wuzhangjin@gmail.com> [2010-06-01 18:29:03+0800]:
> >>
> >> We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is awful. This patch
> >> rewrites it in C.
> >>
> > I really feel that going down the C route is even worse....what's more
> > this implementation is broken as it always returns with zero, even when
> > sscanf() fails....and 'return -1' is just plain wrong too (look at
> > sysexits.h for wisdom[1]).
> 
> ooh, Sorry, Just found I have forgotten one "return", and for
> portability, will use exit(EXIT_SUCCESS) and exit(EXIT_FAILURE)
> instead later.
>
I *think* 'return EXIT_SUCCESS' is just as good if not better, as you 
have 'int main()' as your entry point...or whatever it is called.
 
> > What is so 'awful' about the shell code version?
> 
> From my point of view, it looks not good at least, and also not good
> for maintaining.
>
Well, I guess I as you are the maintaining, what ever you says 
goes...more importantly whatever you are more comfortable with also.
 
> > The shell lump is shorter in implementation size and I am personally not
> > convinced any reasons hinting towards 'clarity' even apply as the shell
> > code is well documented plus it is trivial to step through on any POSIX
> > shell implementation; which cannot be said for the C code.
> 
> I like shell too, herein, it is really shorter but is also hard to
> understand, and of course, we need to ensure "unsigned long long" is
> at least 64bit wide, I have tested it on my thinkpad SL400 laptop(X86)
> and my Yeeloong netbook(MIPS), both of them works well.
> 
> > I am also not too confident 'unsigned long long' is a great 
> > idea...maybe 'u64' or 'uint64_t' if you are relying on C99[1]?
> 
> good idea, which c header file defines u64 and uint64_t?
>
Wackipedia claims[1] that for C99 you want stdint.h, a quick grep of my 
/usr/include directory agrees too.  It seems that you want 'uint64_t' 
too and not 'u64' which is Linux only...or something.
 
Cheers

[1] http://en.wikipedia.org/wiki/Stdint.h

-- 
Alexander Clouter
.sigmonster says: Gibble, Gobble, we ACCEPT YOU ...

From wuzhangjin@gmail.com Tue Jun  1 15:12:31 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 15:12:35 +0200 (CEST)
Received: from mail-px0-f177.google.com ([209.85.212.177]:52357 "EHLO
        mail-px0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492349Ab0FANMb (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 15:12:31 +0200
Received: by pxi1 with SMTP id 1so2070074pxi.36
        for <multiple recipients>; Tue, 01 Jun 2010 06:12:21 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=GWvSWRV9Qk29VyHeoYIIOJjN0RhDnyHELyjnw8CGeQk=;
        b=buLO1Z74ulpQ/wdXe1L+ZOtbmywb+Q58rRu4sLabBRHT9tKoROBZCrVFHTMqLZ0I5D
         JIVq0e2k6ex1iYp/kFhUFXEdCClqOYZxmpeeVeTrJjzBXxQN8VGyYVhwlGazfO1RkZTf
         FZN1FoWEqEToS4WivhKoqwtn0UJwHZ9Igr5OU=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=kb2P4X5g0rCUR8uB04oTruJWM0q5PiZ4eJyXyuvlmORZaAPFf+A/kMR7v17bO1lQ0f
         wYHVWEdvdCEzeb4CdDIuwFmM5v3fDVmtlFNjAlgerTJsxo5MBG+2GCr2oSPwQqYYzXcj
         D3RUIYUT/TFXDplCHVzkOSGHU9BVKZrtQiF8M=
Received: by 10.141.106.21 with SMTP id i21mr4506764rvm.40.1275397940955;
        Tue, 01 Jun 2010 06:12:20 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id i19sm5220005rvn.23.2010.06.01.06.12.17
        (version=SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 06:12:20 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH v2] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
Date:   Tue,  1 Jun 2010 21:11:56 +0800
Message-Id: <1275397916-6401-1-git-send-email-wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26962
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 342
Content-Length: 4709
Lines: 140

Changes:

v1 -> v2:
  o make it more portable (feedback from Alexander Clouter)
    use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
    instead of "unsigned long long".
  o add a missing return value (feedback from Alexander Clouter)
    return EXIT_FAILURE if (n != 1).

We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is awful. This patch
rewrites it in C.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/boot/.gitignore                          |    1 +
 arch/mips/boot/compressed/Makefile                 |   22 ++++----
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   55 ++++++++++++++++++++
 3 files changed, 66 insertions(+), 12 deletions(-)
 create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c

diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
index 4667a5f..f210b09 100644
--- a/arch/mips/boot/.gitignore
+++ b/arch/mips/boot/.gitignore
@@ -3,3 +3,4 @@ elf2ecoff
 vmlinux.*
 zImage
 zImage.tmp
+calc_vmlinuz_load_addr
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 7204dfc..cd9ee04 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -12,14 +12,6 @@
 # Author: Wu Zhangjin <wuzhangjin@gmail.com>
 #
 
-# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
-VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
-VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
-# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE"
-HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10)))
-LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8)
-VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32))))
-
 # set the default size of the mallocing area for decompressing
 BOOT_HEAP_SIZE := 0x400000
 
@@ -63,9 +55,15 @@ OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.z \
 $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.z FORCE
 	$(call if_changed,objcopy)
 
-LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
-vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
-	$(call cmd,ld)
+# Calculate the load address of the compressed kernel
+hostprogs-y := calc_vmlinuz_load_addr
+
+vmlinuzobjs-y += $(obj)/piggy.o
+
+quiet_cmd_zld = LD      $@
+      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(shell $(obj)/calc_vmlinuz_load_addr $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -T $< $(vmlinuzobjs-y) -o $@
+vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
+	$(call cmd,zld)
 	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@
 
 #
@@ -76,7 +74,7 @@ ifdef CONFIG_MACH_DECSTATION
 endif
 
 # elf2ecoff can only handle 32bit image
-hostprogs-y := ../elf2ecoff
+hostprogs-y += ../elf2ecoff
 
 ifdef CONFIG_32BIT
 	VMLINUZ = vmlinuz
diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
new file mode 100644
index 0000000..81176b1
--- /dev/null
+++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 "Wu Zhangjin" <wuzhangjin@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+	int n;
+	struct stat sb;
+	uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
+				argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	if (stat(argv[1], &sb) == -1) {
+		perror("stat");
+		return EXIT_FAILURE;
+	}
+
+	/* Convert hex characters to dec number */
+	errno = 0;
+	n = sscanf(argv[2], "%llx", &vmlinux_load_addr);
+	if (n != 1) {
+		if (errno != 0)
+			perror("sscanf");
+		else
+			fprintf(stderr, "No matching characters\n");
+
+		return EXIT_FAILURE;
+	}
+
+	vmlinux_size = (unsigned long long)sb.st_size;
+	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
+
+	/* Align with 65536 */
+	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);
+
+	printf("0x%llx\n", vmlinuz_load_addr);
+
+	return EXIT_SUCCESS;
+}
-- 
1.6.5


From ralf@linux-mips.org Tue Jun  1 15:13:44 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 15:13:49 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:45861 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492349Ab0FANNo (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 15:13:44 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o51DDHp4023529;
        Tue, 1 Jun 2010 14:13:17 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o51DDHrk023527;
        Tue, 1 Jun 2010 14:13:17 +0100
Date:   Tue, 1 Jun 2010 14:13:17 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     linux-mips <linux-mips@linux-mips.org>,
        Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: Re: [PATCH] MIPS: Move Loongson Makefile parts to their own Platform
 file
Message-ID: <20100601131316.GA23270@linux-mips.org>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
 <1275388144-5998-3-git-send-email-wuzhangjin@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275388144-5998-3-git-send-email-wuzhangjin@gmail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26963
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 343
Content-Length: 99
Lines: 5

On Tue, Jun 01, 2010 at 06:29:04PM +0800, Wu Zhangjin wrote:

Thanks Wu, queued for 2.6.36.

 Ralf

From alex@digriz.org.uk Tue Jun  1 15:41:54 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 15:41:58 +0200 (CEST)
Received: from chipmunk.wormnet.eu ([195.195.131.226]:38495 "EHLO
        chipmunk.wormnet.eu" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1492352Ab0FANly (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 15:41:54 +0200
Received: by chipmunk.wormnet.eu (Postfix, from userid 1000)
        id 720B183871; Tue,  1 Jun 2010 14:41:53 +0100 (BST)
Date:   Tue, 1 Jun 2010 14:41:53 +0100
From:   Alexander Clouter <alex@digriz.org.uk>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: Re: [PATCH v2] MIPS: Clean up the calculation of
        VMLINUZ_LOAD_ADDRESS
Message-ID: <20100601134153.GK2519@chipmunk>
References: <1275397916-6401-1-git-send-email-wuzhangjin@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275397916-6401-1-git-send-email-wuzhangjin@gmail.com>
Organization: diGriz
X-URL:  http://www.digriz.org.uk/
X-JabberID: alex@digriz.org.uk
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26964
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: alex@digriz.org.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 372
Content-Length: 1813
Lines: 66

Hi,

* Wu Zhangjin <wuzhangjin@gmail.com> [2010-06-01 21:11:56+0800]:
>
> Changes:
> 
> v1 -> v2:
>   o make it more portable (feedback from Alexander Clouter)
>     use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
>     instead of "unsigned long long".
>   o add a missing return value (feedback from Alexander Clouter)
>     return EXIT_FAILURE if (n != 1).
> 
> We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is awful. This patch
> rewrites it in C.
> 
s/awful/indecipherable/

:)

> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> ---
>  arch/mips/boot/.gitignore                          |    1 +
>  arch/mips/boot/compressed/Makefile                 |   22 ++++----
>  arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   55 ++++++++++++++++++++
>  3 files changed, 66 insertions(+), 12 deletions(-)
>  create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
> 
> diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
> new file mode 100644
> index 0000000..81176b1
> --- /dev/null
> +++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
> @@ -0,0 +1,55 @@
>
> [snipped]
>
> +
> +	/* Convert hex characters to dec number */
> +	errno = 0;
> +	n = sscanf(argv[2], "%llx", &vmlinux_load_addr);
> +	if (n != 1) {
>
you can drop the 'n' with:

if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) {

> +		if (errno != 0)
> +			perror("sscanf");
> +		else
> +			fprintf(stderr, "No matching characters\n");
> +
> +		return EXIT_FAILURE;
> +	}
> +
> +	vmlinux_size = (unsigned long long)sb.st_size;
>
I'm guessing this should probably be uint64_t also?

Other than that, makes me happy :)

Cheers

-- 
Alexander Clouter
.sigmonster says: And furthermore, my bowling average is unimpeachable!!!

From wuzhangjin@gmail.com Tue Jun  1 15:55:24 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 15:55:31 +0200 (CEST)
Received: from mail-pw0-f49.google.com ([209.85.160.49]:64159 "EHLO
        mail-pw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492468Ab0FANzY convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 15:55:24 +0200
Received: by pwi2 with SMTP id 2so2134889pwi.36
        for <multiple recipients>; Tue, 01 Jun 2010 06:55:17 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=nn03zRJJNROxRp77PEkebJSUxcejSKUg++yHEB+ylcI=;
        b=JFiFnSKy/UZaclhoJjch8fN3SFq7V+mT/zZEJvSICQ/Zf7TMz65ZBy1lWzhnGDUBEK
         RBwyEfAlJvOyG2ejbVQbEqZFucvS6n/z2FscfzJO266MIrUFuLoTsga+N6R1wToJN0VE
         NHeGUVUBfJ+5VjmkmwTRGAhKso5/Ub6cdP1jI=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=LveJY8XVTyyqk8b9Dkg1cheGx1q21b9rto6AgQ3fI1v1L4F+x4wTvUt93WxoDHyIMc
         lCAdSR74i90lwWTvq2gJ6/SkI30pBZJRMfpwbJMYm92LUmBacjOJ3wGe3yIjzvECBKyw
         3UueKc4ddkTdNykdF6O45FlvoMvWozwJiDe2A=
MIME-Version: 1.0
Received: by 10.142.67.27 with SMTP id p27mr4171673wfa.139.1275400207761; Tue, 
        01 Jun 2010 06:50:07 -0700 (PDT)
Received: by 10.142.179.7 with HTTP; Tue, 1 Jun 2010 06:50:07 -0700 (PDT)
In-Reply-To: <20100601134153.GK2519@chipmunk>
References: <1275397916-6401-1-git-send-email-wuzhangjin@gmail.com>
        <20100601134153.GK2519@chipmunk>
Date:   Tue, 1 Jun 2010 21:50:07 +0800
Message-ID: <AANLkTin_DI1LBRLlLa-01kDmnk94b1Or1zHmiMQDscDY@mail.gmail.com>
Subject: Re: [PATCH v2] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
From:   wu zhangjin <wuzhangjin@gmail.com>
To:     Alexander Clouter <alex@digriz.org.uk>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26965
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 392
Content-Length: 2446
Lines: 81

v3 is ready ;)

On Tue, Jun 1, 2010 at 9:41 PM, Alexander Clouter <alex@digriz.org.uk> wrote:
> Hi,
>
> * Wu Zhangjin <wuzhangjin@gmail.com> [2010-06-01 21:11:56+0800]:
>>
>> Changes:
>>
>> v1 -> v2:
>>   o make it more portable (feedback from Alexander Clouter)
>>     use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
>>     instead of "unsigned long long".
>>   o add a missing return value (feedback from Alexander Clouter)
>>     return EXIT_FAILURE if (n != 1).
>>
>> We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is awful. This patch
>> rewrites it in C.
>>
> s/awful/indecipherable/
>
> :)
>
>> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
>> ---
>>  arch/mips/boot/.gitignore                          |    1 +
>>  arch/mips/boot/compressed/Makefile                 |   22 ++++----
>>  arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   55 ++++++++++++++++++++
>>  3 files changed, 66 insertions(+), 12 deletions(-)
>>  create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
>>
>> diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
>> new file mode 100644
>> index 0000000..81176b1
>> --- /dev/null
>> +++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
>> @@ -0,0 +1,55 @@
>>
>> [snipped]
>>
>> +
>> +     /* Convert hex characters to dec number */
>> +     errno = 0;
>> +     n = sscanf(argv[2], "%llx", &vmlinux_load_addr);
>> +     if (n != 1) {
>>
> you can drop the 'n' with:
>
> if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) {
>
>> +             if (errno != 0)
>> +                     perror("sscanf");
>> +             else
>> +                     fprintf(stderr, "No matching characters\n");
>> +
>> +             return EXIT_FAILURE;
>> +     }
>> +
>> +     vmlinux_size = (unsigned long long)sb.st_size;
>>
> I'm guessing this should probably be uint64_t also?
>
> Other than that, makes me happy :)
>
> Cheers
>
> --
> Alexander Clouter
> .sigmonster says: And furthermore, my bowling average is unimpeachable!!!
>



-- 
Studying engineer. Wu Zhangjin
Lanzhou University      http://www.lzu.edu.cn
Distributed & Embedded System Lab      http://dslab.lzu.edu.cn
School of Information Science and Engeneering         http://xxxy.lzu.edu.cn
wuzhangjin@gmail.com         http://falcon.oss.lzu.edu.cn
Address:Tianshui South Road 222,Lanzhou,P.R.China    Zip Code:730000
Tel:+86-931-8912025

From wuzhangjin@gmail.com Tue Jun  1 16:07:06 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 16:07:15 +0200 (CEST)
Received: from mail-pz0-f197.google.com ([209.85.222.197]:35038 "EHLO
        mail-pz0-f197.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492234Ab0FAOHG (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 16:07:06 +0200
Received: by pzk35 with SMTP id 35so474410pzk.0
        for <multiple recipients>; Tue, 01 Jun 2010 07:06:59 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=15XhFgG+Xt3hL/WzqBltvEce5BFqRH0kJxhculSR288=;
        b=F3lja6nReYhD9ouH9W/nMcbyp6ZIZIoij7obc0KL+1assFXI6cfFvGGdwS14AOuT+t
         Oq+4iwEZ9vn7oAqixdkCYBUECSA83mx1BlZ1cKdZo9wjQX/8COnnF6LWnItSHcWevtjc
         R1j55tK3uJsn4p22nM+0Zsi/PypoXIGME1bHo=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=E666EF98wisY9thLSLqohqE6Knr/RVd9iXBm4NxZJ6y7JNFf39CQCmKU1UbM3ePfDG
         RqxUsg26Tg0VwlMHZJzOf1f8bMrNyxyJ9X8mYvKC8lF78VPqkuEQHYoHLq4s0odVVZjV
         Ua4jwnCiuxmGqS34bT4Wt1tYPxqK+zv42yg9A=
Received: by 10.115.64.5 with SMTP id r5mr4875888wak.180.1275401219180;
        Tue, 01 Jun 2010 07:06:59 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id f11sm59675190wai.23.2010.06.01.07.06.55
        (version=SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 07:06:58 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH v3] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
Date:   Tue,  1 Jun 2010 22:06:41 +0800
Message-Id: <616317d6d889537d03c3c0860231da9a2cce0b69.1275372093.git.wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26966
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 401
Content-Length: 4800
Lines: 142

Changes:

v2 -> v3: (feedback from Alexander Clouter)
  o Drop the unneeded variable n
  o Replace the last "unsigned long long" by uint64_t

v1 -> v2: (feedback from Alexander Clouter)
  o make it more portable
    use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
    instead of "unsigned long long".
  o add a missing return value
    return EXIT_FAILURE if sscanf not return 1.

We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is indecipherable. This
patch rewrites it in C.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/boot/.gitignore                          |    1 +
 arch/mips/boot/compressed/Makefile                 |   22 ++++-----
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   53 ++++++++++++++++++++
 3 files changed, 64 insertions(+), 12 deletions(-)
 create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c

diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
index 4667a5f..f210b09 100644
--- a/arch/mips/boot/.gitignore
+++ b/arch/mips/boot/.gitignore
@@ -3,3 +3,4 @@ elf2ecoff
 vmlinux.*
 zImage
 zImage.tmp
+calc_vmlinuz_load_addr
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 7204dfc..cd9ee04 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -12,14 +12,6 @@
 # Author: Wu Zhangjin <wuzhangjin@gmail.com>
 #
 
-# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
-VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
-VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
-# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE"
-HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10)))
-LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8)
-VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32))))
-
 # set the default size of the mallocing area for decompressing
 BOOT_HEAP_SIZE := 0x400000
 
@@ -63,9 +55,15 @@ OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.z \
 $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.z FORCE
 	$(call if_changed,objcopy)
 
-LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
-vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
-	$(call cmd,ld)
+# Calculate the load address of the compressed kernel
+hostprogs-y := calc_vmlinuz_load_addr
+
+vmlinuzobjs-y += $(obj)/piggy.o
+
+quiet_cmd_zld = LD      $@
+      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(shell $(obj)/calc_vmlinuz_load_addr $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -T $< $(vmlinuzobjs-y) -o $@
+vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
+	$(call cmd,zld)
 	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@
 
 #
@@ -76,7 +74,7 @@ ifdef CONFIG_MACH_DECSTATION
 endif
 
 # elf2ecoff can only handle 32bit image
-hostprogs-y := ../elf2ecoff
+hostprogs-y += ../elf2ecoff
 
 ifdef CONFIG_32BIT
 	VMLINUZ = vmlinuz
diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
new file mode 100644
index 0000000..d3c57d5
--- /dev/null
+++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 "Wu Zhangjin" <wuzhangjin@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+	struct stat sb;
+	uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
+				argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	if (stat(argv[1], &sb) == -1) {
+		perror("stat");
+		return EXIT_FAILURE;
+	}
+
+	/* Convert hex characters to dec number */
+	errno = 0;
+	if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) {
+		if (errno != 0)
+			perror("sscanf");
+		else
+			fprintf(stderr, "No matching characters\n");
+
+		return EXIT_FAILURE;
+	}
+
+	vmlinux_size = (uint64_t)sb.st_size;
+	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
+
+	/* Align with 65536 */
+	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);
+
+	printf("0x%llx\n", vmlinuz_load_addr);
+
+	return EXIT_SUCCESS;
+}
-- 
1.6.5


From manuel.lauss@googlemail.com Tue Jun  1 17:23:29 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 17:23:34 +0200 (CEST)
Received: from mail-fx0-f49.google.com ([209.85.161.49]:45419 "EHLO
        mail-fx0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492486Ab0FAPX3 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 17:23:29 +0200
Received: by fxm15 with SMTP id 15so3848868fxm.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 08:23:24 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=googlemail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=thkr8vKBxcqz3CYIZl/7GAUvD98nF6Cf19Q7/hX00sM=;
        b=Gy5v/f3dMwTFH2D8lDUNfqvAFExOwSjQ9BoeG8JoCHNWTtJHQodlsJYoGSjd387p0T
         h8TRV3uQbu++5bafxjoJaMbqYmMn9xOSLiJAhWfXkPfBV3SSsKRaWfzMyUNKrHcsQAFj
         EydcLmGS5d4Ju8ZwoNvCG65m//yFUi5dkMdM8=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=googlemail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=DuOnGaAr82kM/dqNwiWaNGj1JS6yuv+7YXr9iaYbkRt1dV186dNzsGvDA4K67QJnTc
         ddrOLfC81K1Rw9V39+Zbsb4vB1dVJaGR2t616HVa1NdK6Xs0JVVpn4JH57plPbWizHic
         qNiJ00IHAM3XI3bglq5/J7eomMI/tSYJMUa/w=
Received: by 10.223.10.11 with SMTP id n11mr7276256fan.3.1275405803860;
        Tue, 01 Jun 2010 08:23:23 -0700 (PDT)
Received: from localhost.localdomain (p5496CC84.dip.t-dialin.net [84.150.204.132])
        by mx.google.com with ESMTPS id g10sm47570505fai.12.2010.06.01.08.23.21
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 08:23:22 -0700 (PDT)
From:   Manuel Lauss <manuel.lauss@googlemail.com>
To:     Linux-MIPS <linux-mips@linux-mips.org>
Cc:     Manuel Lauss <manuel.lauss@googlemail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: [PATCH -queue v2] MIPS: Move Alchemy Makefile parts to their own Platform file.
Date:   Tue,  1 Jun 2010 17:23:15 +0200
Message-Id: <1275405795-9009-1-git-send-email-manuel.lauss@googlemail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26967
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: manuel.lauss@googlemail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 459
Content-Length: 8883
Lines: 284

Cc: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
On top of latest mips-queue.  The changes to the mtx1/xx1500 Makefiles were
necessary to work around vmlinux link failures.

 arch/mips/Kbuild.platforms         |    1 +
 arch/mips/Makefile                 |  105 ----------------------------------
 arch/mips/alchemy/Platform         |  109 ++++++++++++++++++++++++++++++++++++
 arch/mips/alchemy/mtx-1/Makefile   |    3 +-
 arch/mips/alchemy/xxs1500/Makefile |    2 +-
 5 files changed, 112 insertions(+), 108 deletions(-)
 create mode 100644 arch/mips/alchemy/Platform

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 9784c49..dc2bac5 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -1,5 +1,6 @@
 # All platforms listed in alphabetic order
 
+platforms += alchemy
 platforms += ar7
 platforms += loongson
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 14b755d..b191730 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -199,111 +199,6 @@ cflags-$(CONFIG_MACH_JAZZ)	+= -I$(srctree)/arch/mips/include/asm/mach-jazz
 load-$(CONFIG_MACH_JAZZ)	+= 0xffffffff80080000
 
 #
-# Common Alchemy Au1x00 stuff
-#
-core-$(CONFIG_SOC_AU1X00)	+= arch/mips/alchemy/common/
-
-#
-# AMD Alchemy Pb1000 eval board
-#
-core-$(CONFIG_MIPS_PB1000)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1000)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1100 eval board
-#
-core-$(CONFIG_MIPS_PB1100)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1100)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1500 eval board
-#
-core-$(CONFIG_MIPS_PB1500)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1500)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1550 eval board
-#
-core-$(CONFIG_MIPS_PB1550)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1550)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1200 eval board
-#
-core-$(CONFIG_MIPS_PB1200)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1200)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1000 eval board
-#
-core-$(CONFIG_MIPS_DB1000)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1000)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1100 eval board
-#
-core-$(CONFIG_MIPS_DB1100)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1100)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1500 eval board
-#
-core-$(CONFIG_MIPS_DB1500)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1500)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1550 eval board
-#
-core-$(CONFIG_MIPS_DB1550)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1550)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1200 eval board
-#
-core-$(CONFIG_MIPS_DB1200)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1200)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Bosporus eval board
-#
-core-$(CONFIG_MIPS_BOSPORUS)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_BOSPORUS)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_BOSPORUS)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Mirage eval board
-#
-core-$(CONFIG_MIPS_MIRAGE)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_MIRAGE)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_MIRAGE)	+= 0xffffffff80100000
-
-#
-# 4G-Systems eval board
-#
-libs-$(CONFIG_MIPS_MTX1)	+= arch/mips/alchemy/mtx-1/
-load-$(CONFIG_MIPS_MTX1)	+= 0xffffffff80100000
-
-#
-# MyCable eval board
-#
-libs-$(CONFIG_MIPS_XXS1500)	+= arch/mips/alchemy/xxs1500/
-load-$(CONFIG_MIPS_XXS1500)	+= 0xffffffff80100000
-
-# must be last for Alchemy systems for GPIO to work properly
-cflags-$(CONFIG_SOC_AU1X00)	+= -I$(srctree)/arch/mips/include/asm/mach-au1x00
-
-
-#
 # Cobalt Server
 #
 core-$(CONFIG_MIPS_COBALT)	+= arch/mips/cobalt/
diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
new file mode 100644
index 0000000..495cc9a
--- /dev/null
+++ b/arch/mips/alchemy/Platform
@@ -0,0 +1,109 @@
+#
+# Core Alchemy code
+#
+platform-$(CONFIG_MACH_ALCHEMY)	+= alchemy/common/
+
+
+#
+# AMD Alchemy Pb1000 eval board
+#
+platform-$(CONFIG_MIPS_PB1000)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1000)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1100 eval board
+#
+platform-$(CONFIG_MIPS_PB1100)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1100)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1500 eval board
+#
+platform-$(CONFIG_MIPS_PB1500)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1500)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1550 eval board
+#
+platform-$(CONFIG_MIPS_PB1550)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1550)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1200 eval board
+#
+platform-$(CONFIG_MIPS_PB1200)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1200)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1000 eval board
+#
+platform-$(CONFIG_MIPS_DB1000)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1000)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1100 eval board
+#
+platform-$(CONFIG_MIPS_DB1100)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1100)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1500 eval board
+#
+platform-$(CONFIG_MIPS_DB1500)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1500)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1550 eval board
+#
+platform-$(CONFIG_MIPS_DB1550)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1550)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1200 eval board
+#
+platform-$(CONFIG_MIPS_DB1200)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1200)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Bosporus eval board
+#
+platform-$(CONFIG_MIPS_BOSPORUS) += alchemy/devboards/
+cflags-$(CONFIG_MIPS_BOSPORUS)	 += -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_BOSPORUS)	 += 0xffffffff80100000
+
+#
+# AMD Alchemy Mirage eval board
+#
+platform-$(CONFIG_MIPS_MIRAGE)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_MIRAGE)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_MIRAGE)	+= 0xffffffff80100000
+
+#
+# 4G-Systems eval board
+#
+platform-$(CONFIG_MIPS_MTX1)	+= alchemy/mtx-1/
+load-$(CONFIG_MIPS_MTX1)	+= 0xffffffff80100000
+
+#
+# MyCable eval board
+#
+platform-$(CONFIG_MIPS_XXS1500)	+= alchemy/xxs1500/
+load-$(CONFIG_MIPS_XXS1500)	+= 0xffffffff80100000
+
+
+# boards can specify their own <gpio.h> in one of their include dirs.
+# If they do, placing this line here at the end will make sure the
+# compiler picks the board one.  If they don't, it will make sure
+# the alchemy generic gpio header is picked up.
+
+cflags-$(CONFIG_MACH_ALCHEMY)	+= -I$(srctree)/arch/mips/include/asm/mach-au1x00
diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
index 4a53815..4d1367e 100644
--- a/arch/mips/alchemy/mtx-1/Makefile
+++ b/arch/mips/alchemy/mtx-1/Makefile
@@ -6,7 +6,6 @@
 # Makefile for 4G Systems MTX-1 board.
 #
 
-lib-y := init.o board_setup.o
-obj-y := platform.o
+obj-y := init.o board_setup.o platform.o
 
 EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile
index 4dc81d7..346bdb0 100644
--- a/arch/mips/alchemy/xxs1500/Makefile
+++ b/arch/mips/alchemy/xxs1500/Makefile
@@ -5,6 +5,6 @@
 # Makefile for MyCable XXS1500 board.
 #
 
-lib-y := init.o board_setup.o platform.o
+obj-y := init.o board_setup.o platform.o
 
 EXTRA_CFLAGS += -Werror
-- 
1.7.1


From sam@ravnborg.org Tue Jun  1 17:28:03 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 17:28:08 +0200 (CEST)
Received: from pqueueb.post.tele.dk ([193.162.153.10]:36708 "EHLO
        pqueueb.post.tele.dk" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1491130Ab0FAP2D (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 17:28:03 +0200
Received: from pfepb.post.tele.dk (pfepb.post.tele.dk [195.41.46.236])
        by pqueueb.post.tele.dk (Postfix) with ESMTP id D6B5E830D;
        Tue,  1 Jun 2010 17:28:02 +0200 (CEST)
Received: from merkur.ravnborg.org (x1-6-00-1e-2a-84-ae-3e.k225.webspeed.dk [80.163.61.94])
        by pfepb.post.tele.dk (Postfix) with ESMTP id 33DB6F84048;
        Tue,  1 Jun 2010 17:27:50 +0200 (CEST)
Date:   Tue, 1 Jun 2010 17:27:50 +0200
From:   Sam Ravnborg <sam@ravnborg.org>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>
Subject: Re: [PATCH v3] MIPS: Clean up the calculation of
        VMLINUZ_LOAD_ADDRESS
Message-ID: <20100601152750.GA5131@merkur.ravnborg.org>
References: <616317d6d889537d03c3c0860231da9a2cce0b69.1275372093.git.wuzhangjin@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <616317d6d889537d03c3c0860231da9a2cce0b69.1275372093.git.wuzhangjin@gmail.com>
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26968
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: sam@ravnborg.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 463
Content-Length: 3482
Lines: 112

On Tue, Jun 01, 2010 at 10:06:41PM +0800, Wu Zhangjin wrote:
> Changes:
> 
> v2 -> v3: (feedback from Alexander Clouter)
>   o Drop the unneeded variable n
>   o Replace the last "unsigned long long" by uint64_t
> 
> v1 -> v2: (feedback from Alexander Clouter)
>   o make it more portable
>     use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
>     instead of "unsigned long long".
>   o add a missing return value
>     return EXIT_FAILURE if sscanf not return 1.
> 
> We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is indecipherable. This
> patch rewrites it in C.

I prefer the C version too as it allow better abstraction
and easier to understand calculations.

> diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
> index 4667a5f..f210b09 100644
> --- a/arch/mips/boot/.gitignore
> +++ b/arch/mips/boot/.gitignore
> @@ -3,3 +3,4 @@ elf2ecoff
>  vmlinux.*
>  zImage
>  zImage.tmp
> +calc_vmlinuz_load_addr

Does this do any good in this file?
I had assumed this covered only the same dir as the .gitignore file
is stored. But I may be wrong.

> diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
> index 7204dfc..cd9ee04 100644
> --- a/arch/mips/boot/compressed/Makefile
> +++ b/arch/mips/boot/compressed/Makefile
>  
> -LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
> -vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
> -	$(call cmd,ld)
> +# Calculate the load address of the compressed kernel
> +hostprogs-y := calc_vmlinuz_load_addr
> +
> +vmlinuzobjs-y += $(obj)/piggy.o
> +
> +quiet_cmd_zld = LD      $@
> +      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(shell $(obj)/calc_vmlinuz_load_addr $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -T $< $(vmlinuzobjs-y) -o $@

The line seriously fail the 80 char limit.
Something like this:

load_addr = $(shell $(obj)/calc_vmlinuz_load_addr \
                    $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)
quiet_cmd_zld = LD      $@
      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(load-addr) -T $< $(vmlinuzobjs-y) -o $@

Note: The load_addr local variable _must_ use "=" asignment

> +vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
> +	$(call cmd,zld)
>  	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@

Does objcopy support equally named input and out files?
If this is the case you could use:
$(call cmd,objcopy) as the last line.

> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <errno.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +int main(int argc, char *argv[])
> +{
> +	struct stat sb;
> +	uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
> +
> +	if (argc != 3) {
> +		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
> +				argv[0]);
> +		return EXIT_FAILURE;
> +	}
> +
> +	if (stat(argv[1], &sb) == -1) {
> +		perror("stat");
> +		return EXIT_FAILURE;
> +	}
> +
> +	/* Convert hex characters to dec number */
> +	errno = 0;
> +	if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) {
> +		if (errno != 0)
> +			perror("sscanf");
> +		else
> +			fprintf(stderr, "No matching characters\n");
> +
> +		return EXIT_FAILURE;
> +	}
> +
> +	vmlinux_size = (uint64_t)sb.st_size;
> +	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
> +
> +	/* Align with 65536 */
> +	vmlinuz_load_addr += (65536 - vmlinux_size % 65536);

You have plenty of rooms for a comment about why you do this.
Would be good to use this possibility.

	Sam

From sam@ravnborg.org Tue Jun  1 18:35:43 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 18:35:50 +0200 (CEST)
Received: from pqueuea.post.tele.dk ([193.162.153.9]:35291 "EHLO
        pqueuea.post.tele.dk" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1491190Ab0FAQfn (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 18:35:43 +0200
Received: from pfepb.post.tele.dk (pfepb.post.tele.dk [195.41.46.236])
        by pqueuea.post.tele.dk (Postfix) with ESMTP id 2FEEFDBBFA
        for <linux-mips@linux-mips.org>; Tue,  1 Jun 2010 18:35:42 +0200 (CEST)
Received: from merkur.ravnborg.org (x1-6-00-1e-2a-84-ae-3e.k225.webspeed.dk [80.163.61.94])
        by pfepb.post.tele.dk (Postfix) with ESMTP id 44931F84031;
        Tue,  1 Jun 2010 18:35:28 +0200 (CEST)
Date:   Tue, 1 Jun 2010 18:35:28 +0200
From:   Sam Ravnborg <sam@ravnborg.org>
To:     Manuel Lauss <manuel.lauss@googlemail.com>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue v2] MIPS: Move Alchemy Makefile parts to their
        own Platform file.
Message-ID: <20100601163528.GA5216@merkur.ravnborg.org>
References: <1275405795-9009-1-git-send-email-manuel.lauss@googlemail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275405795-9009-1-git-send-email-manuel.lauss@googlemail.com>
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26969
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: sam@ravnborg.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 503
Content-Length: 1421
Lines: 45

On Tue, Jun 01, 2010 at 05:23:15PM +0200, Manuel Lauss wrote:
> Cc: Sam Ravnborg <sam@ravnborg.org>
> Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
> ---
> On top of latest mips-queue.  The changes to the mtx1/xx1500 Makefiles were
> necessary to work around vmlinux link failures.

Was this something the platform patches introduced or
is it needed to fix the build?
In the first case I have broken something I need to fix.
In the latter case this should be a seperate patch (that comes first).

> diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
> new file mode 100644
> index 0000000..495cc9a
> --- /dev/null
> +++ b/arch/mips/alchemy/Platform

...
> +#
> +# 4G-Systems eval board
> +#
> +platform-$(CONFIG_MIPS_MTX1)	+= alchemy/mtx-1/
> +load-$(CONFIG_MIPS_MTX1)	+= 0xffffffff80100000

> diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
> index 4a53815..4d1367e 100644
> --- a/arch/mips/alchemy/mtx-1/Makefile
> +++ b/arch/mips/alchemy/mtx-1/Makefile
> @@ -6,7 +6,6 @@
>  # Makefile for 4G Systems MTX-1 board.
>  #
>  
> -lib-y := init.o board_setup.o
> -obj-y := platform.o
> +obj-y := init.o board_setup.o platform.o
>  
>  EXTRA_CFLAGS += -Werror

In the above we added alchemy/mtx-1/ to platform-y
so mtx-1/ is automatically covered by -Werror by arch/mips/Kbuild

So the above assignment to EXTRA_CFLAGS is now redundant and can be dropped.

	Sam

From manuel.lauss@googlemail.com Tue Jun  1 18:48:23 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 19:09:50 +0200 (CEST)
Received: from mail-gy0-f177.google.com ([209.85.160.177]:45961 "EHLO
        mail-gy0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491129Ab0FAQsX convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 18:48:23 +0200
Received: by gyb11 with SMTP id 11so3865343gyb.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 09:48:17 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=googlemail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=XoITNFhF18q9hj+97cGX4B6o2k1xRQbLjjqSpir84Og=;
        b=mcnKgnI3UMPeIa0hzzl7sAtyePDOdfdkJanYR5Xd6iFoRpA17f16rn+j/zyUo52iFb
         q7prnoc+s3COHqpdaGb32/228yWx0Iz/JKcuUdkSol3SzjdqyAUfWTeX58C2U0gc8Sd2
         i6aL1HndhNS6aaKhDp3YQnyqPG+vPzM+WYbFM=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=googlemail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=QER0DXk45O8SVZ8KNhpYNM+JZUNp8ZQ12+/6FcaZEA5kHGmcrijC0LMWpFyZXAesSz
         X0bcbl0kzWg2GYHXdrYbOK3Ge4Mhsm010a0ntO4buyt9LivUnkrjD+Di9T6Fb0q8bFBi
         2NrbTnj8I9E5qBYZDvpMMR0ed4QNncAPZ+MIU=
MIME-Version: 1.0
Received: by 10.231.169.6 with SMTP id w6mr1168895iby.5.1275410879337; Tue, 01 
        Jun 2010 09:47:59 -0700 (PDT)
Received: by 10.231.183.74 with HTTP; Tue, 1 Jun 2010 09:47:59 -0700 (PDT)
In-Reply-To: <20100601163528.GA5216@merkur.ravnborg.org>
References: <1275405795-9009-1-git-send-email-manuel.lauss@googlemail.com>
        <20100601163528.GA5216@merkur.ravnborg.org>
Date:   Tue, 1 Jun 2010 18:47:59 +0200
Message-ID: <AANLkTikIiKmqjhuZKnguhyNeuCXnPeBLHSSeolCTf3d0@mail.gmail.com>
Subject: Re: [PATCH -queue v2] MIPS: Move Alchemy Makefile parts to their own 
        Platform file.
From:   Manuel Lauss <manuel.lauss@googlemail.com>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26970
X-Approved-By: ralf@linux-mips.org
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: manuel.lauss@googlemail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 528
Content-Length: 2788
Lines: 77

On Tue, Jun 1, 2010 at 6:35 PM, Sam Ravnborg <sam@ravnborg.org> wrote:
> On Tue, Jun 01, 2010 at 05:23:15PM +0200, Manuel Lauss wrote:
>> Cc: Sam Ravnborg <sam@ravnborg.org>
>> Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
>> ---
>> On top of latest mips-queue.  The changes to the mtx1/xx1500 Makefiles were
>> necessary to work around vmlinux link failures.
>
> Was this something the platform patches introduced or
> is it needed to fix the build?

Maybe.  Link failures with the "lib-y" parts do crop up occasionally.
Usually, the lib-y parts are built as the last files (along with other
arch/mips/lib code); with your changes they're built with the other
files in a directory:
 CC      arch/mips/alchemy/mtx-1/platform.o
  LD      arch/mips/alchemy/mtx-1/built-in.o
  CC      arch/mips/alchemy/mtx-1/board_setup.o
  CC      arch/mips/alchemy/mtx-1/init.o
  AR      arch/mips/alchemy/mtx-1/lib.a

That lib.a is apparently not picked up by the linker:
  LD      .tmp_vmlinux1
arch/mips/built-in.o: In function `plat_mem_setup':
/mnt/data/_home/mano/db1200/kernel/linux-2.6.git/arch/mips/alchemy/common/setup.c:55:
undefined reference to `board_setup'
/mnt/data/_home/mano/db1200/kernel/linux-2.6.git/arch/mips/alchemy/common/setup.c:55:
relocation truncated to fit: R_MIPS_26 against `board_setup'
arch/mips/built-in.o: In function `setup_arch':
/mnt/data/_home/mano/db1200/kernel/linux-2.6.git/arch/mips/kernel/setup.c:550:
undefined reference to `prom_init'
/mnt/data/_home/mano/db1200/kernel/linux-2.6.git/arch/mips/kernel/setup.c:550:
relocation truncated to fit: R_MIPS_26 against `prom_init'
[...]
make[1]: *** [.tmp_vmlinux1] Error 1
make: *** [sub-make] Error 2

Using obj-y is much more reliable.  I have no idea why some boards have
lib-y code; maybe Ralf knows more.


>> diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
>> new file mode 100644
>> index 0000000..495cc9a
>> --- /dev/null
>> +++ b/arch/mips/alchemy/Platform
>
> ...
>> +#
>> +# 4G-Systems eval board
>> +#
>> +platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/
>> +load-$(CONFIG_MIPS_MTX1)     += 0xffffffff80100000
>
>> diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
>> index 4a53815..4d1367e 100644
>> --- a/arch/mips/alchemy/mtx-1/Makefile
>> +++ b/arch/mips/alchemy/mtx-1/Makefile
>> @@ -6,7 +6,6 @@
>>  # Makefile for 4G Systems MTX-1 board.
>>  #
>>
>> -lib-y := init.o board_setup.o
>> -obj-y := platform.o
>> +obj-y := init.o board_setup.o platform.o
>>
>>  EXTRA_CFLAGS += -Werror
>
> In the above we added alchemy/mtx-1/ to platform-y
> so mtx-1/ is automatically covered by -Werror by arch/mips/Kbuild
>
> So the above assignment to EXTRA_CFLAGS is now redundant and can be dropped.

Okay, they're gone.

Thank you,
     Manuel Lauss

From irek.szczesniak@gmail.com Tue Jun  1 21:07:19 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 21:07:22 +0200 (CEST)
Received: from mail-fx0-f49.google.com ([209.85.161.49]:57326 "EHLO
        mail-fx0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492149Ab0FATHT (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 21:07:19 +0200
Received: by fxm15 with SMTP id 15so4079039fxm.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 12:07:14 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:message-id:date:from
         :user-agent:mime-version:to:subject:content-type
         :content-transfer-encoding;
        bh=/Qne7c1E9MrAkSZGGbOvmMoJ/+iV3DxXGMyXupWTWOI=;
        b=T5X0a+9f/nuIUrs00Olb1Kloa4JdSZFkeiYoqR/hfhPQHxj9Y7P7Ba9y/RArRRJ5hF
         yRQb7HghYX44gh2Y5jUA93pL3kPbSglpq0A4fgpsaPRulTzSs/DWEuDjnXRKo15cE0dF
         0rIYEcp5QxHeGEGjDBDW1Agx2Rbs2vj032jPI=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=message-id:date:from:user-agent:mime-version:to:subject
         :content-type:content-transfer-encoding;
        b=JY7zSqNbSr6jHieFGfNBb2BFOOIViCbxvyQkubANxW/qvba5+dFfNk/7E7bAZ5gaWJ
         wx23gZsPk5hH+mRa6u1gaCfD19bssukm/ltc6wsfFs4HZdYVyyUaYOwMSufTyKm2D99U
         R6dvXzIdvCuKZO8dEchU4hLGnk6zHHrKsx7XM=
Received: by 10.223.5.89 with SMTP id 25mr7506898fau.87.1275419233858;
        Tue, 01 Jun 2010 12:07:13 -0700 (PDT)
Received: from [192.168.2.50] (host-83.2.142.85.tvksmp.pl [83.2.142.85])
        by mx.google.com with ESMTPS id 13sm48400021fad.7.2010.06.01.12.07.13
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 12:07:13 -0700 (PDT)
Message-ID: <4C055A60.3000203@gmail.com>
Date:   Tue, 01 Jun 2010 21:07:12 +0200
From:   =?UTF-8?B?SXJlbmV1c3ogU3pjemXFm25pYWs=?= 
        <irek.szczesniak@gmail.com>
User-Agent: Thunderbird 2.0.0.24 (X11/20100411)
MIME-Version: 1.0
To:     linux-mips@linux-mips.org
Subject: MIPS 24Kc
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
X-archive-position: 26971
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: irek.szczesniak@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 615
Content-Length: 345
Lines: 15

Hi,

I'm writing to inquire about the status of the support for MIPS 24Kc.

I have a RouterBOARD 433 that has the Atheros AR7130 processor with 
the MIPS 24Kc core.  I would like to compile my kernel with the KGDB 
enabled, so that I can debug the kernel on the live hardware.


Thanks,
Irek

-- 
Ireneusz (Irek) Szczesniak
http://www.irkos.org

From florian@openwrt.org Tue Jun  1 21:44:53 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 21:44:58 +0200 (CEST)
Received: from mail-wy0-f177.google.com ([74.125.82.177]:50992 "EHLO
        mail-wy0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492508Ab0FATox convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 21:44:53 +0200
Received: by wyj26 with SMTP id 26so1272781wyj.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 12:44:45 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:sender:from:reply-to:to
         :subject:date:user-agent:cc:references:in-reply-to:mime-version
         :content-type:content-transfer-encoding:message-id;
        bh=QgRkPKtOnZOhaNa/qGtNpz0QmojOzAyxCA0jCOBunMw=;
        b=BEZU/3qUrJptO+nT+9OVinHbP14z7kPKLGVMB4dlAAvfo5+j3p2Q33Q6gDFJdS4bUL
         SEZwz8PtoSPrdMUxTy4yYBBJIxnKY0DB355dmYfHUhytVwSEnAqSMH2nsFKEQkt/T4eo
         OgZGDuasrS5BVM9zjzPlvEH+sU5TGcjiAsZaw=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=sender:from:reply-to:to:subject:date:user-agent:cc:references
         :in-reply-to:mime-version:content-type:content-transfer-encoding
         :message-id;
        b=VN9bVrY0KLOCkW4NwlPSCt99nrAn3u76g9mEXFU1k6uTRNJ5kmWa/abDaRwG5B9ivU
         C4ONy2MsPJsukdxo+p8wJwqIzU0UZ7T5rjpg7les86fSuYIm0CmtI9U7aCAVCEl8xVEf
         UjJiqhOqNtewqL0BqADkcTkBNp5xmUrVRCBdM=
Received: by 10.227.127.148 with SMTP id g20mr6566714wbs.192.1275421483932;
        Tue, 01 Jun 2010 12:44:43 -0700 (PDT)
Received: from lenovo.localnet (208.59.76-86.rev.gaoland.net [86.76.59.208])
        by mx.google.com with ESMTPS id l23sm52257313wbb.8.2010.06.01.12.44.42
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 12:44:43 -0700 (PDT)
From:   Florian Fainelli <florian@openwrt.org>
Reply-To: Florian Fainelli <florian@openwrt.org>
To:     Ireneusz =?utf-8?q?Szcze=C5=9Bniak?= <irek.szczesniak@gmail.com>
Subject: Re: MIPS 24Kc
Date:   Tue, 1 Jun 2010 21:44:42 +0200
User-Agent: KMail/1.13.3 (Linux/2.6.34-1-686; KDE/4.4.3; i686; ; )
Cc:     linux-mips@linux-mips.org
References: <4C055A60.3000203@gmail.com>
In-Reply-To: <4C055A60.3000203@gmail.com>
MIME-Version: 1.0
Content-Type: Text/Plain;
  charset="utf-8"
Content-Transfer-Encoding: 8BIT
Message-Id: <201006012144.43447.florian@openwrt.org>
X-archive-position: 26972
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: florian@openwrt.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 661
Content-Length: 506
Lines: 16

Hi,

Le mardi 1 juin 2010 21:07:12, Ireneusz SzczeÅ›niak a Ã©crit :
> Hi,
> 
> I'm writing to inquire about the status of the support for MIPS 24Kc.
> 
> I have a RouterBOARD 433 that has the Atheros AR7130 processor with
> the MIPS 24Kc core.  I would like to compile my kernel with the KGDB
> enabled, so that I can debug the kernel on the live hardware.

I would recommend checking OpenWr's ar71xx port[1] which supports RB433.

[1]: https://dev.openwrt.org/browser/trunk/target/linux/ar71xx
--
Florian

From sam@ravnborg.org Tue Jun  1 22:02:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 22:02:06 +0200 (CEST)
Received: from pfepa.post.tele.dk ([195.41.46.235]:42065 "EHLO
        pfepa.post.tele.dk" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1492389Ab0FAUCB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 22:02:01 +0200
Received: from merkur.ravnborg.org (x1-6-00-1e-2a-84-ae-3e.k225.webspeed.dk [80.163.61.94])
        by pfepa.post.tele.dk (Postfix) with ESMTP id 4EAD6A50006;
        Tue,  1 Jun 2010 22:01:59 +0200 (CEST)
Date:   Tue, 1 Jun 2010 22:02:00 +0200
From:   Sam Ravnborg <sam@ravnborg.org>
To:     Manuel Lauss <manuel.lauss@googlemail.com>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue v2] MIPS: Move Alchemy Makefile parts to their
        own Platform file.
Message-ID: <20100601200200.GA5438@merkur.ravnborg.org>
References: <1275405795-9009-1-git-send-email-manuel.lauss@googlemail.com> <20100601163528.GA5216@merkur.ravnborg.org> <AANLkTikIiKmqjhuZKnguhyNeuCXnPeBLHSSeolCTf3d0@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
In-Reply-To: <AANLkTikIiKmqjhuZKnguhyNeuCXnPeBLHSSeolCTf3d0@mail.gmail.com>
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26973
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: sam@ravnborg.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 678
Content-Length: 3004
Lines: 86

On Tue, Jun 01, 2010 at 06:47:59PM +0200, Manuel Lauss wrote:
> On Tue, Jun 1, 2010 at 6:35 PM, Sam Ravnborg <sam@ravnborg.org> wrote:
> > On Tue, Jun 01, 2010 at 05:23:15PM +0200, Manuel Lauss wrote:
> >> Cc: Sam Ravnborg <sam@ravnborg.org>
> >> Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
> >> ---
> >> On top of latest mips-queue.  The changes to the mtx1/xx1500 Makefiles were
> >> necessary to work around vmlinux link failures.
> >
> > Was this something the platform patches introduced or
> > is it needed to fix the build?
> 
> Maybe.  Link failures with the "lib-y" parts do crop up occasionally.
> Usually, the lib-y parts are built as the last files (along with other
> arch/mips/lib code); with your changes they're built with the other
> files in a directory:
>  CC      arch/mips/alchemy/mtx-1/platform.o
>   LD      arch/mips/alchemy/mtx-1/built-in.o
>   CC      arch/mips/alchemy/mtx-1/board_setup.o
>   CC      arch/mips/alchemy/mtx-1/init.o
>   AR      arch/mips/alchemy/mtx-1/lib.a
> 
> That lib.a is apparently not picked up by the linker:
>   LD      .tmp_vmlinux1

...

> > ...
> >> +#
> >> +# 4G-Systems eval board
> >> +#
> >> +platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/
> >> +load-$(CONFIG_MIPS_MTX1)     += 0xffffffff80100000
> >
> >> diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
> >> index 4a53815..4d1367e 100644
> >> --- a/arch/mips/alchemy/mtx-1/Makefile
> >> +++ b/arch/mips/alchemy/mtx-1/Makefile
> >> @@ -6,7 +6,6 @@
> >>  # Makefile for 4G Systems MTX-1 board.
> >>  #
> >>
> >> -lib-y := init.o board_setup.o
> >> -obj-y := platform.o
> >> +obj-y := init.o board_setup.o platform.o
> >>
> >>  EXTRA_CFLAGS += -Werror
> >

So the original ocde looked like this:

arch/mips/Makefile:
libs-$(CONFIG_MIPS_MTX1)        += arch/mips/alchemy/mtx-1/

The above is used to tell that it shall look for a lib.a
in the directory: arch/mips/alchemy/mtx-1/
It also tell kbuild to build any built-in or modules in the same dir. 

In your conversion this became:
platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/

The above tells kbuild to build objects as built-in or modules
in the directory. It does not say anything about libs.

So we loose the information about the lib.a in the directory.
I know that kbuild will build it - but it happens
to forget all about it when done.

The right fixs seems to keep the libs-$(...) assignments in
the Platform files and let kbuild pick them up due to
the include in arch/mips/Makefile.

This is not optimal and we may address this later.
But for now this looks like the simplest/safest way forward.

Getting rid of the libs like you did is also an option.
And if this is OK then this is the niver way to do it.
But I have not looked into this enough to judge.
Does the lib files contain stuff that is only used in some
confgurations or does the content end up being linked
in always anyway?
Also are there any linker order constrains to tke care of?

Lots of questions I know - sorry.

	Sam

From ddaney@caviumnetworks.com Tue Jun  1 22:18:27 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 22:18:34 +0200 (CEST)
Received: from mail3.caviumnetworks.com ([12.108.191.235]:13207 "EHLO
        mail3.caviumnetworks.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491801Ab0FAUS1 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 22:18:27 +0200
Received: from caexch01.caveonetworks.com (Not Verified[192.168.16.9]) by mail3.caviumnetworks.com with MailMarshal (v6,7,2,8378)
        id <B4c056b230000>; Tue, 01 Jun 2010 13:18:43 -0700
Received: from caexch01.caveonetworks.com ([192.168.16.9]) by caexch01.caveonetworks.com with Microsoft SMTPSVC(6.0.3790.4675);
         Tue, 1 Jun 2010 13:18:23 -0700
Received: from dd1.caveonetworks.com ([12.108.191.236]) by caexch01.caveonetworks.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675);
         Tue, 1 Jun 2010 13:18:22 -0700
Received: from dd1.caveonetworks.com (localhost.localdomain [127.0.0.1])
        by dd1.caveonetworks.com (8.14.3/8.14.3) with ESMTP id o51KIIvV006786;
        Tue, 1 Jun 2010 13:18:18 -0700
Received: (from ddaney@localhost)
        by dd1.caveonetworks.com (8.14.3/8.14.3/Submit) id o51KIG80006785;
        Tue, 1 Jun 2010 13:18:16 -0700
From:   David Daney <ddaney@caviumnetworks.com>
To:     linux-mips@linux-mips.org, ralf@linux-mips.org
Cc:     David Daney <ddaney@caviumnetworks.com>
Subject: [PATCH] MIPS: Octeon: Implement delays with cycle counter.
Date:   Tue,  1 Jun 2010 13:18:15 -0700
Message-Id: <1275423495-6751-1-git-send-email-ddaney@caviumnetworks.com>
X-Mailer: git-send-email 1.6.6.1
X-OriginalArrivalTime: 01 Jun 2010 20:18:22.0809 (UTC) FILETIME=[9579AC90:01CB01C7]
X-archive-position: 26974
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ddaney@caviumnetworks.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 692
Content-Length: 4057
Lines: 137

Power throttling make deterministic delay loops impossible.
Re-implement delays using the cycle counter.  This also allows us to
get rid of the code that calculates loops per jiffy.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
---
 arch/mips/cavium-octeon/csrc-octeon.c              |   55 ++++++++++++++++++++
 arch/mips/cavium-octeon/setup.c                    |    4 +-
 .../asm/mach-cavium-octeon/cpu-feature-overrides.h |   11 ----
 arch/mips/include/asm/octeon/octeon.h              |    1 +
 4 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
index 0bf4bbe..a7d2b39 100644
--- a/arch/mips/cavium-octeon/csrc-octeon.c
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -88,3 +88,58 @@ void __init plat_time_init(void)
 	clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
 	clocksource_register(&clocksource_mips);
 }
+
+static u64 octeon_udelay_factor;
+static u64 octeon_ndelay_factor;
+
+void __init octeon_setup_delays(void)
+{
+	octeon_udelay_factor = octeon_get_clock_rate() / 1000000;
+	/*
+	 * For __ndelay we divide by 2^16, so the factor is multiplied
+	 * by the same amount.
+	 */
+	octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull;
+
+	preset_lpj = octeon_get_clock_rate() / HZ;
+}
+
+void __udelay(unsigned long us)
+{
+	u64 cur, end, inc;
+
+	cur = read_c0_cvmcount();
+
+	inc = us * octeon_udelay_factor;
+	end = cur + inc;
+
+	while (end > cur)
+		cur = read_c0_cvmcount();
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long ns)
+{
+	u64 cur, end, inc;
+
+	cur = read_c0_cvmcount();
+
+	inc = ((ns * octeon_ndelay_factor) >> 16);
+	end = cur + inc;
+
+	while (end > cur)
+		cur = read_c0_cvmcount();
+}
+EXPORT_SYMBOL(__ndelay);
+
+void __delay(unsigned long loops)
+{
+	u64 cur, end;
+
+	cur = read_c0_cvmcount();
+	end = cur + loops;
+
+	while (end > cur)
+		cur = read_c0_cvmcount();
+}
+EXPORT_SYMBOL(__delay);
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index d1b5ffa..6f36bc1 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -598,13 +598,13 @@ void __init prom_init(void)
 		 * the filesystem. Also specify the calibration delay
 		 * to avoid calculating it every time.
 		 */
-		strcat(arcs_cmdline, " rw root=1f00"
-		       " lpj=60176 slram=root,0x40000000,+1073741824");
+		strcat(arcs_cmdline, " rw root=1f00 slram=root,0x40000000,+1073741824");
 	}
 
 	mips_hpt_frequency = octeon_get_clock_rate();
 
 	octeon_init_cvmcount();
+	octeon_setup_delays();
 
 	_machine_restart = octeon_restart;
 	_machine_halt = octeon_halt;
diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
index bbf0540..e412777 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
@@ -61,22 +61,11 @@
 
 #define kernel_uses_smartmips_rixi (cpu_data[0].cputype == CPU_CAVIUM_OCTEON_PLUS)
 
-#define ARCH_HAS_READ_CURRENT_TIMER 1
 #define ARCH_HAS_IRQ_PER_CPU	1
 #define ARCH_HAS_SPINLOCK_PREFETCH 1
 #define spin_lock_prefetch(x) prefetch(x)
 #define PREFETCH_STRIDE 128
 
-static inline int read_current_timer(unsigned long *result)
-{
-	asm volatile ("rdhwr %0,$31\n"
-#ifndef CONFIG_64BIT
-		      "\tsll %0, 0"
-#endif
-		      : "=r" (*result));
-	return 0;
-}
-
 static inline int octeon_has_saa(void)
 {
 	int id;
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index ca6214b..8a3eb3b 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -50,6 +50,7 @@ extern void octeon_crypto_disable(struct octeon_cop2_state *state,
 extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
 
 extern void octeon_init_cvmcount(void);
+extern void octeon_setup_delays(void);
 
 #define OCTEON_ARGV_MAX_ARGS	64
 #define OCTOEN_SERIAL_LEN	20
-- 
1.6.6.1


From manuel.lauss@googlemail.com Tue Jun  1 22:30:55 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 22:30:58 +0200 (CEST)
Received: from mail-fx0-f49.google.com ([209.85.161.49]:44968 "EHLO
        mail-fx0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491103Ab0FAUaz (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 22:30:55 +0200
Received: by fxm15 with SMTP id 15so4160968fxm.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 13:30:49 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=googlemail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=knv9en/oxDlQuFd0kdlqQ/yERBv4s/HNYyuqmMn8O6E=;
        b=OU2QQhC3JCdXrcP51caUMMEgo50IiELTBNYmz0LHA/AGQXwi3MiWMHg11nD+GulzRB
         nxNdJhC4v8yRPvFI9irk2iSQ6YQZP2cAyQIUfVbNzfrFbfHUcyquw56WRHSiNIDg55Ho
         Z/tRWPZoKwhxMYt2tIBoIuoPz9qA/Ttn9C3io=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=googlemail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=oHbzxdyn/u2QbjgfW4Pk9BjLDOuoRFNgmPv037UBIkxGOlDLFD3DIE27J5tpnMIJOh
         cE8z51IdmYOSyqJNUIms2bEuIvUOFzBCiVfjdwBmb5JxjAkuHANGmRxybWijjkeSbSrl
         XTxIFJ4fhMOW8UMQSovjt66U5ft5GNk/tVH2E=
Received: by 10.223.51.152 with SMTP id d24mr7635654fag.36.1275424249610;
        Tue, 01 Jun 2010 13:30:49 -0700 (PDT)
Received: from localhost.localdomain (p5496C36D.dip.t-dialin.net [84.150.195.109])
        by mx.google.com with ESMTPS id 2sm48702233fav.13.2010.06.01.13.30.47
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 13:30:48 -0700 (PDT)
From:   Manuel Lauss <manuel.lauss@googlemail.com>
To:     Linux-MIPS <linux-mips@linux-mips.org>
Cc:     Manuel Lauss <manuel.lauss@googlemail.com>
Subject: [PATCH -queue 1/2] MIPS: Alchemy: move boards over to obj-y
Date:   Tue,  1 Jun 2010 22:30:36 +0200
Message-Id: <1275424237-8120-1-git-send-email-manuel.lauss@googlemail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26975
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: manuel.lauss@googlemail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 702
Content-Length: 1933
Lines: 62

Preparatory step for moving Alchemy over to new  MIPS Platform
build system support.

Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
The other boards no longer use libs, without any ill effects.
In the past the lib-y code would sometimes not be picked up and
cause link failures, so this also improves build reliability.

 arch/mips/Makefile                 |    4 ++--
 arch/mips/alchemy/mtx-1/Makefile   |    3 +--
 arch/mips/alchemy/xxs1500/Makefile |    2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 14b755d..8282152 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -290,13 +290,13 @@ load-$(CONFIG_MIPS_MIRAGE)	+= 0xffffffff80100000
 #
 # 4G-Systems eval board
 #
-libs-$(CONFIG_MIPS_MTX1)	+= arch/mips/alchemy/mtx-1/
+core-$(CONFIG_MIPS_MTX1)	+= arch/mips/alchemy/mtx-1/
 load-$(CONFIG_MIPS_MTX1)	+= 0xffffffff80100000
 
 #
 # MyCable eval board
 #
-libs-$(CONFIG_MIPS_XXS1500)	+= arch/mips/alchemy/xxs1500/
+core-$(CONFIG_MIPS_XXS1500)	+= arch/mips/alchemy/xxs1500/
 load-$(CONFIG_MIPS_XXS1500)	+= 0xffffffff80100000
 
 # must be last for Alchemy systems for GPIO to work properly
diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
index 4a53815..f912022 100644
--- a/arch/mips/alchemy/mtx-1/Makefile
+++ b/arch/mips/alchemy/mtx-1/Makefile
@@ -6,7 +6,6 @@
 # Makefile for 4G Systems MTX-1 board.
 #
 
-lib-y := init.o board_setup.o
-obj-y := platform.o
+obj-y += init.o board_setup.o platform.o
 
 EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile
index 4dc81d7..81c516e 100644
--- a/arch/mips/alchemy/xxs1500/Makefile
+++ b/arch/mips/alchemy/xxs1500/Makefile
@@ -5,6 +5,6 @@
 # Makefile for MyCable XXS1500 board.
 #
 
-lib-y := init.o board_setup.o platform.o
+obj-y += init.o board_setup.o platform.o
 
 EXTRA_CFLAGS += -Werror
-- 
1.7.1


From manuel.lauss@googlemail.com Tue Jun  1 22:30:59 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 22:31:29 +0200 (CEST)
Received: from mail-fx0-f49.google.com ([209.85.161.49]:56763 "EHLO
        mail-fx0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492512Ab0FAUa7 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 1 Jun 2010 22:30:59 +0200
Received: by fxm15 with SMTP id 15so4161007fxm.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 13:30:53 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=googlemail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer:in-reply-to:references;
        bh=eCtAOpA+Lc9OUkWeQ6sRot77dBNfu9lBLG9Knnwpwrg=;
        b=lNo3+jvA65q3GA2KfVXe0VFyjvc1WofXO15ewXzkDsskSl48SWPGIZ2pmhdnC5DjWt
         8DxZBjSKzwwG7cbKFrz78SyEmgPnoEl1W64v7xD5LcSp5d8XEKW628h3MwgRsG2ddO+d
         9Kfuj0PTU+CUgGllvt37eZJ/uuv3tgDXzq5e8=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=googlemail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;
        b=G0u3pyjE1S/3e74nuUaKzkl6Y9BcvsZS49Fnse80wrMXNiO0XJ4Uw5GTGE4Dbs9PlL
         I6FEZhyC9tkzCX5aQOWDlxwW144qcKCPRXsNPW7yQ3JVQT8SjwDG+FngFuiFkWIAkPDB
         IU90AKm+H25Njjzaew5TJZaxi3gRR7BnTWFGg=
Received: by 10.223.25.208 with SMTP id a16mr7621405fac.79.1275424252815;
        Tue, 01 Jun 2010 13:30:52 -0700 (PDT)
Received: from localhost.localdomain (p5496C36D.dip.t-dialin.net [84.150.195.109])
        by mx.google.com with ESMTPS id 2sm48702233fav.13.2010.06.01.13.30.50
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Tue, 01 Jun 2010 13:30:51 -0700 (PDT)
From:   Manuel Lauss <manuel.lauss@googlemail.com>
To:     Linux-MIPS <linux-mips@linux-mips.org>
Cc:     Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Manuel Lauss <manuel.lauss@googlemail.com>
Subject: [PATCH -queue v3 2/2] MIPS: Move Alchemy Makefile parts to their own Platform file.
Date:   Tue,  1 Jun 2010 22:30:37 +0200
Message-Id: <1275424237-8120-2-git-send-email-manuel.lauss@googlemail.com>
X-Mailer: git-send-email 1.7.1
In-Reply-To: <1275424237-8120-1-git-send-email-manuel.lauss@googlemail.com>
References: <1275424237-8120-1-git-send-email-manuel.lauss@googlemail.com>
X-archive-position: 26976
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: manuel.lauss@googlemail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 705
Content-Length: 9484
Lines: 302

From: Manuel Lauss <manuel.lauss@gmail.com>

Cc: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
On top of mips-queue, build tested.

 arch/mips/Kbuild.platforms           |    1 +
 arch/mips/Makefile                   |  105 --------------------------------
 arch/mips/alchemy/Platform           |  109 ++++++++++++++++++++++++++++++++++
 arch/mips/alchemy/common/Makefile    |    2 -
 arch/mips/alchemy/devboards/Makefile |    2 -
 arch/mips/alchemy/mtx-1/Makefile     |    2 -
 arch/mips/alchemy/xxs1500/Makefile   |    2 -
 7 files changed, 110 insertions(+), 113 deletions(-)
 create mode 100644 arch/mips/alchemy/Platform

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 9784c49..dc2bac5 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -1,5 +1,6 @@
 # All platforms listed in alphabetic order
 
+platforms += alchemy
 platforms += ar7
 platforms += loongson
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 8282152..b191730 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -199,111 +199,6 @@ cflags-$(CONFIG_MACH_JAZZ)	+= -I$(srctree)/arch/mips/include/asm/mach-jazz
 load-$(CONFIG_MACH_JAZZ)	+= 0xffffffff80080000
 
 #
-# Common Alchemy Au1x00 stuff
-#
-core-$(CONFIG_SOC_AU1X00)	+= arch/mips/alchemy/common/
-
-#
-# AMD Alchemy Pb1000 eval board
-#
-core-$(CONFIG_MIPS_PB1000)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1000)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1100 eval board
-#
-core-$(CONFIG_MIPS_PB1100)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1100)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1500 eval board
-#
-core-$(CONFIG_MIPS_PB1500)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1500)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1550 eval board
-#
-core-$(CONFIG_MIPS_PB1550)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1550)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Pb1200 eval board
-#
-core-$(CONFIG_MIPS_PB1200)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_PB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
-load-$(CONFIG_MIPS_PB1200)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1000 eval board
-#
-core-$(CONFIG_MIPS_DB1000)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1000)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1100 eval board
-#
-core-$(CONFIG_MIPS_DB1100)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1100)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1500 eval board
-#
-core-$(CONFIG_MIPS_DB1500)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1500)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1550 eval board
-#
-core-$(CONFIG_MIPS_DB1550)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1550)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Db1200 eval board
-#
-core-$(CONFIG_MIPS_DB1200)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1200)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Bosporus eval board
-#
-core-$(CONFIG_MIPS_BOSPORUS)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_BOSPORUS)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_BOSPORUS)	+= 0xffffffff80100000
-
-#
-# AMD Alchemy Mirage eval board
-#
-core-$(CONFIG_MIPS_MIRAGE)	+= arch/mips/alchemy/devboards/
-cflags-$(CONFIG_MIPS_MIRAGE)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_MIRAGE)	+= 0xffffffff80100000
-
-#
-# 4G-Systems eval board
-#
-core-$(CONFIG_MIPS_MTX1)	+= arch/mips/alchemy/mtx-1/
-load-$(CONFIG_MIPS_MTX1)	+= 0xffffffff80100000
-
-#
-# MyCable eval board
-#
-core-$(CONFIG_MIPS_XXS1500)	+= arch/mips/alchemy/xxs1500/
-load-$(CONFIG_MIPS_XXS1500)	+= 0xffffffff80100000
-
-# must be last for Alchemy systems for GPIO to work properly
-cflags-$(CONFIG_SOC_AU1X00)	+= -I$(srctree)/arch/mips/include/asm/mach-au1x00
-
-
-#
 # Cobalt Server
 #
 core-$(CONFIG_MIPS_COBALT)	+= arch/mips/cobalt/
diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
new file mode 100644
index 0000000..495cc9a
--- /dev/null
+++ b/arch/mips/alchemy/Platform
@@ -0,0 +1,109 @@
+#
+# Core Alchemy code
+#
+platform-$(CONFIG_MACH_ALCHEMY)	+= alchemy/common/
+
+
+#
+# AMD Alchemy Pb1000 eval board
+#
+platform-$(CONFIG_MIPS_PB1000)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1000)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1100 eval board
+#
+platform-$(CONFIG_MIPS_PB1100)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1100)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1500 eval board
+#
+platform-$(CONFIG_MIPS_PB1500)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1500)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1550 eval board
+#
+platform-$(CONFIG_MIPS_PB1550)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1550)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1200 eval board
+#
+platform-$(CONFIG_MIPS_PB1200)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_PB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-pb1x00
+load-$(CONFIG_MIPS_PB1200)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1000 eval board
+#
+platform-$(CONFIG_MIPS_DB1000)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1000)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1000)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1100 eval board
+#
+platform-$(CONFIG_MIPS_DB1100)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1100)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1100)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1500 eval board
+#
+platform-$(CONFIG_MIPS_DB1500)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1500)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1500)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1550 eval board
+#
+platform-$(CONFIG_MIPS_DB1550)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1550)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1550)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Db1200 eval board
+#
+platform-$(CONFIG_MIPS_DB1200)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1200)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1200)	+= 0xffffffff80100000
+
+#
+# AMD Alchemy Bosporus eval board
+#
+platform-$(CONFIG_MIPS_BOSPORUS) += alchemy/devboards/
+cflags-$(CONFIG_MIPS_BOSPORUS)	 += -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_BOSPORUS)	 += 0xffffffff80100000
+
+#
+# AMD Alchemy Mirage eval board
+#
+platform-$(CONFIG_MIPS_MIRAGE)	+= alchemy/devboards/
+cflags-$(CONFIG_MIPS_MIRAGE)	+= -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_MIRAGE)	+= 0xffffffff80100000
+
+#
+# 4G-Systems eval board
+#
+platform-$(CONFIG_MIPS_MTX1)	+= alchemy/mtx-1/
+load-$(CONFIG_MIPS_MTX1)	+= 0xffffffff80100000
+
+#
+# MyCable eval board
+#
+platform-$(CONFIG_MIPS_XXS1500)	+= alchemy/xxs1500/
+load-$(CONFIG_MIPS_XXS1500)	+= 0xffffffff80100000
+
+
+# boards can specify their own <gpio.h> in one of their include dirs.
+# If they do, placing this line here at the end will make sure the
+# compiler picks the board one.  If they don't, it will make sure
+# the alchemy generic gpio header is picked up.
+
+cflags-$(CONFIG_MACH_ALCHEMY)	+= -I$(srctree)/arch/mips/include/asm/mach-au1x00
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile
index 06c0e65..27811fe 100644
--- a/arch/mips/alchemy/common/Makefile
+++ b/arch/mips/alchemy/common/Makefile
@@ -18,5 +18,3 @@ ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
 endif
 
 obj-$(CONFIG_PCI)		+= pci.o
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile
index ecbd37f..826449c 100644
--- a/arch/mips/alchemy/devboards/Makefile
+++ b/arch/mips/alchemy/devboards/Makefile
@@ -16,5 +16,3 @@ obj-$(CONFIG_MIPS_DB1500)	+= db1x00/
 obj-$(CONFIG_MIPS_DB1550)	+= db1x00/
 obj-$(CONFIG_MIPS_BOSPORUS)	+= db1x00/
 obj-$(CONFIG_MIPS_MIRAGE)	+= db1x00/
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
index f912022..81b540c 100644
--- a/arch/mips/alchemy/mtx-1/Makefile
+++ b/arch/mips/alchemy/mtx-1/Makefile
@@ -7,5 +7,3 @@
 #
 
 obj-y += init.o board_setup.o platform.o
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/alchemy/xxs1500/Makefile b/arch/mips/alchemy/xxs1500/Makefile
index 81c516e..91defcf 100644
--- a/arch/mips/alchemy/xxs1500/Makefile
+++ b/arch/mips/alchemy/xxs1500/Makefile
@@ -6,5 +6,3 @@
 #
 
 obj-y += init.o board_setup.o platform.o
-
-EXTRA_CFLAGS += -Werror
-- 
1.7.1


From manuel.lauss@googlemail.com Tue Jun  1 22:13:03 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 01 Jun 2010 22:46:43 +0200 (CEST)
Received: from mail-iw0-f177.google.com ([209.85.214.177]:59314 "EHLO
        mail-iw0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491801Ab0FAUND convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Tue, 1 Jun 2010 22:13:03 +0200
Received: by iwn34 with SMTP id 34so282010iwn.36
        for <linux-mips@linux-mips.org>; Tue, 01 Jun 2010 13:13:00 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=googlemail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=eYV3NXYD+5orpMQLFMghf7iW9I0IOQ4vgnq+vt09KV0=;
        b=asXoPi1hrUNTnt0Jci3GUsmaNhRilJfkoZ4vqHRRhQnCYO2Qt7qYYPgqPG3eSetgNj
         FgiddksbQr9FySoNY7kBI6Y8s3pvLLHHiX3yJ8cigSGxTA6X3o3DqQYQLfT3sy7FT5ws
         Y9UK4pJTpdjT3d7CyPLFaz0wPTmOriggM4ekk=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=googlemail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=spanyDJpu0f77ooI/YdqrhOQNOdwgHP5FI+2n2lR/3Ua7fjTmyOyjtdAFvn5P/hswN
         9dBo44FdQp0KcifrUMyoLAXYYLAtrCasVvedpkvv+p5S7DXDVUiOZCkAwVn4lfSu8sIu
         ToXE714MVSnhOvfvMVEThENeqvZuI2/NA0XI0=
MIME-Version: 1.0
Received: by 10.231.150.2 with SMTP id w2mr8442083ibv.37.1275423179775; Tue, 
        01 Jun 2010 13:12:59 -0700 (PDT)
Received: by 10.231.183.74 with HTTP; Tue, 1 Jun 2010 13:12:59 -0700 (PDT)
In-Reply-To: <20100601200200.GA5438@merkur.ravnborg.org>
References: <1275405795-9009-1-git-send-email-manuel.lauss@googlemail.com>
        <20100601163528.GA5216@merkur.ravnborg.org>
        <AANLkTikIiKmqjhuZKnguhyNeuCXnPeBLHSSeolCTf3d0@mail.gmail.com>
        <20100601200200.GA5438@merkur.ravnborg.org>
Date:   Tue, 1 Jun 2010 22:12:59 +0200
Message-ID: <AANLkTimJXcCxazHZXLOA2tfVuc326LyQty9uAfW7V11i@mail.gmail.com>
Subject: Re: [PATCH -queue v2] MIPS: Move Alchemy Makefile parts to their own 
        Platform file.
From:   Manuel Lauss <manuel.lauss@googlemail.com>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26977
X-Approved-By: ralf@linux-mips.org
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: manuel.lauss@googlemail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 724
Content-Length: 3304
Lines: 98

On Tue, Jun 1, 2010 at 10:02 PM, Sam Ravnborg <sam@ravnborg.org> wrote:
> On Tue, Jun 01, 2010 at 06:47:59PM +0200, Manuel Lauss wrote:
>> On Tue, Jun 1, 2010 at 6:35 PM, Sam Ravnborg <sam@ravnborg.org> wrote:
>> > On Tue, Jun 01, 2010 at 05:23:15PM +0200, Manuel Lauss wrote:
>> >> Cc: Sam Ravnborg <sam@ravnborg.org>
>> >> Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
>> >> ---
>> >> On top of latest mips-queue.  The changes to the mtx1/xx1500 Makefiles were
>> >> necessary to work around vmlinux link failures.
>> >
>> > Was this something the platform patches introduced or
>> > is it needed to fix the build?
>>
>> Maybe.  Link failures with the "lib-y" parts do crop up occasionally.
>> Usually, the lib-y parts are built as the last files (along with other
>> arch/mips/lib code); with your changes they're built with the other
>> files in a directory:
>>  CC      arch/mips/alchemy/mtx-1/platform.o
>>   LD      arch/mips/alchemy/mtx-1/built-in.o
>>   CC      arch/mips/alchemy/mtx-1/board_setup.o
>>   CC      arch/mips/alchemy/mtx-1/init.o
>>   AR      arch/mips/alchemy/mtx-1/lib.a
>>
>> That lib.a is apparently not picked up by the linker:
>>   LD      .tmp_vmlinux1
>
> ...
>
>> > ...
>> >> +#
>> >> +# 4G-Systems eval board
>> >> +#
>> >> +platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/
>> >> +load-$(CONFIG_MIPS_MTX1)     += 0xffffffff80100000
>> >
>> >> diff --git a/arch/mips/alchemy/mtx-1/Makefile b/arch/mips/alchemy/mtx-1/Makefile
>> >> index 4a53815..4d1367e 100644
>> >> --- a/arch/mips/alchemy/mtx-1/Makefile
>> >> +++ b/arch/mips/alchemy/mtx-1/Makefile
>> >> @@ -6,7 +6,6 @@
>> >>  # Makefile for 4G Systems MTX-1 board.
>> >>  #
>> >>
>> >> -lib-y := init.o board_setup.o
>> >> -obj-y := platform.o
>> >> +obj-y := init.o board_setup.o platform.o
>> >>
>> >>  EXTRA_CFLAGS += -Werror
>> >
>
> So the original ocde looked like this:
>
> arch/mips/Makefile:
> libs-$(CONFIG_MIPS_MTX1)        += arch/mips/alchemy/mtx-1/
>
> The above is used to tell that it shall look for a lib.a
> in the directory: arch/mips/alchemy/mtx-1/
> It also tell kbuild to build any built-in or modules in the same dir.
>
> In your conversion this became:
> platform-$(CONFIG_MIPS_MTX1) += alchemy/mtx-1/
>
> The above tells kbuild to build objects as built-in or modules
> in the directory. It does not say anything about libs.
>
> So we loose the information about the lib.a in the directory.
> I know that kbuild will build it - but it happens
> to forget all about it when done.
>
> The right fixs seems to keep the libs-$(...) assignments in
> the Platform files and let kbuild pick them up due to
> the include in arch/mips/Makefile.

That doesn't work, I get errors for instance when doing "make clean":

linux-2.6.git/scripts/Makefile.clean:17:
linux-2.6.git/alchemy/mtx-1/Makefile: No such file or directory


> Getting rid of the libs like you did is also an option.

I'll send new patches doing exactly that and pile this one on
top of it.


> Does the lib files contain stuff that is only used in some
> confgurations or does the content end up being linked
> in always anyway?

Nope, just usual board initialization and platform data.


> Also are there any linker order constrains to tke care of?

None that I'm aware of, at least for the affected boards.


        Manuel

From ralf@linux-mips.org Wed Jun  2 02:56:52 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 02:56:56 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:58354 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492530Ab0FBA4w (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 02:56:52 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o520uiIt031664;
        Wed, 2 Jun 2010 01:56:45 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o520ug3D031662;
        Wed, 2 Jun 2010 01:56:42 +0100
Date:   Wed, 2 Jun 2010 01:56:42 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Manuel Lauss <manuel.lauss@googlemail.com>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue 1/2] MIPS: Alchemy: move boards over to obj-y
Message-ID: <20100602005641.GA31658@linux-mips.org>
References: <1275424237-8120-1-git-send-email-manuel.lauss@googlemail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275424237-8120-1-git-send-email-manuel.lauss@googlemail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26978
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 906
Content-Length: 42
Lines: 3

Thanks Manuel, queued for 2.6.36.

  Ralf

From ralf@linux-mips.org Wed Jun  2 02:57:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 02:57:20 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:58359 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492532Ab0FBA5B (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 02:57:01 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o520usmD031670;
        Wed, 2 Jun 2010 01:56:56 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o520urcK031669;
        Wed, 2 Jun 2010 01:56:53 +0100
Date:   Wed, 2 Jun 2010 01:56:53 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Manuel Lauss <manuel.lauss@googlemail.com>
Cc:     Linux-MIPS <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: Re: [PATCH -queue v3 2/2] MIPS: Move Alchemy Makefile parts to their
 own Platform file.
Message-ID: <20100602005653.GB31658@linux-mips.org>
References: <1275424237-8120-1-git-send-email-manuel.lauss@googlemail.com>
 <1275424237-8120-2-git-send-email-manuel.lauss@googlemail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275424237-8120-2-git-send-email-manuel.lauss@googlemail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26979
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 907
Content-Length: 41
Lines: 3

Thanks Manuel, queued for 2.6.36.

  Ral

From wuzhangjin@gmail.com Wed Jun  2 04:31:11 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 04:31:20 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:65237 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491203Ab0FBCbL convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 04:31:11 +0200
Received: by pvb32 with SMTP id 32so712751pvb.36
        for <multiple recipients>; Tue, 01 Jun 2010 19:31:03 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=s1VSctApP4TXWvj/tQyoalced30bItNZJXOBLFeKle4=;
        b=ERYeHAjS7p3etAZPA9hoiTjYq8TIdQgW5bDD56DZK0K7/KaqHnWcqEPNT53zcZKDWS
         TF/0re8fBasArJkYLN8wToUzEcLjKsxw0G/VpVQVkg+JJtCGK1xnIGciKHbkLQsy9Tpj
         0QMl0hCgwDRulCW+MYWhlnlXgbst5VV8Y71js=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=i0sm7G8wyjYGjZLo8ia/boBZLyLBVIU0ydol+ZtbcdBQ20aoQT4DUiiFI/IV9m5jQJ
         zDcn6eiiN8GpcEE3YZBhnslf7y1ZdfZ/W5WL6J7HeS8aYwRH58soVmpif0igVdwmOhgr
         hLU5MRJsCmwGhqxHzWvbn4Ul6lcPLoaPC+FKk=
MIME-Version: 1.0
Received: by 10.141.90.18 with SMTP id s18mr5631177rvl.297.1275445862212; Tue, 
        01 Jun 2010 19:31:02 -0700 (PDT)
Received: by 10.142.179.7 with HTTP; Tue, 1 Jun 2010 19:31:02 -0700 (PDT)
In-Reply-To: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
References: <1275388144-5998-1-git-send-email-wuzhangjin@gmail.com>
Date:   Wed, 2 Jun 2010 10:31:02 +0800
Message-ID: <AANLkTimphf48ZsNVS29mUNwx4NHSd7FeicoFcHsdmd58@mail.gmail.com>
Subject: Re: [PATCH] MIPS: arch/mips/boot/compressed/Makefile: Unify the 
        suffix of compressed vmlinux.bin
From:   wu zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26980
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 927
Content-Length: 2274
Lines: 63

Hi,

I will use vmlinux.bin.z in the next revision of this patch.

Regards,


On Tue, Jun 1, 2010 at 6:29 PM, Wu Zhangjin <wuzhangjin@gmail.com> wrote:
> The compressed vmlinux.{gz,bz2,lzo,lzma} are only temp files, we can use the
> same suffix for them to remove several lines and simpify the maintaining.
>
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> ---
>  arch/mips/boot/compressed/Makefile |   12 ++++--------
>  1 files changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
> index 74a52d7..7204dfc 100644
> --- a/arch/mips/boot/compressed/Makefile
> +++ b/arch/mips/boot/compressed/Makefile
> @@ -48,23 +48,19 @@ OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
>  $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
>        $(call if_changed,objcopy)
>
> -suffix_$(CONFIG_KERNEL_GZIP)  = gz
> -suffix_$(CONFIG_KERNEL_BZIP2) = bz2
> -suffix_$(CONFIG_KERNEL_LZMA)  = lzma
> -suffix_$(CONFIG_KERNEL_LZO)   = lzo
>  tool_$(CONFIG_KERNEL_GZIP)    = gzip
>  tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
>  tool_$(CONFIG_KERNEL_LZMA)    = lzma
>  tool_$(CONFIG_KERNEL_LZO)     = lzo
>
> -targets += vmlinux.gz vmlinux.bz2 vmlinux.lzma vmlinux.lzo
> -$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin FORCE
> +targets += vmlinux.z
> +$(obj)/vmlinux.z: $(obj)/vmlinux.bin FORCE
>        $(call if_changed,$(tool_y))
>
>  targets += piggy.o
> -OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.$(suffix_y) \
> +OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.z \
>                         --set-section-flags=.image=contents,alloc,load,readonly,data
> -$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.$(suffix_y) FORCE
> +$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.z FORCE
>        $(call if_changed,objcopy)
>
>  LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
> --
> 1.6.5
>
>



-- 
Studying engineer. Wu Zhangjin
Lanzhou University      http://www.lzu.edu.cn
Distributed & Embedded System Lab      http://dslab.lzu.edu.cn
School of Information Science and Engeneering         http://xxxy.lzu.edu.cn
wuzhangjin@gmail.com         http://falcon.oss.lzu.edu.cn
Address:Tianshui South Road 222,Lanzhou,P.R.China    Zip Code:730000
Tel:+86-931-8912025

From wuzhangjin@gmail.com Wed Jun  2 05:06:41 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 05:26:18 +0200 (CEST)
Received: from mail-pw0-f49.google.com ([209.85.160.49]:42202 "EHLO
        mail-pw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491753Ab0FBDGl convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 05:06:41 +0200
Received: by pwi2 with SMTP id 2so2510481pwi.36
        for <multiple recipients>; Tue, 01 Jun 2010 20:06:33 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=7AlnwrCYNGFzbY7Ji2R28wDJFzeqs+AJp13lg4xeTRA=;
        b=WI1RAnqbI77xF4hVpXtSCN6sKh8FoD1p97rn93415YSiU3mhCQQ4AtDrlwW9Fz/Ftr
         g1i250nzHBi/tIhW5l6F5307R4p43p6ZYY4wQY/xnucGRsWbjqTQPtj/EcICItWcBCeQ
         TFQCWf+4cfS9IYA956mSpD4SbTkqaTdC2b+DQ=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=F4rcIsYxm+pi1+Qp48T+9LLL4Q3nGi8+LNlS/lmk92Jk9Ett4KqZeD/32Re7mY2WbI
         DNfVpPW9XZCG1qdLZPmocoNDgh1Bzd6wYl98SREBu6hoXpkUIrsB6CnV5LEVOEHNlRsh
         D1ZSHOcJWnG68TWtSxYn3Hl+gMFVh087PI4ps=
MIME-Version: 1.0
Received: by 10.141.90.18 with SMTP id s18mr5677312rvl.297.1275447993155; Tue, 
        01 Jun 2010 20:06:33 -0700 (PDT)
Received: by 10.142.179.7 with HTTP; Tue, 1 Jun 2010 20:06:33 -0700 (PDT)
In-Reply-To: <20100601152750.GA5131@merkur.ravnborg.org>
References: <616317d6d889537d03c3c0860231da9a2cce0b69.1275372093.git.wuzhangjin@gmail.com>
        <20100601152750.GA5131@merkur.ravnborg.org>
Date:   Wed, 2 Jun 2010 11:06:33 +0800
Message-ID: <AANLkTikR8qY2NwurQ76R1F-AQ4QcmmqXvoWtlOqCB5Ou@mail.gmail.com>
Subject: Re: [PATCH v3] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
From:   wu zhangjin <wuzhangjin@gmail.com>
To:     Sam Ravnborg <sam@ravnborg.org>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26981
X-Approved-By: ralf@linux-mips.org
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 948
Content-Length: 3797
Lines: 104

Hi, Sam

On Tue, Jun 1, 2010 at 11:27 PM, Sam Ravnborg <sam@ravnborg.org> wrote:
[...]
>
>> diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
>> index 4667a5f..f210b09 100644
>> --- a/arch/mips/boot/.gitignore
>> +++ b/arch/mips/boot/.gitignore
>> @@ -3,3 +3,4 @@ elf2ecoff
>>  vmlinux.*
>>  zImage
>>  zImage.tmp
>> +calc_vmlinuz_load_addr
>
> Does this do any good in this file?
> I had assumed this covered only the same dir as the .gitignore file
> is stored. But I may be wrong.

I have tried to add this to boot/compressed/.gitignore, but there was
no .gitignore there and found the vmlinux.* in boot/.gitignore, it
worked to hide the vmlinux.* under boot/compressed/, then I put the
calc_vmlinuz_load_addr to this .gitignore too ;) it really hided the
calc_vmlinuz_load_addr, that's it.

BTW: I just don't want to add a new file for one line if it is not necessary ;)

>
>> diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
>> index 7204dfc..cd9ee04 100644
>> --- a/arch/mips/boot/compressed/Makefile
>> +++ b/arch/mips/boot/compressed/Makefile
>>
>> -LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
>> -vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
>> -     $(call cmd,ld)
>> +# Calculate the load address of the compressed kernel
>> +hostprogs-y := calc_vmlinuz_load_addr
>> +
>> +vmlinuzobjs-y += $(obj)/piggy.o
>> +
>> +quiet_cmd_zld = LD      $@
>> +      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(shell $(obj)/calc_vmlinuz_load_addr $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) -T $< $(vmlinuzobjs-y) -o $@
>
> The line seriously fail the 80 char limit.
> Something like this:
>
> load_addr = $(shell $(obj)/calc_vmlinuz_load_addr \
>                    $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)
> quiet_cmd_zld = LD      $@
>      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(load-addr) -T $< $(vmlinuzobjs-y) -o $@
>
> Note: The load_addr local variable _must_ use "=" asignment

This is the _key_ stuff. I  tried to use VMLINUZ_LOAD_ADDR(like your
load_addr) as the load address, but failed all the time, seems I used
the ":=" assignment, now with "=", it works, thanks!

And could you please explain their differences?

>
>> +vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
>> +     $(call cmd,zld)
>>       $(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@
>
> Does objcopy support equally named input and out files?
> If this is the case you could use:
> $(call cmd,objcopy) as the last line.

Just checked the ld.script, and found the .reginfo section have been
discarded, then it's time to remove this objcopy line(this objcopy
line only remove the .reginfo section).

[...]
>> +
>> +     /* Align with 65536 */
>> +     vmlinuz_load_addr += (65536 - vmlinux_size % 65536);
>
> You have plenty of rooms for a comment about why you do this.
> Would be good to use this possibility.
>

The address of "vmlinux_load_addr + vmlinux_size" may be not aligned
with the standard data type of MIPS, that's why we need the alignment,
but here 65536, 64k(about several pages), is really a little big, I
will use 16 bytes in the next revision and add more comments for it:

+       /*
+        * Align with 16 bytes: "greater than that used for any standard data
+        * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition).
+        */
+
+       vmlinuz_load_addr += (16 - vmlinux_size % 16);

Thanks & Regards,

-- 
Studying engineer. Wu Zhangjin
Lanzhou University      http://www.lzu.edu.cn
Distributed & Embedded System Lab      http://dslab.lzu.edu.cn
School of Information Science and Engeneering         http://xxxy.lzu.edu.cn
wuzhangjin@gmail.com         http://falcon.oss.lzu.edu.cn
Address:Tianshui South Road 222,Lanzhou,P.R.China    Zip Code:730000
Tel:+86-931-8912025

From sam@ravnborg.org Wed Jun  2 06:48:28 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 06:48:32 +0200 (CEST)
Received: from pfepb.post.tele.dk ([195.41.46.236]:54485 "EHLO
        pfepb.post.tele.dk" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1492533Ab0FBEs2 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 06:48:28 +0200
Received: from merkur.ravnborg.org (x1-6-00-1e-2a-84-ae-3e.k225.webspeed.dk [80.163.61.94])
        by pfepb.post.tele.dk (Postfix) with ESMTP id 89C66F84011;
        Wed,  2 Jun 2010 06:48:27 +0200 (CEST)
Date:   Wed, 2 Jun 2010 06:48:27 +0200
From:   Sam Ravnborg <sam@ravnborg.org>
To:     wu zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>
Subject: Re: [PATCH v3] MIPS: Clean up the calculation of
        VMLINUZ_LOAD_ADDRESS
Message-ID: <20100602044827.GA6295@merkur.ravnborg.org>
References: <616317d6d889537d03c3c0860231da9a2cce0b69.1275372093.git.wuzhangjin@gmail.com> <20100601152750.GA5131@merkur.ravnborg.org> <AANLkTikR8qY2NwurQ76R1F-AQ4QcmmqXvoWtlOqCB5Ou@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <AANLkTikR8qY2NwurQ76R1F-AQ4QcmmqXvoWtlOqCB5Ou@mail.gmail.com>
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 26982
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: sam@ravnborg.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 980
Content-Length: 557
Lines: 15

> >
> > Note: The load_addr local variable _must_ use "=" asignment
> 
> This is the _key_ stuff. I  tried to use VMLINUZ_LOAD_ADDR(like your
> load_addr) as the load address, but failed all the time, seems I used
> the ":=" assignment, now with "=", it works, thanks!

:= evaluate at once. So the right hand side is executed when Make see the line.
= do late evaluation, so the right hand side is executed/evaluated when
required.

In your case you need the late version because calc_vmlinux_load_Addr needs
to be built before you do the evaluation.

	Sam

From apatard@mandriva.com Wed Jun  2 08:31:31 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 08:31:39 +0200 (CEST)
Received: from mx1.moondrake.net ([212.85.150.166]:45806 "EHLO
        mx1.mandriva.com" rhost-flags-OK-OK-OK-FAIL) by eddie.linux-mips.org
        with ESMTP id S1492537Ab0FBGbb (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 08:31:31 +0200
Received: by mx1.mandriva.com (Postfix, from userid 501)
        id 4119B274015; Wed,  2 Jun 2010 08:31:11 +0200 (CEST)
Received: from office-abk.mandriva.com (unknown [195.7.104.248])
        (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
        (No client certificate requested)
        by mx1.mandriva.com (Postfix) with ESMTP id 1ACFF274012;
        Wed,  2 Jun 2010 08:31:08 +0200 (CEST)
Received: from anduin.mandriva.com (fw2.mandriva.com [192.168.2.3])
        by office-abk.mandriva.com (Postfix) with ESMTP id F247F8499D;
        Wed,  2 Jun 2010 08:50:20 +0200 (CEST)
Received: by anduin.mandriva.com (Postfix, from userid 500)
        id D2FE4FF855; Wed,  2 Jun 2010 08:31:17 +0200 (CEST)
Message-Id: <20100601224232.291773884@n5.mandriva.com>
User-Agent: quilt/0.48-1
Date:   Wed, 02 Jun 2010 00:39:54 +0200
From:   apatard@mandriva.com
To:     linux-mips@linux-mips.org
Cc:     aba@not.so.argh.org
Subject: [patch 1/1] Loongson: define rtc device on mc146818 compatible systems
References: <20100601223953.165137063@n5.mandriva.com>
Content-Disposition: inline; filename=lm2e_rtc.patch
X-archive-position: 26983
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: apatard@mandriva.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1040
Content-Length: 3207
Lines: 104

This patch declare the rtc device present on systems with clock compatible with
the mc146818 and handled by rtc-cmos. I've introduced a new Kconfig entry because
there are some systems without rtc-cmos compatible clock.

Signed-off-by: Arnaud Patard <apatard@mandriva.com>

---
 arch/mips/loongson/Kconfig         |    8 	8 +	0 -	0 !
 arch/mips/loongson/common/Makefile |    1 	1 +	0 -	0 !
 arch/mips/loongson/common/rtc.c    |   43 	43 +	0 -	0 !
 3 files changed, 52 insertions(+)

Index: linux-2.6/arch/mips/loongson/common/Makefile
===================================================================
--- linux-2.6.orig/arch/mips/loongson/common/Makefile
+++ linux-2.6/arch/mips/loongson/common/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GENERIC_GPIO) += gpio.o
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 obj-$(CONFIG_SERIAL_8250) += serial.o
 obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
+obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
 
 #
 # Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure
Index: linux-2.6/arch/mips/loongson/common/rtc.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/mips/loongson/common/rtc.c
@@ -0,0 +1,43 @@
+/*
+ *  Lemote Fuloong platform support
+ *
+ *  Copyright(c) 2010 Arnaud Patard <apatard@mandriva.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mc146818rtc.h>
+
+struct resource loongson_rtc_resources[] = {
+	{
+		.start	= RTC_PORT(0),
+		.end	= RTC_PORT(1),
+		.flags	= IORESOURCE_IO,
+	}, {
+		.start	= RTC_IRQ,
+		.end	= RTC_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device loongson_rtc_device = {
+	.name		= "rtc_cmos",
+	.id		= -1,
+	.resource	= loongson_rtc_resources,
+	.num_resources	= ARRAY_SIZE(loongson_rtc_resources),
+};
+
+
+static int __init loongson_rtc_platform_init(void)
+{
+	platform_device_register(&loongson_rtc_device);
+	return 0;
+}
+
+device_initcall(loongson_rtc_platform_init);
Index: linux-2.6/arch/mips/loongson/Kconfig
===================================================================
--- linux-2.6.orig/arch/mips/loongson/Kconfig
+++ linux-2.6/arch/mips/loongson/Kconfig
@@ -23,6 +23,7 @@ config LEMOTE_FULOONG2E
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select GENERIC_ISA_DMA_SUPPORT_BROKEN
 	select CPU_HAS_WB
+	select LOONGSON_MC146818
 	help
 	  Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
 	  an FPGA northbridge
@@ -51,6 +52,7 @@ config LEMOTE_MACH2F
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select LOONGSON_MC146818
 	help
 	  Lemote Loongson 2F family machines utilize the 2F revision of
 	  Loongson processor and the AMD CS5536 south bridge.
@@ -83,3 +85,9 @@ config LOONGSON_UART_BASE
 	bool
 	default y
 	depends on EARLY_PRINTK || SERIAL_8250
+
+config LOONGSON_MC146818
+	bool
+	default n
+
+



From apatard@mandriva.com Wed Jun  2 08:31:31 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 08:32:09 +0200 (CEST)
Received: from mx1.moondrake.net ([212.85.150.166]:45807 "EHLO
        mx1.mandriva.com" rhost-flags-OK-OK-OK-FAIL) by eddie.linux-mips.org
        with ESMTP id S1492540Ab0FBGbb (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 08:31:31 +0200
Received: by mx1.mandriva.com (Postfix, from userid 501)
        id 14EFB274038; Wed,  2 Jun 2010 08:31:11 +0200 (CEST)
Received: from office-abk.mandriva.com (unknown [195.7.104.248])
        (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
        (No client certificate requested)
        by mx1.mandriva.com (Postfix) with ESMTP id 270F8274015;
        Wed,  2 Jun 2010 08:31:08 +0200 (CEST)
Received: from anduin.mandriva.com (fw2.mandriva.com [192.168.2.3])
        by office-abk.mandriva.com (Postfix) with ESMTP id 043B284A61;
        Wed,  2 Jun 2010 08:50:21 +0200 (CEST)
Received: by anduin.mandriva.com (Postfix, from userid 500)
        id B9215FF869; Wed,  2 Jun 2010 08:31:17 +0200 (CEST)
Message-Id: <20100601223953.165137063@n5.mandriva.com>
User-Agent: quilt/0.48-1
Date:   Wed, 02 Jun 2010 00:39:53 +0200
From:   apatard@mandriva.com
To:     linux-mips@linux-mips.org
Cc:     aba@not.so.argh.org
Subject: [patch 0/1] loongson: enable rtc on rtc-cmos compatibles systems.
X-archive-position: 26984
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: apatard@mandriva.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1041
Content-Length: 145
Lines: 11


Hi,

Now that the rtc-cmos patch has been merged, one can use the rtc-cmos driver
on loongson systems with mc146818 compatible rtc.


Arnaud




From ralf@linux-mips.org Wed Jun  2 09:32:48 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 09:32:55 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:39170 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491112Ab0FBHcs (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 09:32:48 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o527WkZV003731;
        Wed, 2 Jun 2010 08:32:46 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o527WjJT003729;
        Wed, 2 Jun 2010 08:32:45 +0100
Date:   Wed, 2 Jun 2010 08:32:44 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     apatard@mandriva.com
Cc:     linux-mips@linux-mips.org, aba@not.so.argh.org
Subject: Re: [patch 1/1] Loongson: define rtc device on mc146818 compatible
 systems
Message-ID: <20100602073244.GB1962@linux-mips.org>
References: <20100601223953.165137063@n5.mandriva.com>
 <20100601224232.291773884@n5.mandriva.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100601224232.291773884@n5.mandriva.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26985
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1066
Content-Length: 639
Lines: 19

On Wed, Jun 02, 2010 at 12:39:54AM +0200, apatard@mandriva.com wrote:

> This patch declare the rtc device present on systems with clock compatible with
> the mc146818 and handled by rtc-cmos. I've introduced a new Kconfig entry because
> there are some systems without rtc-cmos compatible clock.

Applied, but:

/home/ralf/src/linux/linux-mips/.git/rebase-apply/patch:87: new blank line at EOF.
+
warning: 1 line adds whitespace errors.

Empty lines at end of file, bad karma.  Also to keep log messages in
"git log" under 80 characters, keep posted log messages to at most 76
columns.

Anyway, applied.  Thanks for sorting this!

  Ralf

From yuasa@linux-mips.org Wed Jun  2 09:55:24 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 09:55:27 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:55748 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492550Ab0FBHzY (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 09:55:24 +0200
Received: by pvb32 with SMTP id 32so816302pvb.36
        for <multiple recipients>; Wed, 02 Jun 2010 00:55:15 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:sender:date:from:to:cc
         :subject:message-id:x-mailer:mime-version:content-type
         :content-transfer-encoding;
        bh=Gsf0IrhSxNGEAeEjBxxVyeLcyheItQNjxqFA34GJPV4=;
        b=jvL76SmMT+lT7CS+FtqcOtiPdWge6gPS2Pf4tgEhK6Ew0ZCOTFlcNKAvygeUIJw7Xq
         Lj/AjDp9iVeYyLVI5In0+JCmciTqgQt/U8InwuAVsZTgJVk6uX/PsFDbfLqxon54LPKD
         EQgPwWajRUEB58Ehu35/JpHNhM1Eqc/58B2xA=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=sender:date:from:to:cc:subject:message-id:x-mailer:mime-version
         :content-type:content-transfer-encoding;
        b=JSz6hm+B5d08sCmu8wjXkGI3+rOUZQHnzdriHBSOwvmhHFKuOZr6HopckyLPsc1rVS
         3dbubUXqdMxK+TcKDSKGgrJ/c5KkYjbbaFpxhAq8wiu7pDE0nEO4a2N6ol5LL71xtJRU
         e4AtChoLwT0x0GjvlASKL4CfKgmf06S/4Wg2E=
Received: by 10.115.134.14 with SMTP id l14mr6508849wan.184.1275465315104;
        Wed, 02 Jun 2010 00:55:15 -0700 (PDT)
Received: from stratos (sannin29006.nirai.ne.jp [203.160.29.6])
        by mx.google.com with ESMTPS id n32sm66784800wae.22.2010.06.02.00.55.12
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 00:55:13 -0700 (PDT)
Date:   Wed, 2 Jun 2010 16:51:16 +0900
From:   Yoichi Yuasa <yuasa@linux-mips.org>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     yuasa@linux-mips.org, linux-mips <linux-mips@linux-mips.org>
Subject: [PATCH -queue 1/2] MIPS: Move Cobalt Makefile parts to their own
 Platform file
Message-Id: <20100602165116.3d8aae62.yuasa@linux-mips.org>
X-Mailer: Sylpheed 3.0.2 (GTK+ 2.16.6; x86_64-unknown-linux-gnu)
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
X-archive-position: 26986
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: yuasa@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1085
Content-Length: 1948
Lines: 63

Signed-off-by: Yoichi Yuasa <yuasa@linux-mips.org>
---
 arch/mips/Kbuild.platforms |    1 +
 arch/mips/Makefile         |    7 -------
 arch/mips/cobalt/Makefile  |    2 --
 arch/mips/cobalt/Platform  |    6 ++++++
 4 files changed, 7 insertions(+), 9 deletions(-)
 create mode 100644 arch/mips/cobalt/Platform

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 77e48b9..6c163c2 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
 
 platforms += alchemy
 platforms += ar7
+platforms += cobalt
 platforms += loongson
 platforms += mipssim
 platforms += sgi-ip27
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 090c969..6b6dc42 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -199,13 +199,6 @@ cflags-$(CONFIG_MACH_JAZZ)	+= -I$(srctree)/arch/mips/include/asm/mach-jazz
 load-$(CONFIG_MACH_JAZZ)	+= 0xffffffff80080000
 
 #
-# Cobalt Server
-#
-core-$(CONFIG_MIPS_COBALT)	+= arch/mips/cobalt/
-cflags-$(CONFIG_MIPS_COBALT)	+= -I$(srctree)/arch/mips/include/asm/mach-cobalt
-load-$(CONFIG_MIPS_COBALT)	+= 0xffffffff80080000
-
-#
 # DECstation family
 #
 core-$(CONFIG_MACH_DECSTATION)	+= arch/mips/dec/
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 2379262..61a334a 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -7,5 +7,3 @@ obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= mtd.o
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/cobalt/Platform b/arch/mips/cobalt/Platform
new file mode 100644
index 0000000..34123ef
--- /dev/null
+++ b/arch/mips/cobalt/Platform
@@ -0,0 +1,6 @@
+#
+# Cobalt Server
+#
+platform-$(CONFIG_MIPS_COBALT)	+= cobalt/
+cflags-$(CONFIG_MIPS_COBALT)	+= -I$(srctree)/arch/mips/include/asm/mach-cobalt
+load-$(CONFIG_MIPS_COBALT)	+= 0xffffffff80080000
-- 
1.7.1

From yuasa@linux-mips.org Wed Jun  2 09:55:27 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 09:55:54 +0200 (CEST)
Received: from mail-pz0-f197.google.com ([209.85.222.197]:55355 "EHLO
        mail-pz0-f197.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492554Ab0FBHz1 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 09:55:27 +0200
Received: by pzk35 with SMTP id 35so909179pzk.0
        for <multiple recipients>; Wed, 02 Jun 2010 00:55:19 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:sender:date:from:to:cc
         :subject:message-id:in-reply-to:references:x-mailer:mime-version
         :content-type:content-transfer-encoding;
        bh=BVHO8b2ehr74ZUiRhTAeWNGOPS+mov5wG83wXgUeE64=;
        b=MizZ/SAOawberxP+5DIES4+YK7eO8L8LekWT8WBUkBtRdezGBSIOSSLfjtHw9eFarU
         Z41+aZbeTY/x4nPMbTOSjADnFmRU0rfAC+o/8JQsh4NLP7Gl6ebLbd9RaQt1t4Soao4k
         EqOYSQTfUahbslmksCTtUY50LI9cuCJnhFZlw=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=sender:date:from:to:cc:subject:message-id:in-reply-to:references
         :x-mailer:mime-version:content-type:content-transfer-encoding;
        b=Mp13/iHC+QIpprp15NM4DyCd+8prn9KSLObXjUk9jT+F7Y0dc6GFvQq3F52nM98yUZ
         yw6McjtzrNU35PRFrHE7dloc4VwRWRMY+8bsaX9ZXCtDeeol5I2bLAxC9UdBXSqyHRUE
         GPTXwTJbaMN3233KU3dhmNcnP20ToB4N75aBg=
Received: by 10.115.66.33 with SMTP id t33mr6492006wak.199.1275465319441;
        Wed, 02 Jun 2010 00:55:19 -0700 (PDT)
Received: from stratos (sannin29006.nirai.ne.jp [203.160.29.6])
        by mx.google.com with ESMTPS id f11sm66781301wai.23.2010.06.02.00.55.17
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 00:55:18 -0700 (PDT)
Date:   Wed, 2 Jun 2010 16:52:21 +0900
From:   Yoichi Yuasa <yuasa@linux-mips.org>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     yuasa@linux-mips.org, linux-mips <linux-mips@linux-mips.org>
Subject: [PATCH -queue 2/2] MIPS: Move VR41xx Makefile parts to their own
 Platform file
Message-Id: <20100602165221.76438760.yuasa@linux-mips.org>
In-Reply-To: <20100602165116.3d8aae62.yuasa@linux-mips.org>
References: <20100602165116.3d8aae62.yuasa@linux-mips.org>
X-Mailer: Sylpheed 3.0.2 (GTK+ 2.16.6; x86_64-unknown-linux-gnu)
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
X-archive-position: 26987
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: yuasa@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1086
Content-Length: 3310
Lines: 115

Signed-off-by: Yoichi Yuasa <yuasa@linux-mips.org>
---
 arch/mips/Kbuild.platforms       |    1 +
 arch/mips/Makefile               |   33 ---------------------------------
 arch/mips/vr41xx/Platform        |   32 ++++++++++++++++++++++++++++++++
 arch/mips/vr41xx/common/Makefile |    2 --
 4 files changed, 33 insertions(+), 35 deletions(-)
 create mode 100644 arch/mips/vr41xx/Platform

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 6c163c2..9b6e8d7 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -6,6 +6,7 @@ platforms += cobalt
 platforms += loongson
 platforms += mipssim
 platforms += sgi-ip27
+platforms += vr41xx
 
 # include the platform specific files
 include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6b6dc42..6997faa 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -243,39 +243,6 @@ core-$(CONFIG_LASAT)		+= arch/mips/lasat/
 cflags-$(CONFIG_LASAT)		+= -I$(srctree)/arch/mips/include/asm/mach-lasat
 load-$(CONFIG_LASAT)		+= 0xffffffff80000000
 
-#
-# Common VR41xx
-#
-core-$(CONFIG_MACH_VR41XX)	+= arch/mips/vr41xx/common/
-cflags-$(CONFIG_MACH_VR41XX)	+= -I$(srctree)/arch/mips/include/asm/mach-vr41xx
-
-#
-# ZAO Networks Capcella (VR4131)
-#
-load-$(CONFIG_ZAO_CAPCELLA)	+= 0xffffffff80000000
-
-#
-# Victor MP-C303/304 (VR4122)
-#
-load-$(CONFIG_VICTOR_MPC30X)	+= 0xffffffff80001000
-
-#
-# IBM WorkPad z50 (VR4121)
-#
-core-$(CONFIG_IBM_WORKPAD)	+= arch/mips/vr41xx/ibm-workpad/
-load-$(CONFIG_IBM_WORKPAD)	+= 0xffffffff80004000
-
-#
-# CASIO CASSIPEIA E-55/65 (VR4111)
-#
-core-$(CONFIG_CASIO_E55)	+= arch/mips/vr41xx/casio-e55/
-load-$(CONFIG_CASIO_E55)	+= 0xffffffff80004000
-
-#
-# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131)
-#
-load-$(CONFIG_TANBAC_TB022X)	+= 0xffffffff80000000
-
 # NXP STB225
 core-$(CONFIG_SOC_PNX833X)		+= arch/mips/nxp/pnx833x/common/
 cflags-$(CONFIG_SOC_PNX833X)	+= -Iarch/mips/include/asm/mach-pnx833x
diff --git a/arch/mips/vr41xx/Platform b/arch/mips/vr41xx/Platform
new file mode 100644
index 0000000..b6c8d5c
--- /dev/null
+++ b/arch/mips/vr41xx/Platform
@@ -0,0 +1,32 @@
+#
+# NEC VR4100 series based machines
+#
+platform-$(CONFIG_MACH_VR41XX)	+= vr41xx/common/
+cflags-$(CONFIG_MACH_VR41XX)	+= -I$(srctree)/arch/mips/include/asm/mach-vr41xx
+
+#
+# CASIO CASSIPEIA E-55/65 (VR4111)
+#
+platform-$(CONFIG_CASIO_E55)	+= vr41xx/casio-e55/
+load-$(CONFIG_CASIO_E55)	+= 0xffffffff80004000
+
+#
+# IBM WorkPad z50 (VR4121)
+#
+platform-$(CONFIG_IBM_WORKPAD)	+= vr41xx/ibm-workpad/
+load-$(CONFIG_IBM_WORKPAD)	+= 0xffffffff80004000
+
+#
+# TANBAC VR4131 multichip module(TB0225) and TANBAC VR4131DIMM(TB0229) (VR4131)
+#
+load-$(CONFIG_TANBAC_TB022X)	+= 0xffffffff80000000
+
+#
+# Victor MP-C303/304 (VR4122)
+#
+load-$(CONFIG_VICTOR_MPC30X)	+= 0xffffffff80001000
+
+#
+# ZAO Networks Capcella (VR4131)
+#
+load-$(CONFIG_ZAO_CAPCELLA)	+= 0xffffffff80000000
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index 7d5d83b..d0d84ec 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -3,5 +3,3 @@
 #
 
 obj-y	+= bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o
-
-EXTRA_CFLAGS += -Werror
-- 
1.7.1

From ralf@linux-mips.org Wed Jun  2 10:08:42 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:08:45 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:52491 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1490962Ab0FBIIm (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 10:08:42 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o5288cuA007385;
        Wed, 2 Jun 2010 09:08:40 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o5288aKt007383;
        Wed, 2 Jun 2010 09:08:37 +0100
Date:   Wed, 2 Jun 2010 09:08:35 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Yoichi Yuasa <yuasa@linux-mips.org>
Cc:     linux-mips <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue 1/2] MIPS: Move Cobalt Makefile parts to their own
 Platform file
Message-ID: <20100602080835.GA6402@linux-mips.org>
References: <20100602165116.3d8aae62.yuasa@linux-mips.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100602165116.3d8aae62.yuasa@linux-mips.org>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26988
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1093
Content-Length: 47
Lines: 3

Queued for 2.6.36.  Thanks Yoichi-San!

  Ralf

From ralf@linux-mips.org Wed Jun  2 10:08:49 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:09:10 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:52493 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491112Ab0FBIIt (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 10:08:49 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o5288m8m007391;
        Wed, 2 Jun 2010 09:08:48 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o5288mow007390;
        Wed, 2 Jun 2010 09:08:48 +0100
Date:   Wed, 2 Jun 2010 09:08:48 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Yoichi Yuasa <yuasa@linux-mips.org>
Cc:     linux-mips <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue 2/2] MIPS: Move VR41xx Makefile parts to their own
 Platform file
Message-ID: <20100602080848.GB6402@linux-mips.org>
References: <20100602165116.3d8aae62.yuasa@linux-mips.org>
 <20100602165221.76438760.yuasa@linux-mips.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100602165221.76438760.yuasa@linux-mips.org>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26989
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1094
Content-Length: 47
Lines: 3

Queued for 2.6.36.  Thanks Yoichi-San!

  Ralf

From Anoop_P.A@pmc-sierra.com Wed Jun  2 10:10:31 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:10:35 +0200 (CEST)
Received: from bby1mta03.pmc-sierra.com ([216.241.235.118]:45383 "EHLO
        bby1mta03.pmc-sierra.bc.ca" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491112Ab0FBIKb convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 10:10:31 +0200
Received: from bby1mta03.pmc-sierra.bc.ca (localhost.pmc-sierra.bc.ca [127.0.0.1])
        by localhost (Postfix) with SMTP id CF4CF1070082;
        Wed,  2 Jun 2010 01:10:19 -0700 (PDT)
Received: from bby1exg02.pmc_nt.nt.pmc-sierra.bc.ca (BBY1EXG02.pmc-sierra.bc.ca [216.241.231.167])
        by bby1mta03.pmc-sierra.bc.ca (Postfix) with SMTP id B9554107007C;
        Wed,  2 Jun 2010 01:10:19 -0700 (PDT)
Received: from BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca ([216.241.231.157]) by bby1exg02.pmc_nt.nt.pmc-sierra.bc.ca with Microsoft SMTPSVC(6.0.3790.4675);
         Wed, 2 Jun 2010 01:10:20 -0700
X-MimeOLE: Produced By Microsoft Exchange V6.5
Content-class: urn:content-classes:message
MIME-Version: 1.0
Content-Type: text/plain;
        charset="US-ASCII"
Content-Transfer-Encoding: 8BIT
Subject: RE: TITAN GE driver
Date:   Wed, 2 Jun 2010 01:10:17 -0700
Message-ID: <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
In-Reply-To: <20100528162722.GB7148@linux-mips.org>
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
Thread-Topic: TITAN GE driver
Thread-Index: Acr+gscrweuzBuNZSFmHArD+k3R8+ADpIFBA
References: <A7DEA48C84FD0B48AAAE33F328C0201404E2D834@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca> <20100528162722.GB7148@linux-mips.org>
From:   "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
To:     "Ralf Baechle" <ralf@linux-mips.org>
Cc:     "linux-mips" <linux-mips@linux-mips.org>
X-OriginalArrivalTime: 02 Jun 2010 08:10:20.0107 (UTC) FILETIME=[0AF811B0:01CB022B]
X-archive-position: 26990
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: Anoop_P.A@pmc-sierra.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1095
Content-Length: 1574
Lines: 49

Hi,

>From the datasheets and design discussion it looks like prefix has been
designed to be static i.e they are expecting all buffers to get
allocated with same prefix. In another words all the buffers should be
below < 0x1fff_ffff ( physical address) or between 0x2000_0000 and
0x3fff_ffff like that.

Is there any way to force kmalloc to allocate memory in certain region
or below some region?

Thanks
Anoop

> -----Original Message-----
> From: linux-mips-bounce@linux-mips.org
[mailto:linux-mips-bounce@linux-
> mips.org] On Behalf Of Ralf Baechle
> Sent: Friday, May 28, 2010 9:57 PM
> To: Anoop P.A.
> Cc: linux-mips
> Subject: Re: TITAN GE driver
> 
> On Thu, May 27, 2010 at 10:51:47PM -0700, Anoop P.A. wrote:
> 
> > Any body used titan GE device with more than 512MB physical memory?
> >
> >
> >
> > If buffer is getting allocated above physical address 0x1fff_ffff (
ie.
> > 30 bit buffer address) we may have to consider setting
XDMA_BUFFADDRPRE
> > (0x5018 ) .This is not taken care in original driver.  Any body had
luck
> > in enabling this prefix. I have tried enabling it and I could do
flood
> > ping with out packet loss. However when I do mass data transfer
kernel
> > getting panic. Further investigation showed kenel panics because DMA
> > copies data to wrong address (which is being used).
> 
> The driver has not been used in ages so it's generally in a sad shape,
> doesn't even compile.  I think nobody touched this driver seriously in
> 5 years, probably longer.  So it's sort of expected to eat your cat or
> do other nasty stuff.
> 
>   Ralf


From ralf@linux-mips.org Wed Jun  2 10:32:58 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:33:02 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:46143 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492556Ab0FBIc6 (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 10:32:58 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o528Wv7B009830;
        Wed, 2 Jun 2010 09:32:57 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o528WuX6009828;
        Wed, 2 Jun 2010 09:32:56 +0100
Date:   Wed, 2 Jun 2010 09:32:56 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
Cc:     linux-mips <linux-mips@linux-mips.org>
Subject: Re: TITAN GE driver
Message-ID: <20100602083255.GA23868@linux-mips.org>
References: <A7DEA48C84FD0B48AAAE33F328C0201404E2D834@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
 <20100528162722.GB7148@linux-mips.org>
 <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 26991
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1106
Content-Length: 699
Lines: 16

On Wed, Jun 02, 2010 at 01:10:17AM -0700, Anoop P.A. wrote:

> >From the datasheets and design discussion it looks like prefix has been
> designed to be static i.e they are expecting all buffers to get
> allocated with same prefix. In another words all the buffers should be
> below < 0x1fff_ffff ( physical address) or between 0x2000_0000 and
> 0x3fff_ffff like that.
> 
> Is there any way to force kmalloc to allocate memory in certain region
> or below some region?

Nothing that would uniformly work for 32-bit and 64-bit kernels and also
Linux only has flags that allocate below certain addresses; nothing that
tells the allocator "give me something between 0x20000000 and 0x3fffffff".

  Ralf

From wuzhangjin@gmail.com Wed Jun  2 10:35:45 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:35:52 +0200 (CEST)
Received: from mail-iw0-f177.google.com ([209.85.214.177]:48357 "EHLO
        mail-iw0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491203Ab0FBIfp (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 10:35:45 +0200
Received: by iwn34 with SMTP id 34so552102iwn.36
        for <multiple recipients>; Wed, 02 Jun 2010 01:35:42 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=acpPPS335cajF56yrAW22OruOn6uR2fZBOlmpCpvkEw=;
        b=fJWM6rGpkSlIBa+oLRygW7Q5t2W9oUmMbA/ib/BuHE6KgRSJ9D3o/3/GACMNvVCMWL
         4Mu1tv9Rzo4tO3v+Ld6dqPPqtfCh0LoKc66Q+WKyRDahMTsVptmTVoWngfYROCF3aNjb
         3EmpnMx0GZWPI6exHQ3/mhG7TAGtkQSc2Hmww=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=edeM31buDstO6XPiNagJIbOIbLPockLz77uQg6kpww87zXe5Q5MO1peARvic8fhw7K
         Yia4LeDf0vKjy4mGU3zloWVlbLZ+LcZ7diW27+iC/aMwUXUJKWMLUWWJoh4Nrwg7RiEh
         njCPUYbTIO1r3hhJX9dGJtWy9bCM8HVSzJXHk=
Received: by 10.231.195.16 with SMTP id ea16mr9333299ibb.64.1275467742139;
        Wed, 02 Jun 2010 01:35:42 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id d9sm35557897ibl.10.2010.06.02.01.35.38
        (version=SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 01:35:41 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH v2] MIPS: Unify the suffix of compressed vmlinux.bin
Date:   Wed,  2 Jun 2010 16:35:24 +0800
Message-Id: <9890d1383c75ce6df44d357687a9c4e2d6ba4050.1275438553.git.wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26992
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1107
Content-Length: 1878
Lines: 50

The compressed vmlinux.bin is only a temp file, we can use the same suffix(.z)
for them(.gz,.lzo,.lzma...) to remove several lines and simpify the
maintaining(no need to add the "suffix_$(xxx) := suffix" line).

Changes:

  v1 -> v2:
    o Rename vmlinux.z to vmlinux.bin.z for vmlinux.z here is the compressed
    vmlinux.bin, not compressed vmlinux.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/boot/compressed/Makefile |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 74a52d7..a517f58 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -48,23 +48,19 @@ OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
 $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
 	$(call if_changed,objcopy)
 
-suffix_$(CONFIG_KERNEL_GZIP)  = gz
-suffix_$(CONFIG_KERNEL_BZIP2) = bz2
-suffix_$(CONFIG_KERNEL_LZMA)  = lzma
-suffix_$(CONFIG_KERNEL_LZO)   = lzo
 tool_$(CONFIG_KERNEL_GZIP)    = gzip
 tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
 tool_$(CONFIG_KERNEL_LZMA)    = lzma
 tool_$(CONFIG_KERNEL_LZO)     = lzo
 
-targets += vmlinux.gz vmlinux.bz2 vmlinux.lzma vmlinux.lzo
-$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin FORCE
+targets += vmlinux.bin.z
+$(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,$(tool_y))
 
 targets += piggy.o
-OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.$(suffix_y) \
+OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.bin.z \
                         --set-section-flags=.image=contents,alloc,load,readonly,data
-$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.$(suffix_y) FORCE
+$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
 	$(call if_changed,objcopy)
 
 LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
-- 
1.6.5


From wuzhangjin@gmail.com Wed Jun  2 10:35:47 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:36:19 +0200 (CEST)
Received: from mail-iw0-f177.google.com ([209.85.214.177]:48357 "EHLO
        mail-iw0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1490962Ab0FBIfr (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 10:35:47 +0200
Received: by mail-iw0-f177.google.com with SMTP id 34so552102iwn.36
        for <multiple recipients>; Wed, 02 Jun 2010 01:35:46 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer:in-reply-to:references;
        bh=s6bXI8dFczbIKVHlS/hHi1Cbq+nZCkxV58jG5LsO2zg=;
        b=VDl9fRtSU4890Kdk5vNo3IwocrafoSkj55YfzQFFNKggSCIvnruTp7kWWYc/zftj5q
         Ml7sQ5xIWAE6aRM7FKDBuhT+6BHOXUZxv+sWOOMPpOJ3ufYgK9eNj81cMl/KQTFtpv/u
         M5mJUIo19Hsqk5zzd6widfZaGrQCRVX1yFnwk=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;
        b=laqtQZeRslicxWGk3hdIkTSPYpl6gyc2pf81L9Wgbhz307/nQVJdWIEZa4CEOWE2P4
         Uk/O9AEaj9Xj2oAFHSLICEvcSy2Adhw48GRUp5ZYEoQWyfxhLfE9KQVv8+r4sjd/8dA+
         JnFRFvy+Nbpt5JJrSFbYpFe+UlzFXvxYsNQ/A=
Received: by 10.231.120.69 with SMTP id c5mr9432021ibr.79.1275467746666;
        Wed, 02 Jun 2010 01:35:46 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id d9sm35557897ibl.10.2010.06.02.01.35.42
        (version=SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 01:35:46 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>,
        Sam Ravnborg <sam@ravnborg.org>,
        Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH v4] MIPS: Clean up the calculation of VMLINUZ_LOAD_ADDRESS
Date:   Wed,  2 Jun 2010 16:35:25 +0800
Message-Id: <96f3b48ba7f749c4357760008cdae644aa55b92d.1275438520.git.wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
In-Reply-To: <9890d1383c75ce6df44d357687a9c4e2d6ba4050.1275438553.git.wuzhangjin@gmail.com>
References: <9890d1383c75ce6df44d357687a9c4e2d6ba4050.1275438553.git.wuzhangjin@gmail.com>
X-archive-position: 26993
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1109
Content-Length: 5263
Lines: 154

We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is indecipherable. This
patch rewrites it in C.

Changes:

v3 -> v4: (feedback from Sam Ravnborg)
  o Makefile: Follow the 80 characters' limit and Remove an un-needed objcopy.
  o calc_vmlinuz_load_addr.c: Use a smaller alignment and Add more comments

v2 -> v3: (feedback from Alexander Clouter)
  o Drop the unneeded variable n
  o Replace the last "unsigned long long" by uint64_t

v1 -> v2: (feedback from Alexander Clouter)
  o make it more portable
    use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
    instead of "unsigned long long".
  o add a missing return value
    return EXIT_FAILURE if sscanf() not return 1

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/boot/.gitignore                          |    1 +
 arch/mips/boot/compressed/Makefile                 |   26 +++++-----
 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c |   57 ++++++++++++++++++++
 3 files changed, 71 insertions(+), 13 deletions(-)
 create mode 100644 arch/mips/boot/compressed/calc_vmlinuz_load_addr.c

diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
index 4667a5f..f210b09 100644
--- a/arch/mips/boot/.gitignore
+++ b/arch/mips/boot/.gitignore
@@ -3,3 +3,4 @@ elf2ecoff
 vmlinux.*
 zImage
 zImage.tmp
+calc_vmlinuz_load_addr
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index a517f58..9ef6e2f 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -12,14 +12,6 @@
 # Author: Wu Zhangjin <wuzhangjin@gmail.com>
 #
 
-# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
-VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
-VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo -n $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
-# VMLINUZ_LOAD_ADDRESS = concat "high32 of VMLINUX_LOAD_ADDRESS" and "(low32 of VMLINUX_LOAD_ADDRESS) + VMLINUX_SIZE"
-HIGH32 := $(shell A=$(VMLINUX_LOAD_ADDRESS); [ $${\#A} -gt 10 ] && expr substr "$(VMLINUX_LOAD_ADDRESS)" 3 $$(($${\#A} - 10)))
-LOW32 := $(shell [ -n "$(HIGH32)" ] && A=11 || A=3; expr substr "$(VMLINUX_LOAD_ADDRESS)" $${A} 8)
-VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" -a -n "$(LOW32)" ] && printf "$(HIGH32)%08x" $$(($(VMLINUX_SIZE) + 0x$(LOW32))))
-
 # set the default size of the mallocing area for decompressing
 BOOT_HEAP_SIZE := 0x400000
 
@@ -63,10 +55,18 @@ OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.bin.z \
 $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
 	$(call if_changed,objcopy)
 
-LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
-vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/piggy.o
-	$(call cmd,ld)
-	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) $@
+# Calculate the load address of the compressed kernel image
+hostprogs-y := calc_vmlinuz_load_addr
+
+VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
+		$(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS))
+
+vmlinuzobjs-y += $(obj)/piggy.o
+
+quiet_cmd_zld = LD      $@
+      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@
+vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
+	$(call cmd,zld)
 
 #
 # Some DECstations need all possible sections of an ECOFF executable
@@ -76,7 +76,7 @@ ifdef CONFIG_MACH_DECSTATION
 endif
 
 # elf2ecoff can only handle 32bit image
-hostprogs-y := ../elf2ecoff
+hostprogs-y += ../elf2ecoff
 
 ifdef CONFIG_32BIT
 	VMLINUZ = vmlinuz
diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
new file mode 100644
index 0000000..88c9d96
--- /dev/null
+++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 "Wu Zhangjin" <wuzhangjin@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+	struct stat sb;
+	uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
+				argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	if (stat(argv[1], &sb) == -1) {
+		perror("stat");
+		return EXIT_FAILURE;
+	}
+
+	/* Convert hex characters to dec number */
+	errno = 0;
+	if (sscanf(argv[2], "%llx", &vmlinux_load_addr) != 1) {
+		if (errno != 0)
+			perror("sscanf");
+		else
+			fprintf(stderr, "No matching characters\n");
+
+		return EXIT_FAILURE;
+	}
+
+	vmlinux_size = (uint64_t)sb.st_size;
+	vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
+
+	/*
+	 * Align with 16 bytes: "greater than that used for any standard data
+	 * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition).
+	 */
+
+	vmlinuz_load_addr += (16 - vmlinux_size % 16);
+
+	printf("0x%llx\n", vmlinuz_load_addr);
+
+	return EXIT_SUCCESS;
+}
-- 
1.6.5


From randomizedthinking@gmail.com Wed Jun  2 10:48:52 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:48:59 +0200 (CEST)
Received: from mail-vw0-f49.google.com ([209.85.212.49]:48175 "EHLO
        mail-vw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491861Ab0FBIsw (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 10:48:52 +0200
Received: by vws7 with SMTP id 7so7507384vws.36
        for <multiple recipients>; Wed, 02 Jun 2010 01:48:44 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:date:message-id
         :subject:from:to:cc:content-type;
        bh=gjMM8VtptnTKe6tS+gMPmay9MLbKCYnCnu/DT+1QA/o=;
        b=FHla/9pv3wGJUEexBQhfHTWXeaF6Ckb1agswFv6fM/8Ph+M1N2fe2XYEI7xi48xKr2
         xj6FPckx1Nw3/5NMVfHgDH1eUvB5lo+ipVhmkPaa0Re+zVB22ioJBoJfTMkF6eCRPsgd
         rUdJ1OV77l1b8qtg/yroVa9RjJGI1JCegObsI=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:date:message-id:subject:from:to:cc:content-type;
        b=RwpZeVrSoBHcDM+1NQOs2xq/Hu7gNisAVu4ix7fXp1RXqtXOaPmRPlmhqL2ovuanaH
         2FqG+QgR/k1xNWw7UtSgkimzZh0o8p8WqtA08RdxNbdbWuHJalip4bUHNtUzCS+bDfY1
         bLp5eKAWGuJF9e39pLNrE6qizo2Ak2z3id0Tc=
MIME-Version: 1.0
Received: by 10.224.41.14 with SMTP id m14mr3021810qae.336.1275468523884; Wed, 
        02 Jun 2010 01:48:43 -0700 (PDT)
Received: by 10.229.232.141 with HTTP; Wed, 2 Jun 2010 01:48:43 -0700 (PDT)
Date:   Wed, 2 Jun 2010 01:48:43 -0700
Message-ID: <AANLkTilcSFUBHXHHttcXFVToL8waTmlxmts-elClSJar@mail.gmail.com>
Subject: [loongson2-PATCH] modification of the cpufreq module
From:   Gang Liang <randomizedthinking@gmail.com>
To:     linux-mips@linux-mips.org, Ralf Baechle <ralf@linux-mips.org>
Cc:     Zhangjin Wu <wuzhangjin@gmail.com>, Hua Yan <yanh@lemote.com>
Content-Type: text/plain; charset=ISO-8859-1
X-archive-position: 26994
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: randomizedthinking@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1117
Content-Length: 9373
Lines: 300

This patch updates some aspects of the current implementation of
cpufreq driver for Loongson2.

1) A default cpu_wait handler is installed such that the cpu will be
alive at the lowest possible power level when a cpu_wait call is made;

2) The number of frequency levels is reduced to 3, and the lowest
frequency is capped as a half of the full cpu speed. The "nowait" option
is removed.

Thanks!

---
 arch/mips/include/asm/mach-loongson/loongson.h |    4 +-
 arch/mips/kernel/cpu-probe.c                   |   21 +++++++++
 arch/mips/kernel/cpufreq/loongson2_clock.c     |   52 +++--------------------
 arch/mips/kernel/cpufreq/loongson2_cpufreq.c   |   54 +++++++++---------------
 4 files changed, 50 insertions(+), 81 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson/loongson.h
b/arch/mips/include/asm/mach-loongson/loongson.h
index 53d0bef..33164b9 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -242,8 +242,8 @@ extern int mach_i8259_irq(void);

 #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
 #include <linux/cpufreq.h>
-extern void loongson2_cpu_wait(void);
-extern struct cpufreq_frequency_table loongson2_clockmod_table[];
+/* extern void loongson2_cpu_wait(void); */
+/* extern struct cpufreq_frequency_table loongson2_clockmod_table[]; */

 /* Chip Config */
 #define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index be5bb16..5b3072c 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -25,6 +25,9 @@
 #include <asm/system.h>
 #include <asm/watch.h>
 #include <asm/spram.h>
+
+#include <loongson.h>
+
 /*
  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
  * the implementation of the "wait" feature differs between CPU families. This
@@ -51,6 +54,21 @@ static void r39xx_wait(void)

 extern void r4k_wait(void);

+DEFINE_SPINLOCK(loongson2_wait_lock);
+static void loongson2_cpu_wait(void)
+{
+    u32 cpu_freq;
+    unsigned long flags;
+
+    /* enter the lowest power mode available while still alive */
+    /* future work: check cpu freq -- do nothing if no change */
+    /* otherwise, change the frequency and propagate the clock rate */
+    spin_lock_irqsave(&loongson2_wait_lock, flags);
+    cpu_freq = LOONGSON_CHIPCFG0;
+	LOONGSON_CHIPCFG0 = (cpu_freq & ~0x7) | 1;
+    spin_unlock_irqrestore(&loongson2_wait_lock, flags);
+}
+
 /*
  * This variant is preferable as it allows testing need_resched and going to
  * sleep depending on the outcome atomically.  Unfortunately the "It is
@@ -212,6 +230,9 @@ void __init check_wait(void)
 		if ((c->processor_id & 0x00ff) >= 0x40)
 			cpu_wait = r4k_wait;
 		break;
+    case CPU_LOONGSON2:
+        cpu_wait = loongson2_cpu_wait;
+        break;
 	default:
 		break;
 	}
diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c
b/arch/mips/kernel/cpufreq/loongson2_clock.c
index cefc6e2..0b30fe9 100644
--- a/arch/mips/kernel/cpufreq/loongson2_clock.c
+++ b/arch/mips/kernel/cpufreq/loongson2_clock.c
@@ -18,25 +18,7 @@ static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
 static DEFINE_MUTEX(clock_list_sem);

-/* Minimum CLK support */
-enum {
-	DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
-	DC_87PT, DC_DISABLE, DC_RESV
-};
-
-struct cpufreq_frequency_table loongson2_clockmod_table[] = {
-	{DC_RESV, CPUFREQ_ENTRY_INVALID},
-	{DC_ZERO, CPUFREQ_ENTRY_INVALID},
-	{DC_25PT, 0},
-	{DC_37PT, 0},
-	{DC_50PT, 0},
-	{DC_62PT, 0},
-	{DC_75PT, 0},
-	{DC_87PT, 0},
-	{DC_DISABLE, 0},
-	{DC_RESV, CPUFREQ_TABLE_END},
-};
-EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
+#define LS2_MAX_CPUFREQ_LEVEL 8

 static struct clk cpu_clk = {
 	.name = "cpu_clk",
@@ -109,21 +91,15 @@ int clk_set_rate_ex(struct clk *clk, unsigned
long rate, int algo_id)
 	if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
 		propagate_rate(clk);

-	for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
-	     i++) {
-		if (loongson2_clockmod_table[i].frequency ==
-		    CPUFREQ_ENTRY_INVALID)
-			continue;
-		if (rate == loongson2_clockmod_table[i].frequency)
-			break;
-	}
-	if (rate != loongson2_clockmod_table[i].frequency)
-		return -ENOTSUPP;
+    i = rate * LS2_MAX_CPUFREQ_LEVEL / cpu_clock_freq;
+    if ( i < 1 || i > LS2_MAX_CPUFREQ_LEVEL )
+        return -ENOTSUPP;

-	clk->rate = rate;
+    /* indeed, a rounded rate is assigned */
+	clk->rate = i * (cpu_clock_freq / LS2_MAX_CPUFREQ_LEVEL);

 	regval = LOONGSON_CHIPCFG0;
-	regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
+	regval = (regval & ~0x7) | i;
 	LOONGSON_CHIPCFG0 = regval;

 	return ret;
@@ -151,20 +127,6 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
  * interrupt disabled content
  */

-DEFINE_SPINLOCK(loongson2_wait_lock);
-void loongson2_cpu_wait(void)
-{
-	u32 cpu_freq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&loongson2_wait_lock, flags);
-	cpu_freq = LOONGSON_CHIPCFG0;
-	LOONGSON_CHIPCFG0 &= ~0x7;	/* Put CPU into wait mode */
-	LOONGSON_CHIPCFG0 = cpu_freq;	/* Restore CPU state */
-	spin_unlock_irqrestore(&loongson2_wait_lock, flags);
-}
-EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
-
 MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
 MODULE_DESCRIPTION("cpufreq driver for Loongson 2F");
 MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
index 2f6a0b1..0488945 100644
--- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
+++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
@@ -21,11 +21,16 @@

 #include <loongson.h>

-static uint nowait;
+#define LS2_CPUFREQ_LEVEL 3

 static struct clk *cpuclk;

-static void (*saved_cpu_wait) (void);
+struct cpufreq_frequency_table loongson2_clockmod_table[] = {
+	{0, 0},
+	{1, 0},
+	{2, 0},
+	{ .frequency = CPUFREQ_TABLE_END },
+};

 static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
 					unsigned long val, void *data);
@@ -67,14 +72,11 @@ static int loongson2_cpufreq_target(struct
cpufreq_policy *policy,
 	cpus_allowed = current->cpus_allowed;
 	set_cpus_allowed(current, cpumask_of_cpu(cpu));

-	if (cpufreq_frequency_table_target
-	    (policy, &loongson2_clockmod_table[0], target_freq, relation,
-	     &newstate))
+	if (cpufreq_frequency_table_target (policy,
+			&loongson2_clockmod_table[0], target_freq, relation, &newstate))
 		return -EINVAL;

-	freq =
-	    ((cpu_clock_freq / 1000) *
-	     loongson2_clockmod_table[newstate].index) / 8;
+	freq = loongson2_clockmod_table[newstate].frequency;
 	if (freq < policy->min || freq > policy->max)
 		return -EINVAL;

@@ -88,15 +90,10 @@ static int loongson2_cpufreq_target(struct
cpufreq_policy *policy,
 	if (freqs.new == freqs.old)
 		return 0;

-	/* notifiers */
+	/* change cpu clock between notifier pairs */
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
 	set_cpus_allowed(current, cpus_allowed);
-
-	/* setting the cpu frequency */
 	clk_set_rate(cpuclk, freq);
-
-	/* notifiers */
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);

 	pr_debug("cpufreq: set frequency %u kHz\n", freq);
@@ -121,11 +118,12 @@ static int loongson2_cpufreq_cpu_init(struct
cpufreq_policy *policy)
 	if (!cpuclk->rate)
 		return -EINVAL;

-	/* clock table init */
-	for (i = 2;
-	     (loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END);
-	     i++)
-		loongson2_clockmod_table[i].frequency = (cpuclk->rate * i) / 8;
+	/* initialize the clock table such that all frequencies */
+	/* evenly span within [cpu_clock_freq/2, cpu_clock_freq] */
+	for (i = 0; i < LS2_CPUFREQ_LEVEL; i++) {
+		loongson2_clockmod_table[i].frequency = cpuclk->rate *
+			(i+LS2_CPUFREQ_LEVEL-1) / (2*LS2_CPUFREQ_LEVEL-2);
+    }

 	policy->cur = loongson2_cpufreq_get(policy->cpu);

@@ -139,7 +137,7 @@ static int loongson2_cpufreq_cpu_init(struct
cpufreq_policy *policy)
 static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy,
-					      &loongson2_clockmod_table[0]);
+					&loongson2_clockmod_table[0]);
 }

 static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
@@ -185,7 +183,7 @@ static int __init cpufreq_init(void)
 {
 	int ret;

-	/* Register platform stuff */
+	/* Register platform driver */
 	ret = platform_driver_register(&platform_driver);
 	if (ret)
 		return ret;
@@ -195,20 +193,11 @@ static int __init cpufreq_init(void)
 	cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
 				  CPUFREQ_TRANSITION_NOTIFIER);

-	ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
-
-	if (!ret && !nowait) {
-		saved_cpu_wait = cpu_wait;
-		cpu_wait = loongson2_cpu_wait;
-	}
-
-	return ret;
+	return cpufreq_register_driver(&loongson2_cpufreq_driver);
 }

 static void __exit cpufreq_exit(void)
 {
-	if (!nowait && saved_cpu_wait)
-		cpu_wait = saved_cpu_wait;
 	cpufreq_unregister_driver(&loongson2_cpufreq_driver);
 	cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block,
 				    CPUFREQ_TRANSITION_NOTIFIER);
@@ -219,9 +208,6 @@ static void __exit cpufreq_exit(void)
 module_init(cpufreq_init);
 module_exit(cpufreq_exit);

-module_param(nowait, uint, 0644);
-MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait");
-
 MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
 MODULE_DESCRIPTION("cpufreq driver for Loongson2F");
 MODULE_LICENSE("GPL");



--
Gang Liang
Life is beautiful!

From wuzhangjin@gmail.com Wed Jun  2 10:53:15 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:53:20 +0200 (CEST)
Received: from mail-iw0-f177.google.com ([209.85.214.177]:48411 "EHLO
        mail-iw0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492555Ab0FBIxP (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 10:53:15 +0200
Received: by iwn34 with SMTP id 34so558377iwn.36
        for <multiple recipients>; Wed, 02 Jun 2010 01:53:14 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:from:to:cc:subject:date
         :message-id:x-mailer;
        bh=FQu1EmorC2GETsVuhiPXev2uxHOs4Xpe/EEZN8TTE9Y=;
        b=nIUzr3myMjGAfV+/IDMmDQ7AODPJlSxkV5XqRAFLkK4Ne6phq1y6FEB79dnLsu1vHl
         qQGsZW44RyntYdDnXkjV8gY0+ZRIGA/Rae+DWXhRzLNkT5GOi5NIRYKUmAtf5Jf/1pqQ
         xpFVvwn77VjAGWe9IamxnqEZD3dVM9XNSTw44=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=from:to:cc:subject:date:message-id:x-mailer;
        b=BYuW5DUk+7UjQXdiyhvLRN4NM83mIrkCXkXDpvgp4ZfZXdpieVGf6sDmSfu6sKrZ3T
         gr3OwJ0UVNdqqu2Y8dtQBliJlt+YRyL8HK224BbZQEtK3TbvLHqHtGpuAAQsjOOlmXtZ
         hboPVp4Xq5OcPbFXvT9Q+j9axQwvyhyrp+svg=
Received: by 10.231.59.1 with SMTP id j1mr2838643ibh.55.1275468794093;
        Wed, 02 Jun 2010 01:53:14 -0700 (PDT)
Received: from yeeloong ([202.201.14.140])
        by mx.google.com with ESMTPS id f1sm35625153ibg.15.2010.06.02.01.53.11
        (version=SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 01:53:13 -0700 (PDT)
From:   Wu Zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Cc:     Sam Ravnborg <sam@ravnborg.org>, Wu Zhangjin <wuzhangjin@gmail.com>
Subject: [PATCH -queue] MIPS: Move Loongson Makefile parts to their own Platform file (cont.)
Date:   Wed,  2 Jun 2010 16:53:00 +0800
Message-Id: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
X-Mailer: git-send-email 1.7.1
X-archive-position: 26995
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1123
Content-Length: 1171
Lines: 37

Hi, Ralf

I have fogotten to remove the -Werror in the Makefiles under loongson/
directory, this patch does it. could you please merge it into the commit "MIPS:
Move Loongson Makefile parts to their own Platform file".

Thanks & Regards,

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/loongson/common/cs5536/Makefile |    2 --
 arch/mips/loongson/fuloong-2e/Makefile    |    2 --
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile
index 510d4cd..f12e640 100644
--- a/arch/mips/loongson/common/cs5536/Makefile
+++ b/arch/mips/loongson/common/cs5536/Makefile
@@ -9,5 +9,3 @@ obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \
 # Enable cs5536 mfgpt Timer
 #
 obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o
-
-EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/loongson/fuloong-2e/Makefile b/arch/mips/loongson/fuloong-2e/Makefile
index 3aba5fc..b762272 100644
--- a/arch/mips/loongson/fuloong-2e/Makefile
+++ b/arch/mips/loongson/fuloong-2e/Makefile
@@ -3,5 +3,3 @@
 #
 
 obj-y += irq.o reset.o
-
-EXTRA_CFLAGS += -Werror
-- 
1.6.5


From Anoop_P.A@pmc-sierra.com Wed Jun  2 10:58:19 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 10:58:23 +0200 (CEST)
Received: from bby1mta02.pmc-sierra.com ([216.241.235.117]:56665 "EHLO
        bby1mta02.pmc-sierra.bc.ca" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491861Ab0FBI6T convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 10:58:19 +0200
Received: from bby1mta02.pmc-sierra.bc.ca (localhost.pmc-sierra.bc.ca [127.0.0.1])
        by localhost (Postfix) with SMTP id BB8728E00B6;
        Wed,  2 Jun 2010 01:58:08 -0700 (PDT)
Received: from bby1exg02.pmc_nt.nt.pmc-sierra.bc.ca (BBY1EXG02.pmc-sierra.bc.ca [216.241.231.167])
        by bby1mta02.pmc-sierra.bc.ca (Postfix) with SMTP id AEFE48E00B2;
        Wed,  2 Jun 2010 01:58:08 -0700 (PDT)
Received: from BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca ([216.241.231.157]) by bby1exg02.pmc_nt.nt.pmc-sierra.bc.ca with Microsoft SMTPSVC(6.0.3790.4675);
         Wed, 2 Jun 2010 01:58:09 -0700
X-MimeOLE: Produced By Microsoft Exchange V6.5
Content-class: urn:content-classes:message
MIME-Version: 1.0
Content-Type: text/plain;
        charset="US-ASCII"
Content-Transfer-Encoding: 8BIT
Subject: RE: TITAN GE driver
Date:   Wed, 2 Jun 2010 01:58:06 -0700
Message-ID: <A7DEA48C84FD0B48AAAE33F328C0201404E2DCA0@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
In-Reply-To: <20100602083255.GA23868@linux-mips.org>
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
Thread-Topic: TITAN GE driver
Thread-Index: AcsCLj5YbEJAOeB8Q5WudZ0mpgirdwAAiVHw
References: <A7DEA48C84FD0B48AAAE33F328C0201404E2D834@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca> <20100528162722.GB7148@linux-mips.org> <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca> <20100602083255.GA23868@linux-mips.org>
From:   "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
To:     "Ralf Baechle" <ralf@linux-mips.org>
Cc:     "linux-mips" <linux-mips@linux-mips.org>
X-OriginalArrivalTime: 02 Jun 2010 08:58:09.0133 (UTC) FILETIME=[B90AB1D0:01CB0231]
X-archive-position: 26996
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: Anoop_P.A@pmc-sierra.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1135
Content-Length: 747
Lines: 29

Ralf,

Thanks for the reply. 

> > allocated with same prefix. In another words all the buffers should
be
> > below < 0x1fff_ffff ( physical address) or between 0x2000_0000 and
> > 0x3fff_ffff like that.
> >
> > Is there any way to force kmalloc to allocate memory in certain
region
> > or below some region?
> 
> Nothing that would uniformly work for 32-bit and 64-bit kernels and
also
> Linux only has flags that allocate below certain addresses; nothing
that
> tells the allocator "give me something between 0x20000000 and
0x3fffffff".
> 
>   Ralf
[Anoop P.A.] You mean there are some flags available to force kmalloc to
allocate memory below some address? I couldn't find one in kmalloc man
pages.

BTW I am using 64 bit kernel.

Thanks
Anoop

From wuzhangjin@gmail.com Wed Jun  2 11:06:32 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 11:06:39 +0200 (CEST)
Received: from mail-pz0-f172.google.com ([209.85.222.172]:43917 "EHLO
        mail-pz0-f172.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491861Ab0FBJGc convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 11:06:32 +0200
Received: by pzk2 with SMTP id 2so1620508pzk.25
        for <multiple recipients>; Wed, 02 Jun 2010 02:06:24 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=FBwt0ghoTMpER87xaNAMA7Dh0saFmpXDmpsDMup2YWQ=;
        b=qbFcgRDRYgtYZUcMHXsdjoAcAlvfXwqR+ybbIf6WwtPwkQMkvCqIzNro9CDiQThq3o
         F+k5bJaE5gpOuMnD3BeYRcV+iApJ7r8OIpPCW7I8kGmusR4oMF3coVgyajRdSJl6gQUT
         tes1H2p+mCeny+2Ad/MB7r3yjtzYxJyuyBPZc=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=UjOj27ifGbdabkaZZtLeuHZzdCR6QwEzJVwkB1Aa4hMFMvV/fiQtyA90pMiCpYB6JH
         x+K4jHopFS1JZB2co9eDoMG+GTOfZvUgsz2oPfKJJgyHGgTY2/lnXYhMJCgIQRxjw6Ee
         vGnMHey9r2bmXIVI7WL1K0vNix3qTwfl4BpgE=
MIME-Version: 1.0
Received: by 10.115.81.7 with SMTP id i7mr6634520wal.115.1275469583756; Wed, 
        02 Jun 2010 02:06:23 -0700 (PDT)
Received: by 10.142.179.7 with HTTP; Wed, 2 Jun 2010 02:06:23 -0700 (PDT)
In-Reply-To: <AANLkTilcSFUBHXHHttcXFVToL8waTmlxmts-elClSJar@mail.gmail.com>
References: <AANLkTilcSFUBHXHHttcXFVToL8waTmlxmts-elClSJar@mail.gmail.com>
Date:   Wed, 2 Jun 2010 17:06:23 +0800
Message-ID: <AANLkTik2DShzlr47Ce7UiS-FIAb6samirpcsjSCvjf97@mail.gmail.com>
Subject: Fwd: [loongson2-PATCH] modification of the cpufreq module
From:   wu zhangjin <wuzhangjin@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>, Dave Jones <davej@redhat.com>,
        Gang Liang <randomizedthinking@gmail.com>
Cc:     loongson-dev@googlegroups.com, Hua Yan <yanh@lemote.com>,
        linux-mips <linux-mips@linux-mips.org>, cpufreq@vger.kernel.org
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26997
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1142
Content-Length: 10706
Lines: 312

(Added more people in the To: and CC: list)


---------- Forwarded message ----------
From: Gang Liang <randomizedthinking@gmail.com>
Date: Wed, Jun 2, 2010 at 4:48 PM
Subject: [loongson2-PATCH] modification of the cpufreq module
To: linux-mips@linux-mips.org, Ralf Baechle <ralf@linux-mips.org>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>, Hua Yan <yanh@lemote.com>


This patch updates some aspects of the current implementation of
cpufreq driver for Loongson2.

1) A default cpu_wait handler is installed such that the cpu will be
alive at the lowest possible power level when a cpu_wait call is made;

2) The number of frequency levels is reduced to 3, and the lowest
frequency is capped as a half of the full cpu speed. The "nowait" option
is removed.

Thanks!

---
 arch/mips/include/asm/mach-loongson/loongson.h |    4 +-
 arch/mips/kernel/cpu-probe.c                   |   21 +++++++++
 arch/mips/kernel/cpufreq/loongson2_clock.c     |   52 +++--------------------
 arch/mips/kernel/cpufreq/loongson2_cpufreq.c   |   54 +++++++++---------------
 4 files changed, 50 insertions(+), 81 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson/loongson.h
b/arch/mips/include/asm/mach-loongson/loongson.h
index 53d0bef..33164b9 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -242,8 +242,8 @@ extern int mach_i8259_irq(void);

 #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
 #include <linux/cpufreq.h>
-extern void loongson2_cpu_wait(void);
-extern struct cpufreq_frequency_table loongson2_clockmod_table[];
+/* extern void loongson2_cpu_wait(void); */
+/* extern struct cpufreq_frequency_table loongson2_clockmod_table[]; */

 /* Chip Config */
 #define LOONGSON_CHIPCFG0              LOONGSON_REG(LOONGSON_REGBASE + 0x80)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index be5bb16..5b3072c 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -25,6 +25,9 @@
 #include <asm/system.h>
 #include <asm/watch.h>
 #include <asm/spram.h>
+
+#include <loongson.h>
+
 /*
 * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
 * the implementation of the "wait" feature differs between CPU families. This
@@ -51,6 +54,21 @@ static void r39xx_wait(void)

 extern void r4k_wait(void);

+DEFINE_SPINLOCK(loongson2_wait_lock);
+static void loongson2_cpu_wait(void)
+{
+    u32 cpu_freq;
+    unsigned long flags;
+
+    /* enter the lowest power mode available while still alive */
+    /* future work: check cpu freq -- do nothing if no change */
+    /* otherwise, change the frequency and propagate the clock rate */
+    spin_lock_irqsave(&loongson2_wait_lock, flags);
+    cpu_freq = LOONGSON_CHIPCFG0;
+       LOONGSON_CHIPCFG0 = (cpu_freq & ~0x7) | 1;
+    spin_unlock_irqrestore(&loongson2_wait_lock, flags);
+}
+
 /*
 * This variant is preferable as it allows testing need_resched and going to
 * sleep depending on the outcome atomically.  Unfortunately the "It is
@@ -212,6 +230,9 @@ void __init check_wait(void)
               if ((c->processor_id & 0x00ff) >= 0x40)
                       cpu_wait = r4k_wait;
               break;
+    case CPU_LOONGSON2:
+        cpu_wait = loongson2_cpu_wait;
+        break;
       default:
               break;
       }
diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c
b/arch/mips/kernel/cpufreq/loongson2_clock.c
index cefc6e2..0b30fe9 100644
--- a/arch/mips/kernel/cpufreq/loongson2_clock.c
+++ b/arch/mips/kernel/cpufreq/loongson2_clock.c
@@ -18,25 +18,7 @@ static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
 static DEFINE_MUTEX(clock_list_sem);

-/* Minimum CLK support */
-enum {
-       DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
-       DC_87PT, DC_DISABLE, DC_RESV
-};
-
-struct cpufreq_frequency_table loongson2_clockmod_table[] = {
-       {DC_RESV, CPUFREQ_ENTRY_INVALID},
-       {DC_ZERO, CPUFREQ_ENTRY_INVALID},
-       {DC_25PT, 0},
-       {DC_37PT, 0},
-       {DC_50PT, 0},
-       {DC_62PT, 0},
-       {DC_75PT, 0},
-       {DC_87PT, 0},
-       {DC_DISABLE, 0},
-       {DC_RESV, CPUFREQ_TABLE_END},
-};
-EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
+#define LS2_MAX_CPUFREQ_LEVEL 8

 static struct clk cpu_clk = {
       .name = "cpu_clk",
@@ -109,21 +91,15 @@ int clk_set_rate_ex(struct clk *clk, unsigned
long rate, int algo_id)
       if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
               propagate_rate(clk);

-       for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
-            i++) {
-               if (loongson2_clockmod_table[i].frequency ==
-                   CPUFREQ_ENTRY_INVALID)
-                       continue;
-               if (rate == loongson2_clockmod_table[i].frequency)
-                       break;
-       }
-       if (rate != loongson2_clockmod_table[i].frequency)
-               return -ENOTSUPP;
+    i = rate * LS2_MAX_CPUFREQ_LEVEL / cpu_clock_freq;
+    if ( i < 1 || i > LS2_MAX_CPUFREQ_LEVEL )
+        return -ENOTSUPP;

-       clk->rate = rate;
+    /* indeed, a rounded rate is assigned */
+       clk->rate = i * (cpu_clock_freq / LS2_MAX_CPUFREQ_LEVEL);

       regval = LOONGSON_CHIPCFG0;
-       regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
+       regval = (regval & ~0x7) | i;
       LOONGSON_CHIPCFG0 = regval;

       return ret;
@@ -151,20 +127,6 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
 * interrupt disabled content
 */

-DEFINE_SPINLOCK(loongson2_wait_lock);
-void loongson2_cpu_wait(void)
-{
-       u32 cpu_freq;
-       unsigned long flags;
-
-       spin_lock_irqsave(&loongson2_wait_lock, flags);
-       cpu_freq = LOONGSON_CHIPCFG0;
-       LOONGSON_CHIPCFG0 &= ~0x7;      /* Put CPU into wait mode */
-       LOONGSON_CHIPCFG0 = cpu_freq;   /* Restore CPU state */
-       spin_unlock_irqrestore(&loongson2_wait_lock, flags);
-}
-EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
-
 MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
 MODULE_DESCRIPTION("cpufreq driver for Loongson 2F");
 MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
index 2f6a0b1..0488945 100644
--- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
+++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
@@ -21,11 +21,16 @@

 #include <loongson.h>

-static uint nowait;
+#define LS2_CPUFREQ_LEVEL 3

 static struct clk *cpuclk;

-static void (*saved_cpu_wait) (void);
+struct cpufreq_frequency_table loongson2_clockmod_table[] = {
+       {0, 0},
+       {1, 0},
+       {2, 0},
+       { .frequency = CPUFREQ_TABLE_END },
+};

 static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
                                       unsigned long val, void *data);
@@ -67,14 +72,11 @@ static int loongson2_cpufreq_target(struct
cpufreq_policy *policy,
       cpus_allowed = current->cpus_allowed;
       set_cpus_allowed(current, cpumask_of_cpu(cpu));

-       if (cpufreq_frequency_table_target
-           (policy, &loongson2_clockmod_table[0], target_freq, relation,
-            &newstate))
+       if (cpufreq_frequency_table_target (policy,
+                       &loongson2_clockmod_table[0], target_freq,
relation, &newstate))
               return -EINVAL;

-       freq =
-           ((cpu_clock_freq / 1000) *
-            loongson2_clockmod_table[newstate].index) / 8;
+       freq = loongson2_clockmod_table[newstate].frequency;
       if (freq < policy->min || freq > policy->max)
               return -EINVAL;

@@ -88,15 +90,10 @@ static int loongson2_cpufreq_target(struct
cpufreq_policy *policy,
       if (freqs.new == freqs.old)
               return 0;

-       /* notifiers */
+       /* change cpu clock between notifier pairs */
       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
       set_cpus_allowed(current, cpus_allowed);
-
-       /* setting the cpu frequency */
       clk_set_rate(cpuclk, freq);
-
-       /* notifiers */
       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);

       pr_debug("cpufreq: set frequency %u kHz\n", freq);
@@ -121,11 +118,12 @@ static int loongson2_cpufreq_cpu_init(struct
cpufreq_policy *policy)
       if (!cpuclk->rate)
               return -EINVAL;

-       /* clock table init */
-       for (i = 2;
-            (loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END);
-            i++)
-               loongson2_clockmod_table[i].frequency = (cpuclk->rate * i) / 8;
+       /* initialize the clock table such that all frequencies */
+       /* evenly span within [cpu_clock_freq/2, cpu_clock_freq] */
+       for (i = 0; i < LS2_CPUFREQ_LEVEL; i++) {
+               loongson2_clockmod_table[i].frequency = cpuclk->rate *
+                       (i+LS2_CPUFREQ_LEVEL-1) / (2*LS2_CPUFREQ_LEVEL-2);
+    }

       policy->cur = loongson2_cpufreq_get(policy->cpu);

@@ -139,7 +137,7 @@ static int loongson2_cpufreq_cpu_init(struct
cpufreq_policy *policy)
 static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
 {
       return cpufreq_frequency_table_verify(policy,
-                                             &loongson2_clockmod_table[0]);
+                                       &loongson2_clockmod_table[0]);
 }

 static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
@@ -185,7 +183,7 @@ static int __init cpufreq_init(void)
 {
       int ret;

-       /* Register platform stuff */
+       /* Register platform driver */
       ret = platform_driver_register(&platform_driver);
       if (ret)
               return ret;
@@ -195,20 +193,11 @@ static int __init cpufreq_init(void)
       cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
                                 CPUFREQ_TRANSITION_NOTIFIER);

-       ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
-
-       if (!ret && !nowait) {
-               saved_cpu_wait = cpu_wait;
-               cpu_wait = loongson2_cpu_wait;
-       }
-
-       return ret;
+       return cpufreq_register_driver(&loongson2_cpufreq_driver);
 }

 static void __exit cpufreq_exit(void)
 {
-       if (!nowait && saved_cpu_wait)
-               cpu_wait = saved_cpu_wait;
       cpufreq_unregister_driver(&loongson2_cpufreq_driver);
       cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block,
                                   CPUFREQ_TRANSITION_NOTIFIER);
@@ -219,9 +208,6 @@ static void __exit cpufreq_exit(void)
 module_init(cpufreq_init);
 module_exit(cpufreq_exit);

-module_param(nowait, uint, 0644);
-MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait");
-
 MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
 MODULE_DESCRIPTION("cpufreq driver for Loongson2F");
 MODULE_LICENSE("GPL");



--
Gang Liang
Life is beautiful!

From wuzhangjin@gmail.com Wed Jun  2 11:35:13 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 11:35:20 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:60733 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491135Ab0FBJfN convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 11:35:13 +0200
Received: by pvb32 with SMTP id 32so847876pvb.36
        for <multiple recipients>; Wed, 02 Jun 2010 02:35:06 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=SQHEZc864lRCuokvgRSoyHwWopJG/DJJqLyBSk0aj90=;
        b=lSlDo3Po0I7/VyZDVnzVR3tNpxK6NGO364ktHO6EW0k+ybkzUpyuPMGRaaHC0yvjGN
         QMUBWh93PFJgoSYJtSzjFjSil/DkkcvbYnpYYScJlupuhv7q6FonKUHllHX6E7q+LMhl
         m7WA00nARm6WAe0r9upGAIMWg4ZuuDbQVWlqE=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=Nc9bpxHv0ICBIC/ZDdC7gx43nB/RACT6Ic7gDiI7BNu7Rg/i0t8T7eUyPijiThKFMe
         mKYK70Y6G1hi5FgOVes898ZAoul6QOxge6Kzk+W+5FnI55vPuPmlq4wXlzvBrnUWt1OQ
         Q9xFop8zD2AiG71bQMIJfOYe7GsMA81iaA+h8=
MIME-Version: 1.0
Received: by 10.115.103.40 with SMTP id f40mr6703857wam.38.1275471306171; Wed, 
        02 Jun 2010 02:35:06 -0700 (PDT)
Received: by 10.142.179.7 with HTTP; Wed, 2 Jun 2010 02:35:06 -0700 (PDT)
In-Reply-To: <AANLkTik2DShzlr47Ce7UiS-FIAb6samirpcsjSCvjf97@mail.gmail.com>
References: <AANLkTilcSFUBHXHHttcXFVToL8waTmlxmts-elClSJar@mail.gmail.com>
        <AANLkTik2DShzlr47Ce7UiS-FIAb6samirpcsjSCvjf97@mail.gmail.com>
Date:   Wed, 2 Jun 2010 17:35:06 +0800
Message-ID: <AANLkTilYtBmSBw2ram0sZ1QblEbTiy3IzspNiokKCfj7@mail.gmail.com>
Subject: Re: [loongson2-PATCH] modification of the cpufreq module
From:   wu zhangjin <wuzhangjin@gmail.com>
To:     Gang Liang <randomizedthinking@gmail.com>
Cc:     loongson-dev@googlegroups.com, Hua Yan <yanh@lemote.com>,
        linux-mips <linux-mips@linux-mips.org>, cpufreq@vger.kernel.org,
        Ralf Baechle <ralf@linux-mips.org>,
        Dave Jones <davej@redhat.com>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 26998
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: wuzhangjin@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1163
Content-Length: 4351
Lines: 157

Hi, Gang

>
>
> This patch updates some aspects of the current implementation of
> cpufreq driver for Loongson2.
>
> 1) A default cpu_wait handler is installed such that the cpu will be
> alive at the lowest possible power level when a cpu_wait call is made;
>
> 2) The number of frequency levels is reduced to 3, and the lowest
> frequency is capped as a half of the full cpu speed. The "nowait" option
> is removed.
>
> Thanks!

Herein, You need to add a more line:

Signed-off-by: Gang Liang <randomizedthinking@gmail.com>

You can generate it automatically with:

$ git commit -s

or

$ git commit --amend -s

If you have configured your name and email address with:

$ git config --global user.name "Gang Liang"
$ git config --global user.email "randomizedthinking@gmail.com"

>
> ---
>  arch/mips/include/asm/mach-loongson/loongson.h |    4 +-
>  arch/mips/kernel/cpu-probe.c                   |   21 +++++++++
>  arch/mips/kernel/cpufreq/loongson2_clock.c     |   52 +++--------------------
>  arch/mips/kernel/cpufreq/loongson2_cpufreq.c   |   54 +++++++++---------------
>  4 files changed, 50 insertions(+), 81 deletions(-)
>
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h
> b/arch/mips/include/asm/mach-loongson/loongson.h
> index 53d0bef..33164b9 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -242,8 +242,8 @@ extern int mach_i8259_irq(void);
>
>  #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
>  #include <linux/cpufreq.h>
> -extern void loongson2_cpu_wait(void);
> -extern struct cpufreq_frequency_table loongson2_clockmod_table[];
> +/* extern void loongson2_cpu_wait(void); */
> +/* extern struct cpufreq_frequency_table loongson2_clockmod_table[]; */

Why not remove them directly?

>
>  /* Chip Config */
>  #define LOONGSON_CHIPCFG0              LOONGSON_REG(LOONGSON_REGBASE + 0x80)
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index be5bb16..5b3072c 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -25,6 +25,9 @@
>  #include <asm/system.h>
>  #include <asm/watch.h>
>  #include <asm/spram.h>
> +
> +#include <loongson.h>
> +

This may fail when building on non-Loongson platform.

Perhaps we need to add:

#ifdef CONFIG_CPU_LOONGSON2
#include <loongson.h>
#endif

>  /*
>  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
>  * the implementation of the "wait" feature differs between CPU families. This
> @@ -51,6 +54,21 @@ static void r39xx_wait(void)
>
>  extern void r4k_wait(void);
>
> +DEFINE_SPINLOCK(loongson2_wait_lock);

Perhaps we'd better use the RAW spinlock here:

DEFINE_RAW_SPINLOCK(loongson2_wait_lock);

and the operation should be raw_spin_lock_irqsave/restore...

> +static void loongson2_cpu_wait(void)
> +{
> +    u32 cpu_freq;
> +    unsigned long flags;
> +

The indent should be a TAB(the same to the others), you can try to
format it with:

indent -linux /path/to/file ...

and please check it with scripts/checkpatch.pl before sending your
next revision.

$ ./scripts/checkpatch.pl --strict /path/to/your_patch

and fix all of the errors and the warnings if possible.

> +    /* enter the lowest power mode available while still alive */
> +    /* future work: check cpu freq -- do nothing if no change */
> +    /* otherwise, change the frequency and propagate the clock rate */

For Comments, you'd better use something like this:

/*
 * enter ....
 */

and if you are using vim, you can format it with :gqap.

> +    spin_lock_irqsave(&loongson2_wait_lock, flags);
> +    cpu_freq = LOONGSON_CHIPCFG0;
> +       LOONGSON_CHIPCFG0 = (cpu_freq & ~0x7) | 1;

The indent problem here too.

> +    spin_unlock_irqrestore(&loongson2_wait_lock, flags);
> +}
> +
>  /*
>  * This variant is preferable as it allows testing need_resched and going to
>  * sleep depending on the outcome atomically.  Unfortunately the "It is
> @@ -212,6 +230,9 @@ void __init check_wait(void)
>                if ((c->processor_id & 0x00ff) >= 0x40)
>                        cpu_wait = r4k_wait;
>                break;
> +    case CPU_LOONGSON2:
> +        cpu_wait = loongson2_cpu_wait;
> +        break;

indent problem ;)

>        default:
>                break;
>        }

[...]

Will take a look at the left parts later.

Regards,
Wu Zhangjin

From adnan.iqbal@seecs.edu.pk Wed Jun  2 12:17:41 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 12:17:49 +0200 (CEST)
Received: from na3sys009aog105.obsmtp.com ([74.125.149.75]:42198 "HELO
        na3sys009aog105.obsmtp.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1491145Ab0FBKRl (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 12:17:41 +0200
Received: from source ([209.85.214.179]) by na3sys009aob105.postini.com ([74.125.148.12]) with SMTP
        ID DSNKTAYvwmYU7pKLt3MCju/GmJXoAF0iB0Ae@postini.com; Wed, 02 Jun 2010 03:17:41 PDT
Received: by mail-iw0-f179.google.com with SMTP id 35so1183247iwn.38
        for <linux-mips@linux-mips.org>; Wed, 02 Jun 2010 03:17:38 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.231.120.37 with SMTP id b37mr9574909ibr.81.1275473858138; Wed, 
        02 Jun 2010 03:17:38 -0700 (PDT)
Received: by 10.231.182.74 with HTTP; Wed, 2 Jun 2010 03:17:38 -0700 (PDT)
Date:   Wed, 2 Jun 2010 15:17:38 +0500
Message-ID: <AANLkTino_WFpj8aueN4zGwkRV-SCVqA5NGsKQOGU9qho@mail.gmail.com>
Subject: Details of MIPS(Octeon) system call semantics
From:   adnan iqbal <adnan.iqbal@seecs.edu.pk>
To:     linux-mips@linux-mips.org
Content-Type: multipart/alternative; boundary=001485e2ebde3c1242048809664f
X-archive-position: 26999
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: adnan.iqbal@seecs.edu.pk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1201
Content-Length: 999
Lines: 24

--001485e2ebde3c1242048809664f
Content-Type: text/plain; charset=ISO-8859-1

hi everybody,

I am able to find system call list (o32 and n64) in
/usr/include/asm/unistd.h over octeon/debian board. I am looking for details
about these system calls so that for each system call i know exactly

1. What parmeters should be set in which registers before syscall
2. Which registers contain output of those system calls.


Thanks in advance for your help.
Regards
Adnan

--001485e2ebde3c1242048809664f
Content-Type: text/html; charset=ISO-8859-1

hi everybody,<br><br>I am able to find system call list (o32 and n64) in /usr/include/asm/unistd.h over octeon/debian board. I am looking for details about these system calls so that for each system call i know exactly<br>
<br>1. What parmeters should be set in which registers before syscall<br>2. Which registers contain output of those system calls.<br><br><br>Thanks in advance for your help.<br>Regards<br>Adnan<br><br>

--001485e2ebde3c1242048809664f--

From ralf@linux-mips.org Wed Jun  2 15:38:14 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 15:38:18 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:35719 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492592Ab0FBNiO (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 15:38:14 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o52DcBXK015715;
        Wed, 2 Jun 2010 14:38:11 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o52Dc98r015713;
        Wed, 2 Jun 2010 14:38:09 +0100
Date:   Wed, 2 Jun 2010 14:38:09 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     adnan iqbal <adnan.iqbal@seecs.edu.pk>
Cc:     linux-mips@linux-mips.org
Subject: Re: Details of MIPS(Octeon) system call semantics
Message-ID: <20100602133809.GA13625@linux-mips.org>
References: <AANLkTino_WFpj8aueN4zGwkRV-SCVqA5NGsKQOGU9qho@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <AANLkTino_WFpj8aueN4zGwkRV-SCVqA5NGsKQOGU9qho@mail.gmail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27000
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                
X-UID: 1352
Content-Length: 1337
Lines: 33

On Wed, Jun 02, 2010 at 03:17:38PM +0500, adnan iqbal wrote:

> I am able to find system call list (o32 and n64) in
> /usr/include/asm/unistd.h over octeon/debian board. I am looking for details
> about these system calls so that for each system call i know exactly
> 
> 1. What parmeters should be set in which registers before syscall
> 2. Which registers contain output of those system calls.

The basic concept for all ABIs is that syscalls are working almost like
subroutine calls, so:

 o arguments are passed in $a0 - $a3 for o32
 o arguments are passed in $a0 - $a7 for N32 and N64
 o argument that don't fit into the argument registers are passed on the
   stack.
 o for details such as alignment of 64-bit arguments the usual ABI
   conventions apply
 o the result is return in $v0

In addition to normal subroutine calls:

 o $a3 on syscall return will indicate success or error.  0 means success,
   non-zero means an error happened in which case $v0 will contain an
   errno.h error code.
 o Many syscalls deviate from this convention.  For example the sigreturn
   family of syscalls doesn't return a result or error status.
 o pipe() will return the 2nd filedescriptor of the result in $v1.
 o vfork is even more weird.
 o The ABI differences mean there are many subtle difference between the
   syscall handlers.

  Ralf

From guenter.roeck@ericsson.com Wed Jun  2 15:48:30 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 15:48:37 +0200 (CEST)
Received: from imr3.ericy.com ([198.24.6.13]:42246 "EHLO imr3.ericy.com"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491795Ab0FBNsa (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 15:48:30 +0200
Received: from eusaamw0712.eamcs.ericsson.se ([147.117.20.181])
        by imr3.ericy.com (8.13.8/8.13.8) with ESMTP id o52DmCv7011264
        (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL);
        Wed, 2 Jun 2010 08:48:19 -0500
Received: from localhost (147.117.20.212) by eusaamw0712.eamcs.ericsson.se
 (147.117.20.182) with Microsoft SMTP Server id 8.2.234.1; Wed, 2 Jun 2010
 09:48:10 -0400
Date:   Wed, 2 Jun 2010 06:48:10 -0700
From:   Guenter Roeck <guenter.roeck@ericsson.com>
To:     "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
CC:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Subject: Re: TITAN GE driver
Message-ID: <20100602134810.GC4388@ericsson.com>
References: <A7DEA48C84FD0B48AAAE33F328C0201404E2D834@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
 <20100528162722.GB7148@linux-mips.org>
 <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
 <20100602083255.GA23868@linux-mips.org>
 <A7DEA48C84FD0B48AAAE33F328C0201404E2DCA0@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <A7DEA48C84FD0B48AAAE33F328C0201404E2DCA0@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
User-Agent: Mutt/1.5.20 (2009-06-14)
X-archive-position: 27001
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: guenter.roeck@ericsson.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1360
Content-Length: 894
Lines: 29

On Wed, Jun 02, 2010 at 04:58:06AM -0400, Anoop P.A. wrote:
> Ralf,
> 
> Thanks for the reply. 
> 
> > > allocated with same prefix. In another words all the buffers should
> be
> > > below < 0x1fff_ffff ( physical address) or between 0x2000_0000 and
> > > 0x3fff_ffff like that.
> > >
> > > Is there any way to force kmalloc to allocate memory in certain
> region
> > > or below some region?
> > 
> > Nothing that would uniformly work for 32-bit and 64-bit kernels and
> also
> > Linux only has flags that allocate below certain addresses; nothing
> that
> > tells the allocator "give me something between 0x20000000 and
> 0x3fffffff".
> > 
> >   Ralf
> [Anoop P.A.] You mean there are some flags available to force kmalloc to
> allocate memory below some address? I couldn't find one in kmalloc man
> pages.
> 
Ralf said "nothing". My reading is that such a flag is _not_ available.

Guenter

From Anoop_P.A@pmc-sierra.com Wed Jun  2 16:03:08 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 16:03:16 +0200 (CEST)
Received: from bby1mta03.pmc-sierra.com ([216.241.235.118]:46691 "EHLO
        bby1mta03.pmc-sierra.bc.ca" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491828Ab0FBODI convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 16:03:08 +0200
Received: from bby1mta03.pmc-sierra.bc.ca (localhost.pmc-sierra.bc.ca [127.0.0.1])
        by localhost (Postfix) with SMTP id 66FF3107008B;
        Wed,  2 Jun 2010 07:02:57 -0700 (PDT)
Received: from bby1exg02.pmc_nt.nt.pmc-sierra.bc.ca (BBY1EXG02.pmc-sierra.bc.ca [216.241.231.167])
        by bby1mta03.pmc-sierra.bc.ca (Postfix) with SMTP id 56FAE107006A;
        Wed,  2 Jun 2010 07:02:57 -0700 (PDT)
Received: from BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca ([216.241.231.157]) by bby1exg02.pmc_nt.nt.pmc-sierra.bc.ca with Microsoft SMTPSVC(6.0.3790.4675);
         Wed, 2 Jun 2010 07:02:57 -0700
X-MimeOLE: Produced By Microsoft Exchange V6.5
Content-class: urn:content-classes:message
MIME-Version: 1.0
Content-Type: text/plain;
        charset="US-ASCII"
Content-Transfer-Encoding: 8BIT
Subject: RE: TITAN GE driver
Date:   Wed, 2 Jun 2010 07:02:55 -0700
Message-ID: <A7DEA48C84FD0B48AAAE33F328C0201404E2DCC1@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
In-Reply-To: <20100602134810.GC4388@ericsson.com>
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
Thread-Topic: TITAN GE driver
Thread-Index: AcsCWkmg+revDixXR1q+Obj5SiPzWwAAJCSw
References: <A7DEA48C84FD0B48AAAE33F328C0201404E2D834@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca> <20100528162722.GB7148@linux-mips.org> <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca> <20100602083255.GA23868@linux-mips.org> <A7DEA48C84FD0B48AAAE33F328C0201404E2DCA0@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca> <20100602134810.GC4388@ericsson.com>
From:   "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
To:     "Guenter Roeck" <guenter.roeck@ericsson.com>
Cc:     "Ralf Baechle" <ralf@linux-mips.org>,
        "linux-mips" <linux-mips@linux-mips.org>
X-OriginalArrivalTime: 02 Jun 2010 14:02:57.0621 (UTC) FILETIME=[4DD48050:01CB025C]
X-archive-position: 27002
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: Anoop_P.A@pmc-sierra.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1373
Content-Length: 356
Lines: 11

> > > Linux only has flags that allocate below certain addresses;

I am probably confused by this line ( BTW I know there is a flag
GFP_DMA32 which will force kmalloc to allocate below 4GB) I was just
wondering if there is a flag to allocate memory below 512MB . 

> >
> Ralf said "nothing". My reading is that such a flag is _not_
available.
> 
> Guenter

From ralf@linux-mips.org Wed Jun  2 16:15:53 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 16:16:00 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:59744 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491790Ab0FBOPx (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Wed, 2 Jun 2010 16:15:53 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o52EFpko016456;
        Wed, 2 Jun 2010 15:15:52 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o52EFpX5016454;
        Wed, 2 Jun 2010 15:15:51 +0100
Date:   Wed, 2 Jun 2010 15:15:51 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
Cc:     linux-mips <linux-mips@linux-mips.org>
Subject: Re: TITAN GE driver
Message-ID: <20100602141551.GA15753@linux-mips.org>
References: <A7DEA48C84FD0B48AAAE33F328C0201404E2D834@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
 <20100528162722.GB7148@linux-mips.org>
 <A7DEA48C84FD0B48AAAE33F328C0201404E2DC94@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
 <20100602083255.GA23868@linux-mips.org>
 <A7DEA48C84FD0B48AAAE33F328C0201404E2DCA0@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <A7DEA48C84FD0B48AAAE33F328C0201404E2DCA0@BBY1EXM11.pmc_nt.nt.pmc-sierra.bc.ca>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27003
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1382
Content-Length: 934
Lines: 27

On Wed, Jun 02, 2010 at 01:58:06AM -0700, Anoop P.A. wrote:

> [Anoop P.A.] You mean there are some flags available to force kmalloc to
> allocate memory below some address? I couldn't find one in kmalloc man
> pages.
> 
> BTW I am using 64 bit kernel.

There are:

 o GFP_DMA which usually means to allocate memory accessible to ISA DMA
   devices.
 o GFP_DMA32 which means memory in the low physical 4GB, that is memory
   accessible by 32-bit DMA devices.
 o GFP_HIGHMEM means any type of memory, even highmem.

All need to be explicitly supported by platform code which the existing
code doesn't.

Passing none of these flags would mean to allocate any non-highmem.  On
32-bit kernels that would be below 512MB physical but on 64-bit kernels
where there never is highmem it would just mean to allocate any memory.

I just hope the NIC isn't as braindead as you were describing but I got
no time to read up the docs again.

  Ralf

From irek.szczesniak@gmail.com Wed Jun  2 16:56:26 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 16:56:32 +0200 (CEST)
Received: from fg-out-1718.google.com ([72.14.220.153]:13712 "EHLO
        fg-out-1718.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491790Ab0FBO40 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 16:56:26 +0200
Received: by fg-out-1718.google.com with SMTP id 16so1312769fgg.6
        for <linux-mips@linux-mips.org>; Wed, 02 Jun 2010 07:56:25 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:message-id:date:from
         :user-agent:mime-version:to:cc:subject:references:in-reply-to
         :content-type:content-transfer-encoding;
        bh=JsQ5MYAzDQKFv7L0/obW/H1daf+/4W88pF0t/BKdJ54=;
        b=YyLXHqQRCEWANcut4lYdkrLChzT/0zpTtkMmM25idv7uBPkfPQmqzcUQJQ6th1f1+W
         nuEwv/dg6saWMwGzrVEMA2fxJ2O4mHlG2FSjb0MzSW2V67taJuGMHmZZUTvIyKuNId39
         eThakSykcTu/bkRkFZcYlR8+cLvpdr+y8nrMk=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=message-id:date:from:user-agent:mime-version:to:cc:subject
         :references:in-reply-to:content-type:content-transfer-encoding;
        b=G7udwPCWYXzWAuRi07/7gKYFnEveEAL9SenVIx14p7xf9GjOBeWsA0aHgYI0EFBHQu
         WeHu8RBd79ZuMFWk7c6mE8Tqc8G/QaZcIbMFlcneyWWCDTTe4/cTVbncc/TbofeOu4Ny
         7pSQuLvedUffT4vaaLAIFIb5aX2wKckvd5QNU=
Received: by 10.87.45.15 with SMTP id x15mr13736628fgj.42.1275490583886;
        Wed, 02 Jun 2010 07:56:23 -0700 (PDT)
Received: from [192.168.2.50] (host-83.2.142.85.tvksmp.pl [83.2.142.85])
        by mx.google.com with ESMTPS id 4sm121508fgg.27.2010.06.02.07.56.23
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 07:56:23 -0700 (PDT)
Message-ID: <4C067116.9000907@gmail.com>
Date:   Wed, 02 Jun 2010 16:56:22 +0200
From:   =?UTF-8?B?SXJlbmV1c3ogU3pjemXFm25pYWs=?= 
        <irek.szczesniak@gmail.com>
User-Agent: Thunderbird 2.0.0.24 (X11/20100411)
MIME-Version: 1.0
To:     Florian Fainelli <florian@openwrt.org>
CC:     linux-mips@linux-mips.org
Subject: Re: MIPS 24Kc
References: <4C055A60.3000203@gmail.com> <201006012144.43447.florian@openwrt.org>
In-Reply-To: <201006012144.43447.florian@openwrt.org>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
X-archive-position: 27004
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: irek.szczesniak@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1407
Content-Length: 517
Lines: 19

Hi,

> I would recommend checking OpenWr's ar71xx port[1] which supports RB433.
> 
> [1]: https://dev.openwrt.org/browser/trunk/target/linux/ar71xx

Thanks for the information.   A few weeks ago I downloaded the most 
recent Kamikaze release (8.09.2), and I didn't get the option of KGDB 
for ar71xx, and so I didn't use it.  But now that I checked out the 
trunk, that you point out, I was able to built OpenWRT with the KGDB 
support!  That's cool!


Best,
Irek

-- 
Ireneusz (Irek) Szczesniak
http://www.irkos.org

From lars@metafoo.de Wed Jun  2 21:04:50 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:05:05 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1088 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492617Ab0FBTEu (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:50 +0200
Received: (qmail 29873 invoked by uid 0); 2 Jun 2010 19:04:42 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:42 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Thomas Gleixner <tglx@linutronix.de>
Subject: [RFC][PATCH 05/26] MIPS: JZ4740: Add clocksource/clockevent support.
Date:   Wed,  2 Jun 2010 21:02:56 +0200
Message-Id: <1275505397-16758-6-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27005
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1585
Content-Length: 4555
Lines: 163

This patch add clocksource and clockevent support for the timer/counter unit on
JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 arch/mips/jz4740/time.c |  144 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 144 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/time.c

diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
new file mode 100644
index 0000000..da8183f
--- /dev/null
+++ b/arch/mips/jz4740/time.c
@@ -0,0 +1,144 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform time support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+
+#include <linux/clockchips.h>
+
+#include <asm/mach-jz4740/irq.h>
+#include <asm/time.h>
+
+#include "clock.h"
+#include "timer.h"
+
+#define TIMER_CLOCKEVENT 0
+#define TIMER_CLOCKSOURCE 1
+
+static uint16_t jz4740_jiffies_per_tick;
+
+static cycle_t jz4740_clocksource_read(struct clocksource *cs)
+{
+	return jz4740_timer_get_count(TIMER_CLOCKSOURCE);
+}
+
+static struct clocksource jz4740_clocksource = {
+	.name = "jz4740-timer",
+	.rating = 200,
+	.read = jz4740_clocksource_read,
+	.mask = CLOCKSOURCE_MASK(16),
+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static irqreturn_t jz4740_clockevent_irq(int irq, void *devid)
+{
+	struct clock_event_device *cd = devid;
+
+	jz4740_timer_ack_full(TIMER_CLOCKEVENT);
+
+	if (cd->mode != CLOCK_EVT_MODE_PERIODIC)
+		jz4740_timer_disable(TIMER_CLOCKEVENT);
+
+	cd->event_handler(cd);
+
+	return IRQ_HANDLED;
+}
+
+static void jz4740_clockevent_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *cd)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		jz4740_timer_set_count(TIMER_CLOCKEVENT, 0);
+		jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick);
+	case CLOCK_EVT_MODE_RESUME:
+		jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
+		jz4740_timer_enable(TIMER_CLOCKEVENT);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		jz4740_timer_disable(TIMER_CLOCKEVENT);
+		break;
+	default:
+		break;
+	}
+}
+
+static int jz4740_clockevent_set_next(unsigned long evt,
+	struct clock_event_device *cd)
+{
+	jz4740_timer_set_count(TIMER_CLOCKEVENT, 0);
+	jz4740_timer_set_period(TIMER_CLOCKEVENT, evt);
+	jz4740_timer_enable(TIMER_CLOCKEVENT);
+
+	return 0;
+}
+
+static struct clock_event_device jz4740_clockevent = {
+	.name = "jz4740-timer",
+	.features = CLOCK_EVT_FEAT_PERIODIC,
+	.set_next_event = jz4740_clockevent_set_next,
+	.set_mode = jz4740_clockevent_set_mode,
+	.rating = 200,
+	.irq = JZ4740_IRQ_TCU0,
+};
+
+static struct irqaction timer_irqaction = {
+	.handler	= jz4740_clockevent_irq,
+	.flags		= IRQF_PERCPU | IRQF_TIMER | IRQF_DISABLED,
+	.name		= "jz4740-timerirq",
+	.dev_id		= &jz4740_clockevent,
+};
+
+void __init plat_time_init(void)
+{
+	int ret;
+	uint32_t clk_rate;
+	uint16_t ctrl;
+
+	jz4740_timer_init();
+
+	clk_rate = jz4740_clock_bdata.ext_rate >> 4;
+	jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ);
+
+	clockevent_set_clock(&jz4740_clockevent, clk_rate);
+	jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent);
+	jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent);
+	jz4740_clockevent.cpumask = cpumask_of(0);
+
+	clockevents_register_device(&jz4740_clockevent);
+
+	clocksource_set_clock(&jz4740_clocksource, clk_rate);
+	ret = clocksource_register(&jz4740_clocksource);
+
+	if (ret)
+		printk(KERN_ERR "Failed to register clocksource: %d\n", ret);
+
+	setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction);
+
+	ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT;
+
+	jz4740_timer_set_ctrl(TIMER_CLOCKEVENT, ctrl);
+	jz4740_timer_set_ctrl(TIMER_CLOCKSOURCE, ctrl);
+
+	jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick);
+	jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
+
+	jz4740_timer_set_period(TIMER_CLOCKSOURCE, 0xffff);
+
+	jz4740_timer_enable(TIMER_CLOCKEVENT);
+	jz4740_timer_enable(TIMER_CLOCKSOURCE);
+}
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:51 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:05:31 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1047 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492618Ab0FBTEv (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:51 +0200
Received: (qmail 29991 invoked by uid 0); 2 Jun 2010 19:04:43 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:43 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 07/26] MIPS: JZ4740: Add setup code
Date:   Wed,  2 Jun 2010 21:02:58 +0200
Message-Id: <1275505397-16758-8-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27006
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1588
Content-Length: 1346
Lines: 50

This patch adds plat_mem_setup and get_system_type for JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/jz4740/setup.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/setup.c

diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
new file mode 100644
index 0000000..d449358
--- /dev/null
+++ b/arch/mips/jz4740/setup.c
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 setup code
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/clock.h>
+
+#include "reset.h"
+#include "clock.h"
+
+void __init plat_mem_setup(void)
+{
+	jz4740_reset_init();
+}
+
+const char *get_system_type(void)
+{
+	return "JZ4740";
+}
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:51 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:06:03 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1028 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492619Ab0FBTEv (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:51 +0200
Received: (qmail 30042 invoked by uid 0); 2 Jun 2010 19:04:44 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:43 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 08/26] MIPS: JZ4740: Add gpio support
Date:   Wed,  2 Jun 2010 21:02:59 +0200
Message-Id: <1275505397-16758-9-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27007
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1592
Content-Length: 33055
Lines: 1028

This patch adds gpiolib support for JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/include/asm/mach-jz4740/gpio.h |  398 ++++++++++++++++++++
 arch/mips/jz4740/gpio.c                  |  605 ++++++++++++++++++++++++++++++
 2 files changed, 1003 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/gpio.h
 create mode 100644 arch/mips/jz4740/gpio.c

diff --git a/arch/mips/include/asm/mach-jz4740/gpio.h b/arch/mips/include/asm/mach-jz4740/gpio.h
new file mode 100644
index 0000000..5f175d7
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/gpio.h
@@ -0,0 +1,398 @@
+/*
+ *  Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ7420/JZ4740 GPIO pin definitions
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _JZ_GPIO_H
+#define _JZ_GPIO_H
+
+#include <linux/types.h>
+
+enum jz_gpio_function {
+    JZ_GPIO_FUNC_NONE,
+    JZ_GPIO_FUNC1,
+    JZ_GPIO_FUNC2,
+    JZ_GPIO_FUNC3,
+};
+
+
+/*
+ Usually a driver for a SoC component has to request several gpio pins and
+ configure them as funcion pins.
+ jz_gpio_bulk_request can be used to ease this process.
+ Usually one would do something like:
+
+ const static struct jz_gpio_bulk_request i2c_pins[] = {
+	JZ_GPIO_BULK_PIN(I2C_SDA),
+	JZ_GPIO_BULK_PIN(I2C_SCK),
+ };
+
+ inside the probe function:
+
+    ret = jz_gpio_bulk_request(i2c_pins, ARRAY_SIZE(i2c_pins));
+    if (ret) {
+	...
+
+ inside the remove function:
+
+    jz_gpio_bulk_free(i2c_pins, ARRAY_SIZE(i2c_pins));
+
+
+*/
+struct jz_gpio_bulk_request {
+	int gpio;
+	const char *name;
+	enum jz_gpio_function function;
+};
+
+#define JZ_GPIO_BULK_PIN(pin) { \
+    .gpio = JZ_GPIO_ ## pin, \
+    .name = #pin, \
+    .function = JZ_GPIO_FUNC_ ## pin \
+}
+
+int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num);
+void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num);
+void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num);
+void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num);
+void jz_gpio_enable_pullup(unsigned gpio);
+void jz_gpio_disable_pullup(unsigned gpio);
+int jz_gpio_set_function(int gpio, enum jz_gpio_function function);
+
+int jz_gpio_port_direction_input(int port, uint32_t mask);
+int jz_gpio_port_direction_output(int port, uint32_t mask);
+void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask);
+uint32_t jz_gpio_port_get_value(int port, uint32_t mask);
+
+#include <asm/mach-generic/gpio.h>
+
+#define JZ_GPIO_PORTA(x) ((x) + 32 * 0)
+#define JZ_GPIO_PORTB(x) ((x) + 32 * 1)
+#define JZ_GPIO_PORTC(x) ((x) + 32 * 2)
+#define JZ_GPIO_PORTD(x) ((x) + 32 * 3)
+
+/* Port A function pins */
+#define JZ_GPIO_MEM_DATA0		JZ_GPIO_PORTA(0)
+#define JZ_GPIO_MEM_DATA1		JZ_GPIO_PORTA(1)
+#define JZ_GPIO_MEM_DATA2		JZ_GPIO_PORTA(2)
+#define JZ_GPIO_MEM_DATA3		JZ_GPIO_PORTA(3)
+#define JZ_GPIO_MEM_DATA4		JZ_GPIO_PORTA(4)
+#define JZ_GPIO_MEM_DATA5		JZ_GPIO_PORTA(5)
+#define JZ_GPIO_MEM_DATA6		JZ_GPIO_PORTA(6)
+#define JZ_GPIO_MEM_DATA7		JZ_GPIO_PORTA(7)
+#define JZ_GPIO_MEM_DATA8		JZ_GPIO_PORTA(8)
+#define JZ_GPIO_MEM_DATA9		JZ_GPIO_PORTA(9)
+#define JZ_GPIO_MEM_DATA10		JZ_GPIO_PORTA(10)
+#define JZ_GPIO_MEM_DATA11		JZ_GPIO_PORTA(11)
+#define JZ_GPIO_MEM_DATA12		JZ_GPIO_PORTA(12)
+#define JZ_GPIO_MEM_DATA13		JZ_GPIO_PORTA(13)
+#define JZ_GPIO_MEM_DATA14		JZ_GPIO_PORTA(14)
+#define JZ_GPIO_MEM_DATA15		JZ_GPIO_PORTA(15)
+#define JZ_GPIO_MEM_DATA16		JZ_GPIO_PORTA(16)
+#define JZ_GPIO_MEM_DATA17		JZ_GPIO_PORTA(17)
+#define JZ_GPIO_MEM_DATA18		JZ_GPIO_PORTA(18)
+#define JZ_GPIO_MEM_DATA19		JZ_GPIO_PORTA(19)
+#define JZ_GPIO_MEM_DATA20		JZ_GPIO_PORTA(20)
+#define JZ_GPIO_MEM_DATA21		JZ_GPIO_PORTA(21)
+#define JZ_GPIO_MEM_DATA22		JZ_GPIO_PORTA(22)
+#define JZ_GPIO_MEM_DATA23		JZ_GPIO_PORTA(23)
+#define JZ_GPIO_MEM_DATA24		JZ_GPIO_PORTA(24)
+#define JZ_GPIO_MEM_DATA25		JZ_GPIO_PORTA(25)
+#define JZ_GPIO_MEM_DATA26		JZ_GPIO_PORTA(26)
+#define JZ_GPIO_MEM_DATA27		JZ_GPIO_PORTA(27)
+#define JZ_GPIO_MEM_DATA28		JZ_GPIO_PORTA(28)
+#define JZ_GPIO_MEM_DATA29		JZ_GPIO_PORTA(29)
+#define JZ_GPIO_MEM_DATA30		JZ_GPIO_PORTA(30)
+#define JZ_GPIO_MEM_DATA31		JZ_GPIO_PORTA(31)
+
+#define JZ_GPIO_FUNC_MEM_DATA0		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA1		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA2		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA3		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA4		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA5		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA6		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA7		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA8		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA9		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA10		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA11		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA12		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA13		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA14		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA15		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA16		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA17		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA18		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA19		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA20		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA21		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA22		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA23		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA24		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA25		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA26		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA27		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA28		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA29		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA30		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DATA31		JZ_GPIO_FUNC1
+
+/* Port B function pins */
+#define JZ_GPIO_MEM_ADDR0		JZ_GPIO_PORTB(0)
+#define JZ_GPIO_MEM_ADDR1		JZ_GPIO_PORTB(1)
+#define JZ_GPIO_MEM_ADDR2		JZ_GPIO_PORTB(2)
+#define JZ_GPIO_MEM_ADDR3		JZ_GPIO_PORTB(3)
+#define JZ_GPIO_MEM_ADDR4		JZ_GPIO_PORTB(4)
+#define JZ_GPIO_MEM_ADDR5		JZ_GPIO_PORTB(5)
+#define JZ_GPIO_MEM_ADDR6		JZ_GPIO_PORTB(6)
+#define JZ_GPIO_MEM_ADDR7		JZ_GPIO_PORTB(7)
+#define JZ_GPIO_MEM_ADDR8		JZ_GPIO_PORTB(8)
+#define JZ_GPIO_MEM_ADDR9		JZ_GPIO_PORTB(9)
+#define JZ_GPIO_MEM_ADDR10		JZ_GPIO_PORTB(10)
+#define JZ_GPIO_MEM_ADDR11		JZ_GPIO_PORTB(11)
+#define JZ_GPIO_MEM_ADDR12		JZ_GPIO_PORTB(12)
+#define JZ_GPIO_MEM_ADDR13		JZ_GPIO_PORTB(13)
+#define JZ_GPIO_MEM_ADDR14		JZ_GPIO_PORTB(14)
+#define JZ_GPIO_MEM_ADDR15		JZ_GPIO_PORTB(15)
+#define JZ_GPIO_MEM_ADDR16		JZ_GPIO_PORTB(16)
+#define JZ_GPIO_MEM_CLS			JZ_GPIO_PORTB(17)
+#define JZ_GPIO_MEM_SPL			JZ_GPIO_PORTB(18)
+#define JZ_GPIO_MEM_DCS			JZ_GPIO_PORTB(19)
+#define JZ_GPIO_MEM_RAS			JZ_GPIO_PORTB(20)
+#define JZ_GPIO_MEM_CAS			JZ_GPIO_PORTB(21)
+#define JZ_GPIO_MEM_SDWE		JZ_GPIO_PORTB(22)
+#define JZ_GPIO_MEM_CKE			JZ_GPIO_PORTB(23)
+#define JZ_GPIO_MEM_CKO			JZ_GPIO_PORTB(24)
+#define JZ_GPIO_MEM_CS0			JZ_GPIO_PORTB(25)
+#define JZ_GPIO_MEM_CS1			JZ_GPIO_PORTB(26)
+#define JZ_GPIO_MEM_CS2			JZ_GPIO_PORTB(27)
+#define JZ_GPIO_MEM_CS3			JZ_GPIO_PORTB(28)
+#define JZ_GPIO_MEM_RD			JZ_GPIO_PORTB(29)
+#define JZ_GPIO_MEM_WR			JZ_GPIO_PORTB(30)
+#define JZ_GPIO_MEM_WE0			JZ_GPIO_PORTB(31)
+
+#define JZ_GPIO_FUNC_MEM_ADDR0		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR1		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR2		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR3		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR4		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR5		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR6		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR7		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR8		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR9		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR10		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR11		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR12		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR13		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR14		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR15		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_ADDR16		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CLS	        JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_SPL		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_DCS		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_RAS		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CAS		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_SDWE		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CKE		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CKO		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CS0		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CS1		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CS2		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_CS3		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_RD		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_WR		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_WE0		JZ_GPIO_FUNC1
+
+
+#define JZ_GPIO_MEM_ADDR21		JZ_GPIO_PORTB(17)
+#define JZ_GPIO_MEM_ADDR22		JZ_GPIO_PORTB(18)
+
+#define JZ_GPIO_FUNC_MEM_ADDR21		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_ADDR22		JZ_GPIO_FUNC2
+
+/* Port C function pins */
+#define JZ_GPIO_LCD_DATA0		JZ_GPIO_PORTC(0)
+#define JZ_GPIO_LCD_DATA1		JZ_GPIO_PORTC(1)
+#define JZ_GPIO_LCD_DATA2		JZ_GPIO_PORTC(2)
+#define JZ_GPIO_LCD_DATA3		JZ_GPIO_PORTC(3)
+#define JZ_GPIO_LCD_DATA4		JZ_GPIO_PORTC(4)
+#define JZ_GPIO_LCD_DATA5		JZ_GPIO_PORTC(5)
+#define JZ_GPIO_LCD_DATA6		JZ_GPIO_PORTC(6)
+#define JZ_GPIO_LCD_DATA7		JZ_GPIO_PORTC(7)
+#define JZ_GPIO_LCD_DATA8		JZ_GPIO_PORTC(8)
+#define JZ_GPIO_LCD_DATA9		JZ_GPIO_PORTC(9)
+#define JZ_GPIO_LCD_DATA10		JZ_GPIO_PORTC(10)
+#define JZ_GPIO_LCD_DATA11		JZ_GPIO_PORTC(11)
+#define JZ_GPIO_LCD_DATA12		JZ_GPIO_PORTC(12)
+#define JZ_GPIO_LCD_DATA13		JZ_GPIO_PORTC(13)
+#define JZ_GPIO_LCD_DATA14		JZ_GPIO_PORTC(14)
+#define JZ_GPIO_LCD_DATA15		JZ_GPIO_PORTC(15)
+#define JZ_GPIO_LCD_DATA16		JZ_GPIO_PORTC(16)
+#define JZ_GPIO_LCD_DATA17		JZ_GPIO_PORTC(17)
+#define JZ_GPIO_LCD_PCLK		JZ_GPIO_PORTC(18)
+#define JZ_GPIO_LCD_HSYNC		JZ_GPIO_PORTC(19)
+#define JZ_GPIO_LCD_VSYNC		JZ_GPIO_PORTC(20)
+#define JZ_GPIO_LCD_DE			JZ_GPIO_PORTC(21)
+#define JZ_GPIO_LCD_PS			JZ_GPIO_PORTC(22)
+#define JZ_GPIO_LCD_REV			JZ_GPIO_PORTC(23)
+#define JZ_GPIO_MEM_WE1			JZ_GPIO_PORTC(24)
+#define JZ_GPIO_MEM_WE2			JZ_GPIO_PORTC(25)
+#define JZ_GPIO_MEM_WE3			JZ_GPIO_PORTC(26)
+#define JZ_GPIO_MEM_WAIT		JZ_GPIO_PORTC(27)
+#define JZ_GPIO_MEM_FRE			JZ_GPIO_PORTC(28)
+#define JZ_GPIO_MEM_FWE			JZ_GPIO_PORTC(29)
+
+#define JZ_GPIO_FUNC_LCD_DATA0		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA1		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA2		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA3		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA4		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA5		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA6		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA7		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA8		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA9		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA10		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA11		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA12		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA13		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA14		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA15		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA16		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DATA17		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_PCLK		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_VSYNC		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_HSYNC		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_DE		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_PS		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_LCD_REV		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_WE1		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_WE2		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_WE3		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_WAIT		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_FRE		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MEM_FWE		JZ_GPIO_FUNC1
+
+
+#define JZ_GPIO_MEM_ADDR19		JZ_GPIO_PORTB(22)
+#define JZ_GPIO_MEM_ADDR20		JZ_GPIO_PORTB(23)
+
+#define JZ_GPIO_FUNC_MEM_ADDR19		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_ADDR20		JZ_GPIO_FUNC2
+
+/* Port D function pins */
+#define JZ_GPIO_CIM_DATA0		JZ_GPIO_PORTD(0)
+#define JZ_GPIO_CIM_DATA1		JZ_GPIO_PORTD(1)
+#define JZ_GPIO_CIM_DATA2		JZ_GPIO_PORTD(2)
+#define JZ_GPIO_CIM_DATA3		JZ_GPIO_PORTD(3)
+#define JZ_GPIO_CIM_DATA4		JZ_GPIO_PORTD(4)
+#define JZ_GPIO_CIM_DATA5		JZ_GPIO_PORTD(5)
+#define JZ_GPIO_CIM_DATA6		JZ_GPIO_PORTD(6)
+#define JZ_GPIO_CIM_DATA7		JZ_GPIO_PORTD(7)
+#define JZ_GPIO_MSC_CMD			JZ_GPIO_PORTD(8)
+#define JZ_GPIO_MSC_CLK			JZ_GPIO_PORTD(9)
+#define JZ_GPIO_MSC_DATA0		JZ_GPIO_PORTD(10)
+#define JZ_GPIO_MSC_DATA1		JZ_GPIO_PORTD(11)
+#define JZ_GPIO_MSC_DATA2		JZ_GPIO_PORTD(12)
+#define JZ_GPIO_MSC_DATA3		JZ_GPIO_PORTD(13)
+#define JZ_GPIO_CIM_MCLK		JZ_GPIO_PORTD(14)
+#define JZ_GPIO_CIM_PCLK		JZ_GPIO_PORTD(15)
+#define JZ_GPIO_CIM_VSYNC		JZ_GPIO_PORTD(16)
+#define JZ_GPIO_CIM_HSYNC		JZ_GPIO_PORTD(17)
+#define JZ_GPIO_SPI_CLK			JZ_GPIO_PORTD(18)
+#define JZ_GPIO_SPI_CE0			JZ_GPIO_PORTD(19)
+#define JZ_GPIO_SPI_DT			JZ_GPIO_PORTD(20)
+#define JZ_GPIO_SPI_DR			JZ_GPIO_PORTD(21)
+#define JZ_GPIO_SPI_CE1			JZ_GPIO_PORTD(22)
+#define JZ_GPIO_PWM0			JZ_GPIO_PORTD(23)
+#define JZ_GPIO_PWM1			JZ_GPIO_PORTD(24)
+#define JZ_GPIO_PWM2			JZ_GPIO_PORTD(25)
+#define JZ_GPIO_PWM3			JZ_GPIO_PORTD(26)
+#define JZ_GPIO_PWM4			JZ_GPIO_PORTD(27)
+#define JZ_GPIO_PWM5			JZ_GPIO_PORTD(28)
+#define JZ_GPIO_PWM6			JZ_GPIO_PORTD(30)
+#define JZ_GPIO_PWM7			JZ_GPIO_PORTD(31)
+
+#define JZ_GPIO_FUNC_CIM_DATA		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_CIM_DATA0		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA1		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA2		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA3		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA4		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA5		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA6		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_CIM_DATA7		JZ_GPIO_FUNC_CIM_DATA
+#define JZ_GPIO_FUNC_MSC_CMD		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MSC_CLK		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MSC_DATA		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_MSC_DATA0		JZ_GPIO_FUNC_MSC_DATA
+#define JZ_GPIO_FUNC_MSC_DATA1		JZ_GPIO_FUNC_MSC_DATA
+#define JZ_GPIO_FUNC_MSC_DATA2		JZ_GPIO_FUNC_MSC_DATA
+#define JZ_GPIO_FUNC_MSC_DATA3		JZ_GPIO_FUNC_MSC_DATA
+#define JZ_GPIO_FUNC_CIM_MCLK		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_CIM_PCLK		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_CIM_VSYNC		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_CIM_HSYNC		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_SPI_CLK		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_SPI_CE0		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_SPI_DT		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_SPI_DR		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_SPI_CE1		JZ_GPIO_FUNC1
+
+#define JZ_GPIO_FUNC_PWM		JZ_GPIO_FUNC1
+#define JZ_GPIO_FUNC_PWM0		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM1		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM2		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM3		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM4		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM5		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM6		JZ_GPIO_FUNC_PWM
+#define JZ_GPIO_FUNC_PWM7		JZ_GPIO_FUNC_PWM
+
+#define JZ_GPIO_MEM_SCLK_RSTN		JZ_GPIO_PORTD(18)
+#define JZ_GPIO_MEM_BCLK		JZ_GPIO_PORTD(19)
+#define JZ_GPIO_MEM_SDATO		JZ_GPIO_PORTD(20)
+#define JZ_GPIO_MEM_SDATI		JZ_GPIO_PORTD(21)
+#define JZ_GPIO_MEM_SYNC		JZ_GPIO_PORTD(22)
+#define JZ_GPIO_I2C_SDA			JZ_GPIO_PORTD(23)
+#define JZ_GPIO_I2C_SCK			JZ_GPIO_PORTD(24)
+#define JZ_GPIO_UART0_TXD		JZ_GPIO_PORTD(25)
+#define JZ_GPIO_UART0_RXD		JZ_GPIO_PORTD(26)
+#define JZ_GPIO_MEM_ADDR17		JZ_GPIO_PORTD(27)
+#define JZ_GPIO_MEM_ADDR18		JZ_GPIO_PORTD(28)
+#define JZ_GPIO_UART0_CTS		JZ_GPIO_PORTD(30)
+#define JZ_GPIO_UART0_RTS		JZ_GPIO_PORTD(31)
+
+#define JZ_GPIO_FUNC_MEM_SCLK_RSTN	JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_BCLK		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_SDATO		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_SDATI		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_SYNC		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_I2C_SDA		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_I2C_SCK		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_UART0_TXD		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_UART0_RXD		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_ADDR17		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_MEM_ADDR18		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_UART0_CTS		JZ_GPIO_FUNC2
+#define JZ_GPIO_FUNC_UART0_RTS		JZ_GPIO_FUNC2
+
+#define JZ_GPIO_UART1_RXD		JZ_GPIO_PORTD(30)
+#define JZ_GPIO_UART1_TXD		JZ_GPIO_PORTD(31)
+
+#define JZ_GPIO_FUNC_UART1_RXD		JZ_GPIO_FUNC3
+#define JZ_GPIO_FUNC_UART1_TXD		JZ_GPIO_FUNC3
+
+#endif
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c
new file mode 100644
index 0000000..8ef08da
--- /dev/null
+++ b/arch/mips/jz4740/gpio.c
@@ -0,0 +1,605 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform GPIO support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/spinlock.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/mach-jz4740/base.h>
+
+#define JZ4740_GPIO_BASE_A (32*0)
+#define JZ4740_GPIO_BASE_B (32*1)
+#define JZ4740_GPIO_BASE_C (32*2)
+#define JZ4740_GPIO_BASE_D (32*3)
+
+#define JZ4740_GPIO_NUM_A 32
+#define JZ4740_GPIO_NUM_B 32
+#define JZ4740_GPIO_NUM_C 31
+#define JZ4740_GPIO_NUM_D 32
+
+#define JZ4740_IRQ_GPIO_BASE_A (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_A)
+#define JZ4740_IRQ_GPIO_BASE_B (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_B)
+#define JZ4740_IRQ_GPIO_BASE_C (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_C)
+#define JZ4740_IRQ_GPIO_BASE_D (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_D)
+
+#define JZ_REG_GPIO_PIN			0x00
+#define JZ_REG_GPIO_DATA		0x10
+#define JZ_REG_GPIO_DATA_SET		0x14
+#define JZ_REG_GPIO_DATA_CLEAR		0x18
+#define JZ_REG_GPIO_MASK		0x20
+#define JZ_REG_GPIO_MASK_SET		0x24
+#define JZ_REG_GPIO_MASK_CLEAR		0x28
+#define JZ_REG_GPIO_PULL		0x30
+#define JZ_REG_GPIO_PULL_SET		0x34
+#define JZ_REG_GPIO_PULL_CLEAR		0x38
+#define JZ_REG_GPIO_FUNC		0x40
+#define JZ_REG_GPIO_FUNC_SET		0x44
+#define JZ_REG_GPIO_FUNC_CLEAR		0x48
+#define JZ_REG_GPIO_SELECT		0x50
+#define JZ_REG_GPIO_SELECT_SET		0x54
+#define JZ_REG_GPIO_SELECT_CLEAR	0x58
+#define JZ_REG_GPIO_DIRECTION		0x60
+#define JZ_REG_GPIO_DIRECTION_SET	0x64
+#define JZ_REG_GPIO_DIRECTION_CLEAR	0x68
+#define JZ_REG_GPIO_TRIGGER		0x70
+#define JZ_REG_GPIO_TRIGGER_SET		0x74
+#define JZ_REG_GPIO_TRIGGER_CLEAR	0x78
+#define JZ_REG_GPIO_FLAG		0x80
+#define JZ_REG_GPIO_FLAG_CLEAR		0x14
+
+
+#define GPIO_TO_BIT(gpio) BIT(gpio & 0x1f)
+#define GPIO_TO_REG(gpio, reg) (gpio_to_jz_gpio_chip(gpio)->base + (reg))
+#define CHIP_TO_REG(chip, reg) (gpio_chip_to_jz_gpio_chip(chip)->base + (reg))
+
+struct jz_gpio_chip {
+	unsigned int irq;
+	unsigned int irq_base;
+	uint32_t wakeup;
+	uint32_t suspend_mask;
+	uint32_t edge_trigger_both;
+
+	void __iomem *base;
+
+	spinlock_t lock;
+
+	struct gpio_chip gpio_chip;
+	struct irq_chip irq_chip;
+	struct sys_device sysdev;
+};
+
+
+static struct jz_gpio_chip jz4740_gpio_chips[];
+
+static inline struct jz_gpio_chip *gpio_to_jz_gpio_chip(unsigned int gpio)
+{
+	return &jz4740_gpio_chips[gpio >> 5];
+}
+
+static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *gpio_chip)
+{
+	return container_of(gpio_chip, struct jz_gpio_chip, gpio_chip);
+}
+
+static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(unsigned int irq)
+{
+	return get_irq_chip_data(irq);
+}
+
+static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg)
+{
+	writel(GPIO_TO_BIT(gpio), GPIO_TO_REG(gpio, reg));
+}
+
+int jz_gpio_set_function(int gpio, enum jz_gpio_function function)
+{
+	if (function == JZ_GPIO_FUNC_NONE) {
+		jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_CLEAR);
+		jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR);
+		jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR);
+	} else {
+		jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_SET);
+		jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR);
+		switch (function) {
+		case JZ_GPIO_FUNC1:
+			jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR);
+			break;
+		case JZ_GPIO_FUNC3:
+			jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_SET);
+		case JZ_GPIO_FUNC2: /* Falltrough */
+			jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_SET);
+			break;
+		default:
+			BUG();
+			break;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(jz_gpio_set_function);
+
+int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num)
+{
+	size_t i;
+	int ret;
+
+	for (i = 0; i < num; ++i, ++request) {
+		ret = gpio_request(request->gpio, request->name);
+		if (ret)
+			goto err;
+		jz_gpio_set_function(request->gpio, request->function);
+	}
+
+	return 0;
+
+err:
+	for (--request; i > 0; --i, --request) {
+		gpio_free(request->gpio);
+		jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_request);
+
+void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num)
+{
+	size_t i;
+
+	for (i = 0; i < num; ++i, ++request) {
+		gpio_free(request->gpio);
+		jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE);
+	}
+
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_free);
+
+void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num)
+{
+	size_t i;
+
+	for (i = 0; i < num; ++i, ++request) {
+		jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE);
+		jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_CLEAR);
+		jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_PULL_SET);
+	}
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_suspend);
+
+void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num)
+{
+	size_t i;
+
+	for (i = 0; i < num; ++i, ++request)
+		jz_gpio_set_function(request->gpio, request->function);
+}
+EXPORT_SYMBOL_GPL(jz_gpio_bulk_resume);
+
+void jz_gpio_enable_pullup(unsigned gpio)
+{
+	jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_CLEAR);
+}
+EXPORT_SYMBOL_GPL(jz_gpio_enable_pullup);
+
+void jz_gpio_disable_pullup(unsigned gpio)
+{
+	jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_SET);
+}
+EXPORT_SYMBOL_GPL(jz_gpio_disable_pullup);
+
+static int jz_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	return !!(readl(CHIP_TO_REG(chip, JZ_REG_GPIO_PIN)) & BIT(gpio));
+}
+
+static void jz_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+	uint32_t __iomem *reg = CHIP_TO_REG(chip, JZ_REG_GPIO_DATA_SET);
+	reg += !value;
+	writel(BIT(gpio), reg);
+}
+
+static int jz_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+	int value)
+{
+	writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_SET));
+	jz_gpio_set_value(chip, gpio, value);
+
+	return 0;
+}
+
+static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_CLEAR));
+
+	return 0;
+}
+
+int jz_gpio_port_direction_input(int port, uint32_t mask)
+{
+	writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR));
+
+	return 0;
+}
+EXPORT_SYMBOL(jz_gpio_port_direction_input);
+
+int jz_gpio_port_direction_output(int port, uint32_t mask)
+{
+	writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_SET));
+
+	return 0;
+}
+EXPORT_SYMBOL(jz_gpio_port_direction_output);
+
+void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask)
+{
+	writel(~value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_CLEAR));
+	writel(value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_SET));
+}
+EXPORT_SYMBOL(jz_gpio_port_set_value);
+
+uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
+{
+	uint32_t value = readl(GPIO_TO_REG(port, JZ_REG_GPIO_PIN));
+
+	return value & mask;
+}
+EXPORT_SYMBOL(jz_gpio_port_get_value);
+
+int gpio_to_irq(unsigned gpio)
+{
+	return JZ4740_IRQ_GPIO(0) + gpio;
+}
+EXPORT_SYMBOL_GPL(gpio_to_irq);
+
+int irq_to_gpio(unsigned irq)
+{
+	return irq - JZ4740_IRQ_GPIO(0);
+}
+EXPORT_SYMBOL_GPL(irq_to_gpio);
+
+#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f)
+
+static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq)
+{
+	uint32_t value;
+	void __iomem *reg;
+	uint32_t mask = IRQ_TO_BIT(irq);
+
+	if (!(chip->edge_trigger_both & mask))
+		return;
+
+	reg = chip->base;
+
+	value = readl(chip->base + JZ_REG_GPIO_PIN);
+	if (value & mask)
+		reg += JZ_REG_GPIO_DIRECTION_CLEAR;
+	else
+		reg += JZ_REG_GPIO_DIRECTION_SET;
+
+	writel(mask, reg);
+}
+
+static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	uint32_t flag;
+	unsigned int gpio_irq;
+	unsigned int gpio_bank;
+	struct jz_gpio_chip *chip = get_irq_desc_data(desc);
+
+	gpio_bank = JZ4740_IRQ_GPIO0 - irq;
+
+	flag = readl(chip->base + JZ_REG_GPIO_FLAG);
+
+	gpio_irq = ffs(flag) - 1;
+
+	jz_gpio_check_trigger_both(chip, irq);
+
+	gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0);
+
+	generic_handle_irq(gpio_irq);
+};
+
+static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg)
+{
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
+	writel(IRQ_TO_BIT(irq), chip->base + reg);
+}
+
+static void jz_gpio_irq_mask(unsigned int irq)
+{
+	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET);
+};
+
+static void jz_gpio_irq_unmask(unsigned int irq)
+{
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
+
+	jz_gpio_check_trigger_both(chip, irq);
+
+	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR);
+};
+
+
+/* TODO: Check if function is gpio */
+static unsigned int jz_gpio_irq_startup(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET);
+
+	desc->status &= ~IRQ_MASKED;
+	jz_gpio_irq_unmask(irq);
+
+	return 0;
+}
+
+static void jz_gpio_irq_shutdown(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	jz_gpio_irq_mask(irq);
+	desc->status |= IRQ_MASKED;
+
+	/* Set direction to input */
+	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
+	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR);
+}
+
+static void jz_gpio_irq_ack(unsigned int irq)
+{
+	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR);
+};
+
+static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	jz_gpio_irq_mask(irq);
+
+	if (flow_type == IRQ_TYPE_EDGE_BOTH) {
+		uint32_t value = readl(chip->base + JZ_REG_GPIO_PIN);
+		if (value & IRQ_TO_BIT(irq))
+			flow_type = IRQ_TYPE_EDGE_FALLING;
+		else
+			flow_type = IRQ_TYPE_EDGE_RISING;
+		chip->edge_trigger_both |= IRQ_TO_BIT(irq);
+	} else {
+		chip->edge_trigger_both &= ~IRQ_TO_BIT(irq);
+	}
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_RISING:
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET);
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET);
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
+		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!(desc->status & IRQ_MASKED))
+		jz_gpio_irq_unmask(irq);
+
+	return 0;
+}
+
+static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
+	spin_lock(&chip->lock);
+	if (on)
+		chip->wakeup |= IRQ_TO_BIT(irq);
+	else
+		chip->wakeup &= ~IRQ_TO_BIT(irq);
+	spin_unlock(&chip->lock);
+
+	set_irq_wake(chip->irq, on);
+	return 0;
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+#define JZ4740_GPIO_CHIP(_bank) { \
+	.irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \
+	.gpio_chip = { \
+		.label = "Bank " # _bank, \
+		.owner = THIS_MODULE, \
+		.set = jz_gpio_set_value, \
+		.get = jz_gpio_get_value, \
+		.direction_output = jz_gpio_direction_output, \
+		.direction_input = jz_gpio_direction_input, \
+		.base = JZ4740_GPIO_BASE_ ## _bank, \
+		.ngpio = JZ4740_GPIO_NUM_ ## _bank, \
+	}, \
+	.irq_chip =  { \
+		.name = "GPIO Bank " # _bank, \
+		.mask = jz_gpio_irq_mask, \
+		.unmask = jz_gpio_irq_unmask, \
+		.ack = jz_gpio_irq_ack, \
+		.startup = jz_gpio_irq_startup, \
+		.shutdown = jz_gpio_irq_shutdown, \
+		.set_type = jz_gpio_irq_set_type, \
+		.set_wake = jz_gpio_irq_set_wake, \
+	}, \
+}
+
+static struct jz_gpio_chip jz4740_gpio_chips[] = {
+	JZ4740_GPIO_CHIP(A),
+	JZ4740_GPIO_CHIP(B),
+	JZ4740_GPIO_CHIP(C),
+	JZ4740_GPIO_CHIP(D),
+};
+
+static inline struct jz_gpio_chip *sysdev_to_chip(struct sys_device *dev)
+{
+	return container_of(dev, struct jz_gpio_chip, sysdev);
+}
+
+static int jz4740_gpio_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct jz_gpio_chip *chip = sysdev_to_chip(dev);
+
+	chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK);
+	writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET);
+	writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR);
+
+	return 0;
+}
+
+static int jz4740_gpio_resume(struct sys_device *dev)
+{
+	struct jz_gpio_chip *chip = sysdev_to_chip(dev);
+	uint32_t mask = chip->suspend_mask;
+
+	writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR);
+	writel(mask, chip->base + JZ_REG_GPIO_MASK_SET);
+
+	return 0;
+}
+
+static struct sysdev_class jz4740_gpio_sysdev_class = {
+	.name = "gpio",
+	.suspend = jz4740_gpio_suspend,
+	.resume = jz4740_gpio_resume,
+};
+
+static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
+{
+	int ret, irq;
+
+	chip->sysdev.id = id;
+	chip->sysdev.cls = &jz4740_gpio_sysdev_class;
+	ret = sysdev_register(&chip->sysdev);
+
+	if (ret)
+		return ret;
+
+	spin_lock_init(&chip->lock);
+
+	chip->base = ioremap(CPHYSADDR(JZ4740_GPIO_BASE_ADDR) + (id * 0x100), 0x100);
+
+	gpiochip_add(&chip->gpio_chip);
+
+	chip->irq = JZ4740_IRQ_INTC_GPIO(id);
+	set_irq_data(chip->irq, chip);
+	set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
+
+	for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) {
+		lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class);
+		set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq);
+		set_irq_chip_data(irq, chip);
+	}
+
+	return 0;
+}
+
+static int __init jz4740_gpio_init(void)
+{
+	unsigned int i;
+	int ret;
+
+	ret = sysdev_class_register(&jz4740_gpio_sysdev_class);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i)
+		jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i);
+
+	printk(KERN_INFO "JZ4740 GPIO initalized\n");
+
+	return 0;
+}
+arch_initcall(jz4740_gpio_init);
+
+#ifdef CONFIG_DEBUG_FS
+
+static inline void gpio_seq_reg(struct seq_file *s, struct jz_gpio_chip *chip,
+	const char *name, unsigned int reg)
+{
+	seq_printf(s, "\t%s: %08x\n", name, readl(chip->base + reg));
+}
+
+
+static int gpio_regs_show(struct seq_file *s, void *unused)
+{
+	struct jz_gpio_chip *chip = jz4740_gpio_chips;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i, ++chip) {
+		seq_printf(s, "==GPIO %d==\n", i);
+		gpio_seq_reg(s, chip, "Pin", JZ_REG_GPIO_PIN);
+		gpio_seq_reg(s, chip, "Data", JZ_REG_GPIO_DATA);
+		gpio_seq_reg(s, chip, "Mask", JZ_REG_GPIO_MASK);
+		gpio_seq_reg(s, chip, "Pull", JZ_REG_GPIO_PULL);
+		gpio_seq_reg(s, chip, "Func", JZ_REG_GPIO_FUNC);
+		gpio_seq_reg(s, chip, "Select", JZ_REG_GPIO_SELECT);
+		gpio_seq_reg(s, chip, "Direction", JZ_REG_GPIO_DIRECTION);
+		gpio_seq_reg(s, chip, "Trigger", JZ_REG_GPIO_TRIGGER);
+		gpio_seq_reg(s, chip, "Flag", JZ_REG_GPIO_FLAG);
+	}
+
+	return 0;
+}
+
+static int gpio_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, gpio_regs_show, NULL);
+}
+
+static const struct file_operations gpio_regs_operations = {
+	.open		= gpio_regs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init gpio_debugfs_init(void)
+{
+	(void) debugfs_create_file("jz_regs_gpio", S_IFREG | S_IRUGO,
+				NULL, NULL, &gpio_regs_operations);
+	return 0;
+}
+subsys_initcall(gpio_debugfs_init);
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:52 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:06:32 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1085 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492621Ab0FBTEw (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:52 +0200
Received: (qmail 29798 invoked by uid 0); 2 Jun 2010 19:04:41 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:41 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 03/26] MIPS: JZ4740: Add clock API support.
Date:   Wed,  2 Jun 2010 21:02:54 +0200
Message-Id: <1275505397-16758-4-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27008
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1593
Content-Length: 28640
Lines: 1175

This patch adds support for managing the clocks found on JZ4740 SoC through
the Linux clock API.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/include/asm/mach-jz4740/clock.h |   28 +
 arch/mips/jz4740/clock-debugfs.c          |  109 ++++
 arch/mips/jz4740/clock.c                  |  920 +++++++++++++++++++++++++++++
 arch/mips/jz4740/clock.h                  |   76 +++
 4 files changed, 1133 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/clock.h
 create mode 100644 arch/mips/jz4740/clock-debugfs.c
 create mode 100644 arch/mips/jz4740/clock.c
 create mode 100644 arch/mips/jz4740/clock.h

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
new file mode 100644
index 0000000..9069727
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __ASM_JZ4740_CLOCK_H__
+#define __ASM_JZ4740_CLOCK_H__
+
+enum jz4740_wait_mode {
+	JZ4740_WAIT_MODE_IDLE,
+	JZ4740_WAIT_MODE_SLEEP,
+};
+
+void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
+
+void jz4740_clock_udc_enable_auto_suspend(void);
+void jz4740_clock_udc_disable_auto_suspend(void);
+
+#endif
diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c
new file mode 100644
index 0000000..993b91b
--- /dev/null
+++ b/arch/mips/jz4740/clock-debugfs.c
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 SoC clock support debugfs entries
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include <asm/mach-jz4740/clock.h>
+#include "clock.h"
+
+static struct dentry *jz4740_clock_debugfs;
+
+static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value)
+{
+	struct clk *clk = data;
+	*value = clk_is_enabled(clk);
+
+	return 0;
+}
+
+static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value)
+{
+	struct clk *clk = data;
+
+	if (value)
+		return clk_enable(clk);
+	else
+		clk_disable(clk);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled,
+	jz4740_clock_debugfs_show_enabled,
+	jz4740_clock_debugfs_set_enabled,
+	"%llu\n");
+
+static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value)
+{
+	struct clk *clk = data;
+	*value = clk_get_rate(clk);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate,
+	jz4740_clock_debugfs_show_rate,
+	NULL,
+	"%llu\n");
+
+void jz4740_clock_debugfs_add_clk(struct clk *clk)
+{
+	if (!jz4740_clock_debugfs)
+		return;
+
+	clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs);
+	debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk,
+				&jz4740_clock_debugfs_ops_rate);
+	debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk,
+				&jz4740_clock_debugfs_ops_enabled);
+
+	if (clk->parent) {
+		char parent_path[100];
+		snprintf(parent_path, 100, "../%s", clk->parent->name);
+		clk->debugfs_parent_entry = debugfs_create_symlink("parent",
+						clk->debugfs_entry,
+						parent_path);
+	}
+}
+
+/* TODO: Locking */
+void jz4740_clock_debugfs_update_parent(struct clk *clk)
+{
+	if (clk->debugfs_parent_entry)
+		debugfs_remove(clk->debugfs_parent_entry);
+
+	if (clk->parent) {
+		char parent_path[100];
+		snprintf(parent_path, 100, "../%s", clk->parent->name);
+		clk->debugfs_parent_entry = debugfs_create_symlink("parent",
+						clk->debugfs_entry,
+						parent_path);
+	} else {
+		clk->debugfs_parent_entry = NULL;
+	}
+}
+
+void jz4740_clock_debugfs_init(void)
+{
+	jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL);
+	if (IS_ERR(jz4740_clock_debugfs))
+		jz4740_clock_debugfs = NULL;
+}
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
new file mode 100644
index 0000000..378f2b0
--- /dev/null
+++ b/arch/mips/jz4740/clock.c
@@ -0,0 +1,920 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 SoC clock support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/err.h>
+
+#include <asm/mach-jz4740/clock.h>
+#include <asm/mach-jz4740/base.h>
+
+#include "clock.h"
+
+#define JZ_REG_CLOCK_CTRL	0x00
+#define JZ_REG_CLOCK_LOW_POWER	0x04
+#define JZ_REG_CLOCK_PLL	0x10
+#define JZ_REG_CLOCK_GATE	0x20
+#define JZ_REG_CLOCK_SLEEP_CTRL	0x24
+#define JZ_REG_CLOCK_I2S	0x60
+#define JZ_REG_CLOCK_LCD	0x64
+#define JZ_REG_CLOCK_MMC	0x68
+#define JZ_REG_CLOCK_UHC	0x6C
+#define JZ_REG_CLOCK_SPI	0x74
+
+#define JZ_CLOCK_CTRL_I2S_SRC_PLL	BIT(31)
+#define JZ_CLOCK_CTRL_KO_ENABLE		BIT(30)
+#define JZ_CLOCK_CTRL_UDC_SRC_PLL	BIT(29)
+#define JZ_CLOCK_CTRL_UDIV_MASK		0x1f800000
+#define JZ_CLOCK_CTRL_CHANGE_ENABLE	BIT(22)
+#define JZ_CLOCK_CTRL_PLL_HALF		BIT(21)
+#define JZ_CLOCK_CTRL_LDIV_MASK		0x001f0000
+#define JZ_CLOCK_CTRL_UDIV_OFFSET	23
+#define JZ_CLOCK_CTRL_LDIV_OFFSET	16
+#define JZ_CLOCK_CTRL_MDIV_OFFSET	12
+#define JZ_CLOCK_CTRL_PDIV_OFFSET	 8
+#define JZ_CLOCK_CTRL_HDIV_OFFSET	 4
+#define JZ_CLOCK_CTRL_CDIV_OFFSET	 0
+
+#define JZ_CLOCK_GATE_UART0	BIT(0)
+#define JZ_CLOCK_GATE_TCU	BIT(1)
+#define JZ_CLOCK_GATE_RTC	BIT(2)
+#define JZ_CLOCK_GATE_I2C	BIT(3)
+#define JZ_CLOCK_GATE_SPI	BIT(4)
+#define JZ_CLOCK_GATE_AIC	BIT(5)
+#define JZ_CLOCK_GATE_I2S	BIT(6)
+#define JZ_CLOCK_GATE_MMC	BIT(7)
+#define JZ_CLOCK_GATE_ADC	BIT(8)
+#define JZ_CLOCK_GATE_CIM	BIT(9)
+#define JZ_CLOCK_GATE_LCD	BIT(10)
+#define JZ_CLOCK_GATE_UDC	BIT(11)
+#define JZ_CLOCK_GATE_DMAC	BIT(12)
+#define JZ_CLOCK_GATE_IPU	BIT(13)
+#define JZ_CLOCK_GATE_UHC	BIT(14)
+#define JZ_CLOCK_GATE_UART1	BIT(15)
+
+#define JZ_CLOCK_I2S_DIV_MASK		0x01ff
+
+#define JZ_CLOCK_LCD_DIV_MASK		0x01ff
+
+#define JZ_CLOCK_MMC_DIV_MASK		0x001f
+
+#define JZ_CLOCK_UHC_DIV_MASK		0x000f
+
+#define JZ_CLOCK_SPI_SRC_PLL		BIT(31)
+#define JZ_CLOCK_SPI_DIV_MASK		0x000f
+
+#define JZ_CLOCK_PLL_M_MASK		0x01ff
+#define JZ_CLOCK_PLL_N_MASK		0x001f
+#define JZ_CLOCK_PLL_OD_MASK		0x0003
+#define JZ_CLOCK_PLL_STABLE		BIT(10)
+#define JZ_CLOCK_PLL_BYPASS		BIT(9)
+#define JZ_CLOCK_PLL_ENABLED		BIT(8)
+#define JZ_CLOCK_PLL_STABLIZE_MASK	0x000f
+#define JZ_CLOCK_PLL_M_OFFSET		23
+#define JZ_CLOCK_PLL_N_OFFSET		18
+#define JZ_CLOCK_PLL_OD_OFFSET		16
+
+#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
+#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
+
+#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
+#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
+
+static void __iomem *jz_clock_base;
+static spinlock_t jz_clock_lock;
+static LIST_HEAD(jz_clocks);
+
+struct main_clk {
+	struct clk clk;
+	uint32_t div_offset;
+};
+
+struct divided_clk {
+	struct clk clk;
+	uint32_t reg;
+	uint32_t mask;
+};
+
+struct static_clk {
+	struct clk clk;
+	unsigned long rate;
+};
+
+static uint32_t jz_clk_reg_read(int reg)
+{
+	return readl(jz_clock_base + reg);
+}
+
+static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
+{
+	uint32_t val2;
+
+	spin_lock(&jz_clock_lock);
+	val2 = readl(jz_clock_base + reg);
+	val2 &= ~mask;
+	val2 |= val;
+	writel(val2, jz_clock_base + reg);
+	spin_unlock(&jz_clock_lock);
+}
+
+static void jz_clk_reg_set_bits(int reg, uint32_t mask)
+{
+	uint32_t val;
+
+	spin_lock(&jz_clock_lock);
+	val = readl(jz_clock_base + reg);
+	val |= mask;
+	writel(val, jz_clock_base + reg);
+	spin_unlock(&jz_clock_lock);
+}
+
+static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
+{
+	uint32_t val;
+
+	spin_lock(&jz_clock_lock);
+	val = readl(jz_clock_base + reg);
+	val &= ~mask;
+	writel(val, jz_clock_base + reg);
+	spin_unlock(&jz_clock_lock);
+}
+
+static int jz_clk_enable_gating(struct clk *clk)
+{
+	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
+		return -EINVAL;
+
+	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
+	return 0;
+}
+
+static int jz_clk_disable_gating(struct clk *clk)
+{
+	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
+		return -EINVAL;
+
+	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
+	return 0;
+}
+
+static int jz_clk_is_enabled_gating(struct clk *clk)
+{
+	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
+		return 1;
+
+	return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
+}
+
+static unsigned long jz_clk_static_get_rate(struct clk *clk)
+{
+	return ((struct static_clk *)clk)->rate;
+}
+
+static int jz_clk_ko_enable(struct clk *clk)
+{
+	jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
+	return 0;
+}
+
+static int jz_clk_ko_disable(struct clk *clk)
+{
+	jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
+	return 0;
+}
+
+static int jz_clk_ko_is_enabled(struct clk *clk)
+{
+	return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
+}
+
+static const int pllno[] = {1, 2, 2, 4};
+
+static unsigned long jz_clk_pll_get_rate(struct clk *clk)
+{
+	uint32_t val;
+	int m;
+	int n;
+	int od;
+
+	val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
+
+	if (val & JZ_CLOCK_PLL_BYPASS)
+		return clk_get_rate(clk->parent);
+
+	m = ((val >> 23) & 0x1ff) + 2;
+	n = ((val >> 18) & 0x1f) + 2;
+	od = (val >> 16) & 0x3;
+
+	return clk_get_rate(clk->parent) * (m / n) / pllno[od];
+}
+
+static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
+{
+	uint32_t reg;
+
+	reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+	if (reg & JZ_CLOCK_CTRL_PLL_HALF)
+		return jz_clk_pll_get_rate(clk->parent);
+	return jz_clk_pll_get_rate(clk->parent) >> 1;
+}
+
+static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
+	int div;
+
+	div = parent_rate / rate;
+	if (div > 32)
+		return parent_rate / 32;
+	else if (div < 1)
+		return parent_rate;
+
+	div &= (0x3 << (ffs(div) - 1));
+
+	return parent_rate / div;
+}
+
+static unsigned long jz_clk_main_get_rate(struct clk *clk)
+{
+	struct main_clk *mclk = (struct main_clk *)clk;
+	uint32_t div;
+
+	div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+
+	div >>= mclk->div_offset;
+	div &= 0xf;
+
+	if (div >= ARRAY_SIZE(jz_clk_main_divs))
+		div = ARRAY_SIZE(jz_clk_main_divs) - 1;
+
+	return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
+}
+
+static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct main_clk *mclk = (struct main_clk *)clk;
+	int i;
+	int div;
+	unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
+
+	rate = jz_clk_main_round_rate(clk, rate);
+
+	div = parent_rate / rate;
+
+	i = (ffs(div) - 1) << 1;
+	if (i > 0 && !(div & BIT(i-1)))
+		i -= 1;
+
+	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
+				0xf << mclk->div_offset);
+
+	return 0;
+}
+
+static struct clk_ops jz_clk_static_ops = {
+	.get_rate = jz_clk_static_get_rate,
+	.enable = jz_clk_enable_gating,
+	.disable = jz_clk_disable_gating,
+	.is_enabled = jz_clk_is_enabled_gating,
+};
+
+static struct static_clk jz_clk_ext = {
+	.clk = {
+		.name = "ext",
+		.gate_bit = JZ4740_CLK_NOT_GATED,
+		.ops = &jz_clk_static_ops,
+	},
+};
+
+static struct clk_ops jz_clk_pll_ops = {
+	.get_rate = jz_clk_static_get_rate,
+};
+
+static struct clk jz_clk_pll = {
+	.name = "pll",
+	.parent = &jz_clk_ext.clk,
+	.ops = &jz_clk_pll_ops,
+};
+
+static struct clk_ops jz_clk_pll_half_ops = {
+	.get_rate = jz_clk_pll_half_get_rate,
+};
+
+static struct clk jz_clk_pll_half = {
+	.name = "pll half",
+	.parent = &jz_clk_pll,
+	.ops = &jz_clk_pll_half_ops,
+};
+
+static const struct clk_ops jz_clk_main_ops = {
+	.get_rate = jz_clk_main_get_rate,
+	.set_rate = jz_clk_main_set_rate,
+	.round_rate = jz_clk_main_round_rate,
+};
+
+static struct main_clk jz_clk_cpu = {
+	.clk = {
+		.name = "cclk",
+		.parent = &jz_clk_pll,
+		.ops = &jz_clk_main_ops,
+	},
+	.div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
+};
+
+static struct main_clk jz_clk_memory = {
+	.clk = {
+		.name = "mclk",
+		.parent = &jz_clk_pll,
+		.ops = &jz_clk_main_ops,
+	},
+	.div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
+};
+
+static struct main_clk jz_clk_high_speed_peripheral = {
+	.clk = {
+		.name = "hclk",
+		.parent = &jz_clk_pll,
+		.ops = &jz_clk_main_ops,
+	},
+	.div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
+};
+
+
+static struct main_clk jz_clk_low_speed_peripheral = {
+	.clk = {
+		.name = "pclk",
+		.parent = &jz_clk_pll,
+		.ops = &jz_clk_main_ops,
+	},
+	.div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
+};
+
+static const struct clk_ops jz_clk_ko_ops = {
+	.enable = jz_clk_ko_enable,
+	.disable = jz_clk_ko_disable,
+	.is_enabled = jz_clk_ko_is_enabled,
+};
+
+static struct clk jz_clk_ko = {
+	.name = "cko",
+	.parent = &jz_clk_memory.clk,
+	.ops = &jz_clk_ko_ops,
+};
+
+static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (parent == &jz_clk_pll)
+		jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
+	else if (parent == &jz_clk_ext.clk)
+		jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	return 0;
+}
+
+static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (parent == &jz_clk_pll_half)
+		jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
+	else if (parent == &jz_clk_ext.clk)
+		jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	return 0;
+}
+
+static int jz_clk_udc_enable(struct clk *clk)
+{
+	jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
+			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
+
+	return 0;
+}
+
+static int jz_clk_udc_disable(struct clk *clk)
+{
+	jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
+			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
+
+	return 0;
+}
+
+static int jz_clk_udc_is_enabled(struct clk *clk)
+{
+	return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
+			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
+}
+static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (parent == &jz_clk_pll_half)
+		jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
+	else if (parent == &jz_clk_ext.clk)
+		jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	return 0;
+}
+
+static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
+{
+	int div;
+
+	if (clk->parent == &jz_clk_ext.clk)
+		return -EINVAL;
+
+	div = clk_get_rate(clk->parent) / rate - 1;
+
+	if (div < 0)
+		div = 0;
+	else if (div > 63)
+		div = 63;
+
+	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
+				JZ_CLOCK_CTRL_UDIV_MASK);
+	return 0;
+}
+
+static unsigned long jz_clk_udc_get_rate(struct clk *clk)
+{
+	int div;
+
+	if (clk->parent == &jz_clk_ext.clk)
+		return clk_get_rate(clk->parent);
+
+	div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
+	div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
+	div += 1;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long jz_clk_divided_get_rate(struct clk *clk)
+{
+	struct divided_clk *dclk = (struct divided_clk *)clk;
+	int div;
+
+	if (clk->parent == &jz_clk_ext.clk)
+		return clk_get_rate(clk->parent);
+
+	div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct divided_clk *dclk = (struct divided_clk *)clk;
+	int div;
+
+	if (clk->parent == &jz_clk_ext.clk)
+		return -EINVAL;
+
+	div = clk_get_rate(clk->parent) / rate - 1;
+
+	if (div < 0)
+		div = 0;
+	else if (div > dclk->mask)
+		div = dclk->mask;
+
+	jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
+
+	return 0;
+}
+
+static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
+{
+	int div;
+	unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
+
+	if (rate > 150000000)
+		return 150000000;
+
+	div = parent_rate / rate;
+	if (div < 1)
+		div = 1;
+	else if (div > 32)
+		div = 32;
+
+	return parent_rate / div;
+}
+
+static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int div;
+
+	if (rate > 150000000)
+		return -EINVAL;
+
+	div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
+	if (div < 0)
+		div = 0;
+	else if (div > 31)
+		div = 31;
+
+	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
+				JZ_CLOCK_CTRL_LDIV_MASK);
+
+	return 0;
+}
+
+static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
+{
+	int div;
+
+	div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
+	div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
+
+	return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
+}
+
+static const struct clk_ops jz_clk_ops_ld = {
+	.set_rate = jz_clk_ldclk_set_rate,
+	.get_rate = jz_clk_ldclk_get_rate,
+	.round_rate = jz_clk_ldclk_round_rate,
+	.enable = jz_clk_enable_gating,
+	.disable = jz_clk_disable_gating,
+	.is_enabled = jz_clk_is_enabled_gating,
+};
+
+static struct clk jz_clk_ld = {
+	.name = "lcd",
+	.gate_bit = JZ_CLOCK_GATE_LCD,
+	.parent = &jz_clk_pll_half,
+	.ops = &jz_clk_ops_ld,
+};
+
+static const struct clk_ops jz_clk_i2s_ops = {
+	.set_rate = jz_clk_divided_set_rate,
+	.get_rate = jz_clk_divided_get_rate,
+	.enable = jz_clk_enable_gating,
+	.disable = jz_clk_disable_gating,
+	.is_enabled = jz_clk_is_enabled_gating,
+	.set_parent = jz_clk_i2s_set_parent,
+};
+
+static const struct clk_ops jz_clk_spi_ops = {
+	.set_rate = jz_clk_divided_set_rate,
+	.get_rate = jz_clk_divided_get_rate,
+	.enable = jz_clk_enable_gating,
+	.disable = jz_clk_disable_gating,
+	.is_enabled = jz_clk_is_enabled_gating,
+	.set_parent = jz_clk_spi_set_parent,
+};
+
+static const struct clk_ops jz_clk_divided_ops = {
+	.set_rate = jz_clk_divided_set_rate,
+	.get_rate = jz_clk_divided_get_rate,
+	.enable = jz_clk_enable_gating,
+	.disable = jz_clk_disable_gating,
+	.is_enabled = jz_clk_is_enabled_gating,
+};
+
+static struct divided_clk jz4740_clock_divided_clks[] = {
+	{
+		.clk = {
+			.name = "lcd_pclk",
+			.parent = &jz_clk_pll_half,
+			.gate_bit = JZ4740_CLK_NOT_GATED,
+			.ops = &jz_clk_divided_ops,
+		},
+		.reg = JZ_REG_CLOCK_LCD,
+		.mask = JZ_CLOCK_LCD_DIV_MASK,
+	},
+	{
+		.clk = {
+			.name = "i2s",
+			.parent = &jz_clk_ext.clk,
+			.gate_bit = JZ_CLOCK_GATE_I2S,
+			.ops = &jz_clk_i2s_ops,
+		},
+		.reg = JZ_REG_CLOCK_I2S,
+		.mask = JZ_CLOCK_I2S_DIV_MASK,
+	},
+	{
+		.clk = {
+			.name = "spi",
+			.parent = &jz_clk_ext.clk,
+			.gate_bit = JZ_CLOCK_GATE_SPI,
+			.ops = &jz_clk_spi_ops,
+		},
+		.reg = JZ_REG_CLOCK_SPI,
+		.mask = JZ_CLOCK_SPI_DIV_MASK,
+	},
+	{
+		.clk = {
+			.name = "mmc",
+			.parent = &jz_clk_pll_half,
+			.gate_bit = JZ_CLOCK_GATE_MMC,
+			.ops = &jz_clk_divided_ops,
+		},
+		.reg = JZ_REG_CLOCK_MMC,
+		.mask = JZ_CLOCK_MMC_DIV_MASK,
+	},
+	{
+		.clk = {
+			.name = "uhc",
+			.parent = &jz_clk_pll_half,
+			.gate_bit = JZ_CLOCK_GATE_UHC,
+			.ops = &jz_clk_divided_ops,
+		},
+		.reg = JZ_REG_CLOCK_UHC,
+		.mask = JZ_CLOCK_UHC_DIV_MASK,
+	},
+};
+
+static const struct clk_ops jz_clk_udc_ops = {
+	.set_parent = jz_clk_udc_set_parent,
+	.set_rate = jz_clk_udc_set_rate,
+	.get_rate = jz_clk_udc_get_rate,
+	.enable = jz_clk_udc_enable,
+	.disable = jz_clk_udc_disable,
+	.is_enabled = jz_clk_udc_is_enabled,
+};
+
+static const struct clk_ops jz_clk_simple_ops = {
+	.enable = jz_clk_enable_gating,
+	.disable = jz_clk_disable_gating,
+	.is_enabled = jz_clk_is_enabled_gating,
+};
+
+static struct clk jz4740_clock_simple_clks[] = {
+	{
+		.name = "udc",
+		.parent = &jz_clk_ext.clk,
+		.ops = &jz_clk_udc_ops,
+	},
+	{
+		.name = "uart0",
+		.parent = &jz_clk_ext.clk,
+		.gate_bit = JZ_CLOCK_GATE_UART0,
+		.ops = &jz_clk_simple_ops,
+	},
+	{
+		.name = "uart1",
+		.parent = &jz_clk_ext.clk,
+		.gate_bit = JZ_CLOCK_GATE_UART1,
+		.ops = &jz_clk_simple_ops,
+	},
+	{
+		.name = "dma",
+		.parent = &jz_clk_high_speed_peripheral.clk,
+		.gate_bit = JZ_CLOCK_GATE_UART0,
+		.ops = &jz_clk_simple_ops,
+	},
+	{
+		.name = "ipu",
+		.parent = &jz_clk_high_speed_peripheral.clk,
+		.gate_bit = JZ_CLOCK_GATE_IPU,
+		.ops = &jz_clk_simple_ops,
+	},
+	{
+		.name = "adc",
+		.parent = &jz_clk_ext.clk,
+		.gate_bit = JZ_CLOCK_GATE_ADC,
+		.ops = &jz_clk_simple_ops,
+	},
+	{
+		.name = "i2c",
+		.parent = &jz_clk_ext.clk,
+		.gate_bit = JZ_CLOCK_GATE_I2C,
+		.ops = &jz_clk_simple_ops,
+	},
+	{
+		.name = "aic",
+		.parent = &jz_clk_ext.clk,
+		.gate_bit = JZ_CLOCK_GATE_AIC,
+		.ops = &jz_clk_simple_ops,
+	},
+};
+
+static struct static_clk jz_clk_rtc = {
+	.clk = {
+		.name = "rtc",
+		.gate_bit = JZ_CLOCK_GATE_RTC,
+		.ops = &jz_clk_static_ops,
+	},
+	.rate = 32768,
+};
+
+int clk_enable(struct clk *clk)
+{
+	if (!clk->ops->enable)
+		return -EINVAL;
+
+	return clk->ops->enable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	if (clk->ops->disable)
+		clk->ops->disable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+int clk_is_enabled(struct clk *clk)
+{
+	if (clk->ops->is_enabled)
+		return clk->ops->is_enabled(clk);
+
+	return 1;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	if (clk->parent)
+		return clk_get_rate(clk->parent);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk->ops->set_rate)
+		return -EINVAL;
+	return clk->ops->set_rate(clk, rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret;
+
+	if (!clk->ops->set_parent)
+		return -EINVAL;
+
+	clk_disable(clk);
+	ret = clk->ops->set_parent(clk, parent);
+	clk_enable(clk);
+
+	jz4740_clock_debugfs_update_parent(clk);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get(struct device *dev, const char *name)
+{
+	struct clk *clk;
+
+	list_for_each_entry(clk, &jz_clocks, list) {
+		if (strcmp(clk->name, name) == 0)
+			return clk;
+	}
+	return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL_GPL(clk_put);
+
+
+static inline void clk_add(struct clk *clk)
+{
+	list_add_tail(&clk->list, &jz_clocks);
+
+	jz4740_clock_debugfs_add_clk(clk);
+}
+
+static void clk_register_clks(void)
+{
+	size_t i;
+
+	clk_add(&jz_clk_ext.clk);
+	clk_add(&jz_clk_pll);
+	clk_add(&jz_clk_pll_half);
+	clk_add(&jz_clk_cpu.clk);
+	clk_add(&jz_clk_high_speed_peripheral.clk);
+	clk_add(&jz_clk_low_speed_peripheral.clk);
+	clk_add(&jz_clk_ko);
+	clk_add(&jz_clk_ld);
+	clk_add(&jz_clk_rtc.clk);
+
+	for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
+		clk_add(&jz4740_clock_divided_clks[i].clk);
+
+	for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
+		clk_add(&jz4740_clock_simple_clks[i]);
+}
+
+void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
+{
+	switch (mode) {
+	case JZ4740_WAIT_MODE_IDLE:
+		jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
+		break;
+	case JZ4740_WAIT_MODE_SLEEP:
+		jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
+		break;
+	}
+}
+
+void jz4740_clock_udc_disable_auto_suspend(void)
+{
+	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
+
+void jz4740_clock_udc_enable_auto_suspend(void)
+{
+	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
+
+void jz4740_clock_suspend(void)
+{
+	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
+		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
+
+	jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
+}
+
+void jz4740_clock_resume(void)
+{
+	uint32_t pll;
+
+	jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
+
+	do {
+		pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
+	} while (!(pll & JZ_CLOCK_PLL_STABLE));
+
+	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
+		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
+}
+
+static int jz4740_clock_init(void)
+{
+	uint32_t val;
+
+	jz_clock_base = ioremap(CPHYSADDR(JZ4740_CPM_BASE_ADDR), 0x100);
+	if (!jz_clock_base)
+		return -EBUSY;
+
+	spin_lock_init(&jz_clock_lock);
+
+	jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
+	jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
+
+	val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
+
+	if (val & JZ_CLOCK_SPI_SRC_PLL)
+		jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
+
+	val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
+
+	if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
+		jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
+
+	if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
+		jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
+
+	jz4740_clock_debugfs_init();
+
+	clk_register_clks();
+
+	return 0;
+}
+subsys_initcall(jz4740_clock_init);
diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h
new file mode 100644
index 0000000..5d07499
--- /dev/null
+++ b/arch/mips/jz4740/clock.h
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 SoC clock support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __MIPS_JZ4740_CLOCK_H__
+#define __MIPS_JZ4740_CLOCK_H__
+
+#include <linux/list.h>
+
+struct jz4740_clock_board_data {
+	unsigned long ext_rate;
+	unsigned long rtc_rate;
+};
+
+extern struct jz4740_clock_board_data jz4740_clock_bdata;
+
+void jz4740_clock_suspend(void);
+void jz4740_clock_resume(void);
+
+struct clk;
+
+struct clk_ops {
+	unsigned long (*get_rate)(struct clk *clk);
+	unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
+	int (*set_rate)(struct clk *clk, unsigned long rate);
+	int (*enable)(struct clk *clk);
+	int (*disable)(struct clk *clk);
+	int (*is_enabled)(struct clk *clk);
+
+	int (*set_parent)(struct clk *clk, struct clk *parent);
+
+};
+
+struct clk {
+	const char *name;
+	struct clk *parent;
+
+	uint32_t gate_bit;
+
+	const struct clk_ops *ops;
+
+	struct list_head list;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_entry;
+	struct dentry *debugfs_parent_entry;
+#endif
+
+};
+
+#define JZ4740_CLK_NOT_GATED ((uint32_t)-1)
+
+int clk_is_enabled(struct clk *clk);
+
+#ifdef CONFIG_DEBUG_FS
+void jz4740_clock_debugfs_init(void);
+void jz4740_clock_debugfs_add_clk(struct clk *clk);
+void jz4740_clock_debugfs_update_parent(struct clk *clk);
+#else
+static inline void jz4740_clock_debugfs_init(void) {};
+static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {};
+static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {};
+#endif
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:52 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:06:58 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1081 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492620Ab0FBTEw (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:52 +0200
Received: (qmail 29726 invoked by uid 0); 2 Jun 2010 19:04:40 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:40 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 01/26] MIPS: Add base support for Ingenic JZ4740 System-on-a-Chip
Date:   Wed,  2 Jun 2010 21:02:52 +0200
Message-Id: <1275505397-16758-2-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27009
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1598
Content-Length: 6004
Lines: 196

This patch adds a new cpu type for the JZ4740 to the Linux MIPS architecture code.
It also adds the iomem addresses for the different components found on a JZ4740
SoC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/include/asm/bootinfo.h         |    6 ++++++
 arch/mips/include/asm/cpu.h              |    9 ++++++++-
 arch/mips/include/asm/mach-jz4740/base.h |   28 ++++++++++++++++++++++++++++
 arch/mips/include/asm/mach-jz4740/war.h  |   25 +++++++++++++++++++++++++
 arch/mips/kernel/cpu-probe.c             |   20 ++++++++++++++++++++
 arch/mips/mm/tlbex.c                     |    5 +++++
 6 files changed, 92 insertions(+), 1 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/base.h
 create mode 100644 arch/mips/include/asm/mach-jz4740/war.h

diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 09eee09..15a8ef0 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -71,6 +71,12 @@
 #define MACH_LEMOTE_LL2F       7
 #define MACH_LOONGSON_END      8
 
+/*
+ * Valid machtype for group INGENIC
+ */
+#define  MACH_INGENIC_JZ4730	0	/* JZ4730 SOC		*/
+#define  MACH_INGENIC_JZ4740	1	/* JZ4740 SOC		*/
+
 extern char *system_type;
 const char *get_system_type(void);
 
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index a5acda4..b201a8f 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -34,7 +34,7 @@
 #define PRID_COMP_LSI		0x080000
 #define PRID_COMP_LEXRA		0x0b0000
 #define PRID_COMP_CAVIUM	0x0d0000
-
+#define PRID_COMP_INGENIC	0xd00000
 
 /*
  * Assigned values for the product ID register.  In order to detect a
@@ -133,6 +133,12 @@
 #define PRID_IMP_CAVIUM_CN52XX 0x0700
 
 /*
+ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
+ */
+
+#define PRID_IMP_JZRISC        0x0200
+
+/*
  * Definitions for 7:0 on legacy processors
  */
 
@@ -219,6 +225,7 @@ enum cpu_type_enum {
 	CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
 	CPU_ALCHEMY, CPU_PR4450, CPU_BCM3302, CPU_BCM4710,
 	CPU_BCM6338, CPU_BCM6345, CPU_BCM6348, CPU_BCM6358,
+	CPU_JZRISC,
 
 	/*
 	 * MIPS64 class processors
diff --git a/arch/mips/include/asm/mach-jz4740/base.h b/arch/mips/include/asm/mach-jz4740/base.h
new file mode 100644
index 0000000..cba3aae
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/base.h
@@ -0,0 +1,28 @@
+#ifndef __ASM_MACH_JZ4740_BASE_H__
+#define __ASM_MACH_JZ4740_BASE_H__
+
+#define JZ4740_CPM_BASE_ADDR	0xb0000000
+#define JZ4740_INTC_BASE_ADDR	0xb0001000
+#define JZ4740_TCU_BASE_ADDR	0xb0002000
+#define JZ4740_WDT_BASE_ADDR	0xb0002000
+#define JZ4740_RTC_BASE_ADDR	0xb0003000
+#define JZ4740_GPIO_BASE_ADDR	0xb0010000
+#define JZ4740_AIC_BASE_ADDR	0xb0020000
+#define JZ4740_ICDC_BASE_ADDR	0xb0020000
+#define JZ4740_MSC_BASE_ADDR	0xb0021000
+#define JZ4740_UART0_BASE_ADDR	0xb0030000
+#define JZ4740_UART1_BASE_ADDR	0xb0031000
+#define JZ4740_I2C_BASE_ADDR	0xb0042000
+#define JZ4740_SSI_BASE_ADDR	0xb0043000
+#define JZ4740_SADC_BASE_ADDR	0xb0070000
+#define JZ4740_EMC_BASE_ADDR	0xb3010000
+#define JZ4740_DMAC_BASE_ADDR	0xb3020000
+#define JZ4740_UHC_BASE_ADDR	0xb3030000
+#define JZ4740_UDC_BASE_ADDR	0xb3040000
+#define JZ4740_LCD_BASE_ADDR	0xb3050000
+#define JZ4740_SLCD_BASE_ADDR	0xb3050000
+#define JZ4740_CIM_BASE_ADDR	0xb3060000
+#define JZ4740_IPU_BASE_ADDR	0xb3080000
+#define JZ4740_ETH_BASE_ADDR	0xb3100000
+
+#endif
diff --git a/arch/mips/include/asm/mach-jz4740/war.h b/arch/mips/include/asm/mach-jz4740/war.h
new file mode 100644
index 0000000..3a5bc17
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H
+#define __ASM_MIPS_MACH_JZ4740_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#define MIPS_CACHE_SYNC_WAR		0
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define RM9000_CDEX_SMP_WAR		0
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 3562b85..9b66331 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -187,6 +187,7 @@ void __init check_wait(void)
 	case CPU_BCM6358:
 	case CPU_CAVIUM_OCTEON:
 	case CPU_CAVIUM_OCTEON_PLUS:
+	case CPU_JZRISC:
 		cpu_wait = r4k_wait;
 		break;
 
@@ -956,6 +957,22 @@ platform:
 	}
 }
 
+static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
+{
+	decode_configs(c);
+	/* JZRISC does not implement the CP0 counter. */
+	c->options &= ~MIPS_CPU_COUNTER;
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_JZRISC:
+		c->cputype = CPU_JZRISC;
+		__cpu_name[cpu] = "Ingenic JZRISC";
+		break;
+	default:
+		panic("Unknown Ingenic Processor ID!");
+		break;
+	}
+}
+
 const char *__cpu_name[NR_CPUS];
 const char *__elf_platform;
 
@@ -994,6 +1011,9 @@ __cpuinit void cpu_probe(void)
 	case PRID_COMP_CAVIUM:
 		cpu_probe_cavium(c, cpu);
 		break;
+	case PRID_COMP_INGENIC:
+		cpu_probe_ingenic(c, cpu);
+		break;
 	}
 
 	BUG_ON(!__cpu_name[cpu]);
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 86f004d..4510e61 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -409,6 +409,11 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
 		tlbw(p);
 		break;
 
+	case CPU_JZRISC:
+		tlbw(p);
+		uasm_i_nop(p);
+		break;
+
 	default:
 		panic("No TLB refill handler yet (CPU type: %d)",
 		      current_cpu_data.cputype);
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:53 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:07:25 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1048 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492622Ab0FBTEx (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:53 +0200
Received: (qmail 29935 invoked by uid 0); 2 Jun 2010 19:04:43 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:42 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 06/26] MIPS: JZ4740: Add power-management and system reset support
Date:   Wed,  2 Jun 2010 21:02:57 +0200
Message-Id: <1275505397-16758-7-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27010
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1599
Content-Length: 4499
Lines: 177

This patch adds support for suspend/resume and poweroff/reboot on a JZ4740 SoC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/jz4740/pm.c    |   56 +++++++++++++++++++++++++++++++
 arch/mips/jz4740/reset.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++
 arch/mips/jz4740/reset.h |    7 ++++
 3 files changed, 144 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/pm.c
 create mode 100644 arch/mips/jz4740/reset.c
 create mode 100644 arch/mips/jz4740/reset.h

diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c
new file mode 100644
index 0000000..3b78ced
--- /dev/null
+++ b/arch/mips/jz4740/pm.c
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *		JZ4740 SoC power management support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/suspend.h>
+
+#include <asm/mach-jz4740/clock.h>
+
+#include "clock.h"
+#include "irq.h"
+
+static int jz4740_pm_enter(suspend_state_t state)
+{
+	jz4740_intc_suspend();
+	jz4740_clock_suspend();
+
+	jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP);
+
+	__asm__(".set\tmips3\n\t"
+		"wait\n\t"
+		".set\tmips0");
+
+	jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE);
+
+	jz4740_clock_resume();
+	jz4740_intc_resume();
+
+	return 0;
+}
+
+static struct platform_suspend_ops jz4740_pm_ops = {
+	.valid		= suspend_valid_only_mem,
+	.enter		= jz4740_pm_enter,
+};
+
+static int __init jz4740_pm_init(void)
+{
+	suspend_set_ops(&jz4740_pm_ops);
+	return 0;
+
+}
+late_initcall(jz4740_pm_init);
diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c
new file mode 100644
index 0000000..448a7da
--- /dev/null
+++ b/arch/mips/jz4740/reset.c
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+
+#include <linux/delay.h>
+
+#include <asm/reboot.h>
+
+#include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/timer.h>
+
+static void jz4740_halt(void)
+{
+	while (1) {
+		__asm__(".set push;\n"
+			".set mips3;\n"
+			"wait;\n"
+			".set pop;\n"
+		);
+	}
+}
+
+#define JZ_REG_WDT_DATA 0x00
+#define JZ_REG_WDT_COUNTER_ENABLE 0x04
+#define JZ_REG_WDT_COUNTER 0x08
+#define JZ_REG_WDT_CTRL 0x0c
+
+static void jz4740_restart(char *command)
+{
+	void __iomem *wdt_base = ioremap(CPHYSADDR(JZ4740_WDT_BASE_ADDR), 0x0f);
+
+	jz4740_timer_enable_watchdog();
+
+	writeb(0, wdt_base + JZ_REG_WDT_COUNTER_ENABLE);
+
+	writew(0, wdt_base + JZ_REG_WDT_COUNTER);
+	writew(0, wdt_base + JZ_REG_WDT_DATA);
+	writew(BIT(2), wdt_base + JZ_REG_WDT_CTRL);
+
+	writeb(1, wdt_base + JZ_REG_WDT_COUNTER_ENABLE);
+	jz4740_halt();
+}
+
+#define JZ_REG_RTC_CTRL		0x00
+#define JZ_REG_RTC_HIBERNATE	0x20
+
+#define JZ_RTC_CTRL_WRDY	BIT(7)
+
+static void jz4740_power_off(void)
+{
+	void __iomem *rtc_base = ioremap(CPHYSADDR(JZ4740_RTC_BASE_ADDR), 0x24);
+	uint32_t ctrl;
+
+	do {
+		ctrl = readl(rtc_base + JZ_REG_RTC_CTRL);
+	} while (!(ctrl & JZ_RTC_CTRL_WRDY));
+
+	writel(1, rtc_base + JZ_REG_RTC_HIBERNATE);
+	jz4740_halt();
+}
+
+void jz4740_reset_init(void)
+{
+	_machine_restart = jz4740_restart;
+	_machine_halt = jz4740_halt;
+	pm_power_off = jz4740_power_off;
+}
diff --git a/arch/mips/jz4740/reset.h b/arch/mips/jz4740/reset.h
new file mode 100644
index 0000000..c57a829
--- /dev/null
+++ b/arch/mips/jz4740/reset.h
@@ -0,0 +1,7 @@
+#ifndef __MIPS_JZ4740_RESET_H__
+#define __MIPS_JZ4740_RESET_H__
+
+extern void jz4740_reset_init(void);
+
+#endif
+
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:54 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:07:49 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1082 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492626Ab0FBTEy (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:54 +0200
Received: (qmail 29756 invoked by uid 0); 2 Jun 2010 19:04:41 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:40 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Thomas Gleixner <tglx@linutronix.de>
Subject: [RFC][PATCH 02/26] MIPS: jz4740: Add IRQ handler code
Date:   Wed,  2 Jun 2010 21:02:53 +0200
Message-Id: <1275505397-16758-3-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27011
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1600
Content-Length: 7945
Lines: 280

This patch adds support for IRQ handling on a JZ4740 SoC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 arch/mips/include/asm/mach-jz4740/irq.h |   55 ++++++++++
 arch/mips/jz4740/irq.c                  |  170 +++++++++++++++++++++++++++++++
 arch/mips/jz4740/irq.h                  |   21 ++++
 3 files changed, 246 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/irq.h
 create mode 100644 arch/mips/jz4740/irq.c
 create mode 100644 arch/mips/jz4740/irq.h

diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
new file mode 100644
index 0000000..5e27b78
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ7420/JZ4740 IRQ definitions
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __ASM_MACH_JZ4740_IRQ_H__
+#define __ASM_MACH_JZ4740_IRQ_H__
+
+#define MIPS_CPU_IRQ_BASE 0
+#define JZ4740_IRQ_BASE 8
+
+/* 1st-level interrupts */
+#define JZ4740_IRQ(x)	(JZ4740_IRQ_BASE + (x))
+#define JZ4740_IRQ_I2C	JZ4740_IRQ(1)
+#define JZ4740_IRQ_UHC	JZ4740_IRQ(3)
+#define JZ4740_IRQ_UART1	JZ4740_IRQ(8)
+#define JZ4740_IRQ_UART0	JZ4740_IRQ(9)
+#define JZ4740_IRQ_SADC	JZ4740_IRQ(12)
+#define JZ4740_IRQ_MSC	JZ4740_IRQ(14)
+#define JZ4740_IRQ_RTC	JZ4740_IRQ(15)
+#define JZ4740_IRQ_SSI	JZ4740_IRQ(16)
+#define JZ4740_IRQ_CIM	JZ4740_IRQ(17)
+#define JZ4740_IRQ_AIC	JZ4740_IRQ(18)
+#define JZ4740_IRQ_ETH	JZ4740_IRQ(19)
+#define JZ4740_IRQ_DMAC	JZ4740_IRQ(20)
+#define JZ4740_IRQ_TCU2	JZ4740_IRQ(21)
+#define JZ4740_IRQ_TCU1	JZ4740_IRQ(22)
+#define JZ4740_IRQ_TCU0	JZ4740_IRQ(23)
+#define JZ4740_IRQ_UDC	JZ4740_IRQ(24)
+#define JZ4740_IRQ_GPIO3	JZ4740_IRQ(25)
+#define JZ4740_IRQ_GPIO2	JZ4740_IRQ(26)
+#define JZ4740_IRQ_GPIO1	JZ4740_IRQ(27)
+#define JZ4740_IRQ_GPIO0	JZ4740_IRQ(28)
+#define JZ4740_IRQ_IPU	JZ4740_IRQ(29)
+#define JZ4740_IRQ_LCD	JZ4740_IRQ(30)
+
+/* 2nd-level interrupts */
+#define JZ4740_IRQ_DMA(x)	((x) + JZ4740_IRQ(32))
+
+#define JZ4740_IRQ_INTC_GPIO(x)	(JZ4740_IRQ_GPIO0 - (x))
+#define JZ4740_IRQ_GPIO(x)		(JZ4740_IRQ(48) + (x))
+
+#define NR_IRQS (JZ4740_IRQ_GPIO(127) + 1)
+
+#endif
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
new file mode 100644
index 0000000..46a03ee
--- /dev/null
+++ b/arch/mips/jz4740/irq.c
@@ -0,0 +1,170 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform IRQ support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/irq_cpu.h>
+
+#include <asm/mach-jz4740/base.h>
+
+static void __iomem *jz_intc_base;
+static uint32_t jz_intc_wakeup;
+static uint32_t jz_intc_saved;
+
+#define JZ_REG_INTC_STATUS	0x00
+#define JZ_REG_INTC_MASK	0x04
+#define JZ_REG_INTC_SET_MASK	0x08
+#define JZ_REG_INTC_CLEAR_MASK	0x0c
+#define JZ_REG_INTC_PENDING	0x10
+
+#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
+
+static void intc_irq_unmask(unsigned int irq)
+{
+	writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
+}
+
+static void intc_irq_mask(unsigned int irq)
+{
+	writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK);
+}
+
+static int intc_irq_set_wake(unsigned int irq, unsigned int on)
+{
+	if (on)
+		jz_intc_wakeup |= IRQ_BIT(irq);
+	else
+		jz_intc_wakeup &= ~IRQ_BIT(irq);
+
+	return 0;
+}
+
+static struct irq_chip intc_irq_type = {
+	.name =		"INTC",
+	.mask =		intc_irq_mask,
+	.mask_ack =	intc_irq_mask,
+	.unmask =	intc_irq_unmask,
+	.set_wake =	intc_irq_set_wake,
+};
+
+static irqreturn_t jz4740_cascade(int irq, void *data)
+{
+	uint32_t irq_reg;
+	int intc_irq;
+
+	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
+
+	intc_irq = ffs(irq_reg);
+	if (intc_irq)
+		generic_handle_irq(intc_irq - 1 + JZ4740_IRQ_BASE);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction jz4740_cascade_action = {
+	.handler = jz4740_cascade,
+	.name = "JZ4740 cascade interrupt",
+	.flags = IRQF_DISABLED,
+};
+
+void __init arch_init_irq(void)
+{
+	int i;
+	mips_cpu_irq_init();
+
+	jz_intc_base = ioremap(CPHYSADDR(JZ4740_INTC_BASE_ADDR), 0x14);
+
+	for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
+		intc_irq_mask(i);
+		set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+	}
+
+	setup_irq(2, &jz4740_cascade_action);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+	if (pending & STATUSF_IP2)
+		do_IRQ(2);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3);
+	else
+		spurious_interrupt();
+}
+
+void jz4740_intc_suspend(void)
+{
+	jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
+	writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
+	writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
+}
+
+void jz4740_intc_resume(void)
+{
+	writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
+	writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static inline void intc_seq_reg(struct seq_file *s, const char *name,
+	unsigned int reg)
+{
+	seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
+}
+
+static int intc_regs_show(struct seq_file *s, void *unused)
+{
+	intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
+	intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
+	intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
+
+	return 0;
+}
+
+static int intc_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, intc_regs_show, NULL);
+}
+
+static const struct file_operations intc_regs_operations = {
+	.open		= intc_regs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init intc_debugfs_init(void)
+{
+	(void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
+				NULL, NULL, &intc_regs_operations);
+	return 0;
+}
+subsys_initcall(intc_debugfs_init);
+
+#endif
diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h
new file mode 100644
index 0000000..dadbd5f
--- /dev/null
+++ b/arch/mips/jz4740/irq.h
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __MIPS_JZ4740_IRQ_H__
+#define __MIPS_JZ4740_IRQ_H__
+
+extern void jz4740_intc_suspend(void);
+extern void jz4740_intc_resume(void);
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:04:54 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:08:16 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1086 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492624Ab0FBTEy (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:04:54 +0200
Received: (qmail 29819 invoked by uid 0); 2 Jun 2010 19:04:42 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 28645
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:04:41 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 04/26] MIPS: JZ4740: Add timer support
Date:   Wed,  2 Jun 2010 21:02:55 +0200
Message-Id: <1275505397-16758-5-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27012
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1601
Content-Length: 7714
Lines: 241

This patch adds support for the timer/counter unit on a JZ4740 SoC.
This code is used as a common base for the JZ4740 clocksource/clockevent
implementation and PWM support.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/include/asm/mach-jz4740/timer.h |   22 +++++
 arch/mips/jz4740/timer.c                  |   48 ++++++++++
 arch/mips/jz4740/timer.h                  |  136 +++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/timer.h
 create mode 100644 arch/mips/jz4740/timer.c
 create mode 100644 arch/mips/jz4740/timer.h

diff --git a/arch/mips/include/asm/mach-jz4740/timer.h b/arch/mips/include/asm/mach-jz4740/timer.h
new file mode 100644
index 0000000..eadbf70
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/timer.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *		JZ4740 platform timer support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __ASM_MACH_JZ4740_TIMER
+#define __ASM_MACH_JZ4740_TIMER
+
+void jz4740_timer_enable_watchdog(void);
+void jz4740_timer_disable_watchdog(void);
+
+#endif
diff --git a/arch/mips/jz4740/timer.c b/arch/mips/jz4740/timer.c
new file mode 100644
index 0000000..6e09cae
--- /dev/null
+++ b/arch/mips/jz4740/timer.c
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform timer support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "timer.h"
+
+#include <asm/mach-jz4740/base.h>
+
+void __iomem *jz4740_timer_base;
+
+void jz4740_timer_enable_watchdog(void)
+{
+	writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
+}
+
+void jz4740_timer_disable_watchdog(void)
+{
+	writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
+}
+
+void __init jz4740_timer_init(void)
+{
+	jz4740_timer_base = ioremap(CPHYSADDR(JZ4740_TCU_BASE_ADDR), 0x100);
+
+	if (!jz4740_timer_base)
+		panic("Failed to ioremap timer registers");
+
+	/* Disable all timer clocks except for those used as system timers */
+	writel(0x000100fc, jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
+
+	/* Timer irqs are unmasked by default, mask them */
+	writel(0x00ff00ff, jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
+}
diff --git a/arch/mips/jz4740/timer.h b/arch/mips/jz4740/timer.h
new file mode 100644
index 0000000..1dacc3b
--- /dev/null
+++ b/arch/mips/jz4740/timer.h
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform timer support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __MIPS_JZ4740_TIMER_H__
+#define __MIPS_JZ4740_TIMER_H__
+
+#include <linux/module.h>
+#include <linux/io.h>
+
+#define JZ_REG_TIMER_STOP		0x1C
+#define JZ_REG_TIMER_STOP_SET		0x2C
+#define JZ_REG_TIMER_STOP_CLEAR		0x3C
+#define JZ_REG_TIMER_ENABLE		0x10
+#define JZ_REG_TIMER_ENABLE_SET		0x14
+#define JZ_REG_TIMER_ENABLE_CLEAR	0x18
+#define JZ_REG_TIMER_FLAG		0x20
+#define JZ_REG_TIMER_FLAG_SET		0x24
+#define JZ_REG_TIMER_FLAG_CLEAR		0x28
+#define JZ_REG_TIMER_MASK		0x30
+#define JZ_REG_TIMER_MASK_SET		0x34
+#define JZ_REG_TIMER_MASK_CLEAR		0x38
+
+#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x40)
+#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x44)
+#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x48)
+#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x4C)
+
+#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
+#define JZ_TIMER_IRQ_FULL(x) BIT(x)
+
+#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN	BIT(9)
+#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW		BIT(8)
+#define JZ_TIMER_CTRL_PWM_ENABLE		BIT(7)
+#define JZ_TIMER_CTRL_PRESCALE_MASK		0x1c
+#define JZ_TIMER_CTRL_PRESCALE_OFFSET		0x3
+#define JZ_TIMER_CTRL_PRESCALE_1		(0 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_4		(1 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_16		(2 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_64		(3 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_256		(4 << 3)
+#define JZ_TIMER_CTRL_PRESCALE_1024		(5 << 3)
+
+#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET)
+
+#define JZ_TIMER_CTRL_SRC_EXT		BIT(2)
+#define JZ_TIMER_CTRL_SRC_RTC		BIT(1)
+#define JZ_TIMER_CTRL_SRC_PCLK		BIT(0)
+
+extern void __iomem *jz4740_timer_base;
+void __init jz4740_timer_init(void);
+
+static inline void jz4740_timer_stop(unsigned int timer)
+{
+	writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
+}
+
+static inline void jz4740_timer_start(unsigned int timer)
+{
+	writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
+}
+
+static inline bool jz4740_timer_is_enabled(unsigned int timer)
+{
+	return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer);
+}
+
+static inline void jz4740_timer_enable(unsigned int timer)
+{
+	writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
+}
+
+static inline void jz4740_timer_disable(unsigned int timer)
+{
+	writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR);
+}
+
+
+static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period)
+{
+	writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer));
+}
+
+static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty)
+{
+	writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer));
+}
+
+static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count)
+{
+	writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
+}
+
+static inline uint16_t jz4740_timer_get_count(unsigned int timer)
+{
+	return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
+}
+
+static inline void jz4740_timer_ack_full(unsigned int timer)
+{
+	writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+}
+
+static inline void jz4740_timer_irq_full_enable(unsigned int timer)
+{
+	writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
+	writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
+}
+
+static inline void jz4740_timer_irq_full_disable(unsigned int timer)
+{
+	writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
+}
+
+static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl)
+{
+	writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
+}
+
+static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer)
+{
+	return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
+}
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:07 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:11:11 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40103 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1491976Ab0FBTLH (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:07 +0200
Received: (qmail 13310 invoked by uid 0); 2 Jun 2010 19:11:06 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:06 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 09/26] MIPS: JZ4740: Add DMA support.
Date:   Wed,  2 Jun 2010 21:10:25 +0200
Message-Id: <1275505832-17185-1-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27013
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1606
Content-Length: 11572
Lines: 404

This patch adds support for DMA transfers on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/include/asm/mach-jz4740/dma.h |   90 ++++++++++
 arch/mips/jz4740/dma.c                  |  289 +++++++++++++++++++++++++++++++
 2 files changed, 379 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/dma.h
 create mode 100644 arch/mips/jz4740/dma.c

diff --git a/arch/mips/include/asm/mach-jz4740/dma.h b/arch/mips/include/asm/mach-jz4740/dma.h
new file mode 100644
index 0000000..bb7fc1e
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/dma.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ7420/JZ4740 DMA definitions
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __ASM_MACH_JZ4740_DMA_H__
+#define __ASM_MACH_JZ4740_DMA_H__
+
+struct jz4740_dma_chan;
+
+enum jz4740_dma_request_type {
+	JZ4740_DMA_TYPE_AUTO_REQUEST =	 8,
+	JZ4740_DMA_TYPE_UART_TRANSMIT = 20,
+	JZ4740_DMA_TYPE_UART_RECEIVE =	21,
+	JZ4740_DMA_TYPE_SPI_TRANSMIT =	22,
+	JZ4740_DMA_TYPE_SPI_RECEIVE =	23,
+	JZ4740_DMA_TYPE_AIC_TRANSMIT =	24,
+	JZ4740_DMA_TYPE_AIC_RECEIVE =	25,
+	JZ4740_DMA_TYPE_MMC_TRANSMIT =	26,
+	JZ4740_DMA_TYPE_MMC_RECEIVE =	27,
+	JZ4740_DMA_TYPE_TCU =		28,
+	JZ4740_DMA_TYPE_SADC =		29,
+	JZ4740_DMA_TYPE_SLCD =		30,
+};
+
+enum jz4740_dma_width {
+	JZ4740_DMA_WIDTH_32BIT	= 0,
+	JZ4740_DMA_WIDTH_8BIT	= 1,
+	JZ4740_DMA_WIDTH_16BIT	= 2,
+};
+
+enum jz4740_dma_transfer_size {
+	JZ4740_DMA_TRANSFER_SIZE_4BYTE  = 0,
+	JZ4740_DMA_TRANSFER_SIZE_1BYTE  = 1,
+	JZ4740_DMA_TRANSFER_SIZE_2BYTE  = 2,
+	JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3,
+	JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4,
+};
+
+enum jz4740_dma_flags {
+	JZ4740_DMA_SRC_AUTOINC = 0x2,
+	JZ4740_DMA_DST_AUTOINC = 0x1,
+};
+
+enum jz4740_dma_mode {
+	JZ4740_DMA_MODE_SINGLE = 0,
+	JZ4740_DMA_MODE_BLOCK = 1,
+};
+
+struct jz4740_dma_config {
+	enum jz4740_dma_width src_width;
+	enum jz4740_dma_width dst_width;
+	enum jz4740_dma_transfer_size transfer_size;
+	enum jz4740_dma_request_type request_type;
+	enum jz4740_dma_flags flags;
+	enum jz4740_dma_mode mode;
+};
+
+typedef void (*jz4740_dma_complete_callback_t)(struct jz4740_dma_chan *, int, void *);
+
+struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name);
+void jz4740_dma_free(struct jz4740_dma_chan *dma);
+
+void jz4740_dma_configure(struct jz4740_dma_chan *dma,
+	const struct jz4740_dma_config *config);
+
+
+void jz4740_dma_enable(struct jz4740_dma_chan *dma);
+void jz4740_dma_disable(struct jz4740_dma_chan *dma);
+
+void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src);
+void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst);
+void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count);
+
+uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma);
+
+void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma,
+	jz4740_dma_complete_callback_t cb);
+
+#endif  /* __ASM_JZ4740_DMA_H__ */
diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c
new file mode 100644
index 0000000..4016e62
--- /dev/null
+++ b/arch/mips/jz4740/dma.c
@@ -0,0 +1,289 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 SoC DMA support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <linux/dma-mapping.h>
+#include <asm/mach-jz4740/dma.h>
+#include <asm/mach-jz4740/base.h>
+
+#define JZ_REG_DMA_SRC_ADDR(x)		(0x00 + (x) * 0x20)
+#define JZ_REG_DMA_DST_ADDR(x)		(0x04 + (x) * 0x20)
+#define JZ_REG_DMA_TRANSFER_COUNT(x)	(0x08 + (x) * 0x20)
+#define JZ_REG_DMA_REQ_TYPE(x)		(0x0C + (x) * 0x20)
+#define JZ_REG_DMA_STATUS_CTRL(x)	(0x10 + (x) * 0x20)
+#define JZ_REG_DMA_CMD(x)		(0x14 + (x) * 0x20)
+#define JZ_REG_DMA_DESC_ADDR(x)		(0x18 + (x) * 0x20)
+
+#define JZ_REG_DMA_CTRL			0x300
+#define JZ_REG_DMA_IRQ			0x304
+#define JZ_REG_DMA_DOORBELL		0x308
+#define JZ_REG_DMA_DOORBELL_SET		0x30C
+
+#define JZ_DMA_STATUS_CTRL_NO_DESC		BIT(31)
+#define JZ_DMA_STATUS_CTRL_DESC_INV		BIT(6)
+#define JZ_DMA_STATUS_CTRL_ADDR_ERR		BIT(4)
+#define JZ_DMA_STATUS_CTRL_TRANSFER_DONE	BIT(3)
+#define JZ_DMA_STATUS_CTRL_HALT			BIT(2)
+#define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE	BIT(1)
+#define JZ_DMA_STATUS_CTRL_ENABLE		BIT(0)
+
+#define JZ_DMA_CMD_SRC_INC			BIT(23)
+#define JZ_DMA_CMD_DST_INC			BIT(22)
+#define JZ_DMA_CMD_RDIL_MASK			(0xf << 16)
+#define JZ_DMA_CMD_SRC_WIDTH_MASK		(0x3 << 14)
+#define JZ_DMA_CMD_DST_WIDTH_MASK		(0x3 << 12)
+#define JZ_DMA_CMD_INTERVAL_LENGTH_MASK		(0x7 << 8)
+#define JZ_DMA_CMD_BLOCK_MODE			BIT(7)
+#define JZ_DMA_CMD_DESC_VALID			BIT(4)
+#define JZ_DMA_CMD_DESC_VALID_MODE		BIT(3)
+#define JZ_DMA_CMD_VALID_IRQ_ENABLE		BIT(2)
+#define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE		BIT(1)
+#define JZ_DMA_CMD_LINK_ENABLE			BIT(0)
+
+#define JZ_DMA_CMD_FLAGS_OFFSET 22
+#define JZ_DMA_CMD_RDIL_OFFSET 16
+#define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14
+#define JZ_DMA_CMD_DST_WIDTH_OFFSET 12
+#define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8
+#define JZ_DMA_CMD_MODE_OFFSET 7
+
+#define JZ_DMA_CTRL_PRIORITY_MASK	(0x3 << 8)
+#define JZ_DMA_CTRL_HALT		BIT(3)
+#define JZ_DMA_CTRL_ADDRESS_ERROR	BIT(2)
+#define JZ_DMA_CTRL_ENABLE		BIT(0)
+
+
+static void __iomem *jz4740_dma_base;
+static spinlock_t jz4740_dma_lock;
+
+static inline uint32_t jz4740_dma_read(size_t reg)
+{
+	return readl(jz4740_dma_base + reg);
+}
+
+static inline void jz4740_dma_write(size_t reg, uint32_t val)
+{
+	writel(val, jz4740_dma_base + reg);
+}
+
+static inline void jz4740_dma_write_mask(size_t reg, uint32_t val, uint32_t mask)
+{
+	uint32_t val2;
+	val2 = jz4740_dma_read(reg);
+	val2 &= ~mask;
+	val2 |= val;
+	jz4740_dma_write(reg, val2);
+}
+
+struct jz4740_dma_chan {
+	unsigned int id;
+	void *dev;
+	const char *name;
+
+	enum jz4740_dma_flags flags;
+	uint32_t transfer_shift;
+
+	jz4740_dma_complete_callback_t complete_cb;
+
+	unsigned used:1;
+};
+
+#define JZ4740_DMA_CHANNEL(_id) { .id = _id }
+
+struct jz4740_dma_chan jz4740_dma_channels[] = {
+	JZ4740_DMA_CHANNEL(0),
+	JZ4740_DMA_CHANNEL(1),
+	JZ4740_DMA_CHANNEL(2),
+	JZ4740_DMA_CHANNEL(3),
+	JZ4740_DMA_CHANNEL(4),
+	JZ4740_DMA_CHANNEL(5),
+};
+
+struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name)
+{
+	unsigned int i;
+	struct jz4740_dma_chan *dma = NULL;
+
+	spin_lock(&jz4740_dma_lock);
+
+	for (i = 0; i < ARRAY_SIZE(jz4740_dma_channels); ++i) {
+		if (!jz4740_dma_channels[i].used) {
+			dma = &jz4740_dma_channels[i];
+			dma->used = 1;
+			break;
+		}
+	}
+
+	spin_unlock(&jz4740_dma_lock);
+
+	if (!dma)
+		return NULL;
+
+	dma->dev = dev;
+	dma->name = name;
+
+	return dma;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_request);
+
+void jz4740_dma_configure(struct jz4740_dma_chan *dma,
+	const struct jz4740_dma_config *config)
+{
+	uint32_t cmd;
+
+	switch (config->transfer_size) {
+	case JZ4740_DMA_TRANSFER_SIZE_2BYTE:
+		dma->transfer_shift = 1;
+		break;
+	case JZ4740_DMA_TRANSFER_SIZE_4BYTE:
+		dma->transfer_shift = 2;
+		break;
+	case JZ4740_DMA_TRANSFER_SIZE_16BYTE:
+		dma->transfer_shift = 4;
+		break;
+	case JZ4740_DMA_TRANSFER_SIZE_32BYTE:
+		dma->transfer_shift = 5;
+		break;
+	default:
+		dma->transfer_shift = 0;
+		break;
+	}
+
+	cmd = config->flags << JZ_DMA_CMD_FLAGS_OFFSET;
+	cmd |= config->src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET;
+	cmd |= config->dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET;
+	cmd |= config->transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET;
+	cmd |= config->mode << JZ_DMA_CMD_MODE_OFFSET;
+	cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE;
+
+	jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd);
+	jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), 0);
+	jz4740_dma_write(JZ_REG_DMA_REQ_TYPE(dma->id), config->request_type);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_configure);
+
+void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src)
+{
+	jz4740_dma_write(JZ_REG_DMA_SRC_ADDR(dma->id), src);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_src_addr);
+
+void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst)
+{
+	jz4740_dma_write(JZ_REG_DMA_DST_ADDR(dma->id), dst);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_dst_addr);
+
+void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count)
+{
+	count >>= dma->transfer_shift;
+	jz4740_dma_write(JZ_REG_DMA_TRANSFER_COUNT(dma->id), count);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_transfer_count);
+
+void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma,
+	jz4740_dma_complete_callback_t cb)
+{
+	dma->complete_cb = cb;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_set_complete_cb);
+
+void jz4740_dma_free(struct jz4740_dma_chan *dma)
+{
+	dma->dev = NULL;
+	dma->complete_cb = NULL;
+	dma->used = 0;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_free);
+
+void jz4740_dma_enable(struct jz4740_dma_chan *dma)
+{
+	jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id),
+			JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE,
+			JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC |
+			JZ_DMA_STATUS_CTRL_ENABLE);
+
+	jz4740_dma_write_mask(JZ_REG_DMA_CTRL,
+			JZ_DMA_CTRL_ENABLE,
+			JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_enable);
+
+void jz4740_dma_disable(struct jz4740_dma_chan *dma)
+{
+	jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
+			JZ_DMA_STATUS_CTRL_ENABLE);
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_disable);
+
+uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma)
+{
+	uint32_t residue;
+	residue = jz4740_dma_read(JZ_REG_DMA_TRANSFER_COUNT(dma->id));
+	return residue << dma->transfer_shift;
+}
+EXPORT_SYMBOL_GPL(jz4740_dma_get_residue);
+
+static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma)
+{
+	uint32_t status;
+
+	status = jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
+
+	jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
+		JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE);
+
+	if (dma->complete_cb)
+		dma->complete_cb(dma, 0, dma->dev);
+}
+
+static irqreturn_t jz4740_dma_irq(int irq, void *dev_id)
+{
+	uint32_t irq_status;
+	unsigned int i;
+
+	irq_status = readl(jz4740_dma_base + JZ_REG_DMA_IRQ);
+
+	for (i = 0; i < 6; ++i) {
+		if (irq_status & (1 << i))
+			jz4740_dma_chan_irq(&jz4740_dma_channels[i]);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int jz4740_dma_init(void)
+{
+	unsigned int ret;
+
+	jz4740_dma_base = ioremap(CPHYSADDR(JZ4740_DMAC_BASE_ADDR), 0x400);
+
+	if (!jz4740_dma_base)
+		return -EBUSY;
+
+	spin_lock_init(&jz4740_dma_lock);
+
+	ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL);
+
+	if (ret)
+		printk(KERN_ERR "JZ4740 DMA: Failed to request irq: %d\n", ret);
+
+	return ret;
+}
+arch_initcall(jz4740_dma_init);
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:09 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:11:36 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40128 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492616Ab0FBTLJ (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:09 +0200
Received: (qmail 13363 invoked by uid 0); 2 Jun 2010 19:11:09 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:07 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 10/26] MIPS: JZ4740: Add PWM support
Date:   Wed,  2 Jun 2010 21:10:26 +0200
Message-Id: <1275505832-17185-2-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27014
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1607
Content-Length: 4179
Lines: 189

This patch adds support for the PWM part of the timer unit on a JZ4740 SoC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/jz4740/pwm.c |  172 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/pwm.c

diff --git a/arch/mips/jz4740/pwm.c b/arch/mips/jz4740/pwm.c
new file mode 100644
index 0000000..01aec10
--- /dev/null
+++ b/arch/mips/jz4740/pwm.c
@@ -0,0 +1,172 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform PWM support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/kernel.h>
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-jz4740/gpio.h>
+#include "timer.h"
+
+static struct clk *jz4740_pwm_clk;
+
+DEFINE_MUTEX(jz4740_pwm_mutex);
+
+struct pwm_device {
+	unsigned int id;
+	unsigned int gpio;
+	bool used;
+};
+
+static struct pwm_device jz4740_pwm_list[] = {
+	{ 2, JZ_GPIO_PWM2, false },
+	{ 3, JZ_GPIO_PWM3, false },
+	{ 4, JZ_GPIO_PWM4, false },
+	{ 5, JZ_GPIO_PWM5, false },
+	{ 6, JZ_GPIO_PWM6, false },
+	{ 7, JZ_GPIO_PWM7, false },
+};
+
+struct pwm_device *pwm_request(int id, const char *label)
+{
+	int ret = 0;
+	struct pwm_device *pwm;
+
+	if (!jz4740_pwm_clk) {
+		jz4740_pwm_clk = clk_get(NULL, "ext");
+
+		if (IS_ERR(jz4740_pwm_clk))
+			return ERR_PTR(PTR_ERR(jz4740_pwm_clk));
+	}
+
+	if (id < 2 || id > 7)
+		return ERR_PTR(-ENOENT);
+
+	mutex_lock(&jz4740_pwm_mutex);
+
+	pwm = &jz4740_pwm_list[id - 2];
+	if (pwm->used)
+		ret = -EBUSY;
+	else
+		pwm->used = true;
+
+	mutex_unlock(&jz4740_pwm_mutex);
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = gpio_request(pwm->gpio, label);
+
+	if (ret) {
+		printk(KERN_ERR "Failed to request pwm gpio: %d\n", ret);
+		pwm->used = false;
+		return ERR_PTR(ret);
+	}
+
+	jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_PWM);
+
+	jz4740_timer_start(id);
+
+	return pwm;
+}
+
+void pwm_free(struct pwm_device *pwm)
+{
+	pwm_disable(pwm);
+	jz4740_timer_set_ctrl(pwm->id, 0);
+
+	jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_NONE);
+	gpio_free(pwm->gpio);
+
+	jz4740_timer_stop(pwm->id);
+
+	pwm->used = false;
+
+}
+
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long long tmp;
+	unsigned long period, duty;
+	unsigned int prescaler = 0;
+	unsigned int id = pwm->id;
+	uint16_t ctrl;
+	bool is_enabled;
+
+	if (duty_ns < 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	tmp = (unsigned long long)clk_get_rate(jz4740_pwm_clk) * period_ns;
+
+	do_div(tmp, 1000000000);
+
+	period = tmp;
+
+	while (period > 0xffff && prescaler < 6) {
+		period >>= 2;
+		++prescaler;
+	}
+
+	if (prescaler == 6)
+		return -EINVAL;
+
+
+	tmp = (unsigned long long)period * duty_ns;
+	do_div(tmp, period_ns);
+	duty = period - tmp;
+
+	if (duty >= period)
+		duty = period - 1;
+
+	is_enabled = jz4740_timer_is_enabled(id);
+	if (is_enabled)
+		pwm_disable(pwm);
+
+	jz4740_timer_set_count(id, 0);
+	jz4740_timer_set_duty(id, duty);
+	jz4740_timer_set_period(id, period);
+
+	ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
+		JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
+
+	jz4740_timer_set_ctrl(id, ctrl);
+
+	if (is_enabled)
+		pwm_enable(pwm);
+
+	return 0;
+}
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id);
+	ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
+	jz4740_timer_set_ctrl(pwm->id, ctrl);
+	jz4740_timer_enable(pwm->id);
+
+	return 0;
+}
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id);
+	ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
+	jz4740_timer_disable(pwm->id);
+	jz4740_timer_set_ctrl(pwm->id, ctrl);
+}
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:10 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:12:01 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40136 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492617Ab0FBTLK (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:10 +0200
Received: (qmail 13392 invoked by uid 0); 2 Jun 2010 19:11:09 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:09 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 11/26] MIPS: JZ4740: Add serial support
Date:   Wed,  2 Jun 2010 21:10:27 +0200
Message-Id: <1275505832-17185-3-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27015
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1608
Content-Length: 2743
Lines: 85

This patch adds support for serials on a JZ4740 SoC.

The JZ4740 UART interface is almost 16550A compatible.
The UART module needs to be enabled by setting a bit in the FCR register and it
has support for receive timeout interrupts.
Instead of adding yet another machine specific quirk to the 8250 serial driver
we provide a serial_out implementation which sets the required additional flags.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/jz4740/serial.c |   33 +++++++++++++++++++++++++++++++++
 arch/mips/jz4740/serial.h |   21 +++++++++++++++++++++
 2 files changed, 54 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/serial.c
 create mode 100644 arch/mips/jz4740/serial.h

diff --git a/arch/mips/jz4740/serial.c b/arch/mips/jz4740/serial.c
new file mode 100644
index 0000000..d23de45
--- /dev/null
+++ b/arch/mips/jz4740/serial.c
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 serial support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+void jz4740_serial_out(struct uart_port *p, int offset, int value)
+{
+	switch (offset) {
+	case UART_FCR:
+		value |= 0x10; /* Enable uart module */
+		break;
+	case UART_IER:
+		value |= (value & 0x4) << 2;
+		break;
+	default:
+		break;
+	}
+	writeb(value, p->membase + (offset << p->regshift));
+}
diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h
new file mode 100644
index 0000000..247a7d8
--- /dev/null
+++ b/arch/mips/jz4740/serial.h
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 serial support
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __MIPS_JZ4740_SERIAL_H__
+
+void jz4740_serial_out(struct uart_port *p, int offset, int value);
+
+#endif
+
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:10 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:12:26 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40143 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492619Ab0FBTLK (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:10 +0200
Received: (qmail 13423 invoked by uid 0); 2 Jun 2010 19:11:10 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:10 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 12/26] MIPS: JZ4740: Add prom support
Date:   Wed,  2 Jun 2010 21:10:28 +0200
Message-Id: <1275505832-17185-4-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27016
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1613
Content-Length: 2095
Lines: 87

This patch adds support for initializing arcs_cmdline on JZ4740 based machines
and provides a prom_putchar implementation.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/jz4740/prom.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 69 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/prom.c

diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
new file mode 100644
index 0000000..6518aee
--- /dev/null
+++ b/arch/mips/jz4740/prom.c
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 SoC prom code
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <linux/serial_reg.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mach-jz4740/base.h>
+
+void jz4740_init_cmdline(int argc, char *argv[])
+{
+	unsigned int count = COMMAND_LINE_SIZE - 1;
+	int i;
+	char *dst = &(arcs_cmdline[0]);
+	char *src;
+
+	for (i = 1; i < argc && count; ++i) {
+		src = argv[i];
+		while (*src && count) {
+			*dst++ = *src++;
+			--count;
+		}
+		*dst++ = ' ';
+	}
+	if (i > 1)
+		--dst;
+
+	*dst = 0;
+}
+
+void __init prom_init(void)
+{
+	jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
+	mips_machtype = MACH_INGENIC_JZ4740;
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+#define UART_REG(_reg) ((void __iomem *)(JZ4740_UART0_BASE_ADDR + (_reg << 2)))
+
+void prom_putchar(char c)
+{
+	uint8_t lsr;
+
+	do {
+		lsr = readb(UART_REG(UART_LSR));
+	} while ((lsr & UART_LSR_TEMT) == 0);
+
+	writeb(c, UART_REG(UART_TX));
+}
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:16 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:12:52 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40178 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492625Ab0FBTLQ (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:16 +0200
Received: (qmail 13494 invoked by uid 0); 2 Jun 2010 19:11:13 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:13 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 14/26] MIPS: JZ4740: Add Kbuild files
Date:   Wed,  2 Jun 2010 21:10:30 +0200
Message-Id: <1275505832-17185-6-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27017
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1615
Content-Length: 2731
Lines: 102

This patch adds the Kbuild files for the JZ4740 architecture and adds JZ4740
support to the MIPS Kbuild files.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/Kconfig         |   13 +++++++++++++
 arch/mips/Makefile        |    6 ++++++
 arch/mips/jz4740/Kconfig  |    8 ++++++++
 arch/mips/jz4740/Makefile |   18 ++++++++++++++++++
 4 files changed, 45 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/Kconfig
 create mode 100644 arch/mips/jz4740/Makefile

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index cdaae94..4d44bad 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -162,6 +162,18 @@ config MACH_JAZZ
 	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and
 	 Olivetti M700-10 workstations.
 
+config MACH_JZ4740
+	bool "Ingenic JZ4740 based machines"
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select SYS_HAS_EARLY_PRINTK
+	select HAVE_PWM
+
 config LASAT
 	bool "LASAT Networks platforms"
 	select CEVT_R4K
@@ -686,6 +698,7 @@ endchoice
 source "arch/mips/alchemy/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
+source "arch/mips/jz4740/Kconfig"
 source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
 source "arch/mips/powertv/Kconfig"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 0b9c01a..a5cb578 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -659,6 +659,12 @@ else
 load-$(CONFIG_CPU_CAVIUM_OCTEON) 	+= 0xffffffff81100000
 endif
 
+# Ingenic JZ4740
+#
+core-$(CONFIG_MACH_JZ4740)	+= arch/mips/jz4740/
+cflags-$(CONFIG_MACH_JZ4740)	+= -I$(srctree)/arch/mips/include/asm/mach-jz4740
+load-$(CONFIG_MACH_JZ4740)	+= 0xffffffff80010000
+
 cflags-y			+= -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/
 
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
new file mode 100644
index 0000000..8a5e850
--- /dev/null
+++ b/arch/mips/jz4740/Kconfig
@@ -0,0 +1,8 @@
+choice
+	prompt "Machine type"
+	depends on MACH_JZ4740
+
+endchoice
+
+config HAVE_PWM
+	bool
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
new file mode 100644
index 0000000..a803ccb
--- /dev/null
+++ b/arch/mips/jz4740/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Ingenic JZ4740.
+#
+
+# Object file lists.
+
+obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
+	gpio.o clock.o platform.o timer.o pwm.o serial.o
+
+obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
+
+# board specific support
+
+# PM support
+
+obj-$(CONFIG_PM) += pm.o
+
+EXTRA_CFLAGS += -Werror -Wall
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:18 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:13:15 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40206 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492626Ab0FBTLS (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:18 +0200
Received: (qmail 13570 invoked by uid 0); 2 Jun 2010 19:11:18 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:13 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Alessandro Zummo <a.zummo@towertech.it>,
        Paul Gortmaker <p_gortmaker@yahoo.com>,
        rtc-linux@googlegroups.com
Subject: [RFC][PATCH 15/26] RTC: Add JZ4740 RTC driver
Date:   Wed,  2 Jun 2010 21:10:31 +0200
Message-Id: <1275505832-17185-7-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27018
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1616
Content-Length: 10285
Lines: 398

This patch adds support for the RTC unit on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Paul Gortmaker <p_gortmaker@yahoo.com>
Cc: rtc-linux@googlegroups.com
---
 drivers/rtc/Kconfig      |   11 ++
 drivers/rtc/Makefile     |    1 +
 drivers/rtc/rtc-jz4740.c |  344 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 356 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-jz4740.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 10ba12c..d0ed7e6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -905,4 +905,15 @@ config RTC_DRV_MPC5121
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-mpc5121.
 
+config RTC_DRV_JZ4740
+	tristate "Ingenic JZ4740 SoC"
+	depends on RTC_CLASS
+	depends on MACH_JZ4740
+	help
+	  If you say yes here you get support for the Ingenic JZ4740 SoC RTC
+	  controller.
+
+	  This driver can also be buillt as a module. If so, the module
+	  will be called rtc-jz4740.
+
 endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 5adbba7..fedf9bb 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
+obj-$(CONFIG_RTC_DRV_JZ4740)	+= rtc-jz4740.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
 obj-$(CONFIG_RTC_DRV_M48T35)	+= rtc-m48t35.o
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
new file mode 100644
index 0000000..41ab78f
--- /dev/null
+++ b/drivers/rtc/rtc-jz4740.c
@@ -0,0 +1,344 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *		JZ4740 SoC RTC driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define JZ_REG_RTC_CTRL		0x00
+#define JZ_REG_RTC_SEC		0x04
+#define JZ_REG_RTC_SEC_ALARM	0x08
+#define JZ_REG_RTC_REGULATOR	0x0C
+#define JZ_REG_RTC_HIBERNATE	0x20
+#define JZ_REG_RTC_SCRATCHPAD	0x34
+
+#define JZ_RTC_CTRL_WRDY	BIT(7)
+#define JZ_RTC_CTRL_1HZ		BIT(6)
+#define JZ_RTC_CTRL_1HZ_IRQ	BIT(5)
+#define JZ_RTC_CTRL_AF		BIT(4)
+#define JZ_RTC_CTRL_AF_IRQ	BIT(3)
+#define JZ_RTC_CTRL_AE		BIT(2)
+#define JZ_RTC_CTRL_ENABLE	BIT(0)
+
+struct jz4740_rtc {
+	struct resource *mem;
+	void __iomem *base;
+
+	struct rtc_device *rtc;
+
+	unsigned int irq;
+
+	spinlock_t lock;
+};
+
+static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
+{
+	return readl(rtc->base + reg);
+}
+
+static inline void jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
+{
+	uint32_t ctrl;
+	do {
+		ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
+	} while (!(ctrl & JZ_RTC_CTRL_WRDY));
+}
+
+
+static inline void jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
+					uint32_t val)
+{
+	jz4740_rtc_wait_write_ready(rtc);
+	writel(val, rtc->base + reg);
+}
+
+static void jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask,
+					uint32_t val)
+{
+	unsigned long flags;
+	uint32_t ctrl;
+
+	spin_lock_irqsave(&rtc->lock, flags);
+
+	ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
+
+	/* Don't clear interrupt flags by accident */
+	ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF;
+
+	ctrl &= ~mask;
+	ctrl |= val;
+
+	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl);
+
+	spin_unlock_irqrestore(&rtc->lock, flags);
+}
+
+static inline struct jz4740_rtc *dev_to_rtc(struct device *dev)
+{
+	return dev_get_drvdata(dev);
+}
+
+static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
+{
+	struct jz4740_rtc *rtc = dev_to_rtc(dev);
+	uint32_t secs, secs2;
+
+	secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
+	secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
+
+	while (secs != secs2) {
+		secs = secs2;
+		secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
+	}
+
+	rtc_time_to_tm(secs, time);
+
+	return rtc_valid_tm(time);
+}
+
+static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+	struct jz4740_rtc *rtc = dev_to_rtc(dev);
+
+	if ((uint32_t)secs != secs)
+		return -EINVAL;
+
+	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs);
+
+	return 0;
+}
+
+static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct jz4740_rtc *rtc = dev_to_rtc(dev);
+	uint32_t secs, secs2;
+	uint32_t ctrl;
+
+	secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
+	secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
+
+	while (secs != secs2) {
+		secs = secs2;
+		secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
+	}
+
+	ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
+
+	alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE);
+	alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF);
+
+	rtc_time_to_tm(secs, &alrm->time);
+
+	return rtc_valid_tm(&alrm->time);
+}
+
+static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct jz4740_rtc *rtc = dev_to_rtc(dev);
+	unsigned long secs;
+
+	rtc_tm_to_time(&alrm->time, &secs);
+
+	if ((uint32_t)secs != secs)
+		return -EINVAL;
+
+	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, (uint32_t)secs);
+	jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE,
+					alrm->enabled ? JZ_RTC_CTRL_AE : 0);
+
+	return 0;
+}
+
+static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable)
+{
+	struct jz4740_rtc *rtc = dev_to_rtc(dev);
+	jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ,
+					enable ? JZ_RTC_CTRL_1HZ_IRQ : 0);
+	return 0;
+}
+
+
+static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+	struct jz4740_rtc *rtc = dev_to_rtc(dev);
+	jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ,
+					enable ? JZ_RTC_CTRL_AF_IRQ : 0);
+	return 0;
+}
+
+static struct rtc_class_ops jz4740_rtc_ops = {
+	.read_time	= jz4740_rtc_read_time,
+	.set_mmss	= jz4740_rtc_set_mmss,
+	.read_alarm	= jz4740_rtc_read_alarm,
+	.set_alarm	= jz4740_rtc_set_alarm,
+	.update_irq_enable = jz4740_rtc_update_irq_enable,
+	.alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t jz4740_rtc_irq(int irq, void *data)
+{
+	struct jz4740_rtc *rtc = data;
+	uint32_t ctrl;
+	unsigned long events = 0;
+	ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
+
+	if (ctrl & JZ_RTC_CTRL_1HZ)
+		events |= (RTC_UF | RTC_IRQF);
+
+	if (ctrl & JZ_RTC_CTRL_AF)
+		events |= (RTC_AF | RTC_IRQF);
+
+	rtc_update_irq(rtc->rtc, 1, events);
+
+	jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, 0);
+
+	return IRQ_HANDLED;
+}
+
+void jz4740_rtc_poweroff(struct device *dev)
+{
+	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
+	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1);
+}
+EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff);
+
+static int __devinit jz4740_rtc_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jz4740_rtc *rtc;
+	uint32_t scratchpad;
+
+	rtc = kmalloc(sizeof(*rtc), GFP_KERNEL);
+
+	rtc->irq = platform_get_irq(pdev, 0);
+
+	if (rtc->irq < 0) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get platform irq\n");
+		goto err_free;
+	}
+
+	rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!rtc->mem) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
+		goto err_free;
+	}
+
+	rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem),
+					pdev->name);
+
+	if (!rtc->mem) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+		goto err_free;
+	}
+
+	rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem));
+
+	if (!rtc->base) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
+		goto err_release_mem_region;
+	}
+
+	spin_lock_init(&rtc->lock);
+
+	platform_set_drvdata(pdev, rtc);
+
+	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops,
+					THIS_MODULE);
+
+	if (IS_ERR(rtc->rtc)) {
+		ret = PTR_ERR(rtc->rtc);
+		dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
+		goto err_iounmap;
+	}
+
+	ret = request_irq(rtc->irq, jz4740_rtc_irq, 0,
+				pdev->name, rtc);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
+		goto err_unregister_rtc;
+	}
+
+	scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
+	if (scratchpad != 0x12345678) {
+		jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
+		jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
+	}
+
+	return 0;
+
+err_unregister_rtc:
+	rtc_device_unregister(rtc->rtc);
+err_iounmap:
+	platform_set_drvdata(pdev, NULL);
+	iounmap(rtc->base);
+err_release_mem_region:
+	release_mem_region(rtc->mem->start, resource_size(rtc->mem));
+err_free:
+	kfree(rtc);
+
+	return ret;
+}
+
+static int __devexit jz4740_rtc_remove(struct platform_device *pdev)
+{
+	struct jz4740_rtc *rtc = platform_get_drvdata(pdev);
+
+	free_irq(rtc->irq, rtc);
+
+	rtc_device_unregister(rtc->rtc);
+
+	iounmap(rtc->base);
+	release_mem_region(rtc->mem->start, resource_size(rtc->mem));
+
+	kfree(rtc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+struct platform_driver jz4740_rtc_driver = {
+	.probe = jz4740_rtc_probe,
+	.remove = __devexit_p(jz4740_rtc_remove),
+	.driver = {
+		.name = "jz4740-rtc",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz4740_rtc_init(void)
+{
+	return platform_driver_register(&jz4740_rtc_driver);
+}
+module_init(jz4740_rtc_init);
+
+static void __exit jz4740_rtc_exit(void)
+{
+	platform_driver_unregister(&jz4740_rtc_driver);
+}
+module_exit(jz4740_rtc_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n");
+MODULE_ALIAS("platform:jz4740-rtc");
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:22 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:13:46 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40214 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492621Ab0FBTLW (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:22 +0200
Received: (qmail 13610 invoked by uid 0); 2 Jun 2010 19:11:18 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:18 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Andrew Morton <akpm@linux-foundation.org>,
        linux-fbdev@vger.kernel.org
Subject: [RFC][PATCH 16/26] fbdev: Add JZ4740 framebuffer driver
Date:   Wed,  2 Jun 2010 21:10:32 +0200
Message-Id: <1275505832-17185-8-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27019
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1618
Content-Length: 23467
Lines: 937

This patch adds support for the LCD controller on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-fbdev@vger.kernel.org
---
 drivers/video/Kconfig     |    9 +
 drivers/video/Makefile    |    1 +
 drivers/video/jz4740_fb.c |  818 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/jz4740_fb.h |   58 ++++
 4 files changed, 886 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/jz4740_fb.c
 create mode 100644 include/linux/jz4740_fb.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 1e6fec4..f3b3893 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2229,6 +2229,15 @@ config FB_BROADSHEET
 	  and could also have been called by other names when coupled with
 	  a bridge adapter.
 
+config FB_JZ4740
+	tristate "JZ4740 LCD framebuffer support"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	help
+	  Framebuffer support for the JZ4740 SoC.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ddc2af2..f56a9ca 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -131,6 +131,7 @@ obj-$(CONFIG_FB_CARMINE)          += carminefb.o
 obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
 obj-$(CONFIG_FB_MSM)              += msm/
 obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
+obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
new file mode 100644
index 0000000..81f280d
--- /dev/null
+++ b/drivers/video/jz4740_fb.c
@@ -0,0 +1,818 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *		JZ4740 SoC LCD framebuffer driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <linux/console.h>
+#include <linux/fb.h>
+
+#include <linux/dma-mapping.h>
+
+#include <linux/jz4740_fb.h>
+#include <asm/mach-jz4740/gpio.h>
+
+#define JZ_REG_LCD_CFG		0x00
+#define JZ_REG_LCD_VSYNC	0x04
+#define JZ_REG_LCD_HSYNC	0x08
+#define JZ_REG_LCD_VAT		0x0C
+#define JZ_REG_LCD_DAH		0x10
+#define JZ_REG_LCD_DAV		0x14
+#define JZ_REG_LCD_PS		0x18
+#define JZ_REG_LCD_CLS		0x1C
+#define JZ_REG_LCD_SPL		0x20
+#define JZ_REG_LCD_REV		0x24
+#define JZ_REG_LCD_CTRL		0x30
+#define JZ_REG_LCD_STATE	0x34
+#define JZ_REG_LCD_IID		0x38
+#define JZ_REG_LCD_DA0		0x40
+#define JZ_REG_LCD_SA0		0x44
+#define JZ_REG_LCD_FID0		0x48
+#define JZ_REG_LCD_CMD0		0x4C
+#define JZ_REG_LCD_DA1		0x50
+#define JZ_REG_LCD_SA1		0x54
+#define JZ_REG_LCD_FID1		0x58
+#define JZ_REG_LCD_CMD1		0x5C
+
+#define JZ_LCD_CFG_SLCD			BIT(31)
+#define JZ_LCD_CFG_PS_DISABLE		BIT(23)
+#define JZ_LCD_CFG_CLS_DISABLE		BIT(22)
+#define JZ_LCD_CFG_SPL_DISABLE		BIT(21)
+#define JZ_LCD_CFG_REV_DISABLE		BIT(20)
+#define JZ_LCD_CFG_HSYNCM		BIT(19)
+#define JZ_LCD_CFG_PCLKM		BIT(18)
+#define JZ_LCD_CFG_INV			BIT(17)
+#define JZ_LCD_CFG_SYNC_DIR		BIT(16)
+#define JZ_LCD_CFG_PS_POLARITY		BIT(15)
+#define JZ_LCD_CFG_CLS_POLARITY		BIT(14)
+#define JZ_LCD_CFG_SPL_POLARITY		BIT(13)
+#define JZ_LCD_CFG_REV_POLARITY		BIT(12)
+#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW	BIT(11)
+#define JZ_LCD_CFG_PCLK_FALLING_EDGE	BIT(10)
+#define JZ_LCD_CFG_DE_ACTIVE_LOW	BIT(9)
+#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW	BIT(8)
+#define JZ_LCD_CFG_18_BIT		BIT(7)
+#define JZ_LCD_CFG_PDW			(BIT(5) | BIT(4))
+#define JZ_LCD_CFG_MODE_MASK 0xf
+
+#define JZ_LCD_CTRL_BURST_4		(0x0 << 28)
+#define JZ_LCD_CTRL_BURST_8		(0x1 << 28)
+#define JZ_LCD_CTRL_BURST_16		(0x2 << 28)
+#define JZ_LCD_CTRL_RGB555		BIT(27)
+#define JZ_LCD_CTRL_OFUP		BIT(26)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_16	(0x0 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_4	(0x1 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_2	(0x2 << 24)
+#define JZ_LCD_CTRL_PDD_MASK		(0xff << 16)
+#define JZ_LCD_CTRL_EOF_IRQ		BIT(13)
+#define JZ_LCD_CTRL_SOF_IRQ		BIT(12)
+#define JZ_LCD_CTRL_OFU_IRQ		BIT(11)
+#define JZ_LCD_CTRL_IFU0_IRQ		BIT(10)
+#define JZ_LCD_CTRL_IFU1_IRQ		BIT(9)
+#define JZ_LCD_CTRL_DD_IRQ		BIT(8)
+#define JZ_LCD_CTRL_QDD_IRQ		BIT(7)
+#define JZ_LCD_CTRL_REVERSE_ENDIAN	BIT(6)
+#define JZ_LCD_CTRL_LSB_FISRT		BIT(5)
+#define JZ_LCD_CTRL_DISABLE		BIT(4)
+#define JZ_LCD_CTRL_ENABLE		BIT(3)
+#define JZ_LCD_CTRL_BPP_1		0x0
+#define JZ_LCD_CTRL_BPP_2		0x1
+#define JZ_LCD_CTRL_BPP_4		0x2
+#define JZ_LCD_CTRL_BPP_8		0x3
+#define JZ_LCD_CTRL_BPP_15_16		0x4
+#define JZ_LCD_CTRL_BPP_18_24		0x5
+
+#define JZ_LCD_CMD_SOF_IRQ BIT(15)
+#define JZ_LCD_CMD_EOF_IRQ BIT(16)
+#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
+
+#define JZ_LCD_SYNC_MASK 0x3ff
+
+#define JZ_LCD_STATE_DISABLED BIT(0)
+
+struct jzfb_framedesc {
+	uint32_t next;
+	uint32_t addr;
+	uint32_t id;
+	uint32_t cmd;
+} __attribute__((packed));
+
+struct jzfb {
+	struct fb_info *fb;
+	struct platform_device *pdev;
+	void __iomem *base;
+	struct resource *mem;
+	struct jz4740_fb_platform_data *pdata;
+
+	size_t vidmem_size;
+	void *vidmem;
+	dma_addr_t vidmem_phys;
+	struct jzfb_framedesc *framedesc;
+	dma_addr_t framedesc_phys;
+
+	struct clk *ldclk;
+	struct clk *lpclk;
+
+	unsigned is_enabled:1;
+	struct mutex lock;
+
+	uint32_t pseudo_palette[16];
+};
+
+static struct fb_fix_screeninfo jzfb_fix __devinitdata = {
+	.id		= "JZ4740 FB",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
+	JZ_GPIO_BULK_PIN(LCD_PCLK),
+	JZ_GPIO_BULK_PIN(LCD_HSYNC),
+	JZ_GPIO_BULK_PIN(LCD_VSYNC),
+	JZ_GPIO_BULK_PIN(LCD_DE),
+	JZ_GPIO_BULK_PIN(LCD_PS),
+	JZ_GPIO_BULK_PIN(LCD_REV),
+};
+
+static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
+	JZ_GPIO_BULK_PIN(LCD_DATA0),
+	JZ_GPIO_BULK_PIN(LCD_DATA1),
+	JZ_GPIO_BULK_PIN(LCD_DATA2),
+	JZ_GPIO_BULK_PIN(LCD_DATA3),
+	JZ_GPIO_BULK_PIN(LCD_DATA4),
+	JZ_GPIO_BULK_PIN(LCD_DATA5),
+	JZ_GPIO_BULK_PIN(LCD_DATA6),
+	JZ_GPIO_BULK_PIN(LCD_DATA7),
+	JZ_GPIO_BULK_PIN(LCD_DATA8),
+	JZ_GPIO_BULK_PIN(LCD_DATA9),
+	JZ_GPIO_BULK_PIN(LCD_DATA10),
+	JZ_GPIO_BULK_PIN(LCD_DATA11),
+	JZ_GPIO_BULK_PIN(LCD_DATA12),
+	JZ_GPIO_BULK_PIN(LCD_DATA13),
+	JZ_GPIO_BULK_PIN(LCD_DATA14),
+	JZ_GPIO_BULK_PIN(LCD_DATA15),
+	JZ_GPIO_BULK_PIN(LCD_DATA16),
+	JZ_GPIO_BULK_PIN(LCD_DATA17),
+};
+
+static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
+{
+	unsigned int num;
+
+	switch (jzfb->pdata->lcd_type) {
+	case JZ_LCD_TYPE_GENERIC_16_BIT:
+		num = 4;
+		break;
+	case JZ_LCD_TYPE_GENERIC_18_BIT:
+		num = 4;
+		break;
+	case JZ_LCD_TYPE_8BIT_SERIAL:
+		num = 3;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+	return num;
+}
+
+static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
+{
+	unsigned int num;
+
+	switch (jzfb->pdata->lcd_type) {
+	case JZ_LCD_TYPE_GENERIC_16_BIT:
+		num = 16;
+		break;
+	case JZ_LCD_TYPE_GENERIC_18_BIT:
+		num = 18;
+		break;
+	case JZ_LCD_TYPE_8BIT_SERIAL:
+		num = 8;
+		break;
+	default:
+		num = 0;
+		break;
+	}
+	return num;
+}
+
+/* Based on CNVT_TOHW macro from skeletonfb.c */
+static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
+	struct fb_bitfield *bf)
+{
+	return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
+}
+
+static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			unsigned blue, unsigned transp, struct fb_info *fb)
+{
+	uint32_t color;
+
+	if (regno >= 16)
+		return -EINVAL;
+
+	color = jzfb_convert_color_to_hw(red, fb->var.red.length);
+	color |= jzfb_convert_color_to_hw(green, fb->var.green.length);
+	color |= jzfb_convert_color_to_hw(blue, fb->var.blue.length);
+	color |= jzfb_convert_color_to_hw(transp, fb->var.transp.length);
+
+	((uint32_t *)(fb->pseudo_palette))[regno] = color;
+
+	return 0;
+}
+
+static int jzfb_get_controller_bpp(struct jzfb *jzfb)
+{
+	switch (jzfb->pdata->bpp) {
+	case 18:
+	case 24:
+		return 32;
+	case 15:
+		return 16;
+	default:
+		return jzfb->pdata->bpp;
+	}
+}
+
+static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
+	struct fb_var_screeninfo *var)
+{
+	size_t i;
+	struct fb_videomode *mode = jzfb->pdata->modes;
+
+	for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
+		if (mode->xres == var->xres && mode->yres == var->yres)
+			return mode;
+	}
+
+	return NULL;
+}
+
+static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
+{
+	struct jzfb *jzfb = fb->par;
+	struct fb_videomode *mode;
+
+	if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
+		var->bits_per_pixel != jzfb->pdata->bpp)
+		return -EINVAL;
+
+	mode = jzfb_get_mode(jzfb, var);
+	if (mode == NULL)
+		return -EINVAL;
+
+	fb_videomode_to_var(var, mode);
+
+	switch (jzfb->pdata->bpp) {
+	case 8:
+		break;
+	case 15:
+		var->red.offset = 10;
+		var->red.length = 5;
+		var->green.offset = 6;
+		var->green.length = 5;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	case 18:
+		var->red.offset = 16;
+		var->red.length = 6;
+		var->green.offset = 8;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 6;
+		var->bits_per_pixel = 32;
+		break;
+	case 32:
+	case 24:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->bits_per_pixel = 32;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int jzfb_set_par(struct fb_info *info)
+{
+	struct jzfb *jzfb = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_videomode *mode;
+	uint16_t hds, vds;
+	uint16_t hde, vde;
+	uint16_t ht, vt;
+	uint32_t ctrl;
+	uint32_t cfg;
+	unsigned long rate;
+
+	mode = jzfb_get_mode(jzfb, var);
+	if (mode == NULL)
+		return -EINVAL;
+
+	info->mode = mode;
+
+	hds = mode->hsync_len + mode->left_margin;
+	hde = hds + mode->xres;
+	ht = hde + mode->right_margin;
+
+	vds = mode->vsync_len + mode->upper_margin;
+	vde = vds + mode->yres;
+	vt = vde + mode->lower_margin;
+
+	ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
+
+	switch (jzfb->pdata->bpp) {
+	case 1:
+		ctrl |= JZ_LCD_CTRL_BPP_1;
+		break;
+	case 2:
+		ctrl |= JZ_LCD_CTRL_BPP_2;
+		break;
+	case 4:
+		ctrl |= JZ_LCD_CTRL_BPP_4;
+		break;
+	case 8:
+		ctrl |= JZ_LCD_CTRL_BPP_8;
+	break;
+	case 15:
+		ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
+	case 16:
+		ctrl |= JZ_LCD_CTRL_BPP_15_16;
+		break;
+	case 18:
+	case 24:
+	case 32:
+		ctrl |= JZ_LCD_CTRL_BPP_18_24;
+		break;
+	default:
+		break;
+	}
+
+	cfg = 0;
+	cfg |= JZ_LCD_CFG_PS_DISABLE;
+	cfg |= JZ_LCD_CFG_CLS_DISABLE;
+	cfg |= JZ_LCD_CFG_SPL_DISABLE;
+	cfg |= JZ_LCD_CFG_REV_DISABLE;
+
+	if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
+		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
+
+	if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
+		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
+
+	if (jzfb->pdata->pixclk_falling_edge)
+		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
+
+	if (jzfb->pdata->date_enable_active_low)
+		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
+
+	if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
+		cfg |= JZ_LCD_CFG_18_BIT;
+
+	cfg |= jzfb->pdata->lcd_type & 0xf;
+
+	if (mode->pixclock) {
+		rate = PICOS2KHZ(mode->pixclock) * 1000;
+		mode->refresh = rate / vt / ht;
+	} else {
+		if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
+			rate = mode->refresh * (vt + 2 * mode->xres) * ht;
+		else
+			rate = mode->refresh * vt * ht;
+
+		mode->pixclock = KHZ2PICOS(rate / 1000);
+	}
+
+	mutex_lock(&jzfb->lock);
+	if (!jzfb->is_enabled)
+		clk_enable(jzfb->ldclk);
+	else
+		ctrl |= JZ_LCD_CTRL_ENABLE;
+
+	writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
+	writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
+
+	writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
+
+	writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
+	writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
+
+	writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
+
+	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
+
+	if (!jzfb->is_enabled)
+		clk_disable(jzfb->ldclk);
+	mutex_unlock(&jzfb->lock);
+
+	clk_set_rate(jzfb->lpclk, rate);
+	clk_set_rate(jzfb->ldclk, rate * 3);
+
+	return 0;
+}
+
+static void jzfb_enable(struct jzfb *jzfb)
+{
+	uint32_t ctrl;
+
+	clk_enable(jzfb->ldclk);
+
+	jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	writel(0, jzfb->base + JZ_REG_LCD_STATE);
+
+	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
+
+	ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
+	ctrl |= JZ_LCD_CTRL_ENABLE;
+	ctrl &= ~JZ_LCD_CTRL_DISABLE;
+	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
+}
+
+static void jzfb_disable(struct jzfb *jzfb)
+{
+	uint32_t ctrl;
+
+	ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
+	ctrl |= JZ_LCD_CTRL_DISABLE;
+	writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
+	do {
+		ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
+	} while (!(ctrl & JZ_LCD_STATE_DISABLED));
+
+	jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	clk_disable(jzfb->ldclk);
+}
+
+static int jzfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct jzfb *jzfb = info->par;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		mutex_lock(&jzfb->lock);
+		if (jzfb->is_enabled) {
+			mutex_unlock(&jzfb->lock);
+			return 0;
+		}
+
+		jzfb_enable(jzfb);
+		jzfb->is_enabled = 1;
+
+		mutex_unlock(&jzfb->lock);
+
+		break;
+	default:
+		mutex_lock(&jzfb->lock);
+		if (!jzfb->is_enabled) {
+			mutex_unlock(&jzfb->lock);
+			return 0;
+		}
+
+		jzfb_disable(jzfb);
+
+		jzfb->is_enabled = 0;
+		mutex_unlock(&jzfb->lock);
+		break;
+	}
+
+	return 0;
+}
+
+static int jzfb_alloc_devmem(struct jzfb *jzfb)
+{
+	int max_videosize = 0;
+	struct fb_videomode *mode = jzfb->pdata->modes;
+	void *page;
+	int i;
+
+	for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
+		if (max_videosize < mode->xres * mode->yres)
+			max_videosize = mode->xres * mode->yres;
+	}
+
+	max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
+
+	jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
+					sizeof(*jzfb->framedesc),
+					&jzfb->framedesc_phys, GFP_KERNEL);
+
+	if (!jzfb->framedesc)
+		return -ENOMEM;
+
+	jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
+	jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
+					jzfb->vidmem_size,
+					&jzfb->vidmem_phys, GFP_KERNEL);
+
+	if (!jzfb->vidmem)
+		goto err_free_framedesc;
+
+	for (page = jzfb->vidmem;
+		 page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
+		 page += PAGE_SIZE) {
+		SetPageReserved(virt_to_page(page));
+	}
+
+	jzfb->framedesc->next = jzfb->framedesc_phys;
+	jzfb->framedesc->addr = jzfb->vidmem_phys;
+	jzfb->framedesc->id = 0xdeafbead;
+	jzfb->framedesc->cmd = 0;
+	jzfb->framedesc->cmd |= max_videosize / 4;
+
+	return 0;
+
+err_free_framedesc:
+	dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
+				jzfb->framedesc, jzfb->framedesc_phys);
+	return -ENOMEM;
+}
+
+static void jzfb_free_devmem(struct jzfb *jzfb)
+{
+	dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
+				jzfb->vidmem, jzfb->vidmem_phys);
+	dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
+				jzfb->framedesc, jzfb->framedesc_phys);
+}
+
+static struct  fb_ops jzfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = jzfb_check_var,
+	.fb_set_par = jzfb_set_par,
+	.fb_blank = jzfb_blank,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_setcolreg = jzfb_setcolreg,
+};
+
+static int __devinit jzfb_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jzfb *jzfb;
+	struct fb_info *fb;
+	struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *mem;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Missing platform data\n");
+		return -ENOENT;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "Failed to get register memory resource\n");
+		return -ENOENT;
+	}
+
+	mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
+	if (!mem) {
+		dev_err(&pdev->dev, "Failed to request register memory region\n");
+		return -EBUSY;
+	}
+
+	fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
+	if (!fb) {
+		dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
+		ret = -ENOMEM;
+		goto err_release_mem_region;
+	}
+
+	fb->fbops = &jzfb_ops;
+	fb->flags = FBINFO_DEFAULT;
+
+	jzfb = fb->par;
+	jzfb->pdev = pdev;
+	jzfb->pdata = pdata;
+	jzfb->mem = mem;
+
+	jzfb->ldclk = clk_get(&pdev->dev, "lcd");
+	if (IS_ERR(jzfb->ldclk)) {
+		ret = PTR_ERR(jzfb->ldclk);
+		dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
+		goto err_framebuffer_release;
+	}
+
+	jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
+	if (IS_ERR(jzfb->lpclk)) {
+		ret = PTR_ERR(jzfb->lpclk);
+		dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
+		goto err_put_ldclk;
+	}
+
+	jzfb->base = ioremap(mem->start, resource_size(mem));
+
+	if (!jzfb->base) {
+		dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
+		ret = -EBUSY;
+		goto err_put_lpclk;
+	}
+
+	platform_set_drvdata(pdev, jzfb);
+
+	fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
+				 &fb->modelist);
+	fb->mode = pdata->modes;
+
+	fb_videomode_to_var(&fb->var, fb->mode);
+	fb->var.bits_per_pixel = pdata->bpp;
+	jzfb_check_var(&fb->var, fb);
+
+	ret = jzfb_alloc_devmem(jzfb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to allocate video memory\n");
+		goto err_iounmap;
+	}
+
+	fb->fix = jzfb_fix;
+	fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
+	fb->fix.mmio_start = mem->start;
+	fb->fix.mmio_len = resource_size(mem);
+	fb->fix.smem_start = jzfb->vidmem_phys;
+	fb->fix.smem_len =  fb->fix.line_length * fb->var.yres;
+	fb->screen_base = jzfb->vidmem;
+	fb->pseudo_palette = jzfb->pseudo_palette;
+
+	fb_alloc_cmap(&fb->cmap, 256, 0);
+
+	mutex_init(&jzfb->lock);
+
+	clk_enable(jzfb->ldclk);
+	jzfb->is_enabled = 1;
+
+	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
+	jzfb_set_par(fb);
+
+	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	ret = register_framebuffer(fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
+		goto err_free_devmem;
+	}
+
+	jzfb->fb = fb;
+
+	return 0;
+
+err_free_devmem:
+	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	fb_dealloc_cmap(&fb->cmap);
+	jzfb_free_devmem(jzfb);
+err_iounmap:
+	iounmap(jzfb->base);
+err_put_lpclk:
+	clk_put(jzfb->lpclk);
+err_put_ldclk:
+	clk_put(jzfb->ldclk);
+err_framebuffer_release:
+	framebuffer_release(fb);
+err_release_mem_region:
+	release_mem_region(mem->start, resource_size(mem));
+	return ret;
+}
+
+static int __devexit jzfb_remove(struct platform_device *pdev)
+{
+	struct jzfb *jzfb = platform_get_drvdata(pdev);
+
+	jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
+
+	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
+	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+
+	iounmap(jzfb->base);
+	release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
+
+	fb_dealloc_cmap(&jzfb->fb->cmap);
+	jzfb_free_devmem(jzfb);
+
+	platform_set_drvdata(pdev, NULL);
+
+	clk_put(jzfb->lpclk);
+	clk_put(jzfb->ldclk);
+
+	framebuffer_release(jzfb->fb);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int jzfb_suspend(struct device *dev)
+{
+	struct jzfb *jzfb = dev_get_drvdata(dev);
+
+	acquire_console_sem();
+	fb_set_suspend(jzfb->fb, 1);
+	release_console_sem();
+
+	mutex_lock(&jzfb->lock);
+	if (jzfb->is_enabled)
+		jzfb_disable(jzfb);
+	mutex_unlock(&jzfb->lock);
+
+	return 0;
+}
+
+static int jzfb_resume(struct device *dev)
+{
+	struct jzfb *jzfb = dev_get_drvdata(dev);
+	clk_enable(jzfb->ldclk);
+
+	mutex_lock(&jzfb->lock);
+	if (jzfb->is_enabled)
+		jzfb_enable(jzfb);
+	mutex_unlock(&jzfb->lock);
+
+	acquire_console_sem();
+	fb_set_suspend(jzfb->fb, 0);
+	release_console_sem();
+
+	return 0;
+}
+
+static const struct dev_pm_ops jzfb_pm_ops = {
+	.suspend	= jzfb_suspend,
+	.resume		= jzfb_resume,
+	.poweroff	= jzfb_suspend,
+	.restore	= jzfb_resume,
+};
+
+#define JZFB_PM_OPS (&jzfb_pm_ops)
+
+#else
+#define JZFB_PM_OPS NULL
+#endif
+
+static struct platform_driver jzfb_driver = {
+	.probe = jzfb_probe,
+	.remove = __devexit_p(jzfb_remove),
+	.driver = {
+		.name = "jz4740-fb",
+		.pm = JZFB_PM_OPS,
+	},
+};
+
+static int __init jzfb_init(void)
+{
+	return platform_driver_register(&jzfb_driver);
+}
+module_init(jzfb_init);
+
+static void __exit jzfb_exit(void)
+{
+	platform_driver_unregister(&jzfb_driver);
+}
+module_exit(jzfb_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
+MODULE_ALIAS("platform:jz4740-fb");
diff --git a/include/linux/jz4740_fb.h b/include/linux/jz4740_fb.h
new file mode 100644
index 0000000..ab4c963
--- /dev/null
+++ b/include/linux/jz4740_fb.h
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __LINUX_JZ4740_FB_H
+#define __LINUX_JZ4740_FB_H
+
+#include <linux/fb.h>
+
+enum jz4740_fb_lcd_type {
+	JZ_LCD_TYPE_GENERIC_16_BIT = 0,
+	JZ_LCD_TYPE_GENERIC_18_BIT = 0 | (1 << 4),
+	JZ_LCD_TYPE_SPECIAL_TFT_1 = 1,
+	JZ_LCD_TYPE_SPECIAL_TFT_2 = 2,
+	JZ_LCD_TYPE_SPECIAL_TFT_3 = 3,
+	JZ_LCD_TYPE_NON_INTERLACED_CCIR656 = 5,
+	JZ_LCD_TYPE_INTERLACED_CCIR656 = 7,
+	JZ_LCD_TYPE_SINGLE_COLOR_STN = 8,
+	JZ_LCD_TYPE_SINGLE_MONOCHROME_STN = 9,
+	JZ_LCD_TYPE_DUAL_COLOR_STN = 10,
+	JZ_LCD_TYPE_DUAL_MONOCHROME_STN = 11,
+	JZ_LCD_TYPE_8BIT_SERIAL = 12,
+};
+
+/*
+* width: width of the lcd display in mm
+* height: height of the lcd display in mm
+* num_modes: size of modes
+* modes: list of valid video modes
+* bpp: bits per pixel for the lcd
+* lcd_type: lcd type
+*/
+
+struct jz4740_fb_platform_data {
+	unsigned int width;
+	unsigned int height;
+
+	size_t num_modes;
+	struct fb_videomode *modes;
+
+	unsigned int bpp;
+	enum jz4740_fb_lcd_type lcd_type;
+
+	unsigned pixclk_falling_edge:1;
+	unsigned date_enable_active_low:1;
+};
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:11:26 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:14:11 +0200 (CEST)
Received: from blue-ld-261.synserver.de ([217.119.54.83]:40189 "EHLO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492613Ab0FBTL0 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:11:26 +0200
Received: (qmail 13473 invoked by uid 0); 2 Jun 2010 19:11:12 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 13236
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.87 with SMTP; 2 Jun 2010 19:11:10 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 13/26] MIPS: JZ4740: Add platform devices
Date:   Wed,  2 Jun 2010 21:10:29 +0200
Message-Id: <1275505832-17185-5-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27020
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1621
Content-Length: 9359
Lines: 349

This patch adds platform devices for all the JZ4740 platform drivers.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/include/asm/mach-jz4740/platform.h |   36 ++++
 arch/mips/jz4740/platform.c                  |  288 ++++++++++++++++++++++++++
 2 files changed, 324 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-jz4740/platform.h
 create mode 100644 arch/mips/jz4740/platform.c

diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
new file mode 100644
index 0000000..7a51c70
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform device definitions
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef __JZ4740_PLATFORM_H
+#define __JZ4740_PLATFORM_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device jz4740_usb_ohci_device;
+extern struct platform_device jz4740_udc_device;
+extern struct platform_device jz4740_mmc_device;
+extern struct platform_device jz4740_rtc_device;
+extern struct platform_device jz4740_i2c_device;
+extern struct platform_device jz4740_nand_device;
+extern struct platform_device jz4740_framebuffer_device;
+extern struct platform_device jz4740_i2s_device;
+extern struct platform_device jz4740_codec_device;
+extern struct platform_device jz4740_adc_device;
+extern struct platform_device jz4740_battery_device;
+
+void jz4740_serial_device_register(void);
+
+#endif
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
new file mode 100644
index 0000000..734b441
--- /dev/null
+++ b/arch/mips/jz4740/platform.c
@@ -0,0 +1,288 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 platform devices
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+
+#include <asm/mach-jz4740/platform.h>
+#include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/irq.h>
+
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include "serial.h"
+#include "clock.h"
+
+/* OHCI (USB full speed host controller) */
+static struct resource jz4740_usb_ohci_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_UHC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_UHC_BASE_ADDR) + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= JZ4740_IRQ_UHC,
+		.end	= JZ4740_IRQ_UHC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+struct platform_device jz4740_usb_ohci_device = {
+	.name		= "jz4740-ohci",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &ohci_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(jz4740_usb_ohci_resources),
+	.resource	= jz4740_usb_ohci_resources,
+};
+
+/* UDC (USB gadget controller) */
+static struct resource jz4740_usb_gdt_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_UDC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_UDC_BASE_ADDR) + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= JZ4740_IRQ_UDC,
+		.end	= JZ4740_IRQ_UDC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 jz4740_udc_dmamask = ~(u32)0;
+
+struct platform_device jz4740_udc_device = {
+	.name		= "jz-udc",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &jz4740_udc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(jz4740_usb_gdt_resources),
+	.resource	= jz4740_usb_gdt_resources,
+};
+
+/** MMC/SD controller **/
+static struct resource jz4740_mmc_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_MSC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_MSC_BASE_ADDR) + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= JZ4740_IRQ_MSC,
+		.end	= JZ4740_IRQ_MSC,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 jz4740_mmc_dmamask =  ~(u32)0;
+
+struct platform_device jz4740_mmc_device = {
+	.name = "jz4740-mmc",
+	.id = 0,
+	.dev = {
+		.dma_mask		= &jz4740_mmc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(jz4740_mmc_resources),
+	.resource	= jz4740_mmc_resources,
+};
+
+static struct resource jz4740_rtc_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_RTC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_RTC_BASE_ADDR) + 0x38 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = JZ4740_IRQ_RTC,
+		.end	= JZ4740_IRQ_RTC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device jz4740_rtc_device = {
+	.name	= "jz4740-rtc",
+	.id	= -1,
+	.num_resources	= ARRAY_SIZE(jz4740_rtc_resources),
+	.resource	= jz4740_rtc_resources,
+};
+
+/** I2C controller **/
+static struct resource jz4740_i2c_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_I2C_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_I2C_BASE_ADDR) + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= JZ4740_IRQ_I2C,
+		.end	= JZ4740_IRQ_I2C,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 jz4740_i2c_dmamask =  ~(u32)0;
+
+struct platform_device jz4740_i2c_device = {
+	.name = "jz_i2c",
+	.id = 0,
+	.dev = {
+		.dma_mask		= &jz4740_i2c_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(jz4740_i2c_resources),
+	.resource	= jz4740_i2c_resources,
+};
+
+static struct resource jz4740_nand_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_EMC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_EMC_BASE_ADDR) + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device jz4740_nand_device = {
+	.name = "jz4740-nand",
+	.num_resources = ARRAY_SIZE(jz4740_nand_resources),
+	.resource = jz4740_nand_resources,
+};
+
+static struct resource jz4740_framebuffer_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_LCD_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_LCD_BASE_ADDR) + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static u64 jz4740_fb_dmamask = ~(u32)0;
+
+struct platform_device jz4740_framebuffer_device = {
+	.name = "jz4740-fb",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(jz4740_framebuffer_resources),
+	.resource = jz4740_framebuffer_resources,
+	.dev = {
+		.dma_mask = &jz4740_fb_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+};
+
+static struct resource jz4740_i2s_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_AIC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_AIC_BASE_ADDR) + 0x38 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device jz4740_i2s_device = {
+	.name = "jz4740-i2s",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(jz4740_i2s_resources),
+	.resource = jz4740_i2s_resources,
+};
+
+static struct resource jz4740_codec_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_AIC_BASE_ADDR) + 0x80,
+		.end	= CPHYSADDR(JZ4740_AIC_BASE_ADDR) + 0x88 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device jz4740_codec_device = {
+	.name		= "jz4740-codec",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(jz4740_codec_resources),
+	.resource	= jz4740_codec_resources,
+};
+
+static struct resource jz4740_adc_resources[] = {
+	[0] = {
+		.start	= CPHYSADDR(JZ4740_SADC_BASE_ADDR),
+		.end	= CPHYSADDR(JZ4740_SADC_BASE_ADDR) + 0x30,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= JZ4740_IRQ_SADC,
+		.end	= JZ4740_IRQ_SADC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device jz4740_adc_device = {
+	.name		= "jz4740-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(jz4740_adc_resources),
+	.resource	= jz4740_adc_resources,
+};
+
+struct platform_device jz4740_battery_device = {
+	.name = "jz4740-battery",
+	.id = -1,
+	.dev = {
+		.parent	= &jz4740_adc_device.dev
+	},
+};
+
+/* Serial */
+#define JZ4740_UART_DATA(_id) \
+	{ \
+		.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \
+		.iotype = UPIO_MEM, \
+		.regshift = 2, \
+		.serial_out = jz4740_serial_out, \
+		.type = PORT_16550A, \
+		.mapbase = CPHYSADDR(JZ4740_UART ## _id ## _BASE_ADDR), \
+		.irq = JZ4740_IRQ_UART ## _id, \
+	}
+
+static struct plat_serial8250_port jz4740_uart_data[] = {
+	JZ4740_UART_DATA(0),
+	JZ4740_UART_DATA(1),
+	{},
+};
+
+static struct platform_device jz4740_uart_device = {
+	.name = "serial8250",
+	.id = 0,
+	.dev = {
+		.platform_data = jz4740_uart_data,
+	},
+};
+
+void jz4740_serial_device_register(void)
+{
+	struct plat_serial8250_port *p;
+
+	for (p = jz4740_uart_data; p->flags != 0; ++p)
+		p->uartclk = jz4740_clock_bdata.ext_rate;
+
+	platform_device_register(&jz4740_uart_device);
+}
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:14:34 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1570 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492625Ab0FBTOB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:01 +0200
Received: (qmail 31626 invoked by uid 0); 2 Jun 2010 19:13:07 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:07 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        David Woodhouse <dwmw2@infradead.org>,
        linux-mtd@lists.infradead.org
Subject: [RFC][PATCH 17/26] MTD: Nand: Add JZ4740 NAND driver
Date:   Wed,  2 Jun 2010 21:12:23 +0200
Message-Id: <1275505950-17334-1-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27021
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1622
Content-Length: 14230
Lines: 531

This patch adds support for the NAND controller on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
---
 drivers/mtd/nand/Kconfig        |    6 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/jz4740_nand.c  |  442 +++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/jz4740_nand.h |   34 +++
 4 files changed, 483 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/jz4740_nand.c
 create mode 100644 include/linux/mtd/jz4740_nand.h

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 98a04b3..5e03939 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -525,4 +525,10 @@ config MTD_NAND_NUC900
 	  This enables the driver for the NAND Flash on evaluation board based
 	  on w90p910 / NUC9xx.
 
+config MTD_NAND_JZ4740
+	tristate "Support for JZ4740 SoC NAND controller"
+	depends on MACH_JZ4740
+	help
+		Enables support for NAND Flash on JZ4740 SoC based boards.
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index e8ab884..ac83dcd 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
+obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
new file mode 100644
index 0000000..fee3123
--- /dev/null
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -0,0 +1,442 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *	JZ4740 SoC NAND controller driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/gpio.h>
+
+#define JZ_REG_NAND_CTRL	0x50
+#define JZ_REG_NAND_ECC_CTRL	0x100
+#define JZ_REG_NAND_DATA	0x104
+#define JZ_REG_NAND_PAR0	0x108
+#define JZ_REG_NAND_PAR1	0x10C
+#define JZ_REG_NAND_PAR2	0x110
+#define JZ_REG_NAND_IRQ_STAT	0x114
+#define JZ_REG_NAND_IRQ_CTRL	0x118
+#define JZ_REG_NAND_ERR(x)	(0x11C + (x << 2))
+
+#define JZ_NAND_ECC_CTRL_PAR_READY	BIT(4)
+#define JZ_NAND_ECC_CTRL_ENCODING	BIT(3)
+#define JZ_NAND_ECC_CTRL_RS		BIT(2)
+#define JZ_NAND_ECC_CTRL_RESET		BIT(1)
+#define JZ_NAND_ECC_CTRL_ENABLE		BIT(0)
+
+#define JZ_NAND_STATUS_ERR_COUNT	(BIT(31) | BIT(30) | BIT(29))
+#define JZ_NAND_STATUS_PAD_FINISH	BIT(4)
+#define JZ_NAND_STATUS_DEC_FINISH	BIT(3)
+#define JZ_NAND_STATUS_ENC_FINISH	BIT(2)
+#define JZ_NAND_STATUS_UNCOR_ERROR	BIT(1)
+#define JZ_NAND_STATUS_ERROR		BIT(0)
+
+#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT(x << 1)
+#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT((x << 1) + 1)
+
+#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
+#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
+#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
+
+struct jz_nand {
+	struct mtd_info mtd;
+	struct nand_chip chip;
+	void __iomem *base;
+	struct resource *mem;
+
+	struct jz_nand_platform_data *pdata;
+	bool is_reading;
+};
+
+static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct jz_nand, mtd);
+}
+
+static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	struct nand_chip *chip = mtd->priv;
+	uint32_t reg;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
+		if (ctrl & NAND_ALE)
+			chip->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
+		else if (ctrl & NAND_CLE)
+			chip->IO_ADDR_W = JZ_NAND_CMD_ADDR;
+		else
+			chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+		reg = readl(nand->base + JZ_REG_NAND_CTRL);
+		if (ctrl & NAND_NCE)
+			reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
+		else
+			reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
+		writel(reg, nand->base + JZ_REG_NAND_CTRL);
+	}
+	if (dat != NAND_CMD_NONE)
+		writeb(dat, chip->IO_ADDR_W);
+}
+
+static int jz_nand_dev_ready(struct mtd_info *mtd)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	return gpio_get_value_cansleep(nand->pdata->busy_gpio);
+}
+
+static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	uint32_t reg;
+
+
+	writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	reg |= JZ_NAND_ECC_CTRL_RESET;
+	reg |= JZ_NAND_ECC_CTRL_ENABLE;
+	reg |= JZ_NAND_ECC_CTRL_RS;
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
+		nand->is_reading = true;
+		break;
+	case NAND_ECC_WRITE:
+		reg |= JZ_NAND_ECC_CTRL_ENCODING;
+		nand->is_reading = false;
+		break;
+	default:
+		break;
+	}
+
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+}
+
+
+static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
+	uint8_t *ecc_code)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	uint32_t reg, status;
+	int i;
+	static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
+						0x8b, 0xff, 0xb7, 0x6f};
+
+	if (nand->is_reading)
+		return 0;
+
+	do {
+		status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+	} while (!(status & JZ_NAND_STATUS_ENC_FINISH));
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	for (i = 0; i < 9; ++i)
+		ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
+
+	/* If the written data is completly 0xff, we also want to write 0xff as
+	 * ecc, otherwise we will get in trouble when doing subpage writes. */
+	if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
+		memset(ecc_code, 0xff, 9);
+
+	return 0;
+}
+
+/*#define printkd printk*/
+#define printkd(...)
+
+static void correct_data(uint8_t *dat, int index, int mask)
+{
+	int offset = index & 0x7;
+	uint16_t data;
+	printkd("correct: ");
+
+	index += (index >> 3);
+
+	data = dat[index];
+	data |= dat[index+1] << 8;
+
+	printkd("0x%x -> ", data);
+
+	mask ^= (data >> offset) & 0x1ff;
+	data &= ~(0x1ff << offset);
+	data |= (mask << offset);
+
+	printkd("0x%x\n", data);
+
+	dat[index] = data & 0xff;
+	dat[index+1] = (data >> 8) & 0xff;
+}
+
+static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
+	uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	int i, error_count, index;
+	uint32_t reg, status, error;
+	uint32_t t;
+
+	t = read_ecc[0];
+
+	if (t == 0xff) {
+		for (i = 1; i < 9; ++i)
+			t &= read_ecc[i];
+
+		t &= dat[0];
+		t &= dat[nand->chip.ecc.size / 2];
+		t &= dat[nand->chip.ecc.size - 1];
+
+		if (t == 0xff) {
+			for (i = 1; i < nand->chip.ecc.size - 1; ++i)
+				t &= dat[i];
+			if (t == 0xff)
+				return 0;
+		}
+	}
+
+	for (i = 0; i < 9; ++i)
+		writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg |= JZ_NAND_ECC_CTRL_PAR_READY;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	do {
+		status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+	} while (!(status & JZ_NAND_STATUS_DEC_FINISH));
+
+	reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+	reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+	writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+	if (status & JZ_NAND_STATUS_ERROR) {
+		if (status & JZ_NAND_STATUS_UNCOR_ERROR) {
+			printkd("uncorrectable ecc:");
+			for (i = 0; i < 9; ++i)
+				printkd(" 0x%x", read_ecc[i]);
+			printkd("\n");
+			printkd("uncorrectable data:");
+			for (i = 0; i < 32; ++i)
+				printkd(" 0x%x", dat[i]);
+			printkd("\n");
+			return -1;
+		}
+
+		error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
+
+		printkd("error_count: %d %x\n", error_count, status);
+
+		for (i = 0; i < error_count; ++i) {
+			error = readl(nand->base + JZ_REG_NAND_ERR(i));
+			index = ((error >> 16) & 0x1ff) - 1;
+			if (index >= 0 && index < 512)
+				correct_data(dat, index, error & 0x1ff);
+		}
+
+		return error_count;
+	}
+
+	return 0;
+}
+
+
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+static const char *part_probes[] = {"cmdline", NULL};
+#endif
+
+static int __devinit jz_nand_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jz_nand *nand;
+	struct nand_chip *chip;
+	struct mtd_info *mtd;
+	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *partition_info;
+	int num_partitions = 0;
+#endif
+
+	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
+	if (!nand) {
+		dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	nand->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!nand->mem) {
+		dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
+		ret = -ENOENT;
+		goto err_free;
+	}
+
+	nand->mem = request_mem_region(nand->mem->start,
+					resource_size(nand->mem), pdev->name);
+
+	if (!nand->mem) {
+		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	nand->base = ioremap(nand->mem->start, resource_size(nand->mem));
+
+	if (!nand->base) {
+		dev_err(&pdev->dev, "Failed to ioremap mmio memory region\n");
+		ret = -EBUSY;
+		goto err_release_mem;
+	}
+
+	if (pdata && gpio_is_valid(pdata->busy_gpio)) {
+		ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request busy gpio %d: %d\n",
+				pdata->busy_gpio, ret);
+			goto err_iounmap;
+		}
+	}
+
+	mtd		= &nand->mtd;
+	chip		= &nand->chip;
+	mtd->priv	= chip;
+	mtd->owner	= THIS_MODULE;
+	mtd->name	= "jz4740-nand";
+
+	chip->ecc.hwctl		= jz_nand_hwctl;
+	chip->ecc.calculate	= jz_nand_calculate_ecc_rs;
+	chip->ecc.correct	= jz_nand_correct_ecc_rs;
+	chip->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
+	chip->ecc.size		= 512;
+	chip->ecc.bytes		= 9;
+	if (pdata)
+		chip->ecc.layout = pdata->ecc_layout;
+
+	chip->chip_delay = 50;
+	chip->cmd_ctrl = jz_nand_cmd_ctrl;
+
+	if (pdata && gpio_is_valid(pdata->busy_gpio))
+		chip->dev_ready = jz_nand_dev_ready;
+
+	chip->IO_ADDR_R = JZ_NAND_DATA_ADDR;
+	chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+	nand->pdata = pdata;
+	platform_set_drvdata(pdev, nand);
+
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret) {
+		dev_err(&pdev->dev,  "Failed to scan nand\n");
+		goto err_gpio_free;
+	}
+
+	if (pdata && pdata->ident_callback) {
+		pdata->ident_callback(pdev, chip, &pdata->partitions,
+					&pdata->num_partitions);
+	}
+
+	ret = nand_scan_tail(mtd);
+	if (ret) {
+		dev_err(&pdev->dev,  "Failed to scan nand\n");
+		goto err_gpio_free;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+	num_partitions = parse_mtd_partitions(mtd, part_probes,
+						&partition_info, 0);
+#endif
+	if (num_partitions <= 0 && pdata) {
+		num_partitions = pdata->num_partitions;
+		partition_info = pdata->partitions;
+	}
+
+	if (num_partitions > 0)
+		ret = add_mtd_partitions(mtd, partition_info, num_partitions);
+	else
+#endif
+	ret = add_mtd_device(mtd);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add mtd device\n");
+		goto err_nand_release;
+	}
+
+	dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
+
+	return 0;
+err_nand_release:
+	nand_release(&nand->mtd);
+err_gpio_free:
+	platform_set_drvdata(pdev, NULL);
+	gpio_free(pdata->busy_gpio);
+err_iounmap:
+	iounmap(nand->base);
+err_release_mem:
+	release_mem_region(nand->mem->start, resource_size(nand->mem));
+err_free:
+	kfree(nand);
+	return ret;
+}
+
+static void __devexit jz_nand_remove(struct platform_device *pdev)
+{
+	struct jz_nand *nand = platform_get_drvdata(pdev);
+
+	nand_release(&nand->mtd);
+
+	iounmap(nand->base);
+
+	release_mem_region(nand->mem->start, resource_size(nand->mem));
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(nand);
+}
+
+struct platform_driver jz_nand_driver = {
+	.probe = jz_nand_probe,
+	.remove = __devexit_p(jz_nand_probe),
+	.driver = {
+		.name = "jz4740-nand",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz_nand_init(void)
+{
+	return platform_driver_register(&jz_nand_driver);
+}
+module_init(jz_nand_init);
+
+static void __exit jz_nand_exit(void)
+{
+	platform_driver_unregister(&jz_nand_driver);
+}
+module_exit(jz_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC");
+MODULE_ALIAS("platform:jz4740-nand");
diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
new file mode 100644
index 0000000..379f9b6
--- /dev/null
+++ b/include/linux/mtd/jz4740_nand.h
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  JZ4740 SoC NAND controller driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __JZ_NAND_H__
+#define __JZ_NAND_H__
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct jz_nand_platform_data {
+	int			num_partitions;
+	struct mtd_partition	*partitions;
+
+	struct nand_ecclayout	*ecc_layout;
+
+	unsigned int busy_gpio;
+
+	void (*ident_callback)(struct platform_device *, struct nand_chip *,
+				struct mtd_partition **, int *num_partitions);
+};
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:14:59 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1573 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492626Ab0FBTOB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:01 +0200
Received: (qmail 31704 invoked by uid 0); 2 Jun 2010 19:13:08 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:07 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Andrew Morton <akpm@linux-foundation.org>,
        linux-mmc@vger.kernel.org
Subject: [RFC][PATCH 18/26] MMC: Add JZ4740 mmc driver
Date:   Wed,  2 Jun 2010 21:12:24 +0200
Message-Id: <1275505950-17334-2-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27022
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1623
Content-Length: 28545
Lines: 1075

This patch adds support for the mmc controller on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mmc@vger.kernel.org
---
 drivers/mmc/host/Kconfig       |    8 +
 drivers/mmc/host/Makefile      |    1 +
 drivers/mmc/host/jz4740_mmc.c  | 1000 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/jz4740_mmc.h |   15 +
 4 files changed, 1024 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/host/jz4740_mmc.c
 create mode 100644 include/linux/mmc/jz4740_mmc.h

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index e171e77..6c3162b 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -81,6 +81,14 @@ config MMC_RICOH_MMC
 
 	  If unsure, say Y.
 
+config MMC_JZ4740
+	tristate "JZ4740 SD/Multimedia Card Interface support"
+	depends on MACH_JZ4740
+	help
+	  This selects the Ingenic Z4740 SD/Multimedia card Interface.
+	  If you have an ngenic platform with a Multimedia Card slot,
+	  say Y or M here.
+
 config MMC_SDHCI_OF
 	tristate "SDHCI support on OpenFirmware platforms"
 	depends on MMC_SDHCI && PPC_OF
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e30c2ee..f4e53c9 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MMC_CB710)	+= cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
+obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 
 obj-$(CONFIG_MMC_SDHCI_OF)	+= sdhci-of.o
 sdhci-of-y				:= sdhci-of-core.o
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
new file mode 100644
index 0000000..1034b85
--- /dev/null
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -0,0 +1,1000 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *	JZ4740 SD/MMC controller driver
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/mmc/host.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/clk.h>
+#include <linux/mmc/jz4740_mmc.h>
+
+#include <linux/gpio.h>
+#include <asm/mach-jz4740/gpio.h>
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+
+#define JZ_REG_MMC_STRPCL	0x00
+#define JZ_REG_MMC_STATUS	0x04
+#define JZ_REG_MMC_CLKRT	0x08
+#define JZ_REG_MMC_CMDAT	0x0C
+#define JZ_REG_MMC_RESTO	0x10
+#define JZ_REG_MMC_RDTO		0x14
+#define JZ_REG_MMC_BLKLEN	0x18
+#define JZ_REG_MMC_NOB		0x1C
+#define JZ_REG_MMC_SNOB		0x20
+#define JZ_REG_MMC_IMASK	0x24
+#define JZ_REG_MMC_IREG		0x28
+#define JZ_REG_MMC_CMD		0x2C
+#define JZ_REG_MMC_ARG		0x30
+#define JZ_REG_MMC_RESP_FIFO	0x34
+#define JZ_REG_MMC_RXFIFO	0x38
+#define JZ_REG_MMC_TXFIFO	0x3C
+
+#define JZ_MMC_STRPCL_EXIT_MULTIPLE BIT(7)
+#define JZ_MMC_STRPCL_EXIT_TRANSFER BIT(6)
+#define JZ_MMC_STRPCL_START_READWAIT BIT(5)
+#define JZ_MMC_STRPCL_STOP_READWAIT BIT(4)
+#define JZ_MMC_STRPCL_RESET BIT(3)
+#define JZ_MMC_STRPCL_START_OP BIT(2)
+#define JZ_MMC_STRPCL_CLOCK_CONTROL (BIT(1) | BIT(0))
+#define JZ_MMC_STRPCL_CLOCK_STOP BIT(0)
+#define JZ_MMC_STRPCL_CLOCK_START BIT(1)
+
+
+#define JZ_MMC_STATUS_IS_RESETTING BIT(15)
+#define JZ_MMC_STATUS_SDIO_INT_ACTIVE BIT(14)
+#define JZ_MMC_STATUS_PRG_DONE BIT(13)
+#define JZ_MMC_STATUS_DATA_TRAN_DONE BIT(12)
+#define JZ_MMC_STATUS_END_CMD_RES BIT(11)
+#define JZ_MMC_STATUS_DATA_FIFO_AFULL BIT(10)
+#define JZ_MMC_STATUS_IS_READWAIT BIT(9)
+#define JZ_MMC_STATUS_CLK_EN BIT(8)
+#define JZ_MMC_STATUS_DATA_FIFO_FULL BIT(7)
+#define JZ_MMC_STATUS_DATA_FIFO_EMPTY BIT(6)
+#define JZ_MMC_STATUS_CRC_RES_ERR BIT(5)
+#define JZ_MMC_STATUS_CRC_READ_ERROR BIT(4)
+#define JZ_MMC_STATUS_TIMEOUT_WRITE BIT(3)
+#define JZ_MMC_STATUS_CRC_WRITE_ERROR BIT(2)
+#define JZ_MMC_STATUS_TIMEOUT_RES BIT(1)
+#define JZ_MMC_STATUS_TIMEOUT_READ BIT(0)
+
+#define JZ_MMC_STATUS_READ_ERROR_MASK (BIT(4) | BIT(0))
+#define JZ_MMC_STATUS_WRITE_ERROR_MASK (BIT(3) | BIT(2))
+
+
+#define JZ_MMC_CMDAT_IO_ABORT BIT(11)
+#define JZ_MMC_CMDAT_BUS_WIDTH_4BIT BIT(10)
+#define JZ_MMC_CMDAT_DMA_EN BIT(8)
+#define JZ_MMC_CMDAT_INIT BIT(7)
+#define JZ_MMC_CMDAT_BUSY BIT(6)
+#define JZ_MMC_CMDAT_STREAM BIT(5)
+#define JZ_MMC_CMDAT_WRITE BIT(4)
+#define JZ_MMC_CMDAT_DATA_EN BIT(3)
+#define JZ_MMC_CMDAT_RESPONSE_FORMAT (BIT(2) | BIT(1) | BIT(0))
+#define JZ_MMC_CMDAT_RSP_R1 1
+#define JZ_MMC_CMDAT_RSP_R2 2
+#define JZ_MMC_CMDAT_RSP_R3 3
+
+#define JZ_MMC_IRQ_SDIO BIT(7)
+#define JZ_MMC_IRQ_TXFIFO_WR_REQ BIT(6)
+#define JZ_MMC_IRQ_RXFIFO_RD_REQ BIT(5)
+#define JZ_MMC_IRQ_END_CMD_RES BIT(2)
+#define JZ_MMC_IRQ_PRG_DONE BIT(1)
+#define JZ_MMC_IRQ_DATA_TRAN_DONE BIT(0)
+
+
+#define JZ_MMC_CLK_RATE 24000000
+
+#define JZ4740_MMC_MAX_TIMEOUT 10000000
+
+struct jz4740_mmc_host {
+	struct mmc_host *mmc;
+	struct platform_device *pdev;
+	struct jz4740_mmc_platform_data *pdata;
+	struct clk *clk;
+
+	int irq;
+	int card_detect_irq;
+
+	struct resource *mem;
+	void __iomem *base;
+	struct mmc_request *req;
+	struct mmc_command *cmd;
+
+	int max_clock;
+	uint32_t cmdat;
+
+	uint16_t irq_mask;
+
+	spinlock_t lock;
+	struct timer_list clock_timer;
+	struct timer_list timeout_timer;
+	unsigned waiting:1;
+};
+
+static void jz4740_mmc_cmd_done(struct jz4740_mmc_host *host);
+
+static void jz4740_mmc_enable_irq(struct jz4740_mmc_host *host, unsigned int irq)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->irq_mask &= ~irq;
+	writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void jz4740_mmc_disable_irq(struct jz4740_mmc_host *host, unsigned int irq)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->irq_mask |= irq;
+	writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host,
+	bool start_transfer)
+{
+	uint16_t val = JZ_MMC_STRPCL_CLOCK_START;
+
+	if (start_transfer)
+		val |= JZ_MMC_STRPCL_START_OP;
+
+	writew(val, host->base + JZ_REG_MMC_STRPCL);
+}
+
+static void jz4740_mmc_clock_disable(struct jz4740_mmc_host *host)
+{
+	uint32_t status;
+
+	writew(JZ_MMC_STRPCL_CLOCK_STOP, host->base + JZ_REG_MMC_STRPCL);
+	do {
+		status = readl(host->base + JZ_REG_MMC_STATUS);
+	} while (status & JZ_MMC_STATUS_CLK_EN);
+
+}
+
+static void jz4740_mmc_reset(struct jz4740_mmc_host *host)
+{
+	uint32_t status;
+
+	writew(JZ_MMC_STRPCL_RESET, host->base + JZ_REG_MMC_STRPCL);
+	udelay(10);
+	do {
+		status = readl(host->base + JZ_REG_MMC_STATUS);
+	} while (status & JZ_MMC_STATUS_IS_RESETTING);
+}
+
+static void jz4740_mmc_request_done(struct jz4740_mmc_host *host)
+{
+	struct mmc_request *req;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	req = host->req;
+	host->req = NULL;
+	host->waiting = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (!unlikely(req))
+		return;
+
+	mmc_request_done(host->mmc, req);
+}
+
+static inline unsigned int jz4740_mmc_wait_irq(struct jz4740_mmc_host *host,
+	unsigned int irq)
+{
+	unsigned int timeout = JZ4740_MMC_MAX_TIMEOUT;
+	uint16_t status;
+
+	do {
+		status = readw(host->base + JZ_REG_MMC_IREG);
+	} while (!(status & irq) && --timeout);
+
+	return timeout;
+}
+
+static void jz4740_mmc_write_data(struct jz4740_mmc_host *host,
+	struct mmc_data *data)
+{
+	struct scatterlist *sg;
+	uint32_t *sg_pointer;
+	int status;
+	unsigned int timeout;
+	size_t i, j;
+
+	for (sg = data->sg; sg; sg = sg_next(sg)) {
+		sg_pointer = sg_virt(sg);
+		i = sg->length / 4;
+		j = i >> 3;
+		i = i & 0x7;
+		while (j) {
+			timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ);
+			if (unlikely(timeout == 0))
+				goto err_timeout;
+
+			writel(sg_pointer[0], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[1], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[2], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[3], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[4], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[5], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[6], host->base + JZ_REG_MMC_TXFIFO);
+			writel(sg_pointer[7], host->base + JZ_REG_MMC_TXFIFO);
+			sg_pointer += 8;
+			--j;
+		}
+		if (i) {
+			timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_TXFIFO_WR_REQ);
+			if (unlikely(timeout == 0))
+				goto err_timeout;
+
+			while (i) {
+				writel(*sg_pointer, host->base + JZ_REG_MMC_TXFIFO);
+				++sg_pointer;
+				--i;
+			}
+		}
+		data->bytes_xfered += sg->length;
+	}
+
+	status = readl(host->base + JZ_REG_MMC_STATUS);
+	if (status & JZ_MMC_STATUS_WRITE_ERROR_MASK)
+		goto err;
+
+	timeout = JZ4740_MMC_MAX_TIMEOUT;
+	do {
+		status = readl(host->base + JZ_REG_MMC_STATUS);
+	} while ((status & JZ_MMC_STATUS_DATA_TRAN_DONE) == 0 && --timeout);
+
+	if (unlikely(timeout == 0))
+		goto err_timeout;
+	writew(JZ_MMC_IRQ_DATA_TRAN_DONE, host->base + JZ_REG_MMC_IREG);
+
+	return;
+err_timeout:
+	host->req->cmd->error = -ETIMEDOUT;
+	data->error = -ETIMEDOUT;
+	return;
+err:
+	if (status & (JZ_MMC_STATUS_TIMEOUT_WRITE)) {
+		host->req->cmd->error = -ETIMEDOUT;
+		data->error = -ETIMEDOUT;
+	} else {
+		host->req->cmd->error = -EIO;
+		data->error = -EIO;
+	}
+}
+
+static void jz4740_mmc_timeout(unsigned long data)
+{
+	struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->waiting) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
+	host->waiting = 0;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	host->req->cmd->error = -ETIMEDOUT;
+	jz4740_mmc_request_done(host);
+}
+
+static void jz4740_mmc_read_data(struct jz4740_mmc_host *host,
+				struct mmc_data *data)
+{
+	struct scatterlist *sg;
+	uint32_t *sg_pointer;
+	uint32_t d;
+	uint16_t status = 0;
+	size_t i, j;
+	unsigned int timeout;
+
+	for (sg = data->sg; sg; sg = sg_next(sg)) {
+		sg_pointer = sg_virt(sg);
+		i = sg->length;
+		j = i >> 5;
+		i = i & 0x1f;
+		while (j) {
+			timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ);
+			if (unlikely(timeout == 0))
+				goto err_timeout;
+
+			sg_pointer[0] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[1] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[2] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[3] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[4] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[5] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[6] = readl(host->base + JZ_REG_MMC_RXFIFO);
+			sg_pointer[7] = readl(host->base + JZ_REG_MMC_RXFIFO);
+
+			sg_pointer += 8;
+			--j;
+		}
+
+		while (i >= 4) {
+			timeout = jz4740_mmc_wait_irq(host, JZ_MMC_IRQ_RXFIFO_RD_REQ);
+			if (unlikely(timeout == 0))
+				goto err_timeout;
+
+			*sg_pointer = readl(host->base + JZ_REG_MMC_RXFIFO);
+			++sg_pointer;
+			i -= 4;
+		}
+		if (i > 0) {
+			d = readl(host->base + JZ_REG_MMC_RXFIFO);
+			memcpy(sg_pointer, &d, i);
+		}
+		data->bytes_xfered += sg->length;
+
+		flush_dcache_page(sg_page(sg));
+	}
+
+	status = readl(host->base + JZ_REG_MMC_STATUS);
+	if (status & JZ_MMC_STATUS_READ_ERROR_MASK)
+		goto err;
+
+	/* For whatever reason there is sometime one word more in the fifo then
+	 * requested */
+	while ((status & JZ_MMC_STATUS_DATA_FIFO_EMPTY) == 0 && --timeout) {
+		d = readl(host->base + JZ_REG_MMC_RXFIFO);
+		status = readl(host->base + JZ_REG_MMC_STATUS);
+	}
+	return;
+err_timeout:
+	host->req->cmd->error = -ETIMEDOUT;
+	data->error = -ETIMEDOUT;
+	return;
+err:
+	if (status & JZ_MMC_STATUS_TIMEOUT_READ) {
+		host->req->cmd->error = -ETIMEDOUT;
+		data->error = -ETIMEDOUT;
+	} else {
+		host->req->cmd->error = -EIO;
+		data->error = -EIO;
+	}
+}
+
+static irqreturn_t jz_mmc_irq_worker(int irq, void *devid)
+{
+	struct jz4740_mmc_host *host = (struct jz4740_mmc_host *)devid;
+
+	if (host->cmd->error)
+		jz4740_mmc_request_done(host);
+	else
+		jz4740_mmc_cmd_done(host);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t jz_mmc_irq(int irq, void *devid)
+{
+	struct jz4740_mmc_host *host = devid;
+	uint16_t irq_reg, status, tmp;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	irq_reg = readw(host->base + JZ_REG_MMC_IREG);
+
+	tmp = irq_reg;
+	spin_lock_irqsave(&host->lock, flags);
+	irq_reg &= ~host->irq_mask;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	tmp &= ~(JZ_MMC_IRQ_TXFIFO_WR_REQ | JZ_MMC_IRQ_RXFIFO_RD_REQ |
+			JZ_MMC_IRQ_PRG_DONE | JZ_MMC_IRQ_DATA_TRAN_DONE);
+
+	if (tmp != irq_reg) {
+		dev_warn(&host->pdev->dev, "Sparse irq: %x\n", tmp & ~irq_reg);
+		writew(tmp & ~irq_reg, host->base + JZ_REG_MMC_IREG);
+	}
+
+
+	if (irq_reg & JZ_MMC_IRQ_SDIO) {
+		writew(JZ_MMC_IRQ_SDIO, host->base + JZ_REG_MMC_IREG);
+		mmc_signal_sdio_irq(host->mmc);
+	}
+
+	if (!host->req || !host->cmd)
+		goto handled;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->waiting) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		goto handled;
+	}
+
+	host->waiting = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	del_timer(&host->timeout_timer);
+
+	status = readl(host->base + JZ_REG_MMC_STATUS);
+
+	if (status & JZ_MMC_STATUS_TIMEOUT_RES) {
+		host->cmd->error = -ETIMEDOUT;
+	} else if (status & JZ_MMC_STATUS_CRC_RES_ERR) {
+		host->cmd->error = -EIO;
+	} else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR |
+			JZ_MMC_STATUS_CRC_WRITE_ERROR)) {
+		host->cmd->data->error = -EIO;
+	} else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR |
+			JZ_MMC_STATUS_CRC_WRITE_ERROR)) {
+		host->cmd->data->error = -EIO;
+	}
+
+	if (irq_reg & JZ_MMC_IRQ_END_CMD_RES) {
+		jz4740_mmc_disable_irq(host, JZ_MMC_IRQ_END_CMD_RES);
+		writew(JZ_MMC_IRQ_END_CMD_RES, host->base + JZ_REG_MMC_IREG);
+		ret = IRQ_WAKE_THREAD;
+	}
+
+	return ret;
+handled:
+
+	writew(0xff, host->base + JZ_REG_MMC_IREG);
+	return IRQ_HANDLED;
+}
+
+static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate)
+{
+	int div = 0;
+	int real_rate;
+
+	jz4740_mmc_clock_disable(host);
+	clk_set_rate(host->clk, JZ_MMC_CLK_RATE);
+
+	real_rate = clk_get_rate(host->clk);
+
+	while (real_rate > rate && div < 7) {
+		++div;
+		real_rate >>= 1;
+	}
+
+	writew(div, host->base + JZ_REG_MMC_CLKRT);
+	return real_rate;
+}
+
+
+static void jz4740_mmc_read_response(struct jz4740_mmc_host *host,
+	struct mmc_command *cmd)
+{
+	int i;
+	uint16_t tmp;
+	if (cmd->flags & MMC_RSP_136) {
+		tmp = readw(host->base + JZ_REG_MMC_RESP_FIFO);
+		for (i = 0; i < 4; ++i) {
+			cmd->resp[i] = tmp << 24;
+			cmd->resp[i] |= readw(host->base + JZ_REG_MMC_RESP_FIFO) << 8;
+			tmp = readw(host->base + JZ_REG_MMC_RESP_FIFO);
+			cmd->resp[i] |= tmp >> 8;
+		}
+	} else {
+		cmd->resp[0] = readw(host->base + JZ_REG_MMC_RESP_FIFO) << 24;
+		cmd->resp[0] |= readw(host->base + JZ_REG_MMC_RESP_FIFO) << 8;
+		cmd->resp[0] |= readw(host->base + JZ_REG_MMC_RESP_FIFO) & 0xff;
+	}
+}
+
+static void jz4740_mmc_send_command(struct jz4740_mmc_host *host,
+	struct mmc_command *cmd)
+{
+	uint32_t cmdat = host->cmdat;
+
+	host->cmdat &= ~JZ_MMC_CMDAT_INIT;
+	jz4740_mmc_clock_disable(host);
+
+	host->cmd = cmd;
+
+	if (cmd->flags & MMC_RSP_BUSY)
+		cmdat |= JZ_MMC_CMDAT_BUSY;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_R1B:
+	case MMC_RSP_R1:
+		cmdat |= JZ_MMC_CMDAT_RSP_R1;
+		break;
+	case MMC_RSP_R2:
+		cmdat |= JZ_MMC_CMDAT_RSP_R2;
+		break;
+	case MMC_RSP_R3:
+		cmdat |= JZ_MMC_CMDAT_RSP_R3;
+		break;
+	default:
+		break;
+	}
+
+	if (cmd->data) {
+		cmdat |= JZ_MMC_CMDAT_DATA_EN;
+		if (cmd->data->flags & MMC_DATA_WRITE)
+			cmdat |= JZ_MMC_CMDAT_WRITE;
+		if (cmd->data->flags & MMC_DATA_STREAM)
+			cmdat |= JZ_MMC_CMDAT_STREAM;
+
+		writew(cmd->data->blksz, host->base + JZ_REG_MMC_BLKLEN);
+		writew(cmd->data->blocks, host->base + JZ_REG_MMC_NOB);
+	}
+
+	writeb(cmd->opcode, host->base + JZ_REG_MMC_CMD);
+	writel(cmd->arg, host->base + JZ_REG_MMC_ARG);
+	writel(cmdat, host->base + JZ_REG_MMC_CMDAT);
+
+	host->waiting = 1;
+	jz4740_mmc_clock_enable(host, 1);
+	mod_timer(&host->timeout_timer, jiffies + 5*HZ);
+}
+
+static void jz4740_mmc_cmd_done(struct jz4740_mmc_host *host)
+{
+	uint32_t status;
+	struct mmc_command *cmd = host->req->cmd;
+	struct mmc_request *req = host->req;
+	unsigned int timeout = JZ4740_MMC_MAX_TIMEOUT;
+
+	if (cmd->flags & MMC_RSP_PRESENT)
+		jz4740_mmc_read_response(host, cmd);
+
+	if (cmd->data) {
+		if (cmd->data->flags & MMC_DATA_READ)
+			jz4740_mmc_read_data(host, cmd->data);
+		else
+			jz4740_mmc_write_data(host, cmd->data);
+	}
+
+	if (req->stop) {
+		jz4740_mmc_send_command(host, req->stop);
+		do {
+			status = readw(host->base + JZ_REG_MMC_IREG);
+		} while ((status & JZ_MMC_IRQ_PRG_DONE) == 0 && --timeout);
+		writew(JZ_MMC_IRQ_PRG_DONE, host->base + JZ_REG_MMC_IREG);
+	}
+
+	if (unlikely(timeout == 0))
+		req->stop->error = -ETIMEDOUT;
+
+	jz4740_mmc_request_done(host);
+}
+
+static void jz4740_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+	struct jz4740_mmc_host *host = mmc_priv(mmc);
+
+	host->req = req;
+
+	writew(0xffff, host->base + JZ_REG_MMC_IREG);
+
+	writew(JZ_MMC_IRQ_END_CMD_RES, host->base + JZ_REG_MMC_IREG);
+	jz4740_mmc_enable_irq(host, JZ_MMC_IRQ_END_CMD_RES);
+	jz4740_mmc_send_command(host, req->cmd);
+}
+
+
+static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct jz4740_mmc_host *host = mmc_priv(mmc);
+	if (ios->clock)
+		jz4740_mmc_set_clock_rate(host, ios->clock);
+
+	switch (ios->power_mode) {
+	case MMC_POWER_UP:
+		jz4740_mmc_reset(host);
+		if (gpio_is_valid(host->pdata->gpio_power))
+			gpio_set_value(host->pdata->gpio_power,
+					!host->pdata->power_active_low);
+		host->cmdat |= JZ_MMC_CMDAT_INIT;
+		clk_enable(host->clk);
+		break;
+	case MMC_POWER_ON:
+		break;
+	default:
+		if (gpio_is_valid(host->pdata->gpio_power))
+			gpio_set_value(host->pdata->gpio_power,
+					host->pdata->power_active_low);
+		clk_disable(host->clk);
+		break;
+	}
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_4BIT;
+		break;
+	case MMC_BUS_WIDTH_4:
+		host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_4BIT;
+		break;
+	default:
+		break;
+	}
+}
+
+static int jz4740_mmc_get_ro(struct mmc_host *mmc)
+{
+	struct jz4740_mmc_host *host = mmc_priv(mmc);
+	if (!gpio_is_valid(host->pdata->gpio_read_only))
+		return -ENOSYS;
+
+	return gpio_get_value(host->pdata->gpio_read_only) ^
+		host->pdata->read_only_active_low;
+}
+
+static int jz4740_mmc_get_cd(struct mmc_host *mmc)
+{
+	struct jz4740_mmc_host *host = mmc_priv(mmc);
+	if (!gpio_is_valid(host->pdata->gpio_card_detect))
+		return -ENOSYS;
+
+	return gpio_get_value(host->pdata->gpio_card_detect) ^
+			host->pdata->card_detect_active_low;
+}
+
+static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid)
+{
+	struct jz4740_mmc_host *host = devid;
+
+	mmc_detect_change(host->mmc, HZ / 3);
+
+	return IRQ_HANDLED;
+}
+
+static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct jz4740_mmc_host *host = mmc_priv(mmc);
+	if (enable)
+		jz4740_mmc_enable_irq(host, JZ_MMC_IRQ_SDIO);
+	else
+		jz4740_mmc_disable_irq(host, JZ_MMC_IRQ_SDIO);
+}
+
+static const struct mmc_host_ops jz4740_mmc_ops = {
+	.request	= jz4740_mmc_request,
+	.set_ios	= jz4740_mmc_set_ios,
+	.get_ro		= jz4740_mmc_get_ro,
+	.get_cd		= jz4740_mmc_get_cd,
+	.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
+};
+
+static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = {
+	JZ_GPIO_BULK_PIN(MSC_CMD),
+	JZ_GPIO_BULK_PIN(MSC_CLK),
+	JZ_GPIO_BULK_PIN(MSC_DATA0),
+	JZ_GPIO_BULK_PIN(MSC_DATA1),
+	JZ_GPIO_BULK_PIN(MSC_DATA2),
+	JZ_GPIO_BULK_PIN(MSC_DATA3),
+};
+
+static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev)
+{
+	int ret;
+	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata)
+		return 0;
+
+	if (gpio_is_valid(pdata->gpio_card_detect)) {
+		ret = gpio_request(pdata->gpio_card_detect, "MMC detect change");
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request detect change gpio\n");
+			goto err;
+		}
+		gpio_direction_input(pdata->gpio_card_detect);
+	}
+
+	if (gpio_is_valid(pdata->gpio_read_only)) {
+		ret = gpio_request(pdata->gpio_read_only, "MMC read only");
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request read only gpio: %d\n", ret);
+			goto err_free_gpio_card_detect;
+		}
+		gpio_direction_input(pdata->gpio_read_only);
+	}
+
+	if (gpio_is_valid(pdata->gpio_power)) {
+		ret = gpio_request(pdata->gpio_power, "MMC power");
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request power gpio: %d\n", ret);
+			goto err_free_gpio_read_only;
+		}
+		gpio_direction_output(pdata->gpio_power, pdata->power_active_low);
+	}
+
+	return 0;
+
+err_free_gpio_read_only:
+	if (gpio_is_valid(pdata->gpio_read_only))
+		gpio_free(pdata->gpio_read_only);
+err_free_gpio_card_detect:
+	if (gpio_is_valid(pdata->gpio_card_detect))
+		gpio_free(pdata->gpio_card_detect);
+err:
+	return ret;
+}
+
+static void jz4740_mmc_free_gpios(struct platform_device *pdev)
+{
+	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata)
+		return;
+
+	if (gpio_is_valid(pdata->gpio_power))
+		gpio_free(pdata->gpio_power);
+	if (gpio_is_valid(pdata->gpio_read_only))
+		gpio_free(pdata->gpio_read_only);
+	if (gpio_is_valid(pdata->gpio_card_detect))
+		gpio_free(pdata->gpio_card_detect);
+}
+
+static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host)
+{
+	size_t num_pins = ARRAY_SIZE(jz4740_mmc_pins);
+	if (host->pdata && host->pdata->data_1bit)
+		num_pins -= 3;
+
+	return num_pins;
+}
+
+static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
+{
+	int ret;
+	struct mmc_host *mmc;
+	struct jz4740_mmc_host *host;
+	struct jz4740_mmc_platform_data *pdata;
+
+	pdata = pdev->dev.platform_data;
+
+	mmc = mmc_alloc_host(sizeof(struct jz4740_mmc_host), &pdev->dev);
+
+	if (!mmc) {
+		dev_err(&pdev->dev, "Failed to alloc mmc host structure\n");
+		return -ENOMEM;
+	}
+
+	host = mmc_priv(mmc);
+	host->pdata = pdata;
+
+	host->irq = platform_get_irq(pdev, 0);
+
+	if (host->irq < 0) {
+		ret = host->irq;
+		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
+		goto err_free_host;
+	}
+
+	host->clk = clk_get(&pdev->dev, "mmc");
+	if (!host->clk) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get mmc clock\n");
+		goto err_free_host;
+	}
+
+	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!host->mem) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get base platform memory\n");
+		goto err_clk_put;
+	}
+
+	host->mem = request_mem_region(host->mem->start,
+					resource_size(host->mem), pdev->name);
+
+	if (!host->mem) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "Failed to request base memory region\n");
+		goto err_clk_put;
+	}
+
+	host->base = ioremap_nocache(host->mem->start, resource_size(host->mem));
+
+	if (!host->base) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "Failed to ioremap base memory\n");
+		goto err_release_mem_region;
+	}
+
+	ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret);
+		goto err_iounmap;
+	}
+
+	ret = jz4740_mmc_request_gpios(pdev);
+	if (ret)
+		goto err_gpio_bulk_free;
+
+	mmc->ops = &jz4740_mmc_ops;
+	mmc->f_min = JZ_MMC_CLK_RATE / 128;
+	mmc->f_max = JZ_MMC_CLK_RATE;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->caps = (pdata && pdata->data_1bit) ? 0 : MMC_CAP_4_BIT_DATA;
+	mmc->caps |= MMC_CAP_SDIO_IRQ;
+
+	mmc->max_blk_size = (1 << 10) - 1;
+	mmc->max_blk_count = (1 << 15) - 1;
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+
+	mmc->max_phys_segs = 128;
+	mmc->max_hw_segs = 128;
+	mmc->max_seg_size = mmc->max_req_size;
+
+	host->mmc = mmc;
+	host->pdev = pdev;
+	host->max_clock = JZ_MMC_CLK_RATE;
+	spin_lock_init(&host->lock);
+	host->irq_mask = 0xffff;
+
+	host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect);
+
+	if (host->card_detect_irq < 0) {
+		dev_warn(&pdev->dev, "Failed to get irq for card detect gpio\n");
+	} else {
+		ret = request_irq(host->card_detect_irq,
+			jz4740_mmc_card_detect_irq,
+			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			"MMC card detect", host);
+
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request card detect irq");
+			goto err_free_gpios;
+		}
+	}
+
+	ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker,
+		IRQF_DISABLED, dev_name(&pdev->dev), host);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+		goto err_free_card_detect_irq;
+	}
+
+	jz4740_mmc_reset(host);
+	jz4740_mmc_clock_disable(host);
+	setup_timer(&host->timeout_timer, jz4740_mmc_timeout,
+			(unsigned long)host);
+
+	platform_set_drvdata(pdev, host);
+	ret = mmc_add_host(mmc);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add mmc host: %d\n", ret);
+		goto err_free_irq;
+	}
+	dev_info(&pdev->dev, "JZ SD/MMC card driver registered\n");
+
+	return 0;
+
+err_free_irq:
+	free_irq(host->irq, host);
+err_free_card_detect_irq:
+	if (host->card_detect_irq >= 0)
+		free_irq(host->card_detect_irq, host);
+err_free_gpios:
+	jz4740_mmc_free_gpios(pdev);
+err_gpio_bulk_free:
+	jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
+err_iounmap:
+	iounmap(host->base);
+err_release_mem_region:
+	release_mem_region(host->mem->start, resource_size(host->mem));
+err_clk_put:
+	clk_put(host->clk);
+err_free_host:
+	platform_set_drvdata(pdev, NULL);
+	mmc_free_host(mmc);
+
+	return ret;
+}
+
+static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
+{
+	struct jz4740_mmc_host *host = platform_get_drvdata(pdev);
+
+	del_timer_sync(&host->timeout_timer);
+	jz4740_mmc_disable_irq(host, 0xff);
+	jz4740_mmc_reset(host);
+
+	mmc_remove_host(host->mmc);
+
+	free_irq(host->irq, host);
+	if (host->card_detect_irq >= 0)
+		free_irq(host->card_detect_irq, host);
+
+	jz4740_mmc_free_gpios(pdev);
+	jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
+
+	iounmap(host->base);
+	release_mem_region(host->mem->start, resource_size(host->mem));
+
+	clk_put(host->clk);
+
+	platform_set_drvdata(pdev, NULL);
+	mmc_free_host(host->mmc);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int jz4740_mmc_suspend(struct device *dev)
+{
+	struct jz4740_mmc_host *host = dev_get_drvdata(dev);
+
+	mmc_suspend_host(host->mmc);
+
+	jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
+
+	return 0;
+}
+
+static int jz4740_mmc_resume(struct device *dev)
+{
+	struct jz4740_mmc_host *host = dev_get_drvdata(dev);
+
+	jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
+
+	mmc_resume_host(host->mmc);
+
+	return 0;
+}
+
+const struct dev_pm_ops jz4740_mmc_pm_ops = {
+	.suspend	= jz4740_mmc_suspend,
+	.resume		= jz4740_mmc_resume,
+	.poweroff	= jz4740_mmc_suspend,
+	.restore	= jz4740_mmc_resume,
+};
+
+#define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops)
+#else
+#define JZ4740_MMC_PM_OPS NULL
+#endif
+
+static struct platform_driver jz4740_mmc_driver = {
+	.probe = jz4740_mmc_probe,
+	.remove = __devexit_p(jz4740_mmc_remove),
+	.driver = {
+		.name = "jz4740-mmc",
+		.owner = THIS_MODULE,
+		.pm = JZ4740_MMC_PM_OPS,
+	},
+};
+
+static int __init jz4740_mmc_init(void)
+{
+	return platform_driver_register(&jz4740_mmc_driver);
+}
+module_init(jz4740_mmc_init);
+
+static void __exit jz4740_mmc_exit(void)
+{
+	platform_driver_unregister(&jz4740_mmc_driver);
+}
+module_exit(jz4740_mmc_exit);
+
+MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/include/linux/mmc/jz4740_mmc.h b/include/linux/mmc/jz4740_mmc.h
new file mode 100644
index 0000000..8543f43
--- /dev/null
+++ b/include/linux/mmc/jz4740_mmc.h
@@ -0,0 +1,15 @@
+#ifndef __LINUX_MMC_JZ4740_MMC
+#define __LINUX_MMC_JZ4740_MMC
+
+struct jz4740_mmc_platform_data {
+	int gpio_power;
+	int gpio_card_detect;
+	int gpio_read_only;
+	unsigned card_detect_active_low:1;
+	unsigned read_only_active_low:1;
+	unsigned power_active_low:1;
+
+	unsigned data_1bit:1;
+};
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:15:31 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1582 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492628Ab0FBTOB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:01 +0200
Received: (qmail 31849 invoked by uid 0); 2 Jun 2010 19:13:10 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:09 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec driver
Date:   Wed,  2 Jun 2010 21:12:26 +0200
Message-Id: <1275505950-17334-4-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27023
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1630
Content-Length: 16968
Lines: 594

This patch adds support for the JZ4740 internal codec.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
Cc: alsa-devel@alsa-project.org
---
 sound/soc/codecs/Kconfig        |    4 +
 sound/soc/codecs/Makefile       |    2 +
 sound/soc/codecs/jz4740-codec.c |  502 +++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/jz4740-codec.h |   20 ++
 4 files changed, 528 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/codecs/jz4740-codec.c
 create mode 100644 sound/soc/codecs/jz4740-codec.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 31ac553..b8008df 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -23,6 +23,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_AK4671 if I2C
 	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
 	select SND_SOC_CS4270 if I2C
+	select SND_SOC_JZ4740 if SOC_JZ4740
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_DA7210 if I2C
 	select SND_SOC_PCM3008
@@ -269,6 +270,9 @@ config SND_SOC_WM9712
 config SND_SOC_WM9713
 	tristate
 
+config SND_SOC_JZ4740_CODEC
+	tristate
+
 # Amp
 config SND_SOC_MAX9877
 	tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 91429ea..4c7ee31 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -56,6 +56,7 @@ snd-soc-wm9705-objs := wm9705.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
+snd-soc-jz4740-codec-objs := jz4740-codec.o
 
 # Amp
 snd-soc-max9877-objs := max9877.o
@@ -121,6 +122,7 @@ obj-$(CONFIG_SND_SOC_WM9705)	+= snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
+obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 
 # Amp
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
diff --git a/sound/soc/codecs/jz4740-codec.c b/sound/soc/codecs/jz4740-codec.c
new file mode 100644
index 0000000..6e4b741
--- /dev/null
+++ b/sound/soc/codecs/jz4740-codec.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc.h>
+
+#define JZ4740_REG_CODEC_1 0x0
+#define JZ4740_REG_CODEC_2 0x1
+
+#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
+#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
+#define JZ4740_CODEC_1_SW1_ENABLE BIT(27)
+#define JZ4740_CODEC_1_ADC_ENABLE BIT(26)
+#define JZ4740_CODEC_1_SW2_ENABLE BIT(25)
+#define JZ4740_CODEC_1_DAC_ENABLE BIT(24)
+#define JZ4740_CODEC_1_VREF_DISABLE BIT(20)
+#define JZ4740_CODEC_1_VREF_AMP_DISABLE BIT(19)
+#define JZ4740_CODEC_1_VREF_PULL_DOWN BIT(18)
+#define JZ4740_CODEC_1_VREF_LOW_CURRENT BIT(17)
+#define JZ4740_CODEC_1_VREF_HIGH_CURRENT BIT(16)
+#define JZ4740_CODEC_1_HEADPHONE_DISABLE BIT(14)
+#define JZ4740_CODEC_1_HEADPHONE_AMP_CHANGE_ANY BIT(13)
+#define JZ4740_CODEC_1_HEADPHONE_CHANGE BIT(12)
+#define JZ4740_CODEC_1_HEADPHONE_PULL_DOWN_M BIT(11)
+#define JZ4740_CODEC_1_HEADPHONE_PULL_DOWN_R BIT(10)
+#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M BIT(9)
+#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN BIT(8)
+#define JZ4740_CODEC_1_SUSPEND BIT(1)
+#define JZ4740_CODEC_1_RESET BIT(0)
+
+#define JZ4740_CODEC_1_LINE_ENABLE_OFFSET 29
+#define JZ4740_CODEC_1_MIC_ENABLE_OFFSET 28
+#define JZ4740_CODEC_1_SW1_ENABLE_OFFSET 27
+#define JZ4740_CODEC_1_ADC_ENABLE_OFFSET 26
+#define JZ4740_CODEC_1_SW2_ENABLE_OFFSET 25
+#define JZ4740_CODEC_1_DAC_ENABLE_OFFSET 24
+#define JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET 14
+#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET 8
+
+#define JZ4740_CODEC_2_INPUT_VOLUME_MASK		0x1f0000
+#define JZ4740_CODEC_2_SAMPLE_RATE_MASK			0x000f00
+#define JZ4740_CODEC_2_MIC_BOOST_GAIN_MASK		0x000030
+#define JZ4740_CODEC_2_HEADPHONE_VOLUME_MASK	0x000003
+
+#define JZ4740_CODEC_2_INPUT_VOLUME_OFFSET		16
+#define JZ4740_CODEC_2_SAMPLE_RATE_OFFSET		 8
+#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET	 4
+#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET	 0
+
+struct jz4740_codec {
+	void __iomem *base;
+	struct resource *mem;
+
+	uint32_t reg_cache[2];
+	struct snd_soc_codec codec;
+};
+
+static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
+{
+	return container_of(codec, struct jz4740_codec, codec);
+}
+
+static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
+	return readl(jz4740_codec->base + (reg << 2));
+}
+
+static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int val)
+{
+	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
+	jz4740_codec->reg_cache[reg] = val;
+
+	writel(val, jz4740_codec->base + (reg << 2));
+	return 0;
+}
+
+static const struct snd_kcontrol_new jz4740_codec_controls[] = {
+	SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
+			JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
+	SOC_SINGLE("Capture Volume", JZ4740_REG_CODEC_2,
+			JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
+	SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
+	SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
+			JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
+};
+
+static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
+	SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0),
+	SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0),
+};
+
+static const struct snd_kcontrol_new jz4740_codec_input_controls[] = {
+	SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0),
+	SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = {
+	SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0),
+	SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0),
+
+	SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET, 1,
+			jz4740_codec_output_controls,
+			ARRAY_SIZE(jz4740_codec_output_controls)),
+
+	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
+			jz4740_codec_input_controls,
+			ARRAY_SIZE(jz4740_codec_input_controls)),
+	SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("LOUT"),
+	SND_SOC_DAPM_OUTPUT("ROUT"),
+
+	SND_SOC_DAPM_INPUT("MIC"),
+	SND_SOC_DAPM_INPUT("LIN"),
+	SND_SOC_DAPM_INPUT("RIN"),
+};
+
+static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
+
+	{"Line Input", NULL, "LIN"},
+	{"Line Input", NULL, "RIN"},
+
+	{"Input Mixer", "Line Capture Switch", "Line Input"},
+	{"Input Mixer", "Mic Capture Switch", "MIC"},
+
+	{"ADC", NULL, "Input Mixer"},
+
+	{"Output Mixer", "Bypass Switch", "Input Mixer"},
+	{"Output Mixer", "DAC Switch", "DAC"},
+
+	{"LOUT", NULL, "Output Mixer"},
+	{"ROUT", NULL, "Output Mixer"},
+};
+
+static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	uint32_t val;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->card->codec;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	switch (params_rate(params)) {
+	case 8000:
+		val = 0;
+		break;
+	case 11025:
+		val = 1;
+		break;
+	case 12000:
+		val = 2;
+		break;
+	case 16000:
+		val = 3;
+		break;
+	case 22050:
+		val = 4;
+		break;
+	case 24000:
+		val = 5;
+		break;
+	case 32000:
+		val = 6;
+		break;
+	case 44100:
+		val = 7;
+		break;
+	case 48000:
+		val = 8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
+
+	snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
+				JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
+
+	return 0;
+}
+
+static int jz4740_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
+	.hw_params = jz4740_codec_hw_params,
+	.set_fmt = jz4740_codec_set_fmt,
+};
+
+struct snd_soc_dai jz4740_codec_dai = {
+	.name = "jz-codec",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
+	},
+	.ops = &jz4740_codec_dai_ops,
+	.symmetric_rates = 1,
+};
+EXPORT_SYMBOL_GPL(jz4740_codec_dai);
+
+static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
+	enum snd_soc_bias_level level)
+{
+
+	if (codec->bias_level == SND_SOC_BIAS_OFF && level != SND_SOC_BIAS_OFF) {
+		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
+		udelay(2);
+
+		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
+	}
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_VREF_DISABLE |
+			JZ4740_CODEC_1_VREF_AMP_DISABLE |
+			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M |
+			JZ4740_CODEC_1_VREF_LOW_CURRENT |
+			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
+			0);
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_VREF_LOW_CURRENT |
+			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
+			JZ4740_CODEC_1_VREF_LOW_CURRENT |
+			JZ4740_CODEC_1_VREF_HIGH_CURRENT);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE,
+			JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE);
+		break;
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+			JZ4740_CODEC_1_SUSPEND, JZ4740_CODEC_1_SUSPEND);
+		break;
+	}
+	codec->bias_level = level;
+
+	return 0;
+}
+
+
+static struct snd_soc_codec *jz4740_codec_codec;
+
+static int jz4740_codec_dev_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = jz4740_codec_codec;
+
+	BUG_ON(!codec);
+
+	socdev->card->codec = codec;
+
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_add_controls(codec, jz4740_codec_controls,
+		ARRAY_SIZE(jz4740_codec_controls));
+
+	snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
+		ARRAY_SIZE(jz4740_codec_dapm_widgets));
+
+	snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
+		ARRAY_SIZE(jz4740_codec_dapm_routes));
+
+	snd_soc_dapm_new_widgets(codec);
+
+	return 0;
+}
+
+static int jz4740_codec_dev_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
+	.probe = jz4740_codec_dev_probe,
+	.remove = jz4740_codec_dev_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
+
+static int __devinit jz4740_codec_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jz4740_codec *jz4740_codec;
+	struct snd_soc_codec *codec;
+
+	jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
+
+	if (!jz4740_codec)
+		return -ENOMEM;
+
+	jz4740_codec->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!jz4740_codec->mem) {
+		dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
+		ret = -ENOENT;
+		goto err_free_codec;
+	}
+
+	jz4740_codec->mem = request_mem_region(jz4740_codec->mem->start,
+				resource_size(jz4740_codec->mem), pdev->name);
+
+	if (!jz4740_codec->mem) {
+		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+		ret = -EBUSY;
+		goto err_free_codec;
+	}
+
+	jz4740_codec->base = ioremap(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
+
+	if (!jz4740_codec->base) {
+		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
+		ret = -EBUSY;
+		goto err_release_mem_region;
+	}
+
+	jz4740_codec_dai.dev = &pdev->dev;
+
+	codec = &jz4740_codec->codec;
+
+	codec->dev		= &pdev->dev;
+	codec->name		= "jz-codec";
+	codec->owner		= THIS_MODULE;
+
+	codec->read		= jz4740_codec_read;
+	codec->write		= jz4740_codec_write;
+	codec->set_bias_level	= jz4740_codec_set_bias_level;
+	codec->bias_level	= SND_SOC_BIAS_OFF;
+
+	codec->dai		= &jz4740_codec_dai;
+	codec->num_dai		= 1;
+
+	codec->reg_cache	= jz4740_codec->reg_cache;
+	codec->reg_cache_size	= 2;
+
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	jz4740_codec_codec = codec;
+
+	snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+				JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
+
+
+	platform_set_drvdata(pdev, jz4740_codec);
+	ret = snd_soc_register_codec(codec);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register codec\n");
+		goto err_iounmap;
+	}
+
+	ret = snd_soc_register_dai(&jz4740_codec_dai);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register codec dai\n");
+		goto err_unregister_codec;
+	}
+
+	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
+err_unregister_codec:
+	snd_soc_unregister_codec(codec);
+err_iounmap:
+	iounmap(jz4740_codec->base);
+err_release_mem_region:
+	release_mem_region(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
+err_free_codec:
+	kfree(jz4740_codec);
+
+	return ret;
+}
+
+static int __devexit jz4740_codec_remove(struct platform_device *pdev)
+{
+	struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_dai(&jz4740_codec_dai);
+	snd_soc_unregister_codec(&jz4740_codec->codec);
+
+	iounmap(jz4740_codec->base);
+	release_mem_region(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(jz4740_codec);
+
+	return 0;
+}
+
+static struct platform_driver jz4740_codec_driver = {
+	.probe = jz4740_codec_probe,
+	.remove = __devexit_p(jz4740_codec_remove),
+	.driver = {
+		.name = "jz4740-codec",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz4740_codec_init(void)
+{
+	return platform_driver_register(&jz4740_codec_driver);
+}
+module_init(jz4740_codec_init);
+
+static void __exit jz4740_codec_exit(void)
+{
+	platform_driver_unregister(&jz4740_codec_driver);
+}
+module_exit(jz4740_codec_exit);
+
+MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:jz-codec");
diff --git a/sound/soc/codecs/jz4740-codec.h b/sound/soc/codecs/jz4740-codec.h
new file mode 100644
index 0000000..b5a0691
--- /dev/null
+++ b/sound/soc/codecs/jz4740-codec.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
+#define __SND_SOC_CODECS_JZ4740_CODEC_H__
+
+extern struct snd_soc_dai jz4740_codec_dai;
+extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:15:59 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1587 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492629Ab0FBTOB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:01 +0200
Received: (qmail 31956 invoked by uid 0); 2 Jun 2010 19:13:11 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:11 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>, lm-sensors@lm-sensors.org
Subject: [RFC][PATCH 22/26] hwmon: Add JZ4740 ADC driver
Date:   Wed,  2 Jun 2010 21:12:28 +0200
Message-Id: <1275505950-17334-6-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27024
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1631
Content-Length: 13079
Lines: 510

This patch adds support for the ADC module on JZ4740 SoCs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: lm-sensors@lm-sensors.org
---
 drivers/hwmon/Kconfig      |   11 ++
 drivers/hwmon/Makefile     |    1 +
 drivers/hwmon/jz4740-adc.c |  423 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/jz4740-adc.h |   25 +++
 4 files changed, 460 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/jz4740-adc.c
 create mode 100644 include/linux/jz4740-adc.h

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e19cf8e..da79ba9 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -446,6 +446,17 @@ config SENSORS_IT87
 	  This driver can also be built as a module.  If so, the module
 	  will be called it87.
 
+config SENSORS_JZ4740
+	tristate "Ingenic JZ4740 SoC ADC driver"
+	depends on MACH_JZ4740
+    help
+      If you say yes here you get support for the Ingenic JZ4740 SoC ADC core.
+      It is required for the JZ4740 battery and touchscreen driver and is used
+      to synchronize access to the adc module between those two.
+
+      This driver can also be build as a module. If so, the module will be
+      called jz4740-adc.
+
 config SENSORS_LM63
 	tristate "National Semiconductor LM63 and LM64"
 	depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 2138ceb..3e772aa 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
+obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-adc.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
 obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
diff --git a/drivers/hwmon/jz4740-adc.c b/drivers/hwmon/jz4740-adc.c
new file mode 100644
index 0000000..635dfe9
--- /dev/null
+++ b/drivers/hwmon/jz4740-adc.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *		JZ4740 SoC ADC driver
+ *
+ * This program is free software; you can redistribute	 it and/or modify it
+ * under  the terms of	 the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the	License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is meant to synchronize access to the adc core for the battery
+ * and touchscreen driver. Thus these drivers should use the adc driver as a
+ * parent.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <linux/clk.h>
+
+#include <linux/jz4740-adc.h>
+
+#define JZ_REG_ADC_ENABLE	0x00
+#define JZ_REG_ADC_CFG		0x04
+#define JZ_REG_ADC_CTRL		0x08
+#define JZ_REG_ADC_STATUS	0x0C
+#define JZ_REG_ADC_SAME		0x10
+#define JZ_REG_ADC_WAIT		0x14
+#define JZ_REG_ADC_TOUCH	0x18
+#define JZ_REG_ADC_BATTERY	0x1C
+#define JZ_REG_ADC_ADCIN	0x20
+
+#define JZ_ADC_ENABLE_TOUCH		BIT(2)
+#define JZ_ADC_ENABLE_BATTERY		BIT(1)
+#define JZ_ADC_ENABLE_ADCIN		BIT(0)
+
+#define JZ_ADC_CFG_SPZZ			BIT(31)
+#define JZ_ADC_CFG_EX_IN		BIT(30)
+#define JZ_ADC_CFG_DNUM_MASK		(0x7 << 16)
+#define JZ_ADC_CFG_DMA_ENABLE		BIT(15)
+#define JZ_ADC_CFG_XYZ_MASK		(0x2 << 13)
+#define JZ_ADC_CFG_SAMPLE_NUM_MASK	(0x7 << 10)
+#define JZ_ADC_CFG_CLKDIV		(0xf << 5)
+#define JZ_ADC_CFG_BAT_MB		BIT(4)
+
+#define JZ_ADC_CFG_DNUM_OFFSET		16
+#define JZ_ADC_CFG_XYZ_OFFSET		13
+#define JZ_ADC_CFG_SAMPLE_NUM_OFFSET	10
+#define JZ_ADC_CFG_CLKDIV_OFFSET	5
+
+#define JZ_ADC_IRQ_PENDOWN		BIT(4)
+#define JZ_ADC_IRQ_PENUP		BIT(3)
+#define JZ_ADC_IRQ_TOUCH		BIT(2)
+#define JZ_ADC_IRQ_BATTERY		BIT(1)
+#define JZ_ADC_IRQ_ADCIN		BIT(0)
+
+#define JZ_ADC_TOUCH_TYPE1		BIT(31)
+#define JZ_ADC_TOUCH_DATA1_MASK		0xfff
+#define JZ_ADC_TOUCH_TYPE0		BIT(15)
+#define JZ_ADC_TOUCH_DATA0_MASK		0xfff
+
+#define JZ_ADC_BATTERY_MASK		0xfff
+
+#define JZ_ADC_ADCIN_MASK		0xfff
+
+struct jz4740_adc {
+	struct resource *mem;
+	void __iomem *base;
+
+	int irq;
+
+	struct clk *clk;
+	unsigned int clk_ref;
+
+	struct device *hwmon;
+
+	struct completion bat_completion;
+	struct completion adc_completion;
+
+	spinlock_t lock;
+};
+
+static irqreturn_t jz4740_adc_irq(int irq, void *data)
+{
+	struct jz4740_adc *adc = data;
+	uint8_t status;
+
+	status = readb(adc->base + JZ_REG_ADC_STATUS);
+
+	if (status & JZ_ADC_IRQ_BATTERY)
+		complete(&adc->bat_completion);
+	if (status & JZ_ADC_IRQ_ADCIN)
+		complete(&adc->adc_completion);
+
+	writeb(0xff, adc->base + JZ_REG_ADC_STATUS);
+
+	return IRQ_HANDLED;
+}
+
+static void jz4740_adc_enable_irq(struct jz4740_adc *adc, int irq)
+{
+	unsigned long flags;
+	uint8_t val;
+
+	spin_lock_irqsave(&adc->lock, flags);
+
+	val = readb(adc->base + JZ_REG_ADC_CTRL);
+	val &= ~irq;
+	writeb(val, adc->base + JZ_REG_ADC_CTRL);
+
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static void jz4740_adc_disable_irq(struct jz4740_adc *adc, int irq)
+{
+	unsigned long flags;
+	uint8_t val;
+
+	spin_lock_irqsave(&adc->lock, flags);
+
+	val = readb(adc->base + JZ_REG_ADC_CTRL);
+	val |= irq;
+	writeb(val, adc->base + JZ_REG_ADC_CTRL);
+
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static void jz4740_adc_enable_adc(struct jz4740_adc *adc, int engine)
+{
+	unsigned long flags;
+	uint8_t val;
+
+	spin_lock_irqsave(&adc->lock, flags);
+
+	val = readb(adc->base + JZ_REG_ADC_ENABLE);
+	val |= engine;
+	writeb(val, adc->base + JZ_REG_ADC_ENABLE);
+
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static void jz4740_adc_disable_adc(struct jz4740_adc *adc, int engine)
+{
+	unsigned long flags;
+	uint8_t val;
+
+	spin_lock_irqsave(&adc->lock, flags);
+
+	val = readb(adc->base + JZ_REG_ADC_ENABLE);
+	val &= ~engine;
+	writeb(val, adc->base + JZ_REG_ADC_ENABLE);
+
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static inline void jz4740_adc_set_cfg(struct jz4740_adc *adc, uint32_t mask,
+uint32_t val)
+{
+	unsigned long flags;
+	uint32_t cfg;
+
+	spin_lock_irqsave(&adc->lock, flags);
+
+	cfg = readl(adc->base + JZ_REG_ADC_CFG);
+
+	cfg &= ~mask;
+	cfg |= val;
+
+	writel(cfg, adc->base + JZ_REG_ADC_CFG);
+
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&adc->lock, flags);
+	if (adc->clk_ref++ == 0)
+		clk_enable(adc->clk);
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&adc->lock, flags);
+	if (--adc->clk_ref == 0)
+		clk_disable(adc->clk);
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+long jz4740_adc_read_battery_voltage(struct device *dev,
+						enum jz_adc_battery_scale scale)
+{
+	struct jz4740_adc *adc = dev_get_drvdata(dev);
+	unsigned long t;
+	long long voltage;
+	uint16_t val;
+
+	if (!adc)
+		return -ENODEV;
+
+	jz4740_adc_clk_enable(adc);
+
+	if (scale == JZ_ADC_BATTERY_SCALE_2V5)
+		jz4740_adc_set_cfg(adc, JZ_ADC_CFG_BAT_MB, JZ_ADC_CFG_BAT_MB);
+	else
+		jz4740_adc_set_cfg(adc, JZ_ADC_CFG_BAT_MB, 0);
+
+	jz4740_adc_enable_irq(adc, JZ_ADC_IRQ_BATTERY);
+	jz4740_adc_enable_adc(adc, JZ_ADC_ENABLE_BATTERY);
+
+	t = wait_for_completion_interruptible_timeout(&adc->bat_completion,
+							HZ);
+
+	jz4740_adc_disable_irq(adc, JZ_ADC_IRQ_BATTERY);
+
+	if (t <= 0) {
+		jz4740_adc_disable_adc(adc, JZ_ADC_ENABLE_BATTERY);
+		return t ? t : -ETIMEDOUT;
+	}
+
+	val = readw(adc->base + JZ_REG_ADC_BATTERY);
+
+	jz4740_adc_clk_disable(adc);
+
+	if (scale == JZ_ADC_BATTERY_SCALE_2V5)
+		voltage = (((long long)val) * 2500000LL) >> 12LL;
+	else
+		voltage = ((((long long)val) * 7395000LL) >> 12LL) + 33000LL;
+
+	return voltage;
+}
+EXPORT_SYMBOL_GPL(jz4740_adc_read_battery_voltage);
+
+static ssize_t jz4740_adc_read_adcin(struct device *dev,
+					struct device_attribute *dev_attr,
+					char *buf)
+{
+	struct jz4740_adc *adc = dev_get_drvdata(dev);
+	unsigned long t;
+	uint16_t val;
+
+	jz4740_adc_clk_enable(adc);
+
+	jz4740_adc_enable_irq(adc, JZ_ADC_IRQ_ADCIN);
+	jz4740_adc_enable_adc(adc, JZ_ADC_ENABLE_ADCIN);
+
+	t = wait_for_completion_interruptible_timeout(&adc->adc_completion,
+							HZ);
+
+	jz4740_adc_disable_irq(adc, JZ_ADC_IRQ_ADCIN);
+
+	if (t <= 0) {
+		jz4740_adc_disable_adc(adc, JZ_ADC_ENABLE_ADCIN);
+		return t ? t : -ETIMEDOUT;
+	}
+
+	val = readw(adc->base + JZ_REG_ADC_ADCIN);
+	jz4740_adc_clk_disable(adc);
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, jz4740_adc_read_adcin, NULL, 0);
+
+static int __devinit jz4740_adc_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct jz4740_adc *adc;
+
+	adc = kmalloc(sizeof(*adc), GFP_KERNEL);
+
+	adc->irq = platform_get_irq(pdev, 0);
+
+	if (adc->irq < 0) {
+		ret = adc->irq;
+		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
+		goto err_free;
+	}
+
+	adc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!adc->mem) {
+		ret = -ENOENT;
+		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
+		goto err_free;
+	}
+
+	adc->mem = request_mem_region(adc->mem->start, resource_size(adc->mem),
+					pdev->name);
+
+	if (!adc->mem) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+		goto err_free;
+	}
+
+	adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem));
+
+	if (!adc->base) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
+		goto err_release_mem_region;
+	}
+
+	adc->clk = clk_get(&pdev->dev, "adc");
+
+	if (IS_ERR(adc->clk)) {
+		ret = PTR_ERR(adc->clk);
+		dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
+		goto err_iounmap;
+	}
+
+	init_completion(&adc->bat_completion);
+	init_completion(&adc->adc_completion);
+
+	spin_lock_init(&adc->lock);
+
+	adc->clk_ref = 0;
+
+	platform_set_drvdata(pdev, adc);
+
+	ret = request_irq(adc->irq, jz4740_adc_irq, 0, pdev->name, adc);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
+		goto err_clk_put;
+	}
+
+	ret = device_create_file(&pdev->dev, &sensor_dev_attr_in0_input.dev_attr);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to create sysfs file: %d\n", ret);
+		goto err_free_irq;
+	}
+
+	adc->hwmon = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(adc->hwmon)) {
+		ret = PTR_ERR(adc->hwmon);
+		goto err_remove_file;
+	}
+
+	writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
+	writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
+
+	return 0;
+
+err_remove_file:
+	device_remove_file(&pdev->dev, &sensor_dev_attr_in0_input.dev_attr);
+err_free_irq:
+	free_irq(adc->irq, adc);
+err_clk_put:
+	clk_put(adc->clk);
+err_iounmap:
+	platform_set_drvdata(pdev, NULL);
+	iounmap(adc->base);
+err_release_mem_region:
+	release_mem_region(adc->mem->start, resource_size(adc->mem));
+err_free:
+	kfree(adc);
+
+	return ret;
+}
+
+static int __devexit jz4740_adc_remove(struct platform_device *pdev)
+{
+	struct jz4740_adc *adc = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(adc->hwmon);
+	device_remove_file(&pdev->dev, &sensor_dev_attr_in0_input.dev_attr);
+
+	free_irq(adc->irq, adc);
+
+	iounmap(adc->base);
+	release_mem_region(adc->mem->start, resource_size(adc->mem));
+
+	clk_put(adc->clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(adc);
+
+	return 0;
+}
+
+struct platform_driver jz4740_adc_driver = {
+	.probe	= jz4740_adc_probe,
+	.remove = __devexit_p(jz4740_adc_remove),
+	.driver = {
+		.name = "jz4740-adc",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz4740_adc_init(void)
+{
+	return platform_driver_register(&jz4740_adc_driver);
+}
+module_init(jz4740_adc_init);
+
+static void __exit jz4740_adc_exit(void)
+{
+	platform_driver_unregister(&jz4740_adc_driver);
+}
+module_exit(jz4740_adc_exit);
+
+MODULE_DESCRIPTION("JZ4740 SoC ADC driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:jz4740-adc");
diff --git a/include/linux/jz4740-adc.h b/include/linux/jz4740-adc.h
new file mode 100644
index 0000000..59cfe63
--- /dev/null
+++ b/include/linux/jz4740-adc.h
@@ -0,0 +1,25 @@
+
+#ifndef __LINUX_JZ4740_ADC
+#define __LINUX_JZ4740_ADC
+
+#include <linux/device.h>
+
+enum jz_adc_battery_scale {
+	JZ_ADC_BATTERY_SCALE_2V5, /* Mesures voltages up to 2.5V */
+	JZ_ADC_BATTERY_SCALE_7V5, /* Mesures voltages up to 7.5V */
+};
+
+/*
+ * jz4740_adc_read_battery_voltage - Read battery voltage from the ADC PBAT pin
+ * @dev: Pointer to a jz4740-adc device
+ * @scale: Whether to use 2.5V or 7.5V scale
+ *
+ * Returns: Battery voltage in mircovolts
+ *
+ * Context: Process
+*/
+long jz4740_adc_read_battery_voltage(struct device *dev,
+					enum jz_adc_battery_scale scale);
+
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:02 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:16:22 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1208 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492631Ab0FBTOC (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:02 +0200
Received: (qmail 32007 invoked by uid 0); 2 Jun 2010 19:13:12 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:11 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Anton Vorontsov <cbouatmailru@gmail.com>
Subject: [RFC][PATCH 23/26] power: Add JZ4740 battery driver.
Date:   Wed,  2 Jun 2010 21:12:29 +0200
Message-Id: <1275505950-17334-7-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27025
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1635
Content-Length: 12154
Lines: 441

This patch adds support for the battery voltage measurement part of the JZ4740
ADC unit.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Anton Vorontsov <cbouatmailru@gmail.com>
---
 drivers/power/Kconfig                |   11 +
 drivers/power/Makefile               |    1 +
 drivers/power/jz4740-battery.c       |  359 ++++++++++++++++++++++++++++++++++
 include/linux/power/jz4740-battery.h |   24 +++
 4 files changed, 395 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/jz4740-battery.c
 create mode 100644 include/linux/power/jz4740-battery.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8e9ba17..80bbd0d 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -142,4 +142,15 @@ config CHARGER_PCF50633
 	help
 	 Say Y to include support for NXP PCF50633 Main Battery Charger.
 
+config BATTERY_JZ4740
+	tristate "Ingenic JZ4740 battery"
+	depends on MACH_JZ4740
+	depends on SENSORS_JZ4740
+	help
+	  Say Y to enable support for the battery on Ingenic JZ4740 based
+	  boards.
+
+	  This driver can be build as a module. If so, the module will be
+	  called jz4740-battery.
+
 endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0005080..cf95009 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_BATTERY_DA9030)	+= da9030_battery.o
 obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
 obj-$(CONFIG_BATTERY_Z2)	+= z2_battery.o
 obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
+obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
new file mode 100644
index 0000000..9eadb36
--- /dev/null
+++ b/drivers/power/jz4740-battery.c
@@ -0,0 +1,359 @@
+/*
+ * Battery measurement code for Ingenic JZ SOC.
+ *
+ * Copyright (C) 2009 Jiejing Zhang <kzjeef@gmail.com>
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * based on tosa_battery.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
+*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/power_supply.h>
+
+#include <linux/power/jz4740-battery.h>
+#include <linux/jz4740-adc.h>
+
+struct jz_battery {
+	struct jz_battery_platform_data *pdata;
+
+	int charge_irq;
+
+	int status;
+	long voltage;
+
+	struct power_supply battery;
+	struct delayed_work work;
+};
+
+static inline struct jz_battery *psy_to_jz_battery(struct power_supply *psy)
+{
+	return container_of(psy, struct jz_battery, battery);
+}
+
+static long jz_battery_read_voltage(struct jz_battery *jz_battery)
+{
+	struct device *adc = jz_battery->battery.dev->parent->parent;
+	enum jz_adc_battery_scale scale;
+
+	if (jz_battery->pdata->info.voltage_max_design > 2500000)
+		scale = JZ_ADC_BATTERY_SCALE_7V5;
+	else
+		scale = JZ_ADC_BATTERY_SCALE_2V5;
+
+	return jz4740_adc_read_battery_voltage(adc, scale);
+}
+
+static int jz_battery_get_capacity(struct power_supply *psy)
+{
+	struct jz_battery *jz_battery = psy_to_jz_battery(psy);
+	struct power_supply_info *info = &jz_battery->pdata->info;
+	long voltage;
+	int ret;
+	int voltage_span;
+
+	voltage = jz_battery_read_voltage(jz_battery);
+
+	if (voltage < 0)
+		return voltage;
+
+	voltage_span = info->voltage_max_design - info->voltage_min_design;
+	ret = ((voltage - info->voltage_min_design) * 100) / voltage_span;
+
+	if (ret > 100)
+		ret = 100;
+	else if (ret < 0)
+		ret = 0;
+
+	return ret;
+}
+
+static int jz_battery_get_property(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct jz_battery *jz_battery = psy_to_jz_battery(psy);
+	struct power_supply_info *info = &jz_battery->pdata->info;
+	long voltage;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = jz_battery->status;
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = jz_battery->pdata->info.technology;
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		voltage = jz_battery_read_voltage(jz_battery);
+		if (voltage < info->voltage_min_design)
+			val->intval = POWER_SUPPLY_HEALTH_DEAD;
+		else
+			val->intval = POWER_SUPPLY_HEALTH_GOOD;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		val->intval = jz_battery_get_capacity(psy);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = jz_battery_read_voltage(jz_battery);
+		if (val->intval < 0)
+			return val->intval;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		val->intval = info->voltage_max_design;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+		val->intval = info->voltage_min_design;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void jz_battery_external_power_changed(struct power_supply *psy)
+{
+	struct jz_battery *jz_battery = psy_to_jz_battery(psy);
+
+	cancel_delayed_work(&jz_battery->work);
+	schedule_delayed_work(&jz_battery->work, 0);
+}
+
+static irqreturn_t jz_battery_charge_irq(int irq, void *data)
+{
+	struct jz_battery *jz_battery = data;
+
+	cancel_delayed_work(&jz_battery->work);
+	schedule_delayed_work(&jz_battery->work, 0);
+
+	return IRQ_HANDLED;
+}
+
+static void jz_battery_update(struct jz_battery *jz_battery)
+{
+	int status;
+	long voltage;
+	long voltage_difference;
+	bool has_changed = 0;
+
+	if (gpio_is_valid(jz_battery->pdata->gpio_charge)) {
+		int is_charging;
+
+		is_charging = gpio_get_value(jz_battery->pdata->gpio_charge);
+		is_charging ^= jz_battery->pdata->gpio_charge_active_low;
+		if (is_charging)
+			status = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+
+		if (status != jz_battery->status) {
+			jz_battery->status = status;
+			has_changed = 1;
+		}
+	}
+
+	voltage = jz_battery_read_voltage(jz_battery);
+	voltage_difference = voltage - jz_battery->voltage;
+	if (voltage_difference > 50000 || voltage_difference < 50000) {
+		jz_battery->voltage = voltage;
+		has_changed = 1;
+	}
+	if (has_changed)
+		power_supply_changed(&jz_battery->battery);
+}
+
+static enum power_supply_property jz_battery_properties[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_PRESENT,
+};
+
+static void jz_battery_work(struct work_struct *work)
+{
+	/* Too small interval will increase system workload */
+	const int interval = HZ * 30;
+	struct jz_battery *jz_battery = container_of(work, struct jz_battery,
+					    work.work);
+
+	jz_battery_update(jz_battery);
+	schedule_delayed_work(&jz_battery->work, interval);
+}
+
+static int __devinit jz_battery_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct jz_battery_platform_data *pdata = pdev->dev.platform_data;
+	struct jz_battery *jz_battery;
+	struct power_supply *battery;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL);
+
+	if (!jz_battery) {
+		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+		return -ENOMEM;
+	}
+
+	battery = &jz_battery->battery;
+	battery->name = pdata->info.name;
+	battery->type = POWER_SUPPLY_TYPE_BATTERY;
+	battery->properties	= jz_battery_properties;
+	battery->num_properties	= ARRAY_SIZE(jz_battery_properties);
+	battery->get_property = jz_battery_get_property;
+	battery->external_power_changed = jz_battery_external_power_changed;
+	battery->use_for_apm = 1;
+
+	jz_battery->pdata = pdata;
+
+	INIT_DELAYED_WORK(&jz_battery->work, jz_battery_work);
+
+	if (gpio_is_valid(pdata->gpio_charge)) {
+		ret = gpio_request(pdata->gpio_charge, dev_name(&pdev->dev));
+		if (ret) {
+			dev_err(&pdev->dev, "charger state gpio request failed.\n");
+			goto err_free;
+		}
+		ret = gpio_direction_input(pdata->gpio_charge);
+		if (ret) {
+			dev_err(&pdev->dev, "charger state gpio set direction failed.\n");
+			goto err_free_gpio;
+		}
+
+		jz_battery->charge_irq = gpio_to_irq(pdata->gpio_charge);
+
+		if (jz_battery->charge_irq >= 0) {
+			ret = request_irq(jz_battery->charge_irq,
+				    jz_battery_charge_irq,
+				    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				    dev_name(&pdev->dev), jz_battery);
+			if (ret) {
+				dev_err(&pdev->dev, "Failed to request charge irq: %d\n", ret);
+				goto err_free_gpio;
+			}
+		}
+	} else {
+		jz_battery->charge_irq = -1;
+	}
+
+
+	ret = power_supply_register(&pdev->dev, &jz_battery->battery);
+	if (ret) {
+		dev_err(&pdev->dev, "power supply battery register failed.\n");
+		goto err_free_irq;
+	}
+
+	platform_set_drvdata(pdev, jz_battery);
+	schedule_delayed_work(&jz_battery->work, 0);
+
+	return 0;
+
+err_free_irq:
+	if (jz_battery->charge_irq >= 0)
+		free_irq(jz_battery->charge_irq, jz_battery);
+err_free_gpio:
+	if (gpio_is_valid(pdata->gpio_charge))
+		gpio_free(jz_battery->pdata->gpio_charge);
+err_free:
+	kfree(jz_battery);
+	return ret;
+}
+
+static int __devexit jz_battery_remove(struct platform_device *pdev)
+{
+	struct jz_battery *jz_battery = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&jz_battery->work);
+
+	if (gpio_is_valid(jz_battery->pdata->gpio_charge)) {
+		if (jz_battery->charge_irq >= 0)
+			free_irq(jz_battery->charge_irq, jz_battery);
+		gpio_free(jz_battery->pdata->gpio_charge);
+	}
+
+	power_supply_unregister(&jz_battery->battery);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int jz_battery_suspend(struct device *dev)
+{
+	struct jz_battery *jz_battery = dev_get_drvdata(dev);
+
+	cancel_delayed_work_sync(&jz_battery->work);
+	jz_battery->status =  POWER_SUPPLY_STATUS_UNKNOWN;
+
+	return 0;
+}
+
+static int jz_battery_resume(struct device *dev)
+{
+	struct jz_battery *jz_battery = dev_get_drvdata(dev);
+
+	schedule_delayed_work(&jz_battery->work, 0);
+
+	return 0;
+}
+
+static const struct dev_pm_ops jz_battery_pm_ops = {
+	.suspend	= jz_battery_suspend,
+	.resume		= jz_battery_resume,
+};
+
+#define JZ_BATTERY_PM_OPS (&jz_battery_pm_ops)
+
+#else
+#define JZ_BATTERY_PM_OPS NULL
+#endif
+
+static struct platform_driver jz_battery_driver = {
+	.probe		= jz_battery_probe,
+	.remove		= __devexit_p(jz_battery_remove),
+	.driver = {
+		.name = "jz4740-battery",
+		.owner = THIS_MODULE,
+		.pm = JZ_BATTERY_PM_OPS,
+	},
+};
+
+static int __init jz_battery_init(void)
+{
+	return platform_driver_register(&jz_battery_driver);
+}
+module_init(jz_battery_init);
+
+static void __exit jz_battery_exit(void)
+{
+	platform_driver_unregister(&jz_battery_driver);
+}
+module_exit(jz_battery_exit);
+
+MODULE_ALIAS("platform:jz4740-battery");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("JZ4740 SoC battery driver");
diff --git a/include/linux/power/jz4740-battery.h b/include/linux/power/jz4740-battery.h
new file mode 100644
index 0000000..19c9610
--- /dev/null
+++ b/include/linux/power/jz4740-battery.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (C) 2009, Jiejing Zhang <kzjeef@gmail.com>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __JZ4740_BATTERY_H
+#define __JZ4740_BATTERY_H
+
+struct jz_battery_platform_data {
+	struct power_supply_info info;
+	int gpio_charge;	/* GPIO port of Charger state */
+	int gpio_charge_active_low;
+};
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:02 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:16:50 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1481 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492635Ab0FBTOC (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:02 +0200
Received: (qmail 32056 invoked by uid 0); 2 Jun 2010 19:13:12 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:12 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 24/26] MIPS: JZ4740: Add qi_lb60 board support
Date:   Wed,  2 Jun 2010 21:12:30 +0200
Message-Id: <1275505950-17334-8-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27026
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1636
Content-Length: 13697
Lines: 531

This patch adds support for the qi_lb60 (a.k.a QI Ben NanoNote) clamshell
device.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/jz4740/Kconfig         |    4 +
 arch/mips/jz4740/Makefile        |    2 +
 arch/mips/jz4740/board-qi_lb60.c |  483 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 489 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/jz4740/board-qi_lb60.c

diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 8a5e850..3e7141f 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -1,6 +1,10 @@
 choice
 	prompt "Machine type"
 	depends on MACH_JZ4740
+	default JZ4740_QI_LB60
+
+config JZ4740_QI_LB60
+	bool "Qi Hardware Ben NanoNote"
 
 endchoice
 
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index a803ccb..a604eae 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
 
 # board specific support
 
+obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi_lb60.o
+
 # PM support
 
 obj-$(CONFIG_PM) += pm.o
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
new file mode 100644
index 0000000..cd7e065
--- /dev/null
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -0,0 +1,483 @@
+/*
+ * linux/arch/mips/jz4740/board-qi_lb60.c
+ *
+ * QI_LB60 board support
+ *
+ * Copyright (c) 2009 Qi Hardware inc.,
+ * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
+ * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/jz4740_fb.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/power_supply.h>
+#include <linux/power/jz4740-battery.h>
+#include <linux/mmc/jz4740_mmc.h>
+
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/leds_pwm.h>
+
+#include <asm/mach-jz4740/platform.h>
+
+#include "clock.h"
+
+static bool is_avt2;
+
+/* GPIOs */
+#define QI_LB60_GPIO_SD_CD		JZ_GPIO_PORTD(0)
+#define QI_LB60_GPIO_SD_VCC_EN_N	JZ_GPIO_PORTD(2)
+
+#define QI_LB60_GPIO_KEYOUT(x)		(JZ_GPIO_PORTC(10) + (x))
+#define QI_LB60_GPIO_KEYIN(x)		(JZ_GPIO_PORTD(18) + (x))
+#define QI_LB60_GPIO_KEYIN8		JZ_GPIO_PORTD(26)
+
+/* NAND */
+static struct nand_ecclayout qi_lb60_ecclayout_1gb = {
+	.eccbytes = 36,
+	.eccpos = {
+		6,  7,  8,  9,  10, 11, 12, 13,
+		14, 15, 16, 17, 18, 19, 20, 21,
+		22, 23, 24, 25, 26, 27, 28, 29,
+		30, 31, 32, 33, 34, 35, 36, 37,
+		38, 39, 40, 41
+	},
+	.oobfree = {
+		{ .offset = 2, .length = 4 },
+		{ .offset = 42, .length = 22 }
+	},
+};
+
+/* Early prototypes of the QI LB60 had only 1GB of NAND.
+ * In order to support these devices aswell the partition and ecc layout is
+ * initalized depending on the NAND size */
+static struct mtd_partition qi_lb60_partitions_1gb[] = {
+	{
+		.name = "NAND BOOT partition",
+		.offset = 0 * 0x100000,
+		.size = 4 * 0x100000,
+	},
+	{
+		.name = "NAND KERNEL partition",
+		.offset = 4 * 0x100000,
+		.size = 4 * 0x100000,
+	},
+	{
+		.name = "NAND ROOTFS partition",
+		.offset = 8 * 0x100000,
+		.size = (504 + 512) * 0x100000,
+	},
+};
+
+static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
+	.eccbytes = 72,
+	.eccpos = {
+		12, 13, 14, 15, 16, 17, 18, 19,
+		20, 21, 22, 23, 24, 25, 26, 27,
+		28, 29, 30, 31, 32, 33, 34, 35,
+		36, 37, 38, 39, 40, 41, 42, 43,
+		44, 45, 46, 47, 48, 49, 50, 51,
+		52, 53, 54, 55, 56, 57, 58, 59,
+		60, 61, 62, 63, 64, 65, 66, 67,
+		68, 69, 70, 71, 72, 73, 74, 75,
+		76, 77, 78, 79, 80, 81, 82, 83
+	},
+	.oobfree = {
+		{ .offset = 2, .length = 10 },
+		{ .offset = 84, .length = 44 },
+	},
+};
+
+static struct mtd_partition qi_lb60_partitions_2gb[] = {
+	{
+		.name = "NAND BOOT partition",
+		.offset = 0 * 0x100000,
+		.size = 4 * 0x100000,
+	},
+	{
+		.name = "NAND KERNEL partition",
+		.offset = 4 * 0x100000,
+		.size = 4 * 0x100000,
+	},
+	{
+		.name = "NAND ROOTFS partition",
+		.offset = 8 * 0x100000,
+		.size = (504 + 512 + 1024) * 0x100000,
+	},
+};
+
+static void qi_lb60_nand_ident(struct platform_device *pdev,
+		struct nand_chip *chip, struct mtd_partition **partitions,
+		int *num_partitions)
+{
+	if (chip->page_shift == 12) {
+		chip->ecc.layout = &qi_lb60_ecclayout_2gb;
+		*partitions = qi_lb60_partitions_2gb;
+		*num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb);
+	} else {
+		chip->ecc.layout = &qi_lb60_ecclayout_1gb;
+		*partitions = qi_lb60_partitions_1gb;
+		*num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb);
+	}
+}
+
+static struct jz_nand_platform_data qi_lb60_nand_pdata = {
+	.ident_callback = qi_lb60_nand_ident,
+	.busy_gpio = 94,
+};
+
+/* Keyboard*/
+
+#define KEY_QI_QI	KEY_F13
+#define KEY_QI_UPRED	KEY_RIGHTALT
+#define KEY_QI_VOLUP	KEY_VOLUMEUP
+#define KEY_QI_VOLDOWN	KEY_VOLUMEDOWN
+#define KEY_QI_FN	KEY_LEFTCTRL
+
+static const uint32_t qi_lb60_keymap[] = {
+	KEY(0, 0, KEY_F1),	/* S2 */
+	KEY(0, 1, KEY_F2),	/* S3 */
+	KEY(0, 2, KEY_F3),	/* S4 */
+	KEY(0, 3, KEY_F4),	/* S5 */
+	KEY(0, 4, KEY_F5),	/* S6 */
+	KEY(0, 5, KEY_F6),	/* S7 */
+	KEY(0, 6, KEY_F7),	/* S8 */
+
+	KEY(1, 0, KEY_Q),	/* S10 */
+	KEY(1, 1, KEY_W),	/* S11 */
+	KEY(1, 2, KEY_E),	/* S12 */
+	KEY(1, 3, KEY_R),	/* S13 */
+	KEY(1, 4, KEY_T),	/* S14 */
+	KEY(1, 5, KEY_Y),	/* S15 */
+	KEY(1, 6, KEY_U),	/* S16 */
+	KEY(1, 7, KEY_I),	/* S17 */
+	KEY(2, 0, KEY_A),	/* S18 */
+	KEY(2, 1, KEY_S),	/* S19 */
+	KEY(2, 2, KEY_D),	/* S20 */
+	KEY(2, 3, KEY_F),	/* S21 */
+	KEY(2, 4, KEY_G),	/* S22 */
+	KEY(2, 5, KEY_H),	/* S23 */
+	KEY(2, 6, KEY_J),	/* S24 */
+	KEY(2, 7, KEY_K),	/* S25 */
+	KEY(3, 0, KEY_ESC),	/* S26 */
+	KEY(3, 1, KEY_Z),	/* S27 */
+	KEY(3, 2, KEY_X),	/* S28 */
+	KEY(3, 3, KEY_C),	/* S29 */
+	KEY(3, 4, KEY_V),	/* S30 */
+	KEY(3, 5, KEY_B),	/* S31 */
+	KEY(3, 6, KEY_N),	/* S32 */
+	KEY(3, 7, KEY_M),	/* S33 */
+	KEY(4, 0, KEY_TAB),	/* S34 */
+	KEY(4, 1, KEY_CAPSLOCK),	/* S35 */
+	KEY(4, 2, KEY_BACKSLASH),	/* S36 */
+	KEY(4, 3, KEY_APOSTROPHE),	/* S37 */
+	KEY(4, 4, KEY_COMMA),	/* S38 */
+	KEY(4, 5, KEY_DOT),	/* S39 */
+	KEY(4, 6, KEY_SLASH),	/* S40 */
+	KEY(4, 7, KEY_UP),	/* S41 */
+	KEY(5, 0, KEY_O),	/* S42 */
+	KEY(5, 1, KEY_L),	/* S43 */
+	KEY(5, 2, KEY_EQUAL),	/* S44 */
+	KEY(5, 3, KEY_QI_UPRED),	/* S45 */
+	KEY(5, 4, KEY_SPACE),	/* S46 */
+	KEY(5, 5, KEY_QI_QI),	/* S47 */
+	KEY(5, 6, KEY_RIGHTCTRL),	/* S48 */
+	KEY(5, 7, KEY_LEFT),	/* S49 */
+	KEY(6, 0, KEY_F8),	/* S50 */
+	KEY(6, 1, KEY_P),	/* S51 */
+	KEY(6, 2, KEY_BACKSPACE),/* S52 */
+	KEY(6, 3, KEY_ENTER),	/* S53 */
+	KEY(6, 4, KEY_QI_VOLUP),	/* S54 */
+	KEY(6, 5, KEY_QI_VOLDOWN),	/* S55 */
+	KEY(6, 6, KEY_DOWN),	/* S56 */
+	KEY(6, 7, KEY_RIGHT),	/* S57 */
+
+	KEY(7, 0, KEY_LEFTSHIFT),	/* S58 */
+	KEY(7, 1, KEY_LEFTALT),	/* S59 */
+	KEY(7, 2, KEY_QI_FN),	/* S60 */
+};
+
+static const struct matrix_keymap_data qi_lb60_keymap_data = {
+	.keymap		= qi_lb60_keymap,
+	.keymap_size	= ARRAY_SIZE(qi_lb60_keymap),
+};
+
+static const unsigned int qi_lb60_keypad_cols[] = {
+	QI_LB60_GPIO_KEYOUT(0),
+	QI_LB60_GPIO_KEYOUT(1),
+	QI_LB60_GPIO_KEYOUT(2),
+	QI_LB60_GPIO_KEYOUT(3),
+	QI_LB60_GPIO_KEYOUT(4),
+	QI_LB60_GPIO_KEYOUT(5),
+	QI_LB60_GPIO_KEYOUT(6),
+	QI_LB60_GPIO_KEYOUT(7),
+};
+
+static const unsigned int qi_lb60_keypad_rows[] = {
+	QI_LB60_GPIO_KEYIN(0),
+	QI_LB60_GPIO_KEYIN(1),
+	QI_LB60_GPIO_KEYIN(2),
+	QI_LB60_GPIO_KEYIN(3),
+	QI_LB60_GPIO_KEYIN(4),
+	QI_LB60_GPIO_KEYIN(5),
+	QI_LB60_GPIO_KEYIN(7),
+	QI_LB60_GPIO_KEYIN8,
+};
+
+static struct matrix_keypad_platform_data qi_lb60_pdata = {
+	.keymap_data = &qi_lb60_keymap_data,
+	.col_gpios	= qi_lb60_keypad_cols,
+	.row_gpios	= qi_lb60_keypad_rows,
+	.num_col_gpios	= ARRAY_SIZE(qi_lb60_keypad_cols),
+	.num_row_gpios	= ARRAY_SIZE(qi_lb60_keypad_rows),
+	.col_scan_delay_us	= 10,
+	.debounce_ms		= 10,
+	.wakeup			= 1,
+	.active_low		= 1,
+};
+
+static struct platform_device qi_lb60_keypad = {
+	.name		= "matrix-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &qi_lb60_pdata,
+	},
+};
+
+/* Display */
+static struct fb_videomode qi_lb60_video_modes[] = {
+	{
+		.name = "320x240",
+		.xres = 320,
+		.yres = 240,
+		.refresh = 30,
+		.left_margin = 140,
+		.right_margin = 273,
+		.upper_margin = 20,
+		.lower_margin = 2,
+		.hsync_len = 1,
+		.vsync_len = 1,
+		.sync = 0,
+		.vmode = FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct jz4740_fb_platform_data qi_lb60_fb_pdata = {
+	.width		= 60,
+	.height		= 45,
+	.num_modes	= ARRAY_SIZE(qi_lb60_video_modes),
+	.modes		= qi_lb60_video_modes,
+	.bpp		= 24,
+	.lcd_type	= JZ_LCD_TYPE_8BIT_SERIAL,
+	.pixclk_falling_edge = 1,
+};
+
+struct spi_gpio_platform_data spigpio_platform_data = {
+	.sck = JZ_GPIO_PORTC(23),
+	.mosi = JZ_GPIO_PORTC(22),
+	.miso = -1,
+	.num_chipselect = 1,
+};
+
+static struct platform_device spigpio_device = {
+	.name = "spi_gpio",
+	.id   = 1,
+	.dev = {
+		.platform_data = &spigpio_platform_data,
+	},
+};
+
+static struct spi_board_info qi_lb60_spi_board_info[] = {
+	{
+		.modalias = "ili8960",
+		.controller_data = (void *)JZ_GPIO_PORTC(21),
+		.chip_select = 0,
+		.bus_num = 1,
+		.max_speed_hz = 30 * 1000,
+		.mode = SPI_3WIRE,
+	},
+};
+
+/* Battery */
+static struct jz_battery_platform_data qi_lb60_battery_pdata = {
+	.gpio_charge =  JZ_GPIO_PORTC(27),
+	.gpio_charge_active_low = 1,
+	.info = {
+		.name = "battery",
+		.technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
+		.voltage_max_design = 4200000,
+		.voltage_min_design = 3600000,
+	},
+};
+
+/* GPIO Key: power */
+static struct gpio_keys_button qi_lb60_gpio_keys_buttons[] = {
+	[0] = {
+		.code		= KEY_POWER,
+		.gpio		= JZ_GPIO_PORTD(29),
+		.active_low	= 1,
+		.desc		= "Power",
+		.wakeup		= 1,
+	},
+};
+
+static struct gpio_keys_platform_data qi_lb60_gpio_keys_data = {
+	.nbuttons = ARRAY_SIZE(qi_lb60_gpio_keys_buttons),
+	.buttons = qi_lb60_gpio_keys_buttons,
+};
+
+static struct platform_device qi_lb60_gpio_keys = {
+	.name =	"gpio-keys",
+	.id =	-1,
+	.dev = {
+		.platform_data = &qi_lb60_gpio_keys_data,
+	}
+};
+
+static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = {
+	.gpio_card_detect	= QI_LB60_GPIO_SD_CD,
+	.gpio_read_only		= -1,
+	.gpio_power		= QI_LB60_GPIO_SD_VCC_EN_N,
+	.power_active_low	= 1,
+};
+
+/* OHCI */
+static struct regulator_consumer_supply avt2_usb_regulator_consumer =
+	REGULATOR_SUPPLY("vbus", "jz4740-ohci");
+
+static struct regulator_init_data avt2_usb_regulator_init_data = {
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &avt2_usb_regulator_consumer,
+	.constraints = {
+		.name = "USB power",
+		.min_uV = 5000000,
+		.max_uV = 5000000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct fixed_voltage_config avt2_usb_regulator_data = {
+	.supply_name = "USB power",
+	.microvolts = 5000000,
+	.gpio = JZ_GPIO_PORTB(17),
+	.init_data = &avt2_usb_regulator_init_data,
+};
+
+static struct platform_device avt2_usb_regulator_device = {
+	.name = "reg-fixed-voltage",
+	.id = -1,
+	.dev = {
+		.platform_data = &avt2_usb_regulator_data,
+	}
+};
+
+/* pizo */
+static struct led_pwm qi_lb60_pizo_led = {
+	.name = "nanonote::pizo",
+	.pwm_id = 4,
+	.max_brightness = 255,
+	.pwm_period_ns = 1000000,
+};
+
+static struct led_pwm_platform_data qi_lb60_pizo_data = {
+	.num_leds = 1,
+	.leds = &qi_lb60_pizo_led,
+};
+
+static struct platform_device qi_lb60_pizo_device = {
+	.name = "leds_pwm",
+	.id = -1,
+	.dev = {
+		.platform_data = &qi_lb60_pizo_data,
+	}
+};
+
+static struct platform_device *jz_platform_devices[] __initdata = {
+	&jz4740_udc_device,
+	&jz4740_mmc_device,
+	&jz4740_nand_device,
+	&qi_lb60_keypad,
+	&spigpio_device,
+	&jz4740_framebuffer_device,
+	&jz4740_i2s_device,
+	&jz4740_codec_device,
+	&jz4740_rtc_device,
+	&jz4740_adc_device,
+	&jz4740_battery_device,
+	&qi_lb60_gpio_keys,
+	&qi_lb60_pizo_device,
+};
+
+static void __init board_gpio_setup(void)
+{
+	/* We only need to enable/disable pullup here for pins used in generic
+	 * drivers. Everything else is done by the drivers themselfs. */
+	jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N);
+	jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD);
+}
+
+static int __init qi_lb60_init_platform_devices(void)
+{
+	jz4740_framebuffer_device.dev.platform_data = &qi_lb60_fb_pdata;
+	jz4740_nand_device.dev.platform_data = &qi_lb60_nand_pdata;
+	jz4740_battery_device.dev.platform_data = &qi_lb60_battery_pdata;
+	jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata;
+
+	jz4740_serial_device_register();
+
+	spi_register_board_info(qi_lb60_spi_board_info,
+				ARRAY_SIZE(qi_lb60_spi_board_info));
+
+	if (is_avt2) {
+		platform_device_register(&avt2_usb_regulator_device);
+		platform_device_register(&jz4740_usb_ohci_device);
+	}
+
+	return platform_add_devices(jz_platform_devices,
+					ARRAY_SIZE(jz_platform_devices));
+
+}
+
+struct jz4740_clock_board_data jz4740_clock_bdata = {
+	.ext_rate = 12000000,
+	.rtc_rate = 32768,
+};
+
+static __init int board_avt2(char *str)
+{
+	qi_lb60_mmc_pdata.card_detect_active_low = 1;
+	is_avt2 = true;
+
+	return 1;
+}
+__setup("avt2", board_avt2);
+
+static int __init qi_lb60_board_setup(void)
+{
+	printk(KERN_INFO "Qi Hardware JZ4740 QI %s setup\n",
+		is_avt2 ? "AVT2" : "LB60");
+
+	board_gpio_setup();
+
+	if (qi_lb60_init_platform_devices())
+		panic("Failed to initalize platform devices\n");
+
+	return 0;
+}
+arch_initcall(qi_lb60_board_setup);
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:06 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:17:19 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1577 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492621Ab0FBTOG (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:06 +0200
Received: (qmail 31776 invoked by uid 0); 2 Jun 2010 19:13:09 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:08 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Greg Kroah-Hartman <gregkh@suse.de>,
        David Brownell <dbrownell@users.sourceforge.net>,
        linux-usb@vger.kernel.org
Subject: [RFC][PATCH 19/26] USB: Add JZ4740 ohci support
Date:   Wed,  2 Jun 2010 21:12:25 +0200
Message-Id: <1275505950-17334-3-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27027
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1637
Content-Length: 7500
Lines: 314

This patch adds ohci glue code for JZ4740 SoCs ohci module.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-usb@vger.kernel.org
---
 drivers/usb/Kconfig            |    1 +
 drivers/usb/host/ohci-hcd.c    |    5 +
 drivers/usb/host/ohci-jz4740.c |  264 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 270 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/host/ohci-jz4740.c

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 6a58cb1..39a6bfd 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -46,6 +46,7 @@ config USB_ARCH_HAS_OHCI
 	default y if PPC_MPC52xx
 	# MIPS:
 	default y if SOC_AU1X00
+	default y if MACH_JZ4740
 	# SH:
 	default y if CPU_SUBTYPE_SH7720
 	default y if CPU_SUBTYPE_SH7721
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index fc57655..05b071c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1095,6 +1095,11 @@ MODULE_LICENSE ("GPL");
 #define TMIO_OHCI_DRIVER	ohci_hcd_tmio_driver
 #endif
 
+#ifdef CONFIG_MACH_JZ4740
+#include "ohci-jz4740.c"
+#define PLATFORM_DRIVER	ohci_hcd_jz4740_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
new file mode 100644
index 0000000..0371b17
--- /dev/null
+++ b/drivers/usb/host/ohci-jz4740.c
@@ -0,0 +1,264 @@
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+struct jz4740_ohci_hcd {
+	struct ohci_hcd ohci_hcd;
+
+	struct regulator *vbus;
+	bool vbus_enabled;
+	struct clk *clk;
+};
+
+static inline struct jz4740_ohci_hcd *hcd_to_jz4740_hcd(struct usb_hcd *hcd)
+{
+	return (struct jz4740_ohci_hcd *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *jz4740_hcd_to_hcd(struct jz4740_ohci_hcd *jz4740_ohci)
+{
+	return container_of((void *)jz4740_ohci, struct usb_hcd, hcd_priv);
+}
+
+static int ohci_jz4740_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int	ret;
+
+	ret = ohci_init(ohci);
+	if (ret < 0)
+		return ret;
+
+	ohci->num_ports = 1;
+
+	ret = ohci_run(ohci);
+	if (ret < 0) {
+		dev_err(hcd->self.controller, "Can not start %s",
+			hcd->self.bus_name);
+		ohci_stop(hcd);
+		return ret;
+	}
+	return 0;
+}
+
+static int ohci_jz4740_set_vbus_power(struct jz4740_ohci_hcd *jz4740_ohci,
+	bool enabled)
+{
+	int ret = 0;
+
+	if (!jz4740_ohci->vbus)
+		return 0;
+
+	if (enabled && !jz4740_ohci->vbus_enabled) {
+		ret = regulator_enable(jz4740_ohci->vbus);
+		if (ret)
+			dev_err(jz4740_hcd_to_hcd(jz4740_ohci)->self.controller,
+				"Could not power vbus\n");
+	} else if (!enabled && jz4740_ohci->vbus_enabled) {
+		ret = regulator_disable(jz4740_ohci->vbus);
+	}
+
+	if (ret == 0)
+		jz4740_ohci->vbus_enabled = enabled;
+
+	return ret;
+}
+
+static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+	u16 wIndex, char *buf, u16 wLength)
+{
+	struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
+	int ret;
+
+	switch (typeReq) {
+	case SetHubFeature:
+		if (wValue == USB_PORT_FEAT_POWER)
+			ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true);
+		break;
+	case ClearHubFeature:
+		if (wValue == USB_PORT_FEAT_POWER)
+			ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false);
+		break;
+	}
+
+	if (ret)
+		return ret;
+
+	return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+}
+
+
+static const struct hc_driver ohci_jz4740_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"JZ4740 OHCI",
+	.hcd_priv_size =	sizeof(struct jz4740_ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start =		ohci_jz4740_start,
+	.stop =			ohci_stop,
+	.shutdown =		ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_jz4740_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+
+static __devinit int jz4740_ohci_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct usb_hcd *hcd;
+	struct jz4740_ohci_hcd *jz4740_ohci;
+	struct resource *res;
+	int irq;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get platform resource\n");
+		return -ENOENT;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Failed to get platform irq\n");
+		return irq;
+	}
+
+	hcd = usb_create_hcd(&ohci_jz4740_hc_driver, &pdev->dev, "jz4740");
+	if (!hcd) {
+		dev_err(&pdev->dev, "Failed to create hcd.\n");
+		return -ENOMEM;
+	}
+
+	jz4740_ohci = hcd_to_jz4740_hcd(hcd);
+
+	res = request_mem_region(res->start, resource_size(res), hcd_name);
+
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to request mem region.\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = ioremap(res->start, resource_size(res));
+
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "Failed to ioremap registers.\n");
+		ret = -EBUSY;
+		goto err_release_mem;
+	}
+
+	jz4740_ohci->clk = clk_get(&pdev->dev, "uhc");
+	if (IS_ERR(jz4740_ohci->clk)) {
+		ret = PTR_ERR(jz4740_ohci->clk);
+		dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
+		goto err_iounmap;
+	}
+
+	jz4740_ohci->vbus = regulator_get(&pdev->dev, "vbus");
+	if (IS_ERR(jz4740_ohci->vbus))
+		jz4740_ohci->vbus = NULL;
+
+
+	clk_set_rate(jz4740_ohci->clk, 48000000);
+	clk_enable(jz4740_ohci->clk);
+	if (jz4740_ohci->vbus)
+		ohci_jz4740_set_vbus_power(jz4740_ohci, true);
+
+	platform_set_drvdata(pdev, hcd);
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret);
+		goto err_disable;
+	}
+
+	return 0;
+
+err_disable:
+	platform_set_drvdata(pdev, NULL);
+	if (jz4740_ohci->vbus) {
+		regulator_disable(jz4740_ohci->vbus);
+		regulator_put(jz4740_ohci->vbus);
+	}
+	clk_disable(jz4740_ohci->clk);
+
+	clk_put(jz4740_ohci->clk);
+err_iounmap:
+	iounmap(hcd->regs);
+err_release_mem:
+	release_mem_region(res->start, resource_size(res));
+err_free:
+	usb_put_hcd(hcd);
+
+	return ret;
+}
+
+static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
+
+	usb_remove_hcd(hcd);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (jz4740_ohci->vbus) {
+		regulator_disable(jz4740_ohci->vbus);
+		regulator_put(jz4740_ohci->vbus);
+	}
+
+	clk_disable(jz4740_ohci->clk);
+	clk_put(jz4740_ohci->clk);
+
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver ohci_hcd_jz4740_driver = {
+	.probe = jz4740_ohci_probe,
+	.remove = __devexit_p(jz4740_ohci_remove),
+	.driver = {
+		.name = "jz4740-ohci",
+		.owner = THIS_MODULE,
+	},
+};
+
+MODULE_ALIAS("platfrom:jz4740-ohci");
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:14:06 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:17:48 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1583 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492639Ab0FBTOG (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:14:06 +0200
Received: (qmail 31914 invoked by uid 0); 2 Jun 2010 19:13:10 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 31322
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.81 with SMTP; 2 Jun 2010 19:13:10 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
Date:   Wed,  2 Jun 2010 21:12:27 +0200
Message-Id: <1275505950-17334-5-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27028
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1640
Content-Length: 27671
Lines: 1063

This patch adds ASoC support for JZ4740 SoCs I2S module.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
Cc: alsa-devel@alsa-project.org
---
 sound/soc/Kconfig             |    1 +
 sound/soc/Makefile            |    1 +
 sound/soc/jz4740/Kconfig      |   13 +
 sound/soc/jz4740/Makefile     |    9 +
 sound/soc/jz4740/jz4740-i2s.c |  568 +++++++++++++++++++++++++++++++++++++++++
 sound/soc/jz4740/jz4740-i2s.h |   18 ++
 sound/soc/jz4740/jz4740-pcm.c |  350 +++++++++++++++++++++++++
 sound/soc/jz4740/jz4740-pcm.h |   22 ++
 8 files changed, 982 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/jz4740/Kconfig
 create mode 100644 sound/soc/jz4740/Makefile
 create mode 100644 sound/soc/jz4740/jz4740-i2s.c
 create mode 100644 sound/soc/jz4740/jz4740-i2s.h
 create mode 100644 sound/soc/jz4740/jz4740-pcm.c
 create mode 100644 sound/soc/jz4740/jz4740-pcm.h

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index b1749bc..5a7a724 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -36,6 +36,7 @@ source "sound/soc/s3c24xx/Kconfig"
 source "sound/soc/s6000/Kconfig"
 source "sound/soc/sh/Kconfig"
 source "sound/soc/txx9/Kconfig"
+source "sound/soc/jz4740/Kconfig"
 
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 1470141..fdbe74d 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_SND_SOC)	+= s3c24xx/
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= sh/
 obj-$(CONFIG_SND_SOC)	+= txx9/
+obj-$(CONFIG_SND_SOC)	+= jz4740/
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
new file mode 100644
index 0000000..39df949
--- /dev/null
+++ b/sound/soc/jz4740/Kconfig
@@ -0,0 +1,13 @@
+config SND_JZ4740_SOC
+	tristate "SoC Audio for Ingenic JZ4740 SoC"
+	depends on SOC_JZ4740 && SND_SOC
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the Jz4740 AC97, I2S or SSP interface. You will also need
+	  to select the audio interfaces to support below.
+
+config SND_JZ4740_SOC_I2S
+	depends on SND_JZ4740_SOC
+	tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip"
+	help
+	  Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 QI_LB60 board.
diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
new file mode 100644
index 0000000..1be8d19
--- /dev/null
+++ b/sound/soc/jz4740/Makefile
@@ -0,0 +1,9 @@
+#
+# Jz4740 Platform Support
+#
+snd-soc-jz4740-objs := jz4740-pcm.o
+snd-soc-jz4740-i2s-objs := jz4740-i2s.o
+
+obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
+obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
+
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
new file mode 100644
index 0000000..2b139fd
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -0,0 +1,568 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "jz4740-i2s.h"
+#include "jz4740-pcm.h"
+
+#define JZ_REG_AIC_CONF		0x00
+#define JZ_REG_AIC_CTRL		0x04
+#define JZ_REG_AIC_I2S_FMT	0x10
+#define JZ_REG_AIC_FIFO_STATUS	0x14
+#define JZ_REG_AIC_I2S_STATUS	0x1c
+#define JZ_REG_AIC_CLK_DIV	0x30
+#define JZ_REG_AIC_FIFO		0x34
+
+#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_MASK (0xf << 12)
+#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_MASK (0xf <<  8)
+#define JZ_AIC_CONF_OVERFLOW_PLAY_LAST BIT(6)
+#define JZ_AIC_CONF_INTERNAL_CODEC BIT(5)
+#define JZ_AIC_CONF_I2S BIT(4)
+#define JZ_AIC_CONF_RESET BIT(3)
+#define JZ_AIC_CONF_BIT_CLK_MASTER BIT(2)
+#define JZ_AIC_CONF_SYNC_CLK_MASTER BIT(1)
+#define JZ_AIC_CONF_ENABLE BIT(0)
+
+#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12
+#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8
+
+#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19)
+#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16)
+#define JZ_AIC_CTRL_ENABLE_RX_DMA BIT(15)
+#define JZ_AIC_CTRL_ENABLE_TX_DMA BIT(14)
+#define JZ_AIC_CTRL_MONO_TO_STEREO BIT(11)
+#define JZ_AIC_CTRL_SWITCH_ENDIANNESS BIT(10)
+#define JZ_AIC_CTRL_SIGNED_TO_UNSIGNED BIT(9)
+#define JZ_AIC_CTRL_FLUSH		BIT(8)
+#define JZ_AIC_CTRL_ENABLE_ROR_INT BIT(6)
+#define JZ_AIC_CTRL_ENABLE_TUR_INT BIT(5)
+#define JZ_AIC_CTRL_ENABLE_RFS_INT BIT(4)
+#define JZ_AIC_CTRL_ENABLE_TFS_INT BIT(3)
+#define JZ_AIC_CTRL_ENABLE_LOOPBACK BIT(2)
+#define JZ_AIC_CTRL_ENABLE_PLAYBACK BIT(1)
+#define JZ_AIC_CTRL_ENABLE_CAPTURE BIT(0)
+
+#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET 19
+#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET  16
+
+#define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12)
+#define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4)
+#define JZ_AIC_I2S_FMT_MSB BIT(0)
+
+#define JZ_AIC_I2S_STATUS_BUSY BIT(2)
+
+#define JZ_AIC_CLK_DIV_MASK 0xf
+
+struct jz4740_i2s {
+	struct resource *mem;
+	void __iomem *base;
+	dma_addr_t phys_base;
+
+	struct clk *clk_aic;
+	struct clk *clk_i2s;
+
+	struct jz4740_pcm_config pcm_config_playback;
+	struct jz4740_pcm_config pcm_config_capture;
+};
+
+static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
+	unsigned int reg)
+{
+	return readl(i2s->base + reg);
+}
+
+static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,
+	unsigned int reg, uint32_t value)
+{
+	writel(value, i2s->base + reg);
+}
+
+static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai)
+{
+	return dai->private_data;
+}
+
+static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	uint32_t conf, ctrl;
+
+	if (dai->active)
+		return 0;
+
+
+	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
+	ctrl |= JZ_AIC_CTRL_FLUSH;
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
+
+	clk_enable(i2s->clk_i2s);
+
+	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
+	conf |= JZ_AIC_CONF_ENABLE;
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
+
+	return 0;
+}
+
+static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	uint32_t conf;
+
+	if (!dai->active)
+		return;
+
+	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
+	conf &= ~JZ_AIC_CONF_ENABLE;
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
+
+	clk_disable(i2s->clk_i2s);
+}
+
+
+static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+	struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+
+	uint32_t ctrl;
+	uint32_t mask;
+
+	if (playback)
+		mask = JZ_AIC_CTRL_ENABLE_PLAYBACK | JZ_AIC_CTRL_ENABLE_TX_DMA;
+	else
+		mask = JZ_AIC_CTRL_ENABLE_CAPTURE | JZ_AIC_CTRL_ENABLE_RX_DMA;
+
+	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		ctrl |= mask;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		ctrl &= ~mask;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
+
+	return 0;
+}
+
+
+static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+
+	uint32_t format = 0;
+	uint32_t conf;
+
+	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
+
+	conf &= ~(JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER);
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER;
+		format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		conf |= JZ_AIC_CONF_SYNC_CLK_MASTER;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+		conf |= JZ_AIC_CONF_BIT_CLK_MASTER;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_MSB:
+		format |= JZ_AIC_I2S_FMT_MSB;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
+	jz4740_i2s_write(i2s, JZ_REG_AIC_I2S_FMT, format);
+
+	return 0;
+}
+
+static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+	enum jz4740_dma_width dma_width;
+	struct jz4740_pcm_config *pcm_config;
+	unsigned int sample_size;
+	uint32_t ctrl;
+
+	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		sample_size = 0;
+		dma_width = JZ4740_DMA_WIDTH_8BIT;
+		break;
+	case SNDRV_PCM_FORMAT_S16:
+		sample_size = 1;
+		dma_width = JZ4740_DMA_WIDTH_16BIT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (playback) {
+		ctrl &= ~JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK;
+		ctrl |= sample_size << JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET;
+	} else {
+		ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
+		ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
+	}
+
+	switch (params_channels(params)) {
+	case 2:
+		break;
+	case 1:
+		if (playback) {
+			ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
+			break;
+		}
+	default: /* Falltrough */
+		return -EINVAL;
+	}
+
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
+
+	if (playback) {
+		pcm_config = &i2s->pcm_config_playback;
+		pcm_config->dma_config.dst_width = dma_width;
+	} else {
+		pcm_config = &i2s->pcm_config_capture;
+		pcm_config->dma_config.src_width = dma_width;
+	}
+
+
+	snd_soc_dai_set_dma_data(dai, substream, pcm_config);
+
+	return 0;
+}
+
+static int jz4740_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+
+	switch (div_id) {
+	case JZ4740_I2S_BIT_CLK:
+		if (div & 1 || div > 16)
+			return -EINVAL;
+		jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div - 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+	unsigned int freq, int dir)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	int ret = 0;
+	struct clk *parent;
+
+	switch (clk_id) {
+	case JZ4740_I2S_CLKSRC_EXT:
+		parent = clk_get(NULL, "ext");
+		clk_set_parent(i2s->clk_i2s, parent);
+		break;
+	case JZ4740_I2S_CLKSRC_PLL:
+		parent = clk_get(NULL, "pll half");
+		clk_set_parent(i2s->clk_i2s, parent);
+		ret = clk_set_rate(i2s->clk_i2s, freq);
+		break;
+	default:
+		return -EINVAL;
+	}
+	clk_put(parent);
+
+	return ret;
+}
+
+static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	uint32_t conf;
+
+	if (dai->active) {
+		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
+		conf &= ~JZ_AIC_CONF_ENABLE;
+		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
+
+		clk_disable(i2s->clk_i2s);
+	}
+
+	clk_disable(i2s->clk_aic);
+
+	return 0;
+}
+
+static int jz4740_i2s_resume(struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	uint32_t conf;
+
+	clk_enable(i2s->clk_aic);
+
+	if (dai->active) {
+		clk_enable(i2s->clk_i2s);
+
+		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
+		conf |= JZ_AIC_CONF_ENABLE;
+		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
+
+	}
+
+	return 0;
+}
+
+static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
+{
+	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+	uint32_t conf;
+
+	conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
+		(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
+		JZ_AIC_CONF_OVERFLOW_PLAY_LAST |
+		JZ_AIC_CONF_I2S |
+		JZ_AIC_CONF_INTERNAL_CODEC;
+
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET);
+	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
+
+	return 0;
+}
+
+
+static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
+	.startup = jz4740_i2s_startup,
+	.shutdown = jz4740_i2s_shutdown,
+	.trigger = jz4740_i2s_trigger,
+	.hw_params = jz4740_i2s_hw_params,
+	.set_fmt = jz4740_i2s_set_fmt,
+	.set_clkdiv = jz4740_i2s_set_clkdiv,
+	.set_sysclk = jz4740_i2s_set_sysclk,
+};
+
+#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
+		SNDRV_PCM_FMTBIT_S16_LE)
+
+struct snd_soc_dai jz4740_i2s_dai = {
+	.name = "jz4740-i2s",
+	.probe = jz4740_i2s_probe,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = JZ4740_I2S_FMTS,
+	},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = JZ4740_I2S_FMTS,
+	},
+	.symmetric_rates = 1,
+	.ops = &jz4740_i2s_dai_ops,
+	.suspend = jz4740_i2s_suspend,
+	.resume = jz4740_i2s_resume,
+};
+EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
+
+static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
+{
+	struct jz4740_dma_config *dma_config;
+
+	/* Playback */
+	dma_config = &i2s->pcm_config_playback.dma_config;
+	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
+	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
+	dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
+	dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
+	dma_config->mode = JZ4740_DMA_MODE_SINGLE;
+	i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+
+	/* Capture */
+	dma_config = &i2s->pcm_config_capture.dma_config;
+	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
+	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
+	dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
+	dma_config->flags = JZ4740_DMA_DST_AUTOINC;
+	dma_config->mode = JZ4740_DMA_MODE_SINGLE;
+	i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+}
+
+static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
+{
+	struct jz4740_i2s *i2s;
+	int ret;
+
+	i2s = kzalloc(sizeof(*i2s), GFP_KERNEL);
+
+	if (!i2s)
+		return -ENOMEM;
+
+	i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!i2s->mem) {
+		ret = -ENOENT;
+		goto err_free;
+	}
+
+	i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem),
+				pdev->name);
+
+	if (!i2s->mem) {
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem));
+
+	if (!i2s->base) {
+		ret = -EBUSY;
+		goto err_release_mem_region;
+	}
+
+	i2s->phys_base = i2s->mem->start;
+
+	i2s->clk_aic = clk_get(&pdev->dev, "aic");
+	if (IS_ERR(i2s->clk_aic)) {
+		ret = PTR_ERR(i2s->clk_aic);
+		goto err_iounmap;
+	}
+
+	i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
+	if (IS_ERR(i2s->clk_i2s)) {
+		ret = PTR_ERR(i2s->clk_i2s);
+		goto err_iounmap;
+	}
+
+	clk_enable(i2s->clk_aic);
+
+	jz4740_i2c_init_pcm_config(i2s);
+
+	jz4740_i2s_dai.private_data = i2s;
+	ret = snd_soc_register_dai(&jz4740_i2s_dai);
+
+	platform_set_drvdata(pdev, i2s);
+
+	return 0;
+
+err_iounmap:
+	iounmap(i2s->base);
+err_release_mem_region:
+	release_mem_region(i2s->mem->start, resource_size(i2s->mem));
+err_free:
+	kfree(i2s);
+
+	return ret;
+}
+
+static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
+{
+	struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_dai(&jz4740_i2s_dai);
+
+	clk_disable(i2s->clk_aic);
+	clk_put(i2s->clk_i2s);
+	clk_put(i2s->clk_aic);
+
+	iounmap(i2s->base);
+	release_mem_region(i2s->mem->start, resource_size(i2s->mem));
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(i2s);
+
+	return 0;
+}
+
+static struct platform_driver jz4740_i2s_driver = {
+	.probe = jz4740_i2s_dev_probe,
+	.remove = __devexit_p(jz4740_i2s_dev_remove),
+	.driver = {
+		.name = "jz4740-i2s",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init jz4740_i2s_init(void)
+{
+	return platform_driver_register(&jz4740_i2s_driver);
+}
+module_init(jz4740_i2s_init);
+
+static void __exit jz4740_i2s_exit(void)
+{
+	platform_driver_unregister(&jz4740_i2s_driver);
+}
+module_exit(jz4740_i2s_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
+MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:jz4740-i2s");
diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h
new file mode 100644
index 0000000..da22ed8
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-i2s.h
@@ -0,0 +1,18 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _JZ4740_I2S_H
+#define _JZ4740_I2S_H
+
+/* I2S clock source */
+#define JZ4740_I2S_CLKSRC_EXT 0
+#define JZ4740_I2S_CLKSRC_PLL 1
+
+#define JZ4740_I2S_BIT_CLK		0
+
+extern struct snd_soc_dai jz4740_i2s_dai;
+
+#endif
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
new file mode 100644
index 0000000..fd1c203
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -0,0 +1,350 @@
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/mach-jz4740/dma.h>
+#include "jz4740-pcm.h"
+
+struct jz4740_runtime_data {
+	unsigned int dma_period;
+	dma_addr_t dma_start;
+	dma_addr_t dma_pos;
+	dma_addr_t dma_end;
+
+	struct jz4740_dma_chan *dma;
+
+	dma_addr_t fifo_addr;
+};
+
+/* identify hardware playback capabilities */
+static const struct snd_pcm_hardware jz4740_pcm_hardware = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
+
+	.rates			= SNDRV_PCM_RATE_8000_48000,
+	.channels_min		= 1,
+	.channels_max		= 2,
+	.period_bytes_min	= 16,
+	.period_bytes_max	= 2 * PAGE_SIZE,
+	.periods_min		= 2,
+	.periods_max		= 128,
+	.buffer_bytes_max	= 128 * 2 * PAGE_SIZE,
+	.fifo_size		= 32,
+};
+
+static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd, int stream)
+{
+	unsigned int count;
+
+	if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
+		count = prtd->dma_end - prtd->dma_pos;
+	else
+		count = prtd->dma_period;
+
+	jz4740_dma_disable(prtd->dma);
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
+		jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
+	} else {
+		jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
+		jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
+	}
+
+	jz4740_dma_set_transfer_count(prtd->dma, count);
+
+	jz4740_dma_enable(prtd->dma);
+
+	prtd->dma_pos += prtd->dma_period;
+	if (prtd->dma_pos >= prtd->dma_end)
+		prtd->dma_pos = prtd->dma_start;
+}
+
+static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
+	void *dev_id)
+{
+	struct snd_pcm_substream *substream = dev_id;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct jz4740_runtime_data *prtd = runtime->private_data;
+
+	snd_pcm_period_elapsed(substream);
+
+	jz4740_pcm_start_transfer(prtd, substream->stream);
+}
+
+static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct jz4740_runtime_data *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct jz4740_pcm_config *config;
+
+	config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+	if (!prtd->dma) {
+		const char *dma_channel_name;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			dma_channel_name = "PCM Playback";
+		else
+			dma_channel_name = "PCM Capture";
+
+		prtd->dma = jz4740_dma_request(substream, dma_channel_name);
+	}
+
+	if (!prtd->dma)
+		return -EBUSY;
+
+	jz4740_dma_configure(prtd->dma, &config->dma_config);
+	prtd->fifo_addr = config->fifo_addr;
+
+	jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+
+	prtd->dma_period = params_period_bytes(params);
+	prtd->dma_start = runtime->dma_addr;
+	prtd->dma_pos = prtd->dma_start;
+	prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
+
+	return 0;
+}
+
+static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct jz4740_runtime_data *prtd = substream->runtime->private_data;
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+	if (prtd->dma) {
+		jz4740_dma_free(prtd->dma);
+		prtd->dma = NULL;
+	}
+
+	return 0;
+}
+
+static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct jz4740_runtime_data *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	if (!prtd->dma)
+			return 0;
+
+	prtd->dma_pos = prtd->dma_start;
+
+	return ret;
+}
+
+static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct jz4740_runtime_data *prtd = runtime->private_data;
+
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		jz4740_pcm_start_transfer(prtd, substream->stream);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		jz4740_dma_disable(prtd->dma);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct jz4740_runtime_data *prtd = runtime->private_data;
+	unsigned long count, pos;
+	snd_pcm_uframes_t offset;
+	struct jz4740_dma_chan *dma = prtd->dma;
+
+	count = jz4740_dma_get_residue(dma);
+	if (prtd->dma_pos == prtd->dma_start)
+		pos = prtd->dma_end - prtd->dma_start - count;
+	else
+		pos = prtd->dma_pos - prtd->dma_start - count;
+
+	offset = bytes_to_frames(runtime, pos);
+	if (offset >= runtime->buffer_size)
+		offset = 0;
+
+	return offset;
+}
+
+static int jz4740_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct jz4740_runtime_data *prtd;
+
+	snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
+	prtd = kzalloc(sizeof(struct jz4740_runtime_data), GFP_KERNEL);
+
+	if (prtd == NULL)
+		return -ENOMEM;
+
+	runtime->private_data = prtd;
+	return 0;
+}
+
+static int jz4740_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct jz4740_runtime_data *prtd = runtime->private_data;
+
+	kfree(prtd);
+
+	return 0;
+}
+
+static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
+	struct vm_area_struct *vma)
+{
+	return remap_pfn_range(vma, vma->vm_start,
+			substream->dma_buffer.addr >> PAGE_SHIFT,
+			vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+static struct snd_pcm_ops jz4740_pcm_ops = {
+	.open		= jz4740_pcm_open,
+	.close		= jz4740_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= jz4740_pcm_hw_params,
+	.hw_free	= jz4740_pcm_hw_free,
+	.prepare	= jz4740_pcm_prepare,
+	.trigger	= jz4740_pcm_trigger,
+	.pointer	= jz4740_pcm_pointer,
+	.mmap		= jz4740_pcm_mmap,
+};
+
+static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = jz4740_pcm_hardware.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+
+	buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
+					  &buf->addr, GFP_KERNEL);
+	if (!buf->area)
+		return -ENOMEM;
+
+	buf->bytes = size;
+
+	return 0;
+}
+
+static void jz4740_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_noncoherent(pcm->card->dev, buf->bytes,
+		  buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+
+static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
+
+int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+	struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &jz4740_pcm_dmamask;
+
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (dai->playback.channels_min) {
+		ret = jz4740_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto err;
+	}
+
+	if (dai->capture.channels_min) {
+		ret = jz4740_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto err;
+	}
+
+err:
+	return ret;
+}
+
+struct snd_soc_platform jz4740_soc_platform = {
+		.name		= "jz4740-pcm",
+		.pcm_ops	= &jz4740_pcm_ops,
+		.pcm_new	= jz4740_pcm_new,
+		.pcm_free	= jz4740_pcm_free,
+};
+EXPORT_SYMBOL_GPL(jz4740_soc_platform);
+
+static int __init jz4740_soc_platform_init(void)
+{
+	return snd_soc_register_platform(&jz4740_soc_platform);
+}
+module_init(jz4740_soc_platform_init);
+
+static void __exit jz4740_soc_platform_exit(void)
+{
+	snd_soc_unregister_platform(&jz4740_soc_platform);
+}
+module_exit(jz4740_soc_platform_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
new file mode 100644
index 0000000..e3f221e
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-pcm.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _JZ4740_PCM_H
+#define _JZ4740_PCM_H
+
+#include <linux/dma-mapping.h>
+#include <asm/mach-jz4740/dma.h>
+
+/* platform data */
+extern struct snd_soc_platform jz4740_soc_platform;
+
+struct jz4740_pcm_config {
+	struct jz4740_dma_config dma_config;
+	phys_addr_t fifo_addr;
+};
+
+#endif
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:16:09 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:18:17 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1497 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492627Ab0FBTQJ (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:16:09 +0200
Received: (qmail 17794 invoked by uid 0); 2 Jun 2010 19:16:08 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 17602
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:16:08 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: [RFC][PATCH 26/26] alsa: ASoC: JZ4740: Add qi_lb60 board driver
Date:   Wed,  2 Jun 2010 21:15:32 +0200
Message-Id: <1275506132-17519-2-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27029
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1641
Content-Length: 6373
Lines: 225

This patch adds ASoC support for the qi_lb60 board.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
Cc: alsa-devel@alsa-project.org
---
 sound/soc/jz4740/Kconfig   |    8 ++
 sound/soc/jz4740/Makefile  |    4 +
 sound/soc/jz4740/qi_lb60.c |  175 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/jz4740/qi_lb60.c

diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
index 39df949..aaa116f 100644
--- a/sound/soc/jz4740/Kconfig
+++ b/sound/soc/jz4740/Kconfig
@@ -11,3 +11,11 @@ config SND_JZ4740_SOC_I2S
 	tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip"
 	help
 	  Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 QI_LB60 board.
+
+config SND_JZ4740_SOC_QI_LB60
+	tristate "SoC Audio support for Qi Hardware Ben Nanonote"
+	depends on SND_JZ4740_SOC && JZ4740_QI_LB60
+	select SND_JZ4740_SOC_I2S
+    select SND_SOC_JZ4740_CODEC
+	help
+	  Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 QI_LB60 board.
diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
index 1be8d19..be873c1 100644
--- a/sound/soc/jz4740/Makefile
+++ b/sound/soc/jz4740/Makefile
@@ -7,3 +7,7 @@ snd-soc-jz4740-i2s-objs := jz4740-i2s.o
 obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
 obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
 
+# Jz4740 Machine Support
+snd-soc-qi-lb60-objs := qi_lb60.o
+
+obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
new file mode 100644
index 0000000..c3f1f91
--- /dev/null
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <linux/gpio.h>
+
+#include "../codecs/jz4740-codec.h"
+#include "jz4740-pcm.h"
+#include "jz4740-i2s.h"
+
+
+#define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29)
+#define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4)
+
+static int qi_lb60_spk_event(struct snd_soc_dapm_widget *widget,
+			     struct snd_kcontrol *ctrl, int event)
+{
+	int on = 0;
+	if (event & SND_SOC_DAPM_POST_PMU)
+		on = 1;
+	else if (event & SND_SOC_DAPM_PRE_PMD)
+		on = 0;
+
+	gpio_set_value(QI_LB60_SND_GPIO, on);
+	gpio_set_value(QI_LB60_AMP_GPIO, on);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget qi_lb60_widgets[] = {
+	SND_SOC_DAPM_SPK("Speaker", qi_lb60_spk_event),
+	SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route qi_lb60_routes[] = {
+	{"Mic", NULL, "MIC"},
+	{"Speaker", NULL, "LOUT"},
+	{"Speaker", NULL, "ROUT"},
+};
+
+#define QI_LB60_DAIFMT (SND_SOC_DAIFMT_I2S | \
+			SND_SOC_DAIFMT_NB_NF | \
+			SND_SOC_DAIFMT_CBM_CFM)
+
+static int qi_lb60_codec_init(struct snd_soc_codec *codec)
+{
+	int ret;
+	struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
+	struct snd_soc_dai *codec_dai = codec->socdev->card->dai_link->codec_dai;
+
+	snd_soc_dapm_nc_pin(codec, "LIN");
+	snd_soc_dapm_nc_pin(codec, "RIN");
+
+	ret = snd_soc_dai_set_fmt(codec_dai, QI_LB60_DAIFMT);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set codec dai format: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, QI_LB60_DAIFMT);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_dapm_new_controls(codec, qi_lb60_widgets, ARRAY_SIZE(qi_lb60_widgets));
+
+	snd_soc_dapm_add_routes(codec, qi_lb60_routes, ARRAY_SIZE(qi_lb60_routes));
+
+	snd_soc_dapm_sync(codec);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link qi_lb60_dai = {
+	.name = "jz4740-codec",
+	.stream_name = "jz4740-codec",
+	.cpu_dai = &jz4740_i2s_dai,
+	.codec_dai = &jz4740_codec_dai,
+	.init = qi_lb60_codec_init,
+};
+
+static struct snd_soc_card qi_lb60 = {
+	.name = "QI LB60",
+	.dai_link = &qi_lb60_dai,
+	.num_links = 1,
+	.platform = &jz4740_soc_platform,
+};
+
+static struct snd_soc_device qi_lb60_snd_devdata = {
+	.card = &qi_lb60,
+	.codec_dev = &soc_codec_dev_jz4740_codec,
+};
+
+static struct platform_device *qi_lb60_snd_device;
+
+static int __init qi_lb60_init(void)
+{
+	int ret;
+
+	qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
+
+	if (!qi_lb60_snd_device)
+		return -ENOMEM;
+
+
+	ret = gpio_request(QI_LB60_SND_GPIO, "SND");
+	if (ret) {
+		pr_err("qi_lb60 snd: Failed to request SND GPIO(%d): %d\n",
+				QI_LB60_SND_GPIO, ret);
+		goto err_device_put;
+	}
+
+	ret = gpio_request(QI_LB60_AMP_GPIO, "AMP");
+	if (ret) {
+		pr_err("qi_lb60 snd: Failed to request AMP GPIO(%d): %d\n",
+				QI_LB60_AMP_GPIO, ret);
+		goto err_gpio_free_snd;
+	}
+
+	gpio_direction_output(JZ_GPIO_PORTB(29), 0);
+	gpio_direction_output(JZ_GPIO_PORTD(4), 0);
+
+	platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata);
+	qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev;
+	ret = platform_device_add(qi_lb60_snd_device);
+	if (ret) {
+		pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
+		goto err_unset_pdata;
+	}
+
+	 return 0;
+
+err_unset_pdata:
+	platform_set_drvdata(qi_lb60_snd_device, NULL);
+/*err_gpio_free_amp:*/
+	gpio_free(QI_LB60_AMP_GPIO);
+err_gpio_free_snd:
+	gpio_free(QI_LB60_SND_GPIO);
+err_device_put:
+	platform_device_put(qi_lb60_snd_device);
+
+	return ret;
+}
+module_init(qi_lb60_init);
+
+static void __exit qi_lb60_exit(void)
+{
+	gpio_free(QI_LB60_AMP_GPIO);
+	gpio_free(QI_LB60_SND_GPIO);
+	platform_device_unregister(qi_lb60_snd_device);
+}
+module_exit(qi_lb60_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
+MODULE_LICENSE("GPL v2");
-- 
1.5.6.5


From lars@metafoo.de Wed Jun  2 21:16:11 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:18:43 +0200 (CEST)
Received: from smtp-out-182.synserver.de ([212.40.180.182]:1496 "HELO
        smtp-out-182.synserver.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with SMTP id S1492632Ab0FBTQL (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:16:11 +0200
Received: (qmail 17765 invoked by uid 0); 2 Jun 2010 19:16:08 -0000
X-SynServer-TrustedSrc: 1
X-SynServer-AuthUser: lars@laprican.de
X-SynServer-PPID: 17602
Received: from port-91163.pppoe.wtnet.de (HELO localhost.localdomain) [84.46.68.144]
  by 217.119.54.73 with SMTP; 2 Jun 2010 19:16:07 -0000
From:   Lars-Peter Clausen <lars@metafoo.de>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Lars-Peter Clausen <lars@metafoo.de>
Subject: [RFC][PATCH 25/26] MIPS: Add defconfig for the qi_lb60 board
Date:   Wed,  2 Jun 2010 21:15:31 +0200
Message-Id: <1275506132-17519-1-git-send-email-lars@metafoo.de>
X-Mailer: git-send-email 1.5.6.5
In-Reply-To: <1275505397-16758-1-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
X-archive-position: 27030
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1642
Content-Length: 37569
Lines: 1473

This patch adds a defconfig for the qi_lb60 clammshell device.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 arch/mips/configs/qi_lb60_defconfig | 1456 +++++++++++++++++++++++++++++++++++
 1 files changed, 1456 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/configs/qi_lb60_defconfig

diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
new file mode 100644
index 0000000..74efbe0
--- /dev/null
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -0,0 +1,1456 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.35-rc1
+# Wed Jun  2 20:58:34 2010
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_JZ4740=y
+# CONFIG_LASAT is not set
+# CONFIG_MACH_LOONGSON is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_POWERTV is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_JZ4740_QI_LB60=y
+CONFIG_HAVE_PWM=y
+CONFIG_LOONGSON_UART_BASE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2E is not set
+# CONFIG_CPU_LOONGSON2F is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+# CONFIG_TREE_RCU is not set
+# CONFIG_TREE_PREEMPT_RCU is not set
+CONFIG_TINY_RCU=y
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+CONFIG_TCP_CONG_WESTWOOD=y
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_HYBLA is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_VENO is not set
+CONFIG_DEFAULT_WESTWOOD=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="westwood"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+
+#
+# Some wireless drivers require a rate control algorithm
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_NAND_JZ4740=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IWMC3200TOP is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WAN is not set
+# CONFIG_ATM_DRIVERS is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+# CONFIG_ISDN_CAPI is not set
+# CONFIG_ISDN_DRV_GIGASET is not set
+# CONFIG_MISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_MATRIX=y
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=2
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_RAMOOPS is not set
+# CONFIG_I2C is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_IT8761E is not set
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_JZ4740=y
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+CONFIG_SENSORS_JZ4740=y
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_FB_JZ4740=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_SUN8x16=y
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_RAWMIDI_SEQ=m
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+CONFIG_SND_VIRMIDI=m
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_MIPS is not set
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_ATM is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_JZ4740=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_DAC124S085 is not set
+CONFIG_LEDS_PWM=y
+# CONFIG_LEDS_LT3593 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_JZ4740=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+# CONFIG_JFFS2_ZLIB is not set
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_LKDTM is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_SPINLOCK_TEST is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_PCOMP=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
-- 
1.5.6.5


From akpm@linux-foundation.org Wed Jun  2 21:37:37 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:37:41 +0200 (CEST)
Received: from smtp1.linux-foundation.org ([140.211.169.13]:41402 "EHLO
        smtp1.linux-foundation.org" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491934Ab0FBThh (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:37:37 +0200
Received: from imap1.linux-foundation.org (imap1.linux-foundation.org [140.211.169.55])
        by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id o52Jawd9031811
        (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO);
        Wed, 2 Jun 2010 12:36:59 -0700
Received: from akpm.mtv.corp.google.com (localhost [127.0.0.1])
        by imap1.linux-foundation.org (8.13.5.20060308/8.13.5/Debian-3ubuntu1.1) with SMTP id o52Javlf012847;
        Wed, 2 Jun 2010 12:36:58 -0700
Date:   Wed, 2 Jun 2010 12:36:57 -0700
From:   Andrew Morton <akpm@linux-foundation.org>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org
Subject: Re: [RFC][PATCH 16/26] fbdev: Add JZ4740 framebuffer driver
Message-Id: <20100602123657.e197990b.akpm@linux-foundation.org>
In-Reply-To: <1275505832-17185-8-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
        <1275505832-17185-8-git-send-email-lars@metafoo.de>
X-Mailer: Sylpheed 2.4.8 (GTK+ 2.12.9; x86_64-pc-linux-gnu)
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
X-MIMEDefang-Filter: lf$Revision: 1.188 $
X-Scanned-By: MIMEDefang 2.63 on 140.211.169.13
X-archive-position: 27031
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: akpm@linux-foundation.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1663
Content-Length: 4804
Lines: 181

On Wed,  2 Jun 2010 21:10:32 +0200
Lars-Peter Clausen <lars@metafoo.de> wrote:

> This patch adds support for the LCD controller on JZ4740 SoCs.
> 
>
> ...
>
> +struct jzfb_framedesc {
> +	uint32_t next;
> +	uint32_t addr;
> +	uint32_t id;
> +	uint32_t cmd;
> +} __attribute__((packed));

We have a little __packed helper.  

>
> ...
>
> +static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
> +			unsigned blue, unsigned transp, struct fb_info *fb)
> +{
> +	uint32_t color;
> +
> +	if (regno >= 16)
> +		return -EINVAL;
> +
> +	color = jzfb_convert_color_to_hw(red, fb->var.red.length);
> +	color |= jzfb_convert_color_to_hw(green, fb->var.green.length);
> +	color |= jzfb_convert_color_to_hw(blue, fb->var.blue.length);
> +	color |= jzfb_convert_color_to_hw(transp, fb->var.transp.length);
> +
> +	((uint32_t *)(fb->pseudo_palette))[regno] = color;

The typecast apepars to be unneeded.  If it _was_ needed then this code
would look rather fishy from an endianness POV.

> +	return 0;
> +}
> +
>
> ...
>
> +static int __devinit jzfb_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct jzfb *jzfb;
> +	struct fb_info *fb;
> +	struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
> +	struct resource *mem;
> +
> +	if (!pdata) {
> +		dev_err(&pdev->dev, "Missing platform data\n");
> +		return -ENOENT;
> +	}
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem) {
> +		dev_err(&pdev->dev, "Failed to get register memory resource\n");
> +		return -ENOENT;
> +	}
> +
> +	mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
> +	if (!mem) {
> +		dev_err(&pdev->dev, "Failed to request register memory region\n");
> +		return -EBUSY;
> +	}
> +
> +	fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
> +	if (!fb) {
> +		dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
> +		ret = -ENOMEM;
> +		goto err_release_mem_region;
> +	}
> +
> +	fb->fbops = &jzfb_ops;
> +	fb->flags = FBINFO_DEFAULT;
> +
> +	jzfb = fb->par;
> +	jzfb->pdev = pdev;
> +	jzfb->pdata = pdata;
> +	jzfb->mem = mem;
> +
> +	jzfb->ldclk = clk_get(&pdev->dev, "lcd");
> +	if (IS_ERR(jzfb->ldclk)) {
> +		ret = PTR_ERR(jzfb->ldclk);
> +		dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
> +		goto err_framebuffer_release;
> +	}
> +
> +	jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
> +	if (IS_ERR(jzfb->lpclk)) {
> +		ret = PTR_ERR(jzfb->lpclk);
> +		dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
> +		goto err_put_ldclk;
> +	}
> +
> +	jzfb->base = ioremap(mem->start, resource_size(mem));
> +
> +	if (!jzfb->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
> +		ret = -EBUSY;
> +		goto err_put_lpclk;
> +	}
> +
> +	platform_set_drvdata(pdev, jzfb);
> +
> +	fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
> +				 &fb->modelist);
> +	fb->mode = pdata->modes;
> +
> +	fb_videomode_to_var(&fb->var, fb->mode);
> +	fb->var.bits_per_pixel = pdata->bpp;
> +	jzfb_check_var(&fb->var, fb);
> +
> +	ret = jzfb_alloc_devmem(jzfb);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to allocate video memory\n");
> +		goto err_iounmap;
> +	}
> +
> +	fb->fix = jzfb_fix;
> +	fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
> +	fb->fix.mmio_start = mem->start;
> +	fb->fix.mmio_len = resource_size(mem);
> +	fb->fix.smem_start = jzfb->vidmem_phys;
> +	fb->fix.smem_len =  fb->fix.line_length * fb->var.yres;
> +	fb->screen_base = jzfb->vidmem;
> +	fb->pseudo_palette = jzfb->pseudo_palette;
> +
> +	fb_alloc_cmap(&fb->cmap, 256, 0);
> +
> +	mutex_init(&jzfb->lock);

I'd suggest initializing the mutex much earlier.  THings like
jzfb_check_var() and jzfb_alloc_devmem() don't currently take that
lock, but who knows what might happen in the future..

> +	clk_enable(jzfb->ldclk);
> +	jzfb->is_enabled = 1;
> +
> +	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
> +	jzfb_set_par(fb);
> +
> +	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> +	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> +
> +	ret = register_framebuffer(fb);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
> +		goto err_free_devmem;
> +	}
> +
> +	jzfb->fb = fb;
> +
> +	return 0;
> +
> +err_free_devmem:
> +	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> +	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> +
> +	fb_dealloc_cmap(&fb->cmap);
> +	jzfb_free_devmem(jzfb);
> +err_iounmap:
> +	iounmap(jzfb->base);
> +err_put_lpclk:
> +	clk_put(jzfb->lpclk);
> +err_put_ldclk:
> +	clk_put(jzfb->ldclk);
> +err_framebuffer_release:
> +	framebuffer_release(fb);
> +err_release_mem_region:
> +	release_mem_region(mem->start, resource_size(mem));
> +	return ret;
> +}
> +
>
> ...
>


From sam@ravnborg.org Wed Jun  2 21:48:18 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 21:48:22 +0200 (CEST)
Received: from pfepa.post.tele.dk ([195.41.46.235]:47076 "EHLO
        pfepa.post.tele.dk" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1492625Ab0FBTsS (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 21:48:18 +0200
Received: from merkur.ravnborg.org (x1-6-00-1e-2a-84-ae-3e.k225.webspeed.dk [80.163.61.94])
        by pfepa.post.tele.dk (Postfix) with ESMTP id A8B81A5003B;
        Wed,  2 Jun 2010 21:48:16 +0200 (CEST)
Date:   Wed, 2 Jun 2010 21:48:17 +0200
From:   Sam Ravnborg <sam@ravnborg.org>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Alexander Clouter <alex@digriz.org.uk>,
        Manuel Lauss <manuel.lauss@gmail.com>
Subject: Re: [PATCH v4] MIPS: Clean up the calculation of
        VMLINUZ_LOAD_ADDRESS
Message-ID: <20100602194817.GA7530@merkur.ravnborg.org>
References: <9890d1383c75ce6df44d357687a9c4e2d6ba4050.1275438553.git.wuzhangjin@gmail.com> <96f3b48ba7f749c4357760008cdae644aa55b92d.1275438520.git.wuzhangjin@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <96f3b48ba7f749c4357760008cdae644aa55b92d.1275438520.git.wuzhangjin@gmail.com>
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 27032
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: sam@ravnborg.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1672
Content-Length: 901
Lines: 23

On Wed, Jun 02, 2010 at 04:35:25PM +0800, Wu Zhangjin wrote:
> We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is indecipherable. This
> patch rewrites it in C.
> 
> Changes:
> 
> v3 -> v4: (feedback from Sam Ravnborg)
>   o Makefile: Follow the 80 characters' limit and Remove an un-needed objcopy.
>   o calc_vmlinuz_load_addr.c: Use a smaller alignment and Add more comments
> 
> v2 -> v3: (feedback from Alexander Clouter)
>   o Drop the unneeded variable n
>   o Replace the last "unsigned long long" by uint64_t
> 
> v1 -> v2: (feedback from Alexander Clouter)
>   o make it more portable
>     use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
>     instead of "unsigned long long".
>   o add a missing return value
>     return EXIT_FAILURE if sscanf() not return 1
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>

From lars@metafoo.de Wed Jun  2 22:06:00 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 22:06:04 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:46141 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491941Ab0FBUGA (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 22:06:00 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 6C1B19AE;
        Wed,  2 Jun 2010 22:05:54 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id V8NA+M-YuJRL; Wed,  2 Jun 2010 22:05:54 +0200 (CEST)
Received: from [192.168.37.31] (port-91163.pppoe.wtnet.de [84.46.68.144])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id DC0E19AD;
        Wed,  2 Jun 2010 22:05:41 +0200 (CEST)
Message-ID: <4C06B974.5010905@metafoo.de>
Date:   Wed, 02 Jun 2010 22:05:08 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Andrew Morton <akpm@linux-foundation.org>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org
Subject: Re: [RFC][PATCH 16/26] fbdev: Add JZ4740 framebuffer driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505832-17185-8-git-send-email-lars@metafoo.de> <20100602123657.e197990b.akpm@linux-foundation.org>
In-Reply-To: <20100602123657.e197990b.akpm@linux-foundation.org>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-archive-position: 27033
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1696
Content-Length: 5165
Lines: 195

Andrew Morton wrote:
> On Wed,  2 Jun 2010 21:10:32 +0200
> Lars-Peter Clausen <lars@metafoo.de> wrote:
>
>   
>> This patch adds support for the LCD controller on JZ4740 SoCs.
>>
>>
>> ...
>>
>> +struct jzfb_framedesc {
>> +	uint32_t next;
>> +	uint32_t addr;
>> +	uint32_t id;
>> +	uint32_t cmd;
>> +} __attribute__((packed));
>>     
>
> We have a little __packed helper.  
>
>   
Ok.
>> ...
>>
>> +static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
>> +			unsigned blue, unsigned transp, struct fb_info *fb)
>> +{
>> +	uint32_t color;
>> +
>> +	if (regno >= 16)
>> +		return -EINVAL;
>> +
>> +	color = jzfb_convert_color_to_hw(red, fb->var.red.length);
>> +	color |= jzfb_convert_color_to_hw(green, fb->var.green.length);
>> +	color |= jzfb_convert_color_to_hw(blue, fb->var.blue.length);
>> +	color |= jzfb_convert_color_to_hw(transp, fb->var.transp.length);
>> +
>> +	((uint32_t *)(fb->pseudo_palette))[regno] = color;
>>     
>
> The typecast apepars to be unneeded.  If it _was_ needed then this code
> would look rather fishy from an endianness POV.
>
>   
It is needed, because the pseudo_palette member of struct fb_info is a
void pointer.
>> +	return 0;
>> +}
>> +
>>
>> ...
>>
>> +static int __devinit jzfb_probe(struct platform_device *pdev)
>> +{
>> +	int ret;
>> +	struct jzfb *jzfb;
>> +	struct fb_info *fb;
>> +	struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
>> +	struct resource *mem;
>> +
>> +	if (!pdata) {
>> +		dev_err(&pdev->dev, "Missing platform data\n");
>> +		return -ENOENT;
>> +	}
>> +
>> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	if (!mem) {
>> +		dev_err(&pdev->dev, "Failed to get register memory resource\n");
>> +		return -ENOENT;
>> +	}
>> +
>> +	mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
>> +	if (!mem) {
>> +		dev_err(&pdev->dev, "Failed to request register memory region\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
>> +	if (!fb) {
>> +		dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
>> +		ret = -ENOMEM;
>> +		goto err_release_mem_region;
>> +	}
>> +
>> +	fb->fbops = &jzfb_ops;
>> +	fb->flags = FBINFO_DEFAULT;
>> +
>> +	jzfb = fb->par;
>> +	jzfb->pdev = pdev;
>> +	jzfb->pdata = pdata;
>> +	jzfb->mem = mem;
>> +
>> +	jzfb->ldclk = clk_get(&pdev->dev, "lcd");
>> +	if (IS_ERR(jzfb->ldclk)) {
>> +		ret = PTR_ERR(jzfb->ldclk);
>> +		dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
>> +		goto err_framebuffer_release;
>> +	}
>> +
>> +	jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
>> +	if (IS_ERR(jzfb->lpclk)) {
>> +		ret = PTR_ERR(jzfb->lpclk);
>> +		dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
>> +		goto err_put_ldclk;
>> +	}
>> +
>> +	jzfb->base = ioremap(mem->start, resource_size(mem));
>> +
>> +	if (!jzfb->base) {
>> +		dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
>> +		ret = -EBUSY;
>> +		goto err_put_lpclk;
>> +	}
>> +
>> +	platform_set_drvdata(pdev, jzfb);
>> +
>> +	fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
>> +				 &fb->modelist);
>> +	fb->mode = pdata->modes;
>> +
>> +	fb_videomode_to_var(&fb->var, fb->mode);
>> +	fb->var.bits_per_pixel = pdata->bpp;
>> +	jzfb_check_var(&fb->var, fb);
>> +
>> +	ret = jzfb_alloc_devmem(jzfb);
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "Failed to allocate video memory\n");
>> +		goto err_iounmap;
>> +	}
>> +
>> +	fb->fix = jzfb_fix;
>> +	fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
>> +	fb->fix.mmio_start = mem->start;
>> +	fb->fix.mmio_len = resource_size(mem);
>> +	fb->fix.smem_start = jzfb->vidmem_phys;
>> +	fb->fix.smem_len =  fb->fix.line_length * fb->var.yres;
>> +	fb->screen_base = jzfb->vidmem;
>> +	fb->pseudo_palette = jzfb->pseudo_palette;
>> +
>> +	fb_alloc_cmap(&fb->cmap, 256, 0);
>> +
>> +	mutex_init(&jzfb->lock);
>>     
>
> I'd suggest initializing the mutex much earlier.  THings like
> jzfb_check_var() and jzfb_alloc_devmem() don't currently take that
> lock, but who knows what might happen in the future..
>
>   
Hm, ok.
>> +	clk_enable(jzfb->ldclk);
>> +	jzfb->is_enabled = 1;
>> +
>> +	writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
>> +	jzfb_set_par(fb);
>> +
>> +	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
>> +	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
>> +
>> +	ret = register_framebuffer(fb);
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
>> +		goto err_free_devmem;
>> +	}
>> +
>> +	jzfb->fb = fb;
>> +
>> +	return 0;
>> +
>> +err_free_devmem:
>> +	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
>> +	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
>> +
>> +	fb_dealloc_cmap(&fb->cmap);
>> +	jzfb_free_devmem(jzfb);
>> +err_iounmap:
>> +	iounmap(jzfb->base);
>> +err_put_lpclk:
>> +	clk_put(jzfb->lpclk);
>> +err_put_ldclk:
>> +	clk_put(jzfb->ldclk);
>> +err_framebuffer_release:
>> +	framebuffer_release(fb);
>> +err_release_mem_region:
>> +	release_mem_region(mem->start, resource_size(mem));
>> +	return ret;
>> +}
>> +
>>
>> ...
>>
>>     
>
>   


From alex@digriz.org.uk Wed Jun  2 23:50:58 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Wed, 02 Jun 2010 23:51:02 +0200 (CEST)
Received: from chipmunk.wormnet.eu ([195.195.131.226]:41231 "EHLO
        chipmunk.wormnet.eu" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1491844Ab0FBVu6 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Wed, 2 Jun 2010 23:50:58 +0200
Received: by chipmunk.wormnet.eu (Postfix, from userid 1000)
        id CA1E986655; Wed,  2 Jun 2010 22:50:56 +0100 (BST)
Date:   Wed, 2 Jun 2010 22:50:56 +0100
From:   Alexander Clouter <alex@digriz.org.uk>
To:     wuzhangjin@gmail.com
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>,
        Manuel Lauss <manuel.lauss@gmail.com>, sam@ravnborg.org
Subject: Re: [PATCH v4] MIPS: Clean up the calculation of
        VMLINUZ_LOAD_ADDRESS
Message-ID: <20100602215056.GX2519@chipmunk>
References: <9890d1383c75ce6df44d357687a9c4e2d6ba4050.1275438553.git.wuzhangjin@gmail.com> <96f3b48ba7f749c4357760008cdae644aa55b92d.1275438520.git.wuzhangjin@gmail.com> <20100602194817.GA7530@merkur.ravnborg.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100602194817.GA7530@merkur.ravnborg.org>
Organization: diGriz
X-URL:  http://www.digriz.org.uk/
X-JabberID: alex@digriz.org.uk
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 27034
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: alex@digriz.org.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1808
Content-Length: 1147
Lines: 31

* Sam Ravnborg <sam@ravnborg.org> [2010-06-02 21:48:17+0200]:
>
> On Wed, Jun 02, 2010 at 04:35:25PM +0800, Wu Zhangjin wrote:
> > We have calculated VMLINUZ_LOAD_ADDRESS in shell, which is indecipherable. This
> > patch rewrites it in C.
> > 
> > Changes:
> > 
> > v3 -> v4: (feedback from Sam Ravnborg)
> >   o Makefile: Follow the 80 characters' limit and Remove an un-needed objcopy.
> >   o calc_vmlinuz_load_addr.c: Use a smaller alignment and Add more comments
> > 
> > v2 -> v3: (feedback from Alexander Clouter)
> >   o Drop the unneeded variable n
> >   o Replace the last "unsigned long long" by uint64_t
> > 
> > v1 -> v2: (feedback from Alexander Clouter)
> >   o make it more portable
> >     use EXIT_SUCCESS and EXIT_FAILURE as the return value, and use uint64_t
> >     instead of "unsigned long long".
> >   o add a missing return value
> >     return EXIT_FAILURE if sscanf() not return 1
> > 
> > Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> Acked-by: Sam Ravnborg <sam@ravnborg.org>

Reviewed-by: Alexander Clouter <alex@digriz.org.uk>

-- 
Alexander Clouter
.sigmonster says: The price of greatness is responsibility.

From graham.gower@gmail.com Thu Jun  3 00:45:23 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 00:45:27 +0200 (CEST)
Received: from mail-bw0-f49.google.com ([209.85.214.49]:59198 "EHLO
        mail-bw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492145Ab0FBWpX convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Thu, 3 Jun 2010 00:45:23 +0200
Received: by bwz5 with SMTP id 5so564182bwz.36
        for <multiple recipients>; Wed, 02 Jun 2010 15:45:22 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=ZgipcGyPoipBa6Qm147izHbM17JLh/LNSOO/coYCuas=;
        b=qF7cNvqw6SThJYWStBOiam5ho+1Qa9z4p64l3fqq/TbzBZB7XLUBcJ98qRYyav51EM
         +YQS/qHEUeDVH542Vb0ASWSf8asMdcM3hl4SHRHm6FiKI0WniyY9M75MP7YKtlEkTOgi
         YNcPu5IpzEPxgHZ9gTKe72tqxFzVe/En4fRgE=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=A9EtH66o7M9LIklBs2+7jgDvkpfvcTjrNPNpR3wSEkk13zXGnPC3+eg7zo3GKepUJL
         sfNZEbvU290XYPGJf1Po5Sl9QH1BNdywl6Uh3q2SlwRhd5ptUBXFuIHR5YDQj7UejzwA
         6qt6ArT0N6dXiIUvgZP6UDU4FX55iyj5Yy4Wc=
MIME-Version: 1.0
Received: by 10.204.3.65 with SMTP id 1mr2246221bkm.210.1275518722173; Wed, 02 
        Jun 2010 15:45:22 -0700 (PDT)
Received: by 10.204.72.197 with HTTP; Wed, 2 Jun 2010 15:45:22 -0700 (PDT)
In-Reply-To: <1275505397-16758-4-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
        <1275505397-16758-4-git-send-email-lars@metafoo.de>
Date:   Thu, 3 Jun 2010 08:15:22 +0930
Message-ID: <AANLkTimVM637peyrPP7dZ3Uy2S-3DAEXspGi-FONcW6p@mail.gmail.com>
Subject: Re: [RFC][PATCH 03/26] MIPS: JZ4740: Add clock API support.
From:   Graham Gower <graham.gower@gmail.com>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-archive-position: 27035
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: graham.gower@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 1871
Content-Length: 340
Lines: 12

On 3 June 2010 04:32, Lars-Peter Clausen <lars@metafoo.de> wrote:

> +       {
> +               .name = "dma",
> +               .parent = &jz_clk_high_speed_peripheral.clk,
> +               .gate_bit = JZ_CLOCK_GATE_UART0,
> +               .ops = &jz_clk_simple_ops,
> +       },

Presumably this should be JZ_CLOCK_GATE_DMAC.

-Graham

From mcuos.com@gmail.com Thu Jun  3 05:36:35 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 05:36:40 +0200 (CEST)
Received: from mail-pw0-f49.google.com ([209.85.160.49]:45202 "EHLO
        mail-pw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491936Ab0FCDgf (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 05:36:35 +0200
Received: by pwi2 with SMTP id 2so3110938pwi.36
        for <multiple recipients>; Wed, 02 Jun 2010 20:36:26 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:message-id:date:from
         :user-agent:mime-version:to:cc:subject:references:in-reply-to
         :content-type:content-transfer-encoding;
        bh=MpLsNMfYQmxMfyCljpcaWVQ4qrArcyTx+pvJ7r1372o=;
        b=A8nfoZ1asgytuvM+4e1y9VPmOzhW9voM0zHOv4E6VEi7zrHGQExRNzaZjiS7QfJpCx
         H8xSY+hELhfkVlYgCRdpmi8Nzr7UWhHzXOCEY1+L5GGFSfwXYvbqllFaF324gKmu42fo
         +2SgkYhwPRoGGY6VTnhWkk23PSLclGUGW1KJ0=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=message-id:date:from:user-agent:mime-version:to:cc:subject
         :references:in-reply-to:content-type:content-transfer-encoding;
        b=KY83kh9bvBVCMiqnoZ/c0ZxjNpR81RebWttLdJSR6bAvkAW2Q8IAc4632pE+Rt633j
         sqtuIL9RPj9Vg2koZQ9Sz+gQOfyleFgC5jyKTWyE+NuZw16+Wbajzca263NX0EqKPJ65
         evYAhROiAqj+z0ifYhfk9NIRmAu2U4gOmDv3s=
Received: by 10.142.121.1 with SMTP id t1mr5916216wfc.100.1275536186136;
        Wed, 02 Jun 2010 20:36:26 -0700 (PDT)
Received: from [192.168.1.10] ([116.226.201.224])
        by mx.google.com with ESMTPS id u34sm2732902wfh.20.2010.06.02.20.36.17
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 20:36:24 -0700 (PDT)
Message-ID: <4C07232C.8010905@gmail.com>
Date:   Thu, 03 Jun 2010 11:36:12 +0800
From:   Wan ZongShun <mcuos.com@gmail.com>
User-Agent: Thunderbird 2.0.0.24 (X11/20100411)
MIME-Version: 1.0
To:     Lars-Peter Clausen <lars@metafoo.de>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>
Subject: Re: [alsa-devel] [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-5-git-send-email-lars@metafoo.de>
In-Reply-To: <1275505950-17334-5-git-send-email-lars@metafoo.de>
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
X-archive-position: 27036
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: mcuos.com@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2033
Content-Length: 30848
Lines: 1095

Hi,

I have some minor comments below:


> This patch adds ASoC support for JZ4740 SoCs I2S module.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> Cc: alsa-devel@alsa-project.org
> ---
>  sound/soc/Kconfig             |    1 +
>  sound/soc/Makefile            |    1 +
>  sound/soc/jz4740/Kconfig      |   13 +
>  sound/soc/jz4740/Makefile     |    9 +
>  sound/soc/jz4740/jz4740-i2s.c |  568 +++++++++++++++++++++++++++++++++++++++++
>  sound/soc/jz4740/jz4740-i2s.h |   18 ++
>  sound/soc/jz4740/jz4740-pcm.c |  350 +++++++++++++++++++++++++
>  sound/soc/jz4740/jz4740-pcm.h |   22 ++
>  8 files changed, 982 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/jz4740/Kconfig
>  create mode 100644 sound/soc/jz4740/Makefile
>  create mode 100644 sound/soc/jz4740/jz4740-i2s.c
>  create mode 100644 sound/soc/jz4740/jz4740-i2s.h
>  create mode 100644 sound/soc/jz4740/jz4740-pcm.c
>  create mode 100644 sound/soc/jz4740/jz4740-pcm.h
> 
> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
> index b1749bc..5a7a724 100644
> --- a/sound/soc/Kconfig
> +++ b/sound/soc/Kconfig
> @@ -36,6 +36,7 @@ source "sound/soc/s3c24xx/Kconfig"
>  source "sound/soc/s6000/Kconfig"
>  source "sound/soc/sh/Kconfig"
>  source "sound/soc/txx9/Kconfig"
> +source "sound/soc/jz4740/Kconfig"
>  
>  # Supported codecs
>  source "sound/soc/codecs/Kconfig"
> diff --git a/sound/soc/Makefile b/sound/soc/Makefile
> index 1470141..fdbe74d 100644
> --- a/sound/soc/Makefile
> +++ b/sound/soc/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_SND_SOC)	+= s3c24xx/
>  obj-$(CONFIG_SND_SOC)	+= s6000/
>  obj-$(CONFIG_SND_SOC)	+= sh/
>  obj-$(CONFIG_SND_SOC)	+= txx9/
> +obj-$(CONFIG_SND_SOC)	+= jz4740/

should keep the Kconfig and Makefile sorted, this helps avoid merge
issues.

except above issue, Also, I see many warning infos when using checkpatch tool,as following:

WARNING: line over 80 characters
#358: FILE: sound/soc/jz4740/jz4740-i2s.c:204:
+		conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER;

WARNING: line over 80 characters
#536: FILE: sound/soc/jz4740/jz4740-i2s.c:382:
+static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)

WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#587: FILE: sound/soc/jz4740/jz4740-i2s.c:433:
+EXPORT_SYMBOL_GPL(jz4740_i2s_dai);

WARNING: line over 80 characters
#813: FILE: sound/soc/jz4740/jz4740-pcm.c:61:
+static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd, int stream)

WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#1086: FILE: sound/soc/jz4740/jz4740-pcm.c:334:
+EXPORT_SYMBOL_GPL(jz4740_soc_platform);

total: 0 errors, 5 warnings, 991 lines checked


> diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
> new file mode 100644
> index 0000000..39df949
> --- /dev/null
> +++ b/sound/soc/jz4740/Kconfig
> @@ -0,0 +1,13 @@
> +config SND_JZ4740_SOC
> +	tristate "SoC Audio for Ingenic JZ4740 SoC"
> +	depends on SOC_JZ4740 && SND_SOC
> +	help
> +	  Say Y or M if you want to add support for codecs attached to
> +	  the Jz4740 AC97, I2S or SSP interface. You will also need
> +	  to select the audio interfaces to support below.
> +
> +config SND_JZ4740_SOC_I2S
> +	depends on SND_JZ4740_SOC
> +	tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip"
> +	help
> +	  Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 QI_LB60 board.
> diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
> new file mode 100644
> index 0000000..1be8d19
> --- /dev/null
> +++ b/sound/soc/jz4740/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Jz4740 Platform Support
> +#
> +snd-soc-jz4740-objs := jz4740-pcm.o
> +snd-soc-jz4740-i2s-objs := jz4740-i2s.o
> +
> +obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
> +obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
> +
> diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
> new file mode 100644
> index 0000000..2b139fd
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-i2s.c
> @@ -0,0 +1,568 @@
> +/*
> + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + *  This program is free software; you can redistribute	 it and/or modify it
> + *  under  the terms of	 the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the	License, or (at your
> + *  option) any later version.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +
> +#include <linux/dma-mapping.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <sound/soc-dapm.h>
> +#include <sound/initval.h>
> +
> +#include "jz4740-i2s.h"
> +#include "jz4740-pcm.h"
> +
> +#define JZ_REG_AIC_CONF		0x00
> +#define JZ_REG_AIC_CTRL		0x04
> +#define JZ_REG_AIC_I2S_FMT	0x10
> +#define JZ_REG_AIC_FIFO_STATUS	0x14
> +#define JZ_REG_AIC_I2S_STATUS	0x1c
> +#define JZ_REG_AIC_CLK_DIV	0x30
> +#define JZ_REG_AIC_FIFO		0x34
> +
> +#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_MASK (0xf << 12)
> +#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_MASK (0xf <<  8)
> +#define JZ_AIC_CONF_OVERFLOW_PLAY_LAST BIT(6)
> +#define JZ_AIC_CONF_INTERNAL_CODEC BIT(5)
> +#define JZ_AIC_CONF_I2S BIT(4)
> +#define JZ_AIC_CONF_RESET BIT(3)
> +#define JZ_AIC_CONF_BIT_CLK_MASTER BIT(2)
> +#define JZ_AIC_CONF_SYNC_CLK_MASTER BIT(1)
> +#define JZ_AIC_CONF_ENABLE BIT(0)
> +
> +#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12
> +#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8
> +
> +#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19)
> +#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16)
> +#define JZ_AIC_CTRL_ENABLE_RX_DMA BIT(15)
> +#define JZ_AIC_CTRL_ENABLE_TX_DMA BIT(14)
> +#define JZ_AIC_CTRL_MONO_TO_STEREO BIT(11)
> +#define JZ_AIC_CTRL_SWITCH_ENDIANNESS BIT(10)
> +#define JZ_AIC_CTRL_SIGNED_TO_UNSIGNED BIT(9)
> +#define JZ_AIC_CTRL_FLUSH		BIT(8)
> +#define JZ_AIC_CTRL_ENABLE_ROR_INT BIT(6)
> +#define JZ_AIC_CTRL_ENABLE_TUR_INT BIT(5)
> +#define JZ_AIC_CTRL_ENABLE_RFS_INT BIT(4)
> +#define JZ_AIC_CTRL_ENABLE_TFS_INT BIT(3)
> +#define JZ_AIC_CTRL_ENABLE_LOOPBACK BIT(2)
> +#define JZ_AIC_CTRL_ENABLE_PLAYBACK BIT(1)
> +#define JZ_AIC_CTRL_ENABLE_CAPTURE BIT(0)
> +
> +#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET 19
> +#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET  16
> +
> +#define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12)
> +#define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4)
> +#define JZ_AIC_I2S_FMT_MSB BIT(0)
> +
> +#define JZ_AIC_I2S_STATUS_BUSY BIT(2)
> +
> +#define JZ_AIC_CLK_DIV_MASK 0xf
> +
> +struct jz4740_i2s {
> +	struct resource *mem;
> +	void __iomem *base;
> +	dma_addr_t phys_base;
> +
> +	struct clk *clk_aic;
> +	struct clk *clk_i2s;
> +
> +	struct jz4740_pcm_config pcm_config_playback;
> +	struct jz4740_pcm_config pcm_config_capture;
> +};
> +
> +static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
> +	unsigned int reg)
> +{
> +	return readl(i2s->base + reg);
> +}
> +
> +static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,
> +	unsigned int reg, uint32_t value)
> +{
> +	writel(value, i2s->base + reg);
> +}
> +
> +static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai)
> +{
> +	return dai->private_data;
> +}
> +
> +static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
> +	struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf, ctrl;
> +
> +	if (dai->active)
> +		return 0;
> +
> +
> +	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
> +	ctrl |= JZ_AIC_CTRL_FLUSH;
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
> +
> +	clk_enable(i2s->clk_i2s);
> +
> +	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +	conf |= JZ_AIC_CONF_ENABLE;
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	return 0;
> +}
> +
> +static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
> +	struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	if (!dai->active)
> +		return;
> +
> +	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +	conf &= ~JZ_AIC_CONF_ENABLE;
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	clk_disable(i2s->clk_i2s);
> +}
> +
> +
> +static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
> +	struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
> +
> +	uint32_t ctrl;
> +	uint32_t mask;
> +
> +	if (playback)
> +		mask = JZ_AIC_CTRL_ENABLE_PLAYBACK | JZ_AIC_CTRL_ENABLE_TX_DMA;
> +	else
> +		mask = JZ_AIC_CTRL_ENABLE_CAPTURE | JZ_AIC_CTRL_ENABLE_RX_DMA;
> +
> +	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		ctrl |= mask;
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		ctrl &= ~mask;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
> +
> +	return 0;
> +}
> +
> +
> +static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +
> +	uint32_t format = 0;
> +	uint32_t conf;
> +
> +	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +
> +	conf &= ~(JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER);
> +
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER;
> +		format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFS:
> +		conf |= JZ_AIC_CONF_SYNC_CLK_MASTER;
> +		break;
> +	case SND_SOC_DAIFMT_CBS_CFM:
> +		conf |= JZ_AIC_CONF_BIT_CLK_MASTER;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_MSB:
> +		format |= JZ_AIC_I2S_FMT_MSB;
> +		break;
> +	case SND_SOC_DAIFMT_I2S:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_NB_NF:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_I2S_FMT, format);
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
> +	enum jz4740_dma_width dma_width;
> +	struct jz4740_pcm_config *pcm_config;
> +	unsigned int sample_size;
> +	uint32_t ctrl;
> +
> +	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
> +
> +	switch (params_format(params)) {
> +	case SNDRV_PCM_FORMAT_S8:
> +		sample_size = 0;
> +		dma_width = JZ4740_DMA_WIDTH_8BIT;
> +		break;
> +	case SNDRV_PCM_FORMAT_S16:
> +		sample_size = 1;
> +		dma_width = JZ4740_DMA_WIDTH_16BIT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (playback) {
> +		ctrl &= ~JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK;
> +		ctrl |= sample_size << JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET;
> +	} else {
> +		ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
> +		ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
> +	}
> +
> +	switch (params_channels(params)) {
> +	case 2:
> +		break;
> +	case 1:
> +		if (playback) {
> +			ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
> +			break;
> +		}
> +	default: /* Falltrough */
> +		return -EINVAL;
> +	}
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
> +
> +	if (playback) {
> +		pcm_config = &i2s->pcm_config_playback;
> +		pcm_config->dma_config.dst_width = dma_width;
> +	} else {
> +		pcm_config = &i2s->pcm_config_capture;
> +		pcm_config->dma_config.src_width = dma_width;
> +	}
> +
> +
> +	snd_soc_dai_set_dma_data(dai, substream, pcm_config);
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +
> +	switch (div_id) {
> +	case JZ4740_I2S_BIT_CLK:
> +		if (div & 1 || div > 16)
> +			return -EINVAL;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div - 1);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
> +	unsigned int freq, int dir)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	int ret = 0;
> +	struct clk *parent;
> +
> +	switch (clk_id) {
> +	case JZ4740_I2S_CLKSRC_EXT:
> +		parent = clk_get(NULL, "ext");
> +		clk_set_parent(i2s->clk_i2s, parent);
> +		break;
> +	case JZ4740_I2S_CLKSRC_PLL:
> +		parent = clk_get(NULL, "pll half");
> +		clk_set_parent(i2s->clk_i2s, parent);
> +		ret = clk_set_rate(i2s->clk_i2s, freq);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	clk_put(parent);
> +
> +	return ret;
> +}
> +
> +static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	if (dai->active) {
> +		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +		conf &= ~JZ_AIC_CONF_ENABLE;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +		clk_disable(i2s->clk_i2s);
> +	}
> +
> +	clk_disable(i2s->clk_aic);
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_resume(struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	clk_enable(i2s->clk_aic);
> +
> +	if (dai->active) {
> +		clk_enable(i2s->clk_i2s);
> +
> +		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +		conf |= JZ_AIC_CONF_ENABLE;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	}
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
> +		(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
> +		JZ_AIC_CONF_OVERFLOW_PLAY_LAST |
> +		JZ_AIC_CONF_I2S |
> +		JZ_AIC_CONF_INTERNAL_CODEC;
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET);
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	return 0;
> +}
> +
> +
> +static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
> +	.startup = jz4740_i2s_startup,
> +	.shutdown = jz4740_i2s_shutdown,
> +	.trigger = jz4740_i2s_trigger,
> +	.hw_params = jz4740_i2s_hw_params,
> +	.set_fmt = jz4740_i2s_set_fmt,
> +	.set_clkdiv = jz4740_i2s_set_clkdiv,
> +	.set_sysclk = jz4740_i2s_set_sysclk,
> +};
> +
> +#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
> +		SNDRV_PCM_FMTBIT_S16_LE)
> +
> +struct snd_soc_dai jz4740_i2s_dai = {
> +	.name = "jz4740-i2s",
> +	.probe = jz4740_i2s_probe,
> +	.playback = {
> +		.channels_min = 1,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = JZ4740_I2S_FMTS,
> +	},
> +	.capture = {
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = JZ4740_I2S_FMTS,
> +	},
> +	.symmetric_rates = 1,
> +	.ops = &jz4740_i2s_dai_ops,
> +	.suspend = jz4740_i2s_suspend,
> +	.resume = jz4740_i2s_resume,
> +};
> +EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
> +
> +static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
> +{
> +	struct jz4740_dma_config *dma_config;
> +
> +	/* Playback */
> +	dma_config = &i2s->pcm_config_playback.dma_config;
> +	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
> +	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
> +	dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
> +	dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
> +	dma_config->mode = JZ4740_DMA_MODE_SINGLE;
> +	i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
> +
> +	/* Capture */
> +	dma_config = &i2s->pcm_config_capture.dma_config;
> +	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
> +	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
> +	dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
> +	dma_config->flags = JZ4740_DMA_DST_AUTOINC;
> +	dma_config->mode = JZ4740_DMA_MODE_SINGLE;
> +	i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
> +}
> +
> +static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
> +{
> +	struct jz4740_i2s *i2s;
> +	int ret;
> +
> +	i2s = kzalloc(sizeof(*i2s), GFP_KERNEL);
> +
> +	if (!i2s)
> +		return -ENOMEM;
> +
> +	i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	if (!i2s->mem) {
> +		ret = -ENOENT;
> +		goto err_free;
> +	}
> +
> +	i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem),
> +				pdev->name);
> +
> +	if (!i2s->mem) {
> +		ret = -EBUSY;
> +		goto err_free;
> +	}
> +
> +	i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem));
> +
> +	if (!i2s->base) {
> +		ret = -EBUSY;
> +		goto err_release_mem_region;
> +	}
> +
> +	i2s->phys_base = i2s->mem->start;
> +
> +	i2s->clk_aic = clk_get(&pdev->dev, "aic");
> +	if (IS_ERR(i2s->clk_aic)) {
> +		ret = PTR_ERR(i2s->clk_aic);
> +		goto err_iounmap;
> +	}
> +
> +	i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
> +	if (IS_ERR(i2s->clk_i2s)) {
> +		ret = PTR_ERR(i2s->clk_i2s);
> +		goto err_iounmap;
> +	}
> +
> +	clk_enable(i2s->clk_aic);
> +
> +	jz4740_i2c_init_pcm_config(i2s);
> +
> +	jz4740_i2s_dai.private_data = i2s;
> +	ret = snd_soc_register_dai(&jz4740_i2s_dai);
> +
> +	platform_set_drvdata(pdev, i2s);
> +
> +	return 0;
> +
> +err_iounmap:
> +	iounmap(i2s->base);
> +err_release_mem_region:
> +	release_mem_region(i2s->mem->start, resource_size(i2s->mem));
> +err_free:
> +	kfree(i2s);
> +
> +	return ret;
> +}
> +
> +static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
> +{
> +	struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
> +
> +	snd_soc_unregister_dai(&jz4740_i2s_dai);
> +
> +	clk_disable(i2s->clk_aic);
> +	clk_put(i2s->clk_i2s);
> +	clk_put(i2s->clk_aic);
> +
> +	iounmap(i2s->base);
> +	release_mem_region(i2s->mem->start, resource_size(i2s->mem));
> +
> +	platform_set_drvdata(pdev, NULL);
> +	kfree(i2s);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver jz4740_i2s_driver = {
> +	.probe = jz4740_i2s_dev_probe,
> +	.remove = __devexit_p(jz4740_i2s_dev_remove),
> +	.driver = {
> +		.name = "jz4740-i2s",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static int __init jz4740_i2s_init(void)
> +{
> +	return platform_driver_register(&jz4740_i2s_driver);
> +}
> +module_init(jz4740_i2s_init);
> +
> +static void __exit jz4740_i2s_exit(void)
> +{
> +	platform_driver_unregister(&jz4740_i2s_driver);
> +}
> +module_exit(jz4740_i2s_exit);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:jz4740-i2s");
> diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h
> new file mode 100644
> index 0000000..da22ed8
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-i2s.h
> @@ -0,0 +1,18 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _JZ4740_I2S_H
> +#define _JZ4740_I2S_H
> +
> +/* I2S clock source */
> +#define JZ4740_I2S_CLKSRC_EXT 0
> +#define JZ4740_I2S_CLKSRC_PLL 1
> +
> +#define JZ4740_I2S_BIT_CLK		0
> +
> +extern struct snd_soc_dai jz4740_i2s_dai;
> +
> +#endif
> diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
> new file mode 100644
> index 0000000..fd1c203
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-pcm.c
> @@ -0,0 +1,350 @@
> +/*
> + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + *  This program is free software; you can redistribute	 it and/or modify it
> + *  under  the terms of	 the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the	License, or (at your
> + *  option) any later version.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +#include <linux/dma-mapping.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +
> +#include <asm/mach-jz4740/dma.h>
> +#include "jz4740-pcm.h"
> +
> +struct jz4740_runtime_data {
> +	unsigned int dma_period;
> +	dma_addr_t dma_start;
> +	dma_addr_t dma_pos;
> +	dma_addr_t dma_end;
> +
> +	struct jz4740_dma_chan *dma;
> +
> +	dma_addr_t fifo_addr;
> +};
> +
> +/* identify hardware playback capabilities */
> +static const struct snd_pcm_hardware jz4740_pcm_hardware = {
> +	.info = SNDRV_PCM_INFO_MMAP |
> +		SNDRV_PCM_INFO_MMAP_VALID |
> +		SNDRV_PCM_INFO_INTERLEAVED |
> +		SNDRV_PCM_INFO_BLOCK_TRANSFER,
> +	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
> +
> +	.rates			= SNDRV_PCM_RATE_8000_48000,
> +	.channels_min		= 1,
> +	.channels_max		= 2,
> +	.period_bytes_min	= 16,
> +	.period_bytes_max	= 2 * PAGE_SIZE,
> +	.periods_min		= 2,
> +	.periods_max		= 128,
> +	.buffer_bytes_max	= 128 * 2 * PAGE_SIZE,
> +	.fifo_size		= 32,
> +};
> +
> +static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd, int stream)
> +{
> +	unsigned int count;
> +
> +	if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
> +		count = prtd->dma_end - prtd->dma_pos;
> +	else
> +		count = prtd->dma_period;
> +
> +	jz4740_dma_disable(prtd->dma);
> +
> +	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
> +		jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
> +	} else {
> +		jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
> +		jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
> +	}
> +
> +	jz4740_dma_set_transfer_count(prtd->dma, count);
> +
> +	jz4740_dma_enable(prtd->dma);
> +
> +	prtd->dma_pos += prtd->dma_period;
> +	if (prtd->dma_pos >= prtd->dma_end)
> +		prtd->dma_pos = prtd->dma_start;
> +}
> +
> +static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
> +	void *dev_id)
> +{
> +	struct snd_pcm_substream *substream = dev_id;
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +
> +	snd_pcm_period_elapsed(substream);
> +
> +	jz4740_pcm_start_transfer(prtd, substream->stream);
> +}
> +
> +static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct jz4740_pcm_config *config;
> +
> +	config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
> +	if (!prtd->dma) {
> +		const char *dma_channel_name;
> +		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +			dma_channel_name = "PCM Playback";
> +		else
> +			dma_channel_name = "PCM Capture";
> +
> +		prtd->dma = jz4740_dma_request(substream, dma_channel_name);
> +	}
> +
> +	if (!prtd->dma)
> +		return -EBUSY;
> +
> +	jz4740_dma_configure(prtd->dma, &config->dma_config);
> +	prtd->fifo_addr = config->fifo_addr;
> +
> +	jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
> +
> +	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> +	runtime->dma_bytes = params_buffer_bytes(params);
> +
> +	prtd->dma_period = params_period_bytes(params);
> +	prtd->dma_start = runtime->dma_addr;
> +	prtd->dma_pos = prtd->dma_start;
> +	prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
> +
> +	return 0;
> +}
> +
> +static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
> +{
> +	struct jz4740_runtime_data *prtd = substream->runtime->private_data;
> +
> +	snd_pcm_set_runtime_buffer(substream, NULL);
> +	if (prtd->dma) {
> +		jz4740_dma_free(prtd->dma);
> +		prtd->dma = NULL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
> +{
> +	struct jz4740_runtime_data *prtd = substream->runtime->private_data;
> +	int ret = 0;
> +
> +	if (!prtd->dma)
> +			return 0;
> +
> +	prtd->dma_pos = prtd->dma_start;
> +
> +	return ret;
> +}
> +
> +static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +
> +	int ret = 0;
> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		jz4740_pcm_start_transfer(prtd, substream->stream);
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		jz4740_dma_disable(prtd->dma);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +	unsigned long count, pos;
> +	snd_pcm_uframes_t offset;
> +	struct jz4740_dma_chan *dma = prtd->dma;
> +
> +	count = jz4740_dma_get_residue(dma);
> +	if (prtd->dma_pos == prtd->dma_start)
> +		pos = prtd->dma_end - prtd->dma_start - count;
> +	else
> +		pos = prtd->dma_pos - prtd->dma_start - count;
> +
> +	offset = bytes_to_frames(runtime, pos);
> +	if (offset >= runtime->buffer_size)
> +		offset = 0;
> +
> +	return offset;
> +}
> +
> +static int jz4740_pcm_open(struct snd_pcm_substream *substream)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd;
> +
> +	snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
> +	prtd = kzalloc(sizeof(struct jz4740_runtime_data), GFP_KERNEL);
> +
> +	if (prtd == NULL)
> +		return -ENOMEM;
> +
> +	runtime->private_data = prtd;
> +	return 0;
> +}
> +
> +static int jz4740_pcm_close(struct snd_pcm_substream *substream)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +
> +	kfree(prtd);
> +
> +	return 0;
> +}
> +
> +static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
> +	struct vm_area_struct *vma)
> +{
> +	return remap_pfn_range(vma, vma->vm_start,
> +			substream->dma_buffer.addr >> PAGE_SHIFT,
> +			vma->vm_end - vma->vm_start, vma->vm_page_prot);
> +}
> +
> +static struct snd_pcm_ops jz4740_pcm_ops = {
> +	.open		= jz4740_pcm_open,
> +	.close		= jz4740_pcm_close,
> +	.ioctl		= snd_pcm_lib_ioctl,
> +	.hw_params	= jz4740_pcm_hw_params,
> +	.hw_free	= jz4740_pcm_hw_free,
> +	.prepare	= jz4740_pcm_prepare,
> +	.trigger	= jz4740_pcm_trigger,
> +	.pointer	= jz4740_pcm_pointer,
> +	.mmap		= jz4740_pcm_mmap,
> +};
> +
> +static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
> +{
> +	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
> +	struct snd_dma_buffer *buf = &substream->dma_buffer;
> +	size_t size = jz4740_pcm_hardware.buffer_bytes_max;
> +
> +	buf->dev.type = SNDRV_DMA_TYPE_DEV;
> +	buf->dev.dev = pcm->card->dev;
> +	buf->private_data = NULL;
> +
> +	buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
> +					  &buf->addr, GFP_KERNEL);
> +	if (!buf->area)
> +		return -ENOMEM;
> +
> +	buf->bytes = size;
> +
> +	return 0;
> +}
> +
> +static void jz4740_pcm_free(struct snd_pcm *pcm)
> +{
> +	struct snd_pcm_substream *substream;
> +	struct snd_dma_buffer *buf;
> +	int stream;
> +
> +	for (stream = 0; stream < 2; stream++) {
> +		substream = pcm->streams[stream].substream;
> +		if (!substream)
> +			continue;
> +
> +		buf = &substream->dma_buffer;
> +		if (!buf->area)
> +			continue;
> +
> +		dma_free_noncoherent(pcm->card->dev, buf->bytes,
> +		  buf->area, buf->addr);
> +		buf->area = NULL;
> +	}
> +}
> +
> +static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
> +
> +int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
> +	struct snd_pcm *pcm)
> +{
> +	int ret = 0;
> +
> +	if (!card->dev->dma_mask)
> +		card->dev->dma_mask = &jz4740_pcm_dmamask;
> +
> +	if (!card->dev->coherent_dma_mask)
> +		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> +
> +	if (dai->playback.channels_min) {
> +		ret = jz4740_pcm_preallocate_dma_buffer(pcm,
> +			SNDRV_PCM_STREAM_PLAYBACK);
> +		if (ret)
> +			goto err;
> +	}
> +
> +	if (dai->capture.channels_min) {
> +		ret = jz4740_pcm_preallocate_dma_buffer(pcm,
> +			SNDRV_PCM_STREAM_CAPTURE);
> +		if (ret)
> +			goto err;
> +	}
> +
> +err:
> +	return ret;
> +}
> +
> +struct snd_soc_platform jz4740_soc_platform = {
> +		.name		= "jz4740-pcm",
> +		.pcm_ops	= &jz4740_pcm_ops,
> +		.pcm_new	= jz4740_pcm_new,
> +		.pcm_free	= jz4740_pcm_free,
> +};
> +EXPORT_SYMBOL_GPL(jz4740_soc_platform);
> +
> +static int __init jz4740_soc_platform_init(void)
> +{
> +	return snd_soc_register_platform(&jz4740_soc_platform);
> +}
> +module_init(jz4740_soc_platform_init);
> +
> +static void __exit jz4740_soc_platform_exit(void)
> +{
> +	snd_soc_unregister_platform(&jz4740_soc_platform);
> +}
> +module_exit(jz4740_soc_platform_exit);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
> new file mode 100644
> index 0000000..e3f221e
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-pcm.h
> @@ -0,0 +1,22 @@
> +/*
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _JZ4740_PCM_H
> +#define _JZ4740_PCM_H
> +
> +#include <linux/dma-mapping.h>
> +#include <asm/mach-jz4740/dma.h>
> +
> +/* platform data */
> +extern struct snd_soc_platform jz4740_soc_platform;
> +
> +struct jz4740_pcm_config {
> +	struct jz4740_dma_config dma_config;
> +	phys_addr_t fifo_addr;
> +};
> +
> +#endif


From mcuos.com@gmail.com Thu Jun  3 07:45:45 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 07:45:50 +0200 (CEST)
Received: from mail-px0-f177.google.com ([209.85.212.177]:64079 "EHLO
        mail-px0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491069Ab0FCFpp (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 07:45:45 +0200
Received: by pxi1 with SMTP id 1so3106003pxi.36
        for <multiple recipients>; Wed, 02 Jun 2010 22:45:36 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:message-id:date:from
         :user-agent:mime-version:to:cc:subject:references:in-reply-to
         :content-type:content-transfer-encoding;
        bh=2ZE7mxWDX0xS3sER8s7imhAvshrEw4PMscp0IygrGPw=;
        b=Lr/xfNzUk51gfzrwZm5RYABWUFt6EY6BEm9L4obNJ3l2U+Ykldojy6ntAaa6EqSx0b
         VIKVttof6WmgLgQ9Tbq8aMy99II5jSy2+Q9Nh0UEIZSrEHT3e+No+6m2wT17b/voFe5g
         mlPowwHgqFhDOcrqkubdSps8VIGZTw08koZKM=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=message-id:date:from:user-agent:mime-version:to:cc:subject
         :references:in-reply-to:content-type:content-transfer-encoding;
        b=X00SpzNx14XJhYqRaQHjJOoeKfvWUTV97iR7S+BcwmsKxrGF978/XWNCxRPNA0Bda5
         6cp+ORZjaworlgAGof4ThO/Ep+4EdTcMv3Si3QWE77nlaBrOhLZazQQySUwLJmbXcrb7
         iPNdv4DlS3u2llmpoXM5kOnNHpCtgpwMBmKoc=
Received: by 10.140.87.41 with SMTP id k41mr7657779rvb.109.1275543936117;
        Wed, 02 Jun 2010 22:45:36 -0700 (PDT)
Received: from [192.168.1.10] ([116.226.201.224])
        by mx.google.com with ESMTPS id h11sm2014957rvm.0.2010.06.02.22.45.28
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Wed, 02 Jun 2010 22:45:35 -0700 (PDT)
Message-ID: <4C074171.2080106@gmail.com>
Date:   Thu, 03 Jun 2010 13:45:21 +0800
From:   Wan ZongShun <mcuos.com@gmail.com>
User-Agent: Thunderbird 2.0.0.24 (X11/20100411)
MIME-Version: 1.0
To:     Lars-Peter Clausen <lars@metafoo.de>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>
Subject: Re: [alsa-devel] [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec
 driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-4-git-send-email-lars@metafoo.de>
In-Reply-To: <1275505950-17334-4-git-send-email-lars@metafoo.de>
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
X-archive-position: 27037
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: mcuos.com@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2083
Content-Length: 18929
Lines: 616

Hi Lars-Peter Clausen,

Your all the patches have two kinds of 'WARNING:',as following:

(1)'WARNING: line over 80 characters' and

Please make a line less than 80 characters.

(2)'WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable'

I can illustrate by a example,bellow:

struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
        .probe = jz4740_codec_dev_probe,
        .remove = jz4740_codec_dev_remove,
};
EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);

I think the ';' should be removed according to 'checkpatch.pl', but Andrew Morton just said the 'warning'
reason from the checkpatch script's own BUG, so far, I could not get any comments about this.

So, Mark & Liam, any comments regarding this 'checkpatch script's own BUG'?

Lars-Peter Clausen:
> This patch adds support for the JZ4740 internal codec.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> Cc: alsa-devel@alsa-project.org
> ---
>  sound/soc/codecs/Kconfig        |    4 +
>  sound/soc/codecs/Makefile       |    2 +
>  sound/soc/codecs/jz4740-codec.c |  502 +++++++++++++++++++++++++++++++++++++++
>  sound/soc/codecs/jz4740-codec.h |   20 ++
>  4 files changed, 528 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/codecs/jz4740-codec.c
>  create mode 100644 sound/soc/codecs/jz4740-codec.h
> 
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 31ac553..b8008df 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -23,6 +23,7 @@ config SND_SOC_ALL_CODECS
>  	select SND_SOC_AK4671 if I2C
>  	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
>  	select SND_SOC_CS4270 if I2C
> +	select SND_SOC_JZ4740 if SOC_JZ4740
>  	select SND_SOC_MAX9877 if I2C
>  	select SND_SOC_DA7210 if I2C
>  	select SND_SOC_PCM3008
> @@ -269,6 +270,9 @@ config SND_SOC_WM9712
>  config SND_SOC_WM9713
>  	tristate
>  
> +config SND_SOC_JZ4740_CODEC
> +	tristate
> +
>  # Amp
>  config SND_SOC_MAX9877
>  	tristate
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 91429ea..4c7ee31 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -56,6 +56,7 @@ snd-soc-wm9705-objs := wm9705.o
>  snd-soc-wm9712-objs := wm9712.o
>  snd-soc-wm9713-objs := wm9713.o
>  snd-soc-wm-hubs-objs := wm_hubs.o
> +snd-soc-jz4740-codec-objs := jz4740-codec.o
>  
>  # Amp
>  snd-soc-max9877-objs := max9877.o
> @@ -121,6 +122,7 @@ obj-$(CONFIG_SND_SOC_WM9705)	+= snd-soc-wm9705.o
>  obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
>  obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
>  obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
> +obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
>  
>  # Amp
>  obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
> diff --git a/sound/soc/codecs/jz4740-codec.c b/sound/soc/codecs/jz4740-codec.c
> new file mode 100644
> index 0000000..6e4b741
> --- /dev/null
> +++ b/sound/soc/codecs/jz4740-codec.c
> @@ -0,0 +1,502 @@
> +/*
> + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <linux/delay.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/initval.h>
> +#include <sound/soc-dapm.h>
> +#include <sound/soc.h>
> +
> +#define JZ4740_REG_CODEC_1 0x0
> +#define JZ4740_REG_CODEC_2 0x1
> +
> +#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
> +#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
> +#define JZ4740_CODEC_1_SW1_ENABLE BIT(27)
> +#define JZ4740_CODEC_1_ADC_ENABLE BIT(26)
> +#define JZ4740_CODEC_1_SW2_ENABLE BIT(25)
> +#define JZ4740_CODEC_1_DAC_ENABLE BIT(24)
> +#define JZ4740_CODEC_1_VREF_DISABLE BIT(20)
> +#define JZ4740_CODEC_1_VREF_AMP_DISABLE BIT(19)
> +#define JZ4740_CODEC_1_VREF_PULL_DOWN BIT(18)
> +#define JZ4740_CODEC_1_VREF_LOW_CURRENT BIT(17)
> +#define JZ4740_CODEC_1_VREF_HIGH_CURRENT BIT(16)
> +#define JZ4740_CODEC_1_HEADPHONE_DISABLE BIT(14)
> +#define JZ4740_CODEC_1_HEADPHONE_AMP_CHANGE_ANY BIT(13)
> +#define JZ4740_CODEC_1_HEADPHONE_CHANGE BIT(12)
> +#define JZ4740_CODEC_1_HEADPHONE_PULL_DOWN_M BIT(11)
> +#define JZ4740_CODEC_1_HEADPHONE_PULL_DOWN_R BIT(10)
> +#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M BIT(9)
> +#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN BIT(8)
> +#define JZ4740_CODEC_1_SUSPEND BIT(1)
> +#define JZ4740_CODEC_1_RESET BIT(0)
> +
> +#define JZ4740_CODEC_1_LINE_ENABLE_OFFSET 29
> +#define JZ4740_CODEC_1_MIC_ENABLE_OFFSET 28
> +#define JZ4740_CODEC_1_SW1_ENABLE_OFFSET 27
> +#define JZ4740_CODEC_1_ADC_ENABLE_OFFSET 26
> +#define JZ4740_CODEC_1_SW2_ENABLE_OFFSET 25
> +#define JZ4740_CODEC_1_DAC_ENABLE_OFFSET 24
> +#define JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET 14
> +#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET 8
> +
> +#define JZ4740_CODEC_2_INPUT_VOLUME_MASK		0x1f0000
> +#define JZ4740_CODEC_2_SAMPLE_RATE_MASK			0x000f00
> +#define JZ4740_CODEC_2_MIC_BOOST_GAIN_MASK		0x000030
> +#define JZ4740_CODEC_2_HEADPHONE_VOLUME_MASK	0x000003
> +
> +#define JZ4740_CODEC_2_INPUT_VOLUME_OFFSET		16
> +#define JZ4740_CODEC_2_SAMPLE_RATE_OFFSET		 8
> +#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET	 4
> +#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET	 0
> +
> +struct jz4740_codec {
> +	void __iomem *base;
> +	struct resource *mem;
> +
> +	uint32_t reg_cache[2];
> +	struct snd_soc_codec codec;
> +};
> +
> +static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
> +{
> +	return container_of(codec, struct jz4740_codec, codec);
> +}
> +
> +static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, unsigned int reg)
> +{
> +	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
> +	return readl(jz4740_codec->base + (reg << 2));
> +}
> +
> +static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
> +	unsigned int val)
> +{
> +	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
> +	jz4740_codec->reg_cache[reg] = val;
> +
> +	writel(val, jz4740_codec->base + (reg << 2));
> +	return 0;
> +}
> +
> +static const struct snd_kcontrol_new jz4740_codec_controls[] = {
> +	SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
> +			JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
> +	SOC_SINGLE("Capture Volume", JZ4740_REG_CODEC_2,
> +			JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
> +	SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
> +	SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
> +			JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
> +};
> +
> +static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
> +	SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0),
> +	SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0),
> +};
> +
> +static const struct snd_kcontrol_new jz4740_codec_input_controls[] = {
> +	SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0),
> +	SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0),
> +};
> +
> +static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = {
> +	SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0),
> +	SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0),
> +
> +	SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET, 1,
> +			jz4740_codec_output_controls,
> +			ARRAY_SIZE(jz4740_codec_output_controls)),
> +
> +	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
> +			jz4740_codec_input_controls,
> +			ARRAY_SIZE(jz4740_codec_input_controls)),
> +	SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
> +
> +	SND_SOC_DAPM_OUTPUT("LOUT"),
> +	SND_SOC_DAPM_OUTPUT("ROUT"),
> +
> +	SND_SOC_DAPM_INPUT("MIC"),
> +	SND_SOC_DAPM_INPUT("LIN"),
> +	SND_SOC_DAPM_INPUT("RIN"),
> +};
> +
> +static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
> +
> +	{"Line Input", NULL, "LIN"},
> +	{"Line Input", NULL, "RIN"},
> +
> +	{"Input Mixer", "Line Capture Switch", "Line Input"},
> +	{"Input Mixer", "Mic Capture Switch", "MIC"},
> +
> +	{"ADC", NULL, "Input Mixer"},
> +
> +	{"Output Mixer", "Bypass Switch", "Input Mixer"},
> +	{"Output Mixer", "DAC Switch", "DAC"},
> +
> +	{"LOUT", NULL, "Output Mixer"},
> +	{"ROUT", NULL, "Output Mixer"},
> +};
> +
> +static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
> +{
> +	uint32_t val;
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct snd_soc_device *socdev = rtd->socdev;
> +	struct snd_soc_codec *codec = socdev->card->codec;
> +
> +	switch (params_format(params)) {
> +	case SNDRV_PCM_FORMAT_S8:
> +	case SNDRV_PCM_FORMAT_S16_LE:
> +	case SNDRV_PCM_FORMAT_S18_3LE:
> +		break;
> +	default:
> +		return -EINVAL;
> +		break;
> +	}
> +
> +	switch (params_rate(params)) {
> +	case 8000:
> +		val = 0;
> +		break;
> +	case 11025:
> +		val = 1;
> +		break;
> +	case 12000:
> +		val = 2;
> +		break;
> +	case 16000:
> +		val = 3;
> +		break;
> +	case 22050:
> +		val = 4;
> +		break;
> +	case 24000:
> +		val = 5;
> +		break;
> +	case 32000:
> +		val = 6;
> +		break;
> +	case 44100:
> +		val = 7;
> +		break;
> +	case 48000:
> +		val = 8;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
> +
> +	snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
> +				JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
> +
> +	return 0;
> +}
> +
> +static int jz4740_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +{
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_I2S:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_NB_NF:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
> +	.hw_params = jz4740_codec_hw_params,
> +	.set_fmt = jz4740_codec_set_fmt,
> +};
> +
> +struct snd_soc_dai jz4740_codec_dai = {
> +	.name = "jz-codec",
> +	.playback = {
> +		.stream_name = "Playback",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
> +	},
> +	.capture = {
> +		.stream_name = "Capture",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
> +	},
> +	.ops = &jz4740_codec_dai_ops,
> +	.symmetric_rates = 1,
> +};
> +EXPORT_SYMBOL_GPL(jz4740_codec_dai);
> +
> +static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
> +	enum snd_soc_bias_level level)
> +{
> +
> +	if (codec->bias_level == SND_SOC_BIAS_OFF && level != SND_SOC_BIAS_OFF) {
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
> +		udelay(2);
> +
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
> +	}
> +	switch (level) {
> +	case SND_SOC_BIAS_ON:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_DISABLE |
> +			JZ4740_CODEC_1_VREF_AMP_DISABLE |
> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M |
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
> +			0);
> +		break;
> +	case SND_SOC_BIAS_PREPARE:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT);
> +		break;
> +	case SND_SOC_BIAS_STANDBY:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE,
> +			JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE);
> +		break;
> +	case SND_SOC_BIAS_OFF:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SUSPEND, JZ4740_CODEC_1_SUSPEND);
> +		break;
> +	}
> +	codec->bias_level = level;
> +
> +	return 0;
> +}
> +
> +
> +static struct snd_soc_codec *jz4740_codec_codec;
> +
> +static int jz4740_codec_dev_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
> +	struct snd_soc_codec *codec = jz4740_codec_codec;
> +
> +	BUG_ON(!codec);
> +
> +	socdev->card->codec = codec;
> +
> +	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
> +		return ret;
> +	}
> +
> +	snd_soc_add_controls(codec, jz4740_codec_controls,
> +		ARRAY_SIZE(jz4740_codec_controls));
> +
> +	snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
> +		ARRAY_SIZE(jz4740_codec_dapm_widgets));
> +
> +	snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
> +		ARRAY_SIZE(jz4740_codec_dapm_routes));
> +
> +	snd_soc_dapm_new_widgets(codec);
> +
> +	return 0;
> +}
> +
> +static int jz4740_codec_dev_remove(struct platform_device *pdev)
> +{
> +	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
> +	snd_soc_free_pcms(socdev);
> +	snd_soc_dapm_free(socdev);
> +
> +	return 0;
> +}
> +
> +struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
> +	.probe = jz4740_codec_dev_probe,
> +	.remove = jz4740_codec_dev_remove,
> +};
> +EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
> +
> +static int __devinit jz4740_codec_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct jz4740_codec *jz4740_codec;
> +	struct snd_soc_codec *codec;
> +
> +	jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
> +
> +	if (!jz4740_codec)
> +		return -ENOMEM;
> +
> +	jz4740_codec->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	if (!jz4740_codec->mem) {
> +		dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
> +		ret = -ENOENT;
> +		goto err_free_codec;
> +	}
> +
> +	jz4740_codec->mem = request_mem_region(jz4740_codec->mem->start,
> +				resource_size(jz4740_codec->mem), pdev->name);
> +
> +	if (!jz4740_codec->mem) {
> +		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
> +		ret = -EBUSY;
> +		goto err_free_codec;
> +	}
> +
> +	jz4740_codec->base = ioremap(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
> +
> +	if (!jz4740_codec->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
> +		ret = -EBUSY;
> +		goto err_release_mem_region;
> +	}
> +
> +	jz4740_codec_dai.dev = &pdev->dev;
> +
> +	codec = &jz4740_codec->codec;
> +
> +	codec->dev		= &pdev->dev;
> +	codec->name		= "jz-codec";
> +	codec->owner		= THIS_MODULE;
> +
> +	codec->read		= jz4740_codec_read;
> +	codec->write		= jz4740_codec_write;
> +	codec->set_bias_level	= jz4740_codec_set_bias_level;
> +	codec->bias_level	= SND_SOC_BIAS_OFF;
> +
> +	codec->dai		= &jz4740_codec_dai;
> +	codec->num_dai		= 1;
> +
> +	codec->reg_cache	= jz4740_codec->reg_cache;
> +	codec->reg_cache_size	= 2;
> +
> +	mutex_init(&codec->mutex);
> +	INIT_LIST_HEAD(&codec->dapm_widgets);
> +	INIT_LIST_HEAD(&codec->dapm_paths);
> +
> +	jz4740_codec_codec = codec;
> +
> +	snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +				JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
> +
> +
> +	platform_set_drvdata(pdev, jz4740_codec);
> +	ret = snd_soc_register_codec(codec);
> +
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register codec\n");
> +		goto err_iounmap;
> +	}
> +
> +	ret = snd_soc_register_dai(&jz4740_codec_dai);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register codec dai\n");
> +		goto err_unregister_codec;
> +	}
> +
> +	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
> +
> +	return 0;
> +err_unregister_codec:
> +	snd_soc_unregister_codec(codec);
> +err_iounmap:
> +	iounmap(jz4740_codec->base);
> +err_release_mem_region:
> +	release_mem_region(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
> +err_free_codec:
> +	kfree(jz4740_codec);
> +
> +	return ret;
> +}
> +
> +static int __devexit jz4740_codec_remove(struct platform_device *pdev)
> +{
> +	struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
> +
> +	snd_soc_unregister_dai(&jz4740_codec_dai);
> +	snd_soc_unregister_codec(&jz4740_codec->codec);
> +
> +	iounmap(jz4740_codec->base);
> +	release_mem_region(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
> +
> +	platform_set_drvdata(pdev, NULL);
> +	kfree(jz4740_codec);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver jz4740_codec_driver = {
> +	.probe = jz4740_codec_probe,
> +	.remove = __devexit_p(jz4740_codec_remove),
> +	.driver = {
> +		.name = "jz4740-codec",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static int __init jz4740_codec_init(void)
> +{
> +	return platform_driver_register(&jz4740_codec_driver);
> +}
> +module_init(jz4740_codec_init);
> +
> +static void __exit jz4740_codec_exit(void)
> +{
> +	platform_driver_unregister(&jz4740_codec_driver);
> +}
> +module_exit(jz4740_codec_exit);
> +
> +MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:jz-codec");
> diff --git a/sound/soc/codecs/jz4740-codec.h b/sound/soc/codecs/jz4740-codec.h
> new file mode 100644
> index 0000000..b5a0691
> --- /dev/null
> +++ b/sound/soc/codecs/jz4740-codec.h
> @@ -0,0 +1,20 @@
> +/*
> + * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
> +#define __SND_SOC_CODECS_JZ4740_CODEC_H__
> +
> +extern struct snd_soc_dai jz4740_codec_dai;
> +extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
> +
> +#endif


From Gurumurthy.Gowdar@gmobis.com Thu Jun  3 11:41:23 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 11:41:26 +0200 (CEST)
Received: from anti.mobis.co.kr ([211.217.52.67]:55596 "HELO
        sniper.mobis.co.kr" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with SMTP id S1492001Ab0FCJlX convert rfc822-to-8bit (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 11:41:23 +0200
Received: (snipe 28071 invoked by uid 0); 3 Jun 2010 18:41:09 +0900
Received: from gurumurthy.gowdar@gmobis.com with  Spamsniper 2.94.22 (Processed in 0.011195 secs);
Received: from unknown (HELO msmobiweb.mobis.co.kr) (10.240.100.165)
  by unknown with SMTP; 3 Jun 2010 18:41:09 +0900
X-RCPTTO: linux-mips@linux-mips.org
Received: from mkegmal01.global.mobis.co.kr ([10.240.200.82]) by msmobiweb.mobis.co.kr with Microsoft SMTPSVC(6.0.3790.3959);
         Thu, 3 Jun 2010 18:49:06 +0900
X-MimeOLE: Produced By Microsoft Exchange V6.5
Content-class: urn:content-classes:message
MIME-Version: 1.0
Content-Type:   text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7BIT
Subject: Linux kernel hangs in panic , not able to mount RFS
Date:   Thu, 3 Jun 2010 18:46:57 +0900
Message-ID: <5858DE952C53A441BDA3408A0524130104CCE0D5@mkegmal01>
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
Thread-Topic: Linux kernel hangs in panic , not able to mount RFS
Thread-Index: AcsDAbUc9tP7ZxlLSPSukUac3icAKw==
From:   =?iso-8859-1?Q?=A0Gurumurthy_G_M?= <Gurumurthy.Gowdar@gmobis.com>
To:     <linux-mips@linux-mips.org>
X-OriginalArrivalTime: 03 Jun 2010 09:49:06.0000 (UTC) FILETIME=[017D5500:01CB0302]
X-archive-position: 27038
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: Gurumurthy.Gowdar@gmobis.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2245
Content-Length: 6091
Lines: 182


Dear All,
         I am using MIPS32 AU1350 processor board with 2MB of NOR Flash, I have programmed u-boot and Linux kernel in NOR Flash. U-boot is working able to boot linux kernel but not able to mount root filesystem from SDRAM.

I have created uRamdisk and also passed boot arguments.

Below is the error log. let me know whether I am missing something.

U-Boot 2010.03 (May 28 2010 - 21:01:02)

Linux Advanced AVN Platform
CPU: Au1350 660MHz, id: 0x80, rev: 0x01
DRAM:  256 MB
Flash:  2 MB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
LinuxAVN=> loadb 0x81000000
## Ready for binary (kermit) download to 0x81000000 at 0 bps...

(Back at localhost)
----------------------------------------------------
(/home/gurumurthy/Downloads/kermit/) C-Kermit>send /tftpboot/rdImage
(/home/gurumurthy/Downloads/kermit/) C-Kermit>\c
Connecting to /dev/ttyS0, speed 115200
 Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------
## Total Size      = 0x002ed937 = 3070263 Bytes
## Start Addr      = 0x81000000
LinuxAVN=> imls
Legacy Image at BFC50000:
   Image Name:   Linux-2.6.28.1
   Created:      2010-06-02  11:38:32 UTC
   Image Type:   MIPS Linux Kernel Image (gzip compressed)
   Data Size:    1134559 Bytes =  1.1 MB
   Load Address: 80100000
   Entry Point:  80104730
   Verifying Checksum ... OK
LinuxAVN=> iminfo 0x81000000

## Checking Image at 81000000 ...
   Legacy image found
   Image Name:  
   Created:      2010-06-02  11:11:16 UTC
   Image Type:   MIPS Linux RAMDisk Image (gzip compressed)
   Data Size:    3070199 Bytes =  2.9 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
LinuxAVN=> setenv bootargs console=ttyS0,115200 root=/dev/ram0 rw
LinuxAVN=> printenv
baudrate=115200
stdin=serial
stdout=serial
stderr=serial
filesize=2ED937
bootargs=console=ttyS0,115200 root=/dev/ram0 rw

Environment size: 121/65532 bytes
LinuxAVN=> 
baudrate=115200
stdin=serial
stdout=serial
stderr=serial
filesize=2ED937
bootargs=console=ttyS0,115200 root=/dev/ram0 rw

Environment size: 121/65532 bytes
LinuxAVN=>
baudrate=115200
stdin=serial
stdout=serial
stderr=serial
filesize=2ED937
bootargs=console=ttyS0,115200 root=/dev/ram0 rw

Environment size: 121/65532 bytes
LinuxAVN=>
baudrate=115200
stdin=serial
stdout=serial
stderr=serial
filesize=2ED937
bootargs=console=ttyS0,115200 root=/dev/ram0 rw

Environment size: 121/65532 bytes
LinuxAVN=> bootm
## Booting kernel from Legacy Image at 81000000 ...
   Image Name:  
   Created:      2010-06-02  11:11:16 UTC
   Image Type:   MIPS Linux RAMDisk Image (gzip compressed)
   Data Size:    3070199 Bytes =  2.9 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
Wrong Image Type for bootm command
ERROR: can't get kernel image!
LinuxAVN=>
LinuxAVN=>
LinuxAVN=> bootm 0xbfc50000 0x81000000
## Booting kernel from Legacy Image at bfc50000 ...
   Image Name:   Linux-2.6.28.1
   Created:      2010-06-02  11:38:32 UTC
   Image Type:   MIPS Linux Kernel Image (gzip compressed)
   Data Size:    1134559 Bytes =  1.1 MB
   Load Address: 80100000
   Entry Point:  80104730
   Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 81000000 ...
   Image Name:  
   Created:      2010-06-02  11:11:16 UTC
   Image Type:   MIPS Linux RAMDisk Image (gzip compressed)
   Data Size:    3070199 Bytes =  2.9 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

Linux version 2.6.29.4-rmi-126-DB1350 (root@gurumurthy) (gcc version 4.2.4) #31 Wed Jun 2 17:05:36 IST 2010
console [early0] enabled
CPU revision is: 800c8001 (Au13xx)
(PRId 800c8001) @ 660.00 MHz
RMI DBAu1300 Development Board
Determined physical RAM map:
 memory: 01800000 @ 00000000 (usable)
 memory: 0c800000 @ 01800000 (reserved)
 memory: 02000000 @ 0e000000 (usable)
Initrd not found or empty - disabling initrd
Zone PFN ranges:
  Normal   0x00000000 -> 0x00010000
  HighMem  0x00010000 -> 0x00010000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00010000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 65024
Kernel command line: console=ttyS0,115200 root=/dev/ram0 rw video=au1200fb:panel:bs
Primary instruction cache 16kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 32 bytes
PID hash table entries: 1024 (order: 10, 4096 bytes)
Alchemy clocksource installed
Console: colour dummy device 80x25
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 51012k/57344k available (1899k kernel code, 5988k reserved, 490k data, 152k init, 0k highmem)
Calibrating delay loop... 658.63 BogoMIPS (lpj=3293184)
Mount-cache hash table entries: 512
Hooking cpu_wait
bio: create slab <bio-0> at 0
SCSI subsystem initialized
Creating sysfs entry for board
Alchemy MEMPOOL initializing
Alchemy MEMPOOL registered at major 235
Available memory pools:
            LCD:  40 MB @ phys 0x01800000, free
            BSA:  64 MB @ phys 0x04000000, free
            MPE:  32 MB @ phys 0x08000000, free
            OGL:  64 MB @ phys 0x0a000000, free
squashfs: version 4.0 (2009/01/31) Phillip Lougher
msgmni has been set to 100
alg: No test for stdrng (krng)
io scheduler noop registered (default)
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
)console handover: boot [early0] -> real [ttyS0]) is a 8250
brd: module loaded
Driver 'sd' needs updating - please use bus_type methods
Driver 'sr' needs updating - please use bus_type methods
List of all partitions:
No filesystem could mount root, tried:  ext3 ext2 cramfs squashfs vfat msdos
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)


With Regards,
Gurumurthy

From mcdonald.shane@gmail.com Thu Jun  3 12:34:18 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 12:34:22 +0200 (CEST)
Received: from mail-vw0-f49.google.com ([209.85.212.49]:33440 "EHLO
        mail-vw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491098Ab0FCKeS (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 12:34:18 +0200
Received: by vws7 with SMTP id 7so9288568vws.36
        for <multiple recipients>; Thu, 03 Jun 2010 03:34:10 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:received:to:subject:cc
         :message-id:from:date;
        bh=R/0HBuAnOnK4RLMuB4Nf9q/9Mox+IklyuVS9HVyjwO4=;
        b=HrXKtlVmKPSwIWJSGI/8GkapRVVFhNzzsylzqV9wBfhJ6L9BlSzeogtEei5VsE3duv
         vosj60PWfz59ZWYQ21ErQv5qqdlKMUJuw2FVrJazTGqs3u2kamDwfIeXUNKACGAJ2mR0
         wlMVCaHIryJb3joRtNfcL+CNpjcsJlX96aNXQ=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=to:subject:cc:message-id:from:date;
        b=jBNYn2ujh2mZswLGmCC3MVvei9SEUD+QM8pPsqYlC0FyN8hJq7chhrVTNOfHBEuugT
         vEAg4FcW9RDptylE+3RKYVevkddpj7+MkqglyFI/WmdPj4sQwCswIEvgn0FsiED09DIF
         IjTuq+ggRoj622fIYCcIvC04mNOQSWBhJJMLM=
Received: by 10.224.121.212 with SMTP id i20mr4359212qar.11.1275561250739;
        Thu, 03 Jun 2010 03:34:10 -0700 (PDT)
Received: from localhost ([207.47.250.203])
        by mx.google.com with ESMTPS id 7sm17603490qwb.14.2010.06.03.03.34.09
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 03:34:10 -0700 (PDT)
Received: from shane by localhost with local (Exim 4.69)
        (envelope-from <shane@localhost>)
        id 1OK7kU-0008RG-Oj; Thu, 03 Jun 2010 04:34:06 -0600
To:     linux-mips@linux-mips.org
Subject: MIPS -queue: Move PMC-Sierra board Makefile parts to their own Platform file
Cc:     ralf@linux-mips.org
Message-Id: <E1OK7kU-0008RG-Oj@localhost>
From:   Shane McDonald <mcdonald.shane@gmail.com>
Date:   Thu, 03 Jun 2010 04:34:06 -0600
X-archive-position: 27039
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: mcdonald.shane@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2272
Content-Length: 2406
Lines: 76

This patch moves the entries for the PMC-Sierra boards from the main
mips Makefile into their own Platform file.

Signed-off-by: Shane McDonald <mcdonald.shane@gmail.com>
---
This patch applies against the linux-queue tree.
It has been compile tested for both the MSP71xx and the yosemite
defconfigs, the yosemite one after disabling the broken Titan GE driver.

 arch/mips/Kbuild.platforms    |    1 +
 arch/mips/Makefile            |   15 ---------------
 arch/mips/pmc-sierra/Platform |   14 ++++++++++++++
 3 files changed, 15 insertions(+), 15 deletions(-)
 create mode 100644 arch/mips/pmc-sierra/Platform

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 9b6e8d7..c074ee2 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -5,6 +5,7 @@ platforms += ar7
 platforms += cobalt
 platforms += loongson
 platforms += mipssim
+platforms += pmc-sierra
 platforms += sgi-ip27
 platforms += vr41xx
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6997faa..a27c645 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -222,21 +222,6 @@ load-$(CONFIG_MIPS_MALTA)	+= 0xffffffff80100000
 all-$(CONFIG_MIPS_MALTA)	:= $(COMPRESSION_FNAME).bin
 
 #
-# PMC-Sierra MSP SOCs
-#
-core-$(CONFIG_PMC_MSP)		+= arch/mips/pmc-sierra/msp71xx/
-cflags-$(CONFIG_PMC_MSP)	+= -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \
-					-mno-branch-likely
-load-$(CONFIG_PMC_MSP)		+= 0xffffffff80100000
-
-#
-# PMC-Sierra Yosemite
-#
-core-$(CONFIG_PMC_YOSEMITE)	+= arch/mips/pmc-sierra/yosemite/
-cflags-$(CONFIG_PMC_YOSEMITE)	+= -I$(srctree)/arch/mips/include/asm/mach-yosemite
-load-$(CONFIG_PMC_YOSEMITE)	+= 0xffffffff80100000
-
-#
 # LASAT platforms
 #
 core-$(CONFIG_LASAT)		+= arch/mips/lasat/
diff --git a/arch/mips/pmc-sierra/Platform b/arch/mips/pmc-sierra/Platform
new file mode 100644
index 0000000..f092f25
--- /dev/null
+++ b/arch/mips/pmc-sierra/Platform
@@ -0,0 +1,14 @@
+#
+# PMC-Sierra MSP SOCs
+#
+platform-$(CONFIG_PMC_MSP)	+= pmc-sierra/msp71xx/
+cflags-$(CONFIG_PMC_MSP)	+= -I$(srctree)/arch/mips/include/asm/pmc-sierra/msp71xx \
+					-mno-branch-likely
+load-$(CONFIG_PMC_MSP)		+= 0xffffffff80100000
+
+#
+# PMC-Sierra Yosemite
+#
+platform-$(CONFIG_PMC_YOSEMITE)	+= pmc-sierra/yosemite/
+cflags-$(CONFIG_PMC_YOSEMITE)	+= -I$(srctree)/arch/mips/include/asm/mach-yosemite
+load-$(CONFIG_PMC_YOSEMITE)	+= 0xffffffff80100000
-- 
1.5.6.5


From ralf@linux-mips.org Thu Jun  3 12:52:02 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 12:52:05 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:42634 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491030Ab0FCKwC (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Thu, 3 Jun 2010 12:52:02 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o53Apvlb014476;
        Thu, 3 Jun 2010 11:52:00 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o53Apv0T014474;
        Thu, 3 Jun 2010 11:51:57 +0100
Date:   Thu, 3 Jun 2010 11:51:56 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Shane McDonald <mcdonald.shane@gmail.com>
Cc:     linux-mips@linux-mips.org
Subject: Re: MIPS -queue: Move PMC-Sierra board Makefile parts to their own
 Platform file
Message-ID: <20100603105156.GA14403@linux-mips.org>
References: <E1OK7kU-0008RG-Oj@localhost>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <E1OK7kU-0008RG-Oj@localhost>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27040
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2282
Content-Length: 280
Lines: 10

On Thu, Jun 03, 2010 at 04:34:06AM -0600, Shane McDonald wrote:

> This patch moves the entries for the PMC-Sierra boards from the main
> mips Makefile into their own Platform file.
> 
> Signed-off-by: Shane McDonald <mcdonald.shane@gmail.com>

Thanks, queued for 2.6.36.

  Ralf

From ralf@linux-mips.org Thu Jun  3 12:59:10 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 12:59:13 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:39112 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492647Ab0FCK7K (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Thu, 3 Jun 2010 12:59:10 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o53Ax5Mi017490;
        Thu, 3 Jun 2010 11:59:06 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o53Ax5if017488;
        Thu, 3 Jun 2010 11:59:05 +0100
Date:   Thu, 3 Jun 2010 11:59:05 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     linux-mips <linux-mips@linux-mips.org>,
        Sam Ravnborg <sam@ravnborg.org>
Subject: Re: [PATCH -queue] MIPS: Move Loongson Makefile parts to their own
 Platform file (cont.)
Message-ID: <20100603105905.GA14741@linux-mips.org>
References: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27041
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2290
Content-Length: 109
Lines: 5

On Wed, Jun 02, 2010 at 04:53:00PM +0800, Wu Zhangjin wrote:

Thanks, folded into the existing patch.

 Ralf

From dmitri.vorobiev@gmail.com Thu Jun  3 13:10:32 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 13:10:36 +0200 (CEST)
Received: from mail-fx0-f49.google.com ([209.85.161.49]:34853 "EHLO
        mail-fx0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492641Ab0FCLKc (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 13:10:32 +0200
Received: by fxm15 with SMTP id 15so5540837fxm.36
        for <multiple recipients>; Thu, 03 Jun 2010 04:10:27 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type;
        bh=X+AlSkPMj6qz1FYei4JfrR8fQ3KLYIfryJlX70NV+n4=;
        b=tNpGBZG/q2URxiC3hH8ZNz2cuJyMBHWPLp5g1tItJiJsszt5s4dZWXyJHzv7Hkly2h
         UwDhGTgl5yO7VlvvRgxE4pLrHyGeUmyrj/ijpGil4Q9pFGPW2jEOx0KGz7OcZdSglwiT
         +zDD9kg47jiPgDyerVNv3WHeItYI+74tLAOFY=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type;
        b=Bw6ff015+hwRql+5DFnxKIa9se9Q85OxwQEuZh6CTMufpeR4scoKkCgsvBHe3mHt7e
         DdLLkl7NauCGcVAAIOfepwfHhYuc8rfKtSIcqmLj5g4G+GRN9dMwYskEbsIbRvv5WlZI
         NYz7YDsXhdVUMUssifJufza6CMY0xp/+4o+Lc=
MIME-Version: 1.0
Received: by 10.223.98.83 with SMTP id p19mr10082057fan.27.1275563426959; Thu, 
        03 Jun 2010 04:10:26 -0700 (PDT)
Received: by 10.223.104.209 with HTTP; Thu, 3 Jun 2010 04:10:26 -0700 (PDT)
In-Reply-To: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
References: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
Date:   Thu, 3 Jun 2010 14:10:26 +0300
Message-ID: <AANLkTikKBasnKuS2Ym6fS8Wr17obMnFWSmA2mJxDIrjU@mail.gmail.com>
Subject: Re: [PATCH -queue] MIPS: Move Loongson Makefile parts to their own 
        Platform file (cont.)
From:   Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
To:     Wu Zhangjin <wuzhangjin@gmail.com>
Cc:     Ralf Baechle <ralf@linux-mips.org>,
        linux-mips <linux-mips@linux-mips.org>
Content-Type: text/plain; charset=ISO-8859-1
X-archive-position: 27042
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: dmitri.vorobiev@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2301
Content-Length: 266
Lines: 9

On Wed, Jun 2, 2010 at 11:53 AM, Wu Zhangjin <wuzhangjin@gmail.com> wrote:
> Hi, Ralf
>
> I have fogotten to remove the -Werror in the Makefiles under loongson/

I'm just curious: why would anyone want to remove -Werror? It's very
useful in most cases, IMO.

Dmitri

From ralf@linux-mips.org Thu Jun  3 13:39:55 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 13:39:59 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:42870 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1491042Ab0FCLjz (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Thu, 3 Jun 2010 13:39:55 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o53BdrtU023251;
        Thu, 3 Jun 2010 12:39:53 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o53BdqsN023249;
        Thu, 3 Jun 2010 12:39:52 +0100
Date:   Thu, 3 Jun 2010 12:39:52 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
Cc:     Wu Zhangjin <wuzhangjin@gmail.com>,
        linux-mips <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue] MIPS: Move Loongson Makefile parts to their own
 Platform file (cont.)
Message-ID: <20100603113952.GA23033@linux-mips.org>
References: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
 <AANLkTikKBasnKuS2Ym6fS8Wr17obMnFWSmA2mJxDIrjU@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <AANLkTikKBasnKuS2Ym6fS8Wr17obMnFWSmA2mJxDIrjU@mail.gmail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27043
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2317
Content-Length: 322
Lines: 12

On Thu, Jun 03, 2010 at 02:10:26PM +0300, Dmitri Vorobiev wrote:

> > Hi, Ralf
> >
> > I have fogotten to remove the -Werror in the Makefiles under loongson/
> 
> I'm just curious: why would anyone want to remove -Werror? It's very
> useful in most cases, IMO.

arch/mips/Kbuild enables -Werror for all platforms.

  Ralf

From broonie@opensource.wolfsonmicro.com Thu Jun  3 14:03:59 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 14:04:04 +0200 (CEST)
Received: from opensource.wolfsonmicro.com ([80.75.67.52]:34946 "EHLO
        opensource2.wolfsonmicro.com" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1491771Ab0FCMD7 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 14:03:59 +0200
Received: from rakim.wolfsonmicro.main (lumison.wolfsonmicro.com [87.246.78.27])
        by opensource2.wolfsonmicro.com (Postfix) with ESMTPSA id 9C5E8110504;
        Thu,  3 Jun 2010 13:03:51 +0100 (BST)
Received: from broonie by rakim.wolfsonmicro.main with local (Exim 4.71)
        (envelope-from <broonie@rakim.wolfsonmicro.main>)
        id 1OK99L-0000nl-3x; Thu, 03 Jun 2010 13:03:51 +0100
Date:   Thu, 3 Jun 2010 13:03:51 +0100
From:   Mark Brown <broonie@opensource.wolfsonmicro.com>
To:     Wan ZongShun <mcuos.com@gmail.com>
Cc:     Lars-Peter Clausen <lars@metafoo.de>,
        Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org,
        Liam Girdwood <lrg@slimlogic.co.uk>
Subject: Re: [alsa-devel] [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec
 driver
Message-ID: <20100603120350.GC2762@rakim.wolfsonmicro.main>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
 <1275505950-17334-4-git-send-email-lars@metafoo.de>
 <4C074171.2080106@gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <4C074171.2080106@gmail.com>
X-Cookie: In the next world, you're on your own.
User-Agent: Mutt/1.5.20 (2009-06-14)
X-archive-position: 27044
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: broonie@opensource.wolfsonmicro.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2327
Content-Length: 502
Lines: 12

On Thu, Jun 03, 2010 at 01:45:21PM +0800, Wan ZongShun wrote:

> Your all the patches have two kinds of 'WARNING:',as following:

> (1)'WARNING: line over 80 characters' and

> Please make a line less than 80 characters.

You need to apply a certain degree of taste when looking at checkpatch
warnings, particularly things like line length.  Sometimes fixing the
warning for the sake of fixing the warning makes the code uglier than it
would be with whatever the style issue that's been identified is.

From dmitri.vorobiev@gmail.com Thu Jun  3 14:04:19 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 14:04:29 +0200 (CEST)
Received: from mail-fx0-f49.google.com ([209.85.161.49]:55049 "EHLO
        mail-fx0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492641Ab0FCMET (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 14:04:19 +0200
Received: by fxm15 with SMTP id 15so32005fxm.36
        for <multiple recipients>; Thu, 03 Jun 2010 05:04:13 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type;
        bh=PhfRKDZMh+7QqMIHR3DMlVROnzdWQUscWTwVwobgFp0=;
        b=q+w2S3GRCdU1Tbjm8CriLCbdiw4RGqrbOU7VKh6bgy8e83WfmifmnLzUk0YA2ivT8W
         cNwHJsZ8Nk8Wvd3BnGF6YL3mdTQrG3KK0TZNgvxqkRFog7TxnV+7dfU46UT1La73vQLi
         yCL5G4ApID5ZjlyUrvcTb3AYT6FFTVRvRIV74=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type;
        b=mHbx5hAlWHy7o35rROpzzO2Y2nNNt61RyhF1bSbnY48rcfjIRvw32QRZ2G4Ze3TrXk
         Xz02wHsZlfpF8ZFk/9p+afoad27fFbCiYkHKeSbdC9OOtbwNtMtguoRgtGEvbsZOxWlt
         aNI96l/kiYfoIWMvh3K0EiXOMMRZLn0bRPvqg=
MIME-Version: 1.0
Received: by 10.223.31.136 with SMTP id y8mr10177502fac.19.1275566653245; Thu, 
        03 Jun 2010 05:04:13 -0700 (PDT)
Received: by 10.223.104.209 with HTTP; Thu, 3 Jun 2010 05:04:13 -0700 (PDT)
In-Reply-To: <20100603113952.GA23033@linux-mips.org>
References: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
        <AANLkTikKBasnKuS2Ym6fS8Wr17obMnFWSmA2mJxDIrjU@mail.gmail.com>
        <20100603113952.GA23033@linux-mips.org>
Date:   Thu, 3 Jun 2010 15:04:13 +0300
Message-ID: <AANLkTikEgVmUmumoKA8NtdclqqGgtqiD-I55JZEgtpZd@mail.gmail.com>
Subject: Re: [PATCH -queue] MIPS: Move Loongson Makefile parts to their own 
        Platform file (cont.)
From:   Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
To:     Ralf Baechle <ralf@linux-mips.org>
Cc:     Wu Zhangjin <wuzhangjin@gmail.com>,
        linux-mips <linux-mips@linux-mips.org>
Content-Type: text/plain; charset=ISO-8859-1
X-archive-position: 27045
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: dmitri.vorobiev@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2328
Content-Length: 457
Lines: 15

On Thu, Jun 3, 2010 at 2:39 PM, Ralf Baechle <ralf@linux-mips.org> wrote:
> On Thu, Jun 03, 2010 at 02:10:26PM +0300, Dmitri Vorobiev wrote:
>
>> > Hi, Ralf
>> >
>> > I have fogotten to remove the -Werror in the Makefiles under loongson/
>>
>> I'm just curious: why would anyone want to remove -Werror? It's very
>> useful in most cases, IMO.
>
> arch/mips/Kbuild enables -Werror for all platforms.

Looks like I'm failing to keep pace with life :)

Dmitri

From ralf@linux-mips.org Thu Jun  3 14:07:54 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 14:07:58 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:43790 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492648Ab0FCMHy (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Thu, 3 Jun 2010 14:07:54 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o53C7pL0023779;
        Thu, 3 Jun 2010 13:07:52 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o53C7o2D023777;
        Thu, 3 Jun 2010 13:07:50 +0100
Date:   Thu, 3 Jun 2010 13:07:50 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
Cc:     Wu Zhangjin <wuzhangjin@gmail.com>,
        linux-mips <linux-mips@linux-mips.org>
Subject: Re: [PATCH -queue] MIPS: Move Loongson Makefile parts to their own
 Platform file (cont.)
Message-ID: <20100603120750.GB23033@linux-mips.org>
References: <95654e45e2f02133c6334fb147d3e28ef94f2bb0.1275439768.git.wuzhangjin@gmail.com>
 <AANLkTikKBasnKuS2Ym6fS8Wr17obMnFWSmA2mJxDIrjU@mail.gmail.com>
 <20100603113952.GA23033@linux-mips.org>
 <AANLkTikEgVmUmumoKA8NtdclqqGgtqiD-I55JZEgtpZd@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <AANLkTikEgVmUmumoKA8NtdclqqGgtqiD-I55JZEgtpZd@mail.gmail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27046
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2334
Content-Length: 457
Lines: 14

On Thu, Jun 03, 2010 at 03:04:13PM +0300, Dmitri Vorobiev wrote:

> >> > I have fogotten to remove the -Werror in the Makefiles under loongson/
> >>
> >> I'm just curious: why would anyone want to remove -Werror? It's very
> >> useful in most cases, IMO.
> >
> > arch/mips/Kbuild enables -Werror for all platforms.
> 
> Looks like I'm failing to keep pace with life :)

Soon you'll need a fiber from vger to your brain just to keep up with lkml ;-)

  Ralf

From lrg@slimlogic.co.uk Thu Jun  3 14:48:36 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 14:48:45 +0200 (CEST)
Received: from mail-ww0-f49.google.com ([74.125.82.49]:45999 "EHLO
        mail-ww0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492641Ab0FCMsg (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 14:48:36 +0200
Received: by wwi17 with SMTP id 17so39844wwi.36
        for <multiple recipients>; Thu, 03 Jun 2010 05:48:31 -0700 (PDT)
Received: by 10.216.85.195 with SMTP id u45mr1096611wee.72.1275569311398;
        Thu, 03 Jun 2010 05:48:31 -0700 (PDT)
Received: from [192.168.1.6] (host81-136-218-57.in-addr.btopenworld.com [81.136.218.57])
        by mx.google.com with ESMTPS id v59sm6668wec.15.2010.06.03.05.48.28
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 05:48:29 -0700 (PDT)
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
From:   Liam Girdwood <lrg@slimlogic.co.uk>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        alsa-devel@alsa-project.org
In-Reply-To: <1275505950-17334-5-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
         <1275505950-17334-5-git-send-email-lars@metafoo.de>
Content-Type: text/plain; charset="UTF-8"
Date:   Thu, 03 Jun 2010 13:48:29 +0100
Message-ID: <1275569309.3593.106.camel@odin>
Mime-Version: 1.0
X-Mailer: Evolution 2.28.3 
Content-Transfer-Encoding: 7bit
X-archive-position: 27047
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lrg@slimlogic.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2362
Content-Length: 30374
Lines: 1105

On Wed, 2010-06-02 at 21:12 +0200, Lars-Peter Clausen wrote:
> This patch adds ASoC support for JZ4740 SoCs I2S module.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> Cc: alsa-devel@alsa-project.org
> ---
>  sound/soc/Kconfig             |    1 +
>  sound/soc/Makefile            |    1 +
>  sound/soc/jz4740/Kconfig      |   13 +
>  sound/soc/jz4740/Makefile     |    9 +
>  sound/soc/jz4740/jz4740-i2s.c |  568 +++++++++++++++++++++++++++++++++++++++++
>  sound/soc/jz4740/jz4740-i2s.h |   18 ++
>  sound/soc/jz4740/jz4740-pcm.c |  350 +++++++++++++++++++++++++
>  sound/soc/jz4740/jz4740-pcm.h |   22 ++
>  8 files changed, 982 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/jz4740/Kconfig
>  create mode 100644 sound/soc/jz4740/Makefile
>  create mode 100644 sound/soc/jz4740/jz4740-i2s.c
>  create mode 100644 sound/soc/jz4740/jz4740-i2s.h
>  create mode 100644 sound/soc/jz4740/jz4740-pcm.c
>  create mode 100644 sound/soc/jz4740/jz4740-pcm.h
> 
> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
> index b1749bc..5a7a724 100644
> --- a/sound/soc/Kconfig
> +++ b/sound/soc/Kconfig
> @@ -36,6 +36,7 @@ source "sound/soc/s3c24xx/Kconfig"
>  source "sound/soc/s6000/Kconfig"
>  source "sound/soc/sh/Kconfig"
>  source "sound/soc/txx9/Kconfig"
> +source "sound/soc/jz4740/Kconfig"
>  
>  # Supported codecs
>  source "sound/soc/codecs/Kconfig"
> diff --git a/sound/soc/Makefile b/sound/soc/Makefile
> index 1470141..fdbe74d 100644
> --- a/sound/soc/Makefile
> +++ b/sound/soc/Makefile
> @@ -14,3 +14,4 @@ obj-$(CONFIG_SND_SOC)	+= s3c24xx/
>  obj-$(CONFIG_SND_SOC)	+= s6000/
>  obj-$(CONFIG_SND_SOC)	+= sh/
>  obj-$(CONFIG_SND_SOC)	+= txx9/
> +obj-$(CONFIG_SND_SOC)	+= jz4740/
> diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
> new file mode 100644
> index 0000000..39df949
> --- /dev/null
> +++ b/sound/soc/jz4740/Kconfig
> @@ -0,0 +1,13 @@
> +config SND_JZ4740_SOC
> +	tristate "SoC Audio for Ingenic JZ4740 SoC"
> +	depends on SOC_JZ4740 && SND_SOC
> +	help
> +	  Say Y or M if you want to add support for codecs attached to
> +	  the Jz4740 AC97, I2S or SSP interface. You will also need

Do you have an AC97 or SSP interface ?

> +	  to select the audio interfaces to support below.
> +
> +config SND_JZ4740_SOC_I2S
> +	depends on SND_JZ4740_SOC
> +	tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip"
> +	help
> +	  Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 QI_LB60 board.
> diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
> new file mode 100644
> index 0000000..1be8d19
> --- /dev/null
> +++ b/sound/soc/jz4740/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Jz4740 Platform Support
> +#
> +snd-soc-jz4740-objs := jz4740-pcm.o
> +snd-soc-jz4740-i2s-objs := jz4740-i2s.o
> +
> +obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
> +obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
> +
> diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
> new file mode 100644
> index 0000000..2b139fd
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-i2s.c
> @@ -0,0 +1,568 @@
> +/*
> + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + *  This program is free software; you can redistribute	 it and/or modify it
> + *  under  the terms of	 the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the	License, or (at your
> + *  option) any later version.
> + *

Formatting looks broken here.

> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +
> +#include <linux/dma-mapping.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <sound/soc-dapm.h>
> +#include <sound/initval.h>
> +
> +#include "jz4740-i2s.h"
> +#include "jz4740-pcm.h"
> +
> +#define JZ_REG_AIC_CONF		0x00
> +#define JZ_REG_AIC_CTRL		0x04
> +#define JZ_REG_AIC_I2S_FMT	0x10
> +#define JZ_REG_AIC_FIFO_STATUS	0x14
> +#define JZ_REG_AIC_I2S_STATUS	0x1c
> +#define JZ_REG_AIC_CLK_DIV	0x30
> +#define JZ_REG_AIC_FIFO		0x34
> +
> +#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_MASK (0xf << 12)
> +#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_MASK (0xf <<  8)
> +#define JZ_AIC_CONF_OVERFLOW_PLAY_LAST BIT(6)
> +#define JZ_AIC_CONF_INTERNAL_CODEC BIT(5)
> +#define JZ_AIC_CONF_I2S BIT(4)
> +#define JZ_AIC_CONF_RESET BIT(3)
> +#define JZ_AIC_CONF_BIT_CLK_MASTER BIT(2)
> +#define JZ_AIC_CONF_SYNC_CLK_MASTER BIT(1)
> +#define JZ_AIC_CONF_ENABLE BIT(0)
> +
> +#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12
> +#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8
> +
> +#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19)
> +#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16)
> +#define JZ_AIC_CTRL_ENABLE_RX_DMA BIT(15)
> +#define JZ_AIC_CTRL_ENABLE_TX_DMA BIT(14)
> +#define JZ_AIC_CTRL_MONO_TO_STEREO BIT(11)
> +#define JZ_AIC_CTRL_SWITCH_ENDIANNESS BIT(10)
> +#define JZ_AIC_CTRL_SIGNED_TO_UNSIGNED BIT(9)
> +#define JZ_AIC_CTRL_FLUSH		BIT(8)
> +#define JZ_AIC_CTRL_ENABLE_ROR_INT BIT(6)
> +#define JZ_AIC_CTRL_ENABLE_TUR_INT BIT(5)
> +#define JZ_AIC_CTRL_ENABLE_RFS_INT BIT(4)
> +#define JZ_AIC_CTRL_ENABLE_TFS_INT BIT(3)
> +#define JZ_AIC_CTRL_ENABLE_LOOPBACK BIT(2)
> +#define JZ_AIC_CTRL_ENABLE_PLAYBACK BIT(1)
> +#define JZ_AIC_CTRL_ENABLE_CAPTURE BIT(0)
> +
> +#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET 19
> +#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET  16
> +
> +#define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12)
> +#define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4)
> +#define JZ_AIC_I2S_FMT_MSB BIT(0)
> +
> +#define JZ_AIC_I2S_STATUS_BUSY BIT(2)
> +
> +#define JZ_AIC_CLK_DIV_MASK 0xf
> +
> +struct jz4740_i2s {
> +	struct resource *mem;
> +	void __iomem *base;
> +	dma_addr_t phys_base;
> +
> +	struct clk *clk_aic;
> +	struct clk *clk_i2s;
> +
> +	struct jz4740_pcm_config pcm_config_playback;
> +	struct jz4740_pcm_config pcm_config_capture;
> +};
> +
> +static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
> +	unsigned int reg)
> +{
> +	return readl(i2s->base + reg);
> +}
> +
> +static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,
> +	unsigned int reg, uint32_t value)
> +{
> +	writel(value, i2s->base + reg);
> +}
> +
> +static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai)
> +{
> +	return dai->private_data;
> +}
> +
> +static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
> +	struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf, ctrl;
> +
> +	if (dai->active)
> +		return 0;
> +
> +
> +	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
> +	ctrl |= JZ_AIC_CTRL_FLUSH;
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
> +
> +	clk_enable(i2s->clk_i2s);
> +
> +	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +	conf |= JZ_AIC_CONF_ENABLE;
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	return 0;
> +}
> +
> +static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
> +	struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	if (!dai->active)
> +		return;
> +
> +	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +	conf &= ~JZ_AIC_CONF_ENABLE;
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	clk_disable(i2s->clk_i2s);
> +}
> +
> +
> +static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
> +	struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
> +
> +	uint32_t ctrl;
> +	uint32_t mask;
> +
> +	if (playback)

It's best to use (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) here.

> +		mask = JZ_AIC_CTRL_ENABLE_PLAYBACK | JZ_AIC_CTRL_ENABLE_TX_DMA;
> +	else
> +		mask = JZ_AIC_CTRL_ENABLE_CAPTURE | JZ_AIC_CTRL_ENABLE_RX_DMA;
> +
> +	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		ctrl |= mask;
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		ctrl &= ~mask;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
> +
> +	return 0;
> +}
> +
> +
> +static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +

No new line is required here.

> +	uint32_t format = 0;
> +	uint32_t conf;
> +
> +	conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +
> +	conf &= ~(JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER);
> +
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER;
> +		format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFS:
> +		conf |= JZ_AIC_CONF_SYNC_CLK_MASTER;
> +		break;
> +	case SND_SOC_DAIFMT_CBS_CFM:
> +		conf |= JZ_AIC_CONF_BIT_CLK_MASTER;
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_MSB:
> +		format |= JZ_AIC_I2S_FMT_MSB;
> +		break;
> +	case SND_SOC_DAIFMT_I2S:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_NB_NF:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_I2S_FMT, format);
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
> +	enum jz4740_dma_width dma_width;
> +	struct jz4740_pcm_config *pcm_config;
> +	unsigned int sample_size;
> +	uint32_t ctrl;
> +
> +	ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
> +
> +	switch (params_format(params)) {
> +	case SNDRV_PCM_FORMAT_S8:
> +		sample_size = 0;
> +		dma_width = JZ4740_DMA_WIDTH_8BIT;
> +		break;
> +	case SNDRV_PCM_FORMAT_S16:
> +		sample_size = 1;
> +		dma_width = JZ4740_DMA_WIDTH_16BIT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (playback) {

Same here re substream->stream

> +		ctrl &= ~JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK;
> +		ctrl |= sample_size << JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET;
> +	} else {
> +		ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
> +		ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
> +	}
> +
> +	switch (params_channels(params)) {
> +	case 2:
> +		break;
> +	case 1:
> +		if (playback) {
> +			ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
> +			break;
> +		}
> +	default: /* Falltrough */
> +		return -EINVAL;
> +	}
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
> +
> +	if (playback) {

ditto
> +		pcm_config = &i2s->pcm_config_playback;
> +		pcm_config->dma_config.dst_width = dma_width;
> +	} else {
> +		pcm_config = &i2s->pcm_config_capture;
> +		pcm_config->dma_config.src_width = dma_width;
> +	}
> +
> +
> +	snd_soc_dai_set_dma_data(dai, substream, pcm_config);
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +
> +	switch (div_id) {
> +	case JZ4740_I2S_BIT_CLK:
> +		if (div & 1 || div > 16)
> +			return -EINVAL;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div - 1);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
> +	unsigned int freq, int dir)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	int ret = 0;
> +	struct clk *parent;
> +
> +	switch (clk_id) {
> +	case JZ4740_I2S_CLKSRC_EXT:
> +		parent = clk_get(NULL, "ext");
> +		clk_set_parent(i2s->clk_i2s, parent);
> +		break;
> +	case JZ4740_I2S_CLKSRC_PLL:
> +		parent = clk_get(NULL, "pll half");
> +		clk_set_parent(i2s->clk_i2s, parent);
> +		ret = clk_set_rate(i2s->clk_i2s, freq);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	clk_put(parent);
> +
> +	return ret;
> +}
> +
> +static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	if (dai->active) {
> +		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +		conf &= ~JZ_AIC_CONF_ENABLE;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +		clk_disable(i2s->clk_i2s);
> +	}
> +
> +	clk_disable(i2s->clk_aic);
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_resume(struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	clk_enable(i2s->clk_aic);
> +
> +	if (dai->active) {
> +		clk_enable(i2s->clk_i2s);
> +
> +		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +		conf |= JZ_AIC_CONF_ENABLE;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	}
> +
> +	return 0;
> +}
> +
> +static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +	uint32_t conf;
> +
> +	conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
> +		(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
> +		JZ_AIC_CONF_OVERFLOW_PLAY_LAST |
> +		JZ_AIC_CONF_I2S |
> +		JZ_AIC_CONF_INTERNAL_CODEC;
> +
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET);
> +	jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +	return 0;
> +}
> +
> +
> +static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
> +	.startup = jz4740_i2s_startup,
> +	.shutdown = jz4740_i2s_shutdown,
> +	.trigger = jz4740_i2s_trigger,
> +	.hw_params = jz4740_i2s_hw_params,
> +	.set_fmt = jz4740_i2s_set_fmt,
> +	.set_clkdiv = jz4740_i2s_set_clkdiv,
> +	.set_sysclk = jz4740_i2s_set_sysclk,
> +};
> +
> +#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
> +		SNDRV_PCM_FMTBIT_S16_LE)
> +
> +struct snd_soc_dai jz4740_i2s_dai = {
> +	.name = "jz4740-i2s",
> +	.probe = jz4740_i2s_probe,
> +	.playback = {
> +		.channels_min = 1,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = JZ4740_I2S_FMTS,
> +	},
> +	.capture = {
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = JZ4740_I2S_FMTS,
> +	},
> +	.symmetric_rates = 1,
> +	.ops = &jz4740_i2s_dai_ops,
> +	.suspend = jz4740_i2s_suspend,
> +	.resume = jz4740_i2s_resume,
> +};
> +EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
> +
> +static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
> +{
> +	struct jz4740_dma_config *dma_config;
> +
> +	/* Playback */
> +	dma_config = &i2s->pcm_config_playback.dma_config;
> +	dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
> +	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
> +	dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
> +	dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
> +	dma_config->mode = JZ4740_DMA_MODE_SINGLE;
> +	i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
> +
> +	/* Capture */
> +	dma_config = &i2s->pcm_config_capture.dma_config;
> +	dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
> +	dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
> +	dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
> +	dma_config->flags = JZ4740_DMA_DST_AUTOINC;
> +	dma_config->mode = JZ4740_DMA_MODE_SINGLE;
> +	i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
> +}
> +
> +static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
> +{
> +	struct jz4740_i2s *i2s;
> +	int ret;
> +
> +	i2s = kzalloc(sizeof(*i2s), GFP_KERNEL);
> +
> +	if (!i2s)
> +		return -ENOMEM;
> +
> +	i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +

Why the new lines here

> +	if (!i2s->mem) {
> +		ret = -ENOENT;
> +		goto err_free;
> +	}
> +
> +	i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem),
> +				pdev->name);
> +

and here

> +	if (!i2s->mem) {
> +		ret = -EBUSY;
> +		goto err_free;
> +	}
> +
> +	i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem));
> +

ditto

> +	if (!i2s->base) {
> +		ret = -EBUSY;
> +		goto err_release_mem_region;
> +	}
> +
> +	i2s->phys_base = i2s->mem->start;
> +
> +	i2s->clk_aic = clk_get(&pdev->dev, "aic");
> +	if (IS_ERR(i2s->clk_aic)) {
> +		ret = PTR_ERR(i2s->clk_aic);
> +		goto err_iounmap;
> +	}
> +
> +	i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
> +	if (IS_ERR(i2s->clk_i2s)) {
> +		ret = PTR_ERR(i2s->clk_i2s);
> +		goto err_iounmap;
> +	}
> +
> +	clk_enable(i2s->clk_aic);
> +
> +	jz4740_i2c_init_pcm_config(i2s);
> +
> +	jz4740_i2s_dai.private_data = i2s;
> +	ret = snd_soc_register_dai(&jz4740_i2s_dai);
> +
> +	platform_set_drvdata(pdev, i2s);
> +
> +	return 0;
> +
> +err_iounmap:
> +	iounmap(i2s->base);
> +err_release_mem_region:
> +	release_mem_region(i2s->mem->start, resource_size(i2s->mem));
> +err_free:
> +	kfree(i2s);
> +
> +	return ret;
> +}
> +
> +static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
> +{
> +	struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
> +
> +	snd_soc_unregister_dai(&jz4740_i2s_dai);
> +
> +	clk_disable(i2s->clk_aic);
> +	clk_put(i2s->clk_i2s);
> +	clk_put(i2s->clk_aic);
> +
> +	iounmap(i2s->base);
> +	release_mem_region(i2s->mem->start, resource_size(i2s->mem));
> +
> +	platform_set_drvdata(pdev, NULL);
> +	kfree(i2s);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver jz4740_i2s_driver = {
> +	.probe = jz4740_i2s_dev_probe,
> +	.remove = __devexit_p(jz4740_i2s_dev_remove),
> +	.driver = {
> +		.name = "jz4740-i2s",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static int __init jz4740_i2s_init(void)
> +{
> +	return platform_driver_register(&jz4740_i2s_driver);
> +}
> +module_init(jz4740_i2s_init);
> +
> +static void __exit jz4740_i2s_exit(void)
> +{
> +	platform_driver_unregister(&jz4740_i2s_driver);
> +}
> +module_exit(jz4740_i2s_exit);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:jz4740-i2s");
> diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h
> new file mode 100644
> index 0000000..da22ed8
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-i2s.h
> @@ -0,0 +1,18 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _JZ4740_I2S_H
> +#define _JZ4740_I2S_H
> +
> +/* I2S clock source */
> +#define JZ4740_I2S_CLKSRC_EXT 0
> +#define JZ4740_I2S_CLKSRC_PLL 1
> +
> +#define JZ4740_I2S_BIT_CLK		0
> +
> +extern struct snd_soc_dai jz4740_i2s_dai;
> +
> +#endif
> diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
> new file mode 100644
> index 0000000..fd1c203
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-pcm.c
> @@ -0,0 +1,350 @@
> +/*
> + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + *  This program is free software; you can redistribute	 it and/or modify it
> + *  under  the terms of	 the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the	License, or (at your
> + *  option) any later version.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +#include <linux/dma-mapping.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +
> +#include <asm/mach-jz4740/dma.h>
> +#include "jz4740-pcm.h"
> +
> +struct jz4740_runtime_data {
> +	unsigned int dma_period;
> +	dma_addr_t dma_start;
> +	dma_addr_t dma_pos;
> +	dma_addr_t dma_end;
> +
> +	struct jz4740_dma_chan *dma;
> +
> +	dma_addr_t fifo_addr;
> +};
> +
> +/* identify hardware playback capabilities */
> +static const struct snd_pcm_hardware jz4740_pcm_hardware = {
> +	.info = SNDRV_PCM_INFO_MMAP |
> +		SNDRV_PCM_INFO_MMAP_VALID |
> +		SNDRV_PCM_INFO_INTERLEAVED |
> +		SNDRV_PCM_INFO_BLOCK_TRANSFER,
> +	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
> +
> +	.rates			= SNDRV_PCM_RATE_8000_48000,
> +	.channels_min		= 1,
> +	.channels_max		= 2,
> +	.period_bytes_min	= 16,
> +	.period_bytes_max	= 2 * PAGE_SIZE,
> +	.periods_min		= 2,
> +	.periods_max		= 128,
> +	.buffer_bytes_max	= 128 * 2 * PAGE_SIZE,
> +	.fifo_size		= 32,
> +};
> +
> +static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd, int stream)
> +{
> +	unsigned int count;
> +
> +	if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
> +		count = prtd->dma_end - prtd->dma_pos;
> +	else
> +		count = prtd->dma_period;
> +
> +	jz4740_dma_disable(prtd->dma);
> +
> +	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
> +		jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
> +	} else {
> +		jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
> +		jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
> +	}
> +
> +	jz4740_dma_set_transfer_count(prtd->dma, count);
> +
> +	jz4740_dma_enable(prtd->dma);
> +
> +	prtd->dma_pos += prtd->dma_period;
> +	if (prtd->dma_pos >= prtd->dma_end)
> +		prtd->dma_pos = prtd->dma_start;
> +}
> +
> +static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
> +	void *dev_id)
> +{
> +	struct snd_pcm_substream *substream = dev_id;
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +
> +	snd_pcm_period_elapsed(substream);
> +
> +	jz4740_pcm_start_transfer(prtd, substream->stream);
> +}
> +
> +static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct jz4740_pcm_config *config;
> +
> +	config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
> +	if (!prtd->dma) {
> +		const char *dma_channel_name;
> +		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +			dma_channel_name = "PCM Playback";
> +		else
> +			dma_channel_name = "PCM Capture";
> +
> +		prtd->dma = jz4740_dma_request(substream, dma_channel_name);

dma_channel_name variable is not required here. Just use the const char
* directly.

> +	}
> +
> +	if (!prtd->dma)
> +		return -EBUSY;
> +
> +	jz4740_dma_configure(prtd->dma, &config->dma_config);
> +	prtd->fifo_addr = config->fifo_addr;
> +
> +	jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
> +
> +	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> +	runtime->dma_bytes = params_buffer_bytes(params);
> +
> +	prtd->dma_period = params_period_bytes(params);
> +	prtd->dma_start = runtime->dma_addr;
> +	prtd->dma_pos = prtd->dma_start;
> +	prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
> +
> +	return 0;
> +}
> +
> +static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
> +{
> +	struct jz4740_runtime_data *prtd = substream->runtime->private_data;
> +
> +	snd_pcm_set_runtime_buffer(substream, NULL);
> +	if (prtd->dma) {
> +		jz4740_dma_free(prtd->dma);
> +		prtd->dma = NULL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
> +{
> +	struct jz4740_runtime_data *prtd = substream->runtime->private_data;
> +	int ret = 0;
> +
> +	if (!prtd->dma)
> +			return 0;
> +
> +	prtd->dma_pos = prtd->dma_start;
> +
> +	return ret;
> +}
> +
> +static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +
No new line.

> +	int ret = 0;
> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		jz4740_pcm_start_transfer(prtd, substream->stream);
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		jz4740_dma_disable(prtd->dma);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +	unsigned long count, pos;
> +	snd_pcm_uframes_t offset;
> +	struct jz4740_dma_chan *dma = prtd->dma;
> +
> +	count = jz4740_dma_get_residue(dma);
> +	if (prtd->dma_pos == prtd->dma_start)
> +		pos = prtd->dma_end - prtd->dma_start - count;
> +	else
> +		pos = prtd->dma_pos - prtd->dma_start - count;
> +
> +	offset = bytes_to_frames(runtime, pos);
> +	if (offset >= runtime->buffer_size)
> +		offset = 0;
> +

Could you comment your calculation a little more.

> +	return offset;
> +}
> +
> +static int jz4740_pcm_open(struct snd_pcm_substream *substream)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd;
> +
> +	snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
> +	prtd = kzalloc(sizeof(struct jz4740_runtime_data), GFP_KERNEL);
> +
> +	if (prtd == NULL)
> +		return -ENOMEM;
> +
> +	runtime->private_data = prtd;
> +	return 0;
> +}
> +
> +static int jz4740_pcm_close(struct snd_pcm_substream *substream)
> +{
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct jz4740_runtime_data *prtd = runtime->private_data;
> +
> +	kfree(prtd);
> +
> +	return 0;
> +}
> +
> +static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
> +	struct vm_area_struct *vma)
> +{
> +	return remap_pfn_range(vma, vma->vm_start,
> +			substream->dma_buffer.addr >> PAGE_SHIFT,
> +			vma->vm_end - vma->vm_start, vma->vm_page_prot);
> +}
> +
> +static struct snd_pcm_ops jz4740_pcm_ops = {
> +	.open		= jz4740_pcm_open,
> +	.close		= jz4740_pcm_close,
> +	.ioctl		= snd_pcm_lib_ioctl,
> +	.hw_params	= jz4740_pcm_hw_params,
> +	.hw_free	= jz4740_pcm_hw_free,
> +	.prepare	= jz4740_pcm_prepare,
> +	.trigger	= jz4740_pcm_trigger,
> +	.pointer	= jz4740_pcm_pointer,
> +	.mmap		= jz4740_pcm_mmap,
> +};
> +
> +static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
> +{
> +	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
> +	struct snd_dma_buffer *buf = &substream->dma_buffer;
> +	size_t size = jz4740_pcm_hardware.buffer_bytes_max;
> +
> +	buf->dev.type = SNDRV_DMA_TYPE_DEV;
> +	buf->dev.dev = pcm->card->dev;
> +	buf->private_data = NULL;
> +
> +	buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
> +					  &buf->addr, GFP_KERNEL);
> +	if (!buf->area)
> +		return -ENOMEM;
> +
> +	buf->bytes = size;
> +
> +	return 0;
> +}
> +
> +static void jz4740_pcm_free(struct snd_pcm *pcm)
> +{
> +	struct snd_pcm_substream *substream;
> +	struct snd_dma_buffer *buf;
> +	int stream;
> +
> +	for (stream = 0; stream < 2; stream++) {
> +		substream = pcm->streams[stream].substream;
> +		if (!substream)
> +			continue;
> +
> +		buf = &substream->dma_buffer;
> +		if (!buf->area)
> +			continue;
> +
> +		dma_free_noncoherent(pcm->card->dev, buf->bytes,
> +		  buf->area, buf->addr);
> +		buf->area = NULL;
> +	}
> +}
> +
> +static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
> +
> +int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
> +	struct snd_pcm *pcm)
> +{
> +	int ret = 0;
> +
> +	if (!card->dev->dma_mask)
> +		card->dev->dma_mask = &jz4740_pcm_dmamask;
> +
> +	if (!card->dev->coherent_dma_mask)
> +		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
> +
> +	if (dai->playback.channels_min) {
> +		ret = jz4740_pcm_preallocate_dma_buffer(pcm,
> +			SNDRV_PCM_STREAM_PLAYBACK);
> +		if (ret)
> +			goto err;
> +	}
> +
> +	if (dai->capture.channels_min) {
> +		ret = jz4740_pcm_preallocate_dma_buffer(pcm,
> +			SNDRV_PCM_STREAM_CAPTURE);
> +		if (ret)
> +			goto err;
> +	}
> +
> +err:
> +	return ret;
> +}
> +
> +struct snd_soc_platform jz4740_soc_platform = {
> +		.name		= "jz4740-pcm",
> +		.pcm_ops	= &jz4740_pcm_ops,
> +		.pcm_new	= jz4740_pcm_new,
> +		.pcm_free	= jz4740_pcm_free,
> +};
> +EXPORT_SYMBOL_GPL(jz4740_soc_platform);
> +
> +static int __init jz4740_soc_platform_init(void)
> +{
> +	return snd_soc_register_platform(&jz4740_soc_platform);
> +}
> +module_init(jz4740_soc_platform_init);
> +
> +static void __exit jz4740_soc_platform_exit(void)
> +{
> +	snd_soc_unregister_platform(&jz4740_soc_platform);
> +}
> +module_exit(jz4740_soc_platform_exit);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
> new file mode 100644
> index 0000000..e3f221e
> --- /dev/null
> +++ b/sound/soc/jz4740/jz4740-pcm.h
> @@ -0,0 +1,22 @@
> +/*
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _JZ4740_PCM_H
> +#define _JZ4740_PCM_H
> +
> +#include <linux/dma-mapping.h>
> +#include <asm/mach-jz4740/dma.h>
> +
> +/* platform data */
> +extern struct snd_soc_platform jz4740_soc_platform;
> +
> +struct jz4740_pcm_config {
> +	struct jz4740_dma_config dma_config;
> +	phys_addr_t fifo_addr;
> +};
> +
> +#endif

Thanks

Liam
-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk


From lrg@slimlogic.co.uk Thu Jun  3 14:50:15 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 14:50:19 +0200 (CEST)
Received: from mail-ww0-f49.google.com ([74.125.82.49]:45624 "EHLO
        mail-ww0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492656Ab0FCMuP (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 14:50:15 +0200
Received: by wwi17 with SMTP id 17so41158wwi.36
        for <multiple recipients>; Thu, 03 Jun 2010 05:50:10 -0700 (PDT)
Received: by 10.227.134.20 with SMTP id h20mr9231375wbt.47.1275569410054;
        Thu, 03 Jun 2010 05:50:10 -0700 (PDT)
Received: from [192.168.1.6] (host81-136-218-57.in-addr.btopenworld.com [81.136.218.57])
        by mx.google.com with ESMTPS id l46sm6270wed.22.2010.06.03.05.50.07
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 05:50:08 -0700 (PDT)
Subject: Re: [alsa-devel] [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec
 driver
From:   Liam Girdwood <lrg@slimlogic.co.uk>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        linux-kernel@vger.kernel.org
In-Reply-To: <1275568334.3593.92.camel@odin>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
         <1275505950-17334-4-git-send-email-lars@metafoo.de>
         <1275568334.3593.92.camel@odin>
Content-Type: text/plain; charset="UTF-8"
Date:   Thu, 03 Jun 2010 13:50:08 +0100
Message-ID: <1275569408.3593.107.camel@odin>
Mime-Version: 1.0
X-Mailer: Evolution 2.28.3 
Content-Transfer-Encoding: 7bit
X-archive-position: 27048
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lrg@slimlogic.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2364
Content-Length: 967
Lines: 29

On Thu, 2010-06-03 at 13:32 +0100, Liam Girdwood wrote:
> On Wed, 2010-06-02 at 21:12 +0200, Lars-Peter Clausen wrote:
> > This patch adds support for the JZ4740 internal codec.
> > 
> > Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> > Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> > Cc: alsa-devel@alsa-project.org
> > ---
> >  sound/soc/codecs/Kconfig        |    4 +
> >  sound/soc/codecs/Makefile       |    2 +
> >  sound/soc/codecs/jz4740-codec.c |  502 +++++++++++++++++++++++++++++++++++++++
> >  sound/soc/codecs/jz4740-codec.h |   20 ++
> >  4 files changed, 528 insertions(+), 0 deletions(-)
> >  create mode 100644 sound/soc/codecs/jz4740-codec.c
> >  create mode 100644 sound/soc/codecs/jz4740-codec.h
> 
> no need for code in file name here.

My bad typing - I mean codec.

Thanks

Liam
-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk


From lrg@slimlogic.co.uk Thu Jun  3 15:15:44 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 15:15:51 +0200 (CEST)
Received: from mail-wy0-f177.google.com ([74.125.82.177]:59144 "EHLO
        mail-wy0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492023Ab0FCNPo (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 15:15:44 +0200
Received: by wyj26 with SMTP id 26so34710wyj.36
        for <multiple recipients>; Thu, 03 Jun 2010 06:15:38 -0700 (PDT)
Received: by 10.227.144.132 with SMTP id z4mr420582wbu.70.1275568335723;
        Thu, 03 Jun 2010 05:32:15 -0700 (PDT)
Received: from [192.168.1.6] (host81-136-218-57.in-addr.btopenworld.com [81.136.218.57])
        by mx.google.com with ESMTPS id k13sm4050794wed.23.2010.06.03.05.32.12
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 05:32:14 -0700 (PDT)
Subject: Re: [alsa-devel] [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec
 driver
From:   Liam Girdwood <lrg@slimlogic.co.uk>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        linux-kernel@vger.kernel.org
In-Reply-To: <1275505950-17334-4-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
         <1275505950-17334-4-git-send-email-lars@metafoo.de>
Content-Type: text/plain; charset="UTF-8"
Date:   Thu, 03 Jun 2010 13:32:14 +0100
Message-ID: <1275568334.3593.92.camel@odin>
Mime-Version: 1.0
X-Mailer: Evolution 2.28.3 
Content-Transfer-Encoding: 7bit
X-archive-position: 27049
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lrg@slimlogic.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2389
Content-Length: 18528
Lines: 619

On Wed, 2010-06-02 at 21:12 +0200, Lars-Peter Clausen wrote:
> This patch adds support for the JZ4740 internal codec.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> Cc: alsa-devel@alsa-project.org
> ---
>  sound/soc/codecs/Kconfig        |    4 +
>  sound/soc/codecs/Makefile       |    2 +
>  sound/soc/codecs/jz4740-codec.c |  502 +++++++++++++++++++++++++++++++++++++++
>  sound/soc/codecs/jz4740-codec.h |   20 ++
>  4 files changed, 528 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/codecs/jz4740-codec.c
>  create mode 100644 sound/soc/codecs/jz4740-codec.h

no need for code in file name here.

> 
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 31ac553..b8008df 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -23,6 +23,7 @@ config SND_SOC_ALL_CODECS
>  	select SND_SOC_AK4671 if I2C
>  	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
>  	select SND_SOC_CS4270 if I2C
> +	select SND_SOC_JZ4740 if SOC_JZ4740
>  	select SND_SOC_MAX9877 if I2C
>  	select SND_SOC_DA7210 if I2C
>  	select SND_SOC_PCM3008
> @@ -269,6 +270,9 @@ config SND_SOC_WM9712
>  config SND_SOC_WM9713
>  	tristate
>  
> +config SND_SOC_JZ4740_CODEC
> +	tristate
> +
>  # Amp
>  config SND_SOC_MAX9877
>  	tristate
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 91429ea..4c7ee31 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -56,6 +56,7 @@ snd-soc-wm9705-objs := wm9705.o
>  snd-soc-wm9712-objs := wm9712.o
>  snd-soc-wm9713-objs := wm9713.o
>  snd-soc-wm-hubs-objs := wm_hubs.o
> +snd-soc-jz4740-codec-objs := jz4740-codec.o
>  

Please use the same format here

>  # Amp
>  snd-soc-max9877-objs := max9877.o
> @@ -121,6 +122,7 @@ obj-$(CONFIG_SND_SOC_WM9705)	+= snd-soc-wm9705.o
>  obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
>  obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
>  obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
> +obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
>  

ditto.

>  # Amp
>  obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
> diff --git a/sound/soc/codecs/jz4740-codec.c b/sound/soc/codecs/jz4740-codec.c
> new file mode 100644
> index 0000000..6e4b741
> --- /dev/null
> +++ b/sound/soc/codecs/jz4740-codec.c
> @@ -0,0 +1,502 @@
> +/*
> + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <linux/delay.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/initval.h>
> +#include <sound/soc-dapm.h>
> +#include <sound/soc.h>
> +
> +#define JZ4740_REG_CODEC_1 0x0
> +#define JZ4740_REG_CODEC_2 0x1
> +
> +#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
> +#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
> +#define JZ4740_CODEC_1_SW1_ENABLE BIT(27)
> +#define JZ4740_CODEC_1_ADC_ENABLE BIT(26)
> +#define JZ4740_CODEC_1_SW2_ENABLE BIT(25)
> +#define JZ4740_CODEC_1_DAC_ENABLE BIT(24)
> +#define JZ4740_CODEC_1_VREF_DISABLE BIT(20)
> +#define JZ4740_CODEC_1_VREF_AMP_DISABLE BIT(19)
> +#define JZ4740_CODEC_1_VREF_PULL_DOWN BIT(18)
> +#define JZ4740_CODEC_1_VREF_LOW_CURRENT BIT(17)
> +#define JZ4740_CODEC_1_VREF_HIGH_CURRENT BIT(16)
> +#define JZ4740_CODEC_1_HEADPHONE_DISABLE BIT(14)
> +#define JZ4740_CODEC_1_HEADPHONE_AMP_CHANGE_ANY BIT(13)
> +#define JZ4740_CODEC_1_HEADPHONE_CHANGE BIT(12)
> +#define JZ4740_CODEC_1_HEADPHONE_PULL_DOWN_M BIT(11)
> +#define JZ4740_CODEC_1_HEADPHONE_PULL_DOWN_R BIT(10)
> +#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M BIT(9)
> +#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN BIT(8)
> +#define JZ4740_CODEC_1_SUSPEND BIT(1)
> +#define JZ4740_CODEC_1_RESET BIT(0)
> +
> +#define JZ4740_CODEC_1_LINE_ENABLE_OFFSET 29
> +#define JZ4740_CODEC_1_MIC_ENABLE_OFFSET 28
> +#define JZ4740_CODEC_1_SW1_ENABLE_OFFSET 27
> +#define JZ4740_CODEC_1_ADC_ENABLE_OFFSET 26
> +#define JZ4740_CODEC_1_SW2_ENABLE_OFFSET 25
> +#define JZ4740_CODEC_1_DAC_ENABLE_OFFSET 24
> +#define JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET 14
> +#define JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET 8
> +
> +#define JZ4740_CODEC_2_INPUT_VOLUME_MASK		0x1f0000
> +#define JZ4740_CODEC_2_SAMPLE_RATE_MASK			0x000f00
> +#define JZ4740_CODEC_2_MIC_BOOST_GAIN_MASK		0x000030
> +#define JZ4740_CODEC_2_HEADPHONE_VOLUME_MASK	0x000003
> +
> +#define JZ4740_CODEC_2_INPUT_VOLUME_OFFSET		16
> +#define JZ4740_CODEC_2_SAMPLE_RATE_OFFSET		 8
> +#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET	 4
> +#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET	 0
> +
> +struct jz4740_codec {
> +	void __iomem *base;
> +	struct resource *mem;
> +
> +	uint32_t reg_cache[2];
> +	struct snd_soc_codec codec;
> +};
> +
> +static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
> +{
> +	return container_of(codec, struct jz4740_codec, codec);
> +}
> +
> +static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, unsigned int reg)
> +{
> +	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
> +	return readl(jz4740_codec->base + (reg << 2));
> +}
> +
> +static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
> +	unsigned int val)
> +{
> +	struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
> +	jz4740_codec->reg_cache[reg] = val;
> +
> +	writel(val, jz4740_codec->base + (reg << 2));
> +	return 0;
> +}
> +
> +static const struct snd_kcontrol_new jz4740_codec_controls[] = {
> +	SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
> +			JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
> +	SOC_SINGLE("Capture Volume", JZ4740_REG_CODEC_2,
> +			JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),

Is this the master capture volume ?

> +	SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
> +	SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
> +			JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
> +};
> +
> +static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
> +	SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0),
> +	SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0),
> +};
> +
> +static const struct snd_kcontrol_new jz4740_codec_input_controls[] = {
> +	SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0),
> +	SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0),
> +};
> +
> +static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = {
> +	SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0),
> +	SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0),
> +
> +	SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET, 1,
> +			jz4740_codec_output_controls,
> +			ARRAY_SIZE(jz4740_codec_output_controls)),
> +
> +	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
> +			jz4740_codec_input_controls,
> +			ARRAY_SIZE(jz4740_codec_input_controls)),
> +	SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
> +
> +	SND_SOC_DAPM_OUTPUT("LOUT"),
> +	SND_SOC_DAPM_OUTPUT("ROUT"),
> +
> +	SND_SOC_DAPM_INPUT("MIC"),
> +	SND_SOC_DAPM_INPUT("LIN"),
> +	SND_SOC_DAPM_INPUT("RIN"),
> +};
> +
> +static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
> +
> +	{"Line Input", NULL, "LIN"},
> +	{"Line Input", NULL, "RIN"},
> +
> +	{"Input Mixer", "Line Capture Switch", "Line Input"},
> +	{"Input Mixer", "Mic Capture Switch", "MIC"},
> +
> +	{"ADC", NULL, "Input Mixer"},
> +
> +	{"Output Mixer", "Bypass Switch", "Input Mixer"},
> +	{"Output Mixer", "DAC Switch", "DAC"},
> +
> +	{"LOUT", NULL, "Output Mixer"},
> +	{"ROUT", NULL, "Output Mixer"},
> +};
> +
> +static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
> +	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
> +{
> +	uint32_t val;
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct snd_soc_device *socdev = rtd->socdev;
> +	struct snd_soc_codec *codec = socdev->card->codec;
> +
> +	switch (params_format(params)) {
> +	case SNDRV_PCM_FORMAT_S8:
> +	case SNDRV_PCM_FORMAT_S16_LE:
> +	case SNDRV_PCM_FORMAT_S18_3LE:
> +		break;
> +	default:
> +		return -EINVAL;
> +		break;
> +	}

The PCM format check is not required here as core checks this.

> +
> +	switch (params_rate(params)) {
> +	case 8000:
> +		val = 0;
> +		break;
> +	case 11025:
> +		val = 1;
> +		break;
> +	case 12000:
> +		val = 2;
> +		break;
> +	case 16000:
> +		val = 3;
> +		break;
> +	case 22050:
> +		val = 4;
> +		break;
> +	case 24000:
> +		val = 5;
> +		break;
> +	case 32000:
> +		val = 6;
> +		break;
> +	case 44100:
> +		val = 7;
> +		break;
> +	case 48000:
> +		val = 8;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
> +
> +	snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
> +				JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
> +
> +	return 0;
> +}
> +
> +static int jz4740_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +{
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_I2S:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_NB_NF:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
> +	.hw_params = jz4740_codec_hw_params,
> +	.set_fmt = jz4740_codec_set_fmt,
> +};
> +
> +struct snd_soc_dai jz4740_codec_dai = {
> +	.name = "jz-codec",

best to use jz4740 here

> +	.playback = {
> +		.stream_name = "Playback",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
> +	},
> +	.capture = {
> +		.stream_name = "Capture",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
> +	},
> +	.ops = &jz4740_codec_dai_ops,
> +	.symmetric_rates = 1,
> +};
> +EXPORT_SYMBOL_GPL(jz4740_codec_dai);
> +
> +static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
> +	enum snd_soc_bias_level level)
> +{
> +
> +	if (codec->bias_level == SND_SOC_BIAS_OFF && level != SND_SOC_BIAS_OFF) {
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
> +		udelay(2);
> +
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
> +	}
> +	switch (level) {
> +	case SND_SOC_BIAS_ON:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_DISABLE |
> +			JZ4740_CODEC_1_VREF_AMP_DISABLE |
> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M |
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
> +			0);
> +		break;
> +	case SND_SOC_BIAS_PREPARE:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT);
> +		break;
> +	case SND_SOC_BIAS_STANDBY:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE,
> +			JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE);
> +		break;
> +	case SND_SOC_BIAS_OFF:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_SUSPEND, JZ4740_CODEC_1_SUSPEND);
> +		break;
> +	}
> +	codec->bias_level = level;
> +
> +	return 0;
> +}
> +
> +
> +static struct snd_soc_codec *jz4740_codec_codec;
> +
> +static int jz4740_codec_dev_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
> +	struct snd_soc_codec *codec = jz4740_codec_codec;
> +
> +	BUG_ON(!codec);
> +
> +	socdev->card->codec = codec;
> +
> +	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
> +		return ret;
> +	}
> +
> +	snd_soc_add_controls(codec, jz4740_codec_controls,
> +		ARRAY_SIZE(jz4740_codec_controls));
> +
> +	snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
> +		ARRAY_SIZE(jz4740_codec_dapm_widgets));
> +
> +	snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
> +		ARRAY_SIZE(jz4740_codec_dapm_routes));
> +
> +	snd_soc_dapm_new_widgets(codec);
> +
> +	return 0;
> +}
> +
> +static int jz4740_codec_dev_remove(struct platform_device *pdev)
> +{
> +	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
> +	snd_soc_free_pcms(socdev);
> +	snd_soc_dapm_free(socdev);
> +
> +	return 0;
> +}
> +
> +struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
> +	.probe = jz4740_codec_dev_probe,
> +	.remove = jz4740_codec_dev_remove,
> +};
> +EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
> +
> +static int __devinit jz4740_codec_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct jz4740_codec *jz4740_codec;
> +	struct snd_soc_codec *codec;
> +
> +	jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
> +
> +	if (!jz4740_codec)
> +		return -ENOMEM;
> +
> +	jz4740_codec->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	if (!jz4740_codec->mem) {
> +		dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
> +		ret = -ENOENT;
> +		goto err_free_codec;
> +	}
> +
> +	jz4740_codec->mem = request_mem_region(jz4740_codec->mem->start,
> +				resource_size(jz4740_codec->mem), pdev->name);
> +
> +	if (!jz4740_codec->mem) {
> +		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
> +		ret = -EBUSY;
> +		goto err_free_codec;
> +	}
> +
> +	jz4740_codec->base = ioremap(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
> +
> +	if (!jz4740_codec->base) {
> +		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
> +		ret = -EBUSY;
> +		goto err_release_mem_region;
> +	}
> +
> +	jz4740_codec_dai.dev = &pdev->dev;
> +
> +	codec = &jz4740_codec->codec;
> +
> +	codec->dev		= &pdev->dev;
> +	codec->name		= "jz-codec";
> +	codec->owner		= THIS_MODULE;
> +
> +	codec->read		= jz4740_codec_read;
> +	codec->write		= jz4740_codec_write;
> +	codec->set_bias_level	= jz4740_codec_set_bias_level;
> +	codec->bias_level	= SND_SOC_BIAS_OFF;
> +
> +	codec->dai		= &jz4740_codec_dai;
> +	codec->num_dai		= 1;
> +
> +	codec->reg_cache	= jz4740_codec->reg_cache;
> +	codec->reg_cache_size	= 2;
> +
> +	mutex_init(&codec->mutex);
> +	INIT_LIST_HEAD(&codec->dapm_widgets);
> +	INIT_LIST_HEAD(&codec->dapm_paths);
> +
> +	jz4740_codec_codec = codec;
> +
> +	snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +				JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
> +
> +
> +	platform_set_drvdata(pdev, jz4740_codec);
> +	ret = snd_soc_register_codec(codec);
> +
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register codec\n");
> +		goto err_iounmap;
> +	}
> +
> +	ret = snd_soc_register_dai(&jz4740_codec_dai);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register codec dai\n");
> +		goto err_unregister_codec;
> +	}
> +
> +	jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
> +
> +	return 0;
> +err_unregister_codec:
> +	snd_soc_unregister_codec(codec);
> +err_iounmap:
> +	iounmap(jz4740_codec->base);
> +err_release_mem_region:
> +	release_mem_region(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
> +err_free_codec:
> +	kfree(jz4740_codec);
> +
> +	return ret;
> +}
> +
> +static int __devexit jz4740_codec_remove(struct platform_device *pdev)
> +{
> +	struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
> +
> +	snd_soc_unregister_dai(&jz4740_codec_dai);
> +	snd_soc_unregister_codec(&jz4740_codec->codec);
> +
> +	iounmap(jz4740_codec->base);
> +	release_mem_region(jz4740_codec->mem->start, resource_size(jz4740_codec->mem));
> +
> +	platform_set_drvdata(pdev, NULL);
> +	kfree(jz4740_codec);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver jz4740_codec_driver = {
> +	.probe = jz4740_codec_probe,
> +	.remove = __devexit_p(jz4740_codec_remove),
> +	.driver = {
> +		.name = "jz4740-codec",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static int __init jz4740_codec_init(void)
> +{
> +	return platform_driver_register(&jz4740_codec_driver);
> +}
> +module_init(jz4740_codec_init);
> +
> +static void __exit jz4740_codec_exit(void)
> +{
> +	platform_driver_unregister(&jz4740_codec_driver);
> +}
> +module_exit(jz4740_codec_exit);
> +
> +MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:jz-codec");
> diff --git a/sound/soc/codecs/jz4740-codec.h b/sound/soc/codecs/jz4740-codec.h
> new file mode 100644
> index 0000000..b5a0691
> --- /dev/null
> +++ b/sound/soc/codecs/jz4740-codec.h
> @@ -0,0 +1,20 @@
> +/*
> + * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
> +#define __SND_SOC_CODECS_JZ4740_CODEC_H__
> +
> +extern struct snd_soc_dai jz4740_codec_dai;
> +extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
> +
> +#endif

Thanks

Liam
-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk


From florian@openwrt.org Thu Jun  3 16:28:50 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 16:28:56 +0200 (CEST)
Received: from mail-ww0-f49.google.com ([74.125.82.49]:64544 "EHLO
        mail-ww0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492342Ab0FCO2u (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 16:28:50 +0200
Received: by wwi17 with SMTP id 17so129143wwi.36
        for <multiple recipients>; Thu, 03 Jun 2010 07:28:44 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:sender:from:organization:to
         :subject:date:user-agent:cc:references:in-reply-to:mime-version
         :content-type:content-transfer-encoding:message-id;
        bh=CG8t6p15urQ6yl3h1szgP/i0bY7osGfqeVd551S3nOg=;
        b=J82St/3ACn5xOUX4lm6YDNNSqwcWNNfedfD8nFdclYKXVvVBLYKTTTNGV4OUxDiTdw
         Ln5EGJbhtxzLjwHhcR3z1aPAyyTSHj3wjVaxXTgPc78fPpzyqIhI8KMGsmKXdhaKEGlN
         eH28yAgHaQpIevdYdCHEaLI4FvAvUtCUpcb/0=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=sender:from:organization:to:subject:date:user-agent:cc:references
         :in-reply-to:mime-version:content-type:content-transfer-encoding
         :message-id;
        b=pl+VarRbvXMl/+Cs2+PG2bRkoX9EA2JoKWMoKtuLG+rjzDsoKVz66MRzedOK+h/Gdd
         TZZNU/L7gy7ibjCXaRaVTsftkIf5Qxhbwy8GtFdI3VtON+ARAJRGhtS8YA/Q/hKB/GKa
         dMnA4XUgKaKNuPHWE01WMAgLlCtRQJ0Ip1Jt0=
Received: by 10.227.135.6 with SMTP id l6mr9376386wbt.60.1275575323568;
        Thu, 03 Jun 2010 07:28:43 -0700 (PDT)
Received: from flexo.localnet (bobafett.staff.proxad.net [213.228.1.121])
        by mx.google.com with ESMTPS id l23sm1346327wbb.2.2010.06.03.07.28.42
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 07:28:42 -0700 (PDT)
From:   Florian Fainelli <florian@openwrt.org>
Organization: OpenWrt
To:     "Lars-Peter Clausen" <lars@metafoo.de>
Subject: Re: [RFC][PATCH 01/26] MIPS: Add base support for Ingenic JZ4740 System-on-a-Chip
Date:   Thu, 3 Jun 2010 16:27:31 +0200
User-Agent: KMail/1.13.2 (Linux/2.6.32-22-server; KDE/4.4.2; x86_64; ; )
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505397-16758-2-git-send-email-lars@metafoo.de>
In-Reply-To: <1275505397-16758-2-git-send-email-lars@metafoo.de>
MIME-Version: 1.0
Content-Type: Text/Plain;
  charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <201006031627.31308.florian@openwrt.org>
X-archive-position: 27050
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: florian@openwrt.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2438
Content-Length: 4614
Lines: 143

Hi Lars,

On Wednesday 02 June 2010 21:02:52 Lars-Peter Clausen wrote:
> This patch adds a new cpu type for the JZ4740 to the Linux MIPS
> architecture code. It also adds the iomem addresses for the different
> components found on a JZ4740 SoC.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
[snip]

>  	 * MIPS64 class processors
> diff --git a/arch/mips/include/asm/mach-jz4740/base.h
> b/arch/mips/include/asm/mach-jz4740/base.h new file mode 100644
> index 0000000..cba3aae
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-jz4740/base.h
> @@ -0,0 +1,28 @@
> +#ifndef __ASM_MACH_JZ4740_BASE_H__
> +#define __ASM_MACH_JZ4740_BASE_H__
> +
> +#define JZ4740_CPM_BASE_ADDR	0xb0000000
> +#define JZ4740_INTC_BASE_ADDR	0xb0001000
> +#define JZ4740_TCU_BASE_ADDR	0xb0002000
> +#define JZ4740_WDT_BASE_ADDR	0xb0002000
> +#define JZ4740_RTC_BASE_ADDR	0xb0003000
> +#define JZ4740_GPIO_BASE_ADDR	0xb0010000
> +#define JZ4740_AIC_BASE_ADDR	0xb0020000
> +#define JZ4740_ICDC_BASE_ADDR	0xb0020000
> +#define JZ4740_MSC_BASE_ADDR	0xb0021000
> +#define JZ4740_UART0_BASE_ADDR	0xb0030000
> +#define JZ4740_UART1_BASE_ADDR	0xb0031000
> +#define JZ4740_I2C_BASE_ADDR	0xb0042000
> +#define JZ4740_SSI_BASE_ADDR	0xb0043000
> +#define JZ4740_SADC_BASE_ADDR	0xb0070000
> +#define JZ4740_EMC_BASE_ADDR	0xb3010000
> +#define JZ4740_DMAC_BASE_ADDR	0xb3020000
> +#define JZ4740_UHC_BASE_ADDR	0xb3030000
> +#define JZ4740_UDC_BASE_ADDR	0xb3040000
> +#define JZ4740_LCD_BASE_ADDR	0xb3050000
> +#define JZ4740_SLCD_BASE_ADDR	0xb3050000
> +#define JZ4740_CIM_BASE_ADDR	0xb3060000
> +#define JZ4740_IPU_BASE_ADDR	0xb3080000
> +#define JZ4740_ETH_BASE_ADDR	0xb3100000

Any reasons why you prefered virtual addresses here instead of physical ones?
You might also want to define a "true" base address and compute the registers
offset relatively to this base address for better clarity.

> +
> +#endif
> diff --git a/arch/mips/include/asm/mach-jz4740/war.h
> b/arch/mips/include/asm/mach-jz4740/war.h new file mode 100644
> index 0000000..3a5bc17
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-jz4740/war.h
> @@ -0,0 +1,25 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General
> Public + * License.  See the file "COPYING" in the main directory of this
> archive + * for more details.
> + *
> + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
> + */
> +#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H
> +#define __ASM_MIPS_MACH_JZ4740_WAR_H
> +
> +#define R4600_V1_INDEX_ICACHEOP_WAR	0
> +#define R4600_V1_HIT_CACHEOP_WAR	0
> +#define R4600_V2_HIT_CACHEOP_WAR	0
> +#define R5432_CP0_INTERRUPT_WAR		0
> +#define BCM1250_M3_WAR			0
> +#define SIBYTE_1956_WAR			0
> +#define MIPS4K_ICACHE_REFILL_WAR	0
> +#define MIPS_CACHE_SYNC_WAR		0
> +#define TX49XX_ICACHE_INDEX_INV_WAR	0
> +#define RM9000_CDEX_SMP_WAR		0
> +#define ICACHE_REFILLS_WORKAROUND_WAR	0
> +#define R10000_LLSC_WAR			0
> +#define MIPS34K_MISSED_ITLB_WAR		0
> +
> +#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index 3562b85..9b66331 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -187,6 +187,7 @@ void __init check_wait(void)
>  	case CPU_BCM6358:
>  	case CPU_CAVIUM_OCTEON:
>  	case CPU_CAVIUM_OCTEON_PLUS:
> +	case CPU_JZRISC:
>  		cpu_wait = r4k_wait;
>  		break;
> 
> @@ -956,6 +957,22 @@ platform:
>  	}
>  }
> 
> +static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int
> cpu) +{
> +	decode_configs(c);
> +	/* JZRISC does not implement the CP0 counter. */
> +	c->options &= ~MIPS_CPU_COUNTER;
> +	switch (c->processor_id & 0xff00) {
> +	case PRID_IMP_JZRISC:
> +		c->cputype = CPU_JZRISC;
> +		__cpu_name[cpu] = "Ingenic JZRISC";
> +		break;
> +	default:
> +		panic("Unknown Ingenic Processor ID!");
> +		break;
> +	}
> +}
> +
>  const char *__cpu_name[NR_CPUS];
>  const char *__elf_platform;
> 
> @@ -994,6 +1011,9 @@ __cpuinit void cpu_probe(void)
>  	case PRID_COMP_CAVIUM:
>  		cpu_probe_cavium(c, cpu);
>  		break;
> +	case PRID_COMP_INGENIC:
> +		cpu_probe_ingenic(c, cpu);
> +		break;
>  	}
> 
>  	BUG_ON(!__cpu_name[cpu]);
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 86f004d..4510e61 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -409,6 +409,11 @@ static void __cpuinit build_tlb_write_entry(u32 **p,
> struct uasm_label **l, tlbw(p);
>  		break;
> 
> +	case CPU_JZRISC:
> +		tlbw(p);
> +		uasm_i_nop(p);
> +		break;
> +
>  	default:
>  		panic("No TLB refill handler yet (CPU type: %d)",
>  		      current_cpu_data.cputype);

From florian@openwrt.org Thu Jun  3 16:36:00 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 16:36:06 +0200 (CEST)
Received: from mail-wy0-f177.google.com ([74.125.82.177]:60158 "EHLO
        mail-wy0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492038Ab0FCOgA (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 16:36:00 +0200
Received: by wyj26 with SMTP id 26so108801wyj.36
        for <multiple recipients>; Thu, 03 Jun 2010 07:35:54 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:sender:from:organization:to
         :subject:date:user-agent:cc:references:in-reply-to:mime-version
         :content-type:content-transfer-encoding:message-id;
        bh=0omDyI/zfEkqGS7Wm1gpCz2yex2DEMTN38GfVUrOsr4=;
        b=YOuEkB/YI8eZBEims7miI5Q+xZOBEIUvZ9Vzx8MyI8zGvUUmfitlLQS5AFQ911gK6X
         j9ZCV2aw/sBbCShZk9W51KxlCBtKmynb3VdId0AYg47zbWY53Xa2B3Zocy8xNW8usPZj
         bkqDaXvPnOqdH/709zy18CqnMLPzfMrubwGCw=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=sender:from:organization:to:subject:date:user-agent:cc:references
         :in-reply-to:mime-version:content-type:content-transfer-encoding
         :message-id;
        b=HBZdnHZ7xv8VMdA6exCELrEcFN3ZqXfrDdHDgV1J4qabj89sEwKBC1taMyADHBw8Kp
         d7eGww4zPbQGp5D6kMPtzr9DiXB8oY6Z38ObJwHhXezYClJi2OZlz0k6x2FHXsfr4//O
         O9c/j7tchrgsDGr24DFlPPVn/Haf97oOSA2V8=
Received: by 10.227.141.201 with SMTP id n9mr9686892wbu.31.1275575435563;
        Thu, 03 Jun 2010 07:30:35 -0700 (PDT)
Received: from flexo.localnet (bobafett.staff.proxad.net [213.228.1.121])
        by mx.google.com with ESMTPS id t70sm87082weq.14.2010.06.03.07.30.34
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 07:30:35 -0700 (PDT)
From:   Florian Fainelli <florian@openwrt.org>
Organization: OpenWrt
To:     "Lars-Peter Clausen" <lars@metafoo.de>
Subject: Re: [RFC][PATCH 02/26] MIPS: jz4740: Add IRQ handler code
Date:   Thu, 3 Jun 2010 16:29:26 +0200
User-Agent: KMail/1.13.2 (Linux/2.6.32-22-server; KDE/4.4.2; x86_64; ; )
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Thomas Gleixner <tglx@linutronix.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505397-16758-3-git-send-email-lars@metafoo.de>
In-Reply-To: <1275505397-16758-3-git-send-email-lars@metafoo.de>
MIME-Version: 1.0
Content-Type: Text/Plain;
  charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <201006031629.26424.florian@openwrt.org>
X-archive-position: 27051
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: florian@openwrt.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2445
Content-Length: 8623
Lines: 288

On Wednesday 02 June 2010 21:02:53 Lars-Peter Clausen wrote:
> This patch adds support for IRQ handling on a JZ4740 SoC.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> ---
>  arch/mips/include/asm/mach-jz4740/irq.h |   55 ++++++++++
>  arch/mips/jz4740/irq.c                  |  170
> +++++++++++++++++++++++++++++++ arch/mips/jz4740/irq.h                  | 
>  21 ++++
>  3 files changed, 246 insertions(+), 0 deletions(-)
>  create mode 100644 arch/mips/include/asm/mach-jz4740/irq.h
>  create mode 100644 arch/mips/jz4740/irq.c
>  create mode 100644 arch/mips/jz4740/irq.h
> 
> diff --git a/arch/mips/include/asm/mach-jz4740/irq.h
> b/arch/mips/include/asm/mach-jz4740/irq.h new file mode 100644
> index 0000000..5e27b78
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-jz4740/irq.h
> @@ -0,0 +1,55 @@
> +/*
> + *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + *  JZ7420/JZ4740 IRQ definitions
> + *
> + *  This program is free software; you can redistribute	 it and/or modify
> it + *  under  the terms of	 the GNU General  Public License as 
published
> by the + *  Free Software Foundation;  either version 2 of the	License, 
or
> (at your + *  option) any later version.
> + *
> + *  You should have received a copy of the  GNU General Public License
> along + *  with this program; if not, write  to the Free Software
> Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __ASM_MACH_JZ4740_IRQ_H__
> +#define __ASM_MACH_JZ4740_IRQ_H__
> +
> +#define MIPS_CPU_IRQ_BASE 0
> +#define JZ4740_IRQ_BASE 8
> +
> +/* 1st-level interrupts */
> +#define JZ4740_IRQ(x)	(JZ4740_IRQ_BASE + (x))
> +#define JZ4740_IRQ_I2C	JZ4740_IRQ(1)
> +#define JZ4740_IRQ_UHC	JZ4740_IRQ(3)
> +#define JZ4740_IRQ_UART1	JZ4740_IRQ(8)
> +#define JZ4740_IRQ_UART0	JZ4740_IRQ(9)
> +#define JZ4740_IRQ_SADC	JZ4740_IRQ(12)
> +#define JZ4740_IRQ_MSC	JZ4740_IRQ(14)
> +#define JZ4740_IRQ_RTC	JZ4740_IRQ(15)
> +#define JZ4740_IRQ_SSI	JZ4740_IRQ(16)
> +#define JZ4740_IRQ_CIM	JZ4740_IRQ(17)
> +#define JZ4740_IRQ_AIC	JZ4740_IRQ(18)
> +#define JZ4740_IRQ_ETH	JZ4740_IRQ(19)
> +#define JZ4740_IRQ_DMAC	JZ4740_IRQ(20)
> +#define JZ4740_IRQ_TCU2	JZ4740_IRQ(21)
> +#define JZ4740_IRQ_TCU1	JZ4740_IRQ(22)
> +#define JZ4740_IRQ_TCU0	JZ4740_IRQ(23)
> +#define JZ4740_IRQ_UDC	JZ4740_IRQ(24)
> +#define JZ4740_IRQ_GPIO3	JZ4740_IRQ(25)
> +#define JZ4740_IRQ_GPIO2	JZ4740_IRQ(26)
> +#define JZ4740_IRQ_GPIO1	JZ4740_IRQ(27)
> +#define JZ4740_IRQ_GPIO0	JZ4740_IRQ(28)
> +#define JZ4740_IRQ_IPU	JZ4740_IRQ(29)
> +#define JZ4740_IRQ_LCD	JZ4740_IRQ(30)
> +
> +/* 2nd-level interrupts */
> +#define JZ4740_IRQ_DMA(x)	((x) + JZ4740_IRQ(32))
> +
> +#define JZ4740_IRQ_INTC_GPIO(x)	(JZ4740_IRQ_GPIO0 - (x))
> +#define JZ4740_IRQ_GPIO(x)		(JZ4740_IRQ(48) + (x))
> +
> +#define NR_IRQS (JZ4740_IRQ_GPIO(127) + 1)
> +
> +#endif
> diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
> new file mode 100644
> index 0000000..46a03ee
> --- /dev/null
> +++ b/arch/mips/jz4740/irq.c
> @@ -0,0 +1,170 @@
> +/*
> + *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + *  JZ4740 platform IRQ support
> + *
> + *  This program is free software; you can redistribute	 it and/or modify
> it + *  under  the terms of	 the GNU General  Public License as 
published
> by the + *  Free Software Foundation;  either version 2 of the	License, 
or
> (at your + *  option) any later version.
> + *
> + *  You should have received a copy of the  GNU General Public License
> along + *  with this program; if not, write  to the Free Software
> Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/types.h>
> +#include <linux/interrupt.h>
> +#include <linux/ioport.h>
> +#include <linux/timex.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +
> +#include <linux/debugfs.h>
> +#include <linux/seq_file.h>
> +
> +#include <asm/io.h>
> +#include <asm/mipsregs.h>
> +#include <asm/irq_cpu.h>
> +
> +#include <asm/mach-jz4740/base.h>
> +
> +static void __iomem *jz_intc_base;
> +static uint32_t jz_intc_wakeup;
> +static uint32_t jz_intc_saved;
> +
> +#define JZ_REG_INTC_STATUS	0x00
> +#define JZ_REG_INTC_MASK	0x04
> +#define JZ_REG_INTC_SET_MASK	0x08
> +#define JZ_REG_INTC_CLEAR_MASK	0x0c
> +#define JZ_REG_INTC_PENDING	0x10
> +
> +#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
> +
> +static void intc_irq_unmask(unsigned int irq)
> +{
> +	writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
> +}
> +
> +static void intc_irq_mask(unsigned int irq)
> +{
> +	writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK);
> +}
> +
> +static int intc_irq_set_wake(unsigned int irq, unsigned int on)
> +{
> +	if (on)
> +		jz_intc_wakeup |= IRQ_BIT(irq);
> +	else
> +		jz_intc_wakeup &= ~IRQ_BIT(irq);
> +
> +	return 0;
> +}
> +
> +static struct irq_chip intc_irq_type = {
> +	.name =		"INTC",
> +	.mask =		intc_irq_mask,
> +	.mask_ack =	intc_irq_mask,
> +	.unmask =	intc_irq_unmask,
> +	.set_wake =	intc_irq_set_wake,
> +};
> +
> +static irqreturn_t jz4740_cascade(int irq, void *data)
> +{
> +	uint32_t irq_reg;
> +	int intc_irq;
> +
> +	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
> +
> +	intc_irq = ffs(irq_reg);
> +	if (intc_irq)
> +		generic_handle_irq(intc_irq - 1 + JZ4740_IRQ_BASE);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static struct irqaction jz4740_cascade_action = {
> +	.handler = jz4740_cascade,
> +	.name = "JZ4740 cascade interrupt",
> +	.flags = IRQF_DISABLED,
> +};
> +
> +void __init arch_init_irq(void)
> +{
> +	int i;
> +	mips_cpu_irq_init();
> +
> +	jz_intc_base = ioremap(CPHYSADDR(JZ4740_INTC_BASE_ADDR), 0x14);

Better define the physical address and use ioremap directly on it.

> +
> +	for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
> +		intc_irq_mask(i);
> +		set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
> +	}
> +
> +	setup_irq(2, &jz4740_cascade_action);
> +}
> +
> +asmlinkage void plat_irq_dispatch(void)
> +{
> +	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
> +	if (pending & STATUSF_IP2)
> +		do_IRQ(2);
> +	else if (pending & STATUSF_IP3)
> +		do_IRQ(3);
> +	else
> +		spurious_interrupt();
> +}
> +
> +void jz4740_intc_suspend(void)
> +{
> +	jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
> +	writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
> +	writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
> +}
> +
> +void jz4740_intc_resume(void)
> +{
> +	writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
> +	writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +
> +static inline void intc_seq_reg(struct seq_file *s, const char *name,
> +	unsigned int reg)
> +{
> +	seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
> +}
> +
> +static int intc_regs_show(struct seq_file *s, void *unused)
> +{
> +	intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
> +	intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
> +	intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
> +
> +	return 0;
> +}
> +
> +static int intc_regs_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, intc_regs_show, NULL);
> +}
> +
> +static const struct file_operations intc_regs_operations = {
> +	.open		= intc_regs_open,
> +	.read		= seq_read,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +};
> +
> +static int __init intc_debugfs_init(void)
> +{
> +	(void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
> +				NULL, NULL, &intc_regs_operations);
> +	return 0;
> +}
> +subsys_initcall(intc_debugfs_init);
> +
> +#endif
> diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h
> new file mode 100644
> index 0000000..dadbd5f
> --- /dev/null
> +++ b/arch/mips/jz4740/irq.h
> @@ -0,0 +1,21 @@
> +/*
> + *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
> + *
> + *  This program is free software; you can redistribute	 it and/or modify
> it + *  under  the terms of	 the GNU General  Public License as 
published
> by the + *  Free Software Foundation;  either version 2 of the	License, 
or
> (at your + *  option) any later version.
> + *
> + *  You should have received a copy of the  GNU General Public License
> along + *  with this program; if not, write  to the Free Software
> Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __MIPS_JZ4740_IRQ_H__
> +#define __MIPS_JZ4740_IRQ_H__
> +
> +extern void jz4740_intc_suspend(void);
> +extern void jz4740_intc_resume(void);
> +
> +#endif

From lars@metafoo.de Thu Jun  3 18:51:05 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 18:51:10 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:48929 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491063Ab0FCQvF (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 18:51:05 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 217CAC3F;
        Thu,  3 Jun 2010 18:51:00 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id dNOOh4CPNXzv; Thu,  3 Jun 2010 18:50:59 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id E1FE0C3E;
        Thu,  3 Jun 2010 18:50:47 +0200 (CEST)
Message-ID: <4C07DD48.2050503@metafoo.de>
Date:   Thu, 03 Jun 2010 18:50:16 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Liam Girdwood <lrg@slimlogic.co.uk>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>         <1275505950-17334-5-git-send-email-lars@metafoo.de> <1275569309.3593.106.camel@odin>
In-Reply-To: <1275569309.3593.106.camel@odin>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-archive-position: 27052
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2591
Content-Length: 4738
Lines: 148

Liam Girdwood wrote:
> On Wed, 2010-06-02 at 21:12 +0200, Lars-Peter Clausen wrote:
>   
>> This patch adds ASoC support for JZ4740 SoCs I2S module.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
>> Cc: alsa-devel@alsa-project.org
>> ---
>>  sound/soc/Kconfig             |    1 +
>>  sound/soc/Makefile            |    1 +
>>  sound/soc/jz4740/Kconfig      |   13 +
>>  sound/soc/jz4740/Makefile     |    9 +
>>  sound/soc/jz4740/jz4740-i2s.c |  568 +++++++++++++++++++++++++++++++++++++++++
>>  sound/soc/jz4740/jz4740-i2s.h |   18 ++
>>  sound/soc/jz4740/jz4740-pcm.c |  350 +++++++++++++++++++++++++
>>  sound/soc/jz4740/jz4740-pcm.h |   22 ++
>>  8 files changed, 982 insertions(+), 0 deletions(-)
>>  create mode 100644 sound/soc/jz4740/Kconfig
>>  create mode 100644 sound/soc/jz4740/Makefile
>>  create mode 100644 sound/soc/jz4740/jz4740-i2s.c
>>  create mode 100644 sound/soc/jz4740/jz4740-i2s.h
>>  create mode 100644 sound/soc/jz4740/jz4740-pcm.c
>>  create mode 100644 sound/soc/jz4740/jz4740-pcm.h
>>
>> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
>> index b1749bc..5a7a724 100644
>> --- a/sound/soc/Kconfig
>> +++ b/sound/soc/Kconfig
>> @@ -36,6 +36,7 @@ source "sound/soc/s3c24xx/Kconfig"
>>  source "sound/soc/s6000/Kconfig"
>>  source "sound/soc/sh/Kconfig"
>>  source "sound/soc/txx9/Kconfig"
>> +source "sound/soc/jz4740/Kconfig"
>>  
>>  # Supported codecs
>>  source "sound/soc/codecs/Kconfig"
>> diff --git a/sound/soc/Makefile b/sound/soc/Makefile
>> index 1470141..fdbe74d 100644
>> --- a/sound/soc/Makefile
>> +++ b/sound/soc/Makefile
>> @@ -14,3 +14,4 @@ obj-$(CONFIG_SND_SOC)	+= s3c24xx/
>>  obj-$(CONFIG_SND_SOC)	+= s6000/
>>  obj-$(CONFIG_SND_SOC)	+= sh/
>>  obj-$(CONFIG_SND_SOC)	+= txx9/
>> +obj-$(CONFIG_SND_SOC)	+= jz4740/
>> diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
>> new file mode 100644
>> index 0000000..39df949
>> --- /dev/null
>> +++ b/sound/soc/jz4740/Kconfig
>> @@ -0,0 +1,13 @@
>> +config SND_JZ4740_SOC
>> +	tristate "SoC Audio for Ingenic JZ4740 SoC"
>> +	depends on SOC_JZ4740 && SND_SOC
>> +	help
>> +	  Say Y or M if you want to add support for codecs attached to
>> +	  the Jz4740 AC97, I2S or SSP interface. You will also need
>>     
>
> Do you have an AC97 or SSP interface ?
>
>   
Whoops. Copy-paste leftover...
>> +	[....]
>> +
>> +
>> +static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
>> +	struct snd_soc_dai *dai)
>> +{
>> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
>> +	bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
>> +
>> +	uint32_t ctrl;
>> +	uint32_t mask;
>> +
>> +	if (playback)
>>     
>
> It's best to use (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) here.
>
>   
hm, ok
>> +	[...]
>> --- /dev/null
>> +++ b/sound/soc/jz4740/jz4740-pcm.c
>> @@ -0,0 +1,350 @@
>> + [...] 
>> +static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
>> +	struct snd_pcm_hw_params *params)
>> +{
>> +	struct snd_pcm_runtime *runtime = substream->runtime;
>> +	struct jz4740_runtime_data *prtd = runtime->private_data;
>> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
>> +	struct jz4740_pcm_config *config;
>> +
>> +	config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
>> +	if (!prtd->dma) {
>> +		const char *dma_channel_name;
>> +		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>> +			dma_channel_name = "PCM Playback";
>> +		else
>> +			dma_channel_name = "PCM Capture";
>> +
>> +		prtd->dma = jz4740_dma_request(substream, dma_channel_name);
>>     
>
> dma_channel_name variable is not required here. Just use the const char
> * directly.
>
>   
I actually had it like that before, but I think it is much more readable
in its current form. Considering that stream value will either be 0 or 1
it might work to put the channel names into a static array.
>> +	[...]
>> +
>> +static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
>> +{
>> +	struct snd_pcm_runtime *runtime = substream->runtime;
>> +	struct jz4740_runtime_data *prtd = runtime->private_data;
>> +	unsigned long count, pos;
>> +	snd_pcm_uframes_t offset;
>> +	struct jz4740_dma_chan *dma = prtd->dma;
>> +
>> +	count = jz4740_dma_get_residue(dma);
>> +	if (prtd->dma_pos == prtd->dma_start)
>> +		pos = prtd->dma_end - prtd->dma_start - count;
>> +	else
>> +		pos = prtd->dma_pos - prtd->dma_start - count;
>> +
>> +	offset = bytes_to_frames(runtime, pos);
>> +	if (offset >= runtime->buffer_size)
>> +		offset = 0;
>> +
>>     
>
> Could you comment your calculation a little more.
>   
Will do.
>
> Thanks
>
> Liam
>   
Thanks for the review
- Lars


From lars@metafoo.de Thu Jun  3 18:59:06 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 18:59:10 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:49335 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492392Ab0FCQ7G (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 18:59:06 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 89FC1C81;
        Thu,  3 Jun 2010 18:59:00 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id PL7KDsHfJMqR; Thu,  3 Jun 2010 18:59:00 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 84366C80;
        Thu,  3 Jun 2010 18:58:59 +0200 (CEST)
Message-ID: <4C07DF34.7030401@metafoo.de>
Date:   Thu, 03 Jun 2010 18:58:28 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Liam Girdwood <lrg@slimlogic.co.uk>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        linux-kernel@vger.kernel.org
Subject: Re: [alsa-devel] [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec
 driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>         <1275505950-17334-4-git-send-email-lars@metafoo.de> <1275568334.3593.92.camel@odin>
In-Reply-To: <1275568334.3593.92.camel@odin>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-archive-position: 27053
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2600
Content-Length: 5996
Lines: 186

Liam Girdwood wrote:
> On Wed, 2010-06-02 at 21:12 +0200, Lars-Peter Clausen wrote:
>   
>> This patch adds support for the JZ4740 internal codec.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
>> Cc: alsa-devel@alsa-project.org
>> ---
>>  sound/soc/codecs/Kconfig        |    4 +
>>  sound/soc/codecs/Makefile       |    2 +
>>  sound/soc/codecs/jz4740-codec.c |  502 +++++++++++++++++++++++++++++++++++++++
>>  sound/soc/codecs/jz4740-codec.h |   20 ++
>>  4 files changed, 528 insertions(+), 0 deletions(-)
>>  create mode 100644 sound/soc/codecs/jz4740-codec.c
>>  create mode 100644 sound/soc/codecs/jz4740-codec.h
>>     
>
> no need for code in file name here.
>
>   
>> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
>> index 31ac553..b8008df 100644
>> --- a/sound/soc/codecs/Kconfig
>> +++ b/sound/soc/codecs/Kconfig
>> @@ -23,6 +23,7 @@ config SND_SOC_ALL_CODECS
>>  	select SND_SOC_AK4671 if I2C
>>  	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
>>  	select SND_SOC_CS4270 if I2C
>> +	select SND_SOC_JZ4740 if SOC_JZ4740
>>  	select SND_SOC_MAX9877 if I2C
>>  	select SND_SOC_DA7210 if I2C
>>  	select SND_SOC_PCM3008
>> @@ -269,6 +270,9 @@ config SND_SOC_WM9712
>>  config SND_SOC_WM9713
>>  	tristate
>>  
>> +config SND_SOC_JZ4740_CODEC
>> +	tristate
>> +
>>  # Amp
>>  config SND_SOC_MAX9877
>>  	tristate
>> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
>> index 91429ea..4c7ee31 100644
>> --- a/sound/soc/codecs/Makefile
>> +++ b/sound/soc/codecs/Makefile
>> @@ -56,6 +56,7 @@ snd-soc-wm9705-objs := wm9705.o
>>  snd-soc-wm9712-objs := wm9712.o
>>  snd-soc-wm9713-objs := wm9713.o
>>  snd-soc-wm-hubs-objs := wm_hubs.o
>> +snd-soc-jz4740-codec-objs := jz4740-codec.o
>>  
>>     
>
> Please use the same format here
>
>   
>>  # Amp
>>  snd-soc-max9877-objs := max9877.o
>> @@ -121,6 +122,7 @@ obj-$(CONFIG_SND_SOC_WM9705)	+= snd-soc-wm9705.o
>>  obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
>>  obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
>>  obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
>> +obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
>>  
>>     
>
> ditto.
>   
Ok, I agree, but the Kconfig symbol should keep the "CODEC" in it,
otherwise it would clash with the JZ4740 ASoC platform support.
>   
>>  # Amp
>>  obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
>> diff --git a/sound/soc/codecs/jz4740-codec.c b/sound/soc/codecs/jz4740-codec.c
>> new file mode 100644
>> index 0000000..6e4b741
>> --- /dev/null
>> +++ b/sound/soc/codecs/jz4740-codec.c
>> @@ -0,0 +1,502 @@
>> + [...]
>> +static const struct snd_kcontrol_new jz4740_codec_controls[] = {
>> +	SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
>> +			JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
>> +	SOC_SINGLE("Capture Volume", JZ4740_REG_CODEC_2,
>> +			JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
>>     
>
> Is this the master capture volume ?
>   
Hm, yes.
>   
>> +	SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
>> +	SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
>> +			JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
>> +};
>> +
>> +static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
>> +	SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0),
>> +	SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0),
>> +};
>> +
>> +static const struct snd_kcontrol_new jz4740_codec_input_controls[] = {
>> +	SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0),
>> +	SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0),
>> +};
>> +
>> +static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = {
>> +	SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0),
>> +	SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0),
>> +
>> +	SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_OFFSET, 1,
>> +			jz4740_codec_output_controls,
>> +			ARRAY_SIZE(jz4740_codec_output_controls)),
>> +
>> +	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
>> +			jz4740_codec_input_controls,
>> +			ARRAY_SIZE(jz4740_codec_input_controls)),
>> +	SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
>> +
>> +	SND_SOC_DAPM_OUTPUT("LOUT"),
>> +	SND_SOC_DAPM_OUTPUT("ROUT"),
>> +
>> +	SND_SOC_DAPM_INPUT("MIC"),
>> +	SND_SOC_DAPM_INPUT("LIN"),
>> +	SND_SOC_DAPM_INPUT("RIN"),
>> +};
>> +
>> +static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
>> +
>> +	{"Line Input", NULL, "LIN"},
>> +	{"Line Input", NULL, "RIN"},
>> +
>> +	{"Input Mixer", "Line Capture Switch", "Line Input"},
>> +	{"Input Mixer", "Mic Capture Switch", "MIC"},
>> +
>> +	{"ADC", NULL, "Input Mixer"},
>> +
>> +	{"Output Mixer", "Bypass Switch", "Input Mixer"},
>> +	{"Output Mixer", "DAC Switch", "DAC"},
>> +
>> +	{"LOUT", NULL, "Output Mixer"},
>> +	{"ROUT", NULL, "Output Mixer"},
>> +};
>> +
>> +static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
>> +	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
>> +{
>> +	uint32_t val;
>> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
>> +	struct snd_soc_device *socdev = rtd->socdev;
>> +	struct snd_soc_codec *codec = socdev->card->codec;
>> +
>> +	switch (params_format(params)) {
>> +	case SNDRV_PCM_FORMAT_S8:
>> +	case SNDRV_PCM_FORMAT_S16_LE:
>> +	case SNDRV_PCM_FORMAT_S18_3LE:
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +		break;
>> +	}
>>     
>
> The PCM format check is not required here as core checks this.
>   
Ok.
>> + [...]
>
> Thanks
>
> Liam
>   

Thanks for reviewing
- Lars

From lars@metafoo.de Thu Jun  3 19:03:41 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:03:49 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:49531 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492671Ab0FCRDl (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:03:41 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 9EDC7C96;
        Thu,  3 Jun 2010 19:03:35 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id Aph1eRcs9MO2; Thu,  3 Jun 2010 19:03:35 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 85518C95;
        Thu,  3 Jun 2010 19:03:34 +0200 (CEST)
Message-ID: <4C07E047.4090401@metafoo.de>
Date:   Thu, 03 Jun 2010 19:03:03 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Florian Fainelli <florian@openwrt.org>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org
Subject: Re: [RFC][PATCH 01/26] MIPS: Add base support for Ingenic JZ4740
 System-on-a-Chip
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505397-16758-2-git-send-email-lars@metafoo.de> <201006031627.31308.florian@openwrt.org>
In-Reply-To: <201006031627.31308.florian@openwrt.org>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-archive-position: 27054
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2608
Content-Length: 2195
Lines: 63

Hi Florian

Florian Fainelli wrote:
> Hi Lars,
>
> On Wednesday 02 June 2010 21:02:52 Lars-Peter Clausen wrote:
>   
>> This patch adds a new cpu type for the JZ4740 to the Linux MIPS
>> architecture code. It also adds the iomem addresses for the different
>> components found on a JZ4740 SoC.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> ---
>>     
> [snip]
>
>   
>>  	 * MIPS64 class processors
>> diff --git a/arch/mips/include/asm/mach-jz4740/base.h
>> b/arch/mips/include/asm/mach-jz4740/base.h new file mode 100644
>> index 0000000..cba3aae
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-jz4740/base.h
>> @@ -0,0 +1,28 @@
>> +#ifndef __ASM_MACH_JZ4740_BASE_H__
>> +#define __ASM_MACH_JZ4740_BASE_H__
>> +
>> +#define JZ4740_CPM_BASE_ADDR	0xb0000000
>> +#define JZ4740_INTC_BASE_ADDR	0xb0001000
>> +#define JZ4740_TCU_BASE_ADDR	0xb0002000
>> +#define JZ4740_WDT_BASE_ADDR	0xb0002000
>> +#define JZ4740_RTC_BASE_ADDR	0xb0003000
>> +#define JZ4740_GPIO_BASE_ADDR	0xb0010000
>> +#define JZ4740_AIC_BASE_ADDR	0xb0020000
>> +#define JZ4740_ICDC_BASE_ADDR	0xb0020000
>> +#define JZ4740_MSC_BASE_ADDR	0xb0021000
>> +#define JZ4740_UART0_BASE_ADDR	0xb0030000
>> +#define JZ4740_UART1_BASE_ADDR	0xb0031000
>> +#define JZ4740_I2C_BASE_ADDR	0xb0042000
>> +#define JZ4740_SSI_BASE_ADDR	0xb0043000
>> +#define JZ4740_SADC_BASE_ADDR	0xb0070000
>> +#define JZ4740_EMC_BASE_ADDR	0xb3010000
>> +#define JZ4740_DMAC_BASE_ADDR	0xb3020000
>> +#define JZ4740_UHC_BASE_ADDR	0xb3030000
>> +#define JZ4740_UDC_BASE_ADDR	0xb3040000
>> +#define JZ4740_LCD_BASE_ADDR	0xb3050000
>> +#define JZ4740_SLCD_BASE_ADDR	0xb3050000
>> +#define JZ4740_CIM_BASE_ADDR	0xb3060000
>> +#define JZ4740_IPU_BASE_ADDR	0xb3080000
>> +#define JZ4740_ETH_BASE_ADDR	0xb3100000
>>     
>
> Any reasons why you prefered virtual addresses here instead of physical ones?
> You might also want to define a "true" base address and compute the registers
> offset relatively to this base address for better clarity.
>
>   
This is historically grown and I agree that I should rather use the
physical addresses here, especially because they are only used together
with CPHYSADDR everywhere now.

Thanks for reviewing
- Lars

From lrg@slimlogic.co.uk Thu Jun  3 19:08:55 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:09:02 +0200 (CEST)
Received: from mail-ww0-f49.google.com ([74.125.82.49]:61483 "EHLO
        mail-ww0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492390Ab0FCRIz (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:08:55 +0200
Received: by wwi17 with SMTP id 17so276789wwi.36
        for <multiple recipients>; Thu, 03 Jun 2010 10:08:50 -0700 (PDT)
Received: by 10.227.144.129 with SMTP id z1mr9691559wbu.3.1275584612631;
        Thu, 03 Jun 2010 10:03:32 -0700 (PDT)
Received: from [192.168.1.6] (host81-136-218-57.in-addr.btopenworld.com [81.136.218.57])
        by mx.google.com with ESMTPS id e82sm206957wej.16.2010.06.03.10.03.30
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 10:03:31 -0700 (PDT)
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
From:   Liam Girdwood <lrg@slimlogic.co.uk>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        alsa-devel@alsa-project.org
In-Reply-To: <4C07DD48.2050503@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
         <1275505950-17334-5-git-send-email-lars@metafoo.de>
         <1275569309.3593.106.camel@odin>  <4C07DD48.2050503@metafoo.de>
Content-Type: text/plain; charset="UTF-8"
Date:   Thu, 03 Jun 2010 18:03:29 +0100
Message-ID: <1275584609.3118.26.camel@odin>
Mime-Version: 1.0
X-Mailer: Evolution 2.28.3 
Content-Transfer-Encoding: 7bit
X-archive-position: 27055
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lrg@slimlogic.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2610
Content-Length: 967
Lines: 31

On Thu, 2010-06-03 at 18:50 +0200, Lars-Peter Clausen wrote:
> >> +    config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai,
> substream);
> >> +    if (!prtd->dma) {
> >> +            const char *dma_channel_name;
> >> +            if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> >> +                    dma_channel_name = "PCM Playback";
> >> +            else
> >> +                    dma_channel_name = "PCM Capture";
> >> +
> >> +            prtd->dma = jz4740_dma_request(substream,
> dma_channel_name);
> >>     
> >
> > dma_channel_name variable is not required here. Just use the const
> char
> > * directly.
> >
> >   
> I actually had it like that before, but I think it is much more readable
> in its current form.

I disagree, having the char pointer here just adds an extra level of
indirection and costs an extra two lines of code. 

Liam 
-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk


From lars@metafoo.de Thu Jun  3 19:17:20 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:17:24 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:50365 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491918Ab0FCRRU (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:17:20 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 34F21CDA;
        Thu,  3 Jun 2010 19:17:14 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id bVLzuL-h-CbM; Thu,  3 Jun 2010 19:17:13 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 56B27CD9;
        Thu,  3 Jun 2010 19:17:13 +0200 (CEST)
Message-ID: <4C07E37A.40502@metafoo.de>
Date:   Thu, 03 Jun 2010 19:16:42 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Liam Girdwood <lrg@slimlogic.co.uk>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>         <1275505950-17334-5-git-send-email-lars@metafoo.de>         <1275569309.3593.106.camel@odin>  <4C07DD48.2050503@metafoo.de> <1275584609.3118.26.camel@odin>
In-Reply-To: <1275584609.3118.26.camel@odin>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-archive-position: 27056
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2616
Content-Length: 1072
Lines: 42

Liam Girdwood wrote:
> On Thu, 2010-06-03 at 18:50 +0200, Lars-Peter Clausen wrote:
>   
>>>> +    config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai,
>>>>         
>> substream);
>>     
>>>> +    if (!prtd->dma) {
>>>> +            const char *dma_channel_name;
>>>> +            if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>>>> +                    dma_channel_name = "PCM Playback";
>>>> +            else
>>>> +                    dma_channel_name = "PCM Capture";
>>>> +
>>>> +            prtd->dma = jz4740_dma_request(substream,
>>>>         
>> dma_channel_name);
>>     
>>>>     
>>>>         
>>> dma_channel_name variable is not required here. Just use the const
>>>       
>> char
>>     
>>> * directly.
>>>
>>>   
>>>       
>> I actually had it like that before, but I think it is much more readable
>> in its current form.
>>     
>
> I disagree, having the char pointer here just adds an extra level of
> indirection and costs an extra two lines of code. 
>
> Liam 
>   
Hi

Could you give an concrete example of how you would code it?

- Lars

From lars@metafoo.de Thu Jun  3 19:21:13 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:21:17 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:50596 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492390Ab0FCRVN (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:21:13 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 5E2BECFE;
        Thu,  3 Jun 2010 19:21:05 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id v+dsXr6szYbs; Thu,  3 Jun 2010 19:21:05 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id BFF84CFD;
        Thu,  3 Jun 2010 19:21:04 +0200 (CEST)
Message-ID: <4C07E461.9000506@metafoo.de>
Date:   Thu, 03 Jun 2010 19:20:33 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Graham Gower <graham.gower@gmail.com>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org
Subject: Re: [RFC][PATCH 03/26] MIPS: JZ4740: Add clock API support.
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>        <1275505397-16758-4-git-send-email-lars@metafoo.de> <AANLkTimVM637peyrPP7dZ3Uy2S-3DAEXspGi-FONcW6p@mail.gmail.com>
In-Reply-To: <AANLkTimVM637peyrPP7dZ3Uy2S-3DAEXspGi-FONcW6p@mail.gmail.com>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-archive-position: 27057
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2618
Content-Length: 431
Lines: 22

Graham Gower wrote:
> On 3 June 2010 04:32, Lars-Peter Clausen <lars@metafoo.de> wrote:
>
>   
>> +       {
>> +               .name = "dma",
>> +               .parent = &jz_clk_high_speed_peripheral.clk,
>> +               .gate_bit = JZ_CLOCK_GATE_UART0,
>> +               .ops = &jz_clk_simple_ops,
>> +       },
>>     
>
> Presumably this should be JZ_CLOCK_GATE_DMAC.
>
> -Graham
>   
Hi

Yes.

Thanks for reviewing
- Lars

From lrg@slimlogic.co.uk Thu Jun  3 19:25:12 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:25:16 +0200 (CEST)
Received: from mail-wy0-f177.google.com ([74.125.82.177]:60044 "EHLO
        mail-wy0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492030Ab0FCRZM (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:25:12 +0200
Received: by wyj26 with SMTP id 26so264365wyj.36
        for <multiple recipients>; Thu, 03 Jun 2010 10:25:04 -0700 (PDT)
Received: by 10.216.88.203 with SMTP id a53mr1472081wef.25.1275585903976;
        Thu, 03 Jun 2010 10:25:03 -0700 (PDT)
Received: from [192.168.1.6] (host81-136-218-57.in-addr.btopenworld.com [81.136.218.57])
        by mx.google.com with ESMTPS id k13sm220714wed.23.2010.06.03.10.25.01
        (version=SSLv3 cipher=RC4-MD5);
        Thu, 03 Jun 2010 10:25:02 -0700 (PDT)
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
From:   Liam Girdwood <lrg@slimlogic.co.uk>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        alsa-devel@alsa-project.org
In-Reply-To: <4C07E37A.40502@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
         <1275505950-17334-5-git-send-email-lars@metafoo.de>
         <1275569309.3593.106.camel@odin>  <4C07DD48.2050503@metafoo.de>
         <1275584609.3118.26.camel@odin>  <4C07E37A.40502@metafoo.de>
Content-Type: text/plain; charset="UTF-8"
Date:   Thu, 03 Jun 2010 18:25:00 +0100
Message-ID: <1275585900.3118.29.camel@odin>
Mime-Version: 1.0
X-Mailer: Evolution 2.28.3 
Content-Transfer-Encoding: 7bit
X-archive-position: 27058
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lrg@slimlogic.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2622
Content-Length: 1581
Lines: 59

On Thu, 2010-06-03 at 19:16 +0200, Lars-Peter Clausen wrote:
> Liam Girdwood wrote:
> > On Thu, 2010-06-03 at 18:50 +0200, Lars-Peter Clausen wrote:
> >   
> >>>> +    config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai,
> >>>>         
> >> substream);
> >>     
> >>>> +    if (!prtd->dma) {
> >>>> +            const char *dma_channel_name;
> >>>> +            if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> >>>> +                    dma_channel_name = "PCM Playback";
> >>>> +            else
> >>>> +                    dma_channel_name = "PCM Capture";
> >>>> +
> >>>> +            prtd->dma = jz4740_dma_request(substream,
> >>>>         
> >> dma_channel_name);
> >>     
> >>>>     
> >>>>         
> >>> dma_channel_name variable is not required here. Just use the const
> >>>       
> >> char
> >>     
> >>> * directly.
> >>>
> >>>   
> >>>       
> >> I actually had it like that before, but I think it is much more readable
> >> in its current form.
> >>     
> >
> > I disagree, having the char pointer here just adds an extra level of
> > indirection and costs an extra two lines of code. 
> >
> > Liam 
> >   
> Hi
> 
> Could you give an concrete example of how you would code it?
> 

Sure,

if (!prtd->dma) {
          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                   prtd->dma = jz4740_dma_request(substream, "PCM Playback");
          else
                   prtd->dma = jz4740_dma_request(substream, "PCM Capture");
}

Liam

-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk


From lars@metafoo.de Thu Jun  3 19:37:51 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:37:56 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:51359 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492667Ab0FCRhv (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:37:51 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 78557D6B;
        Thu,  3 Jun 2010 19:37:45 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id Rp8hKXhWcpYA; Thu,  3 Jun 2010 19:37:45 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 9FBF0D6A;
        Thu,  3 Jun 2010 19:37:44 +0200 (CEST)
Message-ID: <4C07E849.6080202@metafoo.de>
Date:   Thu, 03 Jun 2010 19:37:13 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Liam Girdwood <lrg@slimlogic.co.uk>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>  <1275505950-17334-5-git-send-email-lars@metafoo.de>     <1275569309.3593.106.camel@odin>  <4C07DD48.2050503@metafoo.de>         <1275584609.3118.26.camel@odin>  <4C07E37A.40502@metafoo.de> <1275585900.3118.29.camel@odin>
In-Reply-To: <1275585900.3118.29.camel@odin>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-archive-position: 27059
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2638
Content-Length: 2017
Lines: 78

Liam Girdwood wrote:
> On Thu, 2010-06-03 at 19:16 +0200, Lars-Peter Clausen wrote:
>   
>> Liam Girdwood wrote:
>>     
>>> On Thu, 2010-06-03 at 18:50 +0200, Lars-Peter Clausen wrote:
>>>   
>>>       
>>>>>> +    config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai,
>>>>>>         
>>>>>>             
>>>> substream);
>>>>     
>>>>         
>>>>>> +    if (!prtd->dma) {
>>>>>> +            const char *dma_channel_name;
>>>>>> +            if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>>>>>> +                    dma_channel_name = "PCM Playback";
>>>>>> +            else
>>>>>> +                    dma_channel_name = "PCM Capture";
>>>>>> +
>>>>>> +            prtd->dma = jz4740_dma_request(substream,
>>>>>>         
>>>>>>             
>>>> dma_channel_name);
>>>>     
>>>>         
>>>>>>     
>>>>>>         
>>>>>>             
>>>>> dma_channel_name variable is not required here. Just use the const
>>>>>       
>>>>>           
>>>> char
>>>>     
>>>>         
>>>>> * directly.
>>>>>
>>>>>   
>>>>>       
>>>>>           
>>>> I actually had it like that before, but I think it is much more readable
>>>> in its current form.
>>>>     
>>>>         
>>> I disagree, having the char pointer here just adds an extra level of
>>> indirection and costs an extra two lines of code. 
>>>
>>> Liam 
>>>   
>>>       
>> Hi
>>
>> Could you give an concrete example of how you would code it?
>>
>>     
>
> Sure,
>
> if (!prtd->dma) {
>           if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>                    prtd->dma = jz4740_dma_request(substream, "PCM Playback");
>           else
>                    prtd->dma = jz4740_dma_request(substream, "PCM Capture");
> }
>
> Liam
>
>   
And now you have the same statement in two different lines. When it
needs to be changed you have to change both lines.
And furthermore in my opinion it distracts from the reason for the if
statement: We want a different channel name.

But ok, if you insist on it, I can live with changing it.

- Lars


From broonie@opensource.wolfsonmicro.com Thu Jun  3 19:50:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:50:05 +0200 (CEST)
Received: from opensource.wolfsonmicro.com ([80.75.67.52]:38614 "EHLO
        opensource2.wolfsonmicro.com" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492676Ab0FCRuB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:50:01 +0200
Received: from rakim.wolfsonmicro.main (lumison.wolfsonmicro.com [87.246.78.27])
        by opensource2.wolfsonmicro.com (Postfix) with ESMTPSA id 006A9110504;
        Thu,  3 Jun 2010 18:49:53 +0100 (BST)
Received: from broonie by rakim.wolfsonmicro.main with local (Exim 4.71)
        (envelope-from <broonie@rakim.wolfsonmicro.main>)
        id 1OKEYD-00017W-Fk; Thu, 03 Jun 2010 18:49:53 +0100
Date:   Thu, 3 Jun 2010 18:49:53 +0100
From:   Mark Brown <broonie@opensource.wolfsonmicro.com>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec driver
Message-ID: <20100603174953.GH2762@rakim.wolfsonmicro.main>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
 <1275505950-17334-4-git-send-email-lars@metafoo.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275505950-17334-4-git-send-email-lars@metafoo.de>
X-Cookie: In the next world, you're on your own.
User-Agent: Mutt/1.5.20 (2009-06-14)
X-archive-position: 27060
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: broonie@opensource.wolfsonmicro.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2647
Content-Length: 2496
Lines: 73

On Wed, Jun 02, 2010 at 09:12:26PM +0200, Lars-Peter Clausen wrote:

> This patch adds support for the JZ4740 internal codec.

This looks very good, there are some issues but nothing too major.  I
may be repeating some things others have said but hopefully not too
much.

>  snd-soc-wm9712-objs := wm9712.o
>  snd-soc-wm9713-objs := wm9713.o
>  snd-soc-wm-hubs-objs := wm_hubs.o
> +snd-soc-jz4740-codec-objs := jz4740-codec.o

Keep the devices sorted in both Makefile and Kconfig.

> +static int jz4740_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
> +{
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}

This does nothing except validate some parameters.  Is there actually an
externally visible DAI for this CODEC?  If it's just integrated into the
SoC and there's nothing to configure then just omit the DAI
configuration since it's not even useful to document the signal format.

> +	.capture = {
> +		.stream_name = "Capture",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = SNDRV_PCM_RATE_8000_48000,
> +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,

You listed an 18 bit format in hw_params - one or other of this and
hw_params is presumably out of date.

> +static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
> +	enum snd_soc_bias_level level)
> +{
> +
> +	if (codec->bias_level == SND_SOC_BIAS_OFF && level != SND_SOC_BIAS_OFF) {
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
> +		udelay(2);

I'd expect to see this as part of the _OFF in the main switch
statement.

> +	switch (level) {
> +	case SND_SOC_BIAS_ON:
> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
> +			JZ4740_CODEC_1_VREF_DISABLE |
> +			JZ4740_CODEC_1_VREF_AMP_DISABLE |
> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M |
> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
> +			0);

This looks suspiciously like you should be using DAPM for the headphone
at least, though if there's only headphone out that's possibly not worth
it.  Also, are you sure that you want both low and high current VREF
configuring here?  I'm not clear what these settings do but the way
they're being managed both here and in _PREPARE seems odd.

> +	codec = &jz4740_codec->codec;
> +
> +	codec->dev		= &pdev->dev;
> +	codec->name		= "jz-codec";

Seems a bit odd to use the part number in some places and not others.

From broonie@opensource.wolfsonmicro.com Thu Jun  3 19:55:17 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:55:20 +0200 (CEST)
Received: from opensource.wolfsonmicro.com ([80.75.67.52]:34399 "EHLO
        opensource2.wolfsonmicro.com" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492670Ab0FCRzR (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:55:17 +0200
Received: from rakim.wolfsonmicro.main (lumison.wolfsonmicro.com [87.246.78.27])
        by opensource2.wolfsonmicro.com (Postfix) with ESMTPSA id B4C97110504;
        Thu,  3 Jun 2010 18:55:11 +0100 (BST)
Received: from broonie by rakim.wolfsonmicro.main with local (Exim 4.71)
        (envelope-from <broonie@rakim.wolfsonmicro.main>)
        id 1OKEdL-00017k-6l; Thu, 03 Jun 2010 18:55:11 +0100
Date:   Thu, 3 Jun 2010 18:55:11 +0100
From:   Mark Brown <broonie@opensource.wolfsonmicro.com>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
Message-ID: <20100603175511.GI2762@rakim.wolfsonmicro.main>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
 <1275505950-17334-5-git-send-email-lars@metafoo.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275505950-17334-5-git-send-email-lars@metafoo.de>
X-Cookie: In the next world, you're on your own.
User-Agent: Mutt/1.5.20 (2009-06-14)
X-archive-position: 27061
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: broonie@opensource.wolfsonmicro.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2658
Content-Length: 1350
Lines: 51

On Wed, Jun 02, 2010 at 09:12:27PM +0200, Lars-Peter Clausen wrote:

Again, overall very good.

> +static int jz4740_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
> +{
> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
> +
> +	switch (div_id) {
> +	case JZ4740_I2S_BIT_CLK:
> +		if (div & 1 || div > 16)
> +			return -EINVAL;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div - 1);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}

You can probably figure out the bit clock automatically by default...

> +	if (dai->active) {
> +		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
> +		conf &= ~JZ_AIC_CONF_ENABLE;
> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
> +
> +		clk_disable(i2s->clk_i2s);
> +	}
> +
> +	clk_disable(i2s->clk_aic);

Might make sense to manage this clock dynamically at runtime too for a
little extra power saving?

> +	i2s->clk_aic = clk_get(&pdev->dev, "aic");
> +	if (IS_ERR(i2s->clk_aic)) {
> +		ret = PTR_ERR(i2s->clk_aic);
> +		goto err_iounmap;
> +	}
> +
> +	i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
> +	if (IS_ERR(i2s->clk_i2s)) {
> +		ret = PTR_ERR(i2s->clk_i2s);
> +		goto err_iounmap;
> +	}

Ideally you'd free the AIC clock when unwinding (and later stop it after
it was enabled).  Though since you don't do any error checking after
this point it's kind of academic :)

From broonie@opensource.wolfsonmicro.com Thu Jun  3 19:57:21 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 19:57:24 +0200 (CEST)
Received: from opensource.wolfsonmicro.com ([80.75.67.52]:34420 "EHLO
        opensource2.wolfsonmicro.com" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492670Ab0FCR5V (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 19:57:21 +0200
Received: from rakim.wolfsonmicro.main (lumison.wolfsonmicro.com [87.246.78.27])
        by opensource2.wolfsonmicro.com (Postfix) with ESMTPSA id A408F110504;
        Thu,  3 Jun 2010 18:57:15 +0100 (BST)
Received: from broonie by rakim.wolfsonmicro.main with local (Exim 4.71)
        (envelope-from <broonie@rakim.wolfsonmicro.main>)
        id 1OKEfL-00017r-4z; Thu, 03 Jun 2010 18:57:15 +0100
Date:   Thu, 3 Jun 2010 18:57:15 +0100
From:   Mark Brown <broonie@opensource.wolfsonmicro.com>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 26/26] alsa: ASoC: JZ4740: Add qi_lb60 board driver
Message-ID: <20100603175714.GJ2762@rakim.wolfsonmicro.main>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
 <1275506132-17519-2-git-send-email-lars@metafoo.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275506132-17519-2-git-send-email-lars@metafoo.de>
X-Cookie: In the next world, you're on your own.
User-Agent: Mutt/1.5.20 (2009-06-14)
X-archive-position: 27062
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: broonie@opensource.wolfsonmicro.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2662
Content-Length: 721
Lines: 22

On Wed, Jun 02, 2010 at 09:15:32PM +0200, Lars-Peter Clausen wrote:

> +	ret = gpio_request(QI_LB60_SND_GPIO, "SND");
> +	if (ret) {
> +		pr_err("qi_lb60 snd: Failed to request SND GPIO(%d): %d\n",
> +				QI_LB60_SND_GPIO, ret);
> +		goto err_device_put;
> +	}
> +
> +	ret = gpio_request(QI_LB60_AMP_GPIO, "AMP");
> +	if (ret) {
> +		pr_err("qi_lb60 snd: Failed to request AMP GPIO(%d): %d\n",
> +				QI_LB60_AMP_GPIO, ret);
> +		goto err_gpio_free_snd;
> +	}
> +
> +	gpio_direction_output(JZ_GPIO_PORTB(29), 0);
> +	gpio_direction_output(JZ_GPIO_PORTD(4), 0);

You're referring to the GPIOs by multiple different names - it'd be more
robust to pick one way of naming them and use it consistently (probably
the #define).

From troy.kisky@boundarydevices.com Thu Jun  3 20:14:29 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 20:14:36 +0200 (CEST)
Received: from smtpauth00.csee.onr.siteprotect.com ([64.26.60.144]:59686 "EHLO
        smtpauth00.csee.onr.siteprotect.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492380Ab0FCSO3 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 20:14:29 +0200
Received: from [192.168.0.251] (unknown [70.96.116.236])
        (Authenticated sender: troy.kisky@boundarydevices.com)
        by smtpauth00.csee.onr.siteprotect.com (Postfix) with ESMTPA id 742D9758099;
        Thu,  3 Jun 2010 13:14:19 -0500 (CDT)
Message-ID: <4C07F0F3.4090201@boundarydevices.com>
Date:   Thu, 03 Jun 2010 11:14:11 -0700
From:   Troy Kisky <troy.kisky@boundarydevices.com>
User-Agent: Thunderbird 2.0.0.24 (Windows/20100228)
MIME-Version: 1.0
To:     Liam Girdwood <lrg@slimlogic.co.uk>
CC:     Lars-Peter Clausen <lars@metafoo.de>, linux-mips@linux-mips.org,
        alsa-devel@alsa-project.org,
        Mark Brown <broonie@opensource.wolfsonmicro.com>,
        linux-kernel@vger.kernel.org, Ralf Baechle <ralf@linux-mips.org>
Subject: Re: [alsa-devel] [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC        support
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-5-git-send-email-lars@metafoo.de>     <1275569309.3593.106.camel@odin>  <4C07DD48.2050503@metafoo.de> <1275584609.3118.26.camel@odin>  <4C07E37A.40502@metafoo.de> <1275585900.3118.29.camel@odin>
In-Reply-To: <1275585900.3118.29.camel@odin>
X-Enigmail-Version: 0.96.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-CTCH-Spam: Unknown
X-CTCH-RefID: str=0001.0A020206.4C07F103.004F,ss=1,fgs=0
X-archive-position: 27063
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: troy.kisky@boundarydevices.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2678
Content-Length: 1673
Lines: 60

Liam Girdwood wrote:
> On Thu, 2010-06-03 at 19:16 +0200, Lars-Peter Clausen wrote:
>> Liam Girdwood wrote:
>>> On Thu, 2010-06-03 at 18:50 +0200, Lars-Peter Clausen wrote:
>>>   
>>>>>> +    config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai,
>>>>>>         
>>>> substream);
>>>>     
>>>>>> +    if (!prtd->dma) {
>>>>>> +            const char *dma_channel_name;
>>>>>> +            if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>>>>>> +                    dma_channel_name = "PCM Playback";
>>>>>> +            else
>>>>>> +                    dma_channel_name = "PCM Capture";
>>>>>> +
>>>>>> +            prtd->dma = jz4740_dma_request(substream,
>>>>>>         
>>>> dma_channel_name);
>>>>     
>>>>>>     
>>>>>>         
>>>>> dma_channel_name variable is not required here. Just use the const
>>>>>       
>>>> char
>>>>     
>>>>> * directly.
>>>>>
>>>>>   
>>>>>       
>>>> I actually had it like that before, but I think it is much more readable
>>>> in its current form.
>>>>     
>>> I disagree, having the char pointer here just adds an extra level of
>>> indirection and costs an extra two lines of code. 
>>>
>>> Liam 
>>>   
>> Hi
>>
>> Could you give an concrete example of how you would code it?
>>
> 
> Sure,
> 
> if (!prtd->dma) {
>           if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
>                    prtd->dma = jz4740_dma_request(substream, "PCM Playback");
>           else
>                    prtd->dma = jz4740_dma_request(substream, "PCM Capture");
> }
> 
> Liam
> 
or,

if (!prtd->dma)
	prtd->dma = jz4740_dma_request(substream, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
		 "PCM Playback" : "PCM Capture");


From lars@metafoo.de Thu Jun  3 21:28:34 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 21:28:39 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:56419 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491808Ab0FCT2e (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 21:28:34 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 82497FF2;
        Thu,  3 Jun 2010 21:28:28 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id NfEQdZbDlW8H; Thu,  3 Jun 2010 21:28:28 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 8680EFF1;
        Thu,  3 Jun 2010 21:28:15 +0200 (CEST)
Message-ID: <4C080230.1070909@metafoo.de>
Date:   Thu, 03 Jun 2010 21:27:44 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Mark Brown <broonie@opensource.wolfsonmicro.com>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 21/26] alsa: ASoC: Add JZ4740 ASoC support
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-5-git-send-email-lars@metafoo.de> <20100603175511.GI2762@rakim.wolfsonmicro.main>
In-Reply-To: <20100603175511.GI2762@rakim.wolfsonmicro.main>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-archive-position: 27064
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2720
Content-Length: 1776
Lines: 68

Mark Brown wrote:
> On Wed, Jun 02, 2010 at 09:12:27PM +0200, Lars-Peter Clausen wrote:
>
> Again, overall very good.
>
>   
>> +static int jz4740_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
>> +{
>> +	struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
>> +
>> +	switch (div_id) {
>> +	case JZ4740_I2S_BIT_CLK:
>> +		if (div & 1 || div > 16)
>> +			return -EINVAL;
>> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div - 1);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>>     
>
> You can probably figure out the bit clock automatically by default...
>   
Hm, yes, you are right.
>   
>> +	if (dai->active) {
>> +		conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
>> +		conf &= ~JZ_AIC_CONF_ENABLE;
>> +		jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
>> +
>> +		clk_disable(i2s->clk_i2s);
>> +	}
>> +
>> +	clk_disable(i2s->clk_aic);
>>     
>
> Might make sense to manage this clock dynamically at runtime too for a
> little extra power saving?
>   
I think I tried it once and the power savings were marginal. On the
other hand each callback would have to make sure the clock is enabled
before accessing registers and disabling it again if it was disabled.
>   
>> +	i2s->clk_aic = clk_get(&pdev->dev, "aic");
>> +	if (IS_ERR(i2s->clk_aic)) {
>> +		ret = PTR_ERR(i2s->clk_aic);
>> +		goto err_iounmap;
>> +	}
>> +
>> +	i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
>> +	if (IS_ERR(i2s->clk_i2s)) {
>> +		ret = PTR_ERR(i2s->clk_i2s);
>> +		goto err_iounmap;
>> +	}
>>     
>
> Ideally you'd free the AIC clock when unwinding (and later stop it after
> it was enabled).  Though since you don't do any error checking after
> this point it's kind of academic :)
>
>   
It should at least freed if the i2s clock is not found.

- Lars


From akpm@linux-foundation.org Thu Jun  3 22:43:34 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Thu, 03 Jun 2010 22:43:41 +0200 (CEST)
Received: from smtp1.linux-foundation.org ([140.211.169.13]:51022 "EHLO
        smtp1.linux-foundation.org" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491848Ab0FCUne (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Thu, 3 Jun 2010 22:43:34 +0200
Received: from imap1.linux-foundation.org (imap1.linux-foundation.org [140.211.169.55])
        by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id o53KhCrZ011402
        (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO);
        Thu, 3 Jun 2010 13:43:13 -0700
Received: from akpm.mtv.corp.google.com (localhost [127.0.0.1])
        by imap1.linux-foundation.org (8.13.5.20060308/8.13.5/Debian-3ubuntu1.1) with SMTP id o53KhAIV014456;
        Thu, 3 Jun 2010 13:43:10 -0700
Date:   Thu, 3 Jun 2010 13:43:10 -0700
From:   Andrew Morton <akpm@linux-foundation.org>
To:     Kevin Cernekee <cernekee@gmail.com>
Cc:     Paul Mundt <lethal@linux-sh.org>, mingo@elte.hu,
        simon.kagstrom@netinsight.net, David.Woodhouse@intel.com,
        rgetz@analog.com, linux-kernel@vger.kernel.org,
        linux-mips@linux-mips.org
Subject: Re: [PATCH v2] printk: fix delayed messages from CPU hotplug events
Message-Id: <20100603134310.b5bae74e.akpm@linux-foundation.org>
In-Reply-To: <AANLkTinY8Htz2bb2I_oN5iWtAjxuDkGzAvX_4TbtmKBh@mail.gmail.com>
References: <ede63b5a20af951c755736f035d1e787772d7c28@localhost>
        <20100601031528.GC15411@linux-sh.org>
        <AANLkTinY8Htz2bb2I_oN5iWtAjxuDkGzAvX_4TbtmKBh@mail.gmail.com>
X-Mailer: Sylpheed 2.4.8 (GTK+ 2.12.9; x86_64-pc-linux-gnu)
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
X-MIMEDefang-Filter: lf$Revision: 1.188 $
X-Scanned-By: MIMEDefang 2.63 on 140.211.169.13
X-archive-position: 27065
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: akpm@linux-foundation.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2773
Content-Length: 2974
Lines: 82

On Mon, 31 May 2010 21:04:42 -0700
Kevin Cernekee <cernekee@gmail.com> wrote:

> On Mon, May 31, 2010 at 8:15 PM, Paul Mundt <lethal@linux-sh.org> wrote:
> > If this is to be entirely restricted to CPU hotplug then you could use
> > the hotcpu notifier here instead of the open-coded cpu notifier directly,
> > the former wraps to the latter in the CPU hotplug case and is simply a
> > nop for the regular SMP case.
> 
> I ran some tests and saw the same problem during the regular MIPS SMP
> boot.  i.e. adding "while (1) { }" at the end of __cpu_up() prevents
> any of the probing/calibration messages originating on CPU1 from ever
> being echoed to the console.  Adding the semaphore code before the
> while loop caused the CPU1 messages to reappear.
> 
> Under normal circumstances you won't ever notice the problem at boot
> time, because printing "Brought up %ld CPUs" has the undocumented side
> effect of flushing out any messages that got stuck during SMP init.
> And if that printk() wasn't there, the next one (from NET, PCI, SCSI,
> ...) would surely take its place.
> 
> But in the case of MIPS CPU hotplug, there is no such printk() at the
> end, and so our luck runs out.

no....  What Paul means is "please use hotcpu_notifier".  It's a
higher-level interface which yields a smaller vmlinux if
CONFIG_HOTPLUG_CPU=n.  grep around for some examples...


other comments:
 
>  /**
> + * console_cpu_notify - print deferred console messages after CPU hotplug
> + *
> + * If printk() is called from a CPU that is not online yet, the messages
> + * will be spooled but will not show up on the console.  This function is
> + * called when a new CPU comes online and ensures that any such output
> + * gets printed.
> + */

It's conventional (although boring and usually useless) to kerneldocify
the arguments also.

> +static int __cpuinit console_cpu_notify(struct notifier_block *self,
> +	unsigned long action, void *hcpu)
> +{
> +	switch (action) {
> +	case CPU_ONLINE:
> +	case CPU_UP_CANCELED:
> +		if (try_acquire_console_sem() == 0)
> +			release_console_sem();
> +	}
> +	return NOTIFY_OK;
> +}

Would prefer to see acquire_console_sem() used here.  Because
try_acquire_console_sem() might simply fail, and the messages still get
stuck.  Possible?  If "not possible" then "needs a code comment".

> +static struct notifier_block __cpuinitdata console_nb = {
> +	.notifier_call		= console_cpu_notify,
> +};
> +
> +static int __init console_notifier_init(void)
> +{
> +	register_cpu_notifier(&console_nb);
> +	return 0;
> +}
> +late_initcall(console_notifier_init);

We don't really need two late_initcall() functions in printk.c.  We'd
save a few bytes by renaming disable_boot_consoles() to
printk_late_init() or something, then adding the hotcpu_notifier() call
there.

otoh, that's a bit of a reduction in source-level quality.

otoh2, perhaps late_initcall() was inappropriate for
console_notifier_init().  Why not do it earlier?

I'll let you decide ;)


From lars@metafoo.de Fri Jun  4 01:57:58 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 04 Jun 2010 01:58:02 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:37423 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492043Ab0FCX56 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Fri, 4 Jun 2010 01:57:58 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id 61D32773;
        Fri,  4 Jun 2010 01:57:52 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id SeUJXCzGOn5p; Fri,  4 Jun 2010 01:57:51 +0200 (CEST)
Received: from [172.31.16.228] (d078029.adsl.hansenet.de [80.171.78.29])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id F235C772;
        Fri,  4 Jun 2010 01:57:40 +0200 (CEST)
Message-ID: <4C084155.5010503@metafoo.de>
Date:   Fri, 04 Jun 2010 01:57:09 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Mark Brown <broonie@opensource.wolfsonmicro.com>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Subject: Re: [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-4-git-send-email-lars@metafoo.de> <20100603174953.GH2762@rakim.wolfsonmicro.main>
In-Reply-To: <20100603174953.GH2762@rakim.wolfsonmicro.main>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-archive-position: 27066
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2874
Content-Length: 3809
Lines: 112

Hi

Mark Brown wrote:
> On Wed, Jun 02, 2010 at 09:12:26PM +0200, Lars-Peter Clausen wrote:
>
>   
>> This patch adds support for the JZ4740 internal codec.
>>     
>
> This looks very good, there are some issues but nothing too major.  I
> may be repeating some things others have said but hopefully not too
> much.
>
>   
>>  snd-soc-wm9712-objs := wm9712.o
>>  snd-soc-wm9713-objs := wm9713.o
>>  snd-soc-wm-hubs-objs := wm_hubs.o
>> +snd-soc-jz4740-codec-objs := jz4740-codec.o
>>     
>
> Keep the devices sorted in both Makefile and Kconfig.
>
>   
>> +static int jz4740_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>> +{
>> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
>> +	case SND_SOC_DAIFMT_CBM_CFM:
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>>     
>
> This does nothing except validate some parameters.  Is there actually an
> externally visible DAI for this CODEC?  If it's just integrated into the
> SoC and there's nothing to configure then just omit the DAI
> configuration since it's not even useful to document the signal format.
>   
Nope, there is no externally visible DAI for the codec, but internally
it is connected through the i2s controller of the JZ4740 which supports
different operating modes. And if you'll do
"snd_soc_dai_set_fmt(codec_dai, BOARD_DAIFMT);
snd_soc_dai_set_fmt(cpu_dai, BOARD_DAIFMT);" with a wrong dai format it
will be noticed.
>> +	.capture = {
>> +		.stream_name = "Capture",
>> +		.channels_min = 2,
>> +		.channels_max = 2,
>> +		.rates = SNDRV_PCM_RATE_8000_48000,
>> +		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
>>     
>
> You listed an 18 bit format in hw_params - one or other of this and
> hw_params is presumably out of date.
>   
In theory the codec supports 18 bit for playback, but the i2s controller
requires it to be 32 bit aligned, while alsa appears to have only
support for a 24 bit aligned 18 bit format(Correct me if I'm wrong). So
I dropped it, I'll remove the whole format check in hw_params as Liam
suggested.
>> +static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
>> +	enum snd_soc_bias_level level)
>> +{
>> +
>> +	if (codec->bias_level == SND_SOC_BIAS_OFF && level != SND_SOC_BIAS_OFF) {
>> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
>> +		udelay(2);
>>     
>
> I'd expect to see this as part of the _OFF in the main switch
> statement.
>   
Uhm, actually this code path is taken when switching from _OFF to
another state. If it is guaranteed that _OFF is always followed by a
certain other state I could put the reset code in its part of the switch
statement.
>   
>> +	switch (level) {
>> +	case SND_SOC_BIAS_ON:
>> +		snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
>> +			JZ4740_CODEC_1_VREF_DISABLE |
>> +			JZ4740_CODEC_1_VREF_AMP_DISABLE |
>> +			JZ4740_CODEC_1_HEADPHONE_POWER_DOWN_M |
>> +			JZ4740_CODEC_1_VREF_LOW_CURRENT |
>> +			JZ4740_CODEC_1_VREF_HIGH_CURRENT,
>> +			0);
>>     
>
> This looks suspiciously like you should be using DAPM for the headphone
> at least, though if there's only headphone out that's possibly not worth
> it.  Also, are you sure that you want both low and high current VREF
> configuring here?  I'm not clear what these settings do but the way
> they're being managed both here and in _PREPARE seems odd.
>   
Hm, I'll take a look.
>   
>> +	codec = &jz4740_codec->codec;
>> +
>> +	codec->dev		= &pdev->dev;
>> +	codec->name		= "jz-codec";
>>     
>
> Seems a bit odd to use the part number in some places and not others.
>   
I renamed the driver from jz-codec to jz4740-codec shortly before
submitting it after I realized that the codec component on other jz47xx
chips is completely different. Seems like I missed the codec name.

Thanks for reviewing the patch
- Lars


From broonie@opensource.wolfsonmicro.com Fri Jun  4 01:59:47 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 04 Jun 2010 01:59:52 +0200 (CEST)
Received: from opensource.wolfsonmicro.com ([80.75.67.52]:40510 "EHLO
        opensource2.wolfsonmicro.com" rhost-flags-OK-OK-OK-FAIL)
        by eddie.linux-mips.org with ESMTP id S1492043Ab0FCX7r (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Fri, 4 Jun 2010 01:59:47 +0200
Received: from localhost (localhost [127.0.0.1])
        by opensource2.wolfsonmicro.com (Postfix) with ESMTP id EC0AF11051C;
        Fri,  4 Jun 2010 00:59:39 +0100 (BST)
X-Virus-Scanned: Debian amavisd-new at opensource.wolfsonmicro.com
Received: from opensource2.wolfsonmicro.com ([127.0.0.1])
        by localhost (opensource.wolfsonmicro.com [127.0.0.1]) (amavisd-new, port 10024)
        with ESMTP id 8V3d+9v790an; Fri,  4 Jun 2010 00:59:39 +0100 (BST)
Received: from [10.0.1.17] (cpc3-sgyl4-0-0-cust125.sgyl.cable.virginmedia.com [82.41.240.126])
        by opensource2.wolfsonmicro.com (Postfix) with ESMTPSA id 192E3110504;
        Fri,  4 Jun 2010 00:59:39 +0100 (BST)
Subject: Re: [RFC][PATCH 20/26] alsa: ASoC: Add JZ4740 codec driver
Mime-Version: 1.0 (Apple Message framework v1078)
Content-Type: text/plain; charset=us-ascii
From:   Mark Brown <broonie@opensource.wolfsonmicro.com>
In-Reply-To: <4C084155.5010503@metafoo.de> (sfid-20100604_005758_018873_5A725743)
Date:   Fri, 4 Jun 2010 00:59:38 +0100
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Liam Girdwood <lrg@slimlogic.co.uk>,
        alsa-devel@alsa-project.org
Content-Transfer-Encoding: 7bit
Message-Id: <BBE59890-DD9C-4B62-AB74-87764381D38E@opensource.wolfsonmicro.com>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-4-git-send-email-lars@metafoo.de> <20100603174953.GH2762@rakim.wolfsonmicro.main> <4C084155.5010503@metafoo.de> (sfid-20100604_005758_018873_5A725743)
To:     Lars-Peter Clausen <lars@metafoo.de>
X-Mailer: Apple Mail (2.1078)
X-archive-position: 27067
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: broonie@opensource.wolfsonmicro.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2877
Content-Length: 369
Lines: 9

On 4 Jun 2010, at 00:57, Lars-Peter Clausen wrote:

> Mark Brown wrote:
> Uhm, actually this code path is taken when switching from _OFF to
> another state. If it is guaranteed that _OFF is always followed by a
> certain other state I could put the reset code in its part of the switch
> statement.

The only possible transitions are OFF <-> STANDBY <-> PREPARE <-> ON

From ralf@linux-mips.org Fri Jun  4 02:47:58 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 04 Jun 2010 02:48:02 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:48588 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492643Ab0FDAr6 (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Fri, 4 Jun 2010 02:47:58 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o540lkk8005659;
        Fri, 4 Jun 2010 01:47:49 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o540lfu0005657;
        Fri, 4 Jun 2010 01:47:41 +0100
Date:   Fri, 4 Jun 2010 01:47:41 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Lars-Peter Clausen <lars@metafoo.de>
Cc:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org
Subject: Re: [RFC][PATCH 14/26] MIPS: JZ4740: Add Kbuild files
Message-ID: <20100604004741.GA4021@linux-mips.org>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
 <1275505832-17185-6-git-send-email-lars@metafoo.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <1275505832-17185-6-git-send-email-lars@metafoo.de>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27068
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 2896
Content-Length: 351
Lines: 10

On Wed, Jun 02, 2010 at 09:10:30PM +0200, Lars-Peter Clausen wrote:

> This patch adds the Kbuild files for the JZ4740 architecture and adds JZ4740
> support to the MIPS Kbuild files.

Checkout the changes to the way MIPS platform Makefiles are implemented in
the linux-queue tree.  This new structure will be mandatory for all new
platforms.

  Ralf

From cernekee@gmail.com Fri Jun  4 07:15:54 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 04 Jun 2010 07:15:58 +0200 (CEST)
Received: from [69.28.251.93] ([69.28.251.93]:41917 "EHLO b32.net"
        rhost-flags-FAIL-FAIL-OK-FAIL) by eddie.linux-mips.org with ESMTP
        id S1491003Ab0FDFPy (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Fri, 4 Jun 2010 07:15:54 +0200
Received: (qmail 17601 invoked from network); 4 Jun 2010 05:15:41 -0000
Received: from unknown (HELO vps-1001064-677.cp.jvds.com) (127.0.0.1)
  by 127.0.0.1 with (DHE-RSA-AES128-SHA encrypted) SMTP; 4 Jun 2010 05:15:41 -0000
Received: by vps-1001064-677.cp.jvds.com (sSMTP sendmail emulation); Thu, 03 Jun 2010 22:15:41 -0700
From:   Kevin Cernekee <cernekee@gmail.com>
To:     <mingo@elte.hu>, <akpm@linux-foundation.org>,
        <simon.kagstrom@netinsight.net>, <David.Woodhouse@intel.com>,
        <lethal@linux-sh.org>
Cc:     <linux-kernel@vger.kernel.org>, <linux-mips@linux-mips.org>
Date:   Thu, 3 Jun 2010 22:11:25 -0700
Subject: [PATCH v3] printk: fix delayed messages from CPU hotplug events
Message-Id: <ee1bf4f9c158983acad0a4548229586128afad67@localhost>
User-Agent: vim 7.2
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
X-archive-position: 27069
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: cernekee@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3018
Content-Length: 3098
Lines: 108

[Changes from v2:

Use hotcpu_notifier - fix will only apply to hotplug events, not
initial SMP boot

Kerneldocify function arguments

Use acquire_console_sem() instead of try_acquire_console_sem()

Reuse the existing disable_boot_consoles() initcall instead of making a
new one]

When a secondary CPU is being brought up, it is not uncommon for
printk() to be invoked when cpu_online(smp_processor_id()) == 0.  The
case that I witnessed personally was on MIPS:

http://lkml.org/lkml/2010/5/30/4

If (can_use_console() == 0), printk() will spool its output to log_buf
and it will be visible in "dmesg", but that output will NOT be echoed to
the console until somebody calls release_console_sem() from a CPU that
is online.  Therefore, the boot time messages from the new CPU can get
stuck in "limbo" for a long time, and might suddenly appear on the
screen when a completely unrelated event (e.g. "eth0: link is down")
occurs.

This patch modifies the console code so that any pending messages are
automatically flushed out to the console whenever a CPU hotplug
operation completes successfully or aborts.

The issue was seen on 2.6.34.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 kernel/printk.c |   34 ++++++++++++++++++++++++++++++++--
 1 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index 444b770..1748519 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -37,6 +37,8 @@
 #include <linux/ratelimit.h>
 #include <linux/kmsg_dump.h>
 #include <linux/syslog.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 
@@ -985,6 +987,33 @@ void resume_console(void)
 }
 
 /**
+ * console_cpu_notify - print deferred console messages after CPU hotplug
+ * @self: notifier struct
+ * @action: CPU hotplug event
+ * @hcpu: unused
+ *
+ * If printk() is called from a CPU that is not online yet, the messages
+ * will be spooled but will not show up on the console.  This function is
+ * called when a new CPU comes online (or fails to come up), and ensures
+ * that any such output gets printed.
+ */
+static int __cpuinit console_cpu_notify(struct notifier_block *self,
+	unsigned long action, void *hcpu)
+{
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_UP_CANCELED:
+		acquire_console_sem();
+		release_console_sem();
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata console_nb = {
+	.notifier_call		= console_cpu_notify,
+};
+
+/**
  * acquire_console_sem - lock the console system for exclusive use.
  *
  * Acquires a semaphore which guarantees that the caller has
@@ -1371,7 +1400,7 @@ int unregister_console(struct console *console)
 }
 EXPORT_SYMBOL(unregister_console);
 
-static int __init disable_boot_consoles(void)
+static int __init printk_late_init(void)
 {
 	struct console *con;
 
@@ -1382,9 +1411,10 @@ static int __init disable_boot_consoles(void)
 			unregister_console(con);
 		}
 	}
+	register_hotcpu_notifier(&console_nb);
 	return 0;
 }
-late_initcall(disable_boot_consoles);
+late_initcall(printk_late_init);
 
 #if defined CONFIG_PRINTK
 
-- 
1.7.0.4


From lethal@linux-sh.org Fri Jun  4 07:20:50 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 04 Jun 2010 07:20:54 +0200 (CEST)
Received: from 124x34x33x190.ap124.ftth.ucom.ne.jp ([124.34.33.190]:48060 "EHLO
        master.linux-sh.org" rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org
        with ESMTP id S1491164Ab0FDFUu (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Fri, 4 Jun 2010 07:20:50 +0200
Received: from localhost (unknown [127.0.0.1])
        by master.linux-sh.org (Postfix) with ESMTP id D1787636B0;
        Fri,  4 Jun 2010 05:20:18 +0000 (UTC)
X-Virus-Scanned: amavisd-new at linux-sh.org
Received: from master.linux-sh.org ([127.0.0.1])
        by localhost (master.linux-sh.org [127.0.0.1]) (amavisd-new, port 10024)
        with ESMTP id BtTlq9lPLxmX; Fri,  4 Jun 2010 14:20:18 +0900 (JST)
Received: by master.linux-sh.org (Postfix, from userid 500)
        id 33187636B3; Fri,  4 Jun 2010 14:20:18 +0900 (JST)
Date:   Fri, 4 Jun 2010 14:20:18 +0900
From:   Paul Mundt <lethal@linux-sh.org>
To:     Kevin Cernekee <cernekee@gmail.com>
Cc:     mingo@elte.hu, akpm@linux-foundation.org,
        simon.kagstrom@netinsight.net, David.Woodhouse@intel.com,
        linux-kernel@vger.kernel.org, linux-mips@linux-mips.org
Subject: Re: [PATCH v3] printk: fix delayed messages from CPU hotplug events
Message-ID: <20100604052018.GA2565@linux-sh.org>
References: <ee1bf4f9c158983acad0a4548229586128afad67@localhost>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <ee1bf4f9c158983acad0a4548229586128afad67@localhost>
User-Agent: Mutt/1.5.13 (2006-08-11)
X-archive-position: 27070
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lethal@linux-sh.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3022
Content-Length: 269
Lines: 9

On Thu, Jun 03, 2010 at 10:11:25PM -0700, Kevin Cernekee wrote:
> [Changes from v2:
> 
> Use hotcpu_notifier - fix will only apply to hotplug events, not
> initial SMP boot
> 
With the hotcpu notifier it looks good to me.

Reviewed-by: Paul Mundt <lethal@linux-sh.org>

From akpm@linux-foundation.org Fri Jun  4 07:59:10 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Fri, 04 Jun 2010 07:59:18 +0200 (CEST)
Received: from smtp1.linux-foundation.org ([140.211.169.13]:52040 "EHLO
        smtp1.linux-foundation.org" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491164Ab0FDF7K (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Fri, 4 Jun 2010 07:59:10 +0200
Received: from imap1.linux-foundation.org (imap1.linux-foundation.org [140.211.169.55])
        by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id o545wMDV003252
        (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO);
        Thu, 3 Jun 2010 22:58:23 -0700
Received: from localhost (localhost [127.0.0.1])
        by imap1.linux-foundation.org (8.13.5.20060308/8.13.5/Debian-3ubuntu1.1) with SMTP id o545wKTn009948;
        Thu, 3 Jun 2010 22:58:21 -0700
Date:   Thu, 3 Jun 2010 22:58:24 -0700
From:   Andrew Morton <akpm@linux-foundation.org>
To:     Kevin Cernekee <cernekee@gmail.com>
Cc:     <mingo@elte.hu>, <simon.kagstrom@netinsight.net>,
        <David.Woodhouse@intel.com>, <lethal@linux-sh.org>,
        <linux-kernel@vger.kernel.org>, <linux-mips@linux-mips.org>
Subject: Re: [PATCH v3] printk: fix delayed messages from CPU hotplug events
Message-Id: <20100603225824.8de77fba.akpm@linux-foundation.org>
In-Reply-To: <ee1bf4f9c158983acad0a4548229586128afad67@localhost>
References: <ee1bf4f9c158983acad0a4548229586128afad67@localhost>
X-Mailer: Sylpheed 2.7.1 (GTK+ 2.18.9; x86_64-redhat-linux-gnu)
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
X-MIMEDefang-Filter: lf$Revision: 1.188 $
X-Scanned-By: MIMEDefang 2.63 on 140.211.169.13
X-archive-position: 27071
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: akpm@linux-foundation.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3043
Content-Length: 3051
Lines: 103

On Thu, 3 Jun 2010 22:11:25 -0700 Kevin Cernekee <cernekee@gmail.com> wrote:

> [Changes from v2:
> 
> Use hotcpu_notifier - fix will only apply to hotplug events, not
> initial SMP boot
> 
> Kerneldocify function arguments
> 
> Use acquire_console_sem() instead of try_acquire_console_sem()
> 
> Reuse the existing disable_boot_consoles() initcall instead of making a
> new one]
> 
> When a secondary CPU is being brought up, it is not uncommon for
> printk() to be invoked when cpu_online(smp_processor_id()) == 0.  The
> case that I witnessed personally was on MIPS:
> 
> http://lkml.org/lkml/2010/5/30/4
> 
> If (can_use_console() == 0), printk() will spool its output to log_buf
> and it will be visible in "dmesg", but that output will NOT be echoed to
> the console until somebody calls release_console_sem() from a CPU that
> is online.  Therefore, the boot time messages from the new CPU can get
> stuck in "limbo" for a long time, and might suddenly appear on the
> screen when a completely unrelated event (e.g. "eth0: link is down")
> occurs.
> 
> This patch modifies the console code so that any pending messages are
> automatically flushed out to the console whenever a CPU hotplug
> operation completes successfully or aborts.
> 
> The issue was seen on 2.6.34.
> 
> ...
>
> +static int __cpuinit console_cpu_notify(struct notifier_block *self,
> +	unsigned long action, void *hcpu)
> +{
> +	switch (action) {
> +	case CPU_ONLINE:
> +	case CPU_UP_CANCELED:
> +		acquire_console_sem();
> +		release_console_sem();
> +	}
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block __cpuinitdata console_nb = {
> +	.notifier_call		= console_cpu_notify,
> +};
> +
> +/**
>   * acquire_console_sem - lock the console system for exclusive use.
>   *
>   * Acquires a semaphore which guarantees that the caller has
> @@ -1371,7 +1400,7 @@ int unregister_console(struct console *console)
>  }
>  EXPORT_SYMBOL(unregister_console);
>  
> -static int __init disable_boot_consoles(void)
> +static int __init printk_late_init(void)
>  {
>  	struct console *con;
>  
> @@ -1382,9 +1411,10 @@ static int __init disable_boot_consoles(void)
>  			unregister_console(con);
>  		}
>  	}
> +	register_hotcpu_notifier(&console_nb);

gack, we seem to have made these interfaces as hard to use and as documentation-free
as we possibly could :(

This:

--- a/kernel/printk.c~printk-fix-delayed-messages-from-cpu-hotplug-events-fix
+++ a/kernel/printk.c
@@ -1009,10 +1009,6 @@ static int __cpuinit console_cpu_notify(
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata console_nb = {
-	.notifier_call		= console_cpu_notify,
-};
-
 /**
  * acquire_console_sem - lock the console system for exclusive use.
  *
@@ -1411,7 +1407,7 @@ static int __init printk_late_init(void)
 			unregister_console(con);
 		}
 	}
-	register_hotcpu_notifier(&console_nb);
+	hotcpu_notifier(console_cpu_notify, 0);
 	return 0;
 }
 late_initcall(printk_late_init);


There are numerous other register_hotcpu_notifier() callsites which can
probably be converted.


From dengcheng.zhu@gmail.com Sat Jun  5 00:22:44 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 00:22:47 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:42193 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492570Ab0FDWWo (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sat, 5 Jun 2010 00:22:44 +0200
Received: by pvg11 with SMTP id 11so298134pvg.36
        for <linux-mips@linux-mips.org>; Fri, 04 Jun 2010 15:22:35 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:date:message-id
         :subject:from:to:cc:content-type;
        bh=BtmlN0yNE3VgWRrldYqZ88uRBtvH+Svqwi6xthZW+t4=;
        b=cwiFCTzYia5D34sSJBYRKEmRpeiCIJWTOQPm/fhKQ1+P/PvdAgjzyhoOf+Rz0fqa0V
         K49Lmc1dvaYfTGcLkyWrn4Xv1fTzIqvuJDkevbXsabXhEhofRakISpSDn9umLLRb5/5S
         c9XubxlFgnWfN228GLhbCfj/CtlI2aN1gagZk=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:date:message-id:subject:from:to:cc:content-type;
        b=BwFwTlVLE6lN/3GyxEaIkSS/6WO9gLkTNeVFZ+jYyf5w3xFpJmrXraSTXHXpymRYy0
         DIrzzSCSBrCzMpxUvxNnjI2g3tPL8h2k1F38oulUvrfV93NL7IOQsHFm8cD5A+w3lAJy
         aPs7TdevPRc0XazQf77+KdHXXyXXX5H6KzzCs=
MIME-Version: 1.0
Received: by 10.114.253.9 with SMTP id a9mr9094402wai.72.1275690155307; Fri, 
        04 Jun 2010 15:22:35 -0700 (PDT)
Received: by 10.115.32.17 with HTTP; Fri, 4 Jun 2010 15:22:35 -0700 (PDT)
Date:   Sat, 5 Jun 2010 06:22:35 +0800
Message-ID: <AANLkTikRaw_OLR7LenUA8acaedJy2V6HZKJ0cAd6PNRk@mail.gmail.com>
Subject: [Q] MIPS: How to record the user stack backtrace in the kernel
From:   Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
To:     linux-mips@linux-mips.org
Cc:     dengcheng.zhu@gmail.com
Content-Type: text/plain; charset=ISO-8859-1
X-archive-position: 27072
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: dengcheng.zhu@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                
X-UID: 3579
Content-Length: 323
Lines: 12

Hi, developers


In the kernel, we don't have frame unwinder to work on the user stack.
Given the different possible compiler flags, getting the backtrace for the
user stack is especially challenging. Certainly, I don't want symbols -
only to get a list of return addresses. Do you have any comments?


Thanks!

Deng-Cheng

From raydudu@gmail.com Sat Jun  5 03:22:47 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 03:22:51 +0200 (CEST)
Received: from mail-iw0-f177.google.com ([209.85.214.177]:51886 "EHLO
        mail-iw0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492103Ab0FEBWr (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sat, 5 Jun 2010 03:22:47 +0200
Received: by iwn34 with SMTP id 34so1880683iwn.36
        for <linux-mips@linux-mips.org>; Fri, 04 Jun 2010 18:22:44 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:message-id:date:from
         :user-agent:mime-version:to:cc:subject:references:in-reply-to
         :content-type:content-transfer-encoding;
        bh=Dph68Bzw3915xsYgLkppNZJhN5uU9pmxAbTe7dMJobQ=;
        b=sdO6/JgAaHQt2YidfvG7y+NlsPSQXN+YBuEgCJLNP61NQiT4A+S4ixysnGKLzHvVHJ
         7aBmZ3bkftz37f684fv5Gb2g+tYopl+i82cGdIJ5kS65jG3vEQOQgv/fxSL+tnWoDTr0
         EZ+tEr2+rW3iIu+EOJs7jvTeWQfuYncG+bkkM=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=message-id:date:from:user-agent:mime-version:to:cc:subject
         :references:in-reply-to:content-type:content-transfer-encoding;
        b=pzQgC7f+7yeCTqICTksUBC8cKYauKq2NCzswO0KLVHzVRAPmhXU1+aRmH9LbxVJdQQ
         pzM2yCOZTd6lOmKtH+75/EC+WvGTSj5elcGCsP5kt+clIZYTj+qhouCytHflH3gZlFo/
         yVmxnlymNYfY/Rr4Y1tlVds3e+jRg2VdCmY+Q=
Received: by 10.231.213.27 with SMTP id gu27mr1617614ibb.168.1275700963890;
        Fri, 04 Jun 2010 18:22:43 -0700 (PDT)
Received: from [192.168.50.141] ([12.169.7.247])
        by mx.google.com with ESMTPS id b3sm7911086ibf.1.2010.06.04.18.22.41
        (version=SSLv3 cipher=RC4-MD5);
        Fri, 04 Jun 2010 18:22:42 -0700 (PDT)
Message-ID: <4C09A6DE.7010303@gmail.com>
Date:   Fri, 04 Jun 2010 20:22:38 -0500
From:   Ray Dudu <raydudu@gmail.com>
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100429 Lightning/1.0b2pre Thunderbird/3.0.4
MIME-Version: 1.0
To:     Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
CC:     linux-mips@linux-mips.org
Subject: Re: [Q] MIPS: How to record the user stack backtrace in the kernel
References: <AANLkTikRaw_OLR7LenUA8acaedJy2V6HZKJ0cAd6PNRk@mail.gmail.com>
In-Reply-To: <AANLkTikRaw_OLR7LenUA8acaedJy2V6HZKJ0cAd6PNRk@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-archive-position: 27073
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: raydudu@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3634
Content-Length: 491
Lines: 23

Hi,

I'm looking for the same thing, please comment it.

04.06.10 17:22, Deng-Cheng Zhu Ð½Ð°Ð¿Ð¸ÑÐ°Ð²(Ð»Ð°):
> Hi, developers
> 
> 
> In the kernel, we don't have frame unwinder to work on the user stack.
> Given the different possible compiler flags, getting the backtrace for the
> user stack is especially challenging. Certainly, I don't want symbols -
> only to get a list of return addresses. Do you have any comments?
> 
> 
> Thanks!
> 
> Deng-Cheng
> 

-- 
Best regards,
RD18-UANIC


From mcuos.com@gmail.com Sat Jun  5 17:48:15 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 17:48:20 +0200 (CEST)
Received: from mail-vw0-f49.google.com ([209.85.212.49]:56024 "EHLO
        mail-vw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492132Ab0FEPsP convert rfc822-to-8bit
        (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Sat, 5 Jun 2010 17:48:15 +0200
Received: by vws7 with SMTP id 7so2948523vws.36
        for <multiple recipients>; Sat, 05 Jun 2010 08:48:07 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:in-reply-to
         :references:date:message-id:subject:from:to:cc:content-type
         :content-transfer-encoding;
        bh=bApWyvqFJ8+ZtyCdqXJvXnEYcne55Q8vwYsI83iF2BI=;
        b=T7gea2/Bd1RVPKcpzR4RUzmn4UvfSvypd4f1S3TXMrWCqu3iFuqFTV4Re7MTP7jFaQ
         r+zZtXgRcFtUGwfbLkYerUfeWZGm4R85Gt9XSCF7U8aLAmZd5LRtRqrB8cM/Dp7B4q0o
         aVddG1IdkN1EhyWYM6DLfu6CcS4+ixRM1WV64=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :cc:content-type:content-transfer-encoding;
        b=eWPoT1Hg6tgppZJa2yl6/vGD2VnaoJvNrpPipmykYSa7WvaST4N3HfG8PFyW4qAJbz
         3GkrJD0C4U7u9jYD154MFQD1jGAOZ8ueD5hHNFXv0tFCFBDd2EiPPeVdpyBz5lvKpgFr
         AJfe6f1fi0o7GulJg0qjEzQnJZFuGLCu9N8Fk=
MIME-Version: 1.0
Received: by 10.224.106.130 with SMTP id x2mr6925068qao.245.1275752887170; 
        Sat, 05 Jun 2010 08:48:07 -0700 (PDT)
Received: by 10.220.200.141 with HTTP; Sat, 5 Jun 2010 08:48:07 -0700 (PDT)
In-Reply-To: <1275505832-17185-7-git-send-email-lars@metafoo.de>
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>
        <1275505832-17185-7-git-send-email-lars@metafoo.de>
Date:   Sat, 5 Jun 2010 23:48:07 +0800
Message-ID: <AANLkTilyeoul7MEs0Q-tlHLdVHBQg6QIuucvy2UH2nkF@mail.gmail.com>
Subject: Re: [rtc-linux] [RFC][PATCH 15/26] RTC: Add JZ4740 RTC driver
From:   Wan ZongShun <mcuos.com@gmail.com>
To:     rtc-linux@googlegroups.com
Cc:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, Lars-Peter Clausen <lars@metafoo.de>,
        Alessandro Zummo <a.zummo@towertech.it>,
        Paul Gortmaker <p_gortmaker@yahoo.com>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8BIT
X-archive-position: 27074
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: mcuos.com@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3875
Content-Length: 14333
Lines: 425

2010/6/3 Lars-Peter Clausen <lars@metafoo.de>:
> This patch adds support for the RTC unit on JZ4740 SoCs.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Alessandro Zummo <a.zummo@towertech.it>
> Cc: Paul Gortmaker <p_gortmaker@yahoo.com>
> Cc: rtc-linux@googlegroups.com
> ---
> Â drivers/rtc/Kconfig Â  Â  Â | Â  11 ++
> Â drivers/rtc/Makefile Â  Â  | Â  Â 1 +
> Â drivers/rtc/rtc-jz4740.c | Â 344 ++++++++++++++++++++++++++++++++++++++++++++++
> Â 3 files changed, 356 insertions(+), 0 deletions(-)
> Â create mode 100644 drivers/rtc/rtc-jz4740.c
>
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 10ba12c..d0ed7e6 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -905,4 +905,15 @@ config RTC_DRV_MPC5121
> Â  Â  Â  Â  Â This driver can also be built as a module. If so, the module
> Â  Â  Â  Â  Â will be called rtc-mpc5121.
>
> +config RTC_DRV_JZ4740
> + Â  Â  Â  tristate "Ingenic JZ4740 SoC"
> + Â  Â  Â  depends on RTC_CLASS
> + Â  Â  Â  depends on MACH_JZ4740
> + Â  Â  Â  help
> + Â  Â  Â  Â  If you say yes here you get support for the Ingenic JZ4740 SoC RTC
> + Â  Â  Â  Â  controller.
> +
> + Â  Â  Â  Â  This driver can also be buillt as a module. If so, the module
> + Â  Â  Â  Â  will be called rtc-jz4740.
> +
> Â endif # RTC_CLASS
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 5adbba7..fedf9bb 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) Â += rtc-ep93xx.o
> Â obj-$(CONFIG_RTC_DRV_FM3130) Â  += rtc-fm3130.o
> Â obj-$(CONFIG_RTC_DRV_GENERIC) Â += rtc-generic.o
> Â obj-$(CONFIG_RTC_DRV_ISL1208) Â += rtc-isl1208.o
> +obj-$(CONFIG_RTC_DRV_JZ4740) Â  += rtc-jz4740.o
> Â obj-$(CONFIG_RTC_DRV_M41T80) Â  += rtc-m41t80.o
> Â obj-$(CONFIG_RTC_DRV_M41T94) Â  += rtc-m41t94.o
> Â obj-$(CONFIG_RTC_DRV_M48T35) Â  += rtc-m48t35.o
> diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
> new file mode 100644
> index 0000000..41ab78f
> --- /dev/null
> +++ b/drivers/rtc/rtc-jz4740.c
> @@ -0,0 +1,344 @@
> +/*
> + * Â Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + * Â  Â  Â  Â  Â  Â  JZ4740 SoC RTC driver
> + *
> + * Â This program is free software; you can redistribute Â  Â  Â  Â  it and/or modify it
> + * Â under Â the terms of Â  Â  Â  Â  the GNU General Â Public License as published by the
> + * Â Free Software Foundation; Â either version 2 of the License, or (at your
> + * Â option) any later version.
> + *
> + * Â You should have received a copy of the Â GNU General Public License along
> + * Â with this program; if not, write Â to the Free Software Foundation, Inc.,
> + * Â 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/rtc.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +#define JZ_REG_RTC_CTRL Â  Â  Â  Â  Â  Â  Â  Â 0x00
> +#define JZ_REG_RTC_SEC Â  Â  Â  Â  0x04
> +#define JZ_REG_RTC_SEC_ALARM Â  0x08
> +#define JZ_REG_RTC_REGULATOR Â  0x0C
> +#define JZ_REG_RTC_HIBERNATE Â  0x20
> +#define JZ_REG_RTC_SCRATCHPAD Â 0x34
> +
> +#define JZ_RTC_CTRL_WRDY Â  Â  Â  BIT(7)
> +#define JZ_RTC_CTRL_1HZ Â  Â  Â  Â  Â  Â  Â  Â BIT(6)
> +#define JZ_RTC_CTRL_1HZ_IRQ Â  Â BIT(5)
> +#define JZ_RTC_CTRL_AF Â  Â  Â  Â  BIT(4)
> +#define JZ_RTC_CTRL_AF_IRQ Â  Â  BIT(3)
> +#define JZ_RTC_CTRL_AE Â  Â  Â  Â  BIT(2)
> +#define JZ_RTC_CTRL_ENABLE Â  Â  BIT(0)
> +
> +struct jz4740_rtc {
> + Â  Â  Â  struct resource *mem;
> + Â  Â  Â  void __iomem *base;
> +
> + Â  Â  Â  struct rtc_device *rtc;
> +
> + Â  Â  Â  unsigned int irq;
> +
> + Â  Â  Â  spinlock_t lock;
> +};
> +
> +static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
> +{
> + Â  Â  Â  return readl(rtc->base + reg);
> +}
> +
> +static inline void jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
> +{
> + Â  Â  Â  uint32_t ctrl;
> + Â  Â  Â  do {
> + Â  Â  Â  Â  Â  Â  Â  ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
> + Â  Â  Â  } while (!(ctrl & JZ_RTC_CTRL_WRDY));
> +}
> +
> +
> +static inline void jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  uint32_t val)
> +{
> + Â  Â  Â  jz4740_rtc_wait_write_ready(rtc);
> + Â  Â  Â  writel(val, rtc->base + reg);
> +}
> +
> +static void jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  uint32_t val)
> +{
> + Â  Â  Â  unsigned long flags;
> + Â  Â  Â  uint32_t ctrl;
> +
> + Â  Â  Â  spin_lock_irqsave(&rtc->lock, flags);
> +
> + Â  Â  Â  ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
> +
> + Â  Â  Â  /* Don't clear interrupt flags by accident */
> + Â  Â  Â  ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF;
> +
> + Â  Â  Â  ctrl &= ~mask;
> + Â  Â  Â  ctrl |= val;
> +
> + Â  Â  Â  jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl);
> +
> + Â  Â  Â  spin_unlock_irqrestore(&rtc->lock, flags);
> +}
> +
> +static inline struct jz4740_rtc *dev_to_rtc(struct device *dev)
> +{
> + Â  Â  Â  return dev_get_drvdata(dev);
> +}
> +

Why do you need to re-implement the 'dev_to_rtc' instead of using
'platform_get_drvdata' provided by Linux own.'

> +static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_to_rtc(dev);
> + Â  Â  Â  uint32_t secs, secs2;
> +
> + Â  Â  Â  secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
> + Â  Â  Â  secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
> +
> + Â  Â  Â  while (secs != secs2) {
> + Â  Â  Â  Â  Â  Â  Â  secs = secs2;
> + Â  Â  Â  Â  Â  Â  Â  secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
> + Â  Â  Â  }
> +
> + Â  Â  Â  rtc_time_to_tm(secs, time);
> +
> + Â  Â  Â  return rtc_valid_tm(time);
> +}
> +
> +static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_to_rtc(dev);
> +
> + Â  Â  Â  if ((uint32_t)secs != secs)
> + Â  Â  Â  Â  Â  Â  Â  return -EINVAL;
> +
> + Â  Â  Â  jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs);
> +
> + Â  Â  Â  return 0;
> +}
> +
> +static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_to_rtc(dev);
> + Â  Â  Â  uint32_t secs, secs2;
> + Â  Â  Â  uint32_t ctrl;
> +
> + Â  Â  Â  secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
> + Â  Â  Â  secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
> +
> + Â  Â  Â  while (secs != secs2) {
> + Â  Â  Â  Â  Â  Â  Â  secs = secs2;
> + Â  Â  Â  Â  Â  Â  Â  secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
> + Â  Â  Â  }
> +
> + Â  Â  Â  ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
> +
> + Â  Â  Â  alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE);
> + Â  Â  Â  alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF);
> +
> + Â  Â  Â  rtc_time_to_tm(secs, &alrm->time);
> +
> + Â  Â  Â  return rtc_valid_tm(&alrm->time);
> +}
> +
> +static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_to_rtc(dev);
> + Â  Â  Â  unsigned long secs;
> +
> + Â  Â  Â  rtc_tm_to_time(&alrm->time, &secs);
> +
> + Â  Â  Â  if ((uint32_t)secs != secs)
> + Â  Â  Â  Â  Â  Â  Â  return -EINVAL;
> +
> + Â  Â  Â  jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, (uint32_t)secs);
> + Â  Â  Â  jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  alrm->enabled ? JZ_RTC_CTRL_AE : 0);
> +
> + Â  Â  Â  return 0;
> +}
> +
> +static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_to_rtc(dev);
> + Â  Â  Â  jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  enable ? JZ_RTC_CTRL_1HZ_IRQ : 0);
> + Â  Â  Â  return 0;
> +}
> +
> +
> +static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_to_rtc(dev);
> + Â  Â  Â  jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  enable ? JZ_RTC_CTRL_AF_IRQ : 0);
> + Â  Â  Â  return 0;
> +}
> +
> +static struct rtc_class_ops jz4740_rtc_ops = {
> + Â  Â  Â  .read_time Â  Â  Â = jz4740_rtc_read_time,
> + Â  Â  Â  .set_mmss Â  Â  Â  = jz4740_rtc_set_mmss,
> + Â  Â  Â  .read_alarm Â  Â  = jz4740_rtc_read_alarm,
> + Â  Â  Â  .set_alarm Â  Â  Â = jz4740_rtc_set_alarm,
> + Â  Â  Â  .update_irq_enable = jz4740_rtc_update_irq_enable,
> + Â  Â  Â  .alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
> +};
> +
> +static irqreturn_t jz4740_rtc_irq(int irq, void *data)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = data;
> + Â  Â  Â  uint32_t ctrl;
> + Â  Â  Â  unsigned long events = 0;
> + Â  Â  Â  ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
> +
> + Â  Â  Â  if (ctrl & JZ_RTC_CTRL_1HZ)
> + Â  Â  Â  Â  Â  Â  Â  events |= (RTC_UF | RTC_IRQF);
> +
> + Â  Â  Â  if (ctrl & JZ_RTC_CTRL_AF)
> + Â  Â  Â  Â  Â  Â  Â  events |= (RTC_AF | RTC_IRQF);
> +
> + Â  Â  Â  rtc_update_irq(rtc->rtc, 1, events);
> +
> + Â  Â  Â  jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, 0);
> +
> + Â  Â  Â  return IRQ_HANDLED;
> +}
> +
> +void jz4740_rtc_poweroff(struct device *dev)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = dev_get_drvdata(dev);
> + Â  Â  Â  jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1);
> +}
> +EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff);
> +
> +static int __devinit jz4740_rtc_probe(struct platform_device *pdev)
> +{
> + Â  Â  Â  int ret;
> + Â  Â  Â  struct jz4740_rtc *rtc;
> + Â  Â  Â  uint32_t scratchpad;
> +
> + Â  Â  Â  rtc = kmalloc(sizeof(*rtc), GFP_KERNEL);
> +
> + Â  Â  Â  rtc->irq = platform_get_irq(pdev, 0);
> +
> + Â  Â  Â  if (rtc->irq < 0) {
> + Â  Â  Â  Â  Â  Â  Â  ret = -ENOENT;
> + Â  Â  Â  Â  Â  Â  Â  dev_err(&pdev->dev, "Failed to get platform irq\n");
> + Â  Â  Â  Â  Â  Â  Â  goto err_free;
> + Â  Â  Â  }
> +
> + Â  Â  Â  rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + Â  Â  Â  if (!rtc->mem) {
> + Â  Â  Â  Â  Â  Â  Â  ret = -ENOENT;
> + Â  Â  Â  Â  Â  Â  Â  dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
> + Â  Â  Â  Â  Â  Â  Â  goto err_free;
> + Â  Â  Â  }
> +
> + Â  Â  Â  rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem),
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  pdev->name);
> +
> + Â  Â  Â  if (!rtc->mem) {
> + Â  Â  Â  Â  Â  Â  Â  ret = -EBUSY;
> + Â  Â  Â  Â  Â  Â  Â  dev_err(&pdev->dev, "Failed to request mmio memory region\n");
> + Â  Â  Â  Â  Â  Â  Â  goto err_free;
> + Â  Â  Â  }
> +
> + Â  Â  Â  rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem));
> +
> + Â  Â  Â  if (!rtc->base) {
> + Â  Â  Â  Â  Â  Â  Â  ret = -EBUSY;
> + Â  Â  Â  Â  Â  Â  Â  dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
> + Â  Â  Â  Â  Â  Â  Â  goto err_release_mem_region;
> + Â  Â  Â  }
> +
> + Â  Â  Â  spin_lock_init(&rtc->lock);
> +
> + Â  Â  Â  platform_set_drvdata(pdev, rtc);
> +
> + Â  Â  Â  rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  THIS_MODULE);
> +
> + Â  Â  Â  if (IS_ERR(rtc->rtc)) {
> + Â  Â  Â  Â  Â  Â  Â  ret = PTR_ERR(rtc->rtc);
> + Â  Â  Â  Â  Â  Â  Â  dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
> + Â  Â  Â  Â  Â  Â  Â  goto err_iounmap;
> + Â  Â  Â  }
> +
> + Â  Â  Â  ret = request_irq(rtc->irq, jz4740_rtc_irq, 0,
> + Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  pdev->name, rtc);
> +
> + Â  Â  Â  if (ret) {
> + Â  Â  Â  Â  Â  Â  Â  dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
> + Â  Â  Â  Â  Â  Â  Â  goto err_unregister_rtc;
> + Â  Â  Â  }
> +
> + Â  Â  Â  scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
> + Â  Â  Â  if (scratchpad != 0x12345678) {
> + Â  Â  Â  Â  Â  Â  Â  jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
> + Â  Â  Â  Â  Â  Â  Â  jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
> + Â  Â  Â  }
> +
> + Â  Â  Â  return 0;
> +
> +err_unregister_rtc:
> + Â  Â  Â  rtc_device_unregister(rtc->rtc);
> +err_iounmap:
> + Â  Â  Â  platform_set_drvdata(pdev, NULL);
> + Â  Â  Â  iounmap(rtc->base);
> +err_release_mem_region:
> + Â  Â  Â  release_mem_region(rtc->mem->start, resource_size(rtc->mem));
> +err_free:
> + Â  Â  Â  kfree(rtc);
> +
> + Â  Â  Â  return ret;
> +}
> +
> +static int __devexit jz4740_rtc_remove(struct platform_device *pdev)
> +{
> + Â  Â  Â  struct jz4740_rtc *rtc = platform_get_drvdata(pdev);
> +
> + Â  Â  Â  free_irq(rtc->irq, rtc);
> +
> + Â  Â  Â  rtc_device_unregister(rtc->rtc);
> +
> + Â  Â  Â  iounmap(rtc->base);
> + Â  Â  Â  release_mem_region(rtc->mem->start, resource_size(rtc->mem));
> +
> + Â  Â  Â  kfree(rtc);
> +
> + Â  Â  Â  platform_set_drvdata(pdev, NULL);
> +
> + Â  Â  Â  return 0;
> +}
> +
> +struct platform_driver jz4740_rtc_driver = {
> + Â  Â  Â  .probe = jz4740_rtc_probe,
> + Â  Â  Â  .remove = __devexit_p(jz4740_rtc_remove),
> + Â  Â  Â  .driver = {
> + Â  Â  Â  Â  Â  Â  Â  .name = "jz4740-rtc",
> + Â  Â  Â  Â  Â  Â  Â  .owner = THIS_MODULE,
> + Â  Â  Â  },
> +};
> +
> +static int __init jz4740_rtc_init(void)
> +{
> + Â  Â  Â  return platform_driver_register(&jz4740_rtc_driver);

platform_driver_probe is much better here.

> +}
> +module_init(jz4740_rtc_init);
> +
> +static void __exit jz4740_rtc_exit(void)
> +{
> + Â  Â  Â  platform_driver_unregister(&jz4740_rtc_driver);
> +}
> +module_exit(jz4740_rtc_exit);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n");
> +MODULE_ALIAS("platform:jz4740-rtc");
> --
> 1.5.6.5
>
> --
> You received this message because you are subscribed to "rtc-linux".
> Membership options at http://groups.google.com/group/rtc-linux .
> Please read http://groups.google.com/group/rtc-linux/web/checklist
> before submitting a driver.



-- 
*linux-arm-kernel mailing list
mail addr:linux-arm-kernel@lists.infradead.org
you can subscribe by:
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

* linux-arm-NUC900 mailing list
mail addr:NUC900@googlegroups.com
main web: https://groups.google.com/group/NUC900
you can subscribe it by sending me mail:
mcuos.com@gmail.com

From kernel@jic23.retrosnub.co.uk Sat Jun  5 19:22:43 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 19:22:47 +0200 (CEST)
Received: from ppsw-33.csi.cam.ac.uk ([131.111.8.133]:40558 "EHLO
        ppsw-33.csi.cam.ac.uk" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492138Ab0FERWn (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sat, 5 Jun 2010 19:22:43 +0200
X-Cam-AntiVirus: no malware found
X-Cam-SpamDetails: not scanned
X-Cam-ScannerInfo: http://www.cam.ac.uk/cs/email/scanner/
Received: from arcturus.eng.cam.ac.uk ([129.169.154.73]:37006)
        by ppsw-33.csi.cam.ac.uk (smtp.hermes.cam.ac.uk [131.111.8.159]:25)
        with esmtpsa (PLAIN:jic23) (TLSv1:DHE-RSA-AES256-SHA:256)
        id 1OKx4z-0007rG-hp (Exim 4.70)
        (return-path <jic23@hermes.cam.ac.uk>); Sat, 05 Jun 2010 18:22:41 +0100
Message-ID: <4C0A87F1.8000201@jic23.retrosnub.co.uk>
Date:   Sat, 05 Jun 2010 18:22:57 +0100
From:   Jonathan Cameron <kernel@jic23.retrosnub.co.uk>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100426 Thunderbird/3.0.4
MIME-Version: 1.0
To:     Lars-Peter Clausen <lars@metafoo.de>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, lm-sensors@lm-sensors.org
Subject: Re: [RFC][PATCH 22/26] hwmon: Add JZ4740 ADC driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-6-git-send-email-lars@metafoo.de>
In-Reply-To: <1275505950-17334-6-git-send-email-lars@metafoo.de>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-archive-position: 27075
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: kernel@jic23.retrosnub.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3913
Content-Length: 15394
Lines: 543

On 06/02/10 20:12, Lars-Peter Clausen wrote:
> This patch adds support for the ADC module on JZ4740 SoCs.
> 
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: lm-sensors@lm-sensors.org
> ---
>  drivers/hwmon/Kconfig      |   11 ++
>  drivers/hwmon/Makefile     |    1 +
>  drivers/hwmon/jz4740-adc.c |  423 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/jz4740-adc.h |   25 +++
>  4 files changed, 460 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/jz4740-adc.c
>  create mode 100644 include/linux/jz4740-adc.h
Hi, I'm just wondering of one wants the majority of this driver to sit in hwmon?

Looks to me like a fairly classic case for something that might be best implemented
as an mfd with the hwmon, touchscreen and battery drivers separately hanging off that.
You might well have someone who needs the battery driver to work, but doesn't care
about hwmon and so doesn't want to build that bit in... 

Just an immediate thought.  Perhaps this is the best way to do things...

Also after a quick look.  How is it used by the touchscreen driver?
If not, please remove the reference from kconfig until it it is true.

Few other bits and bobs inline.

> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index e19cf8e..da79ba9 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -446,6 +446,17 @@ config SENSORS_IT87
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called it87.
>  
> +config SENSORS_JZ4740
> +	tristate "Ingenic JZ4740 SoC ADC driver"
> +	depends on MACH_JZ4740
> +    help
> +      If you say yes here you get support for the Ingenic JZ4740 SoC ADC core.
> +      It is required for the JZ4740 battery and touchscreen driver and is used
> +      to synchronize access to the adc module between those two.
> +
> +      This driver can also be build as a module. If so, the module will be
> +      called jz4740-adc.
> +
>  config SENSORS_LM63
>  	tristate "National Semiconductor LM63 and LM64"
>  	depends on I2C
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 2138ceb..3e772aa 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -55,6 +55,7 @@ obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
>  obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
>  obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
>  obj-$(CONFIG_SENSORS_IT87)	+= it87.o
> +obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-adc.o
>  obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
>  obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
>  obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
> diff --git a/drivers/hwmon/jz4740-adc.c b/drivers/hwmon/jz4740-adc.c
> new file mode 100644
> index 0000000..635dfe9
> --- /dev/null
> +++ b/drivers/hwmon/jz4740-adc.c
> @@ -0,0 +1,423 @@
> +/*
> + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + *		JZ4740 SoC ADC driver
> + *
> + * This program is free software; you can redistribute	 it and/or modify it
> + * under  the terms of	 the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the	License, or (at your
> + * option) any later version.
> + *
> + * You should have received a copy of the  GNU General Public License along
> + * with this program; if not, write  to the Free Software Foundation, Inc.,
> + * 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * This driver is meant to synchronize access to the adc core for the battery
> + * and touchscreen driver. Thus these drivers should use the adc driver as a
> + * parent.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +#include <linux/clk.h>
> +
> +#include <linux/jz4740-adc.h>
> +
> +#define JZ_REG_ADC_ENABLE	0x00
> +#define JZ_REG_ADC_CFG		0x04
> +#define JZ_REG_ADC_CTRL		0x08
> +#define JZ_REG_ADC_STATUS	0x0C
> +#define JZ_REG_ADC_SAME		0x10
> +#define JZ_REG_ADC_WAIT		0x14
> +#define JZ_REG_ADC_TOUCH	0x18
> +#define JZ_REG_ADC_BATTERY	0x1C
> +#define JZ_REG_ADC_ADCIN	0x20
> +
> +#define JZ_ADC_ENABLE_TOUCH		BIT(2)
> +#define JZ_ADC_ENABLE_BATTERY		BIT(1)
> +#define JZ_ADC_ENABLE_ADCIN		BIT(0)
> +
> +#define JZ_ADC_CFG_SPZZ			BIT(31)
> +#define JZ_ADC_CFG_EX_IN		BIT(30)
> +#define JZ_ADC_CFG_DNUM_MASK		(0x7 << 16)
> +#define JZ_ADC_CFG_DMA_ENABLE		BIT(15)
> +#define JZ_ADC_CFG_XYZ_MASK		(0x2 << 13)
> +#define JZ_ADC_CFG_SAMPLE_NUM_MASK	(0x7 << 10)
> +#define JZ_ADC_CFG_CLKDIV		(0xf << 5)
> +#define JZ_ADC_CFG_BAT_MB		BIT(4)
> +
> +#define JZ_ADC_CFG_DNUM_OFFSET		16
> +#define JZ_ADC_CFG_XYZ_OFFSET		13
> +#define JZ_ADC_CFG_SAMPLE_NUM_OFFSET	10
> +#define JZ_ADC_CFG_CLKDIV_OFFSET	5
> +
> +#define JZ_ADC_IRQ_PENDOWN		BIT(4)
> +#define JZ_ADC_IRQ_PENUP		BIT(3)
> +#define JZ_ADC_IRQ_TOUCH		BIT(2)
> +#define JZ_ADC_IRQ_BATTERY		BIT(1)
> +#define JZ_ADC_IRQ_ADCIN		BIT(0)
> +
> +#define JZ_ADC_TOUCH_TYPE1		BIT(31)
> +#define JZ_ADC_TOUCH_DATA1_MASK		0xfff
> +#define JZ_ADC_TOUCH_TYPE0		BIT(15)
> +#define JZ_ADC_TOUCH_DATA0_MASK		0xfff
> +
> +#define JZ_ADC_BATTERY_MASK		0xfff
> +
> +#define JZ_ADC_ADCIN_MASK		0xfff
> +
> +struct jz4740_adc {
> +	struct resource *mem;
> +	void __iomem *base;
> +
> +	int irq;
> +
> +	struct clk *clk;
> +	unsigned int clk_ref;
> +
> +	struct device *hwmon;
> +
> +	struct completion bat_completion;
> +	struct completion adc_completion;
> +
> +	spinlock_t lock;
> +};
> +
> +static irqreturn_t jz4740_adc_irq(int irq, void *data)
> +{
> +	struct jz4740_adc *adc = data;
> +	uint8_t status;
> +
> +	status = readb(adc->base + JZ_REG_ADC_STATUS);
> +
> +	if (status & JZ_ADC_IRQ_BATTERY)
> +		complete(&adc->bat_completion);
> +	if (status & JZ_ADC_IRQ_ADCIN)
> +		complete(&adc->adc_completion);
> +
> +	writeb(0xff, adc->base + JZ_REG_ADC_STATUS);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void jz4740_adc_enable_irq(struct jz4740_adc *adc, int irq)
> +{
> +	unsigned long flags;
> +	uint8_t val;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +
> +	val = readb(adc->base + JZ_REG_ADC_CTRL);
> +	val &= ~irq;
> +	writeb(val, adc->base + JZ_REG_ADC_CTRL);
> +
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +static void jz4740_adc_disable_irq(struct jz4740_adc *adc, int irq)
> +{
> +	unsigned long flags;
> +	uint8_t val;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +
> +	val = readb(adc->base + JZ_REG_ADC_CTRL);
> +	val |= irq;
> +	writeb(val, adc->base + JZ_REG_ADC_CTRL);
> +
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
You could unify the two functions above with a simple parameter.  They share
almost all their code.


> +
> +static void jz4740_adc_enable_adc(struct jz4740_adc *adc, int engine)
> +{
> +	unsigned long flags;
> +	uint8_t val;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +
> +	val = readb(adc->base + JZ_REG_ADC_ENABLE);
> +	val |= engine;
> +	writeb(val, adc->base + JZ_REG_ADC_ENABLE);
> +
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +static void jz4740_adc_disable_adc(struct jz4740_adc *adc, int engine)
> +{
> +	unsigned long flags;
> +	uint8_t val;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +
> +	val = readb(adc->base + JZ_REG_ADC_ENABLE);
> +	val &= ~engine;
> +	writeb(val, adc->base + JZ_REG_ADC_ENABLE);
> +
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
The two above could be unified as well.

> +
> +static inline void jz4740_adc_set_cfg(struct jz4740_adc *adc, uint32_t mask,
> +uint32_t val)
Not sure, but the formatting of this line looks a bit odd..


> +{
> +	unsigned long flags;
> +	uint32_t cfg;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +
> +	cfg = readl(adc->base + JZ_REG_ADC_CFG);
> +
> +	cfg &= ~mask;
> +	cfg |= val;
> +
> +	writel(cfg, adc->base + JZ_REG_ADC_CFG);
> +
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +	if (adc->clk_ref++ == 0)
> +		clk_enable(adc->clk);
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +	if (--adc->clk_ref == 0)
> +		clk_disable(adc->clk);
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +

For example of mfd reasoning, nothing in this driver cares about this functionality.
To my mind it should be in the battery driver and the exports should be the
higher level functions.

Having this sort of access control in a hwmon driver seems like an unusual
approach.
> +long jz4740_adc_read_battery_voltage(struct device *dev,
> +						enum jz_adc_battery_scale scale)
> +{
> +	struct jz4740_adc *adc = dev_get_drvdata(dev);
> +	unsigned long t;
> +	long long voltage;
> +	uint16_t val;
> +
> +	if (!adc)
> +		return -ENODEV;
> +
> +	jz4740_adc_clk_enable(adc);
> +
> +	if (scale == JZ_ADC_BATTERY_SCALE_2V5)
> +		jz4740_adc_set_cfg(adc, JZ_ADC_CFG_BAT_MB, JZ_ADC_CFG_BAT_MB);
> +	else
> +		jz4740_adc_set_cfg(adc, JZ_ADC_CFG_BAT_MB, 0);
> +

> +	jz4740_adc_enable_irq(adc, JZ_ADC_IRQ_BATTERY);
> +	jz4740_adc_enable_adc(adc, JZ_ADC_ENABLE_BATTERY);
> +
> +	t = wait_for_completion_interruptible_timeout(&adc->bat_completion,
> +							HZ);
> +
> +	jz4740_adc_disable_irq(adc, JZ_ADC_IRQ_BATTERY);
> +
> +	if (t <= 0) {
> +		jz4740_adc_disable_adc(adc, JZ_ADC_ENABLE_BATTERY);
> +		return t ? t : -ETIMEDOUT;
> +	}
> +
> +	val = readw(adc->base + JZ_REG_ADC_BATTERY);
> +
> +	jz4740_adc_clk_disable(adc);
> +
> +	if (scale == JZ_ADC_BATTERY_SCALE_2V5)
> +		voltage = (((long long)val) * 2500000LL) >> 12LL;
> +	else
> +		voltage = ((((long long)val) * 7395000LL) >> 12LL) + 33000LL;
> +
> +	return voltage;
> +}
> +EXPORT_SYMBOL_GPL(jz4740_adc_read_battery_voltage);
> +
> +static ssize_t jz4740_adc_read_adcin(struct device *dev,
> +					struct device_attribute *dev_attr,
> +					char *buf)
> +{
> +	struct jz4740_adc *adc = dev_get_drvdata(dev);
> +	unsigned long t;
> +	uint16_t val;
> +
> +	jz4740_adc_clk_enable(adc);
> +
Is there a possible race here?
> +	jz4740_adc_enable_irq(adc, JZ_ADC_IRQ_ADCIN);
> +	jz4740_adc_enable_adc(adc, JZ_ADC_ENABLE_ADCIN);
> +
> +	t = wait_for_completion_interruptible_timeout(&adc->adc_completion,
> +							HZ);
> +
> +	jz4740_adc_disable_irq(adc, JZ_ADC_IRQ_ADCIN);
> +
> +	if (t <= 0) {
> +		jz4740_adc_disable_adc(adc, JZ_ADC_ENABLE_ADCIN);
> +		return t ? t : -ETIMEDOUT;
> +	}
> +
> +	val = readw(adc->base + JZ_REG_ADC_ADCIN);
> +	jz4740_adc_clk_disable(adc);
> +
Does this device really use units of milivolts? (standard in hwmon).
I couldn't confirm either way via quick googling.
> +	return sprintf(buf, "%d\n", val);
> +}
> +
> +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, jz4740_adc_read_adcin, NULL, 0);
> +
> +static int __devinit jz4740_adc_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct jz4740_adc *adc;
> +
> +	adc = kmalloc(sizeof(*adc), GFP_KERNEL);
> +
> +	adc->irq = platform_get_irq(pdev, 0);
> +
> +	if (adc->irq < 0) {
> +		ret = adc->irq;
> +		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
> +		goto err_free;
> +	}
> +
> +	adc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	if (!adc->mem) {
> +		ret = -ENOENT;
> +		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
> +		goto err_free;
> +	}
> +
> +	adc->mem = request_mem_region(adc->mem->start, resource_size(adc->mem),
> +					pdev->name);
> +
> +	if (!adc->mem) {
> +		ret = -EBUSY;
> +		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
> +		goto err_free;
> +	}
> +
> +	adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem));
> +
> +	if (!adc->base) {
> +		ret = -EBUSY;
> +		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
> +		goto err_release_mem_region;
> +	}
> +
> +	adc->clk = clk_get(&pdev->dev, "adc");
> +
> +	if (IS_ERR(adc->clk)) {
> +		ret = PTR_ERR(adc->clk);
> +		dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
> +		goto err_iounmap;
> +	}
> +
> +	init_completion(&adc->bat_completion);
> +	init_completion(&adc->adc_completion);
> +
> +	spin_lock_init(&adc->lock);
> +
> +	adc->clk_ref = 0;
> +
> +	platform_set_drvdata(pdev, adc);
> +
> +	ret = request_irq(adc->irq, jz4740_adc_irq, 0, pdev->name, adc);
> +
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
> +		goto err_clk_put;
> +	}
> +
> +	ret = device_create_file(&pdev->dev, &sensor_dev_attr_in0_input.dev_attr);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to create sysfs file: %d\n", ret);
> +		goto err_free_irq;
> +	}
> +
> +	adc->hwmon = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(adc->hwmon)) {
> +		ret = PTR_ERR(adc->hwmon);
> +		goto err_remove_file;
> +	}
> +
> +	writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
> +	writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
> +
> +	return 0;
> +
> +err_remove_file:
> +	device_remove_file(&pdev->dev, &sensor_dev_attr_in0_input.dev_attr);
> +err_free_irq:
> +	free_irq(adc->irq, adc);
> +err_clk_put:
> +	clk_put(adc->clk);
> +err_iounmap:
> +	platform_set_drvdata(pdev, NULL);
> +	iounmap(adc->base);
> +err_release_mem_region:
> +	release_mem_region(adc->mem->start, resource_size(adc->mem));
> +err_free:
> +	kfree(adc);
> +
> +	return ret;
> +}
> +
> +static int __devexit jz4740_adc_remove(struct platform_device *pdev)
> +{
> +	struct jz4740_adc *adc = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(adc->hwmon);
> +	device_remove_file(&pdev->dev, &sensor_dev_attr_in0_input.dev_attr);
> +
> +	free_irq(adc->irq, adc);
> +
> +	iounmap(adc->base);
> +	release_mem_region(adc->mem->start, resource_size(adc->mem));
> +
> +	clk_put(adc->clk);
> +
> +	platform_set_drvdata(pdev, NULL);
> +
> +	kfree(adc);
> +
> +	return 0;
> +}
> +
> +struct platform_driver jz4740_adc_driver = {
> +	.probe	= jz4740_adc_probe,
> +	.remove = __devexit_p(jz4740_adc_remove),
> +	.driver = {
> +		.name = "jz4740-adc",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static int __init jz4740_adc_init(void)
> +{
> +	return platform_driver_register(&jz4740_adc_driver);
> +}
> +module_init(jz4740_adc_init);
> +
> +static void __exit jz4740_adc_exit(void)
> +{
> +	platform_driver_unregister(&jz4740_adc_driver);
> +}
> +module_exit(jz4740_adc_exit);
> +
> +MODULE_DESCRIPTION("JZ4740 SoC ADC driver");
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:jz4740-adc");
> diff --git a/include/linux/jz4740-adc.h b/include/linux/jz4740-adc.h
> new file mode 100644
> index 0000000..59cfe63
> --- /dev/null
> +++ b/include/linux/jz4740-adc.h
> @@ -0,0 +1,25 @@
> +
> +#ifndef __LINUX_JZ4740_ADC
> +#define __LINUX_JZ4740_ADC
> +
> +#include <linux/device.h>
> +
> +enum jz_adc_battery_scale {
> +	JZ_ADC_BATTERY_SCALE_2V5, /* Mesures voltages up to 2.5V */
> +	JZ_ADC_BATTERY_SCALE_7V5, /* Mesures voltages up to 7.5V */
> +};
> +
> +/*
> + * jz4740_adc_read_battery_voltage - Read battery voltage from the ADC PBAT pin
> + * @dev: Pointer to a jz4740-adc device
> + * @scale: Whether to use 2.5V or 7.5V scale
> + *
> + * Returns: Battery voltage in mircovolts
> + *
> + * Context: Process
> +*/
> +long jz4740_adc_read_battery_voltage(struct device *dev,
> +					enum jz_adc_battery_scale scale);
> +
> +
> +#endif


From lars@metafoo.de Sat Jun  5 19:26:55 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 19:27:02 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:63853 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491995Ab0FER0z (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sat, 5 Jun 2010 19:26:55 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id E294E395;
        Sat,  5 Jun 2010 19:26:49 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id XTnpyaXX2PwF; Sat,  5 Jun 2010 19:26:49 +0200 (CEST)
Received: from [192.168.37.30] (port-11083.pppoe.wtnet.de [84.46.43.118])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 6C8C5393;
        Sat,  5 Jun 2010 19:26:39 +0200 (CEST)
Message-ID: <4C0A88B0.4060107@metafoo.de>
Date:   Sat, 05 Jun 2010 19:26:08 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Wan ZongShun <mcuos.com@gmail.com>
CC:     rtc-linux@googlegroups.com, Ralf Baechle <ralf@linux-mips.org>,
        linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Alessandro Zummo <a.zummo@towertech.it>,
        Paul Gortmaker <p_gortmaker@yahoo.com>
Subject: Re: [rtc-linux] [RFC][PATCH 15/26] RTC: Add JZ4740 RTC driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de>        <1275505832-17185-7-git-send-email-lars@metafoo.de> <AANLkTilyeoul7MEs0Q-tlHLdVHBQg6QIuucvy2UH2nkF@mail.gmail.com>
In-Reply-To: <AANLkTilyeoul7MEs0Q-tlHLdVHBQg6QIuucvy2UH2nkF@mail.gmail.com>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-archive-position: 27076
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3915
Content-Length: 13653
Lines: 422

Hi

Wan ZongShun wrote:
> 2010/6/3 Lars-Peter Clausen <lars@metafoo.de>:
>   
>> This patch adds support for the RTC unit on JZ4740 SoCs.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> Cc: Alessandro Zummo <a.zummo@towertech.it>
>> Cc: Paul Gortmaker <p_gortmaker@yahoo.com>
>> Cc: rtc-linux@googlegroups.com
>> ---
>>  drivers/rtc/Kconfig      |   11 ++
>>  drivers/rtc/Makefile     |    1 +
>>  drivers/rtc/rtc-jz4740.c |  344 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 356 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/rtc/rtc-jz4740.c
>>
>> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
>> index 10ba12c..d0ed7e6 100644
>> --- a/drivers/rtc/Kconfig
>> +++ b/drivers/rtc/Kconfig
>> @@ -905,4 +905,15 @@ config RTC_DRV_MPC5121
>>          This driver can also be built as a module. If so, the module
>>          will be called rtc-mpc5121.
>>
>> +config RTC_DRV_JZ4740
>> +       tristate "Ingenic JZ4740 SoC"
>> +       depends on RTC_CLASS
>> +       depends on MACH_JZ4740
>> +       help
>> +         If you say yes here you get support for the Ingenic JZ4740 SoC RTC
>> +         controller.
>> +
>> +         This driver can also be buillt as a module. If so, the module
>> +         will be called rtc-jz4740.
>> +
>>  endif # RTC_CLASS
>> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
>> index 5adbba7..fedf9bb 100644
>> --- a/drivers/rtc/Makefile
>> +++ b/drivers/rtc/Makefile
>> @@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX)  += rtc-ep93xx.o
>>  obj-$(CONFIG_RTC_DRV_FM3130)   += rtc-fm3130.o
>>  obj-$(CONFIG_RTC_DRV_GENERIC)  += rtc-generic.o
>>  obj-$(CONFIG_RTC_DRV_ISL1208)  += rtc-isl1208.o
>> +obj-$(CONFIG_RTC_DRV_JZ4740)   += rtc-jz4740.o
>>  obj-$(CONFIG_RTC_DRV_M41T80)   += rtc-m41t80.o
>>  obj-$(CONFIG_RTC_DRV_M41T94)   += rtc-m41t94.o
>>  obj-$(CONFIG_RTC_DRV_M48T35)   += rtc-m48t35.o
>> diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
>> new file mode 100644
>> index 0000000..41ab78f
>> --- /dev/null
>> +++ b/drivers/rtc/rtc-jz4740.c
>> @@ -0,0 +1,344 @@
>> +/*
>> + *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
>> + *             JZ4740 SoC RTC driver
>> + *
>> + *  This program is free software; you can redistribute         it and/or modify it
>> + *  under  the terms of         the GNU General  Public License as published by the
>> + *  Free Software Foundation;  either version 2 of the License, or (at your
>> + *  option) any later version.
>> + *
>> + *  You should have received a copy of the  GNU General Public License along
>> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
>> + *  675 Mass Ave, Cambridge, MA 02139, USA.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/rtc.h>
>> +#include <linux/slab.h>
>> +#include <linux/spinlock.h>
>> +
>> +#define JZ_REG_RTC_CTRL                0x00
>> +#define JZ_REG_RTC_SEC         0x04
>> +#define JZ_REG_RTC_SEC_ALARM   0x08
>> +#define JZ_REG_RTC_REGULATOR   0x0C
>> +#define JZ_REG_RTC_HIBERNATE   0x20
>> +#define JZ_REG_RTC_SCRATCHPAD  0x34
>> +
>> +#define JZ_RTC_CTRL_WRDY       BIT(7)
>> +#define JZ_RTC_CTRL_1HZ                BIT(6)
>> +#define JZ_RTC_CTRL_1HZ_IRQ    BIT(5)
>> +#define JZ_RTC_CTRL_AF         BIT(4)
>> +#define JZ_RTC_CTRL_AF_IRQ     BIT(3)
>> +#define JZ_RTC_CTRL_AE         BIT(2)
>> +#define JZ_RTC_CTRL_ENABLE     BIT(0)
>> +
>> +struct jz4740_rtc {
>> +       struct resource *mem;
>> +       void __iomem *base;
>> +
>> +       struct rtc_device *rtc;
>> +
>> +       unsigned int irq;
>> +
>> +       spinlock_t lock;
>> +};
>> +
>> +static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
>> +{
>> +       return readl(rtc->base + reg);
>> +}
>> +
>> +static inline void jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
>> +{
>> +       uint32_t ctrl;
>> +       do {
>> +               ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
>> +       } while (!(ctrl & JZ_RTC_CTRL_WRDY));
>> +}
>> +
>> +
>> +static inline void jz4740_rtc_reg_write(struct jz4740_rtc *rtc, size_t reg,
>> +                                       uint32_t val)
>> +{
>> +       jz4740_rtc_wait_write_ready(rtc);
>> +       writel(val, rtc->base + reg);
>> +}
>> +
>> +static void jz4740_rtc_ctrl_set_bits(struct jz4740_rtc *rtc, uint32_t mask,
>> +                                       uint32_t val)
>> +{
>> +       unsigned long flags;
>> +       uint32_t ctrl;
>> +
>> +       spin_lock_irqsave(&rtc->lock, flags);
>> +
>> +       ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
>> +
>> +       /* Don't clear interrupt flags by accident */
>> +       ctrl |= JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF;
>> +
>> +       ctrl &= ~mask;
>> +       ctrl |= val;
>> +
>> +       jz4740_rtc_reg_write(rtc, JZ_REG_RTC_CTRL, ctrl);
>> +
>> +       spin_unlock_irqrestore(&rtc->lock, flags);
>> +}
>> +
>> +static inline struct jz4740_rtc *dev_to_rtc(struct device *dev)
>> +{
>> +       return dev_get_drvdata(dev);
>> +}
>> +
>>     
>
> Why do you need to re-implement the 'dev_to_rtc' instead of using
> 'platform_get_drvdata' provided by Linux own.'
>   
I like to write self documenting code, so this documents how to get the
a pointer to the jz4740_rtc struct if you only have device. But I guess
in this case it's safe to use dev_get_drvdata directly from within the
other of the drivers functions without loosing to much.
>> +static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
>> +{
>> +       struct jz4740_rtc *rtc = dev_to_rtc(dev);
>> +       uint32_t secs, secs2;
>> +
>> +       secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
>> +       secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
>> +
>> +       while (secs != secs2) {
>> +               secs = secs2;
>> +               secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC);
>> +       }
>> +
>> +       rtc_time_to_tm(secs, time);
>> +
>> +       return rtc_valid_tm(time);
>> +}
>> +
>> +static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)
>> +{
>> +       struct jz4740_rtc *rtc = dev_to_rtc(dev);
>> +
>> +       if ((uint32_t)secs != secs)
>> +               return -EINVAL;
>> +
>> +       jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, secs);
>> +
>> +       return 0;
>> +}
>> +
>> +static int jz4740_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>> +{
>> +       struct jz4740_rtc *rtc = dev_to_rtc(dev);
>> +       uint32_t secs, secs2;
>> +       uint32_t ctrl;
>> +
>> +       secs = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
>> +       secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
>> +
>> +       while (secs != secs2) {
>> +               secs = secs2;
>> +               secs2 = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SEC_ALARM);
>> +       }
>> +
>> +       ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
>> +
>> +       alrm->enabled = !!(ctrl & JZ_RTC_CTRL_AE);
>> +       alrm->pending = !!(ctrl & JZ_RTC_CTRL_AF);
>> +
>> +       rtc_time_to_tm(secs, &alrm->time);
>> +
>> +       return rtc_valid_tm(&alrm->time);
>> +}
>> +
>> +static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>> +{
>> +       struct jz4740_rtc *rtc = dev_to_rtc(dev);
>> +       unsigned long secs;
>> +
>> +       rtc_tm_to_time(&alrm->time, &secs);
>> +
>> +       if ((uint32_t)secs != secs)
>> +               return -EINVAL;
>> +
>> +       jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, (uint32_t)secs);
>> +       jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE,
>> +                                       alrm->enabled ? JZ_RTC_CTRL_AE : 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable)
>> +{
>> +       struct jz4740_rtc *rtc = dev_to_rtc(dev);
>> +       jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ,
>> +                                       enable ? JZ_RTC_CTRL_1HZ_IRQ : 0);
>> +       return 0;
>> +}
>> +
>> +
>> +static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
>> +{
>> +       struct jz4740_rtc *rtc = dev_to_rtc(dev);
>> +       jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ,
>> +                                       enable ? JZ_RTC_CTRL_AF_IRQ : 0);
>> +       return 0;
>> +}
>> +
>> +static struct rtc_class_ops jz4740_rtc_ops = {
>> +       .read_time      = jz4740_rtc_read_time,
>> +       .set_mmss       = jz4740_rtc_set_mmss,
>> +       .read_alarm     = jz4740_rtc_read_alarm,
>> +       .set_alarm      = jz4740_rtc_set_alarm,
>> +       .update_irq_enable = jz4740_rtc_update_irq_enable,
>> +       .alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
>> +};
>> +
>> +static irqreturn_t jz4740_rtc_irq(int irq, void *data)
>> +{
>> +       struct jz4740_rtc *rtc = data;
>> +       uint32_t ctrl;
>> +       unsigned long events = 0;
>> +       ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
>> +
>> +       if (ctrl & JZ_RTC_CTRL_1HZ)
>> +               events |= (RTC_UF | RTC_IRQF);
>> +
>> +       if (ctrl & JZ_RTC_CTRL_AF)
>> +               events |= (RTC_AF | RTC_IRQF);
>> +
>> +       rtc_update_irq(rtc->rtc, 1, events);
>> +
>> +       jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ | JZ_RTC_CTRL_AF, 0);
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +void jz4740_rtc_poweroff(struct device *dev)
>> +{
>> +       struct jz4740_rtc *rtc = dev_get_drvdata(dev);
>> +       jz4740_rtc_reg_write(rtc, JZ_REG_RTC_HIBERNATE, 1);
>> +}
>> +EXPORT_SYMBOL_GPL(jz4740_rtc_poweroff);
>> +
>> +static int __devinit jz4740_rtc_probe(struct platform_device *pdev)
>> +{
>> +       int ret;
>> +       struct jz4740_rtc *rtc;
>> +       uint32_t scratchpad;
>> +
>> +       rtc = kmalloc(sizeof(*rtc), GFP_KERNEL);
>> +
>> +       rtc->irq = platform_get_irq(pdev, 0);
>> +
>> +       if (rtc->irq < 0) {
>> +               ret = -ENOENT;
>> +               dev_err(&pdev->dev, "Failed to get platform irq\n");
>> +               goto err_free;
>> +       }
>> +
>> +       rtc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       if (!rtc->mem) {
>> +               ret = -ENOENT;
>> +               dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
>> +               goto err_free;
>> +       }
>> +
>> +       rtc->mem = request_mem_region(rtc->mem->start, resource_size(rtc->mem),
>> +                                       pdev->name);
>> +
>> +       if (!rtc->mem) {
>> +               ret = -EBUSY;
>> +               dev_err(&pdev->dev, "Failed to request mmio memory region\n");
>> +               goto err_free;
>> +       }
>> +
>> +       rtc->base = ioremap_nocache(rtc->mem->start, resource_size(rtc->mem));
>> +
>> +       if (!rtc->base) {
>> +               ret = -EBUSY;
>> +               dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
>> +               goto err_release_mem_region;
>> +       }
>> +
>> +       spin_lock_init(&rtc->lock);
>> +
>> +       platform_set_drvdata(pdev, rtc);
>> +
>> +       rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops,
>> +                                       THIS_MODULE);
>> +
>> +       if (IS_ERR(rtc->rtc)) {
>> +               ret = PTR_ERR(rtc->rtc);
>> +               dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
>> +               goto err_iounmap;
>> +       }
>> +
>> +       ret = request_irq(rtc->irq, jz4740_rtc_irq, 0,
>> +                               pdev->name, rtc);
>> +
>> +       if (ret) {
>> +               dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
>> +               goto err_unregister_rtc;
>> +       }
>> +
>> +       scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
>> +       if (scratchpad != 0x12345678) {
>> +               jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
>> +               jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
>> +       }
>> +
>> +       return 0;
>> +
>> +err_unregister_rtc:
>> +       rtc_device_unregister(rtc->rtc);
>> +err_iounmap:
>> +       platform_set_drvdata(pdev, NULL);
>> +       iounmap(rtc->base);
>> +err_release_mem_region:
>> +       release_mem_region(rtc->mem->start, resource_size(rtc->mem));
>> +err_free:
>> +       kfree(rtc);
>> +
>> +       return ret;
>> +}
>> +
>> +static int __devexit jz4740_rtc_remove(struct platform_device *pdev)
>> +{
>> +       struct jz4740_rtc *rtc = platform_get_drvdata(pdev);
>> +
>> +       free_irq(rtc->irq, rtc);
>> +
>> +       rtc_device_unregister(rtc->rtc);
>> +
>> +       iounmap(rtc->base);
>> +       release_mem_region(rtc->mem->start, resource_size(rtc->mem));
>> +
>> +       kfree(rtc);
>> +
>> +       platform_set_drvdata(pdev, NULL);
>> +
>> +       return 0;
>> +}
>> +
>> +struct platform_driver jz4740_rtc_driver = {
>> +       .probe = jz4740_rtc_probe,
>> +       .remove = __devexit_p(jz4740_rtc_remove),
>> +       .driver = {
>> +               .name = "jz4740-rtc",
>> +               .owner = THIS_MODULE,
>> +       },
>> +};
>> +
>> +static int __init jz4740_rtc_init(void)
>> +{
>> +       return platform_driver_register(&jz4740_rtc_driver);
>>     
>
> platform_driver_probe is much better here.
>
>   
Ok.
>> +}
>> +module_init(jz4740_rtc_init);
>> +
>> +static void __exit jz4740_rtc_exit(void)
>> +{
>> +       platform_driver_unregister(&jz4740_rtc_driver);
>> +}
>> +module_exit(jz4740_rtc_exit);
>> +
>> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
>> +MODULE_LICENSE("GPL");
>> +MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n");
>> +MODULE_ALIAS("platform:jz4740-rtc");
>> --
>> 1.5.6.5
>>
>> -
Thanks for reviewing the patch.

- Lars

From lars@metafoo.de Sat Jun  5 21:09:41 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 21:09:45 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:34772 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492137Ab0FETJl (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sat, 5 Jun 2010 21:09:41 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id D75244B6;
        Sat,  5 Jun 2010 21:09:35 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id FqKkiA7B3FJQ; Sat,  5 Jun 2010 21:09:35 +0200 (CEST)
Received: from [192.168.37.30] (port-11083.pppoe.wtnet.de [84.46.43.118])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id C9DD44B5;
        Sat,  5 Jun 2010 21:09:29 +0200 (CEST)
Message-ID: <4C0AA0CA.9020808@metafoo.de>
Date:   Sat, 05 Jun 2010 21:08:58 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Jonathan Cameron <kernel@jic23.retrosnub.co.uk>
CC:     Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org,
        linux-kernel@vger.kernel.org, lm-sensors@lm-sensors.org
Subject: Re: [RFC][PATCH 22/26] hwmon: Add JZ4740 ADC driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-6-git-send-email-lars@metafoo.de> <4C0A87F1.8000201@jic23.retrosnub.co.uk>
In-Reply-To: <4C0A87F1.8000201@jic23.retrosnub.co.uk>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-archive-position: 27077
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 3956
Content-Length: 3324
Lines: 96

Hi

Jonathan Cameron wrote:
> On 06/02/10 20:12, Lars-Peter Clausen wrote:
>   
>> This patch adds support for the ADC module on JZ4740 SoCs.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> Cc: lm-sensors@lm-sensors.org
>> ---
>>  drivers/hwmon/Kconfig      |   11 ++
>>  drivers/hwmon/Makefile     |    1 +
>>  drivers/hwmon/jz4740-adc.c |  423 ++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/jz4740-adc.h |   25 +++
>>  4 files changed, 460 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hwmon/jz4740-adc.c
>>  create mode 100644 include/linux/jz4740-adc.h
>>     
> Hi, I'm just wondering of one wants the majority of this driver to sit in hwmon?
>
> Looks to me like a fairly classic case for something that might be best implemented
> as an mfd with the hwmon, touchscreen and battery drivers separately hanging off that.
> You might well have someone who needs the battery driver to work, but doesn't care
> about hwmon and so doesn't want to build that bit in... 
>
> Just an immediate thought.  Perhaps this is the best way to do things...
>   
I've thought about it before and rejected the idea at that time, because
I thought it will add more abstraction then actually needed.
But at that time the adc driver was not a hwmon driver yet and thus
didn't pull in the whole hwmon framework if you only wanted to use the
battery driver.
But the more I'm thinking about it now it might actually make sense to
move the common code to a MFD driver.
> Also after a quick look.  How is it used by the touchscreen driver?
> If not, please remove the reference from kconfig until it it is true.
>   
There is no touchscreen driver yet. But if I'm going to remove the
reference I'm pretty sure that someone will come up and ask why it
actually is necessary to have a separate driver instead of putting all
the code into the battery driver.
> Few other bits and bobs inline.
>   
>>
>> diff --git a/drivers/hwmon/jz4740-adc.c b/drivers/hwmon/jz4740-adc.c
>> new file mode 100644
>> index 0000000..635dfe9
>> --- /dev/null
>> +++ b/drivers/hwmon/jz4740-adc.c
>> @@ -0,0 +1,423 @@
>> + [...]
>> +static ssize_t jz4740_adc_read_adcin(struct device *dev,
>> +					struct device_attribute *dev_attr,
>> +					char *buf)
>> +{
>> +	struct jz4740_adc *adc = dev_get_drvdata(dev);
>> +	unsigned long t;
>> +	uint16_t val;
>> +
>> +	jz4740_adc_clk_enable(adc);
>> +
>>     
> Is there a possible race here?
>   
Where exactly?
>> +	jz4740_adc_enable_irq(adc, JZ_ADC_IRQ_ADCIN);
>> +	jz4740_adc_enable_adc(adc, JZ_ADC_ENABLE_ADCIN);
>> +
>> +	t = wait_for_completion_interruptible_timeout(&adc->adc_completion,
>> +							HZ);
>> +
>> +	jz4740_adc_disable_irq(adc, JZ_ADC_IRQ_ADCIN);
>> +
>> +	if (t <= 0) {
>> +		jz4740_adc_disable_adc(adc, JZ_ADC_ENABLE_ADCIN);
>> +		return t ? t : -ETIMEDOUT;
>> +	}
>> +
>> +	val = readw(adc->base + JZ_REG_ADC_ADCIN);
>> +	jz4740_adc_clk_disable(adc);
>> +
>>     
> Does this device really use units of milivolts? (standard in hwmon).
> I couldn't confirm either way via quick googling.
>   
Hm, right, it does not. Interestingly the datasheet does not tell the
unit of the returned data, but I found a formula in the datasheet for a
similar SoC.
>> +	return sprintf(buf, "%d\n", val);
>> +}
>> +
>> + [...]
>>     
Thanks for reviewing the patch.

- Lars

From kernel@jic23.retrosnub.co.uk Sat Jun  5 23:06:59 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sat, 05 Jun 2010 23:07:04 +0200 (CEST)
Received: from ppsw-32.csi.cam.ac.uk ([131.111.8.132]:38755 "EHLO
        ppsw-32.csi.cam.ac.uk" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491970Ab0FEVG7 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sat, 5 Jun 2010 23:06:59 +0200
X-Cam-AntiVirus: no malware found
X-Cam-SpamDetails: not scanned
X-Cam-ScannerInfo: http://www.cam.ac.uk/cs/email/scanner/
Received: from arcturus.eng.cam.ac.uk ([129.169.154.73]:58572)
        by ppsw-32.csi.cam.ac.uk (smtp.hermes.cam.ac.uk [131.111.8.158]:25)
        with esmtpsa (PLAIN:jic23) (TLSv1:DHE-RSA-AES256-SHA:256)
        id 1OL0Zy-0006QB-2H (Exim 4.70)
        (return-path <jic23@hermes.cam.ac.uk>); Sat, 05 Jun 2010 22:06:54 +0100
Message-ID: <4C0ABC75.9020908@jic23.retrosnub.co.uk>
Date:   Sat, 05 Jun 2010 22:07:01 +0100
From:   Jonathan Cameron <kernel@jic23.retrosnub.co.uk>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100426 Thunderbird/3.0.4
MIME-Version: 1.0
To:     Lars-Peter Clausen <lars@metafoo.de>
CC:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Ralf Baechle <ralf@linux-mips.org>, lm-sensors@lm-sensors.org
Subject: Re: [lm-sensors] [RFC][PATCH 22/26] hwmon: Add JZ4740 ADC driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-6-git-send-email-lars@metafoo.de>     <4C0A87F1.8000201@jic23.retrosnub.co.uk> <4C0AA0CA.9020808@metafoo.de>
In-Reply-To: <4C0AA0CA.9020808@metafoo.de>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-archive-position: 27078
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: kernel@jic23.retrosnub.co.uk
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4005
Content-Length: 4093
Lines: 106

On 06/05/10 20:08, Lars-Peter Clausen wrote:
> Hi
> 
> Jonathan Cameron wrote:
>> On 06/02/10 20:12, Lars-Peter Clausen wrote:
>>   
>>> This patch adds support for the ADC module on JZ4740 SoCs.
>>>
>>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>>> Cc: lm-sensors@lm-sensors.org
>>> ---
>>>  drivers/hwmon/Kconfig      |   11 ++
>>>  drivers/hwmon/Makefile     |    1 +
>>>  drivers/hwmon/jz4740-adc.c |  423 ++++++++++++++++++++++++++++++++++++++++++++
>>>  include/linux/jz4740-adc.h |   25 +++
>>>  4 files changed, 460 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/hwmon/jz4740-adc.c
>>>  create mode 100644 include/linux/jz4740-adc.h
>>>     
>> Hi, I'm just wondering of one wants the majority of this driver to sit in hwmon?
>>
>> Looks to me like a fairly classic case for something that might be best implemented
>> as an mfd with the hwmon, touchscreen and battery drivers separately hanging off that.
>> You might well have someone who needs the battery driver to work, but doesn't care
>> about hwmon and so doesn't want to build that bit in... 
>>
>> Just an immediate thought.  Perhaps this is the best way to do things...
>>   
> I've thought about it before and rejected the idea at that time, because
> I thought it will add more abstraction then actually needed.
> But at that time the adc driver was not a hwmon driver yet and thus
> didn't pull in the whole hwmon framework if you only wanted to use the
> battery driver.
> But the more I'm thinking about it now it might actually make sense to
> move the common code to a MFD driver.
>> Also after a quick look.  How is it used by the touchscreen driver?
>> If not, please remove the reference from kconfig until it it is true.
>>   
> There is no touchscreen driver yet. But if I'm going to remove the
> reference I'm pretty sure that someone will come up and ask why it
> actually is necessary to have a separate driver instead of putting all
> the code into the battery driver.
Fair enough.  Perhaps a comment for the patch rather than in Kconfig
as it currently is.  People will enable it then go 'Why can't I now
enable the touchscreen driver?'

>> Few other bits and bobs inline.
>>   
>>>
>>> diff --git a/drivers/hwmon/jz4740-adc.c b/drivers/hwmon/jz4740-adc.c
>>> new file mode 100644
>>> index 0000000..635dfe9
>>> --- /dev/null
>>> +++ b/drivers/hwmon/jz4740-adc.c
>>> @@ -0,0 +1,423 @@
>>> + [...]
>>> +static ssize_t jz4740_adc_read_adcin(struct device *dev,
>>> +					struct device_attribute *dev_attr,
>>> +					char *buf)
>>> +{
>>> +	struct jz4740_adc *adc = dev_get_drvdata(dev);
>>> +	unsigned long t;
>>> +	uint16_t val;
>>> +
>>> +	jz4740_adc_clk_enable(adc);
>>> +
>>>     
>> Is there a possible race here?
>>   
> Where exactly?
I can't recall off the top of my head if sysfs attributes can having multiple
simultaneous readers. If they can then thread two is just past the next line.
Whilst the earlier thread has passed the t = wait.... line as the interrupt has
fired.  The irq is then disabled by thread 1 whilst thread 2 enables the adc.
Clearly the timeout will prevent any serious issues but the 2nd thread is going
to falsely wait a second I think... ?
>>> +	jz4740_adc_enable_irq(adc, JZ_ADC_IRQ_ADCIN);
>>> +	jz4740_adc_enable_adc(adc, JZ_ADC_ENABLE_ADCIN);
>>> +
>>> +	t = wait_for_completion_interruptible_timeout(&adc->adc_completion,
>>> +							HZ);
>>> +
>>> +	jz4740_adc_disable_irq(adc, JZ_ADC_IRQ_ADCIN);
>>> +
>>> +	if (t <= 0) {
>>> +		jz4740_adc_disable_adc(adc, JZ_ADC_ENABLE_ADCIN);
>>> +		return t ? t : -ETIMEDOUT;
>>> +	}
>>> +
>>> +	val = readw(adc->base + JZ_REG_ADC_ADCIN);
>>> +	jz4740_adc_clk_disable(adc);
>>> +
>>>     
>> Does this device really use units of milivolts? (standard in hwmon).
>> I couldn't confirm either way via quick googling.
>>   
> Hm, right, it does not. Interestingly the datasheet does not tell the
> unit of the returned data, but I found a formula in the datasheet for a
> similar SoC.
>>> +	return sprintf(buf, "%d\n", val);
>>> +}
>>> +
>>> + [...]
>>>     
> Thanks for reviewing the patch.
You are welcome.

From lars@metafoo.de Sun Jun  6 00:13:15 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sun, 06 Jun 2010 00:13:20 +0200 (CEST)
Received: from mailhost.informatik.uni-hamburg.de ([134.100.9.70]:42617 "EHLO
        mailhost.informatik.uni-hamburg.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492002Ab0FEWNP (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sun, 6 Jun 2010 00:13:15 +0200
Received: from localhost (localhost [127.0.0.1])
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTP id EAC33691;
        Sun,  6 Jun 2010 00:13:03 +0200 (CEST)
X-Virus-Scanned: amavisd-new at informatik.uni-hamburg.de
Received: from mailhost.informatik.uni-hamburg.de ([127.0.0.1])
        by localhost (mailhost.informatik.uni-hamburg.de [127.0.0.1]) (amavisd-new, port 10024)
        with LMTP id suIG7NIwPYzB; Sun,  6 Jun 2010 00:13:03 +0200 (CEST)
Received: from [192.168.37.30] (port-11083.pppoe.wtnet.de [84.46.43.118])
        (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
        (Client did not present a certificate)
        (Authenticated sender: 7clausen)
        by mailhost.informatik.uni-hamburg.de (Postfix) with ESMTPSA id 58691690;
        Sun,  6 Jun 2010 00:12:53 +0200 (CEST)
Message-ID: <4C0ACBC6.6050209@metafoo.de>
Date:   Sun, 06 Jun 2010 00:12:22 +0200
From:   Lars-Peter Clausen <lars@metafoo.de>
User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100329)
MIME-Version: 1.0
To:     Jonathan Cameron <kernel@jic23.retrosnub.co.uk>
CC:     linux-mips@linux-mips.org, linux-kernel@vger.kernel.org,
        Ralf Baechle <ralf@linux-mips.org>, lm-sensors@lm-sensors.org
Subject: Re: [lm-sensors] [RFC][PATCH 22/26] hwmon: Add JZ4740 ADC driver
References: <1275505397-16758-1-git-send-email-lars@metafoo.de> <1275505950-17334-6-git-send-email-lars@metafoo.de>     <4C0A87F1.8000201@jic23.retrosnub.co.uk> <4C0AA0CA.9020808@metafoo.de> <4C0ABC75.9020908@jic23.retrosnub.co.uk>
In-Reply-To: <4C0ABC75.9020908@jic23.retrosnub.co.uk>
X-Enigmail-Version: 0.95.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-archive-position: 27079
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: lars@metafoo.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4024
Content-Length: 3726
Lines: 98

Jonathan Cameron wrote:
> On 06/05/10 20:08, Lars-Peter Clausen wrote:
>   
>> Hi
>>
>> Jonathan Cameron wrote:
>>     
>>> On 06/02/10 20:12, Lars-Peter Clausen wrote:
>>>   
>>>       
>>>> This patch adds support for the ADC module on JZ4740 SoCs.
>>>>
>>>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>>>> Cc: lm-sensors@lm-sensors.org
>>>> ---
>>>>  drivers/hwmon/Kconfig      |   11 ++
>>>>  drivers/hwmon/Makefile     |    1 +
>>>>  drivers/hwmon/jz4740-adc.c |  423 ++++++++++++++++++++++++++++++++++++++++++++
>>>>  include/linux/jz4740-adc.h |   25 +++
>>>>  4 files changed, 460 insertions(+), 0 deletions(-)
>>>>  create mode 100644 drivers/hwmon/jz4740-adc.c
>>>>  create mode 100644 include/linux/jz4740-adc.h
>>>>     
>>>>         
>>> Hi, I'm just wondering of one wants the majority of this driver to sit in hwmon?
>>>
>>> Looks to me like a fairly classic case for something that might be best implemented
>>> as an mfd with the hwmon, touchscreen and battery drivers separately hanging off that.
>>> You might well have someone who needs the battery driver to work, but doesn't care
>>> about hwmon and so doesn't want to build that bit in... 
>>>
>>> Just an immediate thought.  Perhaps this is the best way to do things...
>>>   
>>>       
>> I've thought about it before and rejected the idea at that time, because
>> I thought it will add more abstraction then actually needed.
>> But at that time the adc driver was not a hwmon driver yet and thus
>> didn't pull in the whole hwmon framework if you only wanted to use the
>> battery driver.
>> But the more I'm thinking about it now it might actually make sense to
>> move the common code to a MFD driver.
>>     
>>> Also after a quick look.  How is it used by the touchscreen driver?
>>> If not, please remove the reference from kconfig until it it is true.
>>>   
>>>       
>> There is no touchscreen driver yet. But if I'm going to remove the
>> reference I'm pretty sure that someone will come up and ask why it
>> actually is necessary to have a separate driver instead of putting all
>> the code into the battery driver.
>>     
> Fair enough.  Perhaps a comment for the patch rather than in Kconfig
> as it currently is.  People will enable it then go 'Why can't I now
> enable the touchscreen driver?'
>
>   
I guess that will work.
>>> Few other bits and bobs inline.
>>>   
>>>       
>>>> diff --git a/drivers/hwmon/jz4740-adc.c b/drivers/hwmon/jz4740-adc.c
>>>> new file mode 100644
>>>> index 0000000..635dfe9
>>>> --- /dev/null
>>>> +++ b/drivers/hwmon/jz4740-adc.c
>>>> @@ -0,0 +1,423 @@
>>>> + [...]
>>>> +static ssize_t jz4740_adc_read_adcin(struct device *dev,
>>>> +					struct device_attribute *dev_attr,
>>>> +					char *buf)
>>>> +{
>>>> +	struct jz4740_adc *adc = dev_get_drvdata(dev);
>>>> +	unsigned long t;
>>>> +	uint16_t val;
>>>> +
>>>> +	jz4740_adc_clk_enable(adc);
>>>> +
>>>>     
>>>>         
>>> Is there a possible race here?
>>>   
>>>       
>> Where exactly?
>>     
> I can't recall off the top of my head if sysfs attributes can having multiple
> simultaneous readers. If they can then thread two is just past the next line.
> Whilst the earlier thread has passed the t = wait.... line as the interrupt has
> fired.  The irq is then disabled by thread 1 whilst thread 2 enables the adc.
> Clearly the timeout will prevent any serious issues but the 2nd thread is going
> to falsely wait a second I think... ?
>   
Hm, right. I didn't thought of that. There can be multiple simultaneous
reads.
Actually there are multiple issues with concurrent reads from adcin pin,
I guess the whole function should be protected by a mutex.
And additionally the clock is not turned off in case of an error.

- Lars

From ralf@linux-mips.org Sun Jun  6 03:30:54 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sun, 06 Jun 2010 03:30:57 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:35533 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492229Ab0FFBay (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Sun, 6 Jun 2010 03:30:54 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o561U2nY006235;
        Sun, 6 Jun 2010 02:30:05 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o561Tx7J006233;
        Sun, 6 Jun 2010 02:29:59 +0100
Date:   Sun, 6 Jun 2010 02:29:59 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Andrew Morton <akpm@linux-foundation.org>
Cc:     Kevin Cernekee <cernekee@gmail.com>, mingo@elte.hu,
        simon.kagstrom@netinsight.net, David.Woodhouse@intel.com,
        lethal@linux-sh.org, linux-kernel@vger.kernel.org,
        linux-mips@linux-mips.org
Subject: Re: [PATCH v3] printk: fix delayed messages from CPU hotplug events
Message-ID: <20100606012958.GA6169@linux-mips.org>
References: <ee1bf4f9c158983acad0a4548229586128afad67@localhost>
 <20100603225824.8de77fba.akpm@linux-foundation.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20100603225824.8de77fba.akpm@linux-foundation.org>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27080
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4084
Content-Length: 354
Lines: 12

On Thu, Jun 03, 2010 at 10:58:24PM -0700, Andrew Morton wrote:

Assuming everybody is happy now I've merged Andrew's patch into Kevin's
patch and dropped it into the linux-queue tree and my tree for -next.
If nobody objects I intend to send the patch to Linus in about a week
or so.

Andrew, your patch had no Signed-off-by ;-)

Thanks everbody,

  Ralf

From ralf@linux-mips.org Sun Jun  6 03:35:18 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sun, 06 Jun 2010 03:35:23 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:54854 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492229Ab0FFBfS (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Sun, 6 Jun 2010 03:35:18 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o561Z5W6006333;
        Sun, 6 Jun 2010 02:35:05 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o561Z5X1006331;
        Sun, 6 Jun 2010 02:35:05 +0100
Date:   Sun, 6 Jun 2010 02:35:05 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     Andrew Morton <akpm@linux-foundation.org>
Cc:     Kevin Cernekee <cernekee@gmail.com>, mingo@elte.hu,
        simon.kagstrom@netinsight.net, David.Woodhouse@intel.com,
        lethal@linux-sh.org, linux-kernel@vger.kernel.org,
        linux-mips@linux-mips.org
Subject: [PATCH v4] printk: fix delayed messages from CPU hotplug events
Message-ID: <20100606013505.GB6169@linux-mips.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27081
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4086
Content-Length: 3309
Lines: 106

From:   Kevin Cernekee <cernekee@gmail.com>

printk: fix delayed messages from CPU hotplug events

When a secondary CPU is being brought up, it is not uncommon for
printk() to be invoked when cpu_online(smp_processor_id()) == 0.  The
case that I witnessed personally was on MIPS:

http://lkml.org/lkml/2010/5/30/4

If (can_use_console() == 0), printk() will spool its output to log_buf
and it will be visible in "dmesg", but that output will NOT be echoed to
the console until somebody calls release_console_sem() from a CPU that
is online.  Therefore, the boot time messages from the new CPU can get
stuck in "limbo" for a long time, and might suddenly appear on the
screen when a completely unrelated event (e.g. "eth0: link is down")
occurs.

This patch modifies the console code so that any pending messages are
automatically flushed out to the console whenever a CPU hotplug
operation completes successfully or aborts.

The issue was seen on 2.6.34.

[Ralf: Cleanup patch posted by akpm merged into the patch]

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
To: <mingo@elte.hu>
To: <akpm@linux-foundation.org>
To: <simon.kagstrom@netinsight.net>
To: <David.Woodhouse@intel.com>
To: <lethal@linux-sh.org>
Cc: <linux-kernel@vger.kernel.org>
Cc: <linux-mips@linux-mips.org>
Patchwork: http://patchwork.linux-mips.org/patch/1355/
Reviewed-by: Paul Mundt <lethal@linux-sh.org>
Patchwork: http://patchwork.linux-mips.org/patch/1356/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

 kernel/printk.c |   30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

Index: linux-queue/kernel/printk.c
===================================================================
--- linux-queue.orig/kernel/printk.c
+++ linux-queue/kernel/printk.c
@@ -37,6 +37,8 @@
 #include <linux/ratelimit.h>
 #include <linux/kmsg_dump.h>
 #include <linux/syslog.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 
@@ -985,6 +987,29 @@ void resume_console(void)
 }
 
 /**
+ * console_cpu_notify - print deferred console messages after CPU hotplug
+ * @self: notifier struct
+ * @action: CPU hotplug event
+ * @hcpu: unused
+ *
+ * If printk() is called from a CPU that is not online yet, the messages
+ * will be spooled but will not show up on the console.  This function is
+ * called when a new CPU comes online (or fails to come up), and ensures
+ * that any such output gets printed.
+ */
+static int __cpuinit console_cpu_notify(struct notifier_block *self,
+	unsigned long action, void *hcpu)
+{
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_UP_CANCELED:
+		acquire_console_sem();
+		release_console_sem();
+	}
+	return NOTIFY_OK;
+}
+
+/**
  * acquire_console_sem - lock the console system for exclusive use.
  *
  * Acquires a semaphore which guarantees that the caller has
@@ -1371,7 +1396,7 @@ int unregister_console(struct console *c
 }
 EXPORT_SYMBOL(unregister_console);
 
-static int __init disable_boot_consoles(void)
+static int __init printk_late_init(void)
 {
 	struct console *con;
 
@@ -1382,9 +1407,10 @@ static int __init disable_boot_consoles(
 			unregister_console(con);
 		}
 	}
+	hotcpu_notifier(console_cpu_notify, 0);
 	return 0;
 }
-late_initcall(disable_boot_consoles);
+late_initcall(printk_late_init);
 
 #if defined CONFIG_PRINTK
 

From macro@linux-mips.org Sun Jun  6 23:19:17 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Sun, 06 Jun 2010 23:19:22 +0200 (CEST)
Received: from localhost.localdomain ([127.0.0.1]:60373 "EHLO
        localhost.localdomain" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492372Ab0FFVTR (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Sun, 6 Jun 2010 23:19:17 +0200
Date:   Sun, 6 Jun 2010 22:19:17 +0100 (BST)
From:   "Maciej W. Rozycki" <macro@linux-mips.org>
To:     Ralf Baechle <ralf@linux-mips.org>
cc:     adnan iqbal <adnan.iqbal@seecs.edu.pk>, linux-mips@linux-mips.org
Subject: Re: Details of MIPS(Octeon) system call semantics
In-Reply-To: <20100602133809.GA13625@linux-mips.org>
Message-ID: <alpine.LFD.2.00.1006062144490.20820@eddie.linux-mips.org>
References: <AANLkTino_WFpj8aueN4zGwkRV-SCVqA5NGsKQOGU9qho@mail.gmail.com> <20100602133809.GA13625@linux-mips.org>
User-Agent: Alpine 2.00 (LFD 1167 2008-08-23)
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
X-archive-position: 27082
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: macro@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4340
Content-Length: 1375
Lines: 28

On Wed, 2 Jun 2010, Ralf Baechle wrote:

> In addition to normal subroutine calls:
> 
>  o $a3 on syscall return will indicate success or error.  0 means success,
>    non-zero means an error happened in which case $v0 will contain an
>    errno.h error code.
>  o Many syscalls deviate from this convention.  For example the sigreturn
>    family of syscalls doesn't return a result or error status.
>  o pipe() will return the 2nd filedescriptor of the result in $v1.
>  o vfork is even more weird.
>  o The ABI differences mean there are many subtle difference between the
>    syscall handlers.

 All of the above plus $v0 holds the syscall number upon entry -- which 
you may effectively consider the "zeroth argument" to the call (the code 
field of the SYSCALL instruction is not used by Linux).

 Also it is mandated by the syscall restart mechanism used by signal 
delivery code that it must be the instruction physically immediately 
preceding the SYSCALL operation that places the syscall number in $v0.  
In most cases a LI operation is used, but this is not a requirement (such 
as utilised by the syscall(3) library wrapper) as long as no temporary 
registers are used to obtain the value, because in the case of a restart 
these will have been clobbered by the syscall being restarted (so e.g. lw 
$v0, 0x100($fp) is fine, but move $v0, $a3 is not).

  Maciej

From macro@linux-mips.org Mon Jun  7 00:02:35 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 07 Jun 2010 00:02:39 +0200 (CEST)
Received: from localhost.localdomain ([127.0.0.1]:42581 "EHLO
        localhost.localdomain" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492262Ab0FFWCf (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Mon, 7 Jun 2010 00:02:35 +0200
Date:   Sun, 6 Jun 2010 23:02:35 +0100 (BST)
From:   "Maciej W. Rozycki" <macro@linux-mips.org>
To:     Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
cc:     linux-mips@linux-mips.org
Subject: Re: [Q] MIPS: How to record the user stack backtrace in the kernel
In-Reply-To: <AANLkTikRaw_OLR7LenUA8acaedJy2V6HZKJ0cAd6PNRk@mail.gmail.com>
Message-ID: <alpine.LFD.2.00.1006062256080.20820@eddie.linux-mips.org>
References: <AANLkTikRaw_OLR7LenUA8acaedJy2V6HZKJ0cAd6PNRk@mail.gmail.com>
User-Agent: Alpine 2.00 (LFD 1167 2008-08-23)
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
X-archive-position: 27083
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: macro@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4356
Content-Length: 733
Lines: 17

On Sat, 5 Jun 2010, Deng-Cheng Zhu wrote:

> In the kernel, we don't have frame unwinder to work on the user stack.
> Given the different possible compiler flags, getting the backtrace for the
> user stack is especially challenging. Certainly, I don't want symbols -
> only to get a list of return addresses. Do you have any comments?

 You can't do that, because, unlike some other platforms, MIPS ABIs do not 
use a fixed frame layout.  You need at least symbol information or, 
preferably, debug records to be able to construct a backtrace.  These can 
be attached to the ELF executables used and are not easily reachable from 
the kernel.

 What's the point anyway?  Just use GDB or other widely available user 
tools.

  Maciej

From yad.naveen@gmail.com Mon Jun  7 14:52:56 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 07 Jun 2010 14:53:03 +0200 (CEST)
Received: from mail-vw0-f49.google.com ([209.85.212.49]:33323 "EHLO
        mail-vw0-f49.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491054Ab0FGMw4 (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Mon, 7 Jun 2010 14:52:56 +0200
Received: by vws7 with SMTP id 7so5491124vws.36
        for <linux-mips@linux-mips.org>; Mon, 07 Jun 2010 05:52:48 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:mime-version:received:received:date:message-id
         :subject:from:to:content-type;
        bh=wD1GWUltj1NUjG05+EaxyP39pJsraWlm3yF4E14mMu0=;
        b=QJ10cErB+HV41uUnBRR4zawQ0CcEjK6BMdG7D1Wt1dqS6Utta/lIwuCikU3sozF7om
         LrYRLom5ylrD1fSm56dfNE99omA1WoHLNTL3+6Kl6TZwubPFt1B6ZJWK8G6ZHf7iIctL
         caSAKIj8qIuW8SNy1qbsoZxZDTmmt6i5m0d84=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=mime-version:date:message-id:subject:from:to:content-type;
        b=tzITshvZ9EHa81Ngq48ECx+MOIqPVoEip5nsA4p1M41annXDuTDMVn4BvnxqJmmk8X
         o+ZBww5sDV9reHbjXBwEpX3cI8NrQub5UnHekI4/84RtS7ITraIybbgYAjhZu2lygVZC
         hjfom5KHYixbY28btE0nt07pq4kDT17su6D5I=
MIME-Version: 1.0
Received: by 10.224.53.34 with SMTP id k34mr8487125qag.290.1275915167932; Mon, 
        07 Jun 2010 05:52:47 -0700 (PDT)
Received: by 10.229.52.137 with HTTP; Mon, 7 Jun 2010 05:52:47 -0700 (PDT)
Date:   Mon, 7 Jun 2010 18:22:47 +0530
Message-ID: <AANLkTimKPVhpBzKehbm9MAzYJ4rewsQ1kSRrw8Bw8B7i@mail.gmail.com>
Subject: info needed for check_bugs
From:   naveen yadav <yad.naveen@gmail.com>
To:     linux-mips@linux-mips.org, kernelnewbies@nl.linux.org
Content-Type: text/plain; charset=ISO-8859-1
X-archive-position: 27084
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: yad.naveen@gmail.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4733
Content-Length: 719
Lines: 34

Hi all ,

I am porting 2.6.30.9 to MIPS target. The target boot well, but when
it reaches to check_bugs() function.
static inline void check_bugs(void)
{
	unsigned int cpu ;
	cpu = smp_processor_id();
	cpu_data[cpu].udelay_val = loops_per_jiffy;
	check_bugs32();
#ifdef CONFIG_64BIT
	check_bugs64();
#endif
}

the debug outupt print to screen become very slow. kernel boots but it
print one char in 1 min.

When i change above function as

static inline void check_bugs(void)
{
	unsigned int cpu ;
	cpu = smp_processor_id();
	//cpu_data[cpu].udelay_val = loops_per_jiffy;
	check_bugs32();
#ifdef CONFIG_64BIT
	check_bugs64();
#endif
}

it works fine. Is there any side effect with this. ?

or how can i fix this issue.

From ralf@linux-mips.org Mon Jun  7 15:27:07 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 07 Jun 2010 15:27:13 +0200 (CEST)
Received: from h5.dl5rb.org.uk ([81.2.74.5]:36027 "EHLO h5.dl5rb.org.uk"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP
        id S1492432Ab0FGN1H (ORCPT <rfc822;linux-mips@linux-mips.org>);
        Mon, 7 Jun 2010 15:27:07 +0200
Received: from h5.dl5rb.org.uk (localhost.localdomain [127.0.0.1])
        by h5.dl5rb.org.uk (8.14.3/8.14.3) with ESMTP id o57DR3Ut017708;
        Mon, 7 Jun 2010 14:27:04 +0100
Received: (from ralf@localhost)
        by h5.dl5rb.org.uk (8.14.3/8.14.3/Submit) id o57DR15D017706;
        Mon, 7 Jun 2010 14:27:01 +0100
Date:   Mon, 7 Jun 2010 14:27:01 +0100
From:   Ralf Baechle <ralf@linux-mips.org>
To:     naveen yadav <yad.naveen@gmail.com>
Cc:     linux-mips@linux-mips.org, kernelnewbies@nl.linux.org
Subject: Re: info needed for check_bugs
Message-ID: <20100607132701.GC728@linux-mips.org>
References: <AANLkTimKPVhpBzKehbm9MAzYJ4rewsQ1kSRrw8Bw8B7i@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <AANLkTimKPVhpBzKehbm9MAzYJ4rewsQ1kSRrw8Bw8B7i@mail.gmail.com>
User-Agent: Mutt/1.5.20 (2009-08-17)
X-archive-position: 27085
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ralf@linux-mips.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4762
Content-Length: 1292
Lines: 44

On Mon, Jun 07, 2010 at 06:22:47PM +0530, naveen yadav wrote:

> I am porting 2.6.30.9 to MIPS target. The target boot well, but when
> it reaches to check_bugs() function.
> static inline void check_bugs(void)
> {
> 	unsigned int cpu ;
> 	cpu = smp_processor_id();
> 	cpu_data[cpu].udelay_val = loops_per_jiffy;
> 	check_bugs32();
> #ifdef CONFIG_64BIT
> 	check_bugs64();
> #endif
> }
> 
> the debug outupt print to screen become very slow. kernel boots but it
> print one char in 1 min.
> 
> When i change above function as
> 
> static inline void check_bugs(void)
> {
> 	unsigned int cpu ;
> 	cpu = smp_processor_id();
> 	//cpu_data[cpu].udelay_val = loops_per_jiffy;
> 	check_bugs32();
> #ifdef CONFIG_64BIT
> 	check_bugs64();
> #endif
> }
> 
> it works fine. Is there any side effect with this. ?

I suggest to check that the value of cpu_data[cpu].udelay_va and of
loops_per_jiffy make sense.  It would appear that loops_per_jiffy is zero
on your system which would cause __delay() to loop 2^32 times.  If that
is the case, checkout the timer interrupt's frequency and the BogoMIPS
calibration.

You may also want to verify that your platform actually needs mdelay(),
udelay() or ndelay().  These calls should be considered a kludge for
broken hardware and avoided if possible.

  Ralf

From hschauhan@nulltrace.org Mon Jun  7 20:31:13 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 07 Jun 2010 20:31:16 +0200 (CEST)
Received: from mail-pv0-f177.google.com ([74.125.83.177]:41342 "EHLO
        mail-pv0-f177.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491930Ab0FGSbN (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Mon, 7 Jun 2010 20:31:13 +0200
Received: by pvg11 with SMTP id 11so1202448pvg.36
        for <multiple recipients>; Mon, 07 Jun 2010 11:31:02 -0700 (PDT)
Received: by 10.142.195.20 with SMTP id s20mr10990049wff.248.1275935462335;
        Mon, 07 Jun 2010 11:31:02 -0700 (PDT)
Received: from localhost.localdomain ([122.167.126.7])
        by mx.google.com with ESMTPS id 20sm3225963pzk.3.2010.06.07.11.30.59
        (version=SSLv3 cipher=RC4-MD5);
        Mon, 07 Jun 2010 11:31:01 -0700 (PDT)
From:   Himanshu Chauhan <hschauhan@nulltrace.org>
To:     ralf@linux-mips.org
Cc:     linux-kernel@vger.kernel.org, linux-mips@linux-mips.org,
        Himanshu Chauhan <hschauhan@nulltrace.org>
Subject: [PATCH] Kprobes support for MIPS architecture.
Date:   Mon,  7 Jun 2010 22:03:59 +0530
Message-Id: <1275928440-21052-1-git-send-email-hschauhan@nulltrace.org>
X-Mailer: git-send-email 1.7.0.4
X-archive-position: 27086
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: hschauhan@nulltrace.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4972
Content-Length: 977
Lines: 25

This is an initial draft of Kprobes support for MIPS architecture.
It is based on a patch series submitted on CELinux mailing list
from Sony for 2.6.16 series. Since then many things changed including
APIs and file paths. So this is essentially a patch replayed on
latest series.

Please review and provide your feedback.

Signed-off-by: Himanshu Chauhan <hschauhan@nulltrace.org>
---
Himanshu Chauhan (1):
  MIPS: KProbes support v0.1

 arch/mips/Kconfig               |   13 ++
 arch/mips/include/asm/kdebug.h  |    5 +
 arch/mips/include/asm/kprobes.h |   85 +++++++++
 arch/mips/kernel/Makefile       |    2 +
 arch/mips/kernel/genex.S        |    6 +
 arch/mips/kernel/kprobes.c      |  380 +++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/traps.c        |   40 ++++-
 arch/mips/mm/fault.c            |   11 +-
 8 files changed, 539 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/include/asm/kprobes.h
 create mode 100644 arch/mips/kernel/kprobes.c


From hschauhan@nulltrace.org Mon Jun  7 20:31:18 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 07 Jun 2010 20:31:43 +0200 (CEST)
Received: from mail-pz0-f197.google.com ([209.85.222.197]:45387 "EHLO
        mail-pz0-f197.google.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1492453Ab0FGSbS (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Mon, 7 Jun 2010 20:31:18 +0200
Received: by pzk35 with SMTP id 35so93412pzk.0
        for <multiple recipients>; Mon, 07 Jun 2010 11:31:11 -0700 (PDT)
Received: by 10.142.248.6 with SMTP id v6mr11121042wfh.262.1275935470874;
        Mon, 07 Jun 2010 11:31:10 -0700 (PDT)
Received: from localhost.localdomain ([122.167.126.7])
        by mx.google.com with ESMTPS id 20sm3225963pzk.3.2010.06.07.11.31.07
        (version=SSLv3 cipher=RC4-MD5);
        Mon, 07 Jun 2010 11:31:09 -0700 (PDT)
From:   Himanshu Chauhan <hschauhan@nulltrace.org>
To:     ralf@linux-mips.org
Cc:     linux-kernel@vger.kernel.org, linux-mips@linux-mips.org,
        Himanshu Chauhan <hschauhan@nulltrace.org>
Subject: [PATCH] MIPS: KProbes support v0.1
Date:   Mon,  7 Jun 2010 22:04:00 +0530
Message-Id: <1275928440-21052-2-git-send-email-hschauhan@nulltrace.org>
X-Mailer: git-send-email 1.7.0.4
In-Reply-To: <1275928440-21052-1-git-send-email-hschauhan@nulltrace.org>
References: <1275928440-21052-1-git-send-email-hschauhan@nulltrace.org>
X-archive-position: 27087
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: hschauhan@nulltrace.org
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 4974
Content-Length: 18710
Lines: 674

Signed-off-by: Himanshu Chauhan <hschauhan@nulltrace.org>

---
 arch/mips/Kconfig               |   13 ++
 arch/mips/include/asm/kdebug.h  |    5 +
 arch/mips/include/asm/kprobes.h |   85 +++++++++
 arch/mips/kernel/Makefile       |    2 +
 arch/mips/kernel/genex.S        |    6 +
 arch/mips/kernel/kprobes.c      |  380 +++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/traps.c        |   40 ++++-
 arch/mips/mm/fault.c            |   11 +-
 8 files changed, 539 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/include/asm/kprobes.h
 create mode 100644 arch/mips/kernel/kprobes.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index cdaae94..ba7cc87 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2243,6 +2243,19 @@ source "kernel/power/Kconfig"
 
 endmenu
 
+menu "Instrumentation Support"
+
+config KPROBES
+       bool "MIPS Kprobes Support (Experimental)"
+       depends on EXPERIMENTAL && MODULES
+       help
+	  Kprobes allow you to trap at almost any kernel address
+	  and execute a callback function. Kprobes is useful for
+	  kernel debugging, non-intrusive instrumetation and testing.
+	  If in doubt, say N.
+
+endmenu
+
 source "arch/mips/kernel/cpufreq/Kconfig"
 
 source "net/Kconfig"
diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h
index 5bf62aa..52818ac 100644
--- a/arch/mips/include/asm/kdebug.h
+++ b/arch/mips/include/asm/kdebug.h
@@ -8,6 +8,11 @@ enum die_val {
 	DIE_FP,
 	DIE_TRAP,
 	DIE_RI,
+#ifdef CONFIG_KPROBES
+	DIE_PAGE_FAULT,
+	DIE_BREAK,
+	DIE_SSTEPBP,
+#endif
 };
 
 #endif /* _ASM_MIPS_KDEBUG_H */
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
new file mode 100644
index 0000000..0f647bf
--- /dev/null
+++ b/arch/mips/include/asm/kprobes.h
@@ -0,0 +1,85 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  include/asm-mips/kprobes.h
+ *
+ *  Copyright 2006 Sony Corp.
+ *
+ *  Himanshu Chauhan <hschauhan@nulltrace.org>
+ *  for >2.6.35 kernels.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _ASM_KPROBES_H
+#define _ASM_KPROBES_H
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/inst.h>
+
+#define  __ARCH_WANT_KPROBES_INSN_SLOT
+
+struct kprobe;
+struct pt_regs;
+
+typedef union mips_instruction kprobe_opcode_t;
+
+#define BREAKPOINT_INSTRUCTION		0x0000000d
+
+/* 
+ * We do not have hardware single-stepping on MIPS.
+ * So we implement software single-stepping with breakpoint
+ * trap 'break 5'.
+ */
+#define BREAKPOINT_INSTRUCTION_2	0x0000014d
+#define MAX_INSN_SIZE 			2
+
+#define flush_insn_slot(p)		do { \
+        /* invalidate I-cache */             \
+        asm volatile("cache 0, 0($0)");      \
+        /* invalidate D-cache */             \
+        asm volatile("cache 9, 0($0)");      \
+        } while(0);
+
+#define kretprobe_blacklist_size	0
+
+void arch_remove_kprobe(struct kprobe *p);
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+	/* copy of the original instruction */
+	kprobe_opcode_t *insn;
+};
+
+struct prev_kprobe {
+	struct kprobe *kp;
+	unsigned long status;
+	unsigned long old_SR;
+	unsigned long saved_SR;
+	unsigned long saved_epc;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+	unsigned long kprobe_status;
+	unsigned long kprobe_old_SR;
+	unsigned long kprobe_saved_SR;
+	unsigned long kprobe_saved_epc;
+	struct prev_kprobe prev_kprobe;
+};
+
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+				    unsigned long val, void *data);
+
+#endif				/* _ASM_KPROBES_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 7a6ac50..714f3c1 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_MIPS32_N32)	+= binfmt_elfn32.o scall64-n32.o signal_n32.o
 obj-$(CONFIG_MIPS32_O32)	+= binfmt_elfo32.o scall64-o32.o
 
 obj-$(CONFIG_KGDB)		+= kgdb.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PROC_FS)		+= proc.o
 
 obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
@@ -95,6 +96,7 @@ obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
 
+
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+= 8250-platform.o
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 8882e57..e53ac80 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -450,7 +450,13 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	BUILD_HANDLER ades ade ade silent		/* #5  */
 	BUILD_HANDLER ibe be cli silent			/* #6  */
 	BUILD_HANDLER dbe be cli silent			/* #7  */
+#ifndef CONFIG_KPROBES
+	/* call do_bp if bp hit and kprobes not configured */
 	BUILD_HANDLER bp bp sti silent			/* #9  */
+#else
+	/* call do_break if bp hit and kprobes are configured */
+	BUILD_HANDLER bp break sti silent		/* #9  */
+#endif
 	BUILD_HANDLER ri ri sti silent			/* #10 */
 	BUILD_HANDLER cpu cpu sti silent		/* #11 */
 	BUILD_HANDLER ov ov sti silent			/* #12 */
diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c
new file mode 100644
index 0000000..0493791
--- /dev/null
+++ b/arch/mips/kernel/kprobes.c
@@ -0,0 +1,380 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  arch/mips/kernel/kprobes.c
+ *
+ *  Copyright 2006 Sony Corp.
+ *
+ *  Himanshu Chauhan <hschauhan@nulltrace.org> for >2.6.35 kernels.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/semaphore.h>
+#include <linux/kdebug.h>
+#include <linux/kprobes.h>
+#include <linux/preempt.h>
+#include <asm/cacheflush.h>
+#include <asm/inst.h>
+#include <asm/ptrace.h>
+
+DECLARE_MUTEX(kprobe_mutex);
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+	union mips_instruction insn;
+	int ret = 0;
+
+	insn = *p->addr;
+
+	switch (insn.i_format.opcode) {
+		/*
+		 * This group contains:
+		 * jr and jalr are in r_format format.
+		 */
+	case spec_op:
+
+		/*
+		 * This group contains:
+		 * bltz_op, bgez_op, bltzl_op, bgezl_op,
+		 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+		 */
+	case bcond_op:
+
+		/*
+		 * These are unconditional and in j_format.
+		 */
+	case jal_op:
+	case j_op:
+
+		/*
+		 * These are conditional and in i_format.
+		 */
+	case beq_op:
+	case beql_op:
+	case bne_op:
+	case bnel_op:
+	case blez_op:
+	case blezl_op:
+	case bgtz_op:
+	case bgtzl_op:
+		/*
+		 * These are the FPA/cp1 branch instructions.
+		 */
+	case cop1_op:
+		printk("Kprobes for branch and jump instructions "
+		       "is not supported\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* insn: must be on special executable page on MIPS. */
+	p->ainsn.insn = get_insn_slot();
+	if (!p->ainsn.insn) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * In the kprobe->ainsn.insn[] array we store the original
+	 * instruction at index zero and a break trap instruction at
+	 * index one.
+	 */
+
+	memcpy(&p->ainsn.insn[0], p->addr, sizeof(kprobe_opcode_t));
+	p->ainsn.insn[1].word = BREAKPOINT_INSTRUCTION_2;
+	p->opcode = *p->addr;
+
+out:
+	return ret;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+	p->addr->word = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long)p->addr,
+			   (unsigned long)p->addr +
+			   (MAX_INSN_SIZE * sizeof(kprobe_opcode_t)));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+	flush_icache_range((unsigned long)p->addr,
+			   (unsigned long)p->addr +
+			   (MAX_INSN_SIZE * sizeof(kprobe_opcode_t)));
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+	down(&kprobe_mutex);
+	free_insn_slot(p->ainsn.insn, 0);
+	up(&kprobe_mutex);
+}
+
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	kcb->prev_kprobe.old_SR = kcb->kprobe_old_SR;
+	kcb->prev_kprobe.saved_SR = kcb->kprobe_saved_SR;
+	kcb->prev_kprobe.saved_epc = kcb->kprobe_saved_epc;
+}
+
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->kprobe_old_SR = kcb->prev_kprobe.old_SR;
+	kcb->kprobe_saved_SR = kcb->prev_kprobe.saved_SR;
+	kcb->kprobe_saved_epc = kcb->prev_kprobe.saved_epc;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+				      struct kprobe_ctlblk *kcb)
+{
+	__get_cpu_var(current_kprobe) = p;
+	kcb->kprobe_saved_SR = kcb->kprobe_old_SR = (regs->cp0_status & ST0_IE);
+	kcb->kprobe_saved_epc = regs->cp0_epc;
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->cp0_status &= ~ST0_IE;
+
+	/* single step inline if the instruction is an break 0 */
+	if ((MIPSInst_OPCODE(p->opcode.word) == BREAKPOINT_INSTRUCTION)
+	    || (MIPSInst_OPCODE(p->opcode.word) == BREAKPOINT_INSTRUCTION_2))
+		regs->cp0_epc = (unsigned long)p->addr;
+	else
+		regs->cp0_epc = (unsigned long)&p->ainsn.insn[0];
+}
+
+static int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *p;
+	int ret = 0;
+	kprobe_opcode_t *addr = NULL;
+	struct kprobe_ctlblk *kcb;
+
+	addr = (kprobe_opcode_t *) regs->cp0_epc;
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+	preempt_disable();
+	kcb = get_kprobe_ctlblk();
+
+	/* Check we're not actually recursing */
+	if (kprobe_running()) {
+		p = get_kprobe(addr);
+		if (p) {
+			if (kcb->kprobe_status == KPROBE_HIT_SS &&
+			    p->ainsn.insn->word == BREAKPOINT_INSTRUCTION) {
+				regs->cp0_status &= ~ST0_IE;
+				regs->cp0_status |= kcb->kprobe_saved_SR;
+				goto no_kprobe;
+			}
+			/* We have reentered the kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, regs, kcb);
+			kprobes_inc_nmissed_count(p);
+			prepare_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_REENTER;
+			return 1;
+		} else {
+			if (addr->word != BREAKPOINT_INSTRUCTION) {
+				/* The breakpoint instruction was removed by
+				 * another cpu right after we hit, no further
+				 * handling of this interrupt is appropriate
+				 */
+				ret = 1;
+				goto no_kprobe;
+			}
+			p = __get_cpu_var(current_kprobe);
+			if (p->break_handler && p->break_handler(p, regs)) {
+				goto ss_probe;
+			}
+		}
+		goto no_kprobe;
+	}
+
+	p = get_kprobe(addr);
+	if (!p) {
+		if (addr->word != BREAKPOINT_INSTRUCTION) {
+			/*
+			 * The breakpoint instruction was removed right
+			 * after we hit it.  Another cpu has removed
+			 * either a probepoint or a debugger breakpoint
+			 * at this address.  In either case, no further
+			 * handling of this interrupt is appropriate.
+			 */
+			ret = 1;
+		}
+		/* Not one of ours: let kernel handle it */
+		goto no_kprobe;
+	}
+
+	set_current_kprobe(p, regs, kcb);
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+	if (p->pre_handler && p->pre_handler(p, regs))
+		/* handler has already set things up, so skip ss setup */
+		return 1;
+
+ss_probe:
+	prepare_singlestep(p, regs);
+	kcb->kprobe_status = KPROBE_HIT_SS;
+	return 1;
+
+no_kprobe:
+	preempt_enable_no_resched();
+	return ret;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the "break 0"
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->ainsn.insn.
+ *
+ * This function prepares to return from the post-single-step
+ * breakpoint trap.
+ */
+static void __kprobes resume_execution(struct kprobe *p,
+				       struct pt_regs *regs,
+				       struct kprobe_ctlblk *kcb)
+{
+	unsigned long orig_epc = kcb->kprobe_saved_epc;
+	regs->cp0_epc = orig_epc + 4;
+}
+
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
+		return 0;
+
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
+	}
+
+	resume_execution(cur, regs, kcb);
+
+	regs->cp0_status |= kcb->kprobe_saved_SR;
+
+	/* Restore back the original saved kprobes variables and continue. */
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
+		goto out;
+	}
+	reset_current_kprobe();
+out:
+	preempt_enable_no_resched();
+
+	return 1;
+}
+
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+		return 1;
+
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs, kcb);
+		regs->cp0_status |= kcb->kprobe_old_SR;
+
+		reset_current_kprobe();
+		preempt_enable_no_resched();
+	}
+	return 0;
+}
+
+/*
+ * Wrapper routine for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+				       unsigned long val, void *data)
+{
+	struct die_args *args = (struct die_args *)data;
+        struct pt_regs *regs = (struct pt_regs *)args->regs;
+	int ret = NOTIFY_DONE;
+	int trapnr = 0;
+
+	switch (val) {
+	case DIE_BREAK:
+                ret = kprobe_handler(regs);
+		if (ret)
+			ret = NOTIFY_STOP;
+		break;
+	case DIE_SSTEPBP:
+		if (post_kprobe_handler(args->regs))
+			ret = NOTIFY_STOP;
+		break;
+
+	case DIE_PAGE_FAULT:
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
+
+		/*
+		 * trapnr is the architecture-specific trap
+		 * number associated with the fault while handling
+		 * the Kprobe (e.g. on mips, 9 for a break or 13 for
+		 * a trap).
+		 * current die_args structure does not have trapnr.
+		 */
+		if (kprobe_running()
+		    && kprobe_fault_handler(args->regs, trapnr))
+			ret = NOTIFY_STOP;
+		preempt_enable();
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	return 0;
+}
+
+void __kprobes jprobe_return(void)
+{
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	return 0;
+}
+
+int __init arch_init_kprobes(void)
+{
+	return 0;
+}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 8bdd6a6..f6b4b41 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -27,6 +27,7 @@
 #include <linux/kdebug.h>
 #include <linux/notifier.h>
 #include <linux/kdb.h>
+#include <linux/kprobes.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -334,7 +335,7 @@ void show_regs(struct pt_regs *regs)
 	__show_regs((struct pt_regs *)regs);
 }
 
-void show_registers(const struct pt_regs *regs)
+void show_registers(struct pt_regs *regs)
 {
 	const int field = 2 * sizeof(unsigned long);
 
@@ -790,6 +791,43 @@ out_sigsegv:
 	force_sig(SIGSEGV, current);
 }
 
+#ifdef CONFIG_KPROBES
+asmlinkage void __kprobes do_break (struct pt_regs *regs)
+{
+	unsigned int opcode, bcode;
+
+	opcode = *(unsigned long *)(regs->cp0_epc);
+
+	bcode = ((opcode >> 6) & ((1 << 20) - 1));
+	if (bcode < (1 << 10))
+		bcode <<= 10;
+
+	/*
+	 * notify the kprobe handlers,if instruction is break 0 or break 5
+	 */
+	switch (bcode) {
+	case BRK_USERBP << 10:
+		if (notify_die(DIE_BREAK, "debug", regs, bcode, 0, 0) == NOTIFY_STOP)
+			return;
+		else
+			break;
+	case BRK_SSTEPBP << 10:
+		if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, 0, 0) == NOTIFY_STOP)
+			return;
+		else
+			break;
+	default:
+		break;
+	}
+
+	/*
+	 * If the bcode is other than 0 and 5, then call the normal
+	 * break handler do_bp()
+	 */
+	do_bp(regs);
+}
+#endif
+
 asmlinkage void do_tr(struct pt_regs *regs)
 {
 	unsigned int opcode, tcode = 0;
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index b78f7d9..86e2d27 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -18,6 +18,8 @@
 #include <linux/smp.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>		/* notify_die and asm/kdebug.h */
 
 #include <asm/branch.h>
 #include <asm/mmu_context.h>
@@ -31,8 +33,8 @@
  * and the problem, and then passes it off to one of the appropriate
  * routines.
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
-			      unsigned long address)
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long write,
+                                        unsigned long address)
 {
 	struct vm_area_struct * vma = NULL;
 	struct task_struct *tsk = current;
@@ -47,6 +49,11 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
 	       field, regs->cp0_epc);
 #endif
 
+	/* Notify kprobes fault handler. */
+        if (notify_die(DIE_PAGE_FAULT, "page fault",
+                       regs, -1, SEGV_MAPERR, SEGV_MAPERR) == NOTIFY_STOP)
+                return;
+
 	info.si_code = SEGV_MAPERR;
 
 	/*
-- 
1.7.0.4


From ddaney@caviumnetworks.com Mon Jun  7 21:42:01 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 07 Jun 2010 21:42:05 +0200 (CEST)
Received: from mail3.caviumnetworks.com ([12.108.191.235]:4127 "EHLO
        mail3.caviumnetworks.com" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491930Ab0FGTmB (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Mon, 7 Jun 2010 21:42:01 +0200
Received: from caexch01.caveonetworks.com (Not Verified[192.168.16.9]) by mail3.caviumnetworks.com with MailMarshal (v6,7,2,8378)
        id <B4c0d4b970000>; Mon, 07 Jun 2010 12:42:15 -0700
Received: from caexch01.caveonetworks.com ([192.168.16.9]) by caexch01.caveonetworks.com with Microsoft SMTPSVC(6.0.3790.4675);
         Mon, 7 Jun 2010 12:41:55 -0700
Received: from dd1.caveonetworks.com ([12.108.191.236]) by caexch01.caveonetworks.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675);
         Mon, 7 Jun 2010 12:41:55 -0700
Message-ID: <4C0D4B82.6020002@caviumnetworks.com>
Date:   Mon, 07 Jun 2010 12:41:54 -0700
From:   David Daney <ddaney@caviumnetworks.com>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100330 Fedora/3.0.4-1.fc12 Thunderbird/3.0.4
MIME-Version: 1.0
To:     Himanshu Chauhan <hschauhan@nulltrace.org>
CC:     ralf@linux-mips.org, linux-kernel@vger.kernel.org,
        linux-mips@linux-mips.org
Subject: Re: [PATCH] MIPS: KProbes support v0.1
References: <1275928440-21052-1-git-send-email-hschauhan@nulltrace.org> <1275928440-21052-2-git-send-email-hschauhan@nulltrace.org>
In-Reply-To: <1275928440-21052-2-git-send-email-hschauhan@nulltrace.org>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
X-OriginalArrivalTime: 07 Jun 2010 19:41:55.0012 (UTC) FILETIME=[7BECD840:01CB0679]
X-archive-position: 27088
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: ddaney@caviumnetworks.com
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 5069
Content-Length: 7183
Lines: 265

I have a few questions and comments below.  Many of them  may be due to 
my lack of understanding about the internals of KProbes.

David Daney.


On 06/07/2010 09:34 AM, Himanshu Chauhan wrote:
[...]
> diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h
> index 5bf62aa..52818ac 100644
> --- a/arch/mips/include/asm/kdebug.h
> +++ b/arch/mips/include/asm/kdebug.h
> @@ -8,6 +8,11 @@ enum die_val {
>   	DIE_FP,
>   	DIE_TRAP,
>   	DIE_RI,
> +#ifdef CONFIG_KPROBES
> +	DIE_PAGE_FAULT,
> +	DIE_BREAK,
> +	DIE_SSTEPBP,
> +#endif
>   };
>

It might be cleaner without the #ifdef.  These are enum value 
definitions, so it doesn't affect code size.


Can you also explain how the die notifier chain interacts with KProbes 
and why it cannot be a seperate notifier chain?

>   #endif /* _ASM_MIPS_KDEBUG_H */
> diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
> new file mode 100644
> index 0000000..0f647bf
> --- /dev/null
> +++ b/arch/mips/include/asm/kprobes.h
> @@ -0,0 +1,85 @@
[...]
> +
> +#define BREAKPOINT_INSTRUCTION		0x0000000d
> +
> +/*
> + * We do not have hardware single-stepping on MIPS.
> + * So we implement software single-stepping with breakpoint
> + * trap 'break 5'.
> + */
> +#define BREAKPOINT_INSTRUCTION_2	0x0000014d

The BREAK codes are defined in asm/break.h  This should be added there 
instead.

Why do you use codes (0 and 5) that are already kind of reserved for 
user space debuggers?

> +#define MAX_INSN_SIZE 			2
> +
> +#define flush_insn_slot(p)		do { \
> +        /* invalidate I-cache */             \
> +        asm volatile("cache 0, 0($0)");      \
> +        /* invalidate D-cache */             \
> +        asm volatile("cache 9, 0($0)");      \
> +        } while(0);
> +

You have to call a function in arch/mips/mm/c-* to do this, you cannot 
open code with CACHE instructions as you need to handle CPU quirks and 
SMP.  It is possible that flush_icache_range() or flush_cache_sigtramp() 
would work.  Or we might need something new.

I see you use flush_icache_range() below, why have this definition, it 
looks unused?


[...]
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 8882e57..e53ac80 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -450,7 +450,13 @@ NESTED(nmi_handler, PT_SIZE, sp)
>   	BUILD_HANDLER ades ade ade silent		/* #5  */
>   	BUILD_HANDLER ibe be cli silent			/* #6  */
>   	BUILD_HANDLER dbe be cli silent			/* #7  */
> +#ifndef CONFIG_KPROBES
> +	/* call do_bp if bp hit and kprobes not configured */
>   	BUILD_HANDLER bp bp sti silent			/* #9  */
> +#else
> +	/* call do_break if bp hit and kprobes are configured */
> +	BUILD_HANDLER bp break sti silent		/* #9  */
> +#endif

Why this ugliness?  Can't you handle it in do_bp() or  do_trap_or_bp()?


>   	BUILD_HANDLER ri ri sti silent			/* #10 */
>   	BUILD_HANDLER cpu cpu sti silent		/* #11 */
>   	BUILD_HANDLER ov ov sti silent			/* #12 */
> diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c
> new file mode 100644
> index 0000000..0493791
> --- /dev/null
> +++ b/arch/mips/kernel/kprobes.c
> @@ -0,0 +1,380 @@
[...]
> +
> +int __kprobes arch_prepare_kprobe(struct kprobe *p)
> +{
> +	union mips_instruction insn;
> +	int ret = 0;
> +
> +	insn = *p->addr;
> +
> +	switch (insn.i_format.opcode) {
> +		/*
> +		 * This group contains:
> +		 * jr and jalr are in r_format format.
> +		 */
> +	case spec_op:
> +
> +		/*
> +		 * This group contains:
> +		 * bltz_op, bgez_op, bltzl_op, bgezl_op,
> +		 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
> +		 */
> +	case bcond_op:
> +
> +		/*
> +		 * These are unconditional and in j_format.
> +		 */
> +	case jal_op:
> +	case j_op:
> +
> +		/*
> +		 * These are conditional and in i_format.
> +		 */
> +	case beq_op:
> +	case beql_op:
> +	case bne_op:
> +	case bnel_op:
> +	case blez_op:
> +	case blezl_op:
> +	case bgtz_op:
> +	case bgtzl_op:

Need to add or otherwise handle:


#ifdef CONFIG_CPU_CAVIUM_OCTEON
	case lwc2_op: /* This is bbit0 on Octeon */
	case ldc2_op: /* This is bbit032 on Octeon */
	case swc2_op: /* This is bbit1 on Octeon */
	case sdc2_op: /* This is bbit132 on Octeon */
#endif


[...]

> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 8bdd6a6..f6b4b41 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -27,6 +27,7 @@
>   #include<linux/kdebug.h>
>   #include<linux/notifier.h>
>   #include<linux/kdb.h>
> +#include<linux/kprobes.h>
>
>   #include<asm/bootinfo.h>
>   #include<asm/branch.h>
> @@ -334,7 +335,7 @@ void show_regs(struct pt_regs *regs)
>   	__show_regs((struct pt_regs *)regs);
>   }
>
> -void show_registers(const struct pt_regs *regs)
> +void show_registers(struct pt_regs *regs)
>   {
>   	const int field = 2 * sizeof(unsigned long);
>
> @@ -790,6 +791,43 @@ out_sigsegv:
>   	force_sig(SIGSEGV, current);
>   }
>
> +#ifdef CONFIG_KPROBES
> +asmlinkage void __kprobes do_break (struct pt_regs *regs)
> +{
> +	unsigned int opcode, bcode;
> +
> +	opcode = *(unsigned long *)(regs->cp0_epc);
> +
> +	bcode = ((opcode>>  6)&  ((1<<  20) - 1));
> +	if (bcode<  (1<<  10))
> +		bcode<<= 10;
> +
> +	/*
> +	 * notify the kprobe handlers,if instruction is break 0 or break 5
> +	 */
> +	switch (bcode) {
> +	case BRK_USERBP<<  10:
> +		if (notify_die(DIE_BREAK, "debug", regs, bcode, 0, 0) == NOTIFY_STOP)
> +			return;
> +		else
> +			break;
> +	case BRK_SSTEPBP<<  10:
> +		if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, 0, 0) == NOTIFY_STOP)
> +			return;
> +		else
> +			break;
> +	default:
> +		break;
> +	}
> +


This should be folded into do_bp().



> +	/*
> +	 * If the bcode is other than 0 and 5, then call the normal
> +	 * break handler do_bp()
> +	 */
> +	do_bp(regs);
> +}
> +#endif
> +
>   asmlinkage void do_tr(struct pt_regs *regs)
>   {
>   	unsigned int opcode, tcode = 0;
> diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
> index b78f7d9..86e2d27 100644
> --- a/arch/mips/mm/fault.c
> +++ b/arch/mips/mm/fault.c
> @@ -18,6 +18,8 @@
>   #include<linux/smp.h>
>   #include<linux/vt_kern.h>		/* For unblank_screen() */
>   #include<linux/module.h>
> +#include<linux/kprobes.h>
> +#include<linux/kdebug.h>		/* notify_die and asm/kdebug.h */
>
>   #include<asm/branch.h>
>   #include<asm/mmu_context.h>
> @@ -31,8 +33,8 @@
>    * and the problem, and then passes it off to one of the appropriate
>    * routines.
>    */
> -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
> -			      unsigned long address)
> +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long write,
> +                                        unsigned long address)
>   {
>   	struct vm_area_struct * vma = NULL;
>   	struct task_struct *tsk = current;
> @@ -47,6 +49,11 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
>   	       field, regs->cp0_epc);
>   #endif
>
> +	/* Notify kprobes fault handler. */
> +        if (notify_die(DIE_PAGE_FAULT, "page fault",
> +                       regs, -1, SEGV_MAPERR, SEGV_MAPERR) == NOTIFY_STOP)
> +                return;
> +
>   	info.si_code = SEGV_MAPERR;
>
>   	/*


From mips@waldemar-brodkorb.de Tue Jun  8 19:06:07 2010
Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 08 Jun 2010 19:06:11 +0200 (CEST)
Received: from waldemar-brodkorb.de ([81.169.141.189]:6022 "EHLO
        helium.waldemar-brodkorb.de" rhost-flags-OK-OK-OK-OK)
        by eddie.linux-mips.org with ESMTP id S1491962Ab0FHRGH (ORCPT
        <rfc822;linux-mips@linux-mips.org>); Tue, 8 Jun 2010 19:06:07 +0200
Received: by helium.waldemar-brodkorb.de (Postfix, from userid 1000)
        id 6FE588B90F; Tue,  8 Jun 2010 19:06:01 +0200 (CEST)
Date:   Tue, 8 Jun 2010 19:06:01 +0200
From:   Waldemar Brodkorb <mips@waldemar-brodkorb.de>
To:     linux-mips@linux-mips.org
Cc:     Hauke Mehrtens <hauke@hauke-m.de>
Subject: [PATCH] MIPS: Add NVRAM support for bcm47xx devices
Message-ID: <20100608170601.GA8537@waldemar-brodkorb.de>
Reply-To: Waldemar Brodkorb <mips@waldemar-brodkorb.de>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
X-Operating-System: OpenBSD 4.5 amd64
User-Agent: Mutt/1.5.18 (2008-05-17)
X-archive-position: 27089
X-ecartis-version: Ecartis v1.0.0
Sender: linux-mips-bounce@linux-mips.org
Errors-to: linux-mips-bounce@linux-mips.org
X-original-sender: mips@waldemar-brodkorb.de
Precedence: bulk
X-list: linux-mips
Return-Path: <linux-mips-bounce@linux-mips.org>
X-Keywords:                 
X-UID: 5721
Content-Length: 8853
Lines: 266

When trying to netboot a Linksys WRT54GS WLAN router, the bootup fails,
because of following error message:

...
[    0.424000] b44: b44.c:v2.0
[    0.424000] b44: Invalid MAC address found in EEPROM
[    0.432000] b44 ssb0:1: Problem fetching invariants of chip,aborting
[    0.436000] b44: probe of ssb0:1 failed with error -22
...

The router uses a CFE bootloader, but most of the needed environment
variables for network card initialization, are not available from CFE
via printenv and even though not via cfe_getenv().
The required environment variables are saved in a special partition
in flash memory. The attached patch implement nvram_getenv and enables
bootup via NFS root on my router.

Most of the patch is extracted from the OpenWrt subversion repository and
stripped down and cleaned up to just fix this issue.

Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
Reviewed-by: Phil Sutter <phil@nwl.cc>
---
 arch/mips/bcm47xx/Makefile                 |    2 +-
 arch/mips/bcm47xx/nvram.c                  |  100 ++++++++++++++++++++++++++++
 arch/mips/bcm47xx/setup.c                  |   39 ++++++++----
 arch/mips/include/asm/mach-bcm47xx/nvram.h |   34 ++++++++++
 4 files changed, 162 insertions(+), 13 deletions(-)
 create mode 100644 arch/mips/bcm47xx/nvram.c
 create mode 100644 arch/mips/include/asm/mach-bcm47xx/nvram.h

diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 35294b1..7465e8a 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
 # under Linux.
 #
 
-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
new file mode 100644
index 0000000..74b2b44
--- /dev/null
+++ b/arch/mips/bcm47xx/nvram.c
@@ -0,0 +1,100 @@
+/*
+ * BCM947xx nvram variable access
+ *
+ * Copyright (C) 2005 Broadcom Corporation
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ssb/ssb.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/mach-bcm47xx/nvram.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
+
+static char nvram_buf[NVRAM_SPACE];
+
+/* Probe for NVRAM header */
+static void __init early_nvram_init(void)
+{
+	struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+	struct nvram_header *header;
+	int i;
+	u32 base, lim, off;
+	u32 *src, *dst;
+
+	base = mcore->flash_window;
+	lim = mcore->flash_window_size;
+
+	off = FLASH_MIN;
+	while (off <= lim) {
+		/* Windowed flash access */
+		header = (struct nvram_header *)
+			KSEG1ADDR(base + off - NVRAM_SPACE);
+		if (header->magic == NVRAM_HEADER)
+			goto found;
+		off <<= 1;
+	}
+
+	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
+	header = (struct nvram_header *) KSEG1ADDR(base + 4096);
+	if (header->magic == NVRAM_HEADER)
+		goto found;
+
+	header = (struct nvram_header *) KSEG1ADDR(base + 1024);
+	if (header->magic == NVRAM_HEADER)
+		goto found;
+
+	return;
+
+found:
+	src = (u32 *) header;
+	dst = (u32 *) nvram_buf;
+	for (i = 0; i < sizeof(struct nvram_header); i += 4)
+		*dst++ = *src++;
+	for (; i < header->len && i < NVRAM_SPACE; i += 4)
+		*dst++ = le32_to_cpu(*src++);
+}
+
+int nvram_getenv(char *name, char *val, size_t val_len)
+{
+	char *var, *value, *end, *eq;
+
+	if (!name)
+		return 1;
+
+	if (!nvram_buf[0])
+		early_nvram_init();
+
+	/* Look for name=value and return value */
+	var = &nvram_buf[sizeof(struct nvram_header)];
+	end = nvram_buf + sizeof(nvram_buf) - 2;
+	end[0] = end[1] = '\0';
+	for (; *var; var = value + strlen(value) + 1) {
+		eq = strchr(var, '=');
+		if (!eq)
+			break;
+		value = eq + 1;
+		if ((eq - var) == strlen(name) &&
+			strncmp(var, name, (eq - var)) == 0) {
+			snprintf(val, val_len, "%s", value);
+			return 0;
+		}
+	}
+	return 1;
+}
+EXPORT_SYMBOL(nvram_getenv);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index d442e11..b1aee33 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,8 +1,8 @@
 /*
  *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
- *  Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
  *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
  *  Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -33,6 +33,7 @@
 #include <asm/time.h>
 #include <bcm47xx.h>
 #include <asm/fw/cfe/cfe_api.h>
+#include <asm/mach-bcm47xx/nvram.h>
 
 struct ssb_bus ssb_bcm47xx;
 EXPORT_SYMBOL(ssb_bcm47xx);
@@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 	/* Fill boardinfo structure */
 	memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
 
-	if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+	if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
 		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-	if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
+	if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
 		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-	if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
+	if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
 		iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
 
 	/* Fill sprom structure */
 	memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
 	iv->sprom.revision = 3;
 
-	if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+	if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
 		str2eaddr(buf, iv->sprom.et0mac);
-	if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+
+	if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
 		str2eaddr(buf, iv->sprom.et1mac);
-	if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
-		iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
-	if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
-		iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
-	if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
+
+	if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
+		iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
+
+	if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
+		iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
+
+	if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
 		iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-	if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
+
+	if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
+	    nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
 		iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
 
 	return 0;
diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h
new file mode 100644
index 0000000..b8b5fe8
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2005, Broadcom Corporation
+ *  Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __NVRAM_H
+#define __NVRAM_H
+
+struct nvram_header {
+	u32 magic;
+	u32 len;
+	u32 crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+	u32 config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */
+	u32 config_ncdl;	/* ncdl values for memc */
+};
+
+#define NVRAM_HEADER		0x48534C46	/* 'FLSH' */
+#define NVRAM_VERSION		1
+#define NVRAM_HEADER_SIZE	20
+#define NVRAM_SPACE		0x8000
+
+#define FLASH_MIN		0x00020000	/* M