Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
85e1f221
Commit
85e1f221
authored
Feb 27, 2020
by
Rob Herring
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dt/ranges-rework' into dt/next
parents
689e16ed
9d55bebd
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
157 additions
and
138 deletions
+157
-138
arch/microblaze/pci/pci-common.c
arch/microblaze/pci/pci-common.c
+1
-6
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci-common.c
+1
-1
drivers/of/address.c
drivers/of/address.c
+146
-127
include/linux/of_address.h
include/linux/of_address.h
+9
-4
No files found.
arch/microblaze/pci/pci-common.c
View file @
85e1f221
...
...
@@ -433,10 +433,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
pr_debug
(
"Parsing ranges property...
\n
"
);
for_each_of_pci_range
(
&
parser
,
&
range
)
{
/* Read next ranges element */
pr_debug
(
"pci_space: 0x%08x pci_addr:0x%016llx "
,
range
.
pci_space
,
range
.
pci_addr
);
pr_debug
(
"cpu_addr:0x%016llx size:0x%016llx
\n
"
,
range
.
cpu_addr
,
range
.
size
);
/* If we failed translation or got a zero-sized region
* (some FW try to feed us with non sensical zero sized regions
...
...
@@ -486,7 +482,7 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
pr_info
(
" MEM 0x%016llx..0x%016llx -> 0x%016llx %s
\n
"
,
range
.
cpu_addr
,
range
.
cpu_addr
+
range
.
size
-
1
,
range
.
pci_addr
,
(
range
.
pci_space
&
0x40000000
)
?
(
range
.
flags
&
IORESOURCE_PREFETCH
)
?
"Prefetch"
:
""
);
/* We support only 3 memory ranges */
...
...
@@ -1121,4 +1117,3 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn,
{
return
pci_bus_find_capability
(
fake_pci_bus
(
hose
,
bus
),
devfn
,
cap
);
}
arch/powerpc/kernel/pci-common.c
View file @
85e1f221
...
...
@@ -728,7 +728,7 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
" MEM 0x%016llx..0x%016llx -> 0x%016llx %s
\n
"
,
range
.
cpu_addr
,
range
.
cpu_addr
+
range
.
size
-
1
,
range
.
pci_addr
,
(
range
.
pci_space
&
0x40000000
)
?
(
range
.
flags
&
IORESOURCE_PREFETCH
)
?
"Prefetch"
:
""
);
/* We support only 3 memory ranges */
...
...
drivers/of/address.c
View file @
85e1f221
...
...
@@ -100,6 +100,28 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
return
IORESOURCE_MEM
;
}
static
unsigned
int
of_bus_pci_get_flags
(
const
__be32
*
addr
)
{
unsigned
int
flags
=
0
;
u32
w
=
be32_to_cpup
(
addr
);
if
(
!
IS_ENABLED
(
CONFIG_PCI
))
return
0
;
switch
((
w
>>
24
)
&
0x03
)
{
case
0x01
:
flags
|=
IORESOURCE_IO
;
break
;
case
0x02
:
/* 32 bits */
case
0x03
:
/* 64 bits */
flags
|=
IORESOURCE_MEM
;
break
;
}
if
(
w
&
0x40000000
)
flags
|=
IORESOURCE_PREFETCH
;
return
flags
;
}
#ifdef CONFIG_PCI
/*
* PCI bus specific translator
...
...
@@ -125,25 +147,6 @@ static void of_bus_pci_count_cells(struct device_node *np,
*
sizec
=
2
;
}
static
unsigned
int
of_bus_pci_get_flags
(
const
__be32
*
addr
)
{
unsigned
int
flags
=
0
;
u32
w
=
be32_to_cpup
(
addr
);
switch
((
w
>>
24
)
&
0x03
)
{
case
0x01
:
flags
|=
IORESOURCE_IO
;
break
;
case
0x02
:
/* 32 bits */
case
0x03
:
/* 64 bits */
flags
|=
IORESOURCE_MEM
;
break
;
}
if
(
w
&
0x40000000
)
flags
|=
IORESOURCE_PREFETCH
;
return
flags
;
}
static
u64
of_bus_pci_map
(
__be32
*
addr
,
const
__be32
*
range
,
int
na
,
int
ns
,
int
pna
)
{
...
...
@@ -234,93 +237,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
}
EXPORT_SYMBOL_GPL
(
of_pci_address_to_resource
);
static
int
parser_init
(
struct
of_pci_range_parser
*
parser
,
struct
device_node
*
node
,
const
char
*
name
)
{
const
int
na
=
3
,
ns
=
2
;
int
rlen
;
parser
->
node
=
node
;
parser
->
pna
=
of_n_addr_cells
(
node
);
parser
->
np
=
parser
->
pna
+
na
+
ns
;
parser
->
dma
=
!
strcmp
(
name
,
"dma-ranges"
);
parser
->
range
=
of_get_property
(
node
,
name
,
&
rlen
);
if
(
parser
->
range
==
NULL
)
return
-
ENOENT
;
parser
->
end
=
parser
->
range
+
rlen
/
sizeof
(
__be32
);
return
0
;
}
int
of_pci_range_parser_init
(
struct
of_pci_range_parser
*
parser
,
struct
device_node
*
node
)
{
return
parser_init
(
parser
,
node
,
"ranges"
);
}
EXPORT_SYMBOL_GPL
(
of_pci_range_parser_init
);
int
of_pci_dma_range_parser_init
(
struct
of_pci_range_parser
*
parser
,
struct
device_node
*
node
)
{
return
parser_init
(
parser
,
node
,
"dma-ranges"
);
}
EXPORT_SYMBOL_GPL
(
of_pci_dma_range_parser_init
);
struct
of_pci_range
*
of_pci_range_parser_one
(
struct
of_pci_range_parser
*
parser
,
struct
of_pci_range
*
range
)
{
const
int
na
=
3
,
ns
=
2
;
if
(
!
range
)
return
NULL
;
if
(
!
parser
->
range
||
parser
->
range
+
parser
->
np
>
parser
->
end
)
return
NULL
;
range
->
pci_space
=
be32_to_cpup
(
parser
->
range
);
range
->
flags
=
of_bus_pci_get_flags
(
parser
->
range
);
range
->
pci_addr
=
of_read_number
(
parser
->
range
+
1
,
ns
);
if
(
parser
->
dma
)
range
->
cpu_addr
=
of_translate_dma_address
(
parser
->
node
,
parser
->
range
+
na
);
else
range
->
cpu_addr
=
of_translate_address
(
parser
->
node
,
parser
->
range
+
na
);
range
->
size
=
of_read_number
(
parser
->
range
+
parser
->
pna
+
na
,
ns
);
parser
->
range
+=
parser
->
np
;
/* Now consume following elements while they are contiguous */
while
(
parser
->
range
+
parser
->
np
<=
parser
->
end
)
{
u32
flags
;
u64
pci_addr
,
cpu_addr
,
size
;
flags
=
of_bus_pci_get_flags
(
parser
->
range
);
pci_addr
=
of_read_number
(
parser
->
range
+
1
,
ns
);
if
(
parser
->
dma
)
cpu_addr
=
of_translate_dma_address
(
parser
->
node
,
parser
->
range
+
na
);
else
cpu_addr
=
of_translate_address
(
parser
->
node
,
parser
->
range
+
na
);
size
=
of_read_number
(
parser
->
range
+
parser
->
pna
+
na
,
ns
);
if
(
flags
!=
range
->
flags
)
break
;
if
(
pci_addr
!=
range
->
pci_addr
+
range
->
size
||
cpu_addr
!=
range
->
cpu_addr
+
range
->
size
)
break
;
range
->
size
+=
size
;
parser
->
range
+=
parser
->
np
;
}
return
range
;
}
EXPORT_SYMBOL_GPL
(
of_pci_range_parser_one
);
/*
* of_pci_range_to_resource - Create a resource from an of_pci_range
* @range: the PCI range that describes the resource
...
...
@@ -775,6 +691,101 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
}
EXPORT_SYMBOL
(
of_get_address
);
static
int
parser_init
(
struct
of_pci_range_parser
*
parser
,
struct
device_node
*
node
,
const
char
*
name
)
{
int
rlen
;
parser
->
node
=
node
;
parser
->
pna
=
of_n_addr_cells
(
node
);
parser
->
na
=
of_bus_n_addr_cells
(
node
);
parser
->
ns
=
of_bus_n_size_cells
(
node
);
parser
->
dma
=
!
strcmp
(
name
,
"dma-ranges"
);
parser
->
range
=
of_get_property
(
node
,
name
,
&
rlen
);
if
(
parser
->
range
==
NULL
)
return
-
ENOENT
;
parser
->
end
=
parser
->
range
+
rlen
/
sizeof
(
__be32
);
return
0
;
}
int
of_pci_range_parser_init
(
struct
of_pci_range_parser
*
parser
,
struct
device_node
*
node
)
{
return
parser_init
(
parser
,
node
,
"ranges"
);
}
EXPORT_SYMBOL_GPL
(
of_pci_range_parser_init
);
int
of_pci_dma_range_parser_init
(
struct
of_pci_range_parser
*
parser
,
struct
device_node
*
node
)
{
return
parser_init
(
parser
,
node
,
"dma-ranges"
);
}
EXPORT_SYMBOL_GPL
(
of_pci_dma_range_parser_init
);
#define of_dma_range_parser_init of_pci_dma_range_parser_init
struct
of_pci_range
*
of_pci_range_parser_one
(
struct
of_pci_range_parser
*
parser
,
struct
of_pci_range
*
range
)
{
int
na
=
parser
->
na
;
int
ns
=
parser
->
ns
;
int
np
=
parser
->
pna
+
na
+
ns
;
if
(
!
range
)
return
NULL
;
if
(
!
parser
->
range
||
parser
->
range
+
np
>
parser
->
end
)
return
NULL
;
if
(
parser
->
na
==
3
)
range
->
flags
=
of_bus_pci_get_flags
(
parser
->
range
);
else
range
->
flags
=
0
;
range
->
pci_addr
=
of_read_number
(
parser
->
range
,
na
);
if
(
parser
->
dma
)
range
->
cpu_addr
=
of_translate_dma_address
(
parser
->
node
,
parser
->
range
+
na
);
else
range
->
cpu_addr
=
of_translate_address
(
parser
->
node
,
parser
->
range
+
na
);
range
->
size
=
of_read_number
(
parser
->
range
+
parser
->
pna
+
na
,
ns
);
parser
->
range
+=
np
;
/* Now consume following elements while they are contiguous */
while
(
parser
->
range
+
np
<=
parser
->
end
)
{
u32
flags
=
0
;
u64
pci_addr
,
cpu_addr
,
size
;
if
(
parser
->
na
==
3
)
flags
=
of_bus_pci_get_flags
(
parser
->
range
);
pci_addr
=
of_read_number
(
parser
->
range
,
na
);
if
(
parser
->
dma
)
cpu_addr
=
of_translate_dma_address
(
parser
->
node
,
parser
->
range
+
na
);
else
cpu_addr
=
of_translate_address
(
parser
->
node
,
parser
->
range
+
na
);
size
=
of_read_number
(
parser
->
range
+
parser
->
pna
+
na
,
ns
);
if
(
flags
!=
range
->
flags
)
break
;
if
(
pci_addr
!=
range
->
pci_addr
+
range
->
size
||
cpu_addr
!=
range
->
cpu_addr
+
range
->
size
)
break
;
range
->
size
+=
size
;
parser
->
range
+=
np
;
}
return
range
;
}
EXPORT_SYMBOL_GPL
(
of_pci_range_parser_one
);
static
u64
of_translate_ioport
(
struct
device_node
*
dev
,
const
__be32
*
in_addr
,
u64
size
)
{
...
...
@@ -928,10 +939,12 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz
{
struct
device_node
*
node
=
of_node_get
(
np
);
const
__be32
*
ranges
=
NULL
;
int
len
,
naddr
,
nsize
,
pna
;
int
len
;
int
ret
=
0
;
bool
found_dma_ranges
=
false
;
u64
dmaaddr
;
struct
of_range_parser
parser
;
struct
of_range
range
;
u64
dma_start
=
U64_MAX
,
dma_end
=
0
,
dma_offset
=
0
;
while
(
node
)
{
ranges
=
of_get_property
(
node
,
"dma-ranges"
,
&
len
);
...
...
@@ -956,32 +969,38 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz
goto
out
;
}
naddr
=
of_bus_n_addr_cells
(
node
);
nsize
=
of_bus_n_size_cells
(
node
);
pna
=
of_n_addr_cells
(
node
);
if
((
len
/
sizeof
(
__be32
))
%
(
pna
+
naddr
+
nsize
))
{
ret
=
-
EINVAL
;
goto
out
;
of_dma_range_parser_init
(
&
parser
,
node
);
for_each_of_range
(
&
parser
,
&
range
)
{
pr_debug
(
"dma_addr(%llx) cpu_addr(%llx) size(%llx)
\n
"
,
range
.
bus_addr
,
range
.
cpu_addr
,
range
.
size
);
if
(
dma_offset
&&
range
.
cpu_addr
-
range
.
bus_addr
!=
dma_offset
)
{
pr_warn
(
"Can't handle multiple dma-ranges with different offsets on node(%pOF)
\n
"
,
node
);
/* Don't error out as we'd break some existing DTs */
continue
;
}
dma_offset
=
range
.
cpu_addr
-
range
.
bus_addr
;
/* Take lower and upper limits */
if
(
range
.
bus_addr
<
dma_start
)
dma_start
=
range
.
bus_addr
;
if
(
range
.
bus_addr
+
range
.
size
>
dma_end
)
dma_end
=
range
.
bus_addr
+
range
.
size
;
}
/* dma-ranges format:
* DMA addr : naddr cells
* CPU addr : pna cells
* size : nsize cells
*/
dmaaddr
=
of_read_number
(
ranges
,
naddr
);
*
paddr
=
of_translate_dma_address
(
node
,
ranges
+
naddr
);
if
(
*
paddr
==
OF_BAD_ADDR
)
{
pr_err
(
"translation of DMA address(%llx) to CPU address failed node(%pOF)
\n
"
,
dmaaddr
,
np
);
if
(
dma_start
>=
dma_end
)
{
ret
=
-
EINVAL
;
pr_debug
(
"Invalid DMA ranges configuration on node(%pOF)
\n
"
,
node
);
goto
out
;
}
*
dma_addr
=
dmaaddr
;
*
size
=
of_read_number
(
ranges
+
naddr
+
pna
,
nsize
);
*
dma_addr
=
dma_start
;
*
size
=
dma_end
-
dma_start
;
*
paddr
=
dma_start
+
dma_offset
;
pr_debug
(
"dma_addr(%llx) cpu_addr(%llx) size(%llx)
\n
"
,
pr_debug
(
"
final:
dma_addr(%llx) cpu_addr(%llx) size(%llx)
\n
"
,
*
dma_addr
,
*
paddr
,
*
size
);
out:
...
...
include/linux/of_address.h
View file @
85e1f221
...
...
@@ -10,21 +10,27 @@ struct of_pci_range_parser {
struct
device_node
*
node
;
const
__be32
*
range
;
const
__be32
*
end
;
int
np
;
int
na
;
int
ns
;
int
pna
;
bool
dma
;
};
#define of_range_parser of_pci_range_parser
struct
of_pci_range
{
u32
pci_space
;
u64
pci_addr
;
union
{
u64
pci_addr
;
u64
bus_addr
;
};
u64
cpu_addr
;
u64
size
;
u32
flags
;
};
#define of_range of_pci_range
#define for_each_of_pci_range(parser, range) \
for (; of_pci_range_parser_one(parser, range);)
#define for_each_of_range for_each_of_pci_range
/* Translate a DMA address from device space to CPU space */
extern
u64
of_translate_dma_address
(
struct
device_node
*
dev
,
...
...
@@ -143,4 +149,3 @@ static inline int of_pci_range_to_resource(struct of_pci_range *range,
#endif
/* CONFIG_OF_ADDRESS && CONFIG_PCI */
#endif
/* __OF_ADDRESS_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment