linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Porting a driver to powerpc using FDT
@ 2010-06-15 22:18 Chris Alfred (Internode)
  0 siblings, 0 replies; 13+ messages in thread
From: Chris Alfred (Internode) @ 2010-06-15 22:18 UTC (permalink / raw)
  To: linuxppc-dev

I am trying to port a DSA (Distributed Switch Architecture) driver for 
the Micrel KS8995M managed switch connected to a MPC5200. There is an 
SPI interface and MII interface managed by the DSA driver.

I can't understand how probe gets called when the flatted device tree 
(FDT) system is used, and how to bind such a driver using the FDT (if 
you have to at all).

The DSA driver is initialised via:

    // net/dsa/dsa.c

    static struct platform_driver dsa_driver = {
     .probe  = dsa_probe,
     .remove  = dsa_remove,
     .shutdown = dsa_shutdown,
     .driver = {
      .name = "dsa",
      .owner = THIS_MODULE,
     },
    };

    static int __init dsa_init_module(void)
    {
     return platform_driver_register(&dsa_driver);
    }

dsa_init_module is being called; but how do I get the system to call 
.probe?

Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Porting a driver to powerpc using FDT
@ 2010-06-15 22:19 Chris Alfred
  2010-06-16 18:22 ` Grant Likely
  0 siblings, 1 reply; 13+ messages in thread
From: Chris Alfred @ 2010-06-15 22:19 UTC (permalink / raw)
  To: linuxppc-dev

I am trying to port a DSA (Distributed Switch Architecture) driver for
the Micrel KS8995M managed switch connected to a MPC5200. There is an
SPI interface and MII interface managed by the DSA driver.

I can't understand how probe gets called when the flatted device tree
(FDT) system is used, and how to bind such a driver using the FDT (if
you have to at all).

The DSA driver is initialised via:

    // net/dsa/dsa.c

    static struct platform_driver dsa_driver = {
     .probe  = dsa_probe,
     .remove  = dsa_remove,
     .shutdown = dsa_shutdown,
     .driver = {
      .name = "dsa",
      .owner = THIS_MODULE,
     },
    };

    static int __init dsa_init_module(void)
    {
     return platform_driver_register(&dsa_driver);
    }

dsa_init_module is being called; but how do I get the system to call
.probe?

Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-15 22:19 Porting a driver to powerpc using FDT Chris Alfred
@ 2010-06-16 18:22 ` Grant Likely
  2010-06-16 22:06   ` Chris Alfred
  0 siblings, 1 reply; 13+ messages in thread
From: Grant Likely @ 2010-06-16 18:22 UTC (permalink / raw)
  To: Chris Alfred; +Cc: linuxppc-dev

On Tue, Jun 15, 2010 at 4:19 PM, Chris Alfred <c.alfred@internode.on.net> w=
rote:
> I am trying to port a DSA (Distributed Switch Architecture) driver for
> the Micrel KS8995M managed switch connected to a MPC5200. There is an
> SPI interface and MII interface managed by the DSA driver.
>
> I can't understand how probe gets called when the flatted device tree
> (FDT) system is used, and how to bind such a driver using the FDT (if
> you have to at all).
>
> The DSA driver is initialised via:
>
> =A0 =A0// net/dsa/dsa.c
>
> =A0 =A0static struct platform_driver dsa_driver =3D {
> =A0 =A0 .probe =A0=3D dsa_probe,
> =A0 =A0 .remove =A0=3D dsa_remove,
> =A0 =A0 .shutdown =3D dsa_shutdown,
> =A0 =A0 .driver =3D {
> =A0 =A0 =A0.name =3D "dsa",
> =A0 =A0 =A0.owner =3D THIS_MODULE,
> =A0 =A0 },
> =A0 =A0};
>
> =A0 =A0static int __init dsa_init_module(void)
> =A0 =A0{
> =A0 =A0 return platform_driver_register(&dsa_driver);
> =A0 =A0}
>
> dsa_init_module is being called; but how do I get the system to call
> .probe?

You need a platform device registered for the driver to bind against.
On a lot of systems, the machine setup code just registers a
statically allocated platform_device.  You can still do this on
powerpc if you create a new machine specific board file in
arch/powerpc/platforms/ (discouraged, but only mildly so for things
that are very board specific).

The "preferred" approach on device tree systems is to add device tree
hooks to the driver you want to use.  However, I'm not going to ask
you to do that since the current approach for doing so is in the
process of being removed (The current approach is to add a new
of_platform_driver registration for the device driver; but I've got
changes in my tree that will make regular old platform_drivers able to
bind against devices described in the device tree).

To avoid writing new machine-specific code in arch/powerpc/platforms,
then I recommend that you add a node to your .dts file to describe the
DSA complex and write a very simple of_platform_driver that binds
against it.  Then use the probe hook to extract data out of the device
tree node (if needed) and register the appropriate platform_device
(don't forget to make the of_device the parent of the
platform_device).  This can be considered a temporary solution, but it
will not break when I make the infrastructure changes, and then you
can migrate over to the new method at your leisure.

Cheers,
g.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-16 18:22 ` Grant Likely
@ 2010-06-16 22:06   ` Chris Alfred
  2010-06-16 22:43     ` Grant Likely
  0 siblings, 1 reply; 13+ messages in thread
From: Chris Alfred @ 2010-06-16 22:06 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

Grant Likely wrote:
> On Tue, Jun 15, 2010 at 4:19 PM, Chris Alfred
> <c.alfred@internode.on.net> wrote:
>> I am trying to port a DSA (Distributed Switch Architecture) driver
>> for the Micrel KS8995M managed switch connected to a MPC5200. There
>> is an SPI interface and MII interface managed by the DSA driver.
>>
>> I can't understand how probe gets called when the flatted device 
>> tree
>> (FDT) system is used, and how to bind such a driver using the FDT 
>> (if
>> you have to at all).
>>
>> The DSA driver is initialised via:
>>
>> // net/dsa/dsa.c
>>
>> static struct platform_driver dsa_driver = {
>> .probe = dsa_probe,
>> .remove = dsa_remove,
>> .shutdown = dsa_shutdown,
>> .driver = {
>> .name = "dsa",
>> .owner = THIS_MODULE,
>> },
>> };
>>
>> static int __init dsa_init_module(void)
>> {
>> return platform_driver_register(&dsa_driver);
>> }
>>
>> dsa_init_module is being called; but how do I get the system to 
>> call
>> .probe?
>
> To avoid writing new machine-specific code in 
> arch/powerpc/platforms,
> then I recommend that you add a node to your .dts file to describe 
> the
> DSA complex and write a very simple of_platform_driver that binds
> against it.  Then use the probe hook to extract data out of the 
> device
> tree node (if needed) and register the appropriate platform_device
> (don't forget to make the of_device the parent of the
> platform_device).  This can be considered a temporary solution, but 
> it
> will not break when I make the infrastructure changes, and then you
> can migrate over to the new method at your leisure.


Thanks for the great response.

I still have some learning to do. To start, I tried to get a simple 
of_platform_driver going.
In my .dts I added:

    / {
        ...
         dsa {
          compatible = "dsa-of";
          reg = <0 0>;   // TODO: might need config values e.g. number 
of phys, cpu port
         };
        ...
    };

I created net/dsa/dsa_of.c - the simple of_platform_driver that will 
bind to the DSA platform driver (in net/dsa/dsa.c):

    #include <linux/of.h>
    #include <linux/kernel.h>
    #include <linux/of_platform.h>

    static int __devinit dsa_of_probe(struct of_device *ofdev, const 
struct of_device_id *match)
    {
     printk("dsa_of_probe\n");
     return 0;
    }

    static int dsa_of_remove(struct of_device *ofdev)
    {
     printk("dsa_of_remove\n");
     return 0;
    }


    static const struct of_device_id dsa_of_match[] = {
     {
      .compatible = "dsa-of",
     },
     {}
    };

    static struct of_platform_driver dsa_of_driver = {
     .name = "dsa-of",
     .match_table = dsa_of_match,
     .probe = dsa_of_probe,
     .remove = dsa_of_remove,
    };

    static int __init dsa_of_init(void)
    {
     printk("dsa_of_init\n");

     if (of_register_platform_driver(&dsa_of_driver))
      printk(KERN_ERR "Unable to register DSA OF platform driver\n");

     return 0;
    }
    module_init(dsa_of_init);

    static void __exit dsa_of_cleanup(void)
    {
     printk("dsa_of_cleanup\n");

     of_unregister_platform_driver(&dsa_of_driver);
    }
    module_exit(dsa_of_cleanup);

    MODULE_DESCRIPTION("DSA OF platform driver");
    MODULE_AUTHOR("Chris Alfred <chris@greyfog.com.au");
    MODULE_LICENSE("GPL v2");

dsa_of_init is successfully called; but dsa_of_probe is not called.

Regards,
Chris 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-16 22:06   ` Chris Alfred
@ 2010-06-16 22:43     ` Grant Likely
  2010-06-16 22:48       ` Chris Alfred
  0 siblings, 1 reply; 13+ messages in thread
From: Grant Likely @ 2010-06-16 22:43 UTC (permalink / raw)
  To: Chris Alfred; +Cc: linuxppc-dev

On Wed, Jun 16, 2010 at 4:06 PM, Chris Alfred <c.alfred@internode.on.net> w=
rote:
> Grant Likely wrote:
>> On Tue, Jun 15, 2010 at 4:19 PM, Chris Alfred
>> <c.alfred@internode.on.net> wrote:
>>> I am trying to port a DSA (Distributed Switch Architecture) driver
>>> for the Micrel KS8995M managed switch connected to a MPC5200. There
>>> is an SPI interface and MII interface managed by the DSA driver.
>>>
>>> I can't understand how probe gets called when the flatted device
>>> tree
>>> (FDT) system is used, and how to bind such a driver using the FDT
>>> (if
>>> you have to at all).
>>>
>>> The DSA driver is initialised via:
>>>
>>> // net/dsa/dsa.c
>>>
>>> static struct platform_driver dsa_driver =3D {
>>> .probe =3D dsa_probe,
>>> .remove =3D dsa_remove,
>>> .shutdown =3D dsa_shutdown,
>>> .driver =3D {
>>> .name =3D "dsa",
>>> .owner =3D THIS_MODULE,
>>> },
>>> };
>>>
>>> static int __init dsa_init_module(void)
>>> {
>>> return platform_driver_register(&dsa_driver);
>>> }
>>>
>>> dsa_init_module is being called; but how do I get the system to
>>> call
>>> .probe?
>>
>> To avoid writing new machine-specific code in
>> arch/powerpc/platforms,
>> then I recommend that you add a node to your .dts file to describe
>> the
>> DSA complex and write a very simple of_platform_driver that binds
>> against it. =A0Then use the probe hook to extract data out of the
>> device
>> tree node (if needed) and register the appropriate platform_device
>> (don't forget to make the of_device the parent of the
>> platform_device). =A0This can be considered a temporary solution, but
>> it
>> will not break when I make the infrastructure changes, and then you
>> can migrate over to the new method at your leisure.
>
>
> Thanks for the great response.
>
> I still have some learning to do. To start, I tried to get a simple
> of_platform_driver going.
> In my .dts I added:
>
> =A0 =A0/ {
> =A0 =A0 =A0 =A0...
> =A0 =A0 =A0 =A0 dsa {
> =A0 =A0 =A0 =A0 =A0compatible =3D "dsa-of";

This is too generic.  Until there is a real generic binding for DSA
devices, use a name specific to your board.  An of driver can bind to
more than one compatible value.  Don't forget to include the vendor
prefix in your compatible value.

> =A0 =A0 =A0 =A0 =A0reg =3D <0 0>; =A0 // TODO: might need config values e=
.g. number
> of phys, cpu port

Just drop this property until you have real data to populate it with.
For a virtual device like this you probably don't need a reg property.
 What you probably do need in this node is references (phandles) to
the node for the marvel switch which I imagine hangs off of an MDIO or
SPI bus.

> =A0 =A0 =A0 =A0 };
> =A0 =A0 =A0 =A0...
> =A0 =A0};
>
> I created net/dsa/dsa_of.c - the simple of_platform_driver that will
> bind to the DSA platform driver (in net/dsa/dsa.c):
>
> =A0 =A0#include <linux/of.h>
> =A0 =A0#include <linux/kernel.h>
> =A0 =A0#include <linux/of_platform.h>
>
> =A0 =A0static int __devinit dsa_of_probe(struct of_device *ofdev, const
> struct of_device_id *match)
> =A0 =A0{
> =A0 =A0 printk("dsa_of_probe\n");
> =A0 =A0 return 0;
> =A0 =A0}
>
> =A0 =A0static int dsa_of_remove(struct of_device *ofdev)
> =A0 =A0{
> =A0 =A0 printk("dsa_of_remove\n");
> =A0 =A0 return 0;
> =A0 =A0}
>
>
> =A0 =A0static const struct of_device_id dsa_of_match[] =3D {
> =A0 =A0 {
> =A0 =A0 =A0.compatible =3D "dsa-of",
> =A0 =A0 },
> =A0 =A0 {}
> =A0 =A0};
>
> =A0 =A0static struct of_platform_driver dsa_of_driver =3D {
> =A0 =A0 .name =3D "dsa-of",
> =A0 =A0 .match_table =3D dsa_of_match,
> =A0 =A0 .probe =3D dsa_of_probe,
> =A0 =A0 .remove =3D dsa_of_remove,
> =A0 =A0};
>
> =A0 =A0static int __init dsa_of_init(void)
> =A0 =A0{
> =A0 =A0 printk("dsa_of_init\n");
>
> =A0 =A0 if (of_register_platform_driver(&dsa_of_driver))
> =A0 =A0 =A0printk(KERN_ERR "Unable to register DSA OF platform driver\n")=
;
>
> =A0 =A0 return 0;
> =A0 =A0}
> =A0 =A0module_init(dsa_of_init);
>
> =A0 =A0static void __exit dsa_of_cleanup(void)
> =A0 =A0{
> =A0 =A0 printk("dsa_of_cleanup\n");
>
> =A0 =A0 of_unregister_platform_driver(&dsa_of_driver);
> =A0 =A0}
> =A0 =A0module_exit(dsa_of_cleanup);
>
> =A0 =A0MODULE_DESCRIPTION("DSA OF platform driver");
> =A0 =A0MODULE_AUTHOR("Chris Alfred <chris@greyfog.com.au");
> =A0 =A0MODULE_LICENSE("GPL v2");
>
> dsa_of_init is successfully called; but dsa_of_probe is not called.

That means the node is not being used to register an of_device.  I
need some more information to suggest how best to fix this.  What SoC
are you using?  What file in arch/powerpc/platforms/* is used to setup
your machine?  It would help to have a copy of your full .dts file.

Cheers,
g.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-16 22:43     ` Grant Likely
@ 2010-06-16 22:48       ` Chris Alfred
  2010-06-16 23:14         ` Grant Likely
  0 siblings, 1 reply; 13+ messages in thread
