* [PATCH v2 5/5] mmc: sdhci-esdhc: enable esdhc on imx53
From: Zhu Richard-R65037 @ 2011-02-28 2:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110225203849.GC2192@pengutronix.de>
Hi WolfSang:
This phenomena is caused by the IC modifications on imx53 refer to imx51.
The details about this patch used for are listed below:
In order to generate the TC INT correctly, the CMD type of CMD12 should be set in the CMD register for
mass storage Multi-BLK IO(CMD18/CMD25), and the bit1 of the Vendor Spec register should be set/clear
at the begin/end of the Multi-BLK read.
Otherwise, there wouldn't TC INT generation in the mass storage Multi-BLK IO(CMD18/CMD25) and
SDIO Multi-BLK read operations.
That's all. How about add these description into the commit?
Best Regards
Richard Zhu
> -----Original Message-----
> From: Wolfram Sang [mailto:w.sang at pengutronix.de]
> Sent: Saturday, February 26, 2011 4:39 AM
> To: Zhu Richard-R65037
> Cc: linux-arm-kernel at lists.infradead.org; kernel at pengutronix.de; linux-
> mmc at vger.kernel.org; cjb at laptop.org; avorontsov at ru.mvista.com;
> eric at eukrea.com; linuxzsc at gmail.com; Zhao Richard-B20223
> Subject: Re: [PATCH v2 5/5] mmc: sdhci-esdhc: enable esdhc on imx53
>
> On Tue, Feb 22, 2011 at 06:13:26PM +0800, Richard Zhu wrote:
>
> > Fix the NO INT in the Multi-BLK IO in SD/MMC, and Multi-BLK read in
> > SDIO
>
> This description is too short. Why does it not work before, and why does
> this patch help?
>
> >
> > Signed-off-by: Richard Zhu <Hong-Xing.Zhu@freescale.com>
> > ---
> > drivers/mmc/host/sdhci-esdhc-imx.c | 41
> +++++++++++++++++++++++++++++++++++-
> > drivers/mmc/host/sdhci-esdhc.h | 5 ++++
> > 2 files changed, 45 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
> > b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 9b82910..a09f786 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -17,6 +17,8 @@
> > #include <linux/clk.h>
> > #include <linux/mmc/host.h>
> > #include <linux/mmc/sdhci-pltfm.h>
> > +#include <linux/mmc/mmc.h>
> > +#include <linux/mmc/sdio.h>
> > #include <mach/hardware.h>
> > #include "sdhci.h"
> > #include "sdhci-pltfm.h"
> > @@ -38,6 +40,27 @@ static u16 esdhc_readw_le(struct sdhci_host *host,
> int reg)
> > return readw(host->ioaddr + reg);
> > }
> >
> > +static void esdhc_writel_le(struct sdhci_host *host, u32 val, int
> > +reg) {
> > + switch (reg) {
> > + case SDHCI_INT_STATUS:
> > + /*
> > + * Fix no INT bug in SDIO MULTI-BLK read
> > + * clear bit1 of Vendor Spec registor after TC
> > + */
>
> Same for this comment. Make it more descriptive, please
>
> > + if (val & SDHCI_INT_DATA_END) {
> > + u32 v;
> > + v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
> > + if (v & 0x2) {
> > + v &= (~0x2);
>
> Braces not needed.
>
> > + writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
> > + }
>
> Can't you clear it unconditionally?
>
> > + }
> > + break;
> > + }
> > + writel(val, host->ioaddr + reg);
> > +}
> > +
> > static void esdhc_writew_le(struct sdhci_host *host, u16 val, int
> > reg) {
> > struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -45,12
> > +68,27 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val,
> int reg)
> > switch (reg) {
> > case SDHCI_TRANSFER_MODE:
> > /*
> > + * Fix no INT bug in SDIO MULTI-BLK read
> > + * set bit1 of Vendor Spec registor
> > + */
> > + if ((host->cmd->opcode == SD_IO_RW_EXTENDED)
> > + && (host->cmd->data->blocks > 1)
> > + && (host->cmd->data->flags & MMC_DATA_READ)) {
> > + u32 v;
> > + v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
> > + v |= 0x2;
> > + writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
> > + }
> > + /*
> > * Postpone this write, we must do it together with a
> > * command write that is down below.
> > */
> > pltfm_host->scratchpad = val;
> > return;
> > case SDHCI_COMMAND:
> > + /*Set the CMD_TYPE of the CMD12, fix no INT in MULTI_BLK IO
> */
> > + if (host->cmd->opcode == MMC_STOP_TRANSMISSION)
> > + val |= SDHCI_CMD_ABORTCMD;
>
> Can't we handle it the same way than the SDIO case? I have to admit, even
> after reading the docs, I don't fully get what this bit1 is about.
>
> > writel(val << 16 | pltfm_host->scratchpad,
> > host->ioaddr + SDHCI_TRANSFER_MODE);
> > return;
> > @@ -113,7 +151,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host,
> struct sdhci_pltfm_data *pd
> > clk_enable(clk);
> > pltfm_host->clk = clk;
> >
> > - if (cpu_is_mx35() || cpu_is_mx51())
> > + if (!cpu_is_mx25())
> > host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
> >
> > /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
> @@
> > -133,6 +171,7 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
> >
> > static struct sdhci_ops sdhci_esdhc_ops = {
> > .read_w = esdhc_readw_le,
> > + .write_l = esdhc_writel_le,
>
> You are applying it for all imx-versions?
>
> > .write_w = esdhc_writew_le,
> > .write_b = esdhc_writeb_le,
> > .set_clock = esdhc_set_clock,
> > diff --git a/drivers/mmc/host/sdhci-esdhc.h
> > b/drivers/mmc/host/sdhci-esdhc.h index 303cde0..c93168c 100644
> > --- a/drivers/mmc/host/sdhci-esdhc.h
> > +++ b/drivers/mmc/host/sdhci-esdhc.h
> > @@ -43,6 +43,11 @@
> >
> > #define ESDHC_HOST_CONTROL_RES 0x05
> >
> > +/* Abort type definition in the command register */
> > +#define SDHCI_CMD_ABORTCMD 0xC0
>
> So, this is vendor-specific, too?
>
> > +/* VENDOR SPEC register */
> > +#define SDHCI_VENDOR_SPEC 0xC0
> > +
> > static inline void esdhc_set_clock(struct sdhci_host *host, unsigned
> > int clock) {
> > int pre_div = 2;
>
> Regards,
>
> Wolfram
>
> --
> Pengutronix e.K. | Wolfram Sang
> |
> Industrial Linux Solutions | http://www.pengutronix.de/
> |
^ permalink raw reply
* [PATCH 0/8] OMAP2+: hwmod/clockevent: allow late-init of individual hwmods
From: Paul Walmsley @ 2011-02-28 2:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D651998.3040002@ti.com>
Salut Beno?t,
On Wed, 23 Feb 2011, Cousson, Benoit wrote:
> On 2/23/2011 8:11 AM, Paul Walmsley wrote:
> > This series adds the ability to late-initialize individual
> > hwmods. The goal here is for clockevent (and eventually
> > clocksource) hwmods to be late-initialized individually, and
> > right before they are needed, in the timer init code. Then
> > omap_hwmod_late_init(), which late-inits the rest of the hwmods,
> > is intended to run as an initcall -- much later in the boot
> > process.
> >
> > This series includes the OMAP2/3 hwmod data for the GPTIMERs that
> > Tarun posted earlier. This data is necessary for this new code
> > to avoid warnings during boot.
> >
> > Boot-tested on N800, OMAP34xx Beagleboard and OMAP4430ES2 Panda.
>
> I'm testing it on 4430sdp, and I have the following warning:
>
> [ 0.000000] omap_hwmod: dpll_mpu_m2_ck: missing clockdomain for dpll_mpu_m2_ck.
> [ 0.000000] ------------[ cut here ]------------
> [ 0.000000] WARNING: at arch/arm/mach-omap2/timer-gp.c:157 omap2_gp_timer_init+0x80/0x190()
> [ 0.000000] timer-gp: omap_dm_timer_set_source() failed
> [ 0.000000] Modules linked in:
> [ 0.000000] [<c0062a6c>] (unwind_backtrace+0x0/0xec) from [<c009422c>] (warn_slowpath_common+0x4c/0x64)
> [ 0.000000] [<c009422c>] (warn_slowpath_common+0x4c/0x64) from [<c00942c4>] (warn_slowpath_fmt+0x2c/0x3c)
> [ 0.000000] [<c00942c4>] (warn_slowpath_fmt+0x2c/0x3c) from [<c0010e30>] (omap2_gp_timer_init+0x80/0x190)
> [ 0.000000] [<c0010e30>] (omap2_gp_timer_init+0x80/0x190) from [<c000c0dc>] (time_init+0x20/0x30)
> [ 0.000000] [<c000c0dc>] (time_init+0x20/0x30) from [<c0008cbc>] (start_kernel+0x1a4/0x30c)
> [ 0.000000] [<c0008cbc>] (start_kernel+0x1a4/0x30c) from [<80008038>] (0x80008038)
> [ 0.000000] ---[ end trace 1b75b31a2719ed1c ]---
> [ 0.000000] OMAP clockevent source: GPTIMER1 at 32768 Hz
This is due to commit 3b03b58dab847883e6b9a431558c7d8e43fa94c6 ("OMAP4:
hwmod data: Prevent timer1 to be reset and idle during init"). Could you
please try reverting this and see if the warning disappears?
Tony, I guess the omap-for-linus branch will probably need to get rebuilt
to drop that patch, once this series is merged...
- Paul
^ permalink raw reply
* [PATCH 0/6] pxa3xx_nand update series set version 5
From: Lei Wen @ 2011-02-28 2:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
V4:
rework the patch set accroding to Eric's suggestion.
Move the recode judgement to the after command execution.
V5:
clean code style issue.
Lei Wen (6):
pxa3xx_nand: make scan procedure more clear
pxa3xx_nand: rework irq logic
pxa3xx_nand: discard wait_for_event,write_cmd,__readid function
pxa3xx_nand: unify prepare command
pxa3xx_nand: mtd scan id process could be defined by driver itself
pxa3xx_nand: clean the keep configure code
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 2 +-
drivers/mtd/nand/pxa3xx_nand.c | 977 ++++++++++++--------------
2 files changed, 458 insertions(+), 521 deletions(-)
^ permalink raw reply
* [PATCH V5 1/6] pxa3xx_nand: make scan procedure more clear
From: Lei Wen @ 2011-02-28 2:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
drivers/mtd/nand/pxa3xx_nand.c | 99 ++++++++++++++++++++++------------------
1 files changed, 55 insertions(+), 44 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index ea2c288..f440443 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -126,6 +126,7 @@ struct pxa3xx_nand_info {
unsigned int buf_start;
unsigned int buf_count;
+ struct mtd_info *mtd;
/* DMA information */
int drcmr_dat;
int drcmr_cmd;
@@ -1044,34 +1045,27 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
this->chip_delay = 25;
}
-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static
+struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
{
- struct pxa3xx_nand_platform_data *pdata;
+ struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
struct pxa3xx_nand_info *info;
- struct nand_chip *this;
struct mtd_info *mtd;
struct resource *r;
- int ret = 0, irq;
-
- pdata = pdev->dev.platform_data;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data defined\n");
- return -ENODEV;
- }
+ int ret, irq;
mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
GFP_KERNEL);
if (!mtd) {
dev_err(&pdev->dev, "failed to allocate memory\n");
- return -ENOMEM;
+ return NULL;
}
info = (struct pxa3xx_nand_info *)(&mtd[1]);
info->pdev = pdev;
- this = &info->nand_chip;
mtd->priv = info;
+ info->mtd = mtd;
mtd->owner = THIS_MODULE;
info->clk = clk_get(&pdev->dev, NULL);
@@ -1149,31 +1143,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
}
pxa3xx_nand_init_mtd(mtd, info);
+ platform_set_drvdata(pdev, info);
- platform_set_drvdata(pdev, mtd);
-
- if (nand_scan(mtd, 1)) {
- dev_err(&pdev->dev, "failed to scan nand\n");
- ret = -ENXIO;
- goto fail_free_irq;
- }
-
-#ifdef CONFIG_MTD_PARTITIONS
- if (mtd_has_cmdlinepart()) {
- static const char *probes[] = { "cmdlinepart", NULL };
- struct mtd_partition *parts;
- int nr_parts;
-
- nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
-
- if (nr_parts)
- return add_mtd_partitions(mtd, parts, nr_parts);
- }
-
- return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
-#else
- return 0;
-#endif
+ return info;
fail_free_irq:
free_irq(irq, info);
@@ -1193,13 +1165,13 @@ fail_put_clk:
clk_put(info->clk);
fail_free_mtd:
kfree(mtd);
- return ret;
+ return NULL;
}
static int pxa3xx_nand_remove(struct platform_device *pdev)
{
- struct mtd_info *mtd = platform_get_drvdata(pdev);
- struct pxa3xx_nand_info *info = mtd->priv;
+ struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = info->mtd;
struct resource *r;
int irq;
@@ -1230,11 +1202,50 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
return 0;
}
+static int pxa3xx_nand_probe(struct platform_device *pdev)
+{
+ struct pxa3xx_nand_platform_data *pdata;
+ struct pxa3xx_nand_info *info;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ return -ENODEV;
+ }
+
+ info = alloc_nand_resource(pdev);
+ if (info == NULL)
+ return -ENOMEM;
+
+ if (nand_scan(info->mtd, 1)) {
+ dev_err(&pdev->dev, "failed to scan nand\n");
+ pxa3xx_nand_remove(pdev);
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (mtd_has_cmdlinepart()) {
+ const char *probes[] = { "cmdlinepart", NULL };
+ struct mtd_partition *parts;
+ int nr_parts;
+
+ nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+
+ if (nr_parts)
+ return add_mtd_partitions(mtd, parts, nr_parts);
+ }
+
+ return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+#else
+ return 0;
+#endif
+}
+
#ifdef CONFIG_PM
static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
- struct pxa3xx_nand_info *info = mtd->priv;
+ struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = info->mtd;
if (info->state != STATE_READY) {
dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
@@ -1246,8 +1257,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
static int pxa3xx_nand_resume(struct platform_device *pdev)
{
- struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
- struct pxa3xx_nand_info *info = mtd->priv;
+ struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = info->mtd;
nand_writel(info, NDTR0CS0, info->ndtr0cs0);
nand_writel(info, NDTR1CS0, info->ndtr1cs0);
--
1.7.0.4
^ permalink raw reply related
* [PATCH V5 3/6] pxa3xx_nand: discard wait_for_event, write_cmd, __readid function
From: Lei Wen @ 2011-02-28 2:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Since we have rework the irq process, we don't need additional
delay in wait_for_event. Also write_cmd and __readid is also
discarded for the same reason.
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Acked-by: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
drivers/mtd/nand/pxa3xx_nand.c | 77 +---------------------------------------
1 files changed, 1 insertions(+), 76 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 3264b1d..be0aa44 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -258,25 +258,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
nand_writel(info, NDTR1CS0, ndtr1);
}
-#define WAIT_EVENT_TIMEOUT 10
-
-static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
-{
- int timeout = WAIT_EVENT_TIMEOUT;
- uint32_t ndsr;
-
- while (timeout--) {
- ndsr = nand_readl(info, NDSR) & NDSR_MASK;
- if (ndsr & event) {
- nand_writel(info, NDSR, ndsr);
- return 0;
- }
- udelay(10);
- }
-
- return -ETIMEDOUT;
-}
-
static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
{
int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
@@ -414,35 +395,6 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
nand_writel(info, NDCR, ndcr | int_mask);
}
-/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
- * otherwise, it does not work
- */
-static int write_cmd(struct pxa3xx_nand_info *info)
-{
- uint32_t ndcr;
-
- /* clear status bits and run */
- nand_writel(info, NDSR, NDSR_MASK);
-
- ndcr = info->reg_ndcr;
-
- ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
- ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
- ndcr |= NDCR_ND_RUN;
-
- nand_writel(info, NDCR, ndcr);
-
- if (wait_for_event(info, NDSR_WRCMDREQ)) {
- printk(KERN_ERR "timed out writing command\n");
- return -ETIMEDOUT;
- }
-
- nand_writel(info, NDCB0, info->ndcb0);
- nand_writel(info, NDCB0, info->ndcb1);
- nand_writel(info, NDCB0, info->ndcb2);
- return 0;
-}
-
static void handle_data_pio(struct pxa3xx_nand_info *info)
{
switch (info->state) {
@@ -778,33 +730,6 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
return 0;
}
-static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
-{
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
- uint32_t ndcr;
- uint8_t id_buff[8];
-
- prepare_other_cmd(info, cmdset->read_id);
-
- /* Send command */
- if (write_cmd(info))
- goto fail_timeout;
-
- /* Wait for CMDDM(command done successfully) */
- if (wait_for_event(info, NDSR_RDDREQ))
- goto fail_timeout;
-
- __raw_readsl(info->mmio_base + NDDB, id_buff, 2);
- *id = id_buff[0] | (id_buff[1] << 8);
- return 0;
-
-fail_timeout:
- ndcr = nand_readl(info, NDCR);
- nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
- udelay(10);
- return -ETIMEDOUT;
-}
-
static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
const struct pxa3xx_nand_flash *f)
{
@@ -857,7 +782,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
- /* set info fields needed to __readid */
+ /* set info fields needed to read id */
info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
info->reg_ndcr = ndcr;
info->cmdset = &default_cmdset;
--
1.7.0.4
^ permalink raw reply related
* [PATCH V5 4/6] pxa3xx_nand: unify prepare command
From: Lei Wen @ 2011-02-28 2:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Make the interface simpler which could make both debug
and enhancement easier.
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
drivers/mtd/nand/pxa3xx_nand.c | 249 ++++++++++++++++++++++------------------
1 files changed, 139 insertions(+), 110 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index be0aa44..de0a2a2 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -28,6 +28,7 @@
#define CHIP_DELAY_TIMEOUT (2 * HZ/10)
#define NAND_STOP_DELAY (2 * HZ/50)
+#define PAGE_CHUNK_SIZE (2048)
/* registers and bit definitions */
#define NDCR (0x00) /* Control register */
@@ -77,6 +78,7 @@
#define NDSR_RDDREQ (0x1 << 1)
#define NDSR_WRCMDREQ (0x1)
+#define NDCB0_ST_ROW_EN (0x1 << 26)
#define NDCB0_AUTO_RS (0x1 << 25)
#define NDCB0_CSEL (0x1 << 24)
#define NDCB0_CMD_TYPE_MASK (0x7 << 21)
@@ -319,66 +321,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
nand_writel(info, NDSR, NDSR_MASK);
}
-static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
- uint16_t cmd, int column, int page_addr)
-{
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
- pxa3xx_set_datasize(info);
-
- /* generate values for NDCBx registers */
- info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
- info->ndcb1 = 0;
- info->ndcb2 = 0;
- info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
-
- if (info->col_addr_cycles == 2) {
- /* large block, 2 cycles for column address
- * row address starts from 3rd cycle
- */
- info->ndcb1 |= page_addr << 16;
- if (info->row_addr_cycles == 3)
- info->ndcb2 = (page_addr >> 16) & 0xff;
- } else
- /* small block, 1 cycles for column address
- * row address starts from 2nd cycle
- */
- info->ndcb1 = page_addr << 8;
-
- if (cmd == cmdset->program)
- info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
-}
-
-static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
- uint16_t cmd, int page_addr)
-{
- info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
- info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
- info->ndcb1 = page_addr;
- info->ndcb2 = 0;
-}
-
-static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
-{
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-
- info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
- info->ndcb1 = 0;
- info->ndcb2 = 0;
-
- info->oob_size = 0;
- if (cmd == cmdset->read_id) {
- info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1);
- info->data_size = 8;
- } else if (cmd == cmdset->read_status) {
- info->ndcb0 |= NDCB0_CMD_TYPE(4);
- info->data_size = 8;
- } else if (cmd == cmdset->reset || cmd == cmdset->lock ||
- cmd == cmdset->unlock) {
- info->ndcb0 |= NDCB0_CMD_TYPE(5);
- } else
- BUG();
-}
-
static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
{
uint32_t ndcr;
@@ -529,81 +471,167 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
return 1;
}
-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
- int column, int page_addr)
+static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+ uint16_t column, int page_addr)
{
- struct pxa3xx_nand_info *info = mtd->priv;
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
- int ret, exec_cmd = 0;
+ uint16_t cmd;
+ int addr_cycle, exec_cmd, ndcb0;
+ struct mtd_info *mtd = info->mtd;
+
+ ndcb0 = 0;
+ addr_cycle = 0;
+ exec_cmd = 1;
- info->use_dma = (use_dma) ? 1 : 0;
- info->use_ecc = 0;
- info->data_size = 0;
- info->state = 0;
- info->retcode = ERR_NONE;
+ /* reset data and oob column point to handle data */
+ info->buf_start = 0;
+ info->buf_count = 0;
+ info->oob_size = 0;
+ info->use_ecc = 0;
+ info->retcode = ERR_NONE;
switch (command) {
+ case NAND_CMD_READ0:
+ case NAND_CMD_PAGEPROG:
+ info->use_ecc = 1;
case NAND_CMD_READOOB:
- /* disable HW ECC to get all the OOB data */
- info->buf_count = mtd->writesize + mtd->oobsize;
- info->buf_start = mtd->writesize + column;
- memset(info->data_buff, 0xFF, info->buf_count);
-
- prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
- exec_cmd = 1;
+ pxa3xx_set_datasize(info);
+ break;
+ case NAND_CMD_SEQIN:
+ exec_cmd = 0;
+ break;
+ default:
+ info->ndcb1 = 0;
+ info->ndcb2 = 0;
break;
+ }
+
+ info->ndcb0 = ndcb0;
+ addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
+ + info->col_addr_cycles);
+ switch (command) {
+ case NAND_CMD_READOOB:
case NAND_CMD_READ0:
- info->use_ecc = 1;
- info->buf_start = column;
- info->buf_count = mtd->writesize + mtd->oobsize;
- memset(info->data_buff, 0xFF, info->buf_count);
+ cmd = info->cmdset->read1;
+ if (command == NAND_CMD_READOOB)
+ info->buf_start = mtd->writesize + column;
+ else
+ info->buf_start = column;
+
+ if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+ info->ndcb0 |= NDCB0_CMD_TYPE(0)
+ | addr_cycle
+ | (cmd & NDCB0_CMD1_MASK);
+ else
+ info->ndcb0 |= NDCB0_CMD_TYPE(0)
+ | NDCB0_DBC
+ | addr_cycle
+ | cmd;
- prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
- exec_cmd = 1;
- break;
case NAND_CMD_SEQIN:
- info->buf_start = column;
+ /* small page addr setting */
+ if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+ info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+ | (column & 0xFF);
+
+ info->ndcb2 = 0;
+ } else {
+ info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+ | (column & 0xFFFF);
+
+ if (page_addr & 0xFF0000)
+ info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+ else
+ info->ndcb2 = 0;
+ }
+
info->buf_count = mtd->writesize + mtd->oobsize;
- memset(info->data_buff, 0xff, info->buf_count);
+ memset(info->data_buff, 0xFF, info->buf_count);
- /* save column/page_addr for next CMD_PAGEPROG */
- info->seqin_column = column;
- info->seqin_page_addr = page_addr;
break;
+
case NAND_CMD_PAGEPROG:
- info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
+ if (is_buf_blank(info->data_buff,
+ (mtd->writesize + mtd->oobsize))) {
+ exec_cmd = 0;
+ break;
+ }
- prepare_read_prog_cmd(info, cmdset->program,
- info->seqin_column, info->seqin_page_addr);
- exec_cmd = 1;
- break;
- case NAND_CMD_ERASE1:
- prepare_erase_cmd(info, cmdset->erase, page_addr);
- exec_cmd = 1;
- break;
- case NAND_CMD_ERASE2:
+ cmd = info->cmdset->program;
+ info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+ | NDCB0_AUTO_RS
+ | NDCB0_ST_ROW_EN
+ | NDCB0_DBC
+ | cmd
+ | addr_cycle;
break;
+
case NAND_CMD_READID:
+ cmd = info->cmdset->read_id;
+ info->buf_count = info->read_id_bytes;
+ info->ndcb0 |= NDCB0_CMD_TYPE(3)
+ | NDCB0_ADDR_CYC(1)
+ | cmd;
+
+ info->data_size = 8;
+ break;
case NAND_CMD_STATUS:
- info->use_dma = 0; /* force PIO read */
- info->buf_start = 0;
- info->buf_count = (command == NAND_CMD_READID) ?
- info->read_id_bytes : 1;
-
- prepare_other_cmd(info, (command == NAND_CMD_READID) ?
- cmdset->read_id : cmdset->read_status);
- exec_cmd = 1;
+ cmd = info->cmdset->read_status;
+ info->buf_count = 1;
+ info->ndcb0 |= NDCB0_CMD_TYPE(4)
+ | NDCB0_ADDR_CYC(1)
+ | cmd;
+
+ info->data_size = 8;
+ break;
+
+ case NAND_CMD_ERASE1:
+ cmd = info->cmdset->erase;
+ info->ndcb0 |= NDCB0_CMD_TYPE(2)
+ | NDCB0_AUTO_RS
+ | NDCB0_ADDR_CYC(3)
+ | NDCB0_DBC
+ | cmd;
+ info->ndcb1 = page_addr;
+ info->ndcb2 = 0;
+
break;
case NAND_CMD_RESET:
- prepare_other_cmd(info, cmdset->reset);
- exec_cmd = 1;
+ cmd = info->cmdset->reset;
+ info->ndcb0 |= NDCB0_CMD_TYPE(5)
+ | cmd;
+
+ break;
+
+ case NAND_CMD_ERASE2:
+ exec_cmd = 0;
break;
+
default:
- printk(KERN_ERR "non-supported command.\n");
+ exec_cmd = 0;
+ printk(KERN_ERR "pxa3xx-nand: non-supported"
+ " command %x\n", command);
break;
}
+ return exec_cmd;
+}
+
+static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+ int column, int page_addr)
+{
+ struct pxa3xx_nand_info *info = mtd->priv;
+ int ret, exec_cmd;
+
+ /*
+ * if this is a x16 device ,then convert the input
+ * "byte" address into a "word" address appropriate
+ * for indexing a word-oriented device
+ */
+ if (info->reg_ndcr & NDCR_DWIDTH_M)
+ column /= 2;
+
+ exec_cmd = prepare_command_pool(info, command, column, page_addr);
if (exec_cmd) {
init_completion(&info->cmd_complete);
pxa3xx_nand_start(info);
@@ -919,6 +947,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
struct nand_chip *this = &info->nand_chip;
this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
+ this->options |= NAND_NO_AUTOINCR;
this->waitfunc = pxa3xx_nand_waitfunc;
this->select_chip = pxa3xx_nand_select_chip;
--
1.7.0.4
^ permalink raw reply related
* [PATCH V5 6/6] pxa3xx_nand: clean the keep configure code
From: Lei Wen @ 2011-02-28 2:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 2 +-
drivers/mtd/nand/pxa3xx_nand.c | 103 +++++++++-----------------
2 files changed, 36 insertions(+), 69 deletions(-)
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 01a8448..442301f 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -30,6 +30,7 @@ struct pxa3xx_nand_cmdset {
};
struct pxa3xx_nand_flash {
+ char *name;
uint32_t chip_id;
unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */
unsigned int page_size; /* Page size in bytes (PAGE_SZ) */
@@ -37,7 +38,6 @@ struct pxa3xx_nand_flash {
unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */
unsigned int num_blocks; /* Number of physical blocks in Flash */
- struct pxa3xx_nand_cmdset *cmdset; /* NAND command set */
struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
};
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index bb50cf2..ab7f4c3 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -211,15 +211,15 @@ static struct pxa3xx_nand_timing timing[] = {
};
static struct pxa3xx_nand_flash builtin_flash_types[] = {
- { 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] },
- { 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] },
- { 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] },
- { 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] },
- { 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] },
- { 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
- { 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] },
- { 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
- { 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
+{ "DEFAULT FLASH", 0, 0, 2048, 8, 8, 0, &timing[0] },
+{ "64MiB 16-bit", 0x46ec, 32, 512, 16, 16, 4096, &timing[1] },
+{ "256MiB 8-bit", 0xdaec, 64, 2048, 8, 8, 2048, &timing[1] },
+{ "4GiB 8-bit", 0xd7ec, 128, 4096, 8, 8, 8192, &timing[1] },
+{ "128MiB 8-bit", 0xa12c, 64, 2048, 8, 8, 1024, &timing[2] },
+{ "128MiB 16-bit", 0xb12c, 64, 2048, 16, 16, 1024, &timing[2] },
+{ "512MiB 8-bit", 0xdc2c, 64, 2048, 8, 8, 4096, &timing[2] },
+{ "512MiB 16-bit", 0xcc2c, 64, 2048, 16, 16, 4096, &timing[2] },
+{ "256MiB 16-bit", 0xba20, 64, 2048, 16, 16, 2048, &timing[3] },
};
/* Define a default flash type setting serve as flash detecting only */
@@ -779,9 +779,8 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
return -EINVAL;
/* calculate flash information */
- info->cmdset = f->cmdset;
+ info->cmdset = &default_cmdset;
info->page_size = f->page_size;
- info->oob_buff = info->data_buff + f->page_size;
info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
/* calculate addressing information */
@@ -811,45 +810,12 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
{
uint32_t ndcr = nand_readl(info, NDCR);
- struct nand_flash_dev *type = NULL;
- uint32_t id = -1, page_per_block, num_blocks;
- int i;
-
- page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
/* set info fields needed to read id */
info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
info->reg_ndcr = ndcr;
info->cmdset = &default_cmdset;
- pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
- id = *((uint16_t *)(info->data_buff));
- if (id == 0)
- return -ENODEV;
-
- /* Lookup the flash id */
- for (i = 0; nand_flash_ids[i].name != NULL; i++) {
- if (id == nand_flash_ids[i].id) {
- type = &nand_flash_ids[i];
- break;
- }
- }
-
- if (!type)
- return -ENODEV;
-
- /* fill the missing flash information */
- i = __ffs(page_per_block * info->page_size);
- num_blocks = type->chipsize << (20 - i);
-
- /* calculate addressing information */
- info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
-
- if (num_blocks * page_per_block > 65536)
- info->row_addr_cycles = 3;
- else
- info->row_addr_cycles = 2;
-
info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
@@ -916,13 +882,15 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
struct pxa3xx_nand_info *info = mtd->priv;
struct platform_device *pdev = info->pdev;
struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} };
const struct pxa3xx_nand_flash *f = NULL;
struct nand_chip *chip = mtd->priv;
uint32_t id = -1;
+ uint64_t chipsize;
int i, ret, num;
if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
- return 0;
+ goto KEEP_CONFIG;
ret = pxa3xx_nand_sensing(info);
if (!ret) {
@@ -953,22 +921,11 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
f = &builtin_flash_types[i - pdata->num_flash + 1];
/* find the chip in default list */
- if (f->chip_id == id) {
- pxa3xx_nand_config_flash(info, f);
- mtd->writesize = f->page_size;
- mtd->writesize_shift = ffs(mtd->writesize) - 1;
- mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
- mtd->oobsize = mtd->writesize / 32;
- mtd->erasesize = f->page_size * f->page_per_block;
- mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
- mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
-
- mtd->name = mtd_names[0];
+ if (f->chip_id == id)
break;
- }
}
- if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+ if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
kfree(mtd);
info->mtd = NULL;
printk(KERN_ERR "ERROR!! flash not defined!!!\n");
@@ -976,18 +933,28 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
return -EINVAL;
}
+ pxa3xx_nand_config_flash(info, f);
+ pxa3xx_flash_ids[0].name = f->name;
+ pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+ pxa3xx_flash_ids[0].pagesize = f->page_size;
+ chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+ pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+ pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+ if (f->flash_width == 16)
+ pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
+KEEP_CONFIG:
+ if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+ return -ENODEV;
+ /* calculate addressing information */
+ info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+ info->oob_buff = info->data_buff + mtd->writesize;
+ if ((mtd->size >> chip->page_shift) > 65536)
+ info->row_addr_cycles = 3;
+ else
+ info->row_addr_cycles = 2;
+ mtd->name = mtd_names[0];
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = f->page_size;
- chip->chipsize = (uint64_t)f->num_blocks * f->page_per_block
- * f->page_size;
- mtd->size = chip->chipsize;
-
- /* Calculate the address shift from the page size */
- chip->page_shift = ffs(mtd->writesize) - 1;
- chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
- chip->numchips = 1;
- chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
- chip->bbt_erase_shift = chip->phys_erase_shift;
chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
chip->options |= NAND_NO_AUTOINCR;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/2] ARM: l2x0: Errata fix for flush by Way operationcan cause data corruption
From: Santosh Shilimkar @ 2011-02-28 3:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110227120021.GA15314@n2100.arm.linux.org.uk>
> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Sent: Sunday, February 27, 2011 5:30 PM
> To: Santosh Shilimkar
> Cc: linux-arm-kernel at lists.infradead.org; tony at atomide.com;
> catalin.marinas at arm.com; linux-omap at vger.kernel.org
> Subject: Re: [PATCH 1/2] ARM: l2x0: Errata fix for flush by Way
> operationcan cause data corruption
>
> On Fri, Feb 18, 2011 at 06:05:24PM +0530, Santosh Shilimkar wrote:
[...]
>
> > @@ -329,6 +330,7 @@ void __init l2x0_init(void __iomem *base,
> __u32 aux_val, __u32 aux_mask)
> > outer_cache.flush_all = l2x0_flush_all;
> > outer_cache.inv_all = l2x0_inv_all;
> > outer_cache.disable = l2x0_disable;
> > + outer_cache.set_debug = NULL;
>
> outer_cache.set_debug = l2x0_set_debug;
>
> may result in more efficient code as we're avoiding having to test
> the value of outer_cache.set_debug each time we want to call it and
> branch appropriately.
Ok. Will do the necessary change and submit it to patch System
Regards,
Santosh
^ permalink raw reply
* [PATCH v5 1/2] PRUSS UIO driver support
From: TK, Pratheesh Gangadhar @ 2011-02-28 4:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1102251049090.2701@localhost6.localdomain6>
Hi,
> -----Original Message-----
> From: Thomas Gleixner [mailto:tglx at linutronix.de]
> Sent: Friday, February 25, 2011 3:24 PM
> To: TK, Pratheesh Gangadhar
> Cc: davinci-linux-open-source at linux.davincidsp.com; hjk at hansjkoch.de;
> gregkh at suse.de; sshtylyov at mvista.com; arnd at arndb.de; Chatterjee, Amit;
> linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH v5 1/2] PRUSS UIO driver support
>
> On Fri, 25 Feb 2011, Pratheesh Gangadhar wrote:
> > +static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
> > +{
> > + void __iomem *base = dev_info->mem[0].internal_addr;
> > + void __iomem *intren_reg = base + PINTC_HIER;
> > + void __iomem *intrstat_reg = base + PINTC_HIPIR + ((irq - 1) << 2);
> > + int val = ioread32(intren_reg), intr_mask = (1 << (irq - 1));
> > +
> > + /* Is interrupt enabled and active ? */
> > + if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND))
> > + return IRQ_NONE;
> > +
> > + /* Disable interrupt */
> > + iowrite32((val & ~intr_mask), intren_reg);
> > + return IRQ_HANDLED;
> > +}
>
> Hmm, just noticed, that you fiddle with the interrupt enable register
> here totally unprotected. So on a SMP system you might haandle two
> different interrupts at the same time. That wants locking.
>
> And even on UP, you have a problem as you reenable that thing from
> user space which requires a read modify write. Racy as hell.
>
> Please look at the other UIO drivers which have the same problem.
> Sorry for not noticing earlier!
Thanks for pointing this out. Yes - this is a problem especially since we have more than one interrupt for PRUSS which is enabled/disabled in this register. I will fix this and resubmit along with fixes addressing Sergei's comments on platform specific portion.
Thanks,
Pratheesh
^ permalink raw reply
* [PATCH 6/6] ARM: S5PV210: Add PWM backlight support on SMDKV210
From: Kyungmin Park @ 2011-02-28 4:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298694546-16816-7-git-send-email-banajit.g@samsung.com>
Hi,
On Sat, Feb 26, 2011 at 1:29 PM, Banajit Goswami <banajit.g@samsung.com> wrote:
> This patch adds support for LCD backlight control using PWM timer
> for Samsung's SMDKV210 board.
>
> Signed-off-by: Banajit Goswami <banajit.g@samsung.com>
> ---
> ?arch/arm/mach-s5pv210/Kconfig ? ? ? ? | ? ?1 +
> ?arch/arm/mach-s5pv210/mach-smdkv210.c | ? 46 +++++++++++++++++++++++++++++++++
> ?2 files changed, 47 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
> index 53aabef..d7fd031 100644
> --- a/arch/arm/mach-s5pv210/Kconfig
> +++ b/arch/arm/mach-s5pv210/Kconfig
> @@ -130,6 +130,7 @@ config MACH_SMDKV210
> ? ? ? ?select SAMSUNG_DEV_ADC
> ? ? ? ?select SAMSUNG_DEV_IDE
> ? ? ? ?select SAMSUNG_DEV_KEYPAD
> + ? ? ? select SAMSUNG_DEV_PWM
> ? ? ? ?select SAMSUNG_DEV_TS
> ? ? ? ?select S5PV210_SETUP_FB_24BPP
> ? ? ? ?select S5PV210_SETUP_I2C1
> diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
> index bc9fdb5..8833e7b 100644
> --- a/arch/arm/mach-s5pv210/mach-smdkv210.c
> +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
> @@ -18,6 +18,7 @@
> ?#include <linux/fb.h>
> ?#include <linux/gpio.h>
> ?#include <linux/delay.h>
> +#include <linux/pwm_backlight.h>
>
> ?#include <asm/mach/arch.h>
> ?#include <asm/mach/map.h>
> @@ -43,6 +44,7 @@
> ?#include <plat/keypad.h>
> ?#include <plat/pm.h>
> ?#include <plat/fb.h>
> +#include <plat/gpio-cfg.h>
>
> ?/* Following are default values for UCON, ULCON and UFCON UART registers */
> ?#define SMDKV210_UCON_DEFAULT ?(S3C2410_UCON_TXILEVEL | ? ? ? ?\
> @@ -208,6 +210,45 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
> ? ? ? ?.setup_gpio ? ? = s5pv210_fb_gpio_setup_24bpp,
> ?};
>
> +static int smdkv210_backlight_init(struct device *dev)
> +{
> + ? ? ? int ret;
> +
> + ? ? ? ret = gpio_request(S5PV210_GPD0(3), "Backlight");
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? printk(KERN_ERR "failed to request GPD for PWM-OUT 3\n");
> + ? ? ? ? ? ? ? return ret;
> + ? ? ? }
> +
> + ? ? ? /* Configure GPIO pin with S5PV210_GPD_0_3_TOUT_3 */
> + ? ? ? s3c_gpio_cfgpin(S5PV210_GPD0(3), (0x2 << 12));
what's (0x2 << 12)? Do you mean S3C_GPIO_SFN(2)?
please use the macro and other patches are same usage.
> +
> + ? ? ? return 0;
> +}
> +
> +static void smdkv210_backlight_exit(struct device *dev)
> +{
> + ? ? ? s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_OUTPUT);
> + ? ? ? gpio_free(S5PV210_GPD0(3));
> +}
> +
> +static struct platform_pwm_backlight_data smdkv210_backlight_data = {
> + ? ? ? .pwm_id ? ? ? ? = 3,
> + ? ? ? .max_brightness = 255,
> + ? ? ? .dft_brightness = 255,
> + ? ? ? .pwm_period_ns ?= 78770,
> + ? ? ? .init ? ? ? ? ? = smdkv210_backlight_init,
> + ? ? ? .exit ? ? ? ? ? = smdkv210_backlight_exit,
> +};
> +
> +static struct platform_device smdkv210_backlight_device = {
> + ? ? ? .name ? ? ? ? ? = "pwm-backlight",
> + ? ? ? .dev ? ? ? ? ? ?= {
> + ? ? ? ? ? ? ? .parent ? ? ? ? = &s3c_device_timer[3].dev,
> + ? ? ? ? ? ? ? .platform_data ?= &smdkv210_backlight_data,
> + ? ? ? },
> +};
> +
> ?static struct platform_device *smdkv210_devices[] __initdata = {
> ? ? ? ?&s3c_device_adc,
> ? ? ? ?&s3c_device_cfcon,
> @@ -229,6 +270,11 @@ static struct platform_device *smdkv210_devices[] __initdata = {
> ? ? ? ?&samsung_device_keypad,
> ? ? ? ?&smdkv210_dm9000,
> ? ? ? ?&smdkv210_lcd_lte480wv,
> + ? ? ? &s3c_device_timer[0],
> + ? ? ? &s3c_device_timer[1],
> + ? ? ? &s3c_device_timer[2],
> + ? ? ? &s3c_device_timer[3],
Why do you register timer[0...2] at here? it's only use the timer[3]
at this patch.
Other patches are same usage.
Thank you,
Kyungmin Park
> + ? ? ? &smdkv210_backlight_device,
> ?};
>
> ?static void __init smdkv210_dm9000_init(void)
> --
> 1.6.5.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v4 2/2] Defines DA850/AM18xx/OMAPL1-38 SOC resources used by PRUSS UIO driver
From: TK, Pratheesh Gangadhar @ 2011-02-28 4:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D6796D6.5050008@mvista.com>
Hi,
> -----Original Message-----
> From: Sergei Shtylyov [mailto:sshtylyov at mvista.com]
> Sent: Friday, February 25, 2011 5:18 PM
> To: TK, Pratheesh Gangadhar
> Cc: davinci-linux-open-source at linux.davincidsp.com; hjk at hansjkoch.de;
> gregkh at suse.de; tglx at linutronix.de; arnd at arndb.de; Chatterjee, Amit;
> linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH v4 2/2] Defines DA850/AM18xx/OMAPL1-38 SOC resources
> used by PRUSS UIO driver
>
> On 24-02-2011 17:06, Pratheesh Gangadhar wrote:
>
> > This patch defines PRUSS, ECAP clocks, memory and IRQ resources
> > used by PRUSS UIO driver in DA850/AM18xx/OMAPL1-38 devices. UIO
>
> It's OMAP-L138.
Ok.
>
> > driver exports 64K I/O region of PRUSS, 128KB L3 RAM and 256KB
> > DDR buffer to user space. PRUSS has 8 host event interrupt lines
> > mapped to IRQ_DA8XX_EVTOUT0..7 of ARM9 INTC.These in conjunction
> > with shared memory can be used to implement IPC between ARM9 and
> > PRUSS.
>
> > Signed-off-by: Pratheesh Gangadhar<pratheesh@ti.com>
> [...]
>
> > diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-
> davinci/board-da850-evm.c
> > index 11f986b..bd85aa3 100644
> > --- a/arch/arm/mach-davinci/board-da850-evm.c
> > +++ b/arch/arm/mach-davinci/board-da850-evm.c
> > @@ -1077,6 +1077,10 @@ static __init void da850_evm_init(void)
> > pr_warning("da850_evm_init: i2c0 registration failed: %d\n",
> > ret);
> >
> > + ret = da8xx_register_pruss();
> > + if (ret)
> > + pr_warning("da850_evm_init: pruss registration failed: %d\n",
> > + ret);
>
> Use __func__ to print the function name.
>
> >
> > ret = da8xx_register_watchdog();
> > if (ret)
>
> As I said, please put this into serpate patch.
>
Ok, will do.
> > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-
> davinci/da850.c
> > index 3443d97..0096d4f 100644
> > --- a/arch/arm/mach-davinci/da850.c
> > +++ b/arch/arm/mach-davinci/da850.c
> > @@ -238,6 +238,13 @@ static struct clk tptc2_clk = {
> > .flags = ALWAYS_ENABLED,
> > };
> >
> > +static struct clk pruss_clk = {
> > + .name = "pruss",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC0_DMAX,
> > + .flags = ALWAYS_ENABLED,
> > +};
> > +
>
> This conflicts with previously posted patch.
>
Ok, shall I rename to align with previous patch from Mistral or drop this from my patchset ?
> > static struct clk uart0_clk = {
> > .name = "uart0",
> > .parent =&pll0_sysclk2,
> > @@ -359,6 +366,30 @@ static struct clk usb20_clk = {
> > .gpsc = 1,
> > };
> >
> > +static struct clk ecap0_clk = {
> > + .name = "ecap0",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC1_ECAP,
> > + .flags = DA850_CLK_ASYNC3,
> > + .gpsc = 1,
> > +};
> > +
> > +static struct clk ecap1_clk = {
> > + .name = "ecap1",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC1_ECAP,
> > + .flags = DA850_CLK_ASYNC3,
> > + .gpsc = 1,
> > +};
> > +
> > +static struct clk ecap2_clk = {
> > + .name = "ecap2",
> > + .parent = &pll0_sysclk2,
> > + .lpsc = DA8XX_LPSC1_ECAP,
> > + .flags = DA850_CLK_ASYNC3,
> > + .gpsc = 1,
> > +};
> > +
>
> This is worth separate patch too...
>
Ok.
> > diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-
> davinci/devices-da8xx.c
> > index beda8a4..4ea3d1f 100644
> > --- a/arch/arm/mach-davinci/devices-da8xx.c
> > +++ b/arch/arm/mach-davinci/devices-da8xx.c
> > @@ -725,3 +725,76 @@ int __init da8xx_register_cpuidle(void)
> >
> > return platform_device_register(&da8xx_cpuidle_device);
> > }
> > +static struct resource pruss_resources[] = {
> > + [0] = {
> > + .start = DA8XX_PRUSS_BASE,
> > + .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [1] = {
> > + .start = DA8XX_L3RAM_BASE,
> > + .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [2] = {
> > + .start = 0,
> > + .end = SZ_256K - 1,
>
> Huh? I don't see where it's filled...
>
The current use is only to indicate memory block size to the PRUSS UIO driver when we allocate DDR memory using dma_alloc_coherent. sram_alloc is changed to use L3_RAM (128KB) instead of ARM RAM (8KB) in Mistral patch set - I need to follow the same convention for L3 RAM as well if I need to align with that patch. Is there a better way to do this?
> > + .flags = IORESOURCE_MEM,
> > + },
> > +
> [...]
> > +int __init da8xx_register_pruss()
> > +{
> > + return platform_device_register(&pruss_device);
> > +}
> > diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-
> davinci/include/mach/da8xx.h
> > index cfcb223..3ed6ee0 100644
> > --- a/arch/arm/mach-davinci/include/mach/da8xx.h
> > +++ b/arch/arm/mach-davinci/include/mach/da8xx.h
> > @@ -60,6 +60,7 @@ extern unsigned int da850_max_speed;
> > #define DA8XX_PLL0_BASE 0x01c11000
> > #define DA8XX_TIMER64P0_BASE 0x01c20000
> > #define DA8XX_TIMER64P1_BASE 0x01c21000
> > +#define DA8XX_PRUSS_BASE 0x01c30000
> > #define DA8XX_GPIO_BASE 0x01e26000
> > #define DA8XX_PSC1_BASE 0x01e27000
> > #define DA8XX_LCD_CNTRL_BASE 0x01e13000
> > @@ -68,6 +69,7 @@ extern unsigned int da850_max_speed;
> > #define DA8XX_AEMIF_CS2_BASE 0x60000000
> > #define DA8XX_AEMIF_CS3_BASE 0x62000000
> > #define DA8XX_AEMIF_CTL_BASE 0x68000000
> > +#define DA8XX_L3RAM_BASE 0x80000000
>
> There were already patches defining macros for these base addresses...
>
Ok - will align with this.
Thanks,
Pratheesh
^ permalink raw reply
* [PATCH 1/3] ARM: EXYNOS4: Add SYSTIMER IO Address mapping for MCT
From: Kukjin Kim @ 2011-02-28 5:16 UTC (permalink / raw)
To: linux-arm-kernel
From: Changhwan Youn <chaos.youn@samsung.com>
The MCT(Multi-Core Timer) is used for implementing kernel timers for
EXYNOS4210.
Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
arch/arm/mach-exynos4/cpu.c | 5 +++++
arch/arm/mach-exynos4/include/mach/map.h | 1 +
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index b0ec6d3..479dfa1 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -31,6 +31,11 @@ extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
/* Initial IO mappings */
static struct map_desc exynos4_iodesc[] __initdata = {
{
+ .virtual = (unsigned long)S5P_VA_SYSTIMER,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)S5P_VA_SYSRAM,
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM),
.length = SZ_4K,
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 80a41e0..d678f08 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -44,6 +44,7 @@
#define EXYNOS4_PA_PMU 0x10020000
#define EXYNOS4_PA_CMU 0x10030000
+#define EXYNOS4_PA_SYSTIMER 0x10050000
#define EXYNOS4_PA_WATCHDOG 0x10060000
#define EXYNOS4_PA_RTC 0x10070000
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] ARM: EXYNOS4: Add irq definition for kernel global timer
From: Kukjin Kim @ 2011-02-28 5:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298870207-1850-1-git-send-email-kgene.kim@samsung.com>
From: Changhwan Youn <chaos.youn@samsung.com>
This patch adds IRQ_MCT_G0 to irq map. IRQ_MCT_G0 is an interrupt of MCT
comparator and used for kernel global timer.
Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
arch/arm/mach-exynos4/include/mach/irqs.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 2dc5900..e3556d4 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -131,6 +131,7 @@
#define IRQ_MCT_L0 COMBINER_IRQ(51, 0)
#define IRQ_WDT COMBINER_IRQ(53, 0)
+#define IRQ_MCT_G0 COMBINER_IRQ(53, 4)
#define MAX_COMBINER_NR 54
--
1.7.1
^ permalink raw reply related
* [PATCH V4] ARM: EXYNOS4: Implement kernel timers using MCT
From: Kukjin Kim @ 2011-02-28 5:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298870207-1850-1-git-send-email-kgene.kim@samsung.com>
From: Changhwan Youn <chaos.youn@samsung.com>
The Multi-Core Timer(MCT) of EXYNOS4 is designed for implementing
clock source timer and clock event timers. This patch implements
1 clock source timer with 64 bit free running counter of MCT and
2 clock event timers with two of 31-bit tick counters.
Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
Changes since v3:
- Re-worked based on exynos4
- Changed member of clock_evetn_device like following
struct mct_clock_event_device {
struct clock_event_device *evt;
...
- Address comments from Russell King
Added static into "irqreturn_t exynos4_mct_comp_isr()"
Added .dev_id member into "struct irqaction mct_comp_event_irq"
Changes since v2:
- Addressed comments from Russell King
Added mct_clock_event_device structure
- Removed suspend()/resume() which are not used now
Changes since v1:
- Addressed comments from Russell King
(implemented global timer, used local timer and so on)
- Fixed small things
arch/arm/Kconfig | 2 +-
arch/arm/mach-exynos4/Kconfig | 5 +
arch/arm/mach-exynos4/Makefile | 11 +-
arch/arm/mach-exynos4/include/mach/regs-mct.h | 52 +++
arch/arm/mach-exynos4/mct.c | 421 +++++++++++++++++++++++++
5 files changed, 488 insertions(+), 3 deletions(-)
create mode 100644 arch/arm/mach-exynos4/include/mach/regs-mct.h
create mode 100644 arch/arm/mach-exynos4/mct.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ec3bf98..b4db99b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1366,7 +1366,7 @@ config LOCAL_TIMERS
bool "Use local timer interrupts"
depends on SMP
default y
- select HAVE_ARM_TWD if !ARCH_MSM_SCORPIONMP
+ select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
help
Enable support for local timers on SMP platforms, rather then the
legacy IPI broadcast method. Local timers allows the system
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index ad03840..77b5d93 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -15,6 +15,11 @@ config CPU_EXYNOS4210
help
Enable EXYNOS4210 CPU support
+config EXYNOS4_MCT
+ bool "Kernel timer support by MCT"
+ help
+ Use MCT (Multi Core Timer) as kernel timers
+
config EXYNOS4_DEV_PD
bool
help
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 0558235..de20b91 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -13,11 +13,18 @@ obj- :=
# Core support for EXYNOS4 system
obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o time.o gpiolib.o irq-eint.o dma.o
+obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o gpiolib.o irq-eint.o dma.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
-obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+
+ifeq ($(CONFIG_EXYNOS4_MCT),y)
+obj-y += mct.o
+else
+obj-y += time.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+endif
+
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
# machine support
diff --git a/arch/arm/mach-exynos4/include/mach/regs-mct.h b/arch/arm/mach-exynos4/include/mach/regs-mct.h
new file mode 100644
index 0000000..ca9c843
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-mct.h
@@ -0,0 +1,52 @@
+/* arch/arm/mach-exynos4/include/mach/regs-mct.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4 MCT configutation
+ *
+ * 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 __ASM_ARCH_REGS_MCT_H
+#define __ASM_ARCH_REGS_MCT_H __FILE__
+
+#include <mach/map.h>
+
+#define EXYNOS4_MCTREG(x) (S5P_VA_SYSTIMER + (x))
+
+#define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT EXYNOS4_MCTREG(0x110)
+
+#define EXYNOS4_MCT_G_COMP0_L EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR EXYNOS4_MCTREG(0x208)
+
+#define EXYNOS4_MCT_G_TCON EXYNOS4_MCTREG(0x240)
+
+#define EXYNOS4_MCT_G_INT_CSTAT EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
+
+#define EXYNOS4_MCT_L0_BASE EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L1_BASE EXYNOS4_MCTREG(0x400)
+
+#define MCT_L_TCNTB_OFFSET (0x00)
+#define MCT_L_ICNTB_OFFSET (0x08)
+#define MCT_L_TCON_OFFSET (0x20)
+#define MCT_L_INT_CSTAT_OFFSET (0x30)
+#define MCT_L_INT_ENB_OFFSET (0x34)
+#define MCT_L_WSTAT_OFFSET (0x40)
+
+#define MCT_G_TCON_START (1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC (1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE (1 << 0)
+
+#define MCT_L_TCON_INTERVAL_MODE (1 << 2)
+#define MCT_L_TCON_INT_START (1 << 1)
+#define MCT_L_TCON_TIMER_START (1 << 0)
+
+#endif /* __ASM_ARCH_REGS_MCT_H */
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
new file mode 100644
index 0000000..6bb4b50
--- /dev/null
+++ b/arch/arm/mach-exynos4/mct.c
@@ -0,0 +1,421 @@
+/* linux/arch/arm/mach-exynos4/mct.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4 MCT(Multi-Core Timer) support
+ *
+ * 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/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/percpu.h>
+
+#include <mach/map.h>
+#include <mach/regs-mct.h>
+#include <asm/mach/time.h>
+
+static unsigned long clk_cnt_per_tick;
+static unsigned long clk_rate;
+
+struct mct_clock_event_device {
+ struct clock_event_device *evt;
+ void __iomem *base;
+};
+
+struct mct_clock_event_device mct_tick[2];
+
+static void exynos4_mct_write(unsigned int value, void *addr)
+{
+ void __iomem *stat_addr;
+ u32 mask;
+ u32 i;
+
+ __raw_writel(value, addr);
+
+ switch ((u32) addr) {
+ case (u32) EXYNOS4_MCT_G_TCON:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 16; /* G_TCON write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_COMP0_L:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 0; /* G_COMP0_L write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_COMP0_U:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 1; /* G_COMP0_U write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+ stat_addr = EXYNOS4_MCT_G_WSTAT;
+ mask = 1 << 2; /* G_COMP0_ADD_INCR write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_CNT_L:
+ stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+ mask = 1 << 0; /* G_CNT_L write status */
+ break;
+ case (u32) EXYNOS4_MCT_G_CNT_U:
+ stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+ mask = 1 << 1; /* G_CNT_U write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
+ stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 3; /* L0_TCON write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
+ stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 3; /* L1_TCON write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 0; /* L0_TCNTB write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 0; /* L1_TCNTB write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 1; /* L0_ICNTB write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 1; /* L1_ICNTB write status */
+ break;
+ default:
+ return;
+ }
+
+ /* Wait maximum 1 ms until written values are applied */
+ for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
+ if (__raw_readl(stat_addr) & mask) {
+ __raw_writel(mask, stat_addr);
+ return;
+ }
+
+ panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+}
+
+/* Clocksource handling */
+static void exynos4_mct_frc_start(u32 hi, u32 lo)
+{
+ u32 reg;
+
+ exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
+ exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
+
+ reg = __raw_readl(EXYNOS4_MCT_G_TCON);
+ reg |= MCT_G_TCON_START;
+ exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
+}
+
+static cycle_t exynos4_frc_read(struct clocksource *cs)
+{
+ unsigned int lo, hi;
+ u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+
+ do {
+ hi = hi2;
+ lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
+ hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+ } while (hi != hi2);
+
+ return ((cycle_t)hi << 32) | lo;
+}
+
+struct clocksource mct_frc = {
+ .name = "mct-frc",
+ .rating = 400,
+ .read = exynos4_frc_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init exynos4_clocksource_init(void)
+{
+ exynos4_mct_frc_start(0, 0);
+
+ if (clocksource_register_hz(&mct_frc, clk_rate))
+ panic("%s: can't register clocksource\n", mct_frc.name);
+}
+
+static void exynos4_mct_comp0_stop(void)
+{
+ unsigned int tcon;
+
+ tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+ tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
+
+ exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
+ exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
+}
+
+static void exynos4_mct_comp0_start(enum clock_event_mode mode,
+ unsigned long cycles)
+{
+ unsigned int tcon;
+ cycle_t comp_cycle;
+
+ tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+
+ if (mode == CLOCK_EVT_MODE_PERIODIC) {
+ tcon |= MCT_G_TCON_COMP0_AUTO_INC;
+ exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
+ }
+
+ comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
+ exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
+ exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
+
+ exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
+
+ tcon |= MCT_G_TCON_COMP0_ENABLE;
+ exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
+}
+
+static int exynos4_comp_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ exynos4_mct_comp0_start(evt->mode, cycles);
+
+ return 0;
+}
+
+static void exynos4_comp_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ exynos4_mct_comp0_stop();
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ exynos4_mct_comp0_start(mode, clk_cnt_per_tick);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device mct_comp_device = {
+ .name = "mct-comp",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 250,
+ .set_next_event = exynos4_comp_set_next_event,
+ .set_mode = exynos4_comp_set_mode,
+};
+
+static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = dev_id;
+
+ exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction mct_comp_event_irq = {
+ .name = "mct_comp_irq",
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = exynos4_mct_comp_isr,
+ .dev_id = &mct_comp_device,
+};
+
+static void exynos4_clockevent_init(void)
+{
+ clk_cnt_per_tick = clk_rate / 2 / HZ;
+
+ clockevents_calc_mult_shift(&mct_comp_device, clk_rate / 2, 5);
+ mct_comp_device.max_delta_ns =
+ clockevent_delta2ns(0xffffffff, &mct_comp_device);
+ mct_comp_device.min_delta_ns =
+ clockevent_delta2ns(0xf, &mct_comp_device);
+ mct_comp_device.cpumask = cpumask_of(0);
+ clockevents_register_device(&mct_comp_device);
+
+ setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+/* Clock event handling */
+static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
+{
+ unsigned long tmp;
+ unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
+ void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+
+ tmp = __raw_readl(addr);
+ if (tmp & mask) {
+ tmp &= ~mask;
+ exynos4_mct_write(tmp, addr);
+ }
+}
+
+static void exynos4_mct_tick_start(unsigned long cycles,
+ struct mct_clock_event_device *mevt)
+{
+ unsigned long tmp;
+
+ exynos4_mct_tick_stop(mevt);
+
+ tmp = (1 << 31) | cycles; /* MCT_L_UPDATE_ICNTB */
+
+ /* update interrupt count buffer */
+ exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
+
+ /* enable MCT tick interupt */
+ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
+
+ tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+ tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
+ MCT_L_TCON_INTERVAL_MODE;
+ exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
+}
+
+static int exynos4_tick_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
+
+ exynos4_mct_tick_start(cycles, mevt);
+
+ return 0;
+}
+
+static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
+
+ exynos4_mct_tick_stop(mevt);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+ struct mct_clock_event_device *mevt = dev_id;
+ struct clock_event_device *evt = mevt->evt;
+
+ /*
+ * This is for supporting oneshot mode.
+ * Mct would generate interrupt periodically
+ * without explicit stopping.
+ */
+ if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
+ exynos4_mct_tick_stop(mevt);
+
+ /* Clear the MCT tick interrupt */
+ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction mct_tick0_event_irq = {
+ .name = "mct_tick0_irq",
+ .flags = IRQF_TIMER | IRQF_NOBALANCING,
+ .handler = exynos4_mct_tick_isr,
+};
+
+static struct irqaction mct_tick1_event_irq = {
+ .name = "mct_tick1_irq",
+ .flags = IRQF_TIMER | IRQF_NOBALANCING,
+ .handler = exynos4_mct_tick_isr,
+};
+
+static void exynos4_mct_tick_init(struct clock_event_device *evt)
+{
+ unsigned int cpu = smp_processor_id();
+
+ mct_tick[cpu].evt = evt;
+
+ if (cpu == 0) {
+ mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
+ evt->name = "mct_tick0";
+ } else {
+ mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
+ evt->name = "mct_tick1";
+ }
+
+ evt->cpumask = cpumask_of(cpu);
+ evt->set_next_event = exynos4_tick_set_next_event;
+ evt->set_mode = exynos4_tick_set_mode;
+ evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ evt->rating = 450;
+
+ clockevents_calc_mult_shift(evt, clk_rate / 2, 5);
+ evt->max_delta_ns =
+ clockevent_delta2ns(0x7fffffff, evt);
+ evt->min_delta_ns =
+ clockevent_delta2ns(0xf, evt);
+
+ clockevents_register_device(evt);
+
+ exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
+
+ if (cpu == 0) {
+ mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+ setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+ } else {
+ mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+ irq_set_affinity(IRQ_MCT1, cpumask_of(1));
+ setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+ }
+}
+
+/* Setup the local clock events for a CPU */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ exynos4_mct_tick_init(evt);
+}
+
+int local_timer_ack(void)
+{
+ return 0;
+}
+
+#endif /* CONFIG_LOCAL_TIMERS */
+
+static void __init exynos4_timer_resources(void)
+{
+ struct clk *mct_clk;
+ mct_clk = clk_get(NULL, "xtal");
+
+ clk_rate = clk_get_rate(mct_clk);
+}
+
+static void __init exynos4_timer_init(void)
+{
+ exynos4_timer_resources();
+ exynos4_clocksource_init();
+ exynos4_clockevent_init();
+}
+
+struct sys_timer exynos4_timer = {
+ .init = exynos4_timer_init,
+};
--
1.7.1
^ permalink raw reply related
* [PATCH 09/09] ARM: s3c2440: gta02: Add touchscreen support
From: Kukjin Kim @ 2011-02-28 6:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-9-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> This patch registers the s3c touchscreen and adc devices to add
touchscreen
> support for the gta02.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 12 ++++++++++++
> 1 files changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index 94456fa..2300ec5 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -79,6 +79,8 @@
> #include <mach/regs-mem.h>
> #include <mach/hardware.h>
>
> +#include <plat/ts.h>
> +
Please group same/similar inclusion together like following.
<linux/...> <asm/...> then <mach/...> or <plat/...>
In other words, please add your <plat/ts.h> inclusion after other <plat/...>
> #include <mach/gta02.h>
>
> #include <plat/regs-serial.h>
> @@ -480,6 +482,13 @@ static struct s3c2410_hcd_info gta02_usb_info
__initdata
> = {
> },
> };
>
> +/* Touchscreen */
> +static struct s3c2410_ts_mach_info gta02_ts_info = {
> + .delay = 10000,
> + .presc = 0xff, /* slow as we can go */
> + .oversampling_shift = 2,
> +};
How about to use tab between member and = like following?
static struct s3c2410_ts_mach_info gta02_ts_info = {
.delay = 10000,
.presc = 0xff, /* slow as we can go */
.oversampling_shift = 2,
};
> +
> /* Buttons */
> static struct gpio_keys_button gta02_buttons[] = {
> {
> @@ -533,6 +542,8 @@ static struct platform_device *gta02_devices[]
__initdata
> = {
> &samsung_asoc_dma,
> &s3c_device_i2c0,
> >a02_buttons_device,
> + &s3c_device_adc,
No need to build plat-samsung/dev-adc.c for this?
If you want to add '&s3c_deivce_adc', should add 'select SAMSUNG_DEV_ADC'
into "config MACH_NEO1973_GTA02".
> + &s3c_device_ts,
'select SAMSUNG_DEV_TS'
> };
>
> /* These guys DO need to be children of PMU. */
> @@ -597,6 +608,7 @@ static void __init gta02_machine_init(void)
> #endif
>
> s3c24xx_udc_set_platdata(>a02_udc_cfg);
> + s3c24xx_ts_set_platdata(>a02_ts_info);
Same as above. 'select SAMSUNG_DEV_TS' should be added for
plat-samsung/dev-ts.c.
> s3c_ohci_set_platdata(>a02_usb_info);
> s3c_nand_set_platdata(>a02_nand_info);
> s3c_i2c0_set_platdata(NULL);
> --
> 1.7.2.3
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH] backlight/platform_lcd: change set power function parameter in plat_lcd_data
From: Donghwa Lee @ 2011-02-28 6:14 UTC (permalink / raw)
To: linux-arm-kernel
In drivers/video/backlight/platform_lcd.c driver, to use lcd power
control function in platdata, it is used
set_power(struct plat_lcd_data *, unsigned int power) callback function.
set_power() function is consists of two parameters,
(struct plat_lcd_data *, unsigned int power).
But actually, there is no one to use (struct plat_lcd_data *), only use
second (unsigned int power) value to control lcd power on/off.
I don't know why (struct plat_lcd_data*) parameter is used in set_power()
callback function. Maybe I think it is unessesntial or changeable to another
meaningful variable. For example, struct lcd_device *, it can be used to
control regulator_get() function.
In mach-nuri.c, it has been patching by Minku Kang, (struct lcd_device*) can be
used to regulator lcd power on/off, and many other machines uses regulator
control to on/off lcd power.
So I think more meaningful variable that (struct lcd_device* ) can be
substituted for unessential variable that (struct plat_lcd_data *).
Thank you,
Donghwa Lee
Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/video/backlight/platform_lcd.c | 2 +-
include/video/platform_lcd.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index 302330a..cf23a3f 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -49,7 +49,7 @@ static int platform_lcd_set_power(struct lcd_device *lcd, int power)
if (power == FB_BLANK_POWERDOWN || plcd->suspended)
lcd_power = 0;
- plcd->pdata->set_power(plcd->pdata, lcd_power);
+ plcd->pdata->set_power(lcd, lcd_power);
plcd->power = power;
return 0;
diff --git a/include/video/platform_lcd.h b/include/video/platform_lcd.h
index ad3bdfe..e92a039 100644
--- a/include/video/platform_lcd.h
+++ b/include/video/platform_lcd.h
@@ -15,7 +15,7 @@ struct plat_lcd_data;
struct fb_info;
struct plat_lcd_data {
- void (*set_power)(struct plat_lcd_data *, unsigned int power);
+ void (*set_power)(struct lcd_device *, unsigned int power);
int (*match_fb)(struct plat_lcd_data *, struct fb_info *);
};
--
1.6.0.4
^ permalink raw reply related
* [PATCH 08/09] ARM: s3c2440: gta02: Request usb pullup pin before using it
From: Kukjin Kim @ 2011-02-28 6:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-8-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> Request the gpio pin used to control the usb pullup before using it to
avoid
> a
> runtime warning about an auto-requested gpio.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 17 +++++++++++++++--
> 1 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index 1396639..94456fa 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -451,11 +451,11 @@ static void gta02_udc_command(enum s3c2410_udc_cmd_e
> cmd)
> switch (cmd) {
> case S3C2410_UDC_P_ENABLE:
> pr_debug("%s S3C2410_UDC_P_ENABLE\n", __func__);
> - gpio_direction_output(GTA02_GPIO_USB_PULLUP, 1);
> + gpio_set_value(GTA02_GPIO_USB_PULLUP, 1);
How about following instead?
gpio_request(GTA02_GPIO_USB_PULLUP, "USB_PULLUP");
gpio_direction_output(GTA02_GPIO_USB_PULLUP, 1);
gpio_free(GTA02_GPIO_USB_PULLUP);
> break;
> case S3C2410_UDC_P_DISABLE:
> pr_debug("%s S3C2410_UDC_P_DISABLE\n", __func__);
> - gpio_direction_output(GTA02_GPIO_USB_PULLUP, 0);
> + gpio_set_value(GTA02_GPIO_USB_PULLUP, 0);
> break;
> case S3C2410_UDC_P_RESET:
> pr_debug("%s S3C2410_UDC_P_RESET\n", __func__);
> @@ -572,11 +572,24 @@ static void gta02_poweroff(void)
> pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
> }
>
> +static void gta02_request_gpios(void)
> +{
> + int ret;
> + ret = gpio_request_one(GTA02_GPIO_USB_PULLUP, GPIOF_OUT_INIT_LOW,
> + "USB pullup");
> + if (ret) {
> + printk(KERN_ERR "Failed to request USB pullup gpio pin:
%d\n",
> + ret);
> + }
> +}
> +
> static void __init gta02_machine_init(void)
> {
> /* Set the panic callback to turn AUX LED on or off. */
> panic_blink = gta02_panic_blink;
>
> + gta02_request_gpios();
> +
> s3c_pm_init();
>
> #ifdef CONFIG_CHARGER_PCF50633
> --
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 06/09] ARM: s3c2440: gta02: Remove state_mem constraints for the pcf50633 regulators
From: Kukjin Kim @ 2011-02-28 6:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-6-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> The pcf50633 regulator driver does not use the state_mem constraints, so
> there
> is no use in setting them.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 15 ---------------
> 1 files changed, 0 insertions(+), 15 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index e57c4d8..01e0930 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -283,9 +283,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> .always_on = 1,
> .apply_uV = 1,
> - .state_mem = {
> - .enabled = 1,
> - },
> },
> },
> [PCF50633_REGULATOR_DOWN1] = {
> @@ -304,9 +301,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> .apply_uV = 1,
> .always_on = 1,
> - .state_mem = {
> - .enabled = 1,
> - },
> },
> },
> [PCF50633_REGULATOR_HCLDO] = {
> @@ -325,9 +319,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> .valid_ops_mask = REGULATOR_CHANGE_STATUS,
> .apply_uV = 1,
> - .state_mem = {
> - .enabled = 0,
> - },
> },
> },
> [PCF50633_REGULATOR_LDO2] = {
> @@ -362,9 +353,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> .valid_ops_mask = REGULATOR_CHANGE_STATUS,
> .apply_uV = 1,
> - .state_mem = {
> - .enabled = 1,
> - },
> },
> },
> [PCF50633_REGULATOR_LDO6] = {
> @@ -379,9 +367,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .min_uV = 1800000,
> .max_uV = 1800000,
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> - .state_mem = {
> - .enabled = 1,
> - },
> },
> },
>
> --
Don't we need regulator_suspend_mem_state_show() on PCF50633?
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 04/09] ARM: s3c2440: gta02: Select missing S3C_DEV_USB_HOST
From: Kukjin Kim @ 2011-02-28 6:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-4-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> The gta02 mach file references the ohci device.
> So we need to select S3C_DEV_USB_HOST to have the device available.
>
> This fixes the following linker errors:
> arch/arm/mach-s3c2440/built-in.o: In function `gta02_machine_init':
> mach-gta02.c:(.init.text+0x370): undefined reference to
> `s3c_ohci_set_platdata'
> arch/arm/mach-s3c2440/built-in.o:(.init.data+0xac): undefined
> reference to `s3c_device_ohci'
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/Kconfig | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
> index a0cb258..50825a3 100644
> --- a/arch/arm/mach-s3c2440/Kconfig
> +++ b/arch/arm/mach-s3c2440/Kconfig
> @@ -99,6 +99,7 @@ config MACH_NEO1973_GTA02
> select POWER_SUPPLY
> select MACH_NEO1973
> select S3C2410_PWM
> + select S3C_DEV_USB_HOST
> help
> Say Y here if you are using the Openmoko GTA02 / Freerunner GSM
> Phone
>
> --
> 1.7.2.3
Ok, applied.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 03/09] ARM: s3c2440: gta02: Add button support
From: Kukjin Kim @ 2011-02-28 6:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-3-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> This patch adds support for the two buttons found on the gta02 device,
which
> are
> connectd to gpio pins, using the gpio-keys driver.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 34
++++++++++++++++++++++++++++++++++
> 1 files changed, 34 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index e83062b..6629998 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -58,6 +58,9 @@
> #include <linux/mfd/pcf50633/pmic.h>
> #include <linux/mfd/pcf50633/backlight.h>
>
> +#include <linux/input.h>
> +#include <linux/gpio_keys.h>
> +
> #include <asm/mach/arch.h>
> #include <asm/mach/map.h>
> #include <asm/mach/irq.h>
> @@ -489,6 +492,36 @@ static struct s3c2410_hcd_info gta02_usb_info
__initdata
> = {
> },
> };
>
> +/* Buttons */
> +static struct gpio_keys_button gta02_buttons[] = {
> + {
> + .gpio = GTA02_GPIO_AUX_KEY,
> + .code = KEY_PHONE,
> + .desc = "Aux",
> + .type = EV_KEY,
> + .debounce_interval = 100,
> + },
> + {
> + .gpio = GTA02_GPIO_HOLD_KEY,
> + .code = KEY_PAUSE,
> + .desc = "Hold",
> + .type = EV_KEY,
> + .debounce_interval = 100,
> + },
> +};
> +
> +static struct gpio_keys_platform_data gta02_buttons_pdata = {
> + .buttons = gta02_buttons,
> + .nbuttons = ARRAY_SIZE(gta02_buttons),
> +};
> +
> +static struct platform_device gta02_buttons_device = {
> + .name = "gpio-keys",
> + .id = -1,
> + .dev = {
> + .platform_data = >a02_buttons_pdata,
> + },
> +};
>
> static void __init gta02_map_io(void)
> {
> @@ -511,6 +544,7 @@ static struct platform_device *gta02_devices[]
__initdata
> = {
> &s3c_device_iis,
> &samsung_asoc_dma,
> &s3c_device_i2c0,
> + >a02_buttons_device,
> };
>
> /* These guys DO need to be children of PMU. */
> --
Ok, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 02/09] ARM: s3c2440: gta02: Register PCM device
From: Kukjin Kim @ 2011-02-28 6:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-2-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> The ASoC multi-component patch introduced a new pcm platform device, which
> needs
> to be registered by board files in order for sound to work.
> This patch does this for the gta02 board.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index 9f2c14e..e83062b 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -509,6 +509,7 @@ static struct platform_device *gta02_devices[]
__initdata
> = {
> >a02_nor_flash,
> &s3c24xx_pwm_device,
> &s3c_device_iis,
> + &samsung_asoc_dma,
> &s3c_device_i2c0,
> };
>
> --
Ok, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 01/09] ARM: s3c2442: gta02: Fix usage gpio bank j pin definitions
From: Kukjin Kim @ 2011-02-28 6:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-1-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> The gta02 header file still uses the old S3C2410_GPJx defines instead of
the
> S3C2410_GPJ(x) macro. Since the S3C2410_GPJx defines have already been
> removed
> this causes the following build failure:
>
> sound/soc/samsung/neo1973_wm8753.c: In function 'lm4853_set_spk':
> sound/soc/samsung/neo1973_wm8753.c:259: error: 'S3C2440_GPJ2'
> undeclared (first use in this function)
> sound/soc/samsung/neo1973_wm8753.c:259: error: (Each undeclared
> identifier is reported only once
> sound/soc/samsung/neo1973_wm8753.c:259: error: for each function it
> appears in.)
> sound/soc/samsung/neo1973_wm8753.c: In function 'lm4853_get_spk':
> sound/soc/samsung/neo1973_wm8753.c:267: error: 'S3C2440_GPJ2'
> undeclared (first use in this function)
> sound/soc/samsung/neo1973_wm8753.c: In function 'lm4853_event':
> sound/soc/samsung/neo1973_wm8753.c:276: error: 'S3C2440_GPJ1'
> undeclared (first use in this function)
> sound/soc/samsung/neo1973_wm8753.c: At top level:
> sound/soc/samsung/neo1973_wm8753.c:439: error: 'S3C2440_GPJ2'
> undeclared here (not in a function)
> sound/soc/samsung/neo1973_wm8753.c:440: error: 'S3C2440_GPJ1'
> undeclared here (not in a function)
>
> This patches fixes the issue by doing a
> s,S3C2410_GPJ([\d]+),S3C2410_GPJ(\1),g
Maybe, "s,S3C2440_GPJ([\d]+),S3C2410_GPJ(\1),g" instead ?
> on the file.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/include/mach/gta02.h | 26
+++++++++++++-------------
> 1 files changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/include/mach/gta02.h b/arch/arm/mach-
> s3c2440/include/mach/gta02.h
> index 953331d..3a56a22 100644
> --- a/arch/arm/mach-s3c2440/include/mach/gta02.h
> +++ b/arch/arm/mach-s3c2440/include/mach/gta02.h
> @@ -44,19 +44,19 @@
> #define GTA02v3_GPIO_nUSB_FLT S3C2410_GPG(10) /* v3 + v4 only */
> #define GTA02v3_GPIO_nGSM_OC S3C2410_GPG(11) /* v3 + v4 only */
>
> -#define GTA02_GPIO_AMP_SHUT S3C2440_GPJ1 /* v2 + v3 + v4 only */
> -#define GTA02v1_GPIO_WLAN_GPIO10 S3C2440_GPJ2
> -#define GTA02_GPIO_HP_IN S3C2440_GPJ2 /* v2 + v3 + v4 only */
> -#define GTA02_GPIO_INT0 S3C2440_GPJ3 /* v2 + v3 + v4 only
*/
> -#define GTA02_GPIO_nGSM_EN S3C2440_GPJ4
> -#define GTA02_GPIO_3D_RESET S3C2440_GPJ5
> -#define GTA02_GPIO_nDL_GSM S3C2440_GPJ6 /* v4 + v5 only */
> -#define GTA02_GPIO_WLAN_GPIO0 S3C2440_GPJ7
> -#define GTA02v1_GPIO_BAT_ID S3C2440_GPJ8
> -#define GTA02_GPIO_KEEPACT S3C2440_GPJ8
> -#define GTA02v1_GPIO_HP_IN S3C2440_GPJ10
> -#define GTA02_CHIP_PWD S3C2440_GPJ11 /* v2 + v3 + v4 only
*/
> -#define GTA02_GPIO_nWLAN_RESET S3C2440_GPJ12 /* v2 + v3 + v4 only
*/
> +#define GTA02_GPIO_AMP_SHUT S3C2410_GPJ(1) /* v2 + v3 + v4 only */
> +#define GTA02v1_GPIO_WLAN_GPIO10 S3C2410_GPJ(2)
> +#define GTA02_GPIO_HP_IN S3C2410_GPJ(2) /* v2 + v3 + v4 only */
> +#define GTA02_GPIO_INT0 S3C2410_GPJ(3) /* v2 + v3 + v4 only
*/
> +#define GTA02_GPIO_nGSM_EN S3C2410_GPJ(4)
> +#define GTA02_GPIO_3D_RESET S3C2410_GPJ(5)
> +#define GTA02_GPIO_nDL_GSM S3C2410_GPJ(6) /* v4 + v5 only */
> +#define GTA02_GPIO_WLAN_GPIO0 S3C2410_GPJ(7)
> +#define GTA02v1_GPIO_BAT_ID S3C2410_GPJ(8)
> +#define GTA02_GPIO_KEEPACT S3C2410_GPJ(8)
> +#define GTA02v1_GPIO_HP_IN S3C2410_GPJ(10)
> +#define GTA02_CHIP_PWD S3C2410_GPJ(11) /* v2 + v3 + v4
> only */
> +#define GTA02_GPIO_nWLAN_RESET S3C2410_GPJ(12) /* v2 + v3 + v4
> only */
>
> #define GTA02_IRQ_GSENSOR_1 IRQ_EINT0
> #define GTA02_IRQ_MODEM IRQ_EINT1
> --
> 1.7.2.3
Yeah, old S3C2440_GPJx has removed.
Is the S3C2410_GPJ(1) right instead of S3C2440_GPJ1?
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH v2 07/09] ARM: s3c2440: gta02: Call regulator_has_full_constraints
From: Kukjin Kim @ 2011-02-28 6:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297133720-18178-1-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> This allows the regulator core to disable all regulators which are not in
use
> at the end of the kernel init phase.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index 01e0930..2682592 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -590,6 +590,8 @@ static void __init gta02_machine_init(void)
>
> platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
> pm_power_off = gta02_poweroff;
> +
> + regulator_has_full_constraints();
> }
>
>
> --
Ok, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 05/09] ARM: s3c2440: gta02: Fix regulator valid_modes_ops
From: Kukjin Kim @ 2011-02-28 6:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297043521-21903-5-git-send-email-lars@metafoo.de>
Lars-Peter Clausen wrote:
>
> The REGULATOR_CHANGE_STATUS flag needs to be set on valid_ops_mask,
otherwise
> it
> a driver wont be able to turn the regulator on or off.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c | 7 +++++--
> 1 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c
b/arch/arm/mach-s3c2440/mach-
> gta02.c
> index 6629998..e57c4d8 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -314,8 +314,8 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .min_uV = 2000000,
> .max_uV = 3300000,
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
> - .always_on = 1,
> + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
> + REGULATOR_CHANGE_STATUS,
> },
> },
> [PCF50633_REGULATOR_LDO1] = {
> @@ -323,6 +323,7 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .min_uV = 3300000,
> .max_uV = 3300000,
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
> .apply_uV = 1,
> .state_mem = {
> .enabled = 0,
> @@ -350,6 +351,7 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .min_uV = 3200000,
> .max_uV = 3200000,
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
> .apply_uV = 1,
> },
> },
> @@ -358,6 +360,7 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
> .min_uV = 3000000,
> .max_uV = 3000000,
> .valid_modes_mask = REGULATOR_MODE_NORMAL,
> + .valid_ops_mask = REGULATOR_CHANGE_STATUS,
> .apply_uV = 1,
> .state_mem = {
> .enabled = 1,
> --
Ok, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH v10 05/18] OMAP2,3 DSS2 Change driver name to omap_display
From: Tomi Valkeinen @ 2011-02-28 6:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298539643.16119.54.camel@deskari>
On Thu, 2011-02-24 at 03:27 -0600, Tomi Valkeinen wrote:
> Hi,
>
> On Mon, 2011-01-24 at 11:51 +0530, ext Sumit Semwal wrote:
> > From: Senthilvadivu Guruswamy <svadivu@ti.com>
> >
> > Change the driver name from omapdss to omap_display as the driver takes care of
> > the display devices ie number of panels, type of panels available in the
> > platform. Change the device name in the board files and 2420,2430,3xxx clock
> > files from omapdss to omap_display to match the driver name.
>
> I just realized that changing the driver name will break all scripts and
> applications using omapdss sysfs files.
>
> How does this sound:
>
> Let's leave the omapdss device name as it is. It represents a "super"
> device, containing the dss sysfs files and upper level dss management.
>
> Name the HW module platform drivers as: omapdss_dss, omapdss_venc,
> omapdss_dispc, etc. This would indicate them to be clearly parts of DSS,
> and would also prevent any possible name conflict if there would happen
> to be a, say, "dsi" block in some other HW component.
Any comments on this?
Tomi
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox