* RE: [PATCH 2/3 v3] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Zang Roy-R61911 @ 2010-09-16 10:08 UTC (permalink / raw)
To: Anton Vorontsov
Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
linux-mtd, akpm, dwmw2, Gala Kumar-B11780
In-Reply-To: <20100916092551.GA17548@oksana.dev.rtsoft.ru>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIFNlcHRl
bWJlciAxNiwgMjAxMCAxNzoyNiBQTQ0KPiBUbzogWmFuZyBSb3ktUjYxOTExDQo+IENjOiBsaW51
eC1tdGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsgZHdtdzJAaW5mcmFkZWFkLm9yZzsgZGVkZWtpbmQx
QGdtYWlsLmNvbTsNCj4gYWtwbUBsaW51eC1mb3VuZGF0aW9uLm9yZzsgTGFuIENodW5oZS1CMjU4
MDY7IFdvb2QgU2NvdHQtQjA3NDIxOyBHYWxhIEt1bWFyLQ0KPiBCMTE3ODA7IGxpbnV4cHBjLWRl
dkBvemxhYnMub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggMi8zIHYzXSBQNDA4MC9tdGQ6IE9u
bHkgbWFrZSBlbGJjIG5hbmQgZHJpdmVyIGRldGVjdCBuYW5kDQo+IGZsYXNoIHBhcnRpdGlvbnMN
Cj4gDQo+IE9uIFRodSwgU2VwIDE2LCAyMDEwIGF0IDA0OjUwOjA1UE0gKzA4MDAsIFphbmcgUm95
LVI2MTkxMSB3cm90ZToNCj4gPiA+IE9uIFRodSwgU2VwIDE2LCAyMDEwIGF0IDAyOjQxOjIzUE0g
KzA4MDAsIFJveSBaYW5nIHdyb3RlOg0KPiA+ID4gWy4uLl0NCj4gPiA+ID4gLXN0YXRpYyBpbnQg
X19kZXZpbml0IGZzbF9lbGJjX2NoaXBfcHJvYmUoc3RydWN0IGZzbF9lbGJjX2N0cmwgKmN0cmws
DQo+ID4gPiA+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBk
ZXZpY2Vfbm9kZSAqbm9kZSkNCj4gPiA+ID4gKy8qDQo+ID4gPiA+ICsgKiBDdXJyZW50bHkgb25s
eSBvbmUgZWxiYyBwcm9iZSBpcyBzdXBwb3J0ZWQuDQo+ID4gPiA+ICsgKi8NCj4gPiA+ID4gK3N0
YXRpYyBpbnQgX19kZXZpbml0IGZzbF9lbGJjX25hbmRfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rl
dmljZSAqZGV2KQ0KPiA+ID4gPiAgew0KPiA+ID4gPiAtICAgICBzdHJ1Y3QgZnNsX2xiY19yZWdz
IF9faW9tZW0gKmxiYyA9IGN0cmwtPnJlZ3M7DQo+ID4gPiA+ICsgICAgIHN0cnVjdCBmc2xfbGJj
X3JlZ3MgX19pb21lbSAqbGJjOw0KPiA+ID4gPiAgICAgICBzdHJ1Y3QgZnNsX2VsYmNfbXRkICpw
cml2Ow0KPiA+ID4gPiAgICAgICBzdHJ1Y3QgcmVzb3VyY2UgcmVzOw0KPiA+ID4gPiArICAgICBz
dHJ1Y3QgZnNsX2VsYmNfZmNtX2N0cmwgKmVsYmNfZmNtX2N0cmwgPSBOVUxMOw0KPiA+ID4gWy4u
Ll0NCj4gPiA+ID4gLSAgICAgY3RybC0+Y2hpcHNbYmFua10gPSBwcml2Ow0KPiA+ID4gPiArICAg
ICBpZiAoZnNsX2xiY19jdHJsX2Rldi0+bmFuZCA9PSBOVUxMKSB7DQo+ID4gPiA+ICsgICAgICAg
ICAgICAgZWxiY19mY21fY3RybCA9IGt6YWxsb2Moc2l6ZW9mKCplbGJjX2ZjbV9jdHJsKSwNCj4g
R0ZQX0tFUk5FTCk7DQo+ID4gPiA+ICsgICAgICAgICAgICAgaWYgKCFlbGJjX2ZjbV9jdHJsKSB7
DQo+ID4gPiBbLi4uXQ0KPiA+ID4gPiArICAgICAgICAgICAgICAgICAgICAgZ290byBlcnI7DQo+
ID4gPiA+ICsgICAgICAgICAgICAgfQ0KPiA+ID4gPiArICAgICAgICAgICAgIGZzbF9sYmNfY3Ry
bF9kZXYtPm5hbmQgPSBlbGJjX2ZjbV9jdHJsOw0KPiA+ID4gPiArICAgICB9DQo+ID4gPiA+ICsN
Cj4gPiA+ID4gKyAgICAgZWxiY19mY21fY3RybC0+Y2hpcHNbYmFua10gPSBwcml2Ow0KPiA+ID4N
Cj4gPiA+IEFnYWluLCB0aGlzIHdpbGwgb29wcyBvbiB0aGUgc2Vjb25kIHByb2JlLg0KPiA+IFdo
eT8NCj4gDQo+IEJlY2F1c2Ugb2YgYSBOVUxMIGRlcmVmZXJlbmNlICgiZWxiY19mY21fY3RybC0+
IikuDQo+IA0KPiBJIHVuZGVyc3RhbmQgdGhhdCB5b3UgZG9uJ3QgaGF2ZSB0byBiZWxpZXZlIG1l
LCBidXQgd2lsbCB5b3UgYmVsaWV2ZQ0KPiBhIGNvbXBpbGVyPw0KPiANCj4gb2tzYW5hOn4kIGNh
dCBhLmMNCj4gI2luY2x1ZGUgPHN0ZGlvLmg+DQo+ICNpbmNsdWRlIDxtYWxsb2MuaD4NCj4gDQo+
IGNoYXIgKmZvbzsNCj4gDQo+IHZvaWQgcHJvYmUodm9pZCkNCj4gew0KPiAgICAgICAgIGNoYXIg
KmJhciA9IE5VTEw7DQo+IA0KPiAgICAgICAgIGlmICghZm9vKSB7DQo+ICAgICAgICAgICAgICAg
ICBiYXIgPSBtYWxsb2Moc2l6ZW9mKCpiYXIpKTsNCj4gICAgICAgICAgICAgICAgIGlmICghYmFy
KQ0KPiAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47DQo+ICAgICAgICAgICAgICAgICBm
b28gPSBiYXI7DQo+ICAgICAgICAgfQ0KPiAgICAgICAgICpiYXIgPSAnYSc7DQo+IH0NCj4gDQo+
IGludCBtYWluKHZvaWQpDQo+IHsNCj4gICAgICAgICBwcm9iZSgpOw0KPiAgICAgICAgIHByb2Jl
KCk7DQo+ICAgICAgICAgcmV0dXJuIDA7DQo+IH0NCj4gb2tzYW5hOn4kIGdjYyBhLmMgJiYgLi9h
Lm91dA0KPiBTZWdtZW50YXRpb24gZmF1bHQNCkludGVyZXN0aW5nLg0KSG93IGFib3V0IHRoaXM/
DQojaW5jbHVkZSA8c3RkaW8uaD4NCiNpbmNsdWRlIDxtYWxsb2MuaD4NCg0KY2hhciAqZm9vOw0K
DQp2b2lkIHByb2JlKHZvaWQpDQp7DQogICAgICAgIGNoYXIgKmJhciA9IE5VTEw7DQoNCiAgICAg
ICAgaWYgKCFmb28pIHsNCiAgICAgICAgICAgICAgICBiYXIgPSBtYWxsb2Moc2l6ZW9mKCpiYXIp
KTsNCiAgICAgICAgICAgICAgICBpZiAoIWJhcikNCiAgICAgICAgICAgICAgICAgICAgICAgIHJl
dHVybjsNCiAgICAgICAgICAgICAgICBmb28gPSBiYXI7DQogICAgICAgIH0gZWxzZQ0KCQkgICBi
YXIgPSBmb287CSAgDQogICAgICAgICpiYXIgPSAnYSc7DQp9DQoNCmludCBtYWluKHZvaWQpDQp7
DQogICAgICAgIHByb2JlKCk7DQogICAgICAgIHByb2JlKCk7DQogICAgICAgIHJldHVybiAwOw0K
fQ0KDQo=
^ permalink raw reply
* Re: Reserved pages in PowerPC
From: Benjamin Herrenschmidt @ 2010-09-16 10:04 UTC (permalink / raw)
To: Ankita Garg; +Cc: linuxppc-dev, linux-mm
In-Reply-To: <20100916052311.GC2332@in.ibm.com>
On Thu, 2010-09-16 at 10:53 +0530, Ankita Garg wrote:
>
> With some debugging I found that that section has reserved pages. On
> instrumenting the memblock_reserve() and reserve_bootmem() routines, I can see
> that many of the memory areas are reserved for kernel and initrd by the
> memblock reserve() itself. reserve_bootmem then looks at the pages already
> reserved and marks them reserved. However, for the very last section, I see
> that bootmem reserves it but I am unable to find a corresponding reservation
> by the memblock code.
It's probably RTAS (firmware runtime services). I'ts instanciated at
boot from prom_init and we do favor high addresses for it below 1G iirc.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 2/3 v3] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Anton Vorontsov @ 2010-09-16 9:25 UTC (permalink / raw)
To: Zang Roy-R61911
Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
linux-mtd, akpm, dwmw2, Gala Kumar-B11780
In-Reply-To: <3850A844E6A3854C827AC5C0BEC7B60A1FC6B8@zch01exm23.fsl.freescale.net>
On Thu, Sep 16, 2010 at 04:50:05PM +0800, Zang Roy-R61911 wrote:
> > On Thu, Sep 16, 2010 at 02:41:23PM +0800, Roy Zang wrote:
> > [...]
> > > -static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
> > > - struct device_node *node)
> > > +/*
> > > + * Currently only one elbc probe is supported.
> > > + */
> > > +static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
> > > {
> > > - struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > > + struct fsl_lbc_regs __iomem *lbc;
> > > struct fsl_elbc_mtd *priv;
> > > struct resource res;
> > > + struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> > [...]
> > > - ctrl->chips[bank] = priv;
> > > + if (fsl_lbc_ctrl_dev->nand == NULL) {
> > > + elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
> > > + if (!elbc_fcm_ctrl) {
> > [...]
> > > + goto err;
> > > + }
> > > + fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
> > > + }
> > > +
> > > + elbc_fcm_ctrl->chips[bank] = priv;
> >
> > Again, this will oops on the second probe.
> Why?
Because of a NULL dereference ("elbc_fcm_ctrl->").
I understand that you don't have to believe me, but will you believe
a compiler?
oksana:~$ cat a.c
#include <stdio.h>
#include <malloc.h>
char *foo;
void probe(void)
{
char *bar = NULL;
if (!foo) {
bar = malloc(sizeof(*bar));
if (!bar)
return;
foo = bar;
}
*bar = 'a';
}
int main(void)
{
probe();
probe();
return 0;
}
oksana:~$ gcc a.c && ./a.out
Segmentation fault
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* RE: [PATCH 2/3 v3] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Zang Roy-R61911 @ 2010-09-16 8:50 UTC (permalink / raw)
To: Anton Vorontsov
Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
linux-mtd, akpm, dwmw2, Gala Kumar-B11780
In-Reply-To: <20100916082141.GA10978@oksana.dev.rtsoft.ru>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIFNlcHRl
bWJlciAxNiwgMjAxMCAxNjoyMiBQTQ0KPiBUbzogWmFuZyBSb3ktUjYxOTExDQo+IENjOiBsaW51
eC1tdGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsgZHdtdzJAaW5mcmFkZWFkLm9yZzsgZGVkZWtpbmQx
QGdtYWlsLmNvbTsNCj4gYWtwbUBsaW51eC1mb3VuZGF0aW9uLm9yZzsgTGFuIENodW5oZS1CMjU4
MDY7IFdvb2QgU2NvdHQtQjA3NDIxOyBHYWxhIEt1bWFyLQ0KPiBCMTE3ODA7IGxpbnV4cHBjLWRl
dkBvemxhYnMub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggMi8zIHYzXSBQNDA4MC9tdGQ6IE9u
bHkgbWFrZSBlbGJjIG5hbmQgZHJpdmVyIGRldGVjdCBuYW5kDQo+IGZsYXNoIHBhcnRpdGlvbnMN
Cj4gDQo+IE9uIFRodSwgU2VwIDE2LCAyMDEwIGF0IDAyOjQxOjIzUE0gKzA4MDAsIFJveSBaYW5n
IHdyb3RlOg0KPiBbLi4uXQ0KPiA+IC1zdGF0aWMgaW50IF9fZGV2aW5pdCBmc2xfZWxiY19jaGlw
X3Byb2JlKHN0cnVjdCBmc2xfZWxiY19jdHJsICpjdHJsLA0KPiA+IC0gICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBkZXZpY2Vfbm9kZSAqbm9kZSkNCj4gPiArLyoN
Cj4gPiArICogQ3VycmVudGx5IG9ubHkgb25lIGVsYmMgcHJvYmUgaXMgc3VwcG9ydGVkLg0KPiA+
ICsgKi8NCj4gPiArc3RhdGljIGludCBfX2RldmluaXQgZnNsX2VsYmNfbmFuZF9wcm9iZShzdHJ1
Y3QgcGxhdGZvcm1fZGV2aWNlICpkZXYpDQo+ID4gIHsNCj4gPiAtICAgICBzdHJ1Y3QgZnNsX2xi
Y19yZWdzIF9faW9tZW0gKmxiYyA9IGN0cmwtPnJlZ3M7DQo+ID4gKyAgICAgc3RydWN0IGZzbF9s
YmNfcmVncyBfX2lvbWVtICpsYmM7DQo+ID4gICAgICAgc3RydWN0IGZzbF9lbGJjX210ZCAqcHJp
djsNCj4gPiAgICAgICBzdHJ1Y3QgcmVzb3VyY2UgcmVzOw0KPiA+ICsgICAgIHN0cnVjdCBmc2xf
ZWxiY19mY21fY3RybCAqZWxiY19mY21fY3RybCA9IE5VTEw7DQo+IFsuLi5dDQo+ID4gLSAgICAg
Y3RybC0+Y2hpcHNbYmFua10gPSBwcml2Ow0KPiA+ICsgICAgIGlmIChmc2xfbGJjX2N0cmxfZGV2
LT5uYW5kID09IE5VTEwpIHsNCj4gPiArICAgICAgICAgICAgIGVsYmNfZmNtX2N0cmwgPSBremFs
bG9jKHNpemVvZigqZWxiY19mY21fY3RybCksIEdGUF9LRVJORUwpOw0KPiA+ICsgICAgICAgICAg
ICAgaWYgKCFlbGJjX2ZjbV9jdHJsKSB7DQo+IFsuLi5dDQo+ID4gKyAgICAgICAgICAgICAgICAg
ICAgIGdvdG8gZXJyOw0KPiA+ICsgICAgICAgICAgICAgfQ0KPiA+ICsgICAgICAgICAgICAgZnNs
X2xiY19jdHJsX2Rldi0+bmFuZCA9IGVsYmNfZmNtX2N0cmw7DQo+ID4gKyAgICAgfQ0KPiA+ICsN
Cj4gPiArICAgICBlbGJjX2ZjbV9jdHJsLT5jaGlwc1tiYW5rXSA9IHByaXY7DQo+IA0KPiBBZ2Fp
biwgdGhpcyB3aWxsIG9vcHMgb24gdGhlIHNlY29uZCBwcm9iZS4NCldoeT8NCg0KPiBBbmQgeW91
IHN0aWxsIGRvbid0DQo+IGxvY2sgZnNsX2xiY19jdHJsX2Rldi0+bmFuZCBkdXJpbmcgY2hlY2st
dGhlbi1hc3NpZ25tZW50LCBzbw0KPiB3aXRoIHBhcmFsbGVsIHByb2JpbmcgdGhlcmUgd2lsbCBi
ZSBhIHJhY2UuIDotKA0KPiANCj4gV2UgZG8gaGF2ZSBib2FyZHMgd2l0aCBzZXZlcmFsIE5BTkQg
Y2hpcHMgKGUuZy4NCj4gYXJjaC9wb3dlcnBjL2Jvb3QvZHRzL21wYzg2MTBfaHBjZC5kdHMpLCBz
byB0aGVzZSBpc3N1ZXMNCj4gYXJlIGFsbCBsZWdpdGltYXRlLg0KT0suIEkgY2FuIGFkZCBhIG11
dGV4IGhlcmUuDQpUaGFua3MuDQpSb3kNCg0K
^ permalink raw reply
* Re: [PATCH 2/3 v3] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Anton Vorontsov @ 2010-09-16 8:21 UTC (permalink / raw)
To: Roy Zang
Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2,
B11780
In-Reply-To: <1284619284-23614-2-git-send-email-tie-fei.zang@freescale.com>
On Thu, Sep 16, 2010 at 02:41:23PM +0800, Roy Zang wrote:
[...]
> -static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
> - struct device_node *node)
> +/*
> + * Currently only one elbc probe is supported.
> + */
> +static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
> {
> - struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> + struct fsl_lbc_regs __iomem *lbc;
> struct fsl_elbc_mtd *priv;
> struct resource res;
> + struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
[...]
> - ctrl->chips[bank] = priv;
> + if (fsl_lbc_ctrl_dev->nand == NULL) {
> + elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
> + if (!elbc_fcm_ctrl) {
[...]
> + goto err;
> + }
> + fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
> + }
> +
> + elbc_fcm_ctrl->chips[bank] = priv;
Again, this will oops on the second probe. And you still don't
lock fsl_lbc_ctrl_dev->nand during check-then-assignment, so
with parallel probing there will be a race. :-(
We do have boards with several NAND chips (e.g.
arch/powerpc/boot/dts/mpc8610_hpcd.dts), so these issues
are all legitimate.
Thanks,
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: Generating elf kernel ?
From: tiejun.chen @ 2010-09-16 7:51 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
In-Reply-To: <201009160925.50082.dargaud@lpsc.in2p3.fr>
Guillaume Dargaud wrote:
>>>> Please use simpleImage.<your target dts name>.elf.
>>> Great, that seems to be it...
>>> Except that nothing happens when I jump to 0x40000, no message from the
>> 0x40000? I recalled the entry point should be 0x400000 for
>> simepleImage.*.elf. So you have to change this on the file,
>> arch/powerpc/boot/wrapper.
>
> Correct, I skipped a zero, the address is indeed 0x400000
>
>> And also you should confirm if the upstream kernel support your board.
>
> Our board is a custom derivative from a ML405.
Understood.
So I recommend you use the kernel tree from xilinx. You can refer to the
following website:
http://xilinx.wikidot.com/powerpc-linux
I hope you can skip many issues to accelerate your progress based on the xilinx
kernel.
> My previous project uses ARCH=PPC and has been working fine for 2 years.
> I'm currently trying to go to ARCH=PowerPC and understand dts files in order to
> boot my first kernel.
> I assume I shouldn't have to change anything in my bootloader.
> After I jump to the kernel address, I don't even get the usual:
> loaded at: 00400000 004F559C
> board data at: 004F3520 004F359C
> relocated to: 0040505C 004050D8
> zimage at: 00405E48 004F211C
> avail ram: 004F6000 08000000
> Linux/PPC load: console=ttyUL0,115200 rw root=/dev/nfs ip=bootp
> Uncompressing Linux...done.
> Now booting the kernel
>
> Something wrong with my serial console ?
You have to check if you go the correct PC address. Note please check the real
pc address according to the previous comments.
If yes you can check where your kernel stop. Certainly if you have some tools,
such as JTAG debug tools it's convenient to track this. But if no it will be
difficult to go no next.
But you still have ways to do, such as display LED, early printk, and dump
__log_buf.
>
>> Additionally let's assume your bootloader create the map between the
>> virtual address and the physical address as 1:1. If so you want to execute
>> from 0x40000. But the actual PC address should be the loader address +
>> offset. You can get this by readelf. Here if your loader address is zero,
>> the offset will be pc address, not 0x40000. You can dump your memory to
>> check this.
>
> The bootloader has no concept of virtual address, right ?
This should be depend on the given PPC core. For example, we cannot disable MMU
on e500. Bur for ML405 we can disable MMU to run real mode on 405.
Cheers
Tiejun
>
^ permalink raw reply
* Re: cuImage and multi image?
From: Shawn Jin @ 2010-09-16 7:49 UTC (permalink / raw)
To: tiejun.chen; +Cc: ppcdev, uboot
In-Reply-To: <4C91C77B.8080501@windriver.com>
> Try the following steps:
> ------
> 1. cp <your ramdisk.gz> arch/powerpc/boot/ramdisk.image.gz
> 2. make cuImage.initrd.<your target>
>
> You can get one Image, cuImage.initrd.<your target>, including kernel and ramdisk.
Cool! Thanks a lot, Tiejun.
-Shawn.
^ permalink raw reply
* Re: [PATCH] spi_mpc8xxx: fix writing to adress 0
From: Joakim Tjernlund @ 2010-09-16 7:39 UTC (permalink / raw)
To: christophe leroy
Cc: spi-devel-general, David Brownell, linuxppc-dev, linux-kernel
In-Reply-To: <20100916070420.95083C7391@messagerie.si.c-s.fr>
> From: christophe leroy <christophe.leroy@c-s.fr>
> To: David Brownell <dbrownell@users.sourceforge.net>, Grant Likely
> <grant.likely@secretlab.ca>, spi-devel-general@lists.sourceforge.net, linux-
> kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
> Date: 2010/09/16 09:06
> Subject: [PATCH] spi_mpc8xxx: fix writing to adress 0
> Sent by: linuxppc-dev-bounces+joakim.tjernlund=transmode.se@lists.ozlabs.org
>
> This patch applies to 2.6.34.7 (already included in 2.6.35.4)
> It fixes an issue when sending only or receiving only (mspi->tx-dma was reset
> as when no tx_buf is defined, tx_dma is 0)
>
> Signed-off-by: christophe leroy <christophe.leroy@c-s.fr>
Acked-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
^ permalink raw reply
* Re: [PATCH] spi_mpc8xxx: fix buffer overrun when sending only/receiving only more than PAGE_SIZE bytes
From: Joakim Tjernlund @ 2010-09-16 7:40 UTC (permalink / raw)
To: christophe leroy
Cc: spi-devel-general, David Brownell, linuxppc-dev, linux-kernel
In-Reply-To: <20100916070525.4882CC7391@messagerie.si.c-s.fr>
> From: christophe leroy <christophe.leroy@c-s.fr>
> To: David Brownell <dbrownell@users.sourceforge.net>, Grant Likely
> <grant.likely@secretlab.ca>, spi-devel-general@lists.sourceforge.net, linux-
> kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
> Date: 2010/09/16 09:07
> Subject: [PATCH] spi_mpc8xxx: fix buffer overrun when sending only/receiving
> only more than PAGE_SIZE bytes
> Sent by: linuxppc-dev-bounces+joakim.tjernlund=transmode.se@lists.ozlabs.org
>
> This patch applies to 2.6.34.7 and 2.6.35.4
> It fixes an issue when sending only or receiving only more than PAGE_SIZE bytes
>
> Signed-off-by: christophe leroy <christophe.leroy@c-s.fr>
Acked-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
^ permalink raw reply
* RE: [PATCH 3/3 v3] P4080/mtd: Fix the freescale lbc issue with 36bit mode
From: Zang Roy-R61911 @ 2010-09-16 7:36 UTC (permalink / raw)
To: Anton Vorontsov
Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
linux-mtd, akpm, dwmw2, Gala Kumar-B11780
In-Reply-To: <20100916073135.GA5431@oksana.dev.rtsoft.ru>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIFNlcHRl
bWJlciAxNiwgMjAxMCAxNTozMiBQTQ0KPiBUbzogWmFuZyBSb3ktUjYxOTExDQo+IENjOiBsaW51
eC1tdGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsgZHdtdzJAaW5mcmFkZWFkLm9yZzsgZGVkZWtpbmQx
QGdtYWlsLmNvbTsNCj4gYWtwbUBsaW51eC1mb3VuZGF0aW9uLm9yZzsgTGFuIENodW5oZS1CMjU4
MDY7IFdvb2QgU2NvdHQtQjA3NDIxOyBHYWxhIEt1bWFyLQ0KPiBCMTE3ODA7IGxpbnV4cHBjLWRl
dkBvemxhYnMub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggMy8zIHYzXSBQNDA4MC9tdGQ6IEZp
eCB0aGUgZnJlZXNjYWxlIGxiYyBpc3N1ZSB3aXRoIDM2Yml0DQo+IG1vZGUNCj4gDQo+IE9uIFRo
dSwgU2VwIDE2LCAyMDEwIGF0IDAyOjQxOjI0UE0gKzA4MDAsIFJveSBaYW5nIHdyb3RlOg0KPiA+
IEZyb206IExhbiBDaHVuaGUtQjI1ODA2IDxiMjU4MDZAZnJlZXNjYWxlLmNvbT4NCj4gPg0KPiA+
IFdoZW4gc3lzdGVtIHVzZXMgMzZiaXQgcGh5c2ljYWwgYWRkcmVzcywgcmVzLnN0YXJ0IGlzIDM2
Yml0DQo+ID4gcGh5c2ljYWwgYWRkcmVzcy4gQnV0IHRoZSBmdW5jdGlvbiBvZiBpbl9iZTMyIHJl
dHVybnMgMzJiaXQNCj4gPiBwaHlzaWNhbCBhZGRyZXNzLiBUaGVuIGJvdGggb2YgdGhlbSBjb21w
YXJlZCBlYWNoIG90aGVyIGlzDQo+ID4gd3JvbmcuIFNvIGJ5IGNvbnZlcnRpbmcgdGhlIGFkZHJl
c3Mgb2YgcmVzLnN0YXJ0IGludG8NCj4gPiB0aGUgcmlnaHQgZm9ybWF0IGZpeGVzIHRoaXMgaXNz
dWUuDQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBMYW4gQ2h1bmhlLUIyNTgwNiA8YjI1ODA2QGZy
ZWVzY2FsZS5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTogUm95IFphbmcgPHRpZS1mZWkuemFuZ0Bm
cmVlc2NhbGUuY29tPg0KPiA+IC0tLQ0KPiA+ICBhcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20vZnNs
X2xiYy5oIHwgICAgMSArDQo+ID4gIGFyY2gvcG93ZXJwYy9zeXNkZXYvZnNsX2xiYy5jICAgICAg
fCAgIDIzICsrKysrKysrKysrKysrKysrKysrKystDQo+ID4gIGRyaXZlcnMvbXRkL25hbmQvZnNs
X2VsYmNfbmFuZC5jICAgfCAgICAyICstDQo+ID4gIDMgZmlsZXMgY2hhbmdlZCwgMjQgaW5zZXJ0
aW9ucygrKSwgMiBkZWxldGlvbnMoLSkNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9hcmNoL3Bvd2Vy
cGMvaW5jbHVkZS9hc20vZnNsX2xiYy5oDQo+IGIvYXJjaC9wb3dlcnBjL2luY2x1ZGUvYXNtL2Zz
bF9sYmMuaA0KPiA+IGluZGV4IGRiOTQ2OTguLjU2MzhiMWUgMTAwNjQ0DQo+ID4gLS0tIGEvYXJj
aC9wb3dlcnBjL2luY2x1ZGUvYXNtL2ZzbF9sYmMuaA0KPiA+ICsrKyBiL2FyY2gvcG93ZXJwYy9p
bmNsdWRlL2FzbS9mc2xfbGJjLmgNCj4gPiBAQCAtMjQ2LDYgKzI0Niw3IEBAIHN0cnVjdCBmc2xf
dXBtIHsNCj4gPiAgCWludCB3aWR0aDsNCj4gPiAgfTsNCj4gPg0KPiA+ICtleHRlcm4gdW5zaWdu
ZWQgaW50IGZzbF9sYmNfYWRkcihwaHlzX2FkZHJfdCBhZGRyX2Jhc2UpOw0KPiANCj4gdTMyIGhl
cmUuDQo+IA0KPiBPdGhlciB0aGFuIHRoYXQsIHRoZSBwYXRjaCBsb29rcyBnb29kLg0KPiANCj4g
UmV2aWV3ZWQtYnk6IEFudG9uIFZvcm9udHNvdiA8Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbT4NCkkg
d2lsbCBjb3JyZWN0IHRoaXMgdG9nZXRoZXIgd2l0aCBwcmV2aW91cyBwYXRjaGVzLg0KRG8geW91
IGhhdmUgYW55IG1vcmUgY29tbWVudHMgZm9yIHRoZSBwcmV2aW91cyB0d28gcGF0Y2hlcz8NClRo
YW5rcy4NClJveQ0K
^ permalink raw reply
* Re: [PATCH 3/3 v3] P4080/mtd: Fix the freescale lbc issue with 36bit mode
From: Anton Vorontsov @ 2010-09-16 7:31 UTC (permalink / raw)
To: Roy Zang
Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2,
B11780
In-Reply-To: <1284619284-23614-3-git-send-email-tie-fei.zang@freescale.com>
On Thu, Sep 16, 2010 at 02:41:24PM +0800, Roy Zang wrote:
> From: Lan Chunhe-B25806 <b25806@freescale.com>
>
> When system uses 36bit physical address, res.start is 36bit
> physical address. But the function of in_be32 returns 32bit
> physical address. Then both of them compared each other is
> wrong. So by converting the address of res.start into
> the right format fixes this issue.
>
> Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> ---
> arch/powerpc/include/asm/fsl_lbc.h | 1 +
> arch/powerpc/sysdev/fsl_lbc.c | 23 ++++++++++++++++++++++-
> drivers/mtd/nand/fsl_elbc_nand.c | 2 +-
> 3 files changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
> index db94698..5638b1e 100644
> --- a/arch/powerpc/include/asm/fsl_lbc.h
> +++ b/arch/powerpc/include/asm/fsl_lbc.h
> @@ -246,6 +246,7 @@ struct fsl_upm {
> int width;
> };
>
> +extern unsigned int fsl_lbc_addr(phys_addr_t addr_base);
u32 here.
Other than that, the patch looks good.
Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>
Thanks!
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: cuImage and multi image?
From: tiejun.chen @ 2010-09-16 7:30 UTC (permalink / raw)
To: Shawn Jin; +Cc: ppcdev, uboot
In-Reply-To: <AANLkTinhvh+G1Q8yU0y5bMDVi5Sc=pYqSfAbXCeuHvBH@mail.gmail.com>
Shawn Jin wrote:
> Hi,
>
> I have a cuImage kernel in order to support legacy u-boot and a
> ramdisk image. Kernel boots fine if these two images are separate and
> "bootm $kernel $ramdisk" is used. But I can not make it to work using
> a single multi image that contains the kernel and ramdisk images. Is
> it even technically possible to boot a multi-image with cuboot
> wrapper?
Try the following steps:
------
1. cp <your ramdisk.gz> arch/powerpc/boot/ramdisk.image.gz
2. make cuImage.initrd.<your target>
You can get one Image, cuImage.initrd.<your target>, including kernel and ramdisk.
Cheers
Tiejun
>
> On the cuImage kernel I have load address set to 0x400000 and the
> entry address set to 0x400554 due to the cuboot wrapper. But to make a
> multi image, both the load and the entry addresses should be set to
> zero. And u-boot (1.1.2) bootm takes the entry address of the multi
> image (i.e. 0x0) as the kernel entry address. 0x0 is certainly not the
> entry address for a cuImage kernel.
>
> Is there a possible workaround other than using two separate images?
>
> Thanks,
> -Shawn.
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH 1/3 v3] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
From: Anton Vorontsov @ 2010-09-16 7:27 UTC (permalink / raw)
To: Roy Zang
Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2,
B11780
In-Reply-To: <1284619284-23614-1-git-send-email-tie-fei.zang@freescale.com>
On Thu, Sep 16, 2010 at 02:41:22PM +0800, Roy Zang wrote:
[...]
> +static const struct platform_device_id fsl_lbc_match[] = {
> + { "fsl,elbc", },
> + { "fsl,pq3-localbus", },
> + { "fsl,pq2-localbus", },
> + { "fsl,pq2pro-localbus", },
> + {},
> +};
> +
> +static struct platform_driver fsl_lbc_ctrl_driver = {
> + .driver = {
> + .name = "fsl-lbc",
> + },
> + .probe = fsl_lbc_ctrl_probe,
> + .id_table = fsl_lbc_match,
> +};
No, it won't work that way (at least not w/o a device constructor
somewhere in fsl_soc.c). Instead, you should write something like
static const struct of_device_id fsl_lbc_match[] = {
...
};
static struct platform_driver fsl_lbc_ctrl_driver = {
.driver = {
.name = "fsl-lbc",
.of_match_table = fsl_lbc_match;
}
...
};
(Note that platform_driver.driver has of_match_table nowadays --
that's what makes it possible to seamlessly transit from
of_platform_driver to platform_driver.)
The same applies for the second patch as well.
Thanks,
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: Generating elf kernel ?
From: Guillaume Dargaud @ 2010-09-16 7:25 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <4C9188DC.2040300@windriver.com>
> >> Please use simpleImage.<your target dts name>.elf.
> >
> > Great, that seems to be it...
> > Except that nothing happens when I jump to 0x40000, no message from the
>
> 0x40000? I recalled the entry point should be 0x400000 for
> simepleImage.*.elf. So you have to change this on the file,
> arch/powerpc/boot/wrapper.
Correct, I skipped a zero, the address is indeed 0x400000
> And also you should confirm if the upstream kernel support your board.
Our board is a custom derivative from a ML405.
My previous project uses ARCH=PPC and has been working fine for 2 years.
I'm currently trying to go to ARCH=PowerPC and understand dts files in order to
boot my first kernel.
I assume I shouldn't have to change anything in my bootloader.
After I jump to the kernel address, I don't even get the usual:
loaded at: 00400000 004F559C
board data at: 004F3520 004F359C
relocated to: 0040505C 004050D8
zimage at: 00405E48 004F211C
avail ram: 004F6000 08000000
Linux/PPC load: console=ttyUL0,115200 rw root=/dev/nfs ip=bootp
Uncompressing Linux...done.
Now booting the kernel
Something wrong with my serial console ?
> Additionally let's assume your bootloader create the map between the
> virtual address and the physical address as 1:1. If so you want to execute
> from 0x40000. But the actual PC address should be the loader address +
> offset. You can get this by readelf. Here if your loader address is zero,
> the offset will be pc address, not 0x40000. You can dump your memory to
> check this.
The bootloader has no concept of virtual address, right ?
--
Guillaume Dargaud
http://www.gdargaud.net/
^ permalink raw reply
* [PATCH] spi_mpc8xxx: fix buffer overrun when sending only/receiving only more than PAGE_SIZE bytes
From: christophe leroy @ 2010-09-16 7:05 UTC (permalink / raw)
To: David Brownell, Grant Likely, spi-devel-general, linux-kernel,
linuxppc-dev
This patch applies to 2.6.34.7 and 2.6.35.4
It fixes an issue when sending only or receiving only more than PAGE_SIZE bytes
Signed-off-by: christophe leroy <christophe.leroy@c-s.fr>
diff -urN c/drivers/spi/spi_mpc8xxx.c d/drivers/spi/spi_mpc8xxx.c
--- c/drivers/spi/spi_mpc8xxx.c 2010-09-08 16:44:03.000000000 +0200
+++ d/drivers/spi/spi_mpc8xxx.c 2010-09-08 16:44:14.000000000 +0200
@@ -393,11 +393,17 @@
xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
- out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
+ if (mspi->rx_dma == mspi->dma_dummy_rx)
+ out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
+ else
+ out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
out_be16(&rx_bd->cbd_datlen, 0);
out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
- out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
+ if (mspi->tx_dma == mspi->dma_dummy_tx)
+ out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
+ else
+ out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
out_be16(&tx_bd->cbd_datlen, xfer_len);
out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
BD_SC_LAST);
^ permalink raw reply
* [PATCH] spi_mpc8xxx: issue with using definition of pram in Device Tree
From: christophe leroy @ 2010-09-16 7:05 UTC (permalink / raw)
To: David Brownell, Grant Likely, spi-devel-general, linux-kernel,
linuxppc-dev
This patch applies to 2.6.34.7 and 2.6.35.4
It fixes an issue during the probe for CPM1 with definition of parameter ram from DTS
Signed-off-by: christophe leroy <christophe.leroy@c-s.fr>
diff -urN b/drivers/spi/spi_mpc8xxx.c c/drivers/spi/spi_mpc8xxx.c
--- b/drivers/spi/spi_mpc8xxx.c 2010-09-08 16:43:50.000000000 +0200
+++ c/drivers/spi/spi_mpc8xxx.c 2010-09-08 16:44:03.000000000 +0200
@@ -822,7 +822,7 @@
if (!iprop || size != sizeof(*iprop) * 4)
return -ENOMEM;
- spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
+ spi_base_ofs = iprop[2];
if (IS_ERR_VALUE(spi_base_ofs))
return -ENOMEM;
@@ -844,7 +844,6 @@
return spi_base_ofs;
}
- cpm_muram_free(spi_base_ofs);
return pram_ofs;
}
^ permalink raw reply
* [PATCH] spi_mpc8xxx: fix writing to adress 0
From: christophe leroy @ 2010-09-16 7:04 UTC (permalink / raw)
To: David Brownell, Grant Likely, spi-devel-general, linux-kernel,
linuxppc-dev
This patch applies to 2.6.34.7 (already included in 2.6.35.4)
It fixes an issue when sending only or receiving only (mspi->tx-dma was reset as when no tx_buf is defined, tx_dma is 0)
Signed-off-by: christophe leroy <christophe.leroy@c-s.fr>
diff -urN a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
--- a/drivers/spi/spi_mpc8xxx.c 2010-09-08 16:42:30.000000000 +0200
+++ b/drivers/spi/spi_mpc8xxx.c 2010-09-08 16:43:50.000000000 +0200
@@ -438,7 +438,7 @@
dev_err(dev, "unable to map tx dma\n");
return -ENOMEM;
}
- } else {
+ } else if (t->tx_buf) {
mspi->tx_dma = t->tx_dma;
}
@@ -449,7 +449,7 @@
dev_err(dev, "unable to map rx dma\n");
goto err_rx_dma;
}
- } else {
+ } else if (t->rx_buf) {
mspi->rx_dma = t->rx_dma;
}
^ permalink raw reply
* [PATCH 3/3 v3] P4080/mtd: Fix the freescale lbc issue with 36bit mode
From: Roy Zang @ 2010-09-16 6:41 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
In-Reply-To: <1284619284-23614-2-git-send-email-tie-fei.zang@freescale.com>
From: Lan Chunhe-B25806 <b25806@freescale.com>
When system uses 36bit physical address, res.start is 36bit
physical address. But the function of in_be32 returns 32bit
physical address. Then both of them compared each other is
wrong. So by converting the address of res.start into
the right format fixes this issue.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
arch/powerpc/include/asm/fsl_lbc.h | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 23 ++++++++++++++++++++++-
drivers/mtd/nand/fsl_elbc_nand.c | 2 +-
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index db94698..5638b1e 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -246,6 +246,7 @@ struct fsl_upm {
int width;
};
+extern unsigned int fsl_lbc_addr(phys_addr_t addr_base);
extern int fsl_lbc_find(phys_addr_t addr_base);
extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index edd6d95..8a835ef 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -34,6 +34,27 @@ struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
/**
+ * fsl_lbc_addr - convert the base address
+ * @addr_base: base address of the memory bank
+ *
+ * This function converts a base address of lbc into the right format for the
+ * BR register. If the SOC has eLBC then it returns 32bit physical address
+ * else it convers a 34bit local bus physical address to correct format of
+ * 32bit address for BR register (Example: MPC8641).
+ */
+u32 fsl_lbc_addr(phys_addr_t addr_base)
+{
+ struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
+ u32 addr = addr_base & 0xffff8000;
+
+ if (of_device_is_compatible(np, "fsl,elbc"))
+ return addr;
+
+ return addr | ((addr_base & 0x300000000ull) >> 19);
+}
+EXPORT_SYMBOL(fsl_lbc_addr);
+
+/**
* fsl_lbc_find - find Localbus bank
* @addr_base: base address of the memory bank
*
@@ -55,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
__be32 br = in_be32(&lbc->bank[i].br);
__be32 or = in_be32(&lbc->bank[i].or);
- if (br & BR_V && (br & or & BR_BA) == addr_base)
+ if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
return i;
}
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 91c5c05..85858e3 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -865,7 +865,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
(in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
(in_be32(&lbc->bank[bank].br) &
in_be32(&lbc->bank[bank].or) & BR_BA)
- == res.start)
+ == fsl_lbc_addr(res.start))
break;
if (bank >= MAX_BANKS) {
--
1.5.6.5
^ permalink raw reply related
* [PATCH 1/3 v3] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
From: Roy Zang @ 2010-09-16 6:41 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
From: Lan Chunhe-B25806 <b25806@freescale.com>
Move Freescale elbc interrupt from nand dirver to elbc driver.
Then all elbc devices can use the interrupt instead of ONLY nand.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v2:
1. according to the feedback, add some decorations.
2. change of_platform_driver to platform_driver
3. rebase to 2.6.36-rc4
arch/powerpc/Kconfig | 7 +-
arch/powerpc/include/asm/fsl_lbc.h | 31 +++++-
arch/powerpc/sysdev/fsl_lbc.c | 246 ++++++++++++++++++++++++++++++------
3 files changed, 242 insertions(+), 42 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..44df1ba 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -687,9 +687,12 @@ config 4xx_SOC
bool
config FSL_LBC
- bool
+ bool "Freescale Local Bus support"
+ depends on FSL_SOC
help
- Freescale Localbus support
+ Enables reporting of errors from the Freescale local bus
+ controller. Also contains some common code used by
+ drivers for specific local bus peripherals.
config FSL_GTM
bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a210..db94698 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
/* Freescale Local Bus Controller
*
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
*
* Authors: Nick Spence <nick.spence@freescale.com>,
* Scott Wood <scottwood@freescale.com>
+ * Jack Lan <jack.lan@freescale.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
@@ -125,13 +126,23 @@ struct fsl_lbc_regs {
#define LTESR_ATMW 0x00800000
#define LTESR_ATMR 0x00400000
#define LTESR_CS 0x00080000
+#define LTESR_UPM 0x00000002
#define LTESR_CC 0x00000001
#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
+ | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
+ | LTESR_CC)
+#define LTESR_CLEAR 0xFFFFFFFF
+#define LTECCR_CLEAR 0xFFFFFFFF
+#define LTESR_STATUS LTESR_MASK
+#define LTEIR_ENABLE LTESR_MASK
+#define LTEDR_ENABLE 0x00000000
__be32 ltedr; /**< Transfer Error Disable Register */
__be32 lteir; /**< Transfer Error Interrupt Register */
__be32 lteatr; /**< Transfer Error Attributes Register */
__be32 ltear; /**< Transfer Error Address Register */
- u8 res6[0xC];
+ __be32 lteccr; /**< Transfer Error ECC Register */
+ u8 res6[0x8];
__be32 lbcr; /**< Configuration Register */
#define LBCR_LDIS 0x80000000
#define LBCR_LDIS_SHIFT 31
@@ -265,7 +276,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
cpu_relax();
}
+/* overview of the fsl lbc controller */
+
+struct fsl_lbc_ctrl {
+ /* device info */
+ struct device *dev;
+ struct fsl_lbc_regs __iomem *regs;
+ int irq;
+ wait_queue_head_t irq_wait;
+ spinlock_t lock;
+ void *nand;
+
+ /* status read from LTESR by irq handler */
+ unsigned int irq_status;
+};
+
extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
u32 mar);
+extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
#endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1..edd6d95 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -2,8 +2,11 @@
* Freescale LBC and UPM routines.
*
* Copyright (c) 2007-2008 MontaVista Software, Inc.
+ * Copyright (c) 2010 Freescale Semiconductor
*
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Author: Jack Lan <Jack.Lan@freescale.com>
+ * Author: Roy Zang <tie-fei.zang@freescale.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
@@ -21,37 +24,14 @@
#include <linux/of.h>
#include <asm/prom.h>
#include <asm/fsl_lbc.h>
+#include <linux/slab.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-
-static char __initdata *compat_lbc[] = {
- "fsl,pq2-localbus",
- "fsl,pq2pro-localbus",
- "fsl,pq3-localbus",
- "fsl,elbc",
-};
-
-static int __init fsl_lbc_init(void)
-{
- struct device_node *lbus;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
- lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
- if (lbus)
- goto found;
- }
- return -ENODEV;
-
-found:
- fsl_lbc_regs = of_iomap(lbus, 0);
- of_node_put(lbus);
- if (!fsl_lbc_regs)
- return -ENOMEM;
- return 0;
-}
-arch_initcall(fsl_lbc_init);
+struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
+EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
/**
* fsl_lbc_find - find Localbus bank
@@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
int fsl_lbc_find(phys_addr_t addr_base)
{
int i;
+ struct fsl_lbc_regs __iomem *lbc;
- if (!fsl_lbc_regs)
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
return -ENODEV;
- for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
- __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
- __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+ lbc = fsl_lbc_ctrl_dev->regs;
+ for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
+ __be32 br = in_be32(&lbc->bank[i].br);
+ __be32 or = in_be32(&lbc->bank[i].or);
if (br & BR_V && (br & or & BR_BA) == addr_base)
return i;
@@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
{
int bank;
__be32 br;
+ struct fsl_lbc_regs __iomem *lbc;
bank = fsl_lbc_find(addr_base);
if (bank < 0)
return bank;
- br = in_be32(&fsl_lbc_regs->bank[bank].br);
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+
+ lbc = fsl_lbc_ctrl_dev->regs;
+ br = in_be32(&lbc->bank[bank].br);
switch (br & BR_MSEL) {
case BR_MS_UPMA:
- upm->mxmr = &fsl_lbc_regs->mamr;
+ upm->mxmr = &lbc->mamr;
break;
case BR_MS_UPMB:
- upm->mxmr = &fsl_lbc_regs->mbmr;
+ upm->mxmr = &lbc->mbmr;
break;
case BR_MS_UPMC:
- upm->mxmr = &fsl_lbc_regs->mcmr;
+ upm->mxmr = &lbc->mcmr;
break;
default:
return -EINVAL;
@@ -143,14 +130,18 @@ EXPORT_SYMBOL(fsl_upm_find);
* thus UPM pattern actually executed. Note that mar usage depends on the
* pre-programmed AMX bits in the UPM RAM.
*/
+
int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
{
int ret = 0;
unsigned long flags;
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+
spin_lock_irqsave(&fsl_lbc_lock, flags);
- out_be32(&fsl_lbc_regs->mar, mar);
+ out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
switch (upm->width) {
case 8:
@@ -172,3 +163,182 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
return ret;
}
EXPORT_SYMBOL(fsl_upm_run_pattern);
+
+static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
+{
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ /* clear event registers */
+ setbits32(&lbc->ltesr, LTESR_CLEAR);
+ out_be32(&lbc->lteatr, 0);
+ out_be32(&lbc->ltear, 0);
+ out_be32(&lbc->lteccr, LTECCR_CLEAR);
+ out_be32(&lbc->ltedr, LTEDR_ENABLE);
+
+ /* Enable interrupts for any detected events */
+ out_be32(&lbc->lteir, LTEIR_ENABLE);
+
+ return 0;
+}
+
+static int __devexit fsl_lbc_ctrl_remove(struct platform_device *dev)
+{
+ struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
+
+ if (ctrl->irq)
+ free_irq(ctrl->irq, ctrl);
+
+ if (ctrl->regs)
+ iounmap(ctrl->regs);
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ kfree(ctrl);
+
+ return 0;
+}
+
+/*
+ * NOTE: This interrupt is used to report localbus events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+
+static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
+{
+ struct fsl_lbc_ctrl *ctrl = data;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ u32 status;
+
+ status = in_be32(&lbc->ltesr);
+ if (!status)
+ return IRQ_NONE;
+
+ out_be32(&lbc->ltesr, LTESR_CLEAR);
+ out_be32(&lbc->lteatr, 0);
+ out_be32(&lbc->ltear, 0);
+ ctrl->irq_status = status;
+
+ if (status & LTESR_BM)
+ dev_err(ctrl->dev, "Local bus monitor time-out: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_WP)
+ dev_err(ctrl->dev, "Write protect error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_ATMW)
+ dev_err(ctrl->dev, "Atomic write error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_ATMR)
+ dev_err(ctrl->dev, "Atomic read error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_CS)
+ dev_err(ctrl->dev, "Chip select error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_UPM)
+ ;
+ if (status & LTESR_FCT) {
+ dev_err(ctrl->dev, "FCM command time-out: "
+ "LTESR 0x%08X\n", status);
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & LTESR_PAR) {
+ dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
+ "LTESR 0x%08X\n", status);
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & LTESR_CC) {
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & ~LTESR_MASK)
+ dev_err(ctrl->dev, "Unknown error: "
+ "LTESR 0x%08X\n", status);
+ return IRQ_HANDLED;
+}
+
+/*
+ * fsl_lbc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only. The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+
+static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
+{
+ int ret;
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL");
+ return -EFAULT;
+ }
+ fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
+ if (!fsl_lbc_ctrl_dev)
+ return -ENOMEM;
+
+ dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
+
+ spin_lock_init(&fsl_lbc_ctrl_dev->lock);
+ init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
+
+ fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
+ if (!fsl_lbc_ctrl_dev->regs) {
+ dev_err(&dev->dev, "failed to get memory region\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
+ if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+ dev_err(&dev->dev, "failed to get irq resource\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ fsl_lbc_ctrl_dev->dev = &dev->dev;
+
+ ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
+ if (ret < 0)
+ goto err;
+
+ ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+ "fsl-lbc", fsl_lbc_ctrl_dev);
+ if (ret != 0) {
+ dev_err(&dev->dev, "failed to install irq (%d)\n",
+ fsl_lbc_ctrl_dev->irq);
+ ret = fsl_lbc_ctrl_dev->irq;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ iounmap(fsl_lbc_ctrl_dev->regs);
+ kfree(fsl_lbc_ctrl_dev);
+ return ret;
+}
+
+static const struct platform_device_id fsl_lbc_match[] = {
+ { "fsl,elbc", },
+ { "fsl,pq3-localbus", },
+ { "fsl,pq2-localbus", },
+ { "fsl,pq2pro-localbus", },
+ {},
+};
+
+static struct platform_driver fsl_lbc_ctrl_driver = {
+ .driver = {
+ .name = "fsl-lbc",
+ },
+ .probe = fsl_lbc_ctrl_probe,
+ .id_table = fsl_lbc_match,
+};
+
+static int __init fsl_lbc_init(void)
+{
+ return platform_driver_register(&fsl_lbc_ctrl_driver);
+}
+module_init(fsl_lbc_init);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 2/3 v3] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Roy Zang @ 2010-09-16 6:41 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
In-Reply-To: <1284619284-23614-1-git-send-email-tie-fei.zang@freescale.com>
From: Jack Lan <jack.lan@freescale.com>
The former driver had the two functions:
1. detecting nand flash partitions;
2. registering elbc interrupt.
Now, second function is removed to fsl_lbc.c.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
drivers/mtd/nand/Kconfig | 1 +
drivers/mtd/nand/fsl_elbc_nand.c | 474 +++++++++++++++-----------------------
2 files changed, 190 insertions(+), 285 deletions(-)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c..4132c46 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -458,6 +458,7 @@ config MTD_NAND_ORION
config MTD_NAND_FSL_ELBC
tristate "NAND support for Freescale eLBC controllers"
depends on PPC_OF
+ select FSL_LBC
help
Various Freescale chips, including the 8313, include a NAND Flash
Controller Module with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bf..91c5c05 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,10 @@
/* Freescale Enhanced Local Bus Controller NAND driver
*
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
*
* Authors: Nick Spence <nick.spence@freescale.com>,
* Scott Wood <scottwood@freescale.com>
+ * Jack Lan <jack.lan@freescale.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
@@ -27,6 +28,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -42,14 +44,12 @@
#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
-struct fsl_elbc_ctrl;
-
/* mtd information per set */
struct fsl_elbc_mtd {
struct mtd_info mtd;
struct nand_chip chip;
- struct fsl_elbc_ctrl *ctrl;
+ struct fsl_lbc_ctrl *ctrl;
struct device *dev;
int bank; /* Chip select bank number */
@@ -58,18 +58,12 @@ struct fsl_elbc_mtd {
unsigned int fmr; /* FCM Flash Mode Register value */
};
-/* overview of the fsl elbc controller */
+/* Freescale eLBC FCM controller infomation */
-struct fsl_elbc_ctrl {
+struct fsl_elbc_fcm_ctrl {
struct nand_hw_control controller;
struct fsl_elbc_mtd *chips[MAX_BANKS];
- /* device info */
- struct device *dev;
- struct fsl_lbc_regs __iomem *regs;
- int irq;
- wait_queue_head_t irq_wait;
- unsigned int irq_status; /* status read from LTESR by irq handler */
u8 __iomem *addr; /* Address of assigned FCM buffer */
unsigned int page; /* Last page written to / read from */
unsigned int read_bytes; /* Number of bytes read during command */
@@ -164,11 +158,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
int buf_num;
- ctrl->page = page_addr;
+ elbc_fcm_ctrl->page = page_addr;
out_be32(&lbc->fbar,
page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +180,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
buf_num = page_addr & 7;
}
- ctrl->addr = priv->vbase + buf_num * 1024;
- ctrl->index = column;
+ elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
+ elbc_fcm_ctrl->index = column;
/* for OOB data point to the second half of the buffer */
if (oob)
- ctrl->index += priv->page_size ? 2048 : 512;
+ elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
- dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+ dev_vdbg(priv->dev, "set_addr: bank=%d, "
+ "elbc_fcm_ctrl->addr=0x%p (0x%p), "
"index %x, pes %d ps %d\n",
- buf_num, ctrl->addr, priv->vbase, ctrl->index,
+ buf_num, elbc_fcm_ctrl->addr, priv->vbase,
+ elbc_fcm_ctrl->index,
chip->phys_erase_shift, chip->page_shift);
}
@@ -205,18 +202,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* Setup the FMR[OP] to execute without write protection */
out_be32(&lbc->fmr, priv->fmr | 3);
- if (ctrl->use_mdr)
- out_be32(&lbc->mdr, ctrl->mdr);
+ if (elbc_fcm_ctrl->use_mdr)
+ out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_run_command: fbar=%08x fpar=%08x "
"fbcr=%08x bank=%d\n",
in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +227,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
/* wait for FCM complete flag or timeout */
wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
FCM_TIMEOUT_MSECS * HZ/1000);
- ctrl->status = ctrl->irq_status;
-
+ elbc_fcm_ctrl->status = ctrl->irq_status;
/* store mdr value in case it was needed */
- if (ctrl->use_mdr)
- ctrl->mdr = in_be32(&lbc->mdr);
+ if (elbc_fcm_ctrl->use_mdr)
+ elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
- ctrl->use_mdr = 0;
+ elbc_fcm_ctrl->use_mdr = 0;
- if (ctrl->status != LTESR_CC) {
- dev_info(ctrl->dev,
+ if (elbc_fcm_ctrl->status != LTESR_CC) {
+ dev_info(priv->dev,
"command failed: fir %x fcr %x status %x mdr %x\n",
in_be32(&lbc->fir), in_be32(&lbc->fcr),
- ctrl->status, ctrl->mdr);
+ elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
return -EIO;
}
@@ -251,7 +248,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (priv->page_size) {
@@ -284,15 +281,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
- ctrl->use_mdr = 0;
+ elbc_fcm_ctrl->use_mdr = 0;
/* clear the read buffer */
- ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->read_bytes = 0;
if (command != NAND_CMD_PAGEPROG)
- ctrl->index = 0;
+ elbc_fcm_ctrl->index = 0;
switch (command) {
/* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +299,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* fall-through */
case NAND_CMD_READ0:
- dev_dbg(ctrl->dev,
+ dev_dbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
" 0x%x, column: 0x%x.\n", page_addr, column);
@@ -309,8 +307,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
set_addr(mtd, 0, page_addr, 0);
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
- ctrl->index += column;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ elbc_fcm_ctrl->index += column;
fsl_elbc_do_read(chip, 0);
fsl_elbc_run_command(mtd);
@@ -318,14 +316,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
" 0x%x, column: 0x%x.\n", page_addr, column);
out_be32(&lbc->fbcr, mtd->oobsize - column);
set_addr(mtd, column, page_addr, 1);
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
fsl_elbc_do_read(chip, 1);
fsl_elbc_run_command(mtd);
@@ -333,7 +331,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* READID must read all 5 possible bytes while CEB is active */
case NAND_CMD_READID:
- dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+ dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_UA << FIR_OP1_SHIFT) |
@@ -341,9 +339,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
/* 5 bytes for manuf, device and exts */
out_be32(&lbc->fbcr, 5);
- ctrl->read_bytes = 5;
- ctrl->use_mdr = 1;
- ctrl->mdr = 0;
+ elbc_fcm_ctrl->read_bytes = 5;
+ elbc_fcm_ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->mdr = 0;
set_addr(mtd, 0, 0, 0);
fsl_elbc_run_command(mtd);
@@ -351,7 +349,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* ERASE1 stores the block and page address */
case NAND_CMD_ERASE1:
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
"page_addr: 0x%x.\n", page_addr);
set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +357,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* ERASE2 uses the block and page address from ERASE1 */
case NAND_CMD_ERASE2:
- dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+ dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
out_be32(&lbc->fir,
(FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +372,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
out_be32(&lbc->fbcr, 0);
- ctrl->read_bytes = 0;
- ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->use_mdr = 1;
fsl_elbc_run_command(mtd);
return;
@@ -383,14 +381,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* SEQIN sets up the addr buffer and all registers except the length */
case NAND_CMD_SEQIN: {
__be32 fcr;
- dev_vdbg(ctrl->dev,
- "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+ dev_vdbg(priv->dev,
+ "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
"page_addr: 0x%x, column: 0x%x.\n",
page_addr, column);
- ctrl->column = column;
- ctrl->oob = 0;
- ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->use_mdr = 1;
fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
(NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
@@ -420,7 +416,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* OOB area --> READOOB */
column -= mtd->writesize;
fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
- ctrl->oob = 1;
+ elbc_fcm_ctrl->oob = 1;
} else {
WARN_ON(column != 0);
/* First 256 bytes --> READ0 */
@@ -429,24 +425,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
}
out_be32(&lbc->fcr, fcr);
- set_addr(mtd, column, page_addr, ctrl->oob);
+ set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
return;
}
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
case NAND_CMD_PAGEPROG: {
int full_page;
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
- "writing %d bytes.\n", ctrl->index);
+ "writing %d bytes.\n", elbc_fcm_ctrl->index);
/* if the write did not start at 0 or is not a full page
* then set the exact length, otherwise use a full page
* write so the HW generates the ECC.
*/
- if (ctrl->oob || ctrl->column != 0 ||
- ctrl->index != mtd->writesize + mtd->oobsize) {
- out_be32(&lbc->fbcr, ctrl->index);
+ if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
+ elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+ out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
full_page = 0;
} else {
out_be32(&lbc->fbcr, 0);
@@ -458,21 +454,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* Read back the page in order to fill in the ECC for the
* caller. Is this really needed?
*/
- if (full_page && ctrl->oob_poi) {
+ if (full_page && elbc_fcm_ctrl->oob_poi) {
out_be32(&lbc->fbcr, 3);
set_addr(mtd, 6, page_addr, 1);
- ctrl->read_bytes = mtd->writesize + 9;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
fsl_elbc_do_read(chip, 1);
fsl_elbc_run_command(mtd);
- memcpy_fromio(ctrl->oob_poi + 6,
- &ctrl->addr[ctrl->index], 3);
- ctrl->index += 3;
+ memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
+ &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
+ elbc_fcm_ctrl->index += 3;
}
- ctrl->oob_poi = NULL;
+ elbc_fcm_ctrl->oob_poi = NULL;
return;
}
@@ -485,26 +481,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
out_be32(&lbc->fbcr, 1);
set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
+ elbc_fcm_ctrl->read_bytes = 1;
fsl_elbc_run_command(mtd);
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- setbits8(ctrl->addr, NAND_STATUS_WP);
+ setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
return;
/* RESET without waiting for the ready line */
case NAND_CMD_RESET:
- dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+ dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
fsl_elbc_run_command(mtd);
return;
default:
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
command);
}
@@ -524,24 +520,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
unsigned int bufsize = mtd->writesize + mtd->oobsize;
if (len <= 0) {
- dev_err(ctrl->dev, "write_buf of %d bytes", len);
- ctrl->status = 0;
+ dev_err(priv->dev, "write_buf of %d bytes", len);
+ elbc_fcm_ctrl->status = 0;
return;
}
- if ((unsigned int)len > bufsize - ctrl->index) {
- dev_err(ctrl->dev,
+ if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
+ dev_err(priv->dev,
"write_buf beyond end of buffer "
"(%d requested, %u available)\n",
- len, bufsize - ctrl->index);
- len = bufsize - ctrl->index;
+ len, bufsize - elbc_fcm_ctrl->index);
+ len = bufsize - elbc_fcm_ctrl->index;
}
- memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+ memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
/*
* This is workaround for the weird elbc hangs during nand write,
* Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +545,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
* is causing problems, and sync isn't helping for some reason."
* Reading back the last byte helps though.
*/
- in_8(&ctrl->addr[ctrl->index] + len - 1);
+ in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
- ctrl->index += len;
+ elbc_fcm_ctrl->index += len;
}
/*
@@ -562,13 +558,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
/* If there are still bytes in the FCM, then use the next byte. */
- if (ctrl->index < ctrl->read_bytes)
- return in_8(&ctrl->addr[ctrl->index++]);
+ if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
+ return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
- dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+ dev_err(priv->dev, "read_byte beyond end of buffer\n");
return ERR_BYTE;
}
@@ -579,18 +575,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int avail;
if (len < 0)
return;
- avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
- memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
- ctrl->index += avail;
+ avail = min((unsigned int)len,
+ elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
+ memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
+ elbc_fcm_ctrl->index += avail;
if (len > avail)
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"read_buf beyond end of buffer "
"(%d requested, %d available)\n",
len, avail);
@@ -603,30 +600,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int i;
if (len < 0) {
- dev_err(ctrl->dev, "write_buf of %d bytes", len);
+ dev_err(priv->dev, "write_buf of %d bytes", len);
return -EINVAL;
}
- if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
- dev_err(ctrl->dev,
- "verify_buf beyond end of buffer "
- "(%d requested, %u available)\n",
- len, ctrl->read_bytes - ctrl->index);
+ if ((unsigned int)len >
+ elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
+ dev_err(priv->dev,
+ "verify_buf beyond end of buffer "
+ "(%d requested, %u available)\n",
+ len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
- ctrl->index = ctrl->read_bytes;
+ elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
return -EINVAL;
}
for (i = 0; i < len; i++)
- if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+ if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
+ != buf[i])
break;
- ctrl->index += len;
- return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+ elbc_fcm_ctrl->index += len;
+ return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
}
/* This function is called after Program and Erase Operations to
@@ -635,22 +634,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
- if (ctrl->status != LTESR_CC)
+ if (elbc_fcm_ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
+ return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
}
static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al;
@@ -665,41 +664,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */
(al << FMR_AL_SHIFT);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
chip->numchips);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
chip->chipsize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
chip->pagemask);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
chip->chip_delay);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
chip->badblockpos);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
chip->chip_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
chip->page_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
chip->phys_erase_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
chip->ecclayout);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
chip->ecc.mode);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
chip->ecc.steps);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
chip->ecc.bytes);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
chip->ecc.total);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
chip->ecc.layout);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
mtd->erasesize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
mtd->writesize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
mtd->oobsize);
/* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +718,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->badblock_pattern = &largepage_memorybased;
}
} else {
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"fsl_elbc_init: page size %d is not supported\n",
mtd->writesize);
return -1;
@@ -750,18 +749,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
const uint8_t *buf)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
- ctrl->oob_poi = chip->oob_poi;
+ elbc_fcm_ctrl->oob_poi = chip->oob_poi;
}
static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
{
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct nand_chip *chip = &priv->chip;
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +790,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
NAND_USE_FLASH_BBT;
- chip->controller = &ctrl->controller;
+ chip->controller = &elbc_fcm_ctrl->controller;
chip->priv = priv;
chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +815,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
{
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
nand_release(&priv->mtd);
kfree(priv->mtd.name);
@@ -824,18 +823,22 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
if (priv->vbase)
iounmap(priv->vbase);
- ctrl->chips[priv->bank] = NULL;
+ elbc_fcm_ctrl->chips[priv->bank] = NULL;
kfree(priv);
-
+ kfree(elbc_fcm_ctrl);
return 0;
}
-static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
- struct device_node *node)
+/*
+ * Currently only one elbc probe is supported.
+ */
+static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
{
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc;
struct fsl_elbc_mtd *priv;
struct resource res;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
+
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[]
= { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +846,16 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
#endif
int ret;
int bank;
+ struct device_node *node = dev->dev.of_node;
+
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+ lbc = fsl_lbc_ctrl_dev->regs;
/* get, allocate and map the memory resource */
ret = of_address_to_resource(node, 0, &res);
if (ret) {
- dev_err(ctrl->dev, "failed to get resource\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to get resource\n");
return ret;
}
@@ -861,7 +869,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
break;
if (bank >= MAX_BANKS) {
- dev_err(ctrl->dev, "address did not match any chip selects\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "address did not match any "
+ "chip selects\n");
return -ENODEV;
}
@@ -869,14 +878,32 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
if (!priv)
return -ENOMEM;
- ctrl->chips[bank] = priv;
+ if (fsl_lbc_ctrl_dev->nand == NULL) {
+ elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
+ if (!elbc_fcm_ctrl) {
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to allocate "
+ "memory\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ elbc_fcm_ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->index = 0;
+ elbc_fcm_ctrl->addr = NULL;
+
+ spin_lock_init(&elbc_fcm_ctrl->controller.lock);
+ init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
+ fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
+ }
+
+ elbc_fcm_ctrl->chips[bank] = priv;
priv->bank = bank;
- priv->ctrl = ctrl;
- priv->dev = ctrl->dev;
+ priv->ctrl = fsl_lbc_ctrl_dev;
+ priv->dev = fsl_lbc_ctrl_dev->dev;
priv->vbase = ioremap(res.start, resource_size(&res));
if (!priv->vbase) {
- dev_err(ctrl->dev, "failed to map chip region\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to map chip region\n");
ret = -ENOMEM;
goto err;
}
@@ -933,171 +960,48 @@ err:
return ret;
}
-static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+static int fsl_elbc_nand_remove(struct platform_device *dev)
{
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
- /*
- * NAND transactions can tie up the bus for a long time, so set the
- * bus timeout to max by clearing LBCR[BMT] (highest base counter
- * value) and setting LBCR[BMTPS] to the highest prescaler value.
- */
- clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
-
- /* clear event registers */
- setbits32(&lbc->ltesr, LTESR_NAND_MASK);
- out_be32(&lbc->lteatr, 0);
-
- /* Enable interrupts for any detected events */
- out_be32(&lbc->lteir, LTESR_NAND_MASK);
-
- ctrl->read_bytes = 0;
- ctrl->index = 0;
- ctrl->addr = NULL;
-
- return 0;
-}
-
-static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
-{
- struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
int i;
-
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
for (i = 0; i < MAX_BANKS; i++)
- if (ctrl->chips[i])
- fsl_elbc_chip_remove(ctrl->chips[i]);
-
- if (ctrl->irq)
- free_irq(ctrl->irq, ctrl);
+ if (elbc_fcm_ctrl->chips[i])
+ fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
- if (ctrl->regs)
- iounmap(ctrl->regs);
+ fsl_lbc_ctrl_dev->nand = NULL;
+ kfree(elbc_fcm_ctrl);
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(ctrl);
return 0;
-}
-
-/* NOTE: This interrupt is also used to report other localbus events,
- * such as transaction errors on other chipselects. If we want to
- * capture those, we'll need to move the IRQ code into a shared
- * LBC driver.
- */
-static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
-{
- struct fsl_elbc_ctrl *ctrl = data;
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
- __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
-
- if (status) {
- out_be32(&lbc->ltesr, status);
- out_be32(&lbc->lteatr, 0);
-
- ctrl->irq_status = status;
- smp_wmb();
- wake_up(&ctrl->irq_wait);
-
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
}
-/* fsl_elbc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only. The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-
-static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *child;
- struct fsl_elbc_ctrl *ctrl;
- int ret;
-
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl)
- return -ENOMEM;
-
- dev_set_drvdata(&ofdev->dev, ctrl);
-
- spin_lock_init(&ctrl->controller.lock);
- init_waitqueue_head(&ctrl->controller.wq);
- init_waitqueue_head(&ctrl->irq_wait);
-
- ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
- if (!ctrl->regs) {
- dev_err(&ofdev->dev, "failed to get memory region\n");
- ret = -ENODEV;
- goto err;
- }
-
- ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
- if (ctrl->irq == NO_IRQ) {
- dev_err(&ofdev->dev, "failed to get irq resource\n");
- ret = -ENODEV;
- goto err;
- }
-
- ctrl->dev = &ofdev->dev;
-
- ret = fsl_elbc_ctrl_init(ctrl);
- if (ret < 0)
- goto err;
-
- ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
- if (ret != 0) {
- dev_err(&ofdev->dev, "failed to install irq (%d)\n",
- ctrl->irq);
- ret = ctrl->irq;
- goto err;
- }
-
- for_each_child_of_node(ofdev->dev.of_node, child)
- if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
- fsl_elbc_chip_probe(ctrl, child);
-
- return 0;
-
-err:
- fsl_elbc_ctrl_remove(ofdev);
- return ret;
-}
-
-static const struct of_device_id fsl_elbc_match[] = {
- {
- .compatible = "fsl,elbc",
- },
+static const struct platform_device_id fsl_elbc_nand_match[] = {
+ { "fsl,elbc-fcm-nand", },
{}
};
-static struct of_platform_driver fsl_elbc_ctrl_driver = {
+static struct platform_driver fsl_elbc_nand_driver = {
.driver = {
- .name = "fsl-elbc",
+ .name = "fsl,elbc-fcm-nand",
.owner = THIS_MODULE,
- .of_match_table = fsl_elbc_match,
},
- .probe = fsl_elbc_ctrl_probe,
- .remove = fsl_elbc_ctrl_remove,
+ .id_table = fsl_elbc_nand_match,
+ .probe = fsl_elbc_nand_probe,
+ .remove = fsl_elbc_nand_remove,
};
-static int __init fsl_elbc_init(void)
+static int __init fsl_elbc_nand_init(void)
{
- return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+ return platform_driver_register(&fsl_elbc_nand_driver);
}
-static void __exit fsl_elbc_exit(void)
+static void __exit fsl_elbc_nand_exit(void)
{
- of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+ platform_driver_unregister(&fsl_elbc_nand_driver);
}
-module_init(fsl_elbc_init);
-module_exit(fsl_elbc_exit);
+module_init(fsl_elbc_nand_init);
+module_exit(fsl_elbc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale");
--
1.5.6.5
^ permalink raw reply related
* cuImage and multi image?
From: Shawn Jin @ 2010-09-16 6:21 UTC (permalink / raw)
To: ppcdev, uboot
Hi,
I have a cuImage kernel in order to support legacy u-boot and a
ramdisk image. Kernel boots fine if these two images are separate and
"bootm $kernel $ramdisk" is used. But I can not make it to work using
a single multi image that contains the kernel and ramdisk images. Is
it even technically possible to boot a multi-image with cuboot
wrapper?
On the cuImage kernel I have load address set to 0x400000 and the
entry address set to 0x400554 due to the cuboot wrapper. But to make a
multi image, both the load and the entry addresses should be set to
zero. And u-boot (1.1.2) bootm takes the entry address of the multi
image (i.e. 0x0) as the kernel entry address. 0x0 is certainly not the
entry address for a cuImage kernel.
Is there a possible workaround other than using two separate images?
Thanks,
-Shawn.
^ permalink raw reply
* Reserved pages in PowerPC
From: Ankita Garg @ 2010-09-16 5:23 UTC (permalink / raw)
To: linuxppc-dev, linux-mm
Hi,
I am trying to hotplug/offline sections of memory on a Power machine.
I boot the kernel with kernelcore=1G commandline parameter. I see that except
for 512MB, the rest of the memory is movable. When trying to do hot-remove, I
notice that I am unable to remove the very last section of memory, one with
the highest physical address. It is always marked as non-movable.
With some debugging I found that that section has reserved pages. On
instrumenting the memblock_reserve() and reserve_bootmem() routines, I can see
that many of the memory areas are reserved for kernel and initrd by the
memblock reserve() itself. reserve_bootmem then looks at the pages already
reserved and marks them reserved. However, for the very last section, I see
that bootmem reserves it but I am unable to find a corresponding reservation
by the memblock code.
memblock_reserve: start 0 size 3519
reserve_bootmem 0 dbf000 nid=0
memblock_reserve: start 12096 size 15372
reserve_bootmem 2f40000 ccc000 nid=0
memblock_reserve: start 15628 size 15650
reserve_bootmem 3d0c000 16000 nid=0
...
...
memblock_reserve: start 1982455 size 1982464
reserve_bootmem 1e3ff7c00 8400 nid=0
reserve_bootmem 3d7f64000 3f000 nid=1
reserve_bootmem 3d7fa3c00 48400 nid=1
reserve_bootmem 3d7feeda8 11258 nid=1
..
Is it a known behavior on Power ? If yes, for what purpose is the memory
in the higher address reserved for ? I have seen that even if the system
has multiple nodes, only the very last section of the last node is not
removable.
--
Regards,
Ankita Garg (ankita@in.ibm.com)
Linux Technology Center
IBM India Systems & Technology Labs,
Bangalore, India
^ permalink raw reply
* Re: Generating elf kernel ?
From: tiejun.chen @ 2010-09-16 3:02 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
In-Reply-To: <201009151651.06816.dargaud@lpsc.in2p3.fr>
Guillaume Dargaud wrote:
>> Please use simpleImage.<your target dts name>.elf.
>
> Great, that seems to be it...
> Except that nothing happens when I jump to 0x40000, no message from the
0x40000? I recalled the entry point should be 0x400000 for simepleImage.*.elf.
So you have to change this on the file, arch/powerpc/boot/wrapper.
And also you should confirm if the upstream kernel support your board.
Additionally let's assume your bootloader create the map between the virtual
address and the physical address as 1:1. If so you want to execute from 0x40000.
But the actual PC address should be the loader address + offset. You can get
this by readelf. Here if your loader address is zero, the offset will be pc
address, not 0x40000. You can dump your memory to check this.
Cheers
Tiejun
> kernel, nothing.
> I'm a bit stumped here as my old kernel worked fine.
^ permalink raw reply
* Re: [PATCH] powerpc/5121: pdm360ng: fix touch irq if 8xxx gpio driver is enabled
From: Grant Likely @ 2010-09-16 2:38 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: linuxppc-dev
In-Reply-To: <1284581577-2217-1-git-send-email-agust@denx.de>
On Wed, Sep 15, 2010 at 10:12:57PM +0200, Anatolij Gustschin wrote:
> Enabling the MPC8xxx GPIO driver with MPC512x GPIO extension
> breaks touch screen support on this board since the GPIO
> interrupt will be mapped to 8xxx GPIO irq host resulting in
> a not requestable interrupt in the touch screen driver. Fix
> it by mapping the touch interrupt on 8xxx GPIO irq host.
This looks wrong to me. The touchscreen code should not go mucking
about in the GPIO controller registers; that is the job of the gpio
driver. What is the reason that the touch interrupt isn't
requestable? It looks like the 8xxx gpio driver is designed to hand
out a separate virq number for each gpio pin (I've not had time to dig
into details, so you'll need to educate me on the problem details)
g.
>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> ---
> arch/powerpc/platforms/512x/pdm360ng.c | 26 ++++++++++++++++++++++----
> 1 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
> index 0575e85..558eb9e 100644
> --- a/arch/powerpc/platforms/512x/pdm360ng.c
> +++ b/arch/powerpc/platforms/512x/pdm360ng.c
> @@ -27,6 +27,7 @@
> #include <linux/spi/ads7846.h>
> #include <linux/spi/spi.h>
> #include <linux/notifier.h>
> +#include <asm/gpio.h>
>
> static void *pdm360ng_gpio_base;
>
> @@ -50,7 +51,7 @@ static struct ads7846_platform_data pdm360ng_ads7846_pdata = {
> .irq_flags = IRQF_TRIGGER_LOW,
> };
>
> -static int __init pdm360ng_penirq_init(void)
> +static int pdm360ng_penirq_init(void)
> {
> struct device_node *np;
>
> @@ -73,6 +74,9 @@ static int __init pdm360ng_penirq_init(void)
> return 0;
> }
>
> +#define GPIO_NR(x) (ARCH_NR_GPIOS - 32 + (x))
> +#define PENDOWN_GPIO GPIO_NR(25)
> +
> static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
> unsigned long event, void *__dev)
> {
> @@ -80,7 +84,24 @@ static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
>
> if ((event == BUS_NOTIFY_ADD_DEVICE) &&
> of_device_is_compatible(dev->of_node, "ti,ads7846")) {
> + struct spi_device *spi = to_spi_device(dev);
> + int gpio = PENDOWN_GPIO;
> +
> dev->platform_data = &pdm360ng_ads7846_pdata;
> + if (pdm360ng_penirq_init())
> + return NOTIFY_DONE;
> +
> + if (gpio_request_one(gpio, GPIOF_IN, "ads7845_pen_down") < 0) {
> + pr_err("Failed to request GPIO %d for "
> + "ads7845 pen down IRQ\n", gpio);
> + return NOTIFY_DONE;
> + }
> + spi->irq = gpio_to_irq(gpio);
> + if (spi->irq < 0) {
> + pr_err("Can't map GPIO IRQ\n");
> + gpio_free(gpio);
> + return NOTIFY_DONE;
> + }
> return NOTIFY_OK;
> }
> return NOTIFY_DONE;
> @@ -92,9 +113,6 @@ static struct notifier_block pdm360ng_touchscreen_nb = {
>
> static void __init pdm360ng_touchscreen_init(void)
> {
> - if (pdm360ng_penirq_init())
> - return;
> -
> bus_register_notifier(&spi_bus_type, &pdm360ng_touchscreen_nb);
> }
> #else
> --
> 1.7.0.4
>
^ permalink raw reply
* Re: Generating elf kernel ?
From: tiejun.chen @ 2010-09-16 2:37 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Guillaume Dargaud
In-Reply-To: <20100915114912.06bc7ed1@schlenkerla.am.freescale.net>
Scott Wood wrote:
> On Wed, 15 Sep 2010 16:27:10 +0800
> "tiejun.chen" <tiejun.chen@windriver.com> wrote:
>
>> It's impossible to boot PPC vmlinux format directly if you only change the
>> original entry point address, 0xc0000000.
>
> Why? That's pretty much what the bootwrapper does. Our hypervisor has
> directly booted vmlinux this way.
Maybe you misunderstand what I mean.
Although you can change entry point of vmlinux
1> can you load the Linux vmlinux directly to the physical address '0' on
current bootloader?
2> additionally you have to find a way to pass dtb to the native vmlinux.
I believe the hypervisor can boot vmlinux directly. But your so-called vmlinux
should be guest OS. And the hypervisor will handle/assit TLB exception for the
guest OS on MMU. Right? So you can use the hypervisor to load vmlinux to any
physical address as you expect. But the guest OS should not be same as the
native Linux.
>
> Note that in recent kernels physaddr is even set to zero, allowing the
> ELF loader to just use that instead of magically knowing the kernel
> wants to go at address zero.
Sure.
>
>> For kernel the following is as default:
>> v:0xc0000000 --> p:0x0
>
> That mapping is set up by code at the entry point of vmlinux, not by
> the bootwrapper.
Absolutely.
Tiejun
>
> -Scott
>
>
^ 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