diff mbox

[v6,3/4] drivers: of: add initialization code for dma reserved memory

Message ID 1376924669-28873-4-git-send-email-m.szyprowski@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marek Szyprowski Aug. 19, 2013, 3:04 p.m. UTC
This patch adds device tree support for contiguous and reserved memory
regions defined in device tree.

Large memory blocks can be reliably reserved only during early boot.
This must happen before the whole memory management subsystem is
initialized, because we need to ensure that the given contiguous blocks
are not yet allocated by kernel. Also it must happen before kernel
mappings for the whole low memory are created, to ensure that there will
be no mappings (for reserved blocks) or mapping with special properties
can be created (for CMA blocks). This all happens before device tree
structures are unflattened, so we need to get reserved memory layout
directly from fdt.

Later, those reserved memory regions are assigned to devices on each
device structure initialization.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Acked-by: Tomasz Figa <t.figa@samsung.com>
---
 Documentation/devicetree/bindings/memory.txt |  166 ++++++++++++++++++++++++
 drivers/of/Kconfig                           |    6 +
 drivers/of/Makefile                          |    1 +
 drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
 drivers/of/platform.c                        |    5 +
 include/linux/of_reserved_mem.h              |   14 +++
 6 files changed, 367 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory.txt
 create mode 100644 drivers/of/of_reserved_mem.c
 create mode 100644 include/linux/of_reserved_mem.h

Comments

Stephen Warren Aug. 19, 2013, 9:49 p.m. UTC | #1
On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> This patch adds device tree support for contiguous and reserved memory
> regions defined in device tree.

> diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt

> +*** Reserved memory regions ***
> +
> +In /memory/reserved-memory node one can create additional nodes

s/additional/child/ or s/additional/sub/ would make it clearer where the
"additional" nodes should be placed.

> +compatible:	"linux,contiguous-memory-region" - enables binding of this
> +		region to Contiguous Memory Allocator (special region for
> +		contiguous memory allocations, shared with movable system
> +		memory, Linux kernel-specific), alternatively if
> +		"reserved-memory-region" - compatibility is defined, given
> +		region is assigned for exclusive usage for by the respective
> +		devices

"alternatively" makes it sound like the two compatible values are
mutually-exclusive. Perhaps make this a list, like:

----------
compatible: One or more of:

	- "linux,contiguous-memory-region" - enables binding of this
	  region to Contiguous Memory Allocator (special region for
	  contiguous memory allocations, shared with movable system
	  memory, Linux kernel-specific).
	- "reserved-memory-region" - compatibility is defined, given
	  region is assigned for exclusive usage for by the respective
	  devices.
----------

"linux,contiguous-memory-region" is already long enough, but I'd
slightly bikeshed towards "linux,contiguous-memory-allocator-region", or
perhaps "linux,cma-region" since it's not really describing whether the
memory is contiguous (at the level of /memory, each chunk of memory is
contiguous...)

> +*** Device node's properties ***
> +
> +Once regions in the /memory/reserved-memory node have been defined, they
> +can be assigned to device nodes to enable respective device drivers to
> +access them. The following properties are defined:
> +
> +memory-region = <&phandle_to_defined_region>;

I think the naming of that property should more obviously match this
binding and/or compatible value; perhaps cma-region or
contiguous-memory-region?
Tomasz Figa Aug. 19, 2013, 10:02 p.m. UTC | #2
Hi Stephen,

On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> > This patch adds device tree support for contiguous and reserved memory
> > regions defined in device tree.
> > 
> > diff --git a/Documentation/devicetree/bindings/memory.txt
> > b/Documentation/devicetree/bindings/memory.txt
> > 
> > +*** Reserved memory regions ***
> > +
> > +In /memory/reserved-memory node one can create additional nodes
> 
> s/additional/child/ or s/additional/sub/ would make it clearer where the
> "additional" nodes should be placed.
> 
> > +compatible:	"linux,contiguous-memory-region" - enables binding 
of
> > this
> > +		region to Contiguous Memory Allocator (special region for
> > +		contiguous memory allocations, shared with movable system
> > +		memory, Linux kernel-specific), alternatively if
> > +		"reserved-memory-region" - compatibility is defined, given
> > +		region is assigned for exclusive usage for by the 
respective
> > +		devices
> 
> "alternatively" makes it sound like the two compatible values are
> mutually-exclusive. Perhaps make this a list, like:
> 
> ----------
> compatible: One or more of:
> 
> 	- "linux,contiguous-memory-region" - enables binding of this
> 	  region to Contiguous Memory Allocator (special region for
> 	  contiguous memory allocations, shared with movable system
> 	  memory, Linux kernel-specific).
> 	- "reserved-memory-region" - compatibility is defined, given
> 	  region is assigned for exclusive usage for by the respective
> 	  devices.
> ----------
> 
> "linux,contiguous-memory-region" is already long enough, but I'd
> slightly bikeshed towards "linux,contiguous-memory-allocator-region", or
> perhaps "linux,cma-region" since it's not really describing whether the
> memory is contiguous (at the level of /memory, each chunk of memory is
> contiguous...)

I'm not really sure if we need the "linux" prefix for "contiguous-memory-
region". The concept of contiguous memory region is rather OS independent 
and tells us that memory allocated from this region will be contiguous. 
IMHO any OS is free to implement its own contiguous memory allocation 
method, without being limited to Linux CMA.

Keep in mind that rationale behind those contiguous regions was that there 
are devices that require buffers contiguous in memory to operate 
correctly.

But this is just nitpicking and I don't really have any strong opinion on 
this.

> > +*** Device node's properties ***
> > +
> > +Once regions in the /memory/reserved-memory node have been defined,
> > they +can be assigned to device nodes to enable respective device
> > drivers to +access them. The following properties are defined:
> > +
> > +memory-region = <&phandle_to_defined_region>;
> 
> I think the naming of that property should more obviously match this
> binding and/or compatible value; perhaps cma-region or
> contiguous-memory-region?

This property is not CMA-specific. Any memory region can be given using 
the memory-region property and used to allocate buffers for particular 
device.

Best regards,
Tomasz
Stephen Warren Aug. 19, 2013, 10:17 p.m. UTC | #3
On 08/19/2013 04:02 PM, Tomasz Figa wrote:
> Hi Stephen,
> 
> On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
>> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
>>> This patch adds device tree support for contiguous and reserved memory
>>> regions defined in device tree.
>>>
>>> diff --git a/Documentation/devicetree/bindings/memory.txt
>>> b/Documentation/devicetree/bindings/memory.txt
>>>
>>> +*** Reserved memory regions ***
>>> +
>>> +In /memory/reserved-memory node one can create additional nodes
>>
>> s/additional/child/ or s/additional/sub/ would make it clearer where the
>> "additional" nodes should be placed.
>>
>>> +compatible:	"linux,contiguous-memory-region" - enables binding 
> of
>>> this
>>> +		region to Contiguous Memory Allocator (special region for
>>> +		contiguous memory allocations, shared with movable system
>>> +		memory, Linux kernel-specific), alternatively if
>>> +		"reserved-memory-region" - compatibility is defined, given
>>> +		region is assigned for exclusive usage for by the 
> respective
>>> +		devices
>>
>> "alternatively" makes it sound like the two compatible values are
>> mutually-exclusive. Perhaps make this a list, like:
>>
>> ----------
>> compatible: One or more of:
>>
>> 	- "linux,contiguous-memory-region" - enables binding of this
>> 	  region to Contiguous Memory Allocator (special region for
>> 	  contiguous memory allocations, shared with movable system
>> 	  memory, Linux kernel-specific).
>> 	- "reserved-memory-region" - compatibility is defined, given
>> 	  region is assigned for exclusive usage for by the respective
>> 	  devices.
>> ----------
>>
>> "linux,contiguous-memory-region" is already long enough, but I'd
>> slightly bikeshed towards "linux,contiguous-memory-allocator-region", or
>> perhaps "linux,cma-region" since it's not really describing whether the
>> memory is contiguous (at the level of /memory, each chunk of memory is
>> contiguous...)
> 
> I'm not really sure if we need the "linux" prefix for "contiguous-memory-
> region". The concept of contiguous memory region is rather OS independent 
> and tells us that memory allocated from this region will be contiguous. 
> IMHO any OS is free to implement its own contiguous memory allocation 
> method, without being limited to Linux CMA.
> 
> Keep in mind that rationale behind those contiguous regions was that there 
> are devices that require buffers contiguous in memory to operate 
> correctly.
> 
> But this is just nitpicking and I don't really have any strong opinion on 
> this.
> 
>>> +*** Device node's properties ***
>>> +
>>> +Once regions in the /memory/reserved-memory node have been defined,
>>> they +can be assigned to device nodes to enable respective device
>>> drivers to +access them. The following properties are defined:
>>> +
>>> +memory-region = <&phandle_to_defined_region>;
>>
>> I think the naming of that property should more obviously match this
>> binding and/or compatible value; perhaps cma-region or
>> contiguous-memory-region?
> 
> This property is not CMA-specific. Any memory region can be given using 
> the memory-region property and used to allocate buffers for particular 
> device.

OK, that makes sense.

What I'm looking for is some way to make it obvious that when you see a
"memory-region" property in a node, you go look at the "memory.txt"
rather than the DT binding for the node where that property appears.
Right now, it doesn't seem that obvious to me.

I think the real issue here is that my brief reading of memory.txt
implies that arbitrary device nodes can include the memory-region
property without the node's own binding having to document it; the
property name is essentially "forced into" all other bindings.

I think instead, memory.txt should say:

----------
** Device node's properties ***

Once regions in the /memory/reserved-memory node have been defined, they
may be referenced by other device nodes. Bindings that wish to reference
memory regions should explicitly document their use of the following
property:

memory-region = <&phandle_to_defined_region>;

This property indicates that the device driver should use the memory
region pointed by the given phandle.
----------

Also, what if a device needs multiple separate memory regions? Perhaps a
GPU is forced to allocate displayable surfaces from addresses 0..32M and
textures/off-screen-render-targets from 256M..384M or something whacky
like that. In that case, we could either:

a) Adjust memory.txt to allow multiple entries in memory-regions, and
add an associated memory-region-names property.

or:

b) Adjust memory.txt not to mention any specific property names, but
simply mention that other DT nodes can refer to define memory regions by
phandle, and leave it up to individual bindings to define which property
they use to reference the memory regions, perhaps with memory.txt
providing a recommendation of memory-region for the simple case, but
perhaps also allowing a custom case, e.g.:

display-memory-region = <&phandl1e1>;
texture-memory-region = <&phahndle2>;
Tomasz Figa Aug. 19, 2013, 10:24 p.m. UTC | #4
On Monday 19 of August 2013 16:17:30 Stephen Warren wrote:
> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
> > Hi Stephen,
> > 
> > On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> >> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> >>> This patch adds device tree support for contiguous and reserved
> >>> memory
> >>> regions defined in device tree.
> >>> 
> >>> diff --git a/Documentation/devicetree/bindings/memory.txt
> >>> b/Documentation/devicetree/bindings/memory.txt
> >>> 
> >>> +*** Reserved memory regions ***
> >>> +
> >>> +In /memory/reserved-memory node one can create additional nodes
> >> 
> >> s/additional/child/ or s/additional/sub/ would make it clearer where
> >> the "additional" nodes should be placed.
> >> 
> >>> +compatible:	"linux,contiguous-memory-region" - enables binding
> > 
> > of
> > 
> >>> this
> >>> +		region to Contiguous Memory Allocator (special region for
> >>> +		contiguous memory allocations, shared with movable system
> >>> +		memory, Linux kernel-specific), alternatively if
> >>> +		"reserved-memory-region" - compatibility is defined, given
> >>> +		region is assigned for exclusive usage for by the
> > 
> > respective
> > 
> >>> +		devices
> >> 
> >> "alternatively" makes it sound like the two compatible values are
> >> mutually-exclusive. Perhaps make this a list, like:
> >> 
> >> ----------
> >> 
> >> compatible: One or more of:
> >> 	- "linux,contiguous-memory-region" - enables binding of this
> >> 	
> >> 	  region to Contiguous Memory Allocator (special region for
> >> 	  contiguous memory allocations, shared with movable system
> >> 	  memory, Linux kernel-specific).
> >> 	
> >> 	- "reserved-memory-region" - compatibility is defined, given
> >> 	
> >> 	  region is assigned for exclusive usage for by the respective
> >> 	  devices.
> >> 
> >> ----------
> >> 
> >> "linux,contiguous-memory-region" is already long enough, but I'd
> >> slightly bikeshed towards "linux,contiguous-memory-allocator-region",
> >> or perhaps "linux,cma-region" since it's not really describing
> >> whether the memory is contiguous (at the level of /memory, each
> >> chunk of memory is contiguous...)
> > 
> > I'm not really sure if we need the "linux" prefix for
> > "contiguous-memory- region". The concept of contiguous memory region
> > is rather OS independent and tells us that memory allocated from this
> > region will be contiguous. IMHO any OS is free to implement its own
> > contiguous memory allocation method, without being limited to Linux
> > CMA.
> > 
> > Keep in mind that rationale behind those contiguous regions was that
> > there are devices that require buffers contiguous in memory to
> > operate correctly.
> > 
> > But this is just nitpicking and I don't really have any strong opinion
> > on this.
> > 
> >>> +*** Device node's properties ***
> >>> +
> >>> +Once regions in the /memory/reserved-memory node have been defined,
> >>> they +can be assigned to device nodes to enable respective device
> >>> drivers to +access them. The following properties are defined:
> >>> +
> >>> +memory-region = <&phandle_to_defined_region>;
> >> 
> >> I think the naming of that property should more obviously match this
> >> binding and/or compatible value; perhaps cma-region or
> >> contiguous-memory-region?
> > 
> > This property is not CMA-specific. Any memory region can be given
> > using
> > the memory-region property and used to allocate buffers for particular
> > device.
> 
> OK, that makes sense.
> 
> What I'm looking for is some way to make it obvious that when you see a
> "memory-region" property in a node, you go look at the "memory.txt"
> rather than the DT binding for the node where that property appears.
> Right now, it doesn't seem that obvious to me.
> 
> I think the real issue here is that my brief reading of memory.txt
> implies that arbitrary device nodes can include the memory-region
> property without the node's own binding having to document it; the
> property name is essentially "forced into" all other bindings.
> 
> I think instead, memory.txt should say:
> 
> ----------
> ** Device node's properties ***
> 
> Once regions in the /memory/reserved-memory node have been defined, they
> may be referenced by other device nodes. Bindings that wish to
> reference memory regions should explicitly document their use of the
> following property:
> 
> memory-region = <&phandle_to_defined_region>;
> 
> This property indicates that the device driver should use the memory
> region pointed by the given phandle.
> ----------
> 
> Also, what if a device needs multiple separate memory regions? Perhaps a
> GPU is forced to allocate displayable surfaces from addresses 0..32M
> and textures/off-screen-render-targets from 256M..384M or something
> whacky like that. In that case, we could either:
> 
> a) Adjust memory.txt to allow multiple entries in memory-regions, and
> add an associated memory-region-names property.
> 
> or:
> 
> b) Adjust memory.txt not to mention any specific property names, but
> simply mention that other DT nodes can refer to define memory regions by
> phandle, and leave it up to individual bindings to define which
> property they use to reference the memory regions, perhaps with
> memory.txt providing a recommendation of memory-region for the simple
> case, but perhaps also allowing a custom case, e.g.:
> 
> display-memory-region = <&phandl1e1>;
> texture-memory-region = <&phahndle2>;

Well, such setup simply cannot be handled by Linux today, as one device 
(aka one struct device) can only have one memory region bound to it. So 
this is not something we can implement today.

I agree that the device tree should be able to describe such 
configurations, though, but I'm not sure if this should be done from this 
side.

IMHO the concept of memport (or bus master) can be used to represent cases 
when multiple parts of an IP have different requirements for memory they 
work with. This is what Marek's patches adjusting MFC bindings to use 
memory-regions are also about.

Best regards,
Tomasz
Stephen Warren Aug. 19, 2013, 10:27 p.m. UTC | #5
On 08/19/2013 04:24 PM, Tomasz Figa wrote:
> On Monday 19 of August 2013 16:17:30 Stephen Warren wrote:
>> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
>>> Hi Stephen,
>>>
>>> On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
>>>> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
>>>>> This patch adds device tree support for contiguous and reserved
>>>>> memory
>>>>> regions defined in device tree.
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/memory.txt
>>>>> b/Documentation/devicetree/bindings/memory.txt
>>>>>
>>>>> +*** Reserved memory regions ***
>>>>> +
>>>>> +In /memory/reserved-memory node one can create additional nodes
>>>>
>>>> s/additional/child/ or s/additional/sub/ would make it clearer where
>>>> the "additional" nodes should be placed.
>>>>
>>>>> +compatible:	"linux,contiguous-memory-region" - enables binding
>>>
>>> of
>>>
>>>>> this
>>>>> +		region to Contiguous Memory Allocator (special region for
>>>>> +		contiguous memory allocations, shared with movable system
>>>>> +		memory, Linux kernel-specific), alternatively if
>>>>> +		"reserved-memory-region" - compatibility is defined, given
>>>>> +		region is assigned for exclusive usage for by the
>>>
>>> respective
>>>
>>>>> +		devices
>>>>
>>>> "alternatively" makes it sound like the two compatible values are
>>>> mutually-exclusive. Perhaps make this a list, like:
>>>>
>>>> ----------
>>>>
>>>> compatible: One or more of:
>>>> 	- "linux,contiguous-memory-region" - enables binding of this
>>>> 	
>>>> 	  region to Contiguous Memory Allocator (special region for
>>>> 	  contiguous memory allocations, shared with movable system
>>>> 	  memory, Linux kernel-specific).
>>>> 	
>>>> 	- "reserved-memory-region" - compatibility is defined, given
>>>> 	
>>>> 	  region is assigned for exclusive usage for by the respective
>>>> 	  devices.
>>>>
>>>> ----------
>>>>
>>>> "linux,contiguous-memory-region" is already long enough, but I'd
>>>> slightly bikeshed towards "linux,contiguous-memory-allocator-region",
>>>> or perhaps "linux,cma-region" since it's not really describing
>>>> whether the memory is contiguous (at the level of /memory, each
>>>> chunk of memory is contiguous...)
>>>
>>> I'm not really sure if we need the "linux" prefix for
>>> "contiguous-memory- region". The concept of contiguous memory region
>>> is rather OS independent and tells us that memory allocated from this
>>> region will be contiguous. IMHO any OS is free to implement its own
>>> contiguous memory allocation method, without being limited to Linux
>>> CMA.
>>>
>>> Keep in mind that rationale behind those contiguous regions was that
>>> there are devices that require buffers contiguous in memory to
>>> operate correctly.
>>>
>>> But this is just nitpicking and I don't really have any strong opinion
>>> on this.
>>>
>>>>> +*** Device node's properties ***
>>>>> +
>>>>> +Once regions in the /memory/reserved-memory node have been defined,
>>>>> they +can be assigned to device nodes to enable respective device
>>>>> drivers to +access them. The following properties are defined:
>>>>> +
>>>>> +memory-region = <&phandle_to_defined_region>;
>>>>
>>>> I think the naming of that property should more obviously match this
>>>> binding and/or compatible value; perhaps cma-region or
>>>> contiguous-memory-region?
>>>
>>> This property is not CMA-specific. Any memory region can be given
>>> using
>>> the memory-region property and used to allocate buffers for particular
>>> device.
>>
>> OK, that makes sense.
>>
>> What I'm looking for is some way to make it obvious that when you see a
>> "memory-region" property in a node, you go look at the "memory.txt"
>> rather than the DT binding for the node where that property appears.
>> Right now, it doesn't seem that obvious to me.
>>
>> I think the real issue here is that my brief reading of memory.txt
>> implies that arbitrary device nodes can include the memory-region
>> property without the node's own binding having to document it; the
>> property name is essentially "forced into" all other bindings.
>>
>> I think instead, memory.txt should say:
>>
>> ----------
>> ** Device node's properties ***
>>
>> Once regions in the /memory/reserved-memory node have been defined, they
>> may be referenced by other device nodes. Bindings that wish to
>> reference memory regions should explicitly document their use of the
>> following property:
>>
>> memory-region = <&phandle_to_defined_region>;
>>
>> This property indicates that the device driver should use the memory
>> region pointed by the given phandle.
>> ----------
>>
>> Also, what if a device needs multiple separate memory regions? Perhaps a
>> GPU is forced to allocate displayable surfaces from addresses 0..32M
>> and textures/off-screen-render-targets from 256M..384M or something
>> whacky like that. In that case, we could either:
>>
>> a) Adjust memory.txt to allow multiple entries in memory-regions, and
>> add an associated memory-region-names property.
>>
>> or:
>>
>> b) Adjust memory.txt not to mention any specific property names, but
>> simply mention that other DT nodes can refer to define memory regions by
>> phandle, and leave it up to individual bindings to define which
>> property they use to reference the memory regions, perhaps with
>> memory.txt providing a recommendation of memory-region for the simple
>> case, but perhaps also allowing a custom case, e.g.:
>>
>> display-memory-region = <&phandl1e1>;
>> texture-memory-region = <&phahndle2>;
> 
> Well, such setup simply cannot be handled by Linux today, as one device 
> (aka one struct device) can only have one memory region bound to it. So 
> this is not something we can implement today.

Don't you just create "fake" struct devices to make this work, so that
the top-level struct device is instantiated from DT, and the others
created manually in the top-level device's probe routine, and the memory
regions get attached to those "fake" child devices? Seems pretty
conceptually easy.

> I agree that the device tree should be able to describe such 
> configurations,

good:-)

> though, but I'm not sure if this should be done from this side.