From: Chris Alfred @ 2010-06-16 22:48 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

>> dsa_of_init is successfully called; but dsa_of_probe is not called.
>
> That means the node is not being used to register an of_device.  I
> need some more information to suggest how best to fix this.

> What SoC are you using?
> What file in arch/powerpc/platforms/* is used to setup your machine?

We are using the MPC5200. Very similar to the Lite5200.

> It would help to have a copy of your full .dts file.

/*
 * jkc5200n8 board Device Tree Source
 *
 * Copyright 2006-2007 Secret Lab Technologies Ltd.
 * Grant Likely <grant.likely@secretlab.ca>
 *
 * This program is free software; you can redistribute  it and/or 
modify it
 * under  the terms of  the GNU General  Public License as published 
by the
 * Free Software Foundation;  either version 2 of the  License, or (at 
your
 * option) any later version.
 */

/dts-v1/;

/ {
 model = "fsl,jkc5200n8";
 compatible = "fsl,jkc5200n8";
 #address-cells = <1>;
 #size-cells = <1>;
 interrupt-parent = <&mpc5200_pic>;

 cpus {
  #address-cells = <1>;
  #size-cells = <0>;

  PowerPC,5200@0 {
   device_type = "cpu";
   reg = <0>;
   d-cache-line-size = <32>;
   i-cache-line-size = <32>;
   d-cache-size = <0x4000>; // L1, 16K
   i-cache-size = <0x4000>; // L1, 16K
   timebase-frequency = <0>; // from bootloader
   bus-frequency = <0>;  // from bootloader
   clock-frequency = <0>;  // from bootloader
  };
 };

 memory {
  device_type = "memory";
  reg = <0x00000000 0x10000000>; // 256MB
 };

 dsa {
  compatible = "dsa-of";
  reg = <0 0>;   // unused
 };

 soc5200@f0000000 {
  #address-cells = <1>;
  #size-cells = <1>;
  compatible = "fsl,mpc5200b-immr";
  ranges = <0 0xf0000000 0x0000c000>;
  reg = <0xf0000000 0x00000100>;
  bus-frequency = <0>;  // from bootloader
  system-frequency = <0>;  // from bootloader

  cdm@200 {
   compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
   reg = <0x200 0x38>;
  };

  mpc5200_pic: interrupt-controller@500 {
   // 5200 interrupts are encoded into two levels;
   interrupt-controller;
   #interrupt-cells = <3>;
   compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
   reg = <0x500 0x80>;
  };

  timer@600 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x600 0x10>;
   interrupts = <1 9 0>;
   fsl,has-wdt;
  };

  timer@610 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x610 0x10>;
   interrupts = <1 10 0>;
  };

  timer@620 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x620 0x10>;
   interrupts = <1 11 0>;
  };

  timer@630 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x630 0x10>;
   interrupts = <1 12 0>;
  };

  timer@640 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x640 0x10>;
   interrupts = <1 13 0>;
  };

  timer@650 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x650 0x10>;
   interrupts = <1 14 0>;
  };

  timer@660 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x660 0x10>;
   interrupts = <1 15 0>;
  };

  timer@670 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x670 0x10>;
   interrupts = <1 16 0>;
  };

  rtc@800 { // Real time clock
   compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
   reg = <0x800 0x100>;
   interrupts = <1 5 0 1 6 0>;
  };

  can@900 {
   compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
   interrupts = <2 17 0>;
   reg = <0x900 0x80>;
  };

  can@980 {
   compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
   interrupts = <2 18 0>;
   reg = <0x980 0x80>;
  };

  gpio_simple: gpio@b00 {
   compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
   reg = <0xb00 0x40>;
   interrupts = <1 7 0>;
   gpio-controller;
   #gpio-cells = <2>;
  };

  gpio_wkup: gpio@c00 {
   compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
   reg = <0xc00 0x40>;
   interrupts = <1 8 0 0 3 0>;
   gpio-controller;
   #gpio-cells = <2>;
  };

  spi@f00 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
   reg = <0xf00 0x20>;
   interrupts = <2 13 0 2 14 0>;
   interrupt-parent = <&mpc5200_pic>;

   switch0: ethernet-switch@0 {
    //compatible = "spidev";
    //compatible = "micrel,spi-ks8995";
    compatible = "micrel,spi-ks8995-dsa";
    spi-max-frequency = <1000000>;
    reg = <0>;
   };
  };

  usb@1000 {
   compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
   reg = <0x1000 0xff>;
   interrupts = <2 6 0>;
  };

  dma-controller@1200 {
   compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
   reg = <0x1200 0x80>;
   interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
                 3 4 0  3 5 0  3 6 0  3 7 0
                 3 8 0  3 9 0  3 10 0  3 11 0
                 3 12 0  3 13 0  3 14 0  3 15 0>;
  };

  xlb@1f00 {
   compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
   reg = <0x1f00 0x100>;
  };

  serial@2000 {  // PSC1
   compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
   cell-index = <0>;
   reg = <0x2000 0x100>;
   interrupts = <2 1 0>;
  };

  // PSC2 in ac97 mode example
  ac97@2200 {  // PSC2
   compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
   cell-index = <1>;
   reg = <0x2200 0x100>;
   interrupts = <2 2 0>;
  };

  // PSC3 in CODEC mode example
  i2s@2400 {  // PSC3
   compatible = "fsl,mpc5200b-psc-i2s"; //not 5200 compatible
   cell-index = <2>;
   reg = <0x2400 0x100>;
   interrupts = <2 3 0>;
   //codec-handle = <&dummycodec>;
  };

  // PSC4 in uart mode example
  //serial@2600 {  // PSC4
  // compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
  // cell-index = <3>;
  // reg = <0x2600 0x100>;
  // interrupts = <2 11 0>;
  //};

  // PSC5 in uart mode example
  //serial@2800 {  // PSC5
  // compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
  // cell-index = <4>;
  // reg = <0x2800 0x100>;
  // interrupts = <2 12 0>;
  //};

  // PSC6 in spi mode example
  //spi@2c00 {  // PSC6
  // compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
  // cell-index = <5>;
  // reg = <0x2c00 0x100>;
  // interrupts = <2 4 0>;
  //};

  ethernet@3000 {
   compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
   reg = <0x3000 0x400>;
   local-mac-address = [ 00 00 00 00 00 00 ];
   interrupts = <2 5 0>;
   phy-handle = <&phy0>;
  };

  mdio@3000 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
   reg = <0x3000 0x400>; // fec range, since we need to setup fec 
interrupts
   interrupts = <2 5 0>; // these are for "mii command finished", not 
link changes & co.

   phy0: ethernet-phy@1 {
    reg = <1>;
   };
   phy1: ethernet-phy@2 {
    reg = <1>;
   };
   phy2: ethernet-phy@3 {
    reg = <1>;
   };
   phy3: ethernet-phy@4 {
    reg = <1>;
   };
  };

  ata@3a00 {
   compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
   reg = <0x3a00 0x100>;
   interrupts = <2 7 0>;
  };

  i2c@3d00 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
   reg = <0x3d00 0x40>;
   interrupts = <2 15 0>;
  };

  i2c@3d40 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
   reg = <0x3d40 0x40>;
   interrupts = <2 16 0>;
  };

  sram@8000 {
   compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
   reg = <0x8000 0x4000>;
  };
 };

 pci@f0000d00 {
  #interrupt-cells = <1>;
  #size-cells = <2>;
  #address-cells = <3>;
  device_type = "pci";
  compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
  reg = <0xf0000d00 0x100>;
  interrupt-map-mask = <0xf800 0 0 7>;
  interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
     0xc000 0 0 2 &mpc5200_pic 1 1 3
     0xc000 0 0 3 &mpc5200_pic 1 2 3
     0xc000 0 0 4 &mpc5200_pic 1 3 3

     0xc800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
     0xc800 0 0 2 &mpc5200_pic 1 2 3
     0xc800 0 0 3 &mpc5200_pic 1 3 3
     0xc800 0 0 4 &mpc5200_pic 0 0 3>;
  clock-frequency = <0>; // From boot loader
  interrupts = <2 8 0 2 9 0 2 10 0>;
  bus-range = <0 0>;
  ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
     0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
     0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
 };

 localbus {
  compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";

  #address-cells = <2>;
  #size-cells = <1>;

  ranges = <0 0 0xff000000 0x01000000  /* CS0: Flash */
     1 0 0x10000000 0x10000000>; /* CS1: USB ISP1761 */

  flash@0,0 {
   compatible = "cfi-flash";
   reg = <0 0 0x01000000>;
   bank-width = <2>;
   #size-cells = <1>;
   #address-cells = <1>;

   // fe000000 aliased at ff000000

   partition@0 {
    label = "spare";
    reg = <0x00000000 0x00f00000>;
   };
   partition@f00000 {
    label = "u-boot";
    reg = <0x00f00000 0x00040000>;
   };
   partition@f40000 {
    label = "u-boot-env";
    reg = <0x00f40000 0x00020000>;
   };
   partition@f60000 {
    label = "spare2";
    reg = <0x00f60000 0x000a0000>;
   };
  };

  isp1761@1,0 {
                        compatible = "nxp,usb-isp1761";
                        reg = <1 0 0x10000000>;
                        bus-width = <16>;
   big-endian;
                        interrupts = <1 1 3>; /* HC INT */
                        //interrupts = <0 0 0>;
  };
 };

};

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-16 22:48       ` Chris Alfred
@ 2010-06-16 23:14         ` Grant Likely
  2010-06-17  4:25           ` Chris Alfred
  2010-06-17 11:11           ` Chris Alfred
  0 siblings, 2 replies; 13+ messages in thread
From: Grant Likely @ 2010-06-16 23:14 UTC (permalink / raw)
  To: Chris Alfred; +Cc: linuxppc-dev