I'm not sure what "from this side" means. It seems pretty simple to
adjust this patch to allow such HW to be represented, so shouldn't we
just do it and be done with the question?
Tomasz Figa Aug. 19, 2013, 10:40 p.m. UTC | #6
On Monday 19 of August 2013 16:27:14 Stephen Warren wrote:
> On 08/19/2013 04:24 PM, Tomasz Figa wrote:
> > On Monday 19 of August 2013 16:17:30 Stephen Warren wrote:
> >> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
> >>> Hi Stephen,
> >>> 
> >>> On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> >>>> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> >>>>> This patch adds device tree support for contiguous and reserved
> >>>>> memory
> >>>>> regions defined in device tree.
> >>>>> 
> >>>>> diff --git a/Documentation/devicetree/bindings/memory.txt
> >>>>> b/Documentation/devicetree/bindings/memory.txt
> >>>>> 
> >>>>> +*** Reserved memory regions ***
> >>>>> +
> >>>>> +In /memory/reserved-memory node one can create additional nodes
> >>>> 
> >>>> s/additional/child/ or s/additional/sub/ would make it clearer
> >>>> where
> >>>> the "additional" nodes should be placed.
> >>>> 
> >>>>> +compatible:	"linux,contiguous-memory-region" - enables binding
> >>> 
> >>> of
> >>> 
> >>>>> this
> >>>>> +		region to Contiguous Memory Allocator (special 
region for
> >>>>> +		contiguous memory allocations, shared with movable 
system
> >>>>> +		memory, Linux kernel-specific), alternatively if
> >>>>> +		"reserved-memory-region" - compatibility is 
defined, given
> >>>>> +		region is assigned for exclusive usage for by the
> >>> 
> >>> respective
> >>> 
> >>>>> +		devices
> >>>> 
> >>>> "alternatively" makes it sound like the two compatible values are
> >>>> mutually-exclusive. Perhaps make this a list, like:
> >>>> 
> >>>> ----------
> >>>> 
> >>>> compatible: One or more of:
> >>>> 	- "linux,contiguous-memory-region" - enables binding of this
> >>>> 	
> >>>> 	  region to Contiguous Memory Allocator (special region for
> >>>> 	  contiguous memory allocations, shared with movable system
> >>>> 	  memory, Linux kernel-specific).
> >>>> 	
> >>>> 	- "reserved-memory-region" - compatibility is defined, given
> >>>> 	
> >>>> 	  region is assigned for exclusive usage for by the respective
> >>>> 	  devices.
> >>>> 
> >>>> ----------
> >>>> 
> >>>> "linux,contiguous-memory-region" is already long enough, but I'd
> >>>> slightly bikeshed towards
> >>>> "linux,contiguous-memory-allocator-region",
> >>>> or perhaps "linux,cma-region" since it's not really describing
> >>>> whether the memory is contiguous (at the level of /memory, each
> >>>> chunk of memory is contiguous...)
> >>> 
> >>> I'm not really sure if we need the "linux" prefix for
> >>> "contiguous-memory- region". The concept of contiguous memory region
> >>> is rather OS independent and tells us that memory allocated from
> >>> this
> >>> region will be contiguous. IMHO any OS is free to implement its own
> >>> contiguous memory allocation method, without being limited to Linux
> >>> CMA.
> >>> 
> >>> Keep in mind that rationale behind those contiguous regions was that
> >>> there are devices that require buffers contiguous in memory to
> >>> operate correctly.
> >>> 
> >>> But this is just nitpicking and I don't really have any strong
> >>> opinion
> >>> on this.
> >>> 
> >>>>> +*** Device node's properties ***
> >>>>> +
> >>>>> +Once regions in the /memory/reserved-memory node have been
> >>>>> defined,
> >>>>> they +can be assigned to device nodes to enable respective device
> >>>>> drivers to +access them. The following properties are defined:
> >>>>> +
> >>>>> +memory-region = <&phandle_to_defined_region>;
> >>>> 
> >>>> I think the naming of that property should more obviously match
> >>>> this
> >>>> binding and/or compatible value; perhaps cma-region or
> >>>> contiguous-memory-region?
> >>> 
> >>> This property is not CMA-specific. Any memory region can be given
> >>> using
> >>> the memory-region property and used to allocate buffers for
> >>> particular
> >>> device.
> >> 
> >> OK, that makes sense.
> >> 
> >> What I'm looking for is some way to make it obvious that when you see
> >> a
> >> "memory-region" property in a node, you go look at the "memory.txt"
> >> rather than the DT binding for the node where that property appears.
> >> Right now, it doesn't seem that obvious to me.
> >> 
> >> I think the real issue here is that my brief reading of memory.txt
> >> implies that arbitrary device nodes can include the memory-region
> >> property without the node's own binding having to document it; the
> >> property name is essentially "forced into" all other bindings.
> >> 
> >> I think instead, memory.txt should say:
> >> 
> >> ----------
> >> ** Device node's properties ***
> >> 
> >> Once regions in the /memory/reserved-memory node have been defined,
> >> they may be referenced by other device nodes. Bindings that wish to
> >> reference memory regions should explicitly document their use of the
> >> following property:
> >> 
> >> memory-region = <&phandle_to_defined_region>;
> >> 
> >> This property indicates that the device driver should use the memory
> >> region pointed by the given phandle.
> >> ----------
> >> 
> >> Also, what if a device needs multiple separate memory regions?
> >> Perhaps a GPU is forced to allocate displayable surfaces from
> >> addresses 0..32M and textures/off-screen-render-targets from
> >> 256M..384M or something whacky like that. In that case, we could
> >> either:
> >> 
> >> a) Adjust memory.txt to allow multiple entries in memory-regions, and
> >> add an associated memory-region-names property.
> >> 
> >> or:
> >> 
> >> b) Adjust memory.txt not to mention any specific property names, but
> >> simply mention that other DT nodes can refer to define memory regions
> >> by phandle, and leave it up to individual bindings to define which
> >> property they use to reference the memory regions, perhaps with
> >> memory.txt providing a recommendation of memory-region for the
> >> simple case, but perhaps also allowing a custom case, e.g.:
> >> 
> >> display-memory-region = <&phandl1e1>;
> >> texture-memory-region = <&phahndle2>;
> > 
> > Well, such setup simply cannot be handled by Linux today, as one
> > device
> > (aka one struct device) can only have one memory region bound to it.
> > So
> > this is not something we can implement today.
> 
> Don't you just create "fake" struct devices to make this work, so that
> the top-level struct device is instantiated from DT, and the others
> created manually in the top-level device's probe routine, and the memory
> regions get attached to those "fake" child devices? Seems pretty
> conceptually easy.

Correct. However you need those fake struct devices to be attached to some 
memory region and often other things like IOMMU. In fact, they aren't 
entirely fake, as they usually represent real bus masters of the IP.

> > I agree that the device tree should be able to describe such
> > configurations,
> 
> good:-)
> 
> > though, but I'm not sure if this should be done from this side.
> 
> I'm not sure what "from this side" means. It seems pretty simple to
> adjust this patch to allow such HW to be represented, so shouldn't we
> just do it and be done with the question?

Well, if it's just about modifying the binding to support such cases, but 
without actually adding support for them in Linux, then I guess it's fine. 
Otherwise a lot of memory management code (mostly the DMA mapping API and 
a lot of its users) would have to be almost completely reworked, which 
wouldn't be an easy task.

Best regards,
Tomasz
Stephen Warren Aug. 19, 2013, 10:54 p.m. UTC | #7
On 08/19/2013 04:40 PM, Tomasz Figa wrote:
> On Monday 19 of August 2013 16:27:14 Stephen Warren wrote:
>> On 08/19/2013 04:24 PM, Tomasz Figa wrote:
>>> On Monday 19 of August 2013 16:17:30 Stephen Warren wrote:
>>>> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
>>>>> Hi Stephen,
>>>>>
>>>>> On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
>>>>>> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
>>>>>>> This patch adds device tree support for contiguous and reserved
>>>>>>> memory regions defined in device tree.
>>>>>>>
>>>>>>> diff --git a/Documentation/devicetree/bindings/memory.txt
>>>>>>> b/Documentation/devicetree/bindings/memory.txt
...
>>>> Also, what if a device needs multiple separate memory regions?
>>>> Perhaps a GPU is forced to allocate displayable surfaces from
>>>> addresses 0..32M and textures/off-screen-render-targets from
>>>> 256M..384M or something whacky like that. In that case, we could
>>>> either:
>>>>
>>>> a) Adjust memory.txt to allow multiple entries in memory-regions, and
>>>> add an associated memory-region-names property.
>>>>
>>>> or:
>>>>
>>>> b) Adjust memory.txt not to mention any specific property names, but
>>>> simply mention that other DT nodes can refer to define memory regions
>>>> by phandle, and leave it up to individual bindings to define which
>>>> property they use to reference the memory regions, perhaps with
>>>> memory.txt providing a recommendation of memory-region for the
>>>> simple case, but perhaps also allowing a custom case, e.g.:
>>>>
>>>> display-memory-region = <&phandl1e1>;
>>>> texture-memory-region = <&phahndle2>;
>>>
>>> Well, such setup simply cannot be handled by Linux today, as one
...
>>> I agree that the device tree should be able to describe such
>>> configurations,
...
> Well, if it's just about modifying the binding to support such cases, but 
> without actually adding support for them in Linux, then I guess it's fine. 

Yes. I don't care so much if the SW won't work (yet?), but I want to
make sure the binding isn't going to need semantic changes.
Marek Szyprowski Aug. 20, 2013, 10:57 a.m. UTC | #8
Hello,

On 8/20/2013 12:17 AM, Stephen Warren wrote:
> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
> > Hi Stephen,
> >
> > On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> >> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> >>> This patch adds device tree support for contiguous and reserved memory
> >>> regions defined in device tree.
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/memory.txt
> >>> b/Documentation/devicetree/bindings/memory.txt
> >>>
> >>> +*** Reserved memory regions ***
> >>> +
> >>> +In /memory/reserved-memory node one can create additional nodes
> >>
> >> s/additional/child/ or s/additional/sub/ would make it clearer where the
> >> "additional" nodes should be placed.
> >>
> >>> +compatible:	"linux,contiguous-memory-region" - enables binding
> > of
> >>> this
> >>> +		region to Contiguous Memory Allocator (special region for
> >>> +		contiguous memory allocations, shared with movable system
> >>> +		memory, Linux kernel-specific), alternatively if
> >>> +		"reserved-memory-region" - compatibility is defined, given
> >>> +		region is assigned for exclusive usage for by the
> > respective
> >>> +		devices
> >>
> >> "alternatively" makes it sound like the two compatible values are
> >> mutually-exclusive. Perhaps make this a list, like:
> >>
> >> ----------
> >> compatible: One or more of:
> >>
> >> 	- "linux,contiguous-memory-region" - enables binding of this
> >> 	  region to Contiguous Memory Allocator (special region for
> >> 	  contiguous memory allocations, shared with movable system
> >> 	  memory, Linux kernel-specific).
> >> 	- "reserved-memory-region" - compatibility is defined, given
> >> 	  region is assigned for exclusive usage for by the respective
> >> 	  devices.
> >> ----------
> >>
> >> "linux,contiguous-memory-region" is already long enough, but I'd
> >> slightly bikeshed towards "linux,contiguous-memory-allocator-region", or
> >> perhaps "linux,cma-region" since it's not really describing whether the
> >> memory is contiguous (at the level of /memory, each chunk of memory is
> >> contiguous...)
> >
> > I'm not really sure if we need the "linux" prefix for "contiguous-memory-
> > region". The concept of contiguous memory region is rather OS independent
> > and tells us that memory allocated from this region will be contiguous.
> > IMHO any OS is free to implement its own contiguous memory allocation
> > method, without being limited to Linux CMA.
> >
> > Keep in mind that rationale behind those contiguous regions was that there
> > are devices that require buffers contiguous in memory to operate
> > correctly.
> >
> > But this is just nitpicking and I don't really have any strong opinion on
> > this.
> >
> >>> +*** Device node's properties ***
> >>> +
> >>> +Once regions in the /memory/reserved-memory node have been defined,
> >>> they +can be assigned to device nodes to enable respective device
> >>> drivers to +access them. The following properties are defined:
> >>> +
> >>> +memory-region = <&phandle_to_defined_region>;
> >>
> >> I think the naming of that property should more obviously match this
> >> binding and/or compatible value; perhaps cma-region or
> >> contiguous-memory-region?
> >
> > This property is not CMA-specific. Any memory region can be given using
> > the memory-region property and used to allocate buffers for particular
> > device.
>
> OK, that makes sense.
>
> What I'm looking for is some way to make it obvious that when you see a
> "memory-region" property in a node, you go look at the "memory.txt"
> rather than the DT binding for the node where that property appears.
> Right now, it doesn't seem that obvious to me.
>
> I think the real issue here is that my brief reading of memory.txt
> implies that arbitrary device nodes can include the memory-region
> property without the node's own binding having to document it; the
> property name is essentially "forced into" all other bindings.
>
> I think instead, memory.txt should say:
>
> ----------
> ** Device node's properties ***
>
> Once regions in the /memory/reserved-memory node have been defined, they
> may be referenced by other device nodes. Bindings that wish to reference
> memory regions should explicitly document their use of the following
> property:
>
> memory-region = <&phandle_to_defined_region>;
>
> This property indicates that the device driver should use the memory
> region pointed by the given phandle.
> ----------
>
> Also, what if a device needs multiple separate memory regions? Perhaps a
> GPU is forced to allocate displayable surfaces from addresses 0..32M and
> textures/off-screen-render-targets from 256M..384M or something whacky
> like that. In that case, we could either:
>
> a) Adjust memory.txt to allow multiple entries in memory-regions, and
> add an associated memory-region-names property.
>
> or:
>
> b) Adjust memory.txt not to mention any specific property names, but
> simply mention that other DT nodes can refer to define memory regions by
> phandle, and leave it up to individual bindings to define which property
> they use to reference the memory regions, perhaps with memory.txt
> providing a recommendation of memory-region for the simple case, but
> perhaps also allowing a custom case, e.g.:
>
> display-memory-region = <&phandl1e1>;
> texture-memory-region = <&phahndle2>;

Support for multiple regions is something that need to be discussed
separately. In case of Exynos hardware it is also related to iommu bindings
and configuration, because each busmuster on the internal memory bus has
separate iommu controller. Having each busmaster defined as a separate node,
enables to put there the associated memory region and/or iommu controller as
well as dma window properties (in case of limited dma window).

However right now I would like to focus on the simple case (1 device,
1 memory region) and define bindings which can be extended later.
I hope that my current proposal covers this (I will send updated binding
documentation asap) and the initial support for reserved memory can be
merged to -next soon.

Best regards
Stephen Warren Aug. 20, 2013, 4:35 p.m. UTC | #9
On 08/20/2013 04:57 AM, Marek Szyprowski wrote:
> Hello,
> 
> On 8/20/2013 12:17 AM, Stephen Warren wrote:
>> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
>> > Hi Stephen,
>> >
>> > On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
>> >> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
>> >>> This patch adds device tree support for contiguous and reserved
>> memory
>> >>> regions defined in device tree.
>> >>>
>> >>> diff --git a/Documentation/devicetree/bindings/memory.txt
>> >>> b/Documentation/devicetree/bindings/memory.txt
>> >>>
>> >>> +*** Reserved memory regions ***
>> >>> +
>> >>> +In /memory/reserved-memory node one can create additional nodes
>> >>
>> >> s/additional/child/ or s/additional/sub/ would make it clearer
>> where the
>> >> "additional" nodes should be placed.
>> >>
>> >>> +compatible:    "linux,contiguous-memory-region" - enables binding
>> > of
>> >>> this
>> >>> +        region to Contiguous Memory Allocator (special region for
>> >>> +        contiguous memory allocations, shared with movable system
>> >>> +        memory, Linux kernel-specific), alternatively if
>> >>> +        "reserved-memory-region" - compatibility is defined, given
>> >>> +        region is assigned for exclusive usage for by the
>> > respective
>> >>> +        devices
>> >>
>> >> "alternatively" makes it sound like the two compatible values are
>> >> mutually-exclusive. Perhaps make this a list, like:
>> >>
>> >> ----------
>> >> compatible: One or more of:
>> >>
>> >>     - "linux,contiguous-memory-region" - enables binding of this
>> >>       region to Contiguous Memory Allocator (special region for
>> >>       contiguous memory allocations, shared with movable system
>> >>       memory, Linux kernel-specific).
>> >>     - "reserved-memory-region" - compatibility is defined, given
>> >>       region is assigned for exclusive usage for by the respective
>> >>       devices.
>> >> ----------
>> >>
>> >> "linux,contiguous-memory-region" is already long enough, but I'd
>> >> slightly bikeshed towards
>> "linux,contiguous-memory-allocator-region", or
>> >> perhaps "linux,cma-region" since it's not really describing whether
>> the
>> >> memory is contiguous (at the level of /memory, each chunk of memory is
>> >> contiguous...)
>> >
>> > I'm not really sure if we need the "linux" prefix for
>> "contiguous-memory-
>> > region". The concept of contiguous memory region is rather OS
>> independent
>> > and tells us that memory allocated from this region will be contiguous.
>> > IMHO any OS is free to implement its own contiguous memory allocation
>> > method, without being limited to Linux CMA.
>> >
>> > Keep in mind that rationale behind those contiguous regions was that
>> there
>> > are devices that require buffers contiguous in memory to operate
>> > correctly.
>> >
>> > But this is just nitpicking and I don't really have any strong
>> opinion on
>> > this.
>> >
>> >>> +*** Device node's properties ***
>> >>> +
>> >>> +Once regions in the /memory/reserved-memory node have been defined,
>> >>> they +can be assigned to device nodes to enable respective device
>> >>> drivers to +access them. The following properties are defined:
>> >>> +
>> >>> +memory-region = <&phandle_to_defined_region>;
>> >>
>> >> I think the naming of that property should more obviously match this
>> >> binding and/or compatible value; perhaps cma-region or
>> >> contiguous-memory-region?
>> >
>> > This property is not CMA-specific. Any memory region can be given using
>> > the memory-region property and used to allocate buffers for particular
>> > device.
>>
>> OK, that makes sense.
>>
>> What I'm looking for is some way to make it obvious that when you see a
>> "memory-region" property in a node, you go look at the "memory.txt"
>> rather than the DT binding for the node where that property appears.
>> Right now, it doesn't seem that obvious to me.
>>
>> I think the real issue here is that my brief reading of memory.txt
>> implies that arbitrary device nodes can include the memory-region
>> property without the node's own binding having to document it; the
>> property name is essentially "forced into" all other bindings.
>>
>> I think instead, memory.txt should say:
>>
>> ----------
>> ** Device node's properties ***
>>
>> Once regions in the /memory/reserved-memory node have been defined, they
>> may be referenced by other device nodes. Bindings that wish to reference
>> memory regions should explicitly document their use of the following
>> property:
>>
>> memory-region = <&phandle_to_defined_region>;
>>
>> This property indicates that the device driver should use the memory
>> region pointed by the given phandle.
>> ----------
>>
>> Also, what if a device needs multiple separate memory regions? Perhaps a
>> GPU is forced to allocate displayable surfaces from addresses 0..32M and
>> textures/off-screen-render-targets from 256M..384M or something whacky
>> like that. In that case, we could either:
>>
>> a) Adjust memory.txt to allow multiple entries in memory-regions, and
>> add an associated memory-region-names property.
>>
>> or:
>>
>> b) Adjust memory.txt not to mention any specific property names, but
>> simply mention that other DT nodes can refer to define memory regions by
>> phandle, and leave it up to individual bindings to define which property
>> they use to reference the memory regions, perhaps with memory.txt
>> providing a recommendation of memory-region for the simple case, but
>> perhaps also allowing a custom case, e.g.:
>>
>> display-memory-region = <&phandl1e1>;
>> texture-memory-region = <&phahndle2>;
> 
> Support for multiple regions is something that need to be discussed
> separately. In case of Exynos hardware it is also related to iommu bindings
> and configuration, because each busmuster on the internal memory bus has
> separate iommu controller. Having each busmaster defined as a separate
> node,
> enables to put there the associated memory region and/or iommu
> controller as
> well as dma window properties (in case of limited dma window).
> 
> However right now I would like to focus on the simple case (1 device,
> 1 memory region) and define bindings which can be extended later.
> I hope that my current proposal covers this (I will send updated binding
> documentation asap) and the initial support for reserved memory can be
> merged to -next soon.

I don't believe that's a good approach unless you have at least a
partial idea of how the current bindings will be extended to support
multiple memory regions.

Without a clear idea how that will eventually work, you run a real risk
of not being able to extend the bindings in a 100% backwards-compatible
way, and hence wishing to break DT ABI.
Marek Szyprowski Aug. 21, 2013, 2:38 p.m. UTC | #10
Hello,

On 8/20/2013 6:35 PM, Stephen Warren wrote:
> On 08/20/2013 04:57 AM, Marek Szyprowski wrote:
> > Hello,
> >
> > On 8/20/2013 12:17 AM, Stephen Warren wrote:
> >> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
> >> > Hi Stephen,
> >> >
> >> > On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> >> >> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> >> >>> This patch adds device tree support for contiguous and reserved
> >> memory
> >> >>> regions defined in device tree.
> >> >>>
> >> >>> diff --git a/Documentation/devicetree/bindings/memory.txt
> >> >>> b/Documentation/devicetree/bindings/memory.txt
> >> >>>
> >> >>> +*** Reserved memory regions ***
> >> >>> +
> >> >>> +In /memory/reserved-memory node one can create additional nodes
> >> >>
> >> >> s/additional/child/ or s/additional/sub/ would make it clearer
> >> where the
> >> >> "additional" nodes should be placed.
> >> >>
> >> >>> +compatible:    "linux,contiguous-memory-region" - enables binding
> >> > of
> >> >>> this
> >> >>> +        region to Contiguous Memory Allocator (special region for
> >> >>> +        contiguous memory allocations, shared with movable system
> >> >>> +        memory, Linux kernel-specific), alternatively if
> >> >>> +        "reserved-memory-region" - compatibility is defined, given
> >> >>> +        region is assigned for exclusive usage for by the
> >> > respective
> >> >>> +        devices
> >> >>
> >> >> "alternatively" makes it sound like the two compatible values are
> >> >> mutually-exclusive. Perhaps make this a list, like:
> >> >>
> >> >> ----------
> >> >> compatible: One or more of:
> >> >>
> >> >>     - "linux,contiguous-memory-region" - enables binding of this
> >> >>       region to Contiguous Memory Allocator (special region for
> >> >>       contiguous memory allocations, shared with movable system
> >> >>       memory, Linux kernel-specific).
> >> >>     - "reserved-memory-region" - compatibility is defined, given
> >> >>       region is assigned for exclusive usage for by the respective
> >> >>       devices.
> >> >> ----------
> >> >>
> >> >> "linux,contiguous-memory-region" is already long enough, but I'd
> >> >> slightly bikeshed towards
> >> "linux,contiguous-memory-allocator-region", or
> >> >> perhaps "linux,cma-region" since it's not really describing whether
> >> the
> >> >> memory is contiguous (at the level of /memory, each chunk of memory is
> >> >> contiguous...)
> >> >
> >> > I'm not really sure if we need the "linux" prefix for
> >> "contiguous-memory-
> >> > region". The concept of contiguous memory region is rather OS
> >> independent
> >> > and tells us that memory allocated from this region will be contiguous.
> >> > IMHO any OS is free to implement its own contiguous memory allocation
> >> > method, without being limited to Linux CMA.
> >> >
> >> > Keep in mind that rationale behind those contiguous regions was that
> >> there
> >> > are devices that require buffers contiguous in memory to operate
> >> > correctly.
> >> >
> >> > But this is just nitpicking and I don't really have any strong
> >> opinion on
> >> > this.
> >> >
> >> >>> +*** Device node's properties ***
> >> >>> +
> >> >>> +Once regions in the /memory/reserved-memory node have been defined,
> >> >>> they +can be assigned to device nodes to enable respective device
> >> >>> drivers to +access them. The following properties are defined:
> >> >>> +
> >> >>> +memory-region = <&phandle_to_defined_region>;
> >> >>
> >> >> I think the naming of that property should more obviously match this
> >> >> binding and/or compatible value; perhaps cma-region or
> >> >> contiguous-memory-region?
> >> >
> >> > This property is not CMA-specific. Any memory region can be given using
> >> > the memory-region property and used to allocate buffers for particular
> >> > device.
> >>
> >> OK, that makes sense.
> >>
> >> What I'm looking for is some way to make it obvious that when you see a
> >> "memory-region" property in a node, you go look at the "memory.txt"
> >> rather than the DT binding for the node where that property appears.
> >> Right now, it doesn't seem that obvious to me.
> >>
> >> I think the real issue here is that my brief reading of memory.txt
> >> implies that arbitrary device nodes can include the memory-region
> >> property without the node's own binding having to document it; the
> >> property name is essentially "forced into" all other bindings.
> >>
> >> I think instead, memory.txt should say:
> >>
> >> ----------
> >> ** Device node's properties ***
> >>
> >> Once regions in the /memory/reserved-memory node have been defined, they
> >> may be referenced by other device nodes. Bindings that wish to reference
> >> memory regions should explicitly document their use of the following
> >> property:
> >>
> >> memory-region = <&phandle_to_defined_region>;
> >>
> >> This property indicates that the device driver should use the memory
> >> region pointed by the given phandle.
> >> ----------
> >>
> >> Also, what if a device needs multiple separate memory regions? Perhaps a
> >> GPU is forced to allocate displayable surfaces from addresses 0..32M and
> >> textures/off-screen-render-targets from 256M..384M or something whacky
> >> like that. In that case, we could either:
> >>
> >> a) Adjust memory.txt to allow multiple entries in memory-regions, and
> >> add an associated memory-region-names property.
> >>
> >> or:
> >>
> >> b) Adjust memory.txt not to mention any specific property names, but
> >> simply mention that other DT nodes can refer to define memory regions by
> >> phandle, and leave it up to individual bindings to define which property
> >> they use to reference the memory regions, perhaps with memory.txt
> >> providing a recommendation of memory-region for the simple case, but
> >> perhaps also allowing a custom case, e.g.:
> >>
> >> display-memory-region = <&phandl1e1>;
> >> texture-memory-region = <&phahndle2>;
> >
> > Support for multiple regions is something that need to be discussed
> > separately. In case of Exynos hardware it is also related to iommu bindings
> > and configuration, because each busmuster on the internal memory bus has
> > separate iommu controller. Having each busmaster defined as a separate
> > node,
> > enables to put there the associated memory region and/or iommu
> > controller as
> > well as dma window properties (in case of limited dma window).
> >
> > However right now I would like to focus on the simple case (1 device,
> > 1 memory region) and define bindings which can be extended later.
> > I hope that my current proposal covers this (I will send updated binding
> > documentation asap) and the initial support for reserved memory can be
> > merged to -next soon.
>
> I don't believe that's a good approach unless you have at least a
> partial idea of how the current bindings will be extended to support
> multiple memory regions.
>
> Without a clear idea how that will eventually work, you run a real risk
> of not being able to extend the bindings in a 100% backwards-compatible
> way, and hence wishing to break DT ABI.