On Wed, Jun 16, 2010 at 4:48 PM, Chris Alfred <c.alfred@internode.on.net> w=
rote:
>>> dsa_of_init is successfully called; but dsa_of_probe is not called.
>>
>> That means the node is not being used to register an of_device. =A0I
>> need some more information to suggest how best to fix this.
>
>> What SoC are you using?
>> What file in arch/powerpc/platforms/* is used to setup your machine?
>
> We are using the MPC5200. Very similar to the Lite5200.

So you're board is driver by arch/powerpc/platforms/52xx/mpc5200_simple.c t=
hen?

>
>> It would help to have a copy of your full .dts file.
>
> /*
> =A0* jkc5200n8 board Device Tree Source
> =A0*
> =A0* Copyright 2006-2007 Secret Lab Technologies Ltd.
> =A0* Grant Likely <grant.likely@secretlab.ca>
> =A0*
> =A0* This program is free software; you can redistribute =A0it and/or
> modify it
> =A0* under =A0the terms of =A0the GNU General =A0Public License as publis=
hed
> by the
> =A0* Free Software Foundation; =A0either version 2 of the =A0License, or =
(at
> your
> =A0* option) any later version.
> =A0*/
>
> /dts-v1/;
>
> / {
> =A0model =3D "fsl,jkc5200n8";
> =A0compatible =3D "fsl,jkc5200n8";

Replace these two instances of 'fsl,' with this vendor name of this
board.  fsl means freescale, and I'm guessing freescale didn't design
this board.

> =A0#address-cells =3D <1>;
> =A0#size-cells =3D <1>;
> =A0interrupt-parent =3D <&mpc5200_pic>;
>
> =A0cpus {
> =A0#address-cells =3D <1>;
> =A0#size-cells =3D <0>;
>
> =A0PowerPC,5200@0 {
> =A0 device_type =3D "cpu";
> =A0 reg =3D <0>;
> =A0 d-cache-line-size =3D <32>;
> =A0 i-cache-line-size =3D <32>;
> =A0 d-cache-size =3D <0x4000>; // L1, 16K
> =A0 i-cache-size =3D <0x4000>; // L1, 16K
> =A0 timebase-frequency =3D <0>; // from bootloader
> =A0 bus-frequency =3D <0>; =A0// from bootloader
> =A0 clock-frequency =3D <0>; =A0// from bootloader
> =A0};
> =A0};
>
> =A0memory {
> =A0device_type =3D "memory";
> =A0reg =3D <0x00000000 0x10000000>; // 256MB
> =A0};
>
> =A0dsa {
> =A0compatible =3D "dsa-of";
> =A0reg =3D <0 0>; =A0 // unused

As mentioned, drop the reg property and be more specific in the
compatible value.

Okay, so the problem is that the 5200 board support doesn't understand
that this device is a real device.  The solution (and this isn't
perfect, but I'm working to make this better) is to put the node in a
place where the platform code actually processes it.  If you do the
following, then it should start working:

virtual-devices {
        compatible =3D "simple-bus";
        dsa {
              compatible =3D "<vendor>,jkc5200n8-dsa";
        };
};

Note that I've encoded the board name in the compatible value.  Until
(when/if) there is a 'generic' binding for DSA devices, you should
just use a string that is board specific.

You can look under /sys/devices to see if your device actually gets
registered or not.

This is *not* ideal.  The support code should pick up the device even
as a child of the root node, but I've got to make some changes to the
registration code to make it work correctly.

Cheers,
g.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-16 23:14         ` Grant Likely
@ 2010-06-17  4:25           ` Chris Alfred
  2010-06-17  4:29             ` Chris Alfred
  2010-06-17 14:55             ` Grant Likely
  2010-06-17 11:11           ` Chris Alfred
  1 sibling, 2 replies; 13+ messages in thread
From: Chris Alfred @ 2010-06-17  4:25 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

>>>> dsa_of_init is successfully called; but dsa_of_probe is not 
>>>> called.
>>>
>>> That means the node is not being used to register an of_device. I
>>> need some more information to suggest how best to fix this.
>>
>>> What SoC are you using?
>>> What file in arch/powerpc/platforms/* is used to setup your 
>>> machine?
>>
>> We are using the MPC5200. Very similar to the Lite5200.
>
> So you're board is driver by
> arch/powerpc/platforms/52xx/mpc5200_simple.c then?

The Lite5200 is based on arch/powerpc/platforms/52xx/lite5200.c

We have only done a text search/replace lite5200 to jkc5200.
Based on your email, we have now also changed fsl,jkc5200n8 to 
jkc,jkc5200n8

> As mentioned, drop the reg property and be more specific in the
> compatible value.

Done, changed fsl,jkc5200n8 to jkc,jkc5200n8

> If you do the
> following, then it should start working:
>
> virtual-devices {
>         compatible = "simple-bus";
>         dsa {
>               compatible = "<vendor>,jkc5200n8-dsa";
>         };
> };

Where did "simple-bus" come from?

Did you mean "mpc5200-simple-platform" from:

    define_machine(mpc5200_simple_platform) {
     .name  = "mpc5200-simple-platform",

     ...
    };

> You can look under /sys/devices to see if your device actually gets
> registered or not.

Not there unfortunately, and probe is still not called.

Regards,
Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-17  4:25           ` Chris Alfred
@ 2010-06-17  4:29             ` Chris Alfred
  2010-06-17 14:55             ` Grant Likely
  1 sibling, 0 replies; 13+ messages in thread
From: Chris Alfred @ 2010-06-17  4:29 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

> We have only done a text search/replace lite5200 to jkc5200.

I meant to write:

We copied lite5200.c to jkc5200n8.c, and have only done a text 
search/replace lite5200 to jkc5200n8

Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-16 23:14         ` Grant Likely
  2010-06-17  4:25           ` Chris Alfred
@ 2010-06-17 11:11           ` Chris Alfred
  2010-06-17 16:37             ` Grant Likely
  1 sibling, 1 reply; 13+ messages in thread
From: Chris Alfred @ 2010-06-17 11:11 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

> virtual-devices {
>         compatible = "simple-bus";
>         dsa {
>               compatible = "<vendor>,jkc5200n8-dsa";
>         };
> };

Ok, after correcting the names, the basic OF driver is probed.

Now to try and use probe to register the DSA platform driver with the 
OF driver as its parent.


=======

For those interested in how to get a very basic OF (uses FDT) driver 
going, the steps I did are below.

'myvendor' is your company name, and 'mydevice' is the name of the 
device - use better names in real code.

(1) The .dts file - this is the Flattened Device Tree (FDT) 
descriptor:

    / {
        ...

         virtual-device {
          compatible = "simple-bus";
          mydevice0 {
           compatible = "myvendor,mydevice";
          };
         };

        ...
    };

    For my board "simple-bus" is an already defined bus in the .dts. 
In my case the .dts had:

    / {
        ...

        localbus {
          compatible = 
"fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";

          ...
         };

        ...
    };

(2) Create the OF driver:

    #include <linux/of.h>
    #include <linux/kernel.h>
    #include <linux/of_platform.h>

    static int __devinit mydevice_probe(struct of_device *ofdev, const 
struct of_device_id *match)
    {
     printk("mydevice_probe\n");
     return 0;
    }

    static int mydevice_remove(struct of_device *ofdev)
    {
     printk("mydevice_remove\n");
     return 0;
    }


    static const struct of_device_id mydevice_match[] = {
     {
      .compatible = "myvendor,mydevice",
     },
     {}
    };

    static struct of_platform_driver mydevice_driver = {
     .name = "mydevice-driver",
     .match_table = mydevice_match,
     .probe = mydevice_probe,
     .remove = mydevice_remove,
    };

    static int __init mydevice_driver_init(void)
    {
     printk("mydevice_drver_init\n");

     if (of_register_platform_driver(&mydevice_driver))
      printk(KERN_ERR "Unable to register platform driver\n");

     return 0;
    }
    module_init(mydevice_driver_init);

    static void __exit mydevice_driver_cleanup(void)
    {
     printk("mydevice_driver_cleanup\n");

     of_unregister_platform_driver(&mydevice_driver);
    }
    module_exit(mydevice_driver_cleanup);

    MODULE_DESCRIPTION("mydevice driver");
    MODULE_AUTHOR("name <email>");
    MODULE_LICENSE("GPL v2");
    MODULE_ALIAS("platform:mydevice-driver");

(3) Change the appropriate Makefile and Kconfig to compile the OF 
driver.

During kernel boot you should see the lines:

    mydevice_driver_init
    mydevice_probe

If not, you probably have one of the strings (text in " ") incorrect.

In /sys/bus/of_platform/drivers, you should have a directory named 
'mydevice-driver'.

In /sys/bus/of_platform/drivers/mydevice-driver you should have a 
directory named 'mydevice0.1'. The name 'mydevice0' comes from the 
.dts above.

==========

Brief explaination of how I think this is all tied together:

(1) The Flattened Device Tree is included with the compiled kernel 
image.

(2) The module_init(...) macro is like declaring a 'main' for drivers. 
The kernel calls all of the functions declared in the module_init(...) 
macros during startup.

(3) When a device driver is registered via 
of_register_platform_driver(), this invokes a scan of the FDT to find 
matches with strings in the .match_table. If a match is found, the 
.probe is called for the created device instance.

Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-17  4:25           ` Chris Alfred
  2010-06-17  4:29             ` Chris Alfred
@ 2010-06-17 14:55             ` Grant Likely
  1 sibling, 0 replies; 13+ messages in thread
From: Grant Likely @ 2010-06-17 14:55 UTC (permalink / raw)
  To: Chris Alfred; +Cc: linuxppc-dev

On Wed, Jun 16, 2010 at 10:25 PM, Chris Alfred
<c.alfred@internode.on.net> wrote:
>>>>> dsa_of_init is successfully called; but dsa_of_probe is not
>>>>> called.
>>>>
>>>> That means the node is not being used to register an of_device. I
>>>> need some more information to suggest how best to fix this.
>>>
>>>> What SoC are you using?
>>>> What file in arch/powerpc/platforms/* is used to setup your
>>>> machine?
>>>
>>> We are using the MPC5200. Very similar to the Lite5200.
>>
>> So you're board is driver by
>> arch/powerpc/platforms/52xx/mpc5200_simple.c then?
>
> The Lite5200 is based on arch/powerpc/platforms/52xx/lite5200.c
>
> We have only done a text search/replace lite5200 to jkc5200.
> Based on your email, we have now also changed fsl,jkc5200n8 to
> jkc,jkc5200n8

Unless you need to add a bunch of board specific setup, you shouldn't
need to do this.  It should be sufficient to add jkc,jkc5200n8 to the
list of boards in mpc5200_simple.c.  The Lite5200 has a separate board
file because the original u-boot firmware for it didn't setup clocks
or port_config correctly.  Almost every other board uses
mpc5200_simple.c

media5200 is the other exception because it needs to add a whole other
irq controller.

>> As mentioned, drop the reg property and be more specific in the
>> compatible value.
>
> Done, changed fsl,jkc5200n8 to jkc,jkc5200n8
>
>> If you do the
>> following, then it should start working:
>>
>> virtual-devices {
>> =A0 =A0 =A0 =A0 compatible =3D "simple-bus";
>> =A0 =A0 =A0 =A0 dsa {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "<vendor>,jkc5200n8-dsa";
>> =A0 =A0 =A0 =A0 };
>> };
>
> Where did "simple-bus" come from?
>
> Did you mean "mpc5200-simple-platform" from:
>
> =A0 =A0define_machine(mpc5200_simple_platform) {
> =A0 =A0 .name =A0=3D "mpc5200-simple-platform",

No, mpc5200-simple-platform is just a name shown to users.  It doesn't
actually match against anything in the device tree.

"simple-bus" means that a node represents a simple transparent bridge
device.  Linux uses that value to decide that the bus node contains
device nodes that it should register.  Take a look at the ePAPR spec.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-17 11:11           ` Chris Alfred
@ 2010-06-17 16:37             ` Grant Likely
  2010-06-17 22:15               ` Chris Alfred
  0 siblings, 1 reply; 13+ messages in thread
From: Grant Likely @ 2010-06-17 16:37 UTC (permalink / raw)
  To: Chris Alfred; +Cc: linuxppc-dev

Hi Chris, thanks for the write up.  Some comments below, and I'm also
in the process of writing better documentation for all of this.  You
can find it here:

http://devicetree.org/Device_Tree_Usage

That page describes how the device tree is structured.  I'm about to
start another page on how Linux uses the device tree.  That page
should cover the same topics that you describe below.

On Thu, Jun 17, 2010 at 5:11 AM, Chris Alfred <c.alfred@internode.on.net> w=
rote:
>> virtual-devices {
>> =A0 =A0 =A0 =A0 compatible =3D "simple-bus";
>> =A0 =A0 =A0 =A0 dsa {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "<vendor>,jkc5200n8-dsa";
>> =A0 =A0 =A0 =A0 };
>> };
>
> Ok, after correcting the names, the basic OF driver is probed.
>
> Now to try and use probe to register the DSA platform driver with the
> OF driver as its parent.
>
>
> =3D=3D=3D=3D=3D=3D=3D
>
> For those interested in how to get a very basic OF (uses FDT) driver
> going, the steps I did are below.
>
> 'myvendor' is your company name, and 'mydevice' is the name of the
> device - use better names in real code.
>
> (1) The .dts file - this is the Flattened Device Tree (FDT)
> descriptor:
>
> =A0 =A0/ {
> =A0 =A0 =A0 =A0...
>
> =A0 =A0 =A0 =A0 virtual-device {
> =A0 =A0 =A0 =A0 =A0compatible =3D "simple-bus";
> =A0 =A0 =A0 =A0 =A0mydevice0 {
> =A0 =A0 =A0 =A0 =A0 compatible =3D "myvendor,mydevice";
> =A0 =A0 =A0 =A0 =A0};
> =A0 =A0 =A0 =A0 };
>
> =A0 =A0 =A0 =A0...
> =A0 =A0};
>
> =A0 =A0For my board "simple-bus" is an already defined bus in the .dts.
> In my case the .dts had:

This comment raised warning flags for me.  Can you post your new
current device tree?  It sounds like you put your DSA device into the
localbus node.  You shouldn't need to do that.  Many nodes in a single
tree can claim compatibility with "simple-bus".

>
> =A0 =A0/ {
> =A0 =A0 =A0 =A0...
>
> =A0 =A0 =A0 =A0localbus {
> =A0 =A0 =A0 =A0 =A0compatible =3D
> "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
>
> =A0 =A0 =A0 =A0 =A0...
> =A0 =A0 =A0 =A0 };
>
> =A0 =A0 =A0 =A0...
> =A0 =A0};
>
> (2) Create the OF driver:
>
> =A0 =A0#include <linux/of.h>
> =A0 =A0#include <linux/kernel.h>
> =A0 =A0#include <linux/of_platform.h>
>
> =A0 =A0static int __devinit mydevice_probe(struct of_device *ofdev, const
> struct of_device_id *match)
> =A0 =A0{
> =A0 =A0 printk("mydevice_probe\n");
> =A0 =A0 return 0;
> =A0 =A0}
>
> =A0 =A0static int mydevice_remove(struct of_device *ofdev)

__devexit

> =A0 =A0{
> =A0 =A0 printk("mydevice_remove\n");
> =A0 =A0 return 0;
> =A0 =A0}
>
>
> =A0 =A0static const struct of_device_id mydevice_match[] =3D {
> =A0 =A0 {
> =A0 =A0 =A0.compatible =3D "myvendor,mydevice",
> =A0 =A0 },
> =A0 =A0 {}
> =A0 =A0};
>
> =A0 =A0static struct of_platform_driver mydevice_driver =3D {
> =A0 =A0 .name =3D "mydevice-driver",
> =A0 =A0 .match_table =3D mydevice_match,
> =A0 =A0 .probe =3D mydevice_probe,
> =A0 =A0 .remove =3D mydevice_remove,
> =A0 =A0};

.remove =3D __devexit_P(mydevice_remove),

>
> =A0 =A0static int __init mydevice_driver_init(void)
> =A0 =A0{
> =A0 =A0 printk("mydevice_drver_init\n");
>
> =A0 =A0 if (of_register_platform_driver(&mydevice_driver))
> =A0 =A0 =A0printk(KERN_ERR "Unable to register platform driver\n");
>
> =A0 =A0 return 0;
> =A0 =A0}
> =A0 =A0module_init(mydevice_driver_init);

Should actually be:
    static int __init mydevice_driver_init(void)
    {
     printk("mydevice_drver_init\n");
     return of_register_platform_driver(&mydevice_driver);
    }
    module_init(mydevice_driver_init);

The driver core will report an error if registration fails.

>
> =A0 =A0static void __exit mydevice_driver_cleanup(void)
> =A0 =A0{
> =A0 =A0 printk("mydevice_driver_cleanup\n");
>
> =A0 =A0 of_unregister_platform_driver(&mydevice_driver);
> =A0 =A0}
> =A0 =A0module_exit(mydevice_driver_cleanup);
>
> =A0 =A0MODULE_DESCRIPTION("mydevice driver");
> =A0 =A0MODULE_AUTHOR("name <email>");
> =A0 =A0MODULE_LICENSE("GPL v2");
> =A0 =A0MODULE_ALIAS("platform:mydevice-driver");
>
> (3) Change the appropriate Makefile and Kconfig to compile the OF
> driver.
>
> During kernel boot you should see the lines:
>
> =A0 =A0mydevice_driver_init
> =A0 =A0mydevice_probe
>
> If not, you probably have one of the strings (text in " ") incorrect.
>
> In /sys/bus/of_platform/drivers, you should have a directory named
> 'mydevice-driver'.
>
> In /sys/bus/of_platform/drivers/mydevice-driver you should have a
> directory named 'mydevice0.1'. The name 'mydevice0' comes from the
> .dts above.

which will be a symlink to the actual device location in the internal
Linux device hierarchy.

>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> Brief explaination of how I think this is all tied together:
>
> (1) The Flattened Device Tree is included with the compiled kernel
> image.

Generally not.  Usually the device tree is passed in via u-boot.
There is a form (cuImage) that links the dtb into the kernel, but that
is not recommended, and is only used for supporting old version of
u-boot that cannot pass the dtb at boot.

> (2) The module_init(...) macro is like declaring a 'main' for drivers.
> The kernel calls all of the functions declared in the module_init(...)
> macros during startup.

yes.

> (3) When a device driver is registered via
> of_register_platform_driver(), this invokes a scan of the FDT to find
> matches with strings in the .match_table. If a match is found, the
> .probe is called for the created device instance.

Not quite.  Registering drivers does not cause a scan of the DT.
Instead, it looks in the list of registered devices to see if there is
anything to bind against.  The devices are actually registered at boot
time in the function of_platform_bus_probe() which on the mpc5200 is
called by the function mpc52xx_declare_of_platform_devices().

Drivers won't bind against anything that isn't already registered as a
device in the Linux device model.

Cheers,
g.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Porting a driver to powerpc using FDT
  2010-06-17 16:37             ` Grant Likely
@ 2010-06-17 22:15               ` Chris Alfred
  0 siblings, 0 replies; 13+ messages in thread
From: Chris Alfred @ 2010-06-17 22:15 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

>> (1) The .dts file - this is the Flattened Device Tree (FDT)
>> descriptor:
>>
>> / {
>> ...
>>
>> virtual-device {
>> compatible = "simple-bus";
>> mydevice0 {
>> compatible = "myvendor,mydevice";
>> };
>> };
>>
>> ...
>> };
>>
>> For my board "simple-bus" is an already defined bus in the .dts.
>> In my case the .dts had:
>
> This comment raised warning flags for me.  Can you post your new
> current device tree?  It sounds like you put your DSA device into 
> the
> localbus node.  You shouldn't need to do that.  Many nodes in a 
> single
> tree can claim compatibility with "simple-bus".

I guess my example structure was not clear. virtual-device is not 
inside localbus. My current .dts is below.

/dts-v1/;

/ {
 model = "jkc,jkc5200n8";
 compatible = "jkc,jkc5200n8";
 #address-cells = <1>;
 #size-cells = <1>;
 interrupt-parent = <&mpc5200_pic>;

 cpus {
  #address-cells = <1>;
  #size-cells = <0>;

  PowerPC,5200@0 {
   device_type = "cpu";
   reg = <0>;
   d-cache-line-size = <32>;
   i-cache-line-size = <32>;
   d-cache-size = <0x4000>; // L1, 16K
   i-cache-size = <0x4000>; // L1, 16K
   timebase-frequency = <0>; // from bootloader
   bus-frequency = <0>;  // from bootloader
   clock-frequency = <0>;  // from bootloader
  };
 };

 memory {
  device_type = "memory";
  reg = <0x00000000 0x10000000>; // 256MB
 };

 soc5200@f0000000 {
  #address-cells = <1>;
  #size-cells = <1>;
  compatible = "fsl,mpc5200b-immr";
  ranges = <0 0xf0000000 0x0000c000>;
  reg = <0xf0000000 0x00000100>;
  bus-frequency = <0>;  // from bootloader
  system-frequency = <0>;  // from bootloader

  cdm@200 {
   compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
   reg = <0x200 0x38>;
  };

  mpc5200_pic: interrupt-controller@500 {
   // 5200 interrupts are encoded into two levels;
   interrupt-controller;
   #interrupt-cells = <3>;
   compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
   reg = <0x500 0x80>;
  };

  timer@600 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x600 0x10>;
   interrupts = <1 9 0>;
   fsl,has-wdt;
  };

  timer@610 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x610 0x10>;
   interrupts = <1 10 0>;
  };

  timer@620 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x620 0x10>;
   interrupts = <1 11 0>;
  };

  timer@630 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x630 0x10>;
   interrupts = <1 12 0>;
  };

  timer@640 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x640 0x10>;
   interrupts = <1 13 0>;
  };

  timer@650 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x650 0x10>;
   interrupts = <1 14 0>;
  };

  timer@660 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x660 0x10>;
   interrupts = <1 15 0>;
  };

  timer@670 { // General Purpose Timer
   compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
   reg = <0x670 0x10>;
   interrupts = <1 16 0>;
  };

  rtc@800 { // Real time clock
   compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
   reg = <0x800 0x100>;
   interrupts = <1 5 0 1 6 0>;
  };

  can@900 {
   compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
   interrupts = <2 17 0>;
   reg = <0x900 0x80>;
  };

  can@980 {
   compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
   interrupts = <2 18 0>;
   reg = <0x980 0x80>;
  };

  gpio_simple: gpio@b00 {
   compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
   reg = <0xb00 0x40>;
   interrupts = <1 7 0>;
   gpio-controller;
   #gpio-cells = <2>;
  };

  gpio_wkup: gpio@c00 {
   compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
   reg = <0xc00 0x40>;
   interrupts = <1 8 0 0 3 0>;
   gpio-controller;
   #gpio-cells = <2>;
  };

  spi@f00 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
   reg = <0xf00 0x20>;
   interrupts = <2 13 0 2 14 0>;
   interrupt-parent = <&mpc5200_pic>;

   switch0: ethernet-switch@0 {
    compatible = "micrel,spi-ks8995-dsa";
    spi-max-frequency = <1000000>;
    reg = <0>;
   };
  };

  usb@1000 {
   compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
   reg = <0x1000 0xff>;
   interrupts = <2 6 0>;
  };

  dma-controller@1200 {
   compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
   reg = <0x1200 0x80>;
   interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
                 3 4 0  3 5 0  3 6 0  3 7 0
                 3 8 0  3 9 0  3 10 0  3 11 0
                 3 12 0  3 13 0  3 14 0  3 15 0>;
  };

  xlb@1f00 {
   compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
   reg = <0x1f00 0x100>;
  };

  serial@2000 {  // PSC1
   compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
   cell-index = <0>;
   reg = <0x2000 0x100>;
   interrupts = <2 1 0>;
  };

  // PSC2 in ac97 mode example
  ac97@2200 {  // PSC2
   compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
   cell-index = <1>;
   reg = <0x2200 0x100>;
   interrupts = <2 2 0>;
  };

  // PSC3 in CODEC mode example
  i2s@2400 {  // PSC3
   compatible = "fsl,mpc5200b-psc-i2s"; //not 5200 compatible
   cell-index = <2>;
   reg = <0x2400 0x100>;
   interrupts = <2 3 0>;
  };

  ethernet0: ethernet@3000 {
   compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
   reg = <0x3000 0x400>;
   local-mac-address = [ 00 00 00 00 00 00 ];
   interrupts = <2 5 0>;
   phy-handle = <&phy0>;
  };

  mdio0: mdio@3000 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
   reg = <0x3000 0x400>; // fec range, since we need to setup fec 