Both already proposed approaches for extending them to support multiple
memory regions are compatible with the 'single memory region' approach
defined in my patches. Adding additional property with region names is
probably the simplest way from binding perspective, while adding additional
child nodes for each bus master or memory interface gives much more
flexibility in describing hardware properties. Besides memory region, one
can assign iommu controller or dma window properties to each such node.

Best regards
Tomasz Figa Aug. 21, 2013, 3:39 p.m. UTC | #11
On Tuesday 20 of August 2013 10:35:51 Stephen Warren wrote:
> On 08/20/2013 04:57 AM, Marek Szyprowski wrote:
> > Hello,
> > 
> > On 8/20/2013 12:17 AM, Stephen Warren wrote:
> >> On 08/19/2013 04:02 PM, Tomasz Figa wrote:
> >> > Hi Stephen,
> >> > 
> >> > On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> >> >> On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> >> >>> This patch adds device tree support for contiguous and reserved
> >> 
> >> memory
> >> 
> >> >>> regions defined in device tree.
> >> >>> 
> >> >>> diff --git a/Documentation/devicetree/bindings/memory.txt
> >> >>> b/Documentation/devicetree/bindings/memory.txt
> >> >>> 
> >> >>> +*** Reserved memory regions ***
> >> >>> +
> >> >>> +In /memory/reserved-memory node one can create additional nodes
> >> >> 
> >> >> s/additional/child/ or s/additional/sub/ would make it clearer
> >> 
> >> where the
> >> 
> >> >> "additional" nodes should be placed.
> >> >> 
> >> >>> +compatible:    "linux,contiguous-memory-region" - enables binding
> >> > 
> >> > of
> >> > 
> >> >>> this
> >> >>> +        region to Contiguous Memory Allocator (special region for
> >> >>> +        contiguous memory allocations, shared with movable system
> >> >>> +        memory, Linux kernel-specific), alternatively if
> >> >>> +        "reserved-memory-region" - compatibility is defined,
> >> >>> given
> >> >>> +        region is assigned for exclusive usage for by the
> >> > 
> >> > respective
> >> > 
> >> >>> +        devices
> >> >> 
> >> >> "alternatively" makes it sound like the two compatible values are
> >> >> mutually-exclusive. Perhaps make this a list, like:
> >> >> 
> >> >> ----------
> >> >> 
> >> >> compatible: One or more of:
> >> >>     - "linux,contiguous-memory-region" - enables binding of this
> >> >>     
> >> >>       region to Contiguous Memory Allocator (special region for
> >> >>       contiguous memory allocations, shared with movable system
> >> >>       memory, Linux kernel-specific).
> >> >>     
> >> >>     - "reserved-memory-region" - compatibility is defined, given
> >> >>     
> >> >>       region is assigned for exclusive usage for by the respective
> >> >>       devices.
> >> >> 
> >> >> ----------
> >> >> 
> >> >> "linux,contiguous-memory-region" is already long enough, but I'd
> >> >> slightly bikeshed towards
> >> 
> >> "linux,contiguous-memory-allocator-region", or
> >> 
> >> >> perhaps "linux,cma-region" since it's not really describing whether
> >> 
> >> the
> >> 
> >> >> memory is contiguous (at the level of /memory, each chunk of memory
> >> >> is
> >> >> contiguous...)
> >> > 
> >> > I'm not really sure if we need the "linux" prefix for
> >> 
> >> "contiguous-memory-
> >> 
> >> > region". The concept of contiguous memory region is rather OS
> >> 
> >> independent
> >> 
> >> > and tells us that memory allocated from this region will be
> >> > contiguous.
> >> > IMHO any OS is free to implement its own contiguous memory
> >> > allocation
> >> > method, without being limited to Linux CMA.
> >> > 
> >> > Keep in mind that rationale behind those contiguous regions was that
> >> 
> >> there
> >> 
> >> > are devices that require buffers contiguous in memory to operate
> >> > correctly.
> >> > 
> >> > But this is just nitpicking and I don't really have any strong
> >> 
> >> opinion on
> >> 
> >> > this.
> >> > 
> >> >>> +*** Device node's properties ***
> >> >>> +
> >> >>> +Once regions in the /memory/reserved-memory node have been
> >> >>> defined,
> >> >>> they +can be assigned to device nodes to enable respective device
> >> >>> drivers to +access them. The following properties are defined:
> >> >>> +
> >> >>> +memory-region = <&phandle_to_defined_region>;
> >> >> 
> >> >> I think the naming of that property should more obviously match
> >> >> this
> >> >> binding and/or compatible value; perhaps cma-region or
> >> >> contiguous-memory-region?
> >> > 
> >> > This property is not CMA-specific. Any memory region can be given
> >> > using
> >> > the memory-region property and used to allocate buffers for
> >> > particular
> >> > device.
> >> 
> >> OK, that makes sense.
> >> 
> >> What I'm looking for is some way to make it obvious that when you see
> >> a
> >> "memory-region" property in a node, you go look at the "memory.txt"
> >> rather than the DT binding for the node where that property appears.
> >> Right now, it doesn't seem that obvious to me.
> >> 
> >> I think the real issue here is that my brief reading of memory.txt
> >> implies that arbitrary device nodes can include the memory-region
> >> property without the node's own binding having to document it; the
> >> property name is essentially "forced into" all other bindings.
> >> 
> >> I think instead, memory.txt should say:
> >> 
> >> ----------
> >> ** Device node's properties ***
> >> 
> >> Once regions in the /memory/reserved-memory node have been defined,
> >> they
> >> may be referenced by other device nodes. Bindings that wish to
> >> reference
> >> memory regions should explicitly document their use of the following
> >> property:
> >> 
> >> memory-region = <&phandle_to_defined_region>;
> >> 
> >> This property indicates that the device driver should use the memory
> >> region pointed by the given phandle.
> >> ----------
> >> 
> >> Also, what if a device needs multiple separate memory regions? Perhaps
> >> a
> >> GPU is forced to allocate displayable surfaces from addresses 0..32M
> >> and
> >> textures/off-screen-render-targets from 256M..384M or something whacky
> >> like that. In that case, we could either:
> >> 
> >> a) Adjust memory.txt to allow multiple entries in memory-regions, and
> >> add an associated memory-region-names property.
> >> 
> >> or:
> >> 
> >> b) Adjust memory.txt not to mention any specific property names, but
> >> simply mention that other DT nodes can refer to define memory regions
> >> by
> >> phandle, and leave it up to individual bindings to define which
> >> property
> >> they use to reference the memory regions, perhaps with memory.txt
> >> providing a recommendation of memory-region for the simple case, but
> >> perhaps also allowing a custom case, e.g.:
> >> 
> >> display-memory-region = <&phandl1e1>;
> >> texture-memory-region = <&phahndle2>;
> > 
> > Support for multiple regions is something that need to be discussed
> > separately. In case of Exynos hardware it is also related to iommu
> > bindings and configuration, because each busmuster on the internal
> > memory bus has separate iommu controller. Having each busmaster
> > defined as a separate node,
> > enables to put there the associated memory region and/or iommu
> > controller as
> > well as dma window properties (in case of limited dma window).
> > 
> > However right now I would like to focus on the simple case (1 device,
> > 1 memory region) and define bindings which can be extended later.
> > I hope that my current proposal covers this (I will send updated
> > binding
> > documentation asap) and the initial support for reserved memory can be
> > merged to -next soon.
> 
> I don't believe that's a good approach unless you have at least a
> partial idea of how the current bindings will be extended to support
> multiple memory regions.

I believe that at least three "at least partial" ideas have been brought in 
this thread. Moreover, I don't think that defining the simple binding now 
would stop us from extending it according to any of those ideas in any way.

> Without a clear idea how that will eventually work, you run a real risk
> of not being able to extend the bindings in a 100% backwards-compatible
> way, and hence wishing to break DT ABI.

As a fallback you can always define a new binding, while keeping support 
for old one. Of course this is the last resort, but it is not that simple 
to find a case that couldn't be supported without breaking the ABI.

Best regards,
Tomasz
Matt Sealey Aug. 21, 2013, 3:56 p.m. UTC | #12
I have a suggestion here.

I recall that CHRP had a reserved node definition which essentially,
since it was not a lot more than a definition of the bare minimum node
that can describe a memory region, acted as a way to carve out
peripheral addresses. In this case, the device_type would be
"reserved" and a property to mark it as for the Linux contiguous
memory allocator would be prudent here. This way nothing new is being
defined except the property. In the case you want default regions and
supplemental regions, give the linux,contiguous-memory-region property
a value. In the case of the reserved node, the name could be "default"
though and CMA could special-case this.

It doesn't even need to be called reserved-memory or be a child node
of it's own, then, but I also guess this would mean duplicating
#address-cells and #size-cells in every node (that said.. isn't there
a case for a 32-bit system having a >32-bit memory map somewhere that
the kernel somehow needs to know about? On PowerPC I've seen 8GB
hooked up to it on CPUs that didn't have 36-bit addressing, and
therefore could not do anything with that amount of memory. But the
DMA controllers in this case were designed around 36-bit addressing
and could easily access the upper 4GB.. it would have come in handy
for a kind of DMA-assisted buffering whereby you wanted to put all
your network or "graphics" stuff in a safe place and copy it in and
out as needed, or even as 4GB of magical swap space driven by a custom
DMA driver)