interrupts
   interrupts = <2 5 0>; // these are for "mii command finished", not 
link changes & co.

   phy0: ethernet-phy@1 {
    reg = <1>;
   };
  };

  ata@3a00 {
   compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
   reg = <0x3a00 0x100>;
   interrupts = <2 7 0>;
  };

  i2c@3d00 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
   reg = <0x3d00 0x40>;
   interrupts = <2 15 0>;
  };

  i2c@3d40 {
   #address-cells = <1>;
   #size-cells = <0>;
   compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
   reg = <0x3d40 0x40>;
   interrupts = <2 16 0>;
  };

  sram@8000 {
   compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
   reg = <0x8000 0x4000>;
  };
 };

 pci@f0000d00 {
  #interrupt-cells = <1>;
  #size-cells = <2>;
  #address-cells = <3>;
  device_type = "pci";
  compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
  reg = <0xf0000d00 0x100>;
  interrupt-map-mask = <0xf800 0 0 7>;
  interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
     0xc000 0 0 2 &mpc5200_pic 1 1 3
     0xc000 0 0 3 &mpc5200_pic 1 2 3
     0xc000 0 0 4 &mpc5200_pic 1 3 3

     0xc800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
     0xc800 0 0 2 &mpc5200_pic 1 2 3
     0xc800 0 0 3 &mpc5200_pic 1 3 3
     0xc800 0 0 4 &mpc5200_pic 0 0 3>;
  clock-frequency = <0>; // From boot loader
  interrupts = <2 8 0 2 9 0 2 10 0>;
  bus-range = <0 0>;
  ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
     0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
     0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
 };

 virtual-device {
  compatible = "simple-bus";
  dsa {
   compatible = "jkc,jkc5200n8-dsa-of";
   ethernet-handle = <&ethernet0>;
   mdio-handle = <&mdio0>;
   // TODO: incomplete, in design
  };
 };

 localbus {
  compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";

  #address-cells = <2>;
  #size-cells = <1>;

  ranges = <0 0 0xff000000 0x01000000  /* CS0: Flash */
     1 0 0x10000000 0x10000000>; /* CS1: USB ISP1761 */

  flash@0,0 {
   compatible = "cfi-flash";
   reg = <0 0 0x01000000>;
   bank-width = <2>;
   #size-cells = <1>;
   #address-cells = <1>;

   // fe000000 aliased at ff000000

   partition@0 {
    label = "spare";
    reg = <0x00000000 0x00f00000>;
   };
   partition@f00000 {
    label = "u-boot";
    reg = <0x00f00000 0x00040000>;
   };
   partition@f40000 {
    label = "u-boot-env";
    reg = <0x00f40000 0x00020000>;
   };
   partition@f60000 {
    label = "spare2";
    reg = <0x00f60000 0x000a0000>;
   };
  };

  isp1761@1,0 {
   compatible = "nxp,usb-isp1761";
   reg = <1 0 0x10000000>;
   bus-width = <16>;
   big-endian;
   interrupts = <1 1 3>; /* HC INT */
  };
 };
};

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-06-17 22:16 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-15 22:19 Porting a driver to powerpc using FDT Chris Alfred
2010-06-16 18:22 ` Grant Likely
2010-06-16 22:06   ` Chris Alfred
2010-06-16 22:43     ` Grant Likely
2010-06-16 22:48       ` Chris Alfred
2010-06-16 23:14         ` Grant Likely
2010-06-17  4:25           ` Chris Alfred
2010-06-17  4:29             ` Chris Alfred
2010-06-17 14:55             ` Grant Likely
2010-06-17 11:11           ` Chris Alfred
2010-06-17 16:37             ` Grant Likely
2010-06-17 22:15               ` Chris Alfred
  -- strict thread matches above, loose matches on Subject: below --
2010-06-15 22:18 Chris Alfred (Internode)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).