The naming of nodes is not really "important" in device-tree, in this
case it might make sense in the same way the regulator guys specify
regulators. In any case where the "default" name does not exist, then
the first parsed becomes the default, but this does mean we'd be kind
of restricting the namespace for everyone based on a Linux kernel
behavior..

If you can search for the device_type = "memory" node you can also
search for all nodes matching device_type = "reserved" under the
memory node, with the appropriate property in place to bundle them up
for adding to CMA, and just carve it out. In fact, this would work
without needing to be in the /memory node at all. Hooray for
device_type, long live device_type? :D

-- Matt

On Mon, Aug 19, 2013 at 10:04 AM, Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
> This patch adds device tree support for contiguous and reserved memory
> regions defined in device tree.
>
> Large memory blocks can be reliably reserved only during early boot.
> This must happen before the whole memory management subsystem is
> initialized, because we need to ensure that the given contiguous blocks
> are not yet allocated by kernel. Also it must happen before kernel
> mappings for the whole low memory are created, to ensure that there will
> be no mappings (for reserved blocks) or mapping with special properties
> can be created (for CMA blocks). This all happens before device tree
> structures are unflattened, so we need to get reserved memory layout
> directly from fdt.
>
> Later, those reserved memory regions are assigned to devices on each
> device structure initialization.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> Acked-by: Michal Nazarewicz <mina86@mina86.com>
> Acked-by: Tomasz Figa <t.figa@samsung.com>
> ---
>  Documentation/devicetree/bindings/memory.txt |  166 ++++++++++++++++++++++++
>  drivers/of/Kconfig                           |    6 +
>  drivers/of/Makefile                          |    1 +
>  drivers/of/of_reserved_mem.c                 |  175 ++++++++++++++++++++++++++
>  drivers/of/platform.c                        |    5 +
>  include/linux/of_reserved_mem.h              |   14 +++
>  6 files changed, 367 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory.txt
>  create mode 100644 drivers/of/of_reserved_mem.c
>  create mode 100644 include/linux/of_reserved_mem.h
>
> diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt
> new file mode 100644
> index 0000000..90e96278
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/memory.txt
> @@ -0,0 +1,166 @@
> +*** Memory binding ***
> +
> +The /memory node provides basic information about the address and size
> +of the physical memory. This node is usually filled or updated by the
> +bootloader, depending on the actual memory configuration of the given
> +hardware.
> +
> +The memory layout is described by the following node:
> +
> +/ {
> +       #address-cells = <(n)>;
> +       #size-cells = <(m)>;
> +       memory {
> +               device_type = "memory";
> +               reg =  <(baseaddr1) (size1)
> +                       (baseaddr2) (size2)
> +                       ...
> +                       (baseaddrN) (sizeN)>;
> +       };
> +       ...
> +};
> +
> +A memory node follows the typical device tree rules for "reg" property:
> +n:             number of cells used to store base address value
> +m:             number of cells used to store size value
> +baseaddrX:     defines a base address of the defined memory bank
> +sizeX:         the size of the defined memory bank
> +
> +
> +More than one memory bank can be defined.
> +
> +
> +*** Reserved memory regions ***
> +
> +In /memory/reserved-memory node one can create additional nodes
> +describing particular reserved (excluded from normal use) memory
> +regions. Such memory regions are usually designed for the special usage
> +by various device drivers. A good example are contiguous memory
> +allocations or memory sharing with other operating system on the same
> +hardware board. Those special memory regions might depend on the board
> +configuration and devices used on the target system.
> +
> +Parameters for each memory region can be encoded into the device tree
> +with the following convention:
> +
> +[(label):] (name) {
> +       compatible = "linux,contiguous-memory-region", "reserved-memory-region";
> +       reg = <(address) (size)>;
> +       (linux,default-contiguous-region);
> +};
> +
> +compatible:    "linux,contiguous-memory-region" - enables binding of this
> +               region to Contiguous Memory Allocator (special region for
> +               contiguous memory allocations, shared with movable system
> +               memory, Linux kernel-specific), alternatively if
> +               "reserved-memory-region" - compatibility is defined, given
> +               region is assigned for exclusive usage for by the respective
> +               devices
> +
> +reg:           standard property defining the base address and size of
> +               the memory region
> +
> +linux,default-contiguous-region: property indicating that the region
> +               is the default region for all contiguous memory
> +               allocations, Linux specific (optional)
> +
> +It is optional to specify the base address, so if one wants to use
> +autoconfiguration of the base address, '0' can be specified as a base
> +address in the 'reg' property.
> +
> +The /memory/reserved-memory node must contain the same #address-cells
> +and #size-cells value as the root node.
> +
> +
> +*** Device node's properties ***
> +
> +Once regions in the /memory/reserved-memory node have been defined, they
> +can be assigned to device nodes to enable respective device drivers to
> +access them. The following properties are defined:
> +
> +memory-region = <&phandle_to_defined_region>;
> +
> +This property indicates that the device driver should use the memory
> +region pointed by the given phandle.
> +
> +
> +*** Example ***
> +
> +This example defines a memory consisting of 4 memory banks. 3 contiguous
> +regions are defined for Linux kernel, one default of all device drivers
> +(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
> +framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
> +and one for multimedia processing (labelled multimedia_mem, placed at
> +0x77000000, 64MiB). 'display_mem' region is then assigned to fb@12300000
> +device for DMA memory allocations (Linux kernel drivers will use CMA is
> +available or dma-exclusive usage otherwise). 'multimedia_mem' is
> +assigned to scaler@12500000 and codec@12600000 devices for contiguous
> +memory allocations when CMA driver is enabled.
> +
> +The reason for creating a separate region for framebuffer device is to
> +match the framebuffer base address to the one configured by bootloader,
> +so once Linux kernel drivers starts no glitches on the displayed boot
> +logo appears. Scaller and codec drivers should share the memory
> +allocations.
> +
> +/ {
> +       #address-cells = <1>;
> +       #size-cells = <1>;
> +
> +       /* ... */
> +
> +       memory {
> +               reg =  <0x40000000 0x10000000
> +                       0x50000000 0x10000000
> +                       0x60000000 0x10000000
> +                       0x70000000 0x10000000>;
> +
> +               reserved-memory {
> +                       #address-cells = <1>;
> +                       #size-cells = <1>;
> +
> +                       /*
> +                        * global autoconfigured region for contiguous allocations
> +                        * (used only with Contiguous Memory Allocator)
> +                        */
> +                       contig_region@0 {
> +                               compatible = "linux,contiguous-memory-region";
> +                               reg = <0x0 0x4000000>;
> +                               linux,default-contiguous-region;
> +                       };
> +
> +                       /*
> +                        * special region for framebuffer
> +                        */
> +                       display_mem: region@78000000 {
> +                               compatible = "linux,contiguous-memory-region", "reserved-memory-region";
> +                               reg = <0x78000000 0x800000>;
> +                       };
> +
> +                       /*
> +                        * special region for multimedia processing devices
> +                        */
> +                       multimedia_mem: region@77000000 {
> +                               compatible = "linux,contiguous-memory-region";
> +                               reg = <0x77000000 0x4000000>;
> +                       };
> +               };
> +       };
> +
> +       /* ... */
> +
> +       fb0: fb@12300000 {
> +               status = "okay";
> +               memory-region = <&display_mem>;
> +       };
> +
> +       scaler: scaler@12500000 {
> +               status = "okay";
> +               memory-region = <&multimedia_mem>;
> +       };
> +
> +       codec: codec@12600000 {
> +               status = "okay";
> +               memory-region = <&multimedia_mem>;
> +       };
> +};
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index 80e5c13..a83ab43 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -80,4 +80,10 @@ config OF_MTD
>         depends on MTD
>         def_bool y
>
> +config OF_RESERVED_MEM
> +       depends on CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK)
> +       def_bool y
> +       help
> +         Initialization code for DMA reserved memory
> +
>  endmenu # OF
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 1f9c0c4..e7e3322 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o
>  obj-$(CONFIG_OF_PCI)   += of_pci.o
>  obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
>  obj-$(CONFIG_OF_MTD)   += of_mtd.o
> +obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
> diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
> new file mode 100644
> index 0000000..95563d33
> --- /dev/null
> +++ b/drivers/of/of_reserved_mem.c
> @@ -0,0 +1,175 @@
> +/*
> + * Device tree based initialization code for reserved memory.
> + *
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + *             http://www.samsung.com
> + * Author: Marek Szyprowski <m.szyprowski@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License or (at your optional) any later version of the license.
> + */
> +
> +#include <asm/dma-contiguous.h>
> +
> +#include <linux/memblock.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_platform.h>
> +#include <linux/mm.h>
> +#include <linux/sizes.h>
> +#include <linux/mm_types.h>
> +#include <linux/dma-contiguous.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/of_reserved_mem.h>
> +
> +#define MAX_RESERVED_REGIONS   16
> +struct reserved_mem {
> +       phys_addr_t             base;
> +       unsigned long           size;
> +       struct cma              *cma;
> +       char                    name[32];
> +};
> +static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
> +static int reserved_mem_count;
> +
> +static int __init fdt_scan_reserved_mem(unsigned long node, const char *uname,
> +                                       int depth, void *data)
> +{
> +       struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
> +       phys_addr_t base, size;
> +       int is_cma, is_reserved;
> +       unsigned long len;
> +       const char *status;
> +       __be32 *prop;
> +
> +       is_cma = IS_ENABLED(CONFIG_CMA) &&
> +              of_flat_dt_is_compatible(node, "linux,contiguous-memory-region");
> +       is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
> +
> +       if (!is_reserved && !is_cma) {
> +               /* ignore node and scan next one */
> +               return 0;
> +       }
> +
> +       status = of_get_flat_dt_prop(node, "status", &len);
> +       if (status && strcmp(status, "okay") != 0) {
> +               /* ignore disabled node nad scan next one */
> +               return 0;
> +       }
> +
> +       prop = of_get_flat_dt_prop(node, "reg", &len);
> +       if (!prop || (len < (dt_root_size_cells + dt_root_addr_cells) *
> +                            sizeof(__be32))) {
> +               pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
> +                      uname);
> +               /* ignore node and scan next one */
> +               return 0;
> +       }
> +       base = dt_mem_next_cell(dt_root_addr_cells, &prop);
> +       size = dt_mem_next_cell(dt_root_size_cells, &prop);
> +
> +       if (!size) {
> +               /* ignore node and scan next one */
> +               return 0;
> +       }
> +
> +       pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
> +               uname, (unsigned long)base, (unsigned long)size / SZ_1M);
> +
> +       if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
> +               return -ENOSPC;
> +
> +       rmem->base = base;
> +       rmem->size = size;
> +       strlcpy(rmem->name, uname, sizeof(rmem->name));
> +
> +       if (is_cma) {
> +               struct cma *cma;
> +               if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
> +                       rmem->cma = cma;
> +                       reserved_mem_count++;
> +                       if (of_get_flat_dt_prop(node,
> +                                               "linux,default-contiguous-region",
> +                                               NULL))
> +                               dma_contiguous_default_area = cma;
> +               }
> +       } else if (is_reserved) {
> +               if (memblock_remove(base, size) == 0)
> +                       reserved_mem_count++;
> +               else
> +                       pr_err("Failed to reserve memory for %s\n", uname);
> +       }
> +
> +       return 0;
> +}
> +
> +static struct reserved_mem *get_dma_memory_region(struct device *dev)
> +{
> +       struct device_node *node;
> +       const char *name;
> +       int i;
> +
> +       node = of_parse_phandle(dev->of_node, "memory-region", 0);
> +       if (!node)
> +               return NULL;
> +
> +       name = kbasename(node->full_name);
> +       for (i = 0; i < reserved_mem_count; i++)
> +               if (strcmp(name, reserved_mem[i].name) == 0)
> +                       return &reserved_mem[i];
> +       return NULL;
> +}
> +
> +/**
> + * of_reserved_mem_device_init() - assign reserved memory region to given device
> + *
> + * This function assign memory region pointed by "memory-region" device tree
> + * property to the given device.
> + */
> +void of_reserved_mem_device_init(struct device *dev)
> +{
> +       struct reserved_mem *region = get_dma_memory_region(dev);
> +       if (!region)
> +               return;
> +
> +       if (region->cma) {
> +               dev_set_cma_area(dev, region->cma);
> +               pr_info("Assigned CMA %s to %s device\n", region->name,
> +                       dev_name(dev));
> +       } else {
> +               if (dma_declare_coherent_memory(dev, region->base, region->base,
> +                   region->size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) != 0)
> +                       pr_info("Declared reserved memory %s to %s device\n",
> +                               region->name, dev_name(dev));
> +       }
> +}
> +
> +/**
> + * of_reserved_mem_device_release() - release reserved memory device structures
> + *
> + * This function releases structures allocated for memory region handling for
> + * the given device.
> + */
> +void of_reserved_mem_device_release(struct device *dev)
> +{
> +       struct reserved_mem *region = get_dma_memory_region(dev);
> +       if (!region && !region->cma)
> +               dma_release_declared_memory(dev);
> +}
> +
> +/**
> + * early_init_dt_scan_reserved_mem() - create reserved memory regions
> + *
> + * This function grabs memory from early allocator for device exclusive use
> + * defined in device tree structures. It should be called by arch specific code
> + * once the early allocator (memblock) has been activated and all other
> + * subsystems have already allocated/reserved memory.
> + */
> +void __init early_init_dt_scan_reserved_mem(void)
> +{
> +       of_scan_flat_dt_by_path("/memory/reserved-memory",
> +                               fdt_scan_reserved_mem, NULL);
> +}
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index e0a6514..1e4e91d 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -21,6 +21,7 @@
>  #include <linux/of_device.h>
>  #include <linux/of_irq.h>
>  #include <linux/of_platform.h>
> +#include <linux/of_reserved_mem.h>
>  #include <linux/platform_device.h>
>
>  const struct of_device_id of_default_bus_match_table[] = {
> @@ -196,6 +197,7 @@ EXPORT_SYMBOL(of_device_alloc);
>   * Returns pointer to created platform device, or NULL if a device was not
>   * registered.  Unavailable devices will not get registered.
>   */
> +
>  struct platform_device *of_platform_device_create_pdata(
>                                         struct device_node *np,
>                                         const char *bus_id,
> @@ -218,6 +220,8 @@ struct platform_device *of_platform_device_create_pdata(
>         dev->dev.bus = &platform_bus_type;
>         dev->dev.platform_data = platform_data;
>
> +       of_reserved_mem_device_init(&dev->dev);
> +
>         /* We do not fill the DMA ops for platform devices by default.
>          * This is currently the responsibility of the platform code
>          * to do such, possibly using a device notifier
> @@ -225,6 +229,7 @@ struct platform_device *of_platform_device_create_pdata(
>
>         if (of_device_add(dev) != 0) {
>                 platform_device_put(dev);
> +               of_reserved_mem_device_release(&dev->dev);
>                 return NULL;
>         }
>
> diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
> new file mode 100644
> index 0000000..c841282
> --- /dev/null
> +++ b/include/linux/of_reserved_mem.h
> @@ -0,0 +1,14 @@
> +#ifndef __OF_RESERVED_MEM_H
> +#define __OF_RESERVED_MEM_H
> +
> +#ifdef CONFIG_OF_RESERVED_MEM
> +void of_reserved_mem_device_init(struct device *dev);
> +void of_reserved_mem_device_release(struct device *dev);
> +void early_init_dt_scan_reserved_mem(void);
> +#else
> +static inline void of_reserved_mem_device_init(struct device *dev) { }
> +static inline void of_reserved_mem_device_release(struct device *dev) { }
> +static inline void early_init_dt_scan_reserved_mem(void) { }
> +#endif
> +
> +#endif /* __OF_RESERVED_MEM_H */
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Stephen Warren Aug. 22, 2013, 8:08 p.m. UTC | #13
On 08/21/2013 08:38 AM, Marek Szyprowski wrote:
...
>> >> b) Adjust memory.txt not to mention any specific property names, but
>> >> simply mention that other DT nodes can refer to define memory regions by
>> >> phandle, and leave it up to individual bindings to define which property
>> >> they use to reference the memory regions, perhaps with memory.txt
>> >> providing a recommendation of memory-region for the simple case

I think if we just make that change to the binding doc, it'll be fine.
It's obvious how to extend the binding then.
Stephen Warren Aug. 23, 2013, 7:27 p.m. UTC | #14
On 08/23/2013 02:39 AM,  wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> This patch adds device tree support for contiguous and reserved memory
> regions defined in device tree.
> 
> Large memory blocks can be reliably reserved only during early boot.
> This must happen before the whole memory management subsystem is
> initialized, because we need to ensure that the given contiguous blocks
> are not yet allocated by kernel. Also it must happen before kernel
> mappings for the whole low memory are created, to ensure that there will
> be no mappings (for reserved blocks) or mapping with special properties
> can be created (for CMA blocks). This all happens before device tree
> structures are unflattened, so we need to get reserved memory layout
> directly from fdt.
> 
> Later, those reserved memory regions are assigned to devices on each
> device structure initialization.

I think the binding looks OK now; just a couple minor comments below.

> diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt

> +*** Reserved memory regions ***

> +compatible:	one or more of:
> +	- "linux,contiguous-memory-region" - enables binding of this
> +	  region to Contiguous Memory Allocator (special region for
> +	  contiguous memory allocations, shared with movable system
> +	  memory, Linux kernel-specific).
> +	- "reserved-memory-region" - compatibility is defined, given
> +	  region is assigned for exclusive usage for by the respective
> +	  devices.

I'm slightly hesitant to agree with "linux" in the name here, since it
seems like the concept of a memory region where DMA buffers/... should
be allocated is pretty OS-independant. Similar for:

> +linux,default-contiguous-region: property indicating that the region
> +	is the default region for all contiguous memory
> +	allocations, Linux specific (optional)

But, I guess there's nothing stopping any other OS from parsing this
same property, so I suppose it's OK. What do other DT maintainers think?

> +*** Example ***

> +		reserved-memory {
...
> +			contig_region@0 {
...
> +			display_mem: region@78000000 {
...
> +			multimedia_mem: region@77000000 {

Nit: I think all 3 of those nodes should be called region, but it's
probably fine as-is.

So, the binding,
Acked-by: Stephen Warren <swarren@nvidia.com>
Rob Herring Aug. 26, 2013, 12:20 p.m. UTC | #15
On Mon, Aug 19, 2013 at 10:04 AM, Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
> This patch adds device tree support for contiguous and reserved memory
> regions defined in device tree.
>
> Large memory blocks can be reliably reserved only during early boot.
> This must happen before the whole memory management subsystem is
> initialized, because we need to ensure that the given contiguous blocks
> are not yet allocated by kernel. Also it must happen before kernel
> mappings for the whole low memory are created, to ensure that there will
> be no mappings (for reserved blocks) or mapping with special properties
> can be created (for CMA blocks). This all happens before device tree
> structures are unflattened, so we need to get reserved memory layout
> directly from fdt.
>
> Later, those reserved memory regions are assigned to devices on each
> device structure initialization.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> Acked-by: Michal Nazarewicz <mina86@mina86.com>
> Acked-by: Tomasz Figa <t.figa@samsung.com>

Reviewed-by: Rob Herring <rob.herring@calxeda.com>
Grant Likely Aug. 29, 2013, 9:12 p.m. UTC | #16
On Tue, 20 Aug 2013 00:02:37 +0200, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Stephen,
> 
> On Monday 19 of August 2013 15:49:20 Stephen Warren wrote:
> > On 08/19/2013 09:04 AM, Marek Szyprowski wrote:
> > > This patch adds device tree support for contiguous and reserved memory
> > > regions defined in device tree.
> > > 
> > > diff --git a/Documentation/devicetree/bindings/memory.txt
> > > b/Documentation/devicetree/bindings/memory.txt
> > > 
> > > +*** Reserved memory regions ***
> > > +
> > > +In /memory/reserved-memory node one can create additional nodes
> > 
> > s/additional/child/ or s/additional/sub/ would make it clearer where the
> > "additional" nodes should be placed.
> > 
> > > +compatible:	"linux,contiguous-memory-region" - enables binding 
> of
> > > this
> > > +		region to Contiguous Memory Allocator (special region for
> > > +		contiguous memory allocations, shared with movable system
> > > +		memory, Linux kernel-specific), alternatively if
> > > +		"reserved-memory-region" - compatibility is defined, given
> > > +		region is assigned for exclusive usage for by the 
> respective
> > > +		devices
> > 
> > "alternatively" makes it sound like the two compatible values are
> > mutually-exclusive. Perhaps make this a list, like:
> > 
> > ----------
> > compatible: One or more of:
> > 
> > 	- "linux,contiguous-memory-region" - enables binding of this
> > 	  region to Contiguous Memory Allocator (special region for
> > 	  contiguous memory allocations, shared with movable system
> > 	  memory, Linux kernel-specific).
> > 	- "reserved-memory-region" - compatibility is defined, given
> > 	  region is assigned for exclusive usage for by the respective
> > 	  devices.
> > ----------
> > 
> > "linux,contiguous-memory-region" is already long enough, but I'd
> > slightly bikeshed towards "linux,contiguous-memory-allocator-region", or
> > perhaps "linux,cma-region" since it's not really describing whether the
> > memory is contiguous (at the level of /memory, each chunk of memory is
> > contiguous...)
> 
> I'm not really sure if we need the "linux" prefix for "contiguous-memory-
> region". The concept of contiguous memory region is rather OS independent 
> and tells us that memory allocated from this region will be contiguous. 
> IMHO any OS is free to implement its own contiguous memory allocation 
> method, without being limited to Linux CMA.
> 
> Keep in mind that rationale behind those contiguous regions was that there 
> are devices that require buffers contiguous in memory to operate 
> correctly.
> 
> But this is just nitpicking and I don't really have any strong opinion on 
> this.

Actually, I think this is important. It is something that describes the
expected usage of the hardware (flicker-free framebuffer is a really
good example) and isn't really linux-specific from that perspective.
I think you can drop the 'linux,' prefix string.

g.
Grant Likely Aug. 29, 2013, 9:20 p.m. UTC | #17
On Wed, 21 Aug 2013 17:39:48 +0200, Tomasz Figa <t.figa@samsung.com> wrote:
> On Tuesday 20 of August 2013 10:35:51 Stephen Warren wrote:
> > >> a) Adjust memory.txt to allow multiple entries in memory-regions, and
> > >> add an associated memory-region-names property.
> > >> 
> > I don't believe that's a good approach unless you have at least a
> > partial idea of how the current bindings will be extended to support
> > multiple memory regions.
> 
> I believe that at least three "at least partial" ideas have been brought in 
> this thread. Moreover, I don't think that defining the simple binding now 
> would stop us from extending it according to any of those ideas in any way.

I would plan on extending later with suggestion 'a)' above. Making the
memory-region an array of phandles is a better match with how most of
the core bindings work.  I actually regret the *-gpio properties that
were defined earlier becasue it makes it harder for software to look at
a tree and determine if there are any gpio references.

It of course doesn't need to be done immediately, only when it becomes
required.

g.
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt
new file mode 100644
index 0000000..90e96278
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory.txt
@@ -0,0 +1,166 @@ 
+*** Memory binding ***
+
+The /memory node provides basic information about the address and size
+of the physical memory. This node is usually filled or updated by the
+bootloader, depending on the actual memory configuration of the given
+hardware.
+
+The memory layout is described by the following node:
+
+/ {
+	#address-cells = <(n)>;
+	#size-cells = <(m)>;
+	memory {
+		device_type = "memory";
+		reg =  <(baseaddr1) (size1)
+			(baseaddr2) (size2)
+			...
+			(baseaddrN) (sizeN)>;
+	};
+	...
+};
+
+A memory node follows the typical device tree rules for "reg" property:
+n:		number of cells used to store base address value
+m:		number of cells used to store size value
+baseaddrX:	defines a base address of the defined memory bank
+sizeX:		the size of the defined memory bank
+
+
+More than one memory bank can be defined.
+
+
+*** Reserved memory regions ***
+
+In /memory/reserved-memory node one can create additional nodes
+describing particular reserved (excluded from normal use) memory
+regions. Such memory regions are usually designed for the special usage
+by various device drivers. A good example are contiguous memory
+allocations or memory sharing with other operating system on the same
+hardware board. Those special memory regions might depend on the board
+configuration and devices used on the target system.
+
+Parameters for each memory region can be encoded into the device tree
+with the following convention:
+
+[(label):] (name) {
+	compatible = "linux,contiguous-memory-region", "reserved-memory-region";
+	reg = <(address) (size)>;
+	(linux,default-contiguous-region);
+};
+
+compatible:	"linux,contiguous-memory-region" - enables binding of this
+		region to Contiguous Memory Allocator (special region for
+		contiguous memory allocations, shared with movable system
+		memory, Linux kernel-specific), alternatively if
+		"reserved-memory-region" - compatibility is defined, given
+		region is assigned for exclusive usage for by the respective
+		devices
+
+reg:		standard property defining the base address and size of
+		the memory region
+
+linux,default-contiguous-region: property indicating that the region
+		is the default region for all contiguous memory
+		allocations, Linux specific (optional)
+
+It is optional to specify the base address, so if one wants to use
+autoconfiguration of the base address, '0' can be specified as a base
+address in the 'reg' property.
+
+The /memory/reserved-memory node must contain the same #address-cells
+and #size-cells value as the root node.
+
+
+*** Device node's properties ***
+
+Once regions in the /memory/reserved-memory node have been defined, they
+can be assigned to device nodes to enable respective device drivers to
+access them. The following properties are defined:
+
+memory-region = <&phandle_to_defined_region>;
+
+This property indicates that the device driver should use the memory
+region pointed by the given phandle.
+
+
+*** Example ***
+
+This example defines a memory consisting of 4 memory banks. 3 contiguous
+regions are defined for Linux kernel, one default of all device drivers
+(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
+framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
+and one for multimedia processing (labelled multimedia_mem, placed at
+0x77000000, 64MiB). 'display_mem' region is then assigned to fb@12300000
+device for DMA memory allocations (Linux kernel drivers will use CMA is
+available or dma-exclusive usage otherwise). 'multimedia_mem' is
+assigned to scaler@12500000 and codec@12600000 devices for contiguous
+memory allocations when CMA driver is enabled.
+
+The reason for creating a separate region for framebuffer device is to
+match the framebuffer base address to the one configured by bootloader,
+so once Linux kernel drivers starts no glitches on the displayed boot
+logo appears. Scaller and codec drivers should share the memory
+allocations.
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	/* ... */
+
+	memory {
+		reg =  <0x40000000 0x10000000
+			0x50000000 0x10000000
+			0x60000000 0x10000000
+			0x70000000 0x10000000>;
+
+		reserved-memory {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			/*
+			 * global autoconfigured region for contiguous allocations
+			 * (used only with Contiguous Memory Allocator)
+			 */
+			contig_region@0 {
+				compatible = "linux,contiguous-memory-region";
+				reg = <0x0 0x4000000>;
+				linux,default-contiguous-region;
+			};
+
+			/*
+			 * special region for framebuffer
+			 */
+			display_mem: region@78000000 {
+				compatible = "linux,contiguous-memory-region", "reserved-memory-region";
+				reg = <0x78000000 0x800000>;
+			};
+
+			/*
+			 * special region for multimedia processing devices
+			 */
+			multimedia_mem: region@77000000 {
+				compatible = "linux,contiguous-memory-region";
+				reg = <0x77000000 0x4000000>;
+			};
+		};
+	};
+
+	/* ... */
+
+	fb0: fb@12300000 {
+		status = "okay";
+		memory-region = <&display_mem>;
+	};
+
+	scaler: scaler@12500000 {
+		status = "okay";
+		memory-region = <&multimedia_mem>;
+	};
+
+	codec: codec@12600000 {
+		status = "okay";
+		memory-region = <&multimedia_mem>;
+	};
+};
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 80e5c13..a83ab43 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -80,4 +80,10 @@  config OF_MTD
 	depends on MTD
 	def_bool y
 
+config OF_RESERVED_MEM
+	depends on CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK)
+	def_bool y
+	help
+	  Initialization code for DMA reserved memory
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 1f9c0c4..e7e3322 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,4 @@  obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
+obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
new file mode 100644
index 0000000..95563d33
--- /dev/null
+++ b/drivers/of/of_reserved_mem.c
@@ -0,0 +1,175 @@ 
+/*
+ * Device tree based initialization code for reserved memory.
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Author: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License or (at your optional) any later version of the license.
+ */
+
+#include <asm/dma-contiguous.h>
+
+#include <linux/memblock.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/mm.h>
+#include <linux/sizes.h>
+#include <linux/mm_types.h>
+#include <linux/dma-contiguous.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_reserved_mem.h>
+
+#define MAX_RESERVED_REGIONS	16
+struct reserved_mem {
+	phys_addr_t		base;
+	unsigned long		size;
+	struct cma		*cma;
+	char			name[32];
+};
+static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
+static int reserved_mem_count;
+
+static int __init fdt_scan_reserved_mem(unsigned long node, const char *uname,
+					int depth, void *data)
+{
+	struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
+	phys_addr_t base, size;
+	int is_cma, is_reserved;
+	unsigned long len;
+	const char *status;
+	__be32 *prop;
+
+	is_cma = IS_ENABLED(CONFIG_CMA) &&
+	       of_flat_dt_is_compatible(node, "linux,contiguous-memory-region");
+	is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
+
+	if (!is_reserved && !is_cma) {
+		/* ignore node and scan next one */
+		return 0;
+	}
+
+	status = of_get_flat_dt_prop(node, "status", &len);
+	if (status && strcmp(status, "okay") != 0) {
+		/* ignore disabled node nad scan next one */
+		return 0;
+	}
+
+	prop = of_get_flat_dt_prop(node, "reg", &len);
+	if (!prop || (len < (dt_root_size_cells + dt_root_addr_cells) *
+			     sizeof(__be32))) {
+		pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
+		       uname);
+		/* ignore node and scan next one */
+		return 0;
+	}
+	base = dt_mem_next_cell(dt_root_addr_cells, &prop);
+	size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+	if (!size) {
+		/* ignore node and scan next one */
+		return 0;
+	}
+
+	pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
+		uname, (unsigned long)base, (unsigned long)size / SZ_1M);
+
+	if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
+		return -ENOSPC;
+
+	rmem->base = base;
+	rmem->size = size;
+	strlcpy(rmem->name, uname, sizeof(rmem->name));
+
+	if (is_cma) {
+		struct cma *cma;
+		if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
+			rmem->cma = cma;
+			reserved_mem_count++;
+			if (of_get_flat_dt_prop(node,
+						"linux,default-contiguous-region",
+						NULL))
+				dma_contiguous_default_area = cma;
+		}
+	} else if (is_reserved) {
+		if (memblock_remove(base, size) == 0)
+			reserved_mem_count++;
+		else
+			pr_err("Failed to reserve memory for %s\n", uname);
+	}
+
+	return 0;
+}
+
+static struct reserved_mem *get_dma_memory_region(struct device *dev)
+{
+	struct device_node *node;
+	const char *name;
+	int i;
+
+	node = of_parse_phandle(dev->of_node, "memory-region", 0);
+	if (!node)
+		return NULL;
+
+	name = kbasename(node->full_name);
+	for (i = 0; i < reserved_mem_count; i++)
+		if (strcmp(name, reserved_mem[i].name) == 0)
+			return &reserved_mem[i];
+	return NULL;
+}
+
+/**
+ * of_reserved_mem_device_init() - assign reserved memory region to given device
+ *
+ * This function assign memory region pointed by "memory-region" device tree
+ * property to the given device.
+ */
+void of_reserved_mem_device_init(struct device *dev)
+{
+	struct reserved_mem *region = get_dma_memory_region(dev);
+	if (!region)
+		return;
+
+	if (region->cma) {
+		dev_set_cma_area(dev, region->cma);
+		pr_info("Assigned CMA %s to %s device\n", region->name,
+			dev_name(dev));
+	} else {
+		if (dma_declare_coherent_memory(dev, region->base, region->base,
+		    region->size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) != 0)
+			pr_info("Declared reserved memory %s to %s device\n",
+				region->name, dev_name(dev));
+	}
+}
+
+/**
+ * of_reserved_mem_device_release() - release reserved memory device structures
+ *
+ * This function releases structures allocated for memory region handling for
+ * the given device.
+ */
+void of_reserved_mem_device_release(struct device *dev)
+{
+	struct reserved_mem *region = get_dma_memory_region(dev);
+	if (!region && !region->cma)
+		dma_release_declared_memory(dev);
+}
+
+/**
+ * early_init_dt_scan_reserved_mem() - create reserved memory regions
+ *
+ * This function grabs memory from early allocator for device exclusive use
+ * defined in device tree structures. It should be called by arch specific code
+ * once the early allocator (memblock) has been activated and all other
+ * subsystems have already allocated/reserved memory.
+ */
+void __init early_init_dt_scan_reserved_mem(void)
+{
+	of_scan_flat_dt_by_path("/memory/reserved-memory",
+				fdt_scan_reserved_mem, NULL);
+}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index e0a6514..1e4e91d 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -21,6 +21,7 @@ 
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 
 const struct of_device_id of_default_bus_match_table[] = {
@@ -196,6 +197,7 @@  EXPORT_SYMBOL(of_device_alloc);
  * Returns pointer to created platform device, or NULL if a device was not
  * registered.  Unavailable devices will not get registered.
  */
+
 struct platform_device *of_platform_device_create_pdata(
 					struct device_node *np,
 					const char *bus_id,
@@ -218,6 +220,8 @@  struct platform_device *of_platform_device_create_pdata(
 	dev->dev.bus = &platform_bus_type;
 	dev->dev.platform_data = platform_data;
 
+	of_reserved_mem_device_init(&dev->dev);
+
 	/* We do not fill the DMA ops for platform devices by default.
 	 * This is currently the responsibility of the platform code
 	 * to do such, possibly using a device notifier
@@ -225,6 +229,7 @@  struct platform_device *of_platform_device_create_pdata(
 
 	if (of_device_add(dev) != 0) {
 		platform_device_put(dev);
+		of_reserved_mem_device_release(&dev->dev);
 		return NULL;
 	}
 
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
new file mode 100644
index 0000000..c841282
--- /dev/null
+++ b/include/linux/of_reserved_mem.h
@@ -0,0 +1,14 @@ 
+#ifndef __OF_RESERVED_MEM_H
+#define __OF_RESERVED_MEM_H
+
+#ifdef CONFIG_OF_RESERVED_MEM
+void of_reserved_mem_device_init(struct device *dev);
+void of_reserved_mem_device_release(struct device *dev);
+void early_init_dt_scan_reserved_mem(void);
+#else
+static inline void of_reserved_mem_device_init(struct device *dev) { }
+static inline void of_reserved_mem_device_release(struct device *dev) { }
+static inline void early_init_dt_scan_reserved_mem(void) { }
+#endif
+
+#endif /* __OF_RESERVED_MEM_H */