* Re: [PATCH v4 3/3] Documentation: of: Document graph bindings
From: Philipp Zabel @ 2014-02-27 10:52 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Russell King - ARM Linux, Mauro Carvalho Chehab, Grant Likely,
Rob Herring, Sylwester Nawrocki, Laurent Pinchart, Kyungmin Park,
linux-kernel, linux-media, devicetree, Guennadi Liakhovetski
In-Reply-To: <530EF294.7070801@ti.com>
Hi Tomi,
Am Donnerstag, den 27.02.2014, 10:08 +0200 schrieb Tomi Valkeinen:
> On 26/02/14 17:47, Philipp Zabel wrote:
> > Please let's not make it mandatory for a port node to contain an
> > endpoint. For any device with multiple ports we can't use the simplified
> > form above, and only adding the (correctly numbered) port in all the
> > board device trees would be a pain.
>
> That's true. I went with having the ports in the board file, for example
> on omap3 the dss has two ports, and N900 board uses the second one:
>
> &dss {
> status = "ok";
>
> pinctrl-names = "default";
> pinctrl-0 = <&dss_sdi_pins>;
>
> vdds_sdi-supply = <&vaux1>;
>
> ports {
> #address-cells = <1>;
> #size-cells = <0>;
>
> port@1 {
> reg = <1>;
>
> sdi_out: endpoint {
> remote-endpoint = <&lcd_in>;
> datapairs = <2>;
> };
> };
> };
> };
This is a bit verbose, and if your output port is on an encoder device
with multiple inputs, the correct port number would become a bit
unintuitive. For example, we'd have to use port@4 as the output encoder
units that have a 4-port input multiplexer and port@1 for those that
don't.
> Here I guess I could have:
>
> &dss {
> status = "ok";
>
> pinctrl-names = "default";
> pinctrl-0 = <&dss_sdi_pins>;
>
> vdds_sdi-supply = <&vaux1>;
> };
What is supplied by this regulator. Is it the PHY?
> &dss_sdi_port {
> sdi_out: endpoint {
> remote-endpoint = <&lcd_in>;
> datapairs = <2>;
> };
> };
>
> But I didn't like that as it splits the pincontrol and regulator supply
> from the port/endpoint, which are functionally linked together.
>
> Actually, somewhat aside the subject, I'd like to have the pinctrl and
> maybe regulator supply also per endpoint, but I didn't see how that
> would be possible with the current framework. If a board would need to
> endpoints for the same port, most likely it would also need to different
> sets of pinctrls.
I have a usecase for this the other way around. The i.MX6 DISP0 parallel
display pads can be connected to two different display controllers via
multiplexers in the pin control block.
parallel-display {
compatible = "fsl,imx-parallel-display";
#address-cells = <1>;
#size-cells = <0>;
port@0 {
endpoint {
remote-endpoint = <&ipu1_di0>;
};
};
port@1 {
endpoint {
remote-endpoint = <&ipu2_di0>;
};
};
disp0: port@2 {
endpoint {
pinctrl-names = "0", "1";
pinctrl-0 = <&pinctrl_disp0_ipu1>;
pinctrl-1 = <&pinctrl_disp0_ipu2>;
remote-endpoint = <&lcd_in>;
};
}
};
Here, depending on the active input port, the corresponding pin control
on the output port could be set. This is probably quite driver specific,
so I don't see yet how the framework should help with this. In any case,
maybe this is a bit out of scope for the generic graph bindings.
regards
Philipp
^ permalink raw reply
* Re: [RFC PATCH v4 3/8] staging: imx-drm: Document updated imx-drm device tree bindings
From: Tomi Valkeinen @ 2014-02-27 11:06 UTC (permalink / raw)
To: Philipp Zabel
Cc: devel, devicetree, Russell King - ARM Linux, David Airlie,
Greg Kroah-Hartman, dri-devel, kernel, Grant Likely, Shawn Guo,
Fabio Estevam, linux-arm-kernel
In-Reply-To: <1393338203-25051-4-git-send-email-p.zabel@pengutronix.de>
[-- Attachment #1.1: Type: text/plain, Size: 2609 bytes --]
On 25/02/14 16:23, Philipp Zabel wrote:
> +Freescale i.MX DRM master device
> +================================
> +
> +The freescale i.MX DRM master device is a virtual device needed to list all
> +IPU or other display interface nodes that comprise the graphics subsystem.
> +
> +Required properties:
> +- compatible: Should be "fsl,imx-drm"
> +- ports: Should contain a list of phandles pointing to display interface ports
> + of IPU devices
> +
> +example:
> +
> +imx-drm {
> + compatible = "fsl,imx-drm";
> + ports = <&ipu_di0>;
> +};
I'm not a fan of having non-hardware related things in the DT data.
Especially if it makes direct references to our SW, in this case DRM.
There's no DRM on the board. I wanted to avoid all that with OMAP
display bindings.
Is there even need for such a master device? You can find all the
connected display devices from any single display device, by just
following the endpoint links.
> display@di0 {
> compatible = "fsl,imx-parallel-display";
> edid = [edid-data];
> - crtc = <&ipu 0>;
> interface-pix-fmt = "rgb24";
> +
> + port {
> + display_in: endpoint {
> + remote-endpoint = <&ipu_di0_disp0>;
> + };
> + };
> };
Shouldn't the pix-fmt be defined in the endpoint node? It is about pixel
format for a particular endpoint, isn't it?
> diff --git a/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt b/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
> index ed93778..578a1fc 100644
> --- a/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
> +++ b/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
> @@ -50,12 +50,14 @@ have a look at Documentation/devicetree/bindings/video/display-timing.txt.
>
> Required properties:
> - reg : should be <0> or <1>
> - - crtcs : a list of phandles with index pointing to the IPU display interfaces
> - that can be used as video source for this channel.
> - fsl,data-mapping : should be "spwg" or "jeida"
> This describes how the color bits are laid out in the
> serialized LVDS signal.
> - fsl,data-width : should be <18> or <24>
> + - port: A port node with endpoint definitions as defined in
> + Documentation/devicetree/bindings/media/video-interfaces.txt.
> + On i.MX6, there should be four ports (port@[0-3]) that correspond
> + to the four LVDS multiplexer inputs.
Is the ldb something that's on the imx SoC?
Do you have a public branch somewhere? It'd be easier to look at the
final result, as I'm not familiar with imx.
Tomi
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 3/6] spi: sh-msiof: Add support for R-Car H2 and M2
From: Geert Uytterhoeven @ 2014-02-27 11:09 UTC (permalink / raw)
To: Laurent Pinchart, Bastian Hecht
Cc: Mark Brown, Takashi Yoshii, Magnus Damm, linux-spi, Linux-sh list,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Geert Uytterhoeven,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1462634.UcxrmdxVtK@avalon>
On Thu, Feb 27, 2014 at 11:41 AM, Laurent Pinchart
<laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org> wrote:
>> >> -- compatible : "renesas,sh-msiof" for SuperH, or
>> >> +- compatible : "renesas,msiof-<soctype>" for SoCs,
>> >> + "renesas,sh-msiof" for SuperH, or
>> >> "renesas,sh-mobile-msiof" for SH Mobile series.
>> >> + Examples with soctypes are:
>> >> + "renesas,msiof-sh7724" (SH)
>> >
>> > Given that the driver doesn't handle the "renesas,msiof-sh7724" compatible
>> > string this might not be a good example. Furthermore SuperH doesn't have
>> > DT support. I would thus drop the "renesas,sh-msiof" compatible string
>> > from patch 1/6 and wouldn't mention sh7724 here. I very much doubt that
>> > someone would have developed DT support for SuperH on the side and
>> > shipped products that would be broken by this change :-)
>>
>> Upon reading your comment again: do you suggest to also remove the plain
>> "renesas,sh-msiof"? That one was present before, since DT support was added
>> to the driver in
>>
>> commit cf9c86efecf9510e62388fd174cf607671c59fa3
>> Author: Bastian Hecht <hechtb-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Date: Wed Dec 12 12:54:48 2012 +0100
>>
>> spi/sh-msiof: Add device tree parsing to driver
>>
>> This adds the capability to retrieve setup data from the device tree
>> node. The usage of platform data is still available.
>>
>> Signed-off-by: Bastian Hecht <hechtb+renesas-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
>>
>> So I prefer not to remove any pre-existing compatible values.
>> Do you agree?
>
> I'd like to remove it (in a separate patch) if we can. The reason is that
> keeping the DT ABI both forward- and backward-compatible is pretty painful
> enough without having to care about compatibility strings that have no user.
> I'd rather work on adding DT support for SuperH MSIOF later when we'll have a
> platform we can test it on, instead of trying to guess now what the needs will
> be, get users later and realize even later on that we made a mistake that we
> can't fix because those users will have DT binaries in the wild. Every
> unneeded bit of DT bindings that we keep in the kernel is one potential
> problem for future binary compatibility.
I agree about the complexity of keeping the DT ABI forward- and
backward-compatible.
However, in this case I don't think it hurts that much to just keep it:
- DT compatible values and platform device names are kept in sync
through a pointer to the same struct sh_msiof_chipdata, so there's
not much maintenance needed.
- DT compatible "renesas,sh-msiof" means exactly the same as
the "spi_sh_msiof" platform device name, which is currently in use.
So even if SuperH never moves to DT, we have to keep support for that
specific MSIOF implementation, unless we drop the platform device version,
too (Hmm, maybe that's what you're alluding to ;-)
And if we remove "renesas,sh-msiof", we should probably remove
"renesas,sh-mobile-msiof", too, as there are no current users, and it also
assumes the same MSIOF implementation?
Bastian: What was your real plan with "renesas,sh-msiof" and
"renesas,sh-mobile-msiof"?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [0/10] RFC: A new start on richer dtc expression support [REPOST]
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA; +Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ
I previously sent these patches to the new devicetree-compiler, but I
suspect not many people had subscribed so I'm resending to the
devicetree list.
So, we've been talking about richer expression / constant / function /
macro support for dtc since forever. So far attempts to start on that
haven't gotten very far (in large part because of my pickiness about
new syntax).
Anyway, I've started having a new crack at this. This patch series
implements the infrastructure for "runtime" evaluated expressions.
For now they're just constructed and immediately evaluated, so they're
not quite usable for user-defined functions yet, but it's a big step
towards that.
10/10 is the only patch in this series which implements new
user-visible functionality, the rest are just internal reworking.
10/10 experiments with the new mechanisms to implement string append
and repeat operators - I'm not 100% sure if I'm happy with the syntax
used for this yet (overloaded + and *, like Python). Suggestions
welcome.
This is indirectly relevant to the schema checking concepts current
much discused. Any schema language is likely to want richer
expression support than we currently have to be useful. In addition,
I expect we'll need data structures very similar to the expression
trees implemented here to keep track of schema "patterns" or other
pieces.
These patches can also be found in the 'expressions' branch at
git://git.kernel.org/pub/scm/utils/dtc/dtc.git. [NOTE: I'm
considering this an experimental branch for now, which will be rebased
at whim].
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 01/10] First cut at expression trees
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
At the moment, the integer expressions supported by dtc are always constant
expressions, and are evaluated as we parse. That's nice and simple but
limits us in a number of ways. It makes named constants awkward to
implement and user defined functions more or less impossible.
As a first step to allowing more possibilities, create the structures we
need to represent expressions at runtime. For now we just construct them
in the parser, then immediately evaluate, but one thing at a time.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
Makefile.dtc | 1 +
dtc-parser.y | 173 +++++++++++++++++++++++++++++++++--------------------------
dtc.h | 58 ++++++++++++++++++++
expression.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 321 insertions(+), 76 deletions(-)
create mode 100644 expression.c
diff --git a/Makefile.dtc b/Makefile.dtc
index bece49b..d41d9c5 100644
--- a/Makefile.dtc
+++ b/Makefile.dtc
@@ -7,6 +7,7 @@ DTC_SRCS = \
checks.c \
data.c \
dtc.c \
+ expression.o \
flattree.c \
fstree.c \
livetree.c \
diff --git a/dtc-parser.y b/dtc-parser.y
index ea57e0a..5e2348e 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -33,6 +33,11 @@ extern void yyerror(char const *s);
extern struct boot_info *the_boot_info;
extern bool treesource_error;
+
+static uint64_t expr_int(struct expression *expr);
+
+#define UNOP(op, a) (expression_##op((a)))
+#define BINOP(op, a, b) (expression_##op((a), (b)))
%}
%union {
@@ -52,6 +57,7 @@ extern bool treesource_error;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
+ struct expression *expr;
}
%token DT_V1
@@ -83,20 +89,20 @@ extern bool treesource_error;
%type <node> subnode
%type <nodelist> subnodes
-%type <integer> integer_prim
-%type <integer> integer_unary
-%type <integer> integer_mul
-%type <integer> integer_add
-%type <integer> integer_shift
-%type <integer> integer_rela
-%type <integer> integer_eq
-%type <integer> integer_bitand
-%type <integer> integer_bitxor
-%type <integer> integer_bitor
-%type <integer> integer_and
-%type <integer> integer_or
-%type <integer> integer_trinary
-%type <integer> integer_expr
+%type <expr> expr_prim
+%type <expr> expr_unary
+%type <expr> expr_mul
+%type <expr> expr_add
+%type <expr> expr_shift
+%type <expr> expr_rela
+%type <expr> expr_eq
+%type <expr> expr_bitand
+%type <expr> expr_bitxor
+%type <expr> expr_bitor
+%type <expr> expr_and
+%type <expr> expr_or
+%type <expr> expr_conditional
+%type <expr> expr
%%
@@ -120,9 +126,10 @@ memreserves:
;
memreserve:
- DT_MEMRESERVE integer_prim integer_prim ';'
+ DT_MEMRESERVE expr_prim expr_prim ';'
{
- $$ = build_reserve_entry($2, $3);
+ $$ = build_reserve_entry(expr_int($2),
+ expr_int($3));
}
| DT_LABEL memreserve
{
@@ -219,18 +226,19 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
- | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
+ | propdataprefix DT_INCBIN '(' DT_STRING ',' expr_prim ',' expr_prim ')'
{
FILE *f = srcfile_relative_open($4.val, NULL);
+ off_t offset = expr_int($6);
struct data d;
- if ($6 != 0)
- if (fseek(f, $6, SEEK_SET) != 0)
+ if (offset != 0)
+ if (fseek(f, offset, SEEK_SET) != 0)
die("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)$6, $4.val,
+ (unsigned long long)offset, $4.val,
strerror(errno));
- d = data_copy_file(f, $8);
+ d = data_copy_file(f, expr_int($8));
$$ = data_merge($1, d);
fclose(f);
@@ -288,8 +296,10 @@ arrayprefix:
$$.data = empty_data;
$$.bits = 32;
}
- | arrayprefix integer_prim
+ | arrayprefix expr_prim
{
+ uint64_t val = expr_int($2);
+
if ($1.bits < 64) {
uint64_t mask = (1ULL << $1.bits) - 1;
/*
@@ -300,12 +310,12 @@ arrayprefix:
* within the mask to one (i.e. | in the
* mask), all bits are one.
*/
- if (($2 > mask) && (($2 | mask) != -1ULL))
+ if ((val > mask) && ((val | mask) != -1ULL))
ERROR(&@2, "Value out of range for"
" %d-bit array element", $1.bits);
}
- $$.data = data_append_integer($1.data, $2, $1.bits);
+ $$.data = data_append_integer($1.data, val, $1.bits);
}
| arrayprefix DT_REF
{
@@ -327,87 +337,90 @@ arrayprefix:
}
;
-integer_prim:
- DT_LITERAL
- | DT_CHAR_LITERAL
- | '(' integer_expr ')'
+expr_prim:
+ DT_LITERAL { $$ = expression_constant($1); }
+ | DT_CHAR_LITERAL { $$ = expression_constant($1); }
+ | '(' expr ')'
{
$$ = $2;
}
;
-integer_expr:
- integer_trinary
+expr:
+ expr_conditional
;
-integer_trinary:
- integer_or
- | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
+expr_conditional:
+ expr_or
+ | expr_or '?' expr ':' expr_conditional
+ {
+ $$ = expression_conditional($1, $3, $5);
+ }
;
-integer_or:
- integer_and
- | integer_or DT_OR integer_and { $$ = $1 || $3; }
+expr_or:
+ expr_and
+ | expr_or DT_OR expr_and { $$ = BINOP(logic_or, $1, $3); }
;
-integer_and:
- integer_bitor
- | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
+expr_and:
+ expr_bitor
+ | expr_and DT_AND expr_bitor { $$ = BINOP(logic_and, $1, $3); }
;
-integer_bitor:
- integer_bitxor
- | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
+expr_bitor:
+ expr_bitxor
+ | expr_bitor '|' expr_bitxor { $$ = BINOP(bit_or, $1, $3); }
;
-integer_bitxor:
- integer_bitand
- | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
+expr_bitxor:
+ expr_bitand
+ | expr_bitxor '^' expr_bitand { $$ = BINOP(bit_xor, $1, $3); }
;
-integer_bitand:
- integer_eq
- | integer_bitand '&' integer_eq { $$ = $1 & $3; }
+expr_bitand:
+ expr_eq
+ | expr_bitand '&' expr_eq { $$ = BINOP(bit_and, $1, $3); }
;
-integer_eq:
- integer_rela
- | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
- | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
+expr_eq:
+ expr_rela
+ | expr_eq DT_EQ expr_rela { $$ = BINOP(eq, $1, $3); }
+ | expr_eq DT_NE expr_rela { $$ = BINOP(ne, $1, $3); }
;
-integer_rela:
- integer_shift
- | integer_rela '<' integer_shift { $$ = $1 < $3; }
- | integer_rela '>' integer_shift { $$ = $1 > $3; }
- | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
- | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
+expr_rela:
+ expr_shift
+ | expr_rela '<' expr_shift { $$ = BINOP(lt, $1, $3); }
+ | expr_rela '>' expr_shift { $$ = BINOP(gt, $1, $3); }
+ | expr_rela DT_LE expr_shift { $$ = BINOP(le, $1, $3); }
+ | expr_rela DT_GE expr_shift { $$ = BINOP(ge, $1, $3); }
;
-integer_shift:
- integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
- | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
- | integer_add
+expr_shift:
+ expr_shift DT_LSHIFT expr_add { $$ = BINOP(lshift, $1, $3); }
+ | expr_shift DT_RSHIFT expr_add { $$ = BINOP(rshift, $1, $3); }
+ | expr_add
;
-integer_add:
- integer_add '+' integer_mul { $$ = $1 + $3; }
- | integer_add '-' integer_mul { $$ = $1 - $3; }
- | integer_mul
+expr_add:
+ expr_add '+' expr_mul { $$ = BINOP(add, $1, $3); }
+ | expr_add '-' expr_mul { $$ = BINOP(sub, $1, $3); }
+ | expr_mul
;
-integer_mul:
- integer_mul '*' integer_unary { $$ = $1 * $3; }
- | integer_mul '/' integer_unary { $$ = $1 / $3; }
- | integer_mul '%' integer_unary { $$ = $1 % $3; }
- | integer_unary
+expr_mul:
+ expr_mul '*' expr_unary { $$ = BINOP(mul, $1, $3); }
+ | expr_mul '/' expr_unary { $$ = BINOP(div, $1, $3); }
+ | expr_mul '%' expr_unary { $$ = BINOP(mod, $1, $3); }
+ | expr_unary
;
-integer_unary:
- integer_prim
- | '-' integer_unary { $$ = -$2; }
- | '~' integer_unary { $$ = ~$2; }
- | '!' integer_unary { $$ = !$2; }
+expr_unary:
+ expr_prim
+ | '-' expr_unary { $$ = UNOP(negate, $2); }
+ | '~' expr_unary { $$ = UNOP(bit_not, $2); }
+ | '!' expr_unary { $$ = UNOP(logic_not, $2); }
;
bytestring:
@@ -463,3 +476,11 @@ void yyerror(char const *s)
{
ERROR(&yylloc, "%s", s);
}
+
+static uint64_t expr_int(struct expression *expr)
+{
+ uint64_t val;
+ val = expression_evaluate(expr);
+ expression_free(expr);
+ return val;
+}
diff --git a/dtc.h b/dtc.h
index 20de073..c40e9d7 100644
--- a/dtc.h
+++ b/dtc.h
@@ -218,6 +218,64 @@ cell_t get_node_phandle(struct node *root, struct node *node);
uint32_t guess_boot_cpuid(struct node *tree);
+/* Expressions */
+
+struct operator;
+
+struct expression {
+ struct operator *op;
+ int nargs;
+ union {
+ uint64_t constant;
+ } u;
+ struct expression *arg[0];
+};
+
+void expression_free(struct expression *expr);
+uint64_t expression_evaluate(struct expression *expr);
+
+struct expression *expression_constant(uint64_t val);
+
+#define DEF_UNARY_OP(nm) \
+ struct expression *expression_##nm(struct expression *)
+DEF_UNARY_OP(negate);
+DEF_UNARY_OP(bit_not);
+DEF_UNARY_OP(logic_not);
+
+#define DEF_BINARY_OP(nm) \
+ struct expression *expression_##nm(struct expression *, struct expression *)
+DEF_BINARY_OP(mod);
+DEF_BINARY_OP(div);
+DEF_BINARY_OP(mul);
+
+DEF_BINARY_OP(add);
+DEF_BINARY_OP(sub);
+
+DEF_BINARY_OP(lshift);
+DEF_BINARY_OP(rshift);
+
+DEF_BINARY_OP(lt);
+DEF_BINARY_OP(gt);
+DEF_BINARY_OP(le);
+DEF_BINARY_OP(ge);
+
+DEF_BINARY_OP(eq);
+DEF_BINARY_OP(ne);
+
+DEF_BINARY_OP(bit_and);
+
+DEF_BINARY_OP(bit_xor);
+
+DEF_BINARY_OP(bit_or);
+
+DEF_BINARY_OP(logic_and);
+
+DEF_BINARY_OP(logic_or);
+
+struct expression *expression_conditional(struct expression *,
+ struct expression *,
+ struct expression *);
+
/* Boot info (tree plus memreserve information */
struct reserve_info {
diff --git a/expression.c b/expression.c
new file mode 100644
index 0000000..dd31a37
--- /dev/null
+++ b/expression.c
@@ -0,0 +1,165 @@
+/*
+ * (C) Copyright David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>, Red Hat 2013.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "dtc.h"
+
+struct operator {
+ const char *name;
+ unsigned nargs;
+ uint64_t (*evaluate)(struct expression *);
+ void (*free)(struct expression *);
+};
+
+static struct expression *__expression_build(struct operator *op, ...)
+{
+ int nargs = 0;
+ struct expression *expr;
+ va_list ap;
+ int i;
+
+ /* Sanity check number of arguments */
+ va_start(ap, op);
+ while (va_arg(ap, struct expression *) != NULL)
+ nargs++;
+ va_end(ap);
+
+ expr = xmalloc(sizeof(*expr) + nargs*sizeof(struct expression *));
+ expr->op = op;
+ expr->nargs = nargs;
+
+ va_start(ap, op);
+ for (i = 0; i < nargs; i++)
+ expr->arg[i] = va_arg(ap, struct expression *);
+ va_end(ap);
+
+ return expr;
+}
+#define expression_build(...) \
+ (__expression_build(__VA_ARGS__, NULL))
+
+void expression_free(struct expression *expr)
+{
+ int i;
+
+ for (i = 0; i < expr->nargs; i++)
+ expression_free(expr->arg[i]);
+ if (expr->op->free)
+ expr->op->free(expr);
+ free(expr);
+}
+
+uint64_t expression_evaluate(struct expression *expr)
+{
+ return expr->op->evaluate(expr);
+}
+
+static uint64_t op_eval_constant(struct expression *expr)
+{
+ assert(expr->nargs == 0);
+ return expr->u.constant;
+}
+static struct operator op_constant = {
+ .name = "constant",
+ .evaluate = op_eval_constant,
+};
+struct expression *expression_constant(uint64_t val)
+{
+ struct expression *expr = expression_build(&op_constant);
+
+ expr->u.constant = val;
+ return expr;
+}
+
+#define INT_UNARY_OP(nm, cop) \
+ static uint64_t op_eval_##nm(struct expression *expr) \
+ { \
+ assert(expr->nargs == 1); \
+ return cop expression_evaluate(expr->arg[0]); \
+ } \
+ static struct operator op_##nm = { \
+ .name = #cop, \
+ .evaluate = op_eval_##nm, \
+ }; \
+ struct expression *expression_##nm(struct expression *arg) \
+ { \
+ return expression_build(&op_##nm, arg); \
+ }
+
+INT_UNARY_OP(negate, -)
+INT_UNARY_OP(bit_not, ~)
+INT_UNARY_OP(logic_not, !)
+
+#define INT_BINARY_OP(nm, cop) \
+ static uint64_t op_eval_##nm(struct expression *expr) \
+ { \
+ assert(expr->nargs == 2); \
+ return expression_evaluate(expr->arg[0]) \
+ cop expression_evaluate(expr->arg[1]); \
+ } \
+ static struct operator op_##nm = { \
+ .name = #cop, \
+ .evaluate = op_eval_##nm, \
+ }; \
+ struct expression *expression_##nm(struct expression *arg1, struct expression *arg2) \
+ { \
+ return expression_build(&op_##nm, arg1, arg2); \
+ }
+
+INT_BINARY_OP(mod, %)
+INT_BINARY_OP(div, /)
+INT_BINARY_OP(mul, *)
+
+INT_BINARY_OP(add, +)
+INT_BINARY_OP(sub, -)
+
+INT_BINARY_OP(lshift, <<)
+INT_BINARY_OP(rshift, >>)
+
+INT_BINARY_OP(lt, <)
+INT_BINARY_OP(gt, >)
+INT_BINARY_OP(le, <=)
+INT_BINARY_OP(ge, >=)
+
+INT_BINARY_OP(eq, ==)
+INT_BINARY_OP(ne, !=)
+
+INT_BINARY_OP(bit_and, &)
+INT_BINARY_OP(bit_xor, ^)
+INT_BINARY_OP(bit_or, |)
+
+INT_BINARY_OP(logic_and, &&)
+INT_BINARY_OP(logic_or, ||)
+
+static uint64_t op_eval_conditional(struct expression *expr)
+{
+ assert(expr->nargs == 3);
+ return expression_evaluate(expr->arg[0])
+ ? expression_evaluate(expr->arg[1])
+ : expression_evaluate(expr->arg[2]);
+}
+static struct operator op_conditional = {
+ .name = "?:",
+ .evaluate = op_eval_conditional,
+};
+struct expression *expression_conditional(struct expression *arg1, struct expression *arg2,
+ struct expression *arg3)
+{
+ return expression_build(&op_conditional, arg1, arg2, arg3);
+}
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 02/10] Add srcpos information to expressions
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
This patch allows information about source locations to be attached to
expression structures. We'll need this information later on in order to
provide reasonable error messages.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 52 ++++++++++++++++++++++++++--------------------------
dtc.h | 14 ++++++++++----
expression.c | 34 ++++++++++++++++++++++------------
3 files changed, 58 insertions(+), 42 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index 5e2348e..c5522e3 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -36,8 +36,8 @@ extern bool treesource_error;
static uint64_t expr_int(struct expression *expr);
-#define UNOP(op, a) (expression_##op((a)))
-#define BINOP(op, a, b) (expression_##op((a), (b)))
+#define UNOP(loc, op, a) (expression_##op(&loc, (a)))
+#define BINOP(loc, op, a, b) (expression_##op(&loc, (a), (b)))
%}
%union {
@@ -338,8 +338,8 @@ arrayprefix:
;
expr_prim:
- DT_LITERAL { $$ = expression_constant($1); }
- | DT_CHAR_LITERAL { $$ = expression_constant($1); }
+ DT_LITERAL { $$ = expression_constant(&yylloc, $1); }
+ | DT_CHAR_LITERAL { $$ = expression_constant(&yylloc, $1); }
| '(' expr ')'
{
$$ = $2;
@@ -354,73 +354,73 @@ expr_conditional:
expr_or
| expr_or '?' expr ':' expr_conditional
{
- $$ = expression_conditional($1, $3, $5);
+ $$ = expression_conditional(&yylloc, $1, $3, $5);
}
;
expr_or:
expr_and
- | expr_or DT_OR expr_and { $$ = BINOP(logic_or, $1, $3); }
+ | expr_or DT_OR expr_and { $$ = BINOP(@$, logic_or, $1, $3); }
;
expr_and:
expr_bitor
- | expr_and DT_AND expr_bitor { $$ = BINOP(logic_and, $1, $3); }
+ | expr_and DT_AND expr_bitor { $$ = BINOP(@$, logic_and, $1, $3); }
;
expr_bitor:
expr_bitxor
- | expr_bitor '|' expr_bitxor { $$ = BINOP(bit_or, $1, $3); }
+ | expr_bitor '|' expr_bitxor { $$ = BINOP(@$, bit_or, $1, $3); }
;
expr_bitxor:
expr_bitand
- | expr_bitxor '^' expr_bitand { $$ = BINOP(bit_xor, $1, $3); }
+ | expr_bitxor '^' expr_bitand { $$ = BINOP(@$, bit_xor, $1, $3); }
;
expr_bitand:
expr_eq
- | expr_bitand '&' expr_eq { $$ = BINOP(bit_and, $1, $3); }
+ | expr_bitand '&' expr_eq { $$ = BINOP(@$, bit_and, $1, $3); }
;
expr_eq:
expr_rela
- | expr_eq DT_EQ expr_rela { $$ = BINOP(eq, $1, $3); }
- | expr_eq DT_NE expr_rela { $$ = BINOP(ne, $1, $3); }
+ | expr_eq DT_EQ expr_rela { $$ = BINOP(@$, eq, $1, $3); }
+ | expr_eq DT_NE expr_rela { $$ = BINOP(@$, ne, $1, $3); }
;
expr_rela:
expr_shift
- | expr_rela '<' expr_shift { $$ = BINOP(lt, $1, $3); }
- | expr_rela '>' expr_shift { $$ = BINOP(gt, $1, $3); }
- | expr_rela DT_LE expr_shift { $$ = BINOP(le, $1, $3); }
- | expr_rela DT_GE expr_shift { $$ = BINOP(ge, $1, $3); }
+ | expr_rela '<' expr_shift { $$ = BINOP(@$, lt, $1, $3); }
+ | expr_rela '>' expr_shift { $$ = BINOP(@$, gt, $1, $3); }
+ | expr_rela DT_LE expr_shift { $$ = BINOP(@$, le, $1, $3); }
+ | expr_rela DT_GE expr_shift { $$ = BINOP(@$, ge, $1, $3); }
;
expr_shift:
- expr_shift DT_LSHIFT expr_add { $$ = BINOP(lshift, $1, $3); }
- | expr_shift DT_RSHIFT expr_add { $$ = BINOP(rshift, $1, $3); }
+ expr_shift DT_LSHIFT expr_add { $$ = BINOP(@$, lshift, $1, $3); }
+ | expr_shift DT_RSHIFT expr_add { $$ = BINOP(@$, rshift, $1, $3); }
| expr_add
;
expr_add:
- expr_add '+' expr_mul { $$ = BINOP(add, $1, $3); }
- | expr_add '-' expr_mul { $$ = BINOP(sub, $1, $3); }
+ expr_add '+' expr_mul { $$ = BINOP(@$, add, $1, $3); }
+ | expr_add '-' expr_mul { $$ = BINOP(@$, sub, $1, $3); }
| expr_mul
;
expr_mul:
- expr_mul '*' expr_unary { $$ = BINOP(mul, $1, $3); }
- | expr_mul '/' expr_unary { $$ = BINOP(div, $1, $3); }
- | expr_mul '%' expr_unary { $$ = BINOP(mod, $1, $3); }
+ expr_mul '*' expr_unary { $$ = BINOP(@$, mul, $1, $3); }
+ | expr_mul '/' expr_unary { $$ = BINOP(@$, div, $1, $3); }
+ | expr_mul '%' expr_unary { $$ = BINOP(@$, mod, $1, $3); }
| expr_unary
;
expr_unary:
expr_prim
- | '-' expr_unary { $$ = UNOP(negate, $2); }
- | '~' expr_unary { $$ = UNOP(bit_not, $2); }
- | '!' expr_unary { $$ = UNOP(logic_not, $2); }
+ | '-' expr_unary { $$ = UNOP(@$, negate, $2); }
+ | '~' expr_unary { $$ = UNOP(@$, bit_not, $2); }
+ | '!' expr_unary { $$ = UNOP(@$, logic_not, $2); }
;
bytestring:
diff --git a/dtc.h b/dtc.h
index c40e9d7..fed9d2d 100644
--- a/dtc.h
+++ b/dtc.h
@@ -221,8 +221,10 @@ uint32_t guess_boot_cpuid(struct node *tree);
/* Expressions */
struct operator;
+struct srcpos;
struct expression {
+ struct srcpos *loc;
struct operator *op;
int nargs;
union {
@@ -234,16 +236,19 @@ struct expression {
void expression_free(struct expression *expr);
uint64_t expression_evaluate(struct expression *expr);
-struct expression *expression_constant(uint64_t val);
+struct expression *expression_constant(struct srcpos *pos, uint64_t val);
#define DEF_UNARY_OP(nm) \
- struct expression *expression_##nm(struct expression *)
+ struct expression *expression_##nm(struct srcpos *, \
+ struct expression *)
DEF_UNARY_OP(negate);
DEF_UNARY_OP(bit_not);
DEF_UNARY_OP(logic_not);
#define DEF_BINARY_OP(nm) \
- struct expression *expression_##nm(struct expression *, struct expression *)
+ struct expression *expression_##nm(struct srcpos *, \
+ struct expression *, \
+ struct expression *)
DEF_BINARY_OP(mod);
DEF_BINARY_OP(div);
DEF_BINARY_OP(mul);
@@ -272,7 +277,8 @@ DEF_BINARY_OP(logic_and);
DEF_BINARY_OP(logic_or);
-struct expression *expression_conditional(struct expression *,
+struct expression *expression_conditional(struct srcpos *pos,
+ struct expression *,
struct expression *,
struct expression *);
diff --git a/expression.c b/expression.c
index dd31a37..05d0df5 100644
--- a/expression.c
+++ b/expression.c
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
-
+#include "srcpos.h"
#include "dtc.h"
struct operator {
@@ -27,7 +27,8 @@ struct operator {
void (*free)(struct expression *);
};
-static struct expression *__expression_build(struct operator *op, ...)
+static struct expression *__expression_build(struct srcpos *loc,
+ struct operator *op, ...)
{
int nargs = 0;
struct expression *expr;
@@ -43,6 +44,10 @@ static struct expression *__expression_build(struct operator *op, ...)
expr = xmalloc(sizeof(*expr) + nargs*sizeof(struct expression *));
expr->op = op;
expr->nargs = nargs;
+ if (loc)
+ expr->loc = srcpos_copy(loc);
+ else
+ expr->loc = NULL;
va_start(ap, op);
for (i = 0; i < nargs; i++)
@@ -51,8 +56,8 @@ static struct expression *__expression_build(struct operator *op, ...)
return expr;
}
-#define expression_build(...) \
- (__expression_build(__VA_ARGS__, NULL))
+#define expression_build(loc, ...) \
+ (__expression_build(loc, __VA_ARGS__, NULL))
void expression_free(struct expression *expr)
{
@@ -79,9 +84,9 @@ static struct operator op_constant = {
.name = "constant",
.evaluate = op_eval_constant,
};
-struct expression *expression_constant(uint64_t val)
+struct expression *expression_constant(struct srcpos *loc, uint64_t val)
{
- struct expression *expr = expression_build(&op_constant);
+ struct expression *expr = expression_build(loc, &op_constant);
expr->u.constant = val;
return expr;
@@ -97,9 +102,10 @@ struct expression *expression_constant(uint64_t val)
.name = #cop, \
.evaluate = op_eval_##nm, \
}; \
- struct expression *expression_##nm(struct expression *arg) \
+ struct expression *expression_##nm(struct srcpos *loc, \
+ struct expression *arg) \
{ \
- return expression_build(&op_##nm, arg); \
+ return expression_build(loc, &op_##nm, arg); \
}
INT_UNARY_OP(negate, -)
@@ -117,9 +123,11 @@ INT_UNARY_OP(logic_not, !)
.name = #cop, \
.evaluate = op_eval_##nm, \
}; \
- struct expression *expression_##nm(struct expression *arg1, struct expression *arg2) \
+ struct expression *expression_##nm(struct srcpos *loc, \
+ struct expression *arg1, \
+ struct expression *arg2) \
{ \
- return expression_build(&op_##nm, arg1, arg2); \
+ return expression_build(loc, &op_##nm, arg1, arg2); \
}
INT_BINARY_OP(mod, %)
@@ -158,8 +166,10 @@ static struct operator op_conditional = {
.name = "?:",
.evaluate = op_eval_conditional,
};
-struct expression *expression_conditional(struct expression *arg1, struct expression *arg2,
+struct expression *expression_conditional(struct srcpos *loc,
+ struct expression *arg1,
+ struct expression *arg2,
struct expression *arg3)
{
- return expression_build(&op_conditional, arg1, arg2, arg3);
+ return expression_build(loc, &op_conditional, arg1, arg2, arg3);
}
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 03/10] Add type information to expression trees
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
This implements a rudimentary dynamic typing system for dtc expressions,
laying the groundwork for expressions of multiple types (e.g. string,
bytestring). For now, we don't actually implement any types beyond
integer, though.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 19 ++++++-----
dtc.h | 20 +++++++++--
expression.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 123 insertions(+), 25 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index c5522e3..fbf5f3c 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -128,8 +128,7 @@ memreserves:
memreserve:
DT_MEMRESERVE expr_prim expr_prim ';'
{
- $$ = build_reserve_entry(expr_int($2),
- expr_int($3));
+ $$ = build_reserve_entry(expr_int($2), expr_int($3));
}
| DT_LABEL memreserve
{
@@ -338,8 +337,8 @@ arrayprefix:
;
expr_prim:
- DT_LITERAL { $$ = expression_constant(&yylloc, $1); }
- | DT_CHAR_LITERAL { $$ = expression_constant(&yylloc, $1); }
+ DT_LITERAL { $$ = expression_integer_constant(&yylloc, $1); }
+ | DT_CHAR_LITERAL { $$ = expression_integer_constant(&yylloc, $1); }
| '(' expr ')'
{
$$ = $2;
@@ -479,8 +478,12 @@ void yyerror(char const *s)
static uint64_t expr_int(struct expression *expr)
{
- uint64_t val;
- val = expression_evaluate(expr);
- expression_free(expr);
- return val;
+ struct expression_value v = expression_evaluate(expr, EXPR_INTEGER);
+
+ if (v.type == EXPR_VOID) {
+ treesource_error = true;
+ return -1;
+ }
+ assert(v.type == EXPR_INTEGER);
+ return v.value.integer;
}
diff --git a/dtc.h b/dtc.h
index fed9d2d..95ed75e 100644
--- a/dtc.h
+++ b/dtc.h
@@ -223,20 +223,34 @@ uint32_t guess_boot_cpuid(struct node *tree);
struct operator;
struct srcpos;
+enum expr_type {
+ EXPR_VOID = 0, /* Missing or unspecified type */
+ EXPR_INTEGER,
+};
+
+struct expression_value {
+ enum expr_type type;
+ union {
+ uint64_t integer;
+ } value;
+};
+
struct expression {
struct srcpos *loc;
struct operator *op;
int nargs;
union {
- uint64_t constant;
+ struct expression_value constant;
} u;
struct expression *arg[0];
};
void expression_free(struct expression *expr);
-uint64_t expression_evaluate(struct expression *expr);
+struct expression_value expression_evaluate(struct expression *expr,
+ enum expr_type context);
-struct expression *expression_constant(struct srcpos *pos, uint64_t val);
+struct expression *expression_integer_constant(struct srcpos *pos,
+ uint64_t val);
#define DEF_UNARY_OP(nm) \
struct expression *expression_##nm(struct srcpos *, \
diff --git a/expression.c b/expression.c
index 05d0df5..a89eea3 100644
--- a/expression.c
+++ b/expression.c
@@ -20,10 +20,25 @@
#include "srcpos.h"
#include "dtc.h"
+static const char *expression_typename(enum expr_type t)
+{
+ switch (t) {
+ case EXPR_VOID:
+ return "void";
+
+ case EXPR_INTEGER:
+ return "integer";
+
+ default:
+ assert(0);
+ }
+}
+
struct operator {
const char *name;
unsigned nargs;
- uint64_t (*evaluate)(struct expression *);
+ struct expression_value (*evaluate)(struct expression *,
+ enum expr_type context);
void (*free)(struct expression *);
};
@@ -70,12 +85,51 @@ void expression_free(struct expression *expr)
free(expr);
}
-uint64_t expression_evaluate(struct expression *expr)
+static struct expression_value type_error(struct expression *expr,
+ const char *fmt, ...)
+{
+ static const struct expression_value v = {
+ .type = EXPR_VOID,
+ };
+
+ va_list(ap);
+
+ va_start(ap, fmt);
+ srcpos_verror(expr->loc, "Type error", fmt, ap);
+ va_end(ap);
+
+ return v;
+}
+
+struct expression_value expression_evaluate(struct expression *expr,
+ enum expr_type context)
{
- return expr->op->evaluate(expr);
+ struct expression_value v = expr->op->evaluate(expr, context);
+
+ if ((context != EXPR_VOID) && (context != v.type))
+ return type_error(expr, "Expected %s expression (found %s)",
+ expression_typename(context),
+ expression_typename(v.type));
+
+ return v;
}
-static uint64_t op_eval_constant(struct expression *expr)
+#define EVALUATE(_v, _ex, _ctx) \
+ do { \
+ (_v) = expression_evaluate((_ex), (_ctx)); \
+ if ((_v).type == EXPR_VOID) \
+ return (_v); \
+ } while (0)
+
+#define EVALUATE_INT(_vi, _ex) \
+ do { \
+ struct expression_value _v; \
+ EVALUATE(_v, (_ex), EXPR_INTEGER); \
+ (_vi) = (_v).value.integer; \
+ } while (0)
+
+static struct expression_value op_eval_constant(struct expression *expr,
+ enum expr_type context)
{
assert(expr->nargs == 0);
return expr->u.constant;
@@ -84,7 +138,9 @@ static struct operator op_constant = {
.name = "constant",
.evaluate = op_eval_constant,
};
-struct expression *expression_constant(struct srcpos *loc, uint64_t val)
+
+static struct expression *__expression_constant(struct srcpos *loc,
+ struct expression_value val)
{
struct expression *expr = expression_build(loc, &op_constant);
@@ -92,11 +148,27 @@ struct expression *expression_constant(struct srcpos *loc, uint64_t val)
return expr;
}
+struct expression *expression_integer_constant(struct srcpos *pos,
+ uint64_t val)
+{
+ struct expression_value v = {
+ .type = EXPR_INTEGER,
+ .value.integer = val,
+ };
+
+ return __expression_constant(pos, v);
+}
+
#define INT_UNARY_OP(nm, cop) \
- static uint64_t op_eval_##nm(struct expression *expr) \
+ static struct expression_value op_eval_##nm(struct expression *expr, \
+ enum expr_type context) \
{ \
+ struct expression_value v = { .type = EXPR_INTEGER, }; \
+ uint64_t arg; \
assert(expr->nargs == 1); \
- return cop expression_evaluate(expr->arg[0]); \
+ EVALUATE_INT(arg, expr->arg[0]); \
+ v.value.integer = cop arg; \
+ return v; \
} \
static struct operator op_##nm = { \
.name = #cop, \
@@ -113,11 +185,16 @@ INT_UNARY_OP(bit_not, ~)
INT_UNARY_OP(logic_not, !)
#define INT_BINARY_OP(nm, cop) \
- static uint64_t op_eval_##nm(struct expression *expr) \
+ static struct expression_value op_eval_##nm(struct expression *expr, \
+ enum expr_type context) \
{ \
+ struct expression_value v = { .type = EXPR_INTEGER, }; \
+ uint64_t arg0, arg1; \
assert(expr->nargs == 2); \
- return expression_evaluate(expr->arg[0]) \
- cop expression_evaluate(expr->arg[1]); \
+ EVALUATE_INT(arg0, expr->arg[0]); \
+ EVALUATE_INT(arg1, expr->arg[1]); \
+ v.value.integer = arg0 cop arg1; \
+ return v; \
} \
static struct operator op_##nm = { \
.name = #cop, \
@@ -155,12 +232,16 @@ INT_BINARY_OP(bit_or, |)
INT_BINARY_OP(logic_and, &&)
INT_BINARY_OP(logic_or, ||)
-static uint64_t op_eval_conditional(struct expression *expr)
+static struct expression_value op_eval_conditional(struct expression *expr,
+ enum expr_type context)
{
+ uint64_t cond;
+
assert(expr->nargs == 3);
- return expression_evaluate(expr->arg[0])
- ? expression_evaluate(expr->arg[1])
- : expression_evaluate(expr->arg[2]);
+ EVALUATE_INT(cond, expr->arg[0]);
+
+ return cond ? expression_evaluate(expr->arg[1], context)
+ : expression_evaluate(expr->arg[2], context);
}
static struct operator op_conditional = {
.name = "?:",
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 04/10] Add string and bytestring expression types
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
Both string and bytestring expression values are represented by a
bytestring internally to handle things like "\0abc". So, the only real
distinction is that string expressions must evaluate to a bytestring which
has a \0 in the last bye. For now the only actual "expressions" of these
types are literals, but we'll expand on that later.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
data.c | 26 ++++++++++++++++--
dtc-parser.y | 58 +++++++++++++++++++++++++++++++---------
dtc.h | 10 +++++++
expression.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 165 insertions(+), 16 deletions(-)
diff --git a/data.c b/data.c
index 4c50b12..4db1f2f 100644
--- a/data.c
+++ b/data.c
@@ -237,12 +237,17 @@ struct data data_append_align(struct data d, int align)
return data_append_zeroes(d, newlen - d.len);
}
-struct data data_add_marker(struct data d, enum markertype type, char *ref)
+static struct data data_add_marker_at(struct data d, enum markertype type,
+ int offset, char *ref)
{
struct marker *m;
+ m = d.markers;
+ for_each_marker(m)
+ assert(m->offset <= offset);
+
m = xmalloc(sizeof(*m));
- m->offset = d.len;
+ m->offset = offset;
m->type = type;
m->ref = ref;
m->next = NULL;
@@ -250,6 +255,11 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
return data_append_markers(d, m);
}
+struct data data_add_marker(struct data d, enum markertype type, char *ref)
+{
+ return data_add_marker_at(d, type, d.len, ref);
+}
+
bool data_is_one_string(struct data d)
{
int i;
@@ -267,3 +277,15 @@ bool data_is_one_string(struct data d)
return true;
}
+
+struct data data_clone(struct data d)
+{
+ struct data clone = data_copy_mem(d.val, d.len);
+ struct marker *m = d.markers;
+
+ for_each_marker(m)
+ clone = data_add_marker_at(clone, m->type,
+ m->offset, strdup(m->ref));
+
+ return clone;
+}
diff --git a/dtc-parser.y b/dtc-parser.y
index fbf5f3c..e4df947 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -35,6 +35,8 @@ extern struct boot_info *the_boot_info;
extern bool treesource_error;
static uint64_t expr_int(struct expression *expr);
+static const char *expr_str(struct expression *expr);
+static struct data expr_bytestring(struct expression *expr);
#define UNOP(loc, op, a) (expression_##op(&loc, (a)))
#define BINOP(loc, op, a, b) (expression_##op(&loc, (a), (b)))
@@ -80,7 +82,7 @@ static uint64_t expr_int(struct expression *expr);
%type <re> memreserve
%type <re> memreserves
%type <array> arrayprefix
-%type <data> bytestring
+%type <data> bytestring_literal
%type <prop> propdef
%type <proplist> proplist
@@ -209,32 +211,30 @@ propdef:
;
propdata:
- propdataprefix DT_STRING
+ propdataprefix expr
{
- $$ = data_merge($1, $2);
+ struct data d = expr_bytestring($2);
+ $$ = data_merge($1, d);
}
| propdataprefix arrayprefix '>'
{
$$ = data_merge($1, $2.data);
}
- | propdataprefix '[' bytestring ']'
- {
- $$ = data_merge($1, $3);
- }
| propdataprefix DT_REF
{
$$ = data_add_marker($1, REF_PATH, $2);
}
- | propdataprefix DT_INCBIN '(' DT_STRING ',' expr_prim ',' expr_prim ')'
+ | propdataprefix DT_INCBIN '(' expr_prim ',' expr_prim ',' expr_prim ')'
{
- FILE *f = srcfile_relative_open($4.val, NULL);
+ const char *filename = expr_str($4);
+ FILE *f = srcfile_relative_open(filename, NULL);
off_t offset = expr_int($6);
struct data d;
if (offset != 0)
if (fseek(f, offset, SEEK_SET) != 0)
die("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)offset, $4.val,
+ (unsigned long long)offset, filename,
strerror(errno));
d = data_copy_file(f, expr_int($8));
@@ -339,6 +339,14 @@ arrayprefix:
expr_prim:
DT_LITERAL { $$ = expression_integer_constant(&yylloc, $1); }
| DT_CHAR_LITERAL { $$ = expression_integer_constant(&yylloc, $1); }
+ | DT_STRING
+ {
+ $$ = expression_string_constant(&yylloc, $1);
+ }
+ | '[' bytestring_literal ']'
+ {
+ $$ = expression_bytestring_constant(&@2, $2);
+ }
| '(' expr ')'
{
$$ = $2;
@@ -422,16 +430,16 @@ expr_unary:
| '!' expr_unary { $$ = UNOP(@$, logic_not, $2); }
;
-bytestring:
+bytestring_literal:
/* empty */
{
$$ = empty_data;
}
- | bytestring DT_BYTE
+ | bytestring_literal DT_BYTE
{
$$ = data_append_byte($1, $2);
}
- | bytestring DT_LABEL
+ | bytestring_literal DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
}
@@ -487,3 +495,27 @@ static uint64_t expr_int(struct expression *expr)
assert(v.type == EXPR_INTEGER);
return v.value.integer;
}
+
+static const char *expr_str(struct expression *expr)
+{
+ struct expression_value v = expression_evaluate(expr, EXPR_STRING);
+
+ if (v.type == EXPR_VOID) {
+ treesource_error = true;
+ return "";
+ }
+ assert(v.type == EXPR_STRING);
+ return v.value.d.val;
+}
+
+static struct data expr_bytestring(struct expression *expr)
+{
+ struct expression_value v = expression_evaluate(expr, EXPR_BYTESTRING);
+
+ if (v.type == EXPR_VOID) {
+ treesource_error = true;
+ return empty_data;
+ }
+ assert(v.type == EXPR_BYTESTRING);
+ return v.value.d;
+}
diff --git a/dtc.h b/dtc.h
index 95ed75e..0b644d2 100644
--- a/dtc.h
+++ b/dtc.h
@@ -120,6 +120,8 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref);
bool data_is_one_string(struct data d);
+struct data data_clone(struct data d);
+
/* DT constraints */
#define MAX_PROPNAME_LEN 31
@@ -226,12 +228,15 @@ struct srcpos;
enum expr_type {
EXPR_VOID = 0, /* Missing or unspecified type */
EXPR_INTEGER,
+ EXPR_STRING,
+ EXPR_BYTESTRING,
};
struct expression_value {
enum expr_type type;
union {
uint64_t integer;
+ struct data d;
} value;
};
@@ -252,6 +257,11 @@ struct expression_value expression_evaluate(struct expression *expr,
struct expression *expression_integer_constant(struct srcpos *pos,
uint64_t val);
+struct expression *expression_string_constant(struct srcpos *pos,
+ struct data d);
+struct expression *expression_bytestring_constant(struct srcpos *pos,
+ struct data val);
+
#define DEF_UNARY_OP(nm) \
struct expression *expression_##nm(struct srcpos *, \
struct expression *)
diff --git a/expression.c b/expression.c
index a89eea3..4ecd84a 100644
--- a/expression.c
+++ b/expression.c
@@ -29,11 +29,49 @@ static const char *expression_typename(enum expr_type t)
case EXPR_INTEGER:
return "integer";
+ case EXPR_STRING:
+ return "string";
+
+ case EXPR_BYTESTRING:
+ return "bytestring";
+
default:
assert(0);
}
}
+static struct expression_value value_clone(struct expression_value val)
+{
+ struct expression_value clone = val;
+
+ switch (val.type) {
+ case EXPR_STRING:
+ case EXPR_BYTESTRING:
+ clone.value.d = data_clone(val.value.d);
+ break;
+
+ default:
+ /* nothing more to do */
+ ;
+ }
+
+ return clone;
+}
+
+static void value_free(struct expression_value val)
+{
+ switch (val.type) {
+ case EXPR_STRING:
+ case EXPR_BYTESTRING:
+ data_free(val.value.d);
+ break;
+
+ default:
+ /* nothing to do */
+ ;
+ }
+}
+
struct operator {
const char *name;
unsigned nargs;
@@ -106,6 +144,11 @@ struct expression_value expression_evaluate(struct expression *expr,
{
struct expression_value v = expr->op->evaluate(expr, context);
+ /* Strings can be promoted to bytestrings */
+ if ((v.type == EXPR_STRING)
+ && (context == EXPR_BYTESTRING))
+ v.type = EXPR_BYTESTRING;
+
if ((context != EXPR_VOID) && (context != v.type))
return type_error(expr, "Expected %s expression (found %s)",
expression_typename(context),
@@ -128,15 +171,35 @@ struct expression_value expression_evaluate(struct expression *expr,
(_vi) = (_v).value.integer; \
} while (0)
+#define EVALUATE_STR(_vs, _ex) \
+ do { \
+ struct expression_value _v; \
+ EVALUATE(_v, (_ex), EXPR_STRING); \
+ (_vs) = (_v).value.d; \
+ } while (0)
+
+#define EVALUATE_BS(_vd, _ex) \
+ do { \
+ struct expression_value _v; \
+ EVALUATE(_v, (_ex), EXPR_BYTESTRING); \
+ (_vd) = (_v).value.d; \
+ } while (0)
+
static struct expression_value op_eval_constant(struct expression *expr,
enum expr_type context)
{
assert(expr->nargs == 0);
- return expr->u.constant;
+ return value_clone(expr->u.constant);
+}
+static void op_free_constant(struct expression *expr)
+{
+ value_free(expr->u.constant);
}
+
static struct operator op_constant = {
.name = "constant",
.evaluate = op_eval_constant,
+ .free = op_free_constant,
};
static struct expression *__expression_constant(struct srcpos *loc,
@@ -159,6 +222,28 @@ struct expression *expression_integer_constant(struct srcpos *pos,
return __expression_constant(pos, v);
}
+struct expression *expression_string_constant(struct srcpos *pos,
+ struct data val)
+{
+ struct expression_value v = {
+ .type = EXPR_STRING,
+ .value.d = val,
+ };
+
+ return __expression_constant(pos, v);
+}
+
+struct expression *expression_bytestring_constant(struct srcpos *pos,
+ struct data val)
+{
+ struct expression_value v = {
+ .type = EXPR_BYTESTRING,
+ .value.d = val,
+ };
+
+ return __expression_constant(pos, v);
+}
+
#define INT_UNARY_OP(nm, cop) \
static struct expression_value op_eval_##nm(struct expression *expr, \
enum expr_type context) \
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 05/10] Integrate /incbin/ with expanded expressions
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
Implement /incbin/ as a new type of bytestring expression operator. This
delays the evaluation of the /incbin/'s parameters until the evaluation
of the /incbin/ itself.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 56 +++++++++++++++-----------------------------------------
dtc.h | 4 ++++
expression.c | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 41 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index e4df947..07cb067 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -35,7 +35,6 @@ extern struct boot_info *the_boot_info;
extern bool treesource_error;
static uint64_t expr_int(struct expression *expr);
-static const char *expr_str(struct expression *expr);
static struct data expr_bytestring(struct expression *expr);
#define UNOP(loc, op, a) (expression_##op(&loc, (a)))
@@ -91,6 +90,7 @@ static struct data expr_bytestring(struct expression *expr);
%type <node> subnode
%type <nodelist> subnodes
+%type <expr> expr_incbin
%type <expr> expr_prim
%type <expr> expr_unary
%type <expr> expr_mul
@@ -224,34 +224,6 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
- | propdataprefix DT_INCBIN '(' expr_prim ',' expr_prim ',' expr_prim ')'
- {
- const char *filename = expr_str($4);
- FILE *f = srcfile_relative_open(filename, NULL);
- off_t offset = expr_int($6);
- struct data d;
-
- if (offset != 0)
- if (fseek(f, offset, SEEK_SET) != 0)
- die("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)offset, filename,
- strerror(errno));
-
- d = data_copy_file(f, expr_int($8));
-
- $$ = data_merge($1, d);
- fclose(f);
- }
- | propdataprefix DT_INCBIN '(' DT_STRING ')'
- {
- FILE *f = srcfile_relative_open($4.val, NULL);
- struct data d = empty_data;
-
- d = data_copy_file(f, -1);
-
- $$ = data_merge($1, d);
- fclose(f);
- }
| propdata DT_LABEL
{
$$ = data_add_marker($1, LABEL, $2);
@@ -336,6 +308,19 @@ arrayprefix:
}
;
+expr_incbin:
+ DT_INCBIN '(' expr_conditional ',' expr_conditional ',' expr_conditional ')'
+ {
+ $$ = expression_incbin(&@$, $3, $5, $7);
+ }
+ | DT_INCBIN '(' expr_conditional ')'
+ {
+ $$ = expression_incbin(&@$, $3,
+ expression_integer_constant(NULL, 0),
+ expression_integer_constant(NULL, -1));
+ }
+ ;
+
expr_prim:
DT_LITERAL { $$ = expression_integer_constant(&yylloc, $1); }
| DT_CHAR_LITERAL { $$ = expression_integer_constant(&yylloc, $1); }
@@ -347,6 +332,7 @@ expr_prim:
{
$$ = expression_bytestring_constant(&@2, $2);
}
+ | expr_incbin
| '(' expr ')'
{
$$ = $2;
@@ -496,18 +482,6 @@ static uint64_t expr_int(struct expression *expr)
return v.value.integer;
}
-static const char *expr_str(struct expression *expr)
-{
- struct expression_value v = expression_evaluate(expr, EXPR_STRING);
-
- if (v.type == EXPR_VOID) {
- treesource_error = true;
- return "";
- }
- assert(v.type == EXPR_STRING);
- return v.value.d.val;
-}
-
static struct data expr_bytestring(struct expression *expr)
{
struct expression_value v = expression_evaluate(expr, EXPR_BYTESTRING);
diff --git a/dtc.h b/dtc.h
index 0b644d2..2ab4ba4 100644
--- a/dtc.h
+++ b/dtc.h
@@ -305,6 +305,10 @@ struct expression *expression_conditional(struct srcpos *pos,
struct expression *,
struct expression *,
struct expression *);
+struct expression *expression_incbin(struct srcpos *loc,
+ struct expression *file,
+ struct expression *off,
+ struct expression *len);
/* Boot info (tree plus memreserve information */
diff --git a/expression.c b/expression.c
index 4ecd84a..49bc8b0 100644
--- a/expression.c
+++ b/expression.c
@@ -339,3 +339,44 @@ struct expression *expression_conditional(struct srcpos *loc,
{
return expression_build(loc, &op_conditional, arg1, arg2, arg3);
}
+
+
+static struct expression_value op_eval_incbin(struct expression *expr,
+ enum expr_type context)
+{
+ struct data filename;
+ uint64_t offset, len;
+ FILE *f;
+ struct expression_value v = {
+ .type = EXPR_BYTESTRING,
+ };
+
+ EVALUATE_STR(filename, expr->arg[0]);
+ EVALUATE_INT(offset, expr->arg[1]);
+ EVALUATE_INT(len, expr->arg[2]);
+
+ f = srcfile_relative_open(filename.val, NULL);
+
+ if (offset != 0)
+ if (fseek(f, offset, SEEK_SET) != 0)
+ die("Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)offset, filename.val,
+ strerror(errno));
+
+ v.value.d = data_copy_file(f, len);
+
+ fclose(f);
+ return v;
+}
+static struct operator op_incbin = {
+ .name = "/incbin/",
+ .nargs = 3,
+ .evaluate = op_eval_incbin,
+};
+struct expression *expression_incbin(struct srcpos *loc,
+ struct expression *file,
+ struct expression *off,
+ struct expression *len)
+{
+ return expression_build(loc, &op_incbin, file, off, len);
+}
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 06/10] Implement arrays as expressions
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
This implements dtc's < ... > array syntax in terms of the new expression
infrastructure. Internally this uses two operator types, one to convert
an integer expression to a bytestring expression and another to append
multiple bytestring expressions together.
phandle references require some fiddling. These are implemented by using a
constant bytestring expression containing a placeholder plus the marker
to substitute in the correct phandle later. Logically it would be neater
for an integer expression itself to expand to the right phandle value, but
we can't do that just yet since the tree's phandle values aren't all
resolved at the time we evaluate expressions.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 60 +++++++++++++++++++++++++++++-------------------------------
dtc.h | 6 ++++++
expression.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 31 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index 07cb067..fcc3b4d 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -48,8 +48,8 @@ static struct data expr_bytestring(struct expression *expr);
struct data data;
struct {
- struct data data;
- int bits;
+ int bits;
+ struct expression *expr;
} array;
struct property *prop;
@@ -80,6 +80,7 @@ static struct data expr_bytestring(struct expression *expr);
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
+%type <array> array
%type <array> arrayprefix
%type <data> bytestring_literal
%type <prop> propdef
@@ -216,10 +217,6 @@ propdata:
struct data d = expr_bytestring($2);
$$ = data_merge($1, d);
}
- | propdataprefix arrayprefix '>'
- {
- $$ = data_merge($1, $2.data);
- }
| propdataprefix DT_REF
{
$$ = data_add_marker($1, REF_PATH, $2);
@@ -245,6 +242,10 @@ propdataprefix:
}
;
+array:
+ arrayprefix '>' { $$ = $1; }
+ ;
+
arrayprefix:
DT_BITS DT_LITERAL '<'
{
@@ -259,52 +260,48 @@ arrayprefix:
bits = 32;
}
- $$.data = empty_data;
$$.bits = bits;
+ $$.expr = expression_bytestring_constant(&@$, empty_data);
}
| '<'
{
- $$.data = empty_data;
$$.bits = 32;
+ $$.expr = expression_bytestring_constant(&@$, empty_data);
}
| arrayprefix expr_prim
{
- uint64_t val = expr_int($2);
-
- if ($1.bits < 64) {
- uint64_t mask = (1ULL << $1.bits) - 1;
- /*
- * Bits above mask must either be all zero
- * (positive within range of mask) or all one
- * (negative and sign-extended). The second
- * condition is true if when we set all bits
- * within the mask to one (i.e. | in the
- * mask), all bits are one.
- */
- if ((val > mask) && ((val | mask) != -1ULL))
- ERROR(&@2, "Value out of range for"
- " %d-bit array element", $1.bits);
- }
-
- $$.data = data_append_integer($1.data, val, $1.bits);
+ struct expression *cell = expression_arraycell(&@2,
+ $1.bits,
+ $2);
+ $$.bits = $1.bits;
+ $$.expr = expression_join(&@$, $1.expr, cell);
}
| arrayprefix DT_REF
{
uint64_t val = ~0ULL >> (64 - $1.bits);
+ struct data d = empty_data;
+ struct expression *cell;
if ($1.bits == 32)
- $1.data = data_add_marker($1.data,
- REF_PHANDLE,
- $2);
+ d = data_add_marker(d, REF_PHANDLE, $2);
else
ERROR(&@2, "References are only allowed in "
"arrays with 32-bit elements.");
- $$.data = data_append_integer($1.data, val, $1.bits);
+ d = data_append_integer(d, val, $1.bits);
+ cell = expression_bytestring_constant(&@2, d);
+
+ $$.bits = $1.bits;
+ $$.expr = expression_join(&@$, $1.expr, cell);
}
| arrayprefix DT_LABEL
{
- $$.data = data_add_marker($1.data, LABEL, $2);
+ struct data d = data_add_marker(empty_data, LABEL, $2);
+ struct expression *label;
+
+ label = expression_bytestring_constant(&@2, d);
+ $$.bits = $1.bits;
+ $$.expr = expression_join(&@$, $1.expr, label);
}
;
@@ -333,6 +330,7 @@ expr_prim:
$$ = expression_bytestring_constant(&@2, $2);
}
| expr_incbin
+ | array { $$ = $1.expr; }
| '(' expr ')'
{
$$ = $2;
diff --git a/dtc.h b/dtc.h
index 2ab4ba4..d270626 100644
--- a/dtc.h
+++ b/dtc.h
@@ -246,6 +246,7 @@ struct expression {
int nargs;
union {
struct expression_value constant;
+ int bits;
} u;
struct expression *arg[0];
};
@@ -309,6 +310,11 @@ struct expression *expression_incbin(struct srcpos *loc,
struct expression *file,
struct expression *off,
struct expression *len);
+struct expression *expression_arraycell(struct srcpos *loc, int bits,
+ struct expression *cell);
+struct expression *expression_join(struct srcpos *loc,
+ struct expression *arg0,
+ struct expression *arg1);
/* Boot info (tree plus memreserve information */
diff --git a/expression.c b/expression.c
index 49bc8b0..8d6474b 100644
--- a/expression.c
+++ b/expression.c
@@ -380,3 +380,57 @@ struct expression *expression_incbin(struct srcpos *loc,
{
return expression_build(loc, &op_incbin, file, off, len);
}
+
+static struct expression_value op_eval_arraycell(struct expression *expr,
+ enum expr_type context)
+{
+ uint64_t cellval;
+ struct expression_value v = {
+ .type = EXPR_BYTESTRING,
+ };
+ int bits = expr->u.bits;
+
+ assert(expr->nargs == 1);
+ EVALUATE_INT(cellval, expr->arg[0]);
+
+ v.value.d = data_append_integer(empty_data, cellval, bits);
+ return v;
+}
+static struct operator op_arraycell = {
+ .name = "< >",
+ .evaluate = op_eval_arraycell,
+};
+struct expression *expression_arraycell(struct srcpos *loc, int bits,
+ struct expression *cell)
+{
+ struct expression *expr = expression_build(loc, &op_arraycell, cell);
+
+ expr->u.bits = bits;
+ return expr;
+}
+
+static struct expression_value op_eval_join(struct expression *expr,
+ enum expr_type context)
+{
+ struct data arg0, arg1;
+ struct expression_value v = {
+ .type = EXPR_BYTESTRING,
+ };
+
+ assert(expr->nargs == 2);
+ EVALUATE_BS(arg0, expr->arg[0]);
+ EVALUATE_BS(arg1, expr->arg[1]);
+
+ v.value.d = data_merge(arg0, arg1);
+ return v;
+}
+static struct operator op_join = {
+ .name = ",",
+ .evaluate = op_eval_join,
+};
+struct expression *expression_join(struct srcpos *loc,
+ struct expression *arg0,
+ struct expression *arg1)
+{
+ return expression_build(loc, &op_join, arg0, arg1);
+}
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 07/10] Implement labels within property values as bytestring expressions
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
This re-implements labels within property values as a form of bytestring
expression. The grammar gets a little hairy to handle the fact that
labels are allowed both at the beginning and end of property values without
introducing parser conflicts.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index fcc3b4d..bff22d9 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -93,6 +93,7 @@ static struct data expr_bytestring(struct expression *expr);
%type <expr> expr_incbin
%type <expr> expr_prim
+%type <expr> expr_prelabel
%type <expr> expr_unary
%type <expr> expr_mul
%type <expr> expr_add
@@ -105,6 +106,7 @@ static struct data expr_bytestring(struct expression *expr);
%type <expr> expr_and
%type <expr> expr_or
%type <expr> expr_conditional
+%type <expr> expr_postlabel
%type <expr> expr
%%
@@ -221,10 +223,6 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
- | propdata DT_LABEL
- {
- $$ = data_add_marker($1, LABEL, $2);
- }
;
propdataprefix:
@@ -236,10 +234,6 @@ propdataprefix:
{
$$ = $1;
}
- | propdataprefix DT_LABEL
- {
- $$ = data_add_marker($1, LABEL, $2);
- }
;
array:
@@ -338,7 +332,19 @@ expr_prim:
;
expr:
- expr_conditional
+ expr_postlabel
+ ;
+
+expr_postlabel:
+ expr_conditional
+ | expr_conditional DT_LABEL
+ {
+ struct data d = data_add_marker(empty_data, LABEL, $2);
+ struct expression *label;
+
+ label = expression_bytestring_constant(&@2, d);
+ $$ = expression_join(&@$, $1, label);
+ }
;
expr_conditional:
@@ -408,12 +414,24 @@ expr_mul:
;
expr_unary:
- expr_prim
+ expr_prelabel
| '-' expr_unary { $$ = UNOP(@$, negate, $2); }
| '~' expr_unary { $$ = UNOP(@$, bit_not, $2); }
| '!' expr_unary { $$ = UNOP(@$, logic_not, $2); }
;
+expr_prelabel:
+ expr_prim
+ | DT_LABEL expr_prelabel
+ {
+ struct data d = data_add_marker(empty_data, LABEL, $1);
+ struct expression *label;
+
+ label = expression_bytestring_constant(&@1, d);
+ $$ = expression_join(&@$, label, $2);
+ }
+ ;
+
bytestring_literal:
/* empty */
{
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 08/10] Implement path references in terms of bytestring expressions
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
This patch re-implements path references (&label which expands to the
referenced node's full path) in terms of the bytestring expression
infrastructure.
Internally this is implemented as a constant bytestring expression
containing nothing but the marker to insert the path reference later.
Logically it would be neater to have the expression itself expand directly
to the right value itself, but for now we're evaluating these expressions
before all the tree's paths have been constructed.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index bff22d9..7e1251d 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -219,10 +219,6 @@ propdata:
struct data d = expr_bytestring($2);
$$ = data_merge($1, d);
}
- | propdataprefix DT_REF
- {
- $$ = data_add_marker($1, REF_PATH, $2);
- }
;
propdataprefix:
@@ -349,6 +345,11 @@ expr_postlabel:
expr_conditional:
expr_or
+ | DT_REF
+ {
+ struct data d = data_add_marker(empty_data, REF_PATH, $1);
+ $$ = expression_bytestring_constant(&@$, d);
+ }
| expr_or '?' expr ':' expr_conditional
{
$$ = expression_conditional(&yylloc, $1, $3, $5);
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 09/10] Re-implement "," in property definitions as a bytestring operator
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
We've already introduced an internal "join" operator which appends
bytestring expressions together. This uses it to implement the "," syntax
in property values as expressions.
This is the last piece of property value syntax to be converted to use
the expression infrastructure, so all (non-empty) property values can now
be implemented as a single expression. For now we still just immediately
evaluate the expression though.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc-parser.y | 37 ++++++++++++++-----------------------
1 file changed, 14 insertions(+), 23 deletions(-)
diff --git a/dtc-parser.y b/dtc-parser.y
index 7e1251d..61cdf66 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -76,8 +76,6 @@ static struct data expr_bytestring(struct expression *expr);
%token <labelref> DT_REF
%token DT_INCBIN
-%type <data> propdata
-%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
%type <array> array
@@ -107,6 +105,7 @@ static struct data expr_bytestring(struct expression *expr);
%type <expr> expr_or
%type <expr> expr_conditional
%type <expr> expr_postlabel
+%type <expr> expr_join
%type <expr> expr
%%
@@ -194,9 +193,11 @@ proplist:
;
propdef:
- DT_PROPNODENAME '=' propdata ';'
+ DT_PROPNODENAME '=' expr ';'
{
- $$ = build_property($1, $3);
+ struct data d = expr_bytestring($3);
+
+ $$ = build_property($1, d);
}
| DT_PROPNODENAME ';'
{
@@ -213,25 +214,6 @@ propdef:
}
;
-propdata:
- propdataprefix expr
- {
- struct data d = expr_bytestring($2);
- $$ = data_merge($1, d);
- }
- ;
-
-propdataprefix:
- /* empty */
- {
- $$ = empty_data;
- }
- | propdata ','
- {
- $$ = $1;
- }
- ;
-
array:
arrayprefix '>' { $$ = $1; }
;
@@ -328,7 +310,15 @@ expr_prim:
;
expr:
+ expr_join
+ ;
+
+expr_join:
expr_postlabel
+ | expr_join ',' expr_postlabel
+ {
+ $$ = expression_join(&@$, $1, $3);
+ }
;
expr_postlabel:
@@ -343,6 +333,7 @@ expr_postlabel:
}
;
+
expr_conditional:
expr_or
| DT_REF
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 10/10] Implement string concatenate and repeat operators
From: David Gibson @ 2014-02-27 11:21 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ, David Gibson
In-Reply-To: <1393500099-28544-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
This patch exercises the new expression infrastructure to implement syntax
to concatenate and repeat strings. We use syntax inspired by Python,
with '+' overloaded for string concatenation and '*' overloaded for string
repeat. Normally we'd use C syntax to inspire dts syntax, but C has no
obvious candidates for these string operators.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
dtc.h | 4 ++
expression.c | 117 ++++++++++++++++++++++++++++++++++++++++++++-
tests/.gitignore | 1 +
tests/Makefile.tests | 2 +-
tests/run_tests.sh | 5 ++
tests/string-expressions.c | 97 +++++++++++++++++++++++++++++++++++++
6 files changed, 223 insertions(+), 3 deletions(-)
create mode 100644 tests/string-expressions.c
diff --git a/dtc.h b/dtc.h
index d270626..d3f8ad0 100644
--- a/dtc.h
+++ b/dtc.h
@@ -302,6 +302,10 @@ DEF_BINARY_OP(logic_and);
DEF_BINARY_OP(logic_or);
+struct expression *expression_concat(struct srcpos *pos,
+ struct expression *arg0,
+ struct expression *arg1);
+
struct expression *expression_conditional(struct srcpos *pos,
struct expression *,
struct expression *,
diff --git a/expression.c b/expression.c
index 8d6474b..2b86fed 100644
--- a/expression.c
+++ b/expression.c
@@ -294,9 +294,7 @@ INT_UNARY_OP(logic_not, !)
INT_BINARY_OP(mod, %)
INT_BINARY_OP(div, /)
-INT_BINARY_OP(mul, *)
-INT_BINARY_OP(add, +)
INT_BINARY_OP(sub, -)
INT_BINARY_OP(lshift, <<)
@@ -317,6 +315,121 @@ INT_BINARY_OP(bit_or, |)
INT_BINARY_OP(logic_and, &&)
INT_BINARY_OP(logic_or, ||)
+/*
+ * We need to write out add and mul in full, since they can be used on
+ * both integer and string arguments with different meanings
+ */
+
+static struct expression_value op_eval_mul(struct expression *expr,
+ enum expr_type context)
+{
+ struct expression_value arg0, arg1;
+ struct expression_value v;
+ uint64_t n, i;
+ struct data s;
+ struct data d = empty_data;
+
+ assert(expr->nargs == 2);
+ EVALUATE(arg0, expr->arg[0], EXPR_VOID);
+ EVALUATE(arg1, expr->arg[1], EXPR_VOID);
+
+ if ((arg0.type == EXPR_INTEGER) && (arg1.type == EXPR_INTEGER)) {
+ v.type = EXPR_INTEGER;
+ v.value.integer = arg0.value.integer * arg1.value.integer;
+ return v;
+ } else if ((arg0.type != EXPR_INTEGER) && (arg0.type != EXPR_STRING)) {
+ return type_error(expr->arg[0], "Expected integer or string"
+ " expression (found %s)",
+ expression_typename(arg0.type));
+ } else if (arg0.type == EXPR_INTEGER) {
+ if (arg1.type != EXPR_STRING)
+ return type_error(expr->arg[1], "Expected string"
+ " expression (found %s)",
+ expression_typename(arg1.type));
+ n = arg0.value.integer;
+ s = arg1.value.d;
+ } else {
+ assert(arg0.type == EXPR_STRING);
+ if (arg1.type != EXPR_INTEGER)
+ return type_error(expr->arg[1], "Expected integer"
+ " expression (found %s)",
+ expression_typename(arg1.type));
+ n = arg1.value.integer;
+ s = arg0.value.d;
+ }
+
+ for (i = 0; i < n; i++)
+ d = data_append_data(d, s.val, s.len - 1);
+
+ v.type = EXPR_STRING;
+ v.value.d = data_append_byte(d, 0); /* Terminating \0 */
+
+ return v;
+}
+static struct operator op_mul = {
+ .name = "*",
+ .evaluate = op_eval_mul,
+};
+struct expression *expression_mul(struct srcpos *loc,
+ struct expression *arg0,
+ struct expression *arg1)
+{
+ return expression_build(loc, &op_mul, arg0, arg1);
+}
+
+static struct expression_value op_eval_add(struct expression *expr,
+ enum expr_type context)
+{
+ struct expression_value arg0, arg1;
+ struct expression_value v;
+
+ assert(expr->nargs == 2);
+ EVALUATE(arg0, expr->arg[0], EXPR_VOID);
+ EVALUATE(arg1, expr->arg[1], EXPR_VOID);
+ if ((arg0.type != EXPR_INTEGER) && (arg0.type != EXPR_STRING))
+ return type_error(expr->arg[0], "Expected integer or string"
+ " expression (found %s)",
+ expression_typename(arg0.type));
+ if ((arg1.type != EXPR_INTEGER) && (arg1.type != EXPR_STRING))
+ return type_error(expr->arg[0], "Expected integer or string"
+ " expression (found %s)",
+ expression_typename(arg1.type));
+
+ if (arg0.type != arg1.type)
+ return type_error(expr, "Operand types to + (%s, %s) don't match",
+ expression_typename(arg0.type),
+ expression_typename(arg1.type));
+
+ v.type = arg0.type;
+
+ switch (v.type) {
+ case EXPR_INTEGER:
+ v.value.integer = arg0.value.integer + arg1.value.integer;
+ break;
+
+ case EXPR_STRING:
+ v.value.d = data_copy_mem(arg0.value.d.val,
+ arg0.value.d.len - 1);
+ v.value.d = data_append_data(v.value.d, arg1.value.d.val,
+ arg1.value.d.len);
+ break;
+
+ default:
+ assert(0);
+ }
+ return v;
+}
+static struct operator op_add = {
+ .name = "+",
+ .evaluate = op_eval_add,
+};
+struct expression *expression_add(struct srcpos *loc,
+ struct expression *arg0,
+ struct expression *arg1)
+{
+ return expression_build(loc, &op_add, arg0, arg1);
+}
+
static struct expression_value op_eval_conditional(struct expression *expr,
enum expr_type context)
{
diff --git a/tests/.gitignore b/tests/.gitignore
index bb5e33a..7931067 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -48,6 +48,7 @@ tmp.*
/setprop_inplace
/sized_cells
/string_escapes
+/string-expressions
/subnode_iterate
/subnode_offset
/supernode_atdepth_offset
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index dafb618..fa4e2d2 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -20,7 +20,7 @@ LIB_TESTS_L = get_mem_rsv \
dtb_reverse dtbs_equal_unordered \
add_subnode_with_nops path_offset_aliases \
utilfdt_test \
- integer-expressions \
+ integer-expressions string-expressions \
subnode_iterate
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 97e016b..44de059 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -446,6 +446,11 @@ dtc_tests () {
run_dtc_test -I dts -O dtb -o integer-expressions.test.dtb integer-expressions.test.dts
run_test integer-expressions integer-expressions.test.dtb
+ # Check string expresisons
+ run_test string-expressions -g string-expressions.test.dts
+ run_dtc_test -I dts -O dtb -o string-expressions.test.dtb string-expressions.test.dts
+ run_test string-expressions string-expressions.test.dtb
+
# Check for graceful failure in some error conditions
run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts
run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb
diff --git a/tests/string-expressions.c b/tests/string-expressions.c
new file mode 100644
index 0000000..da6854f
--- /dev/null
+++ b/tests/string-expressions.c
@@ -0,0 +1,97 @@
+/*
+ * Testcase for dtc string expression support
+ *
+ * Copyright (C) 2013 David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+struct test_expr {
+ const char *expr;
+ const char *result;
+} expr_table[] = {
+#define TE(expr, res) { #expr, (res) }
+ TE("hello", "hello"),
+ TE("hello " + "world", "hello world"),
+ TE("hello" + " " + "world", "hello world"),
+ TE("hello" * 2 + " world", "hellohello world"),
+ TE("hello " + 2 * "world", "hello worldworld"),
+ TE(("hello"), "hello"),
+ TE(0 ? "hello" : "goodbye", "goodbye"),
+ TE(1 ? "hello" : "goodbye", "hello"),
+};
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const char *res;
+ int reslen;
+ int i;
+
+ test_init(argc, argv);
+
+ if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) {
+ FILE *f = fopen(argv[2], "w");
+
+ if (!f)
+ FAIL("Couldn't open \"%s\" for output: %s\n",
+ argv[2], strerror(errno));
+
+ fprintf(f, "/dts-v1/;\n");
+ fprintf(f, "/ {\n");
+ for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+ fprintf(f, "\texpression-%d = %s;\n", i,
+ expr_table[i].expr);
+ fprintf(f, "};\n");
+ fclose(f);
+ } else {
+ fdt = load_blob_arg(argc, argv);
+
+ for (i = 0; i < ARRAY_SIZE(expr_table); i++) {
+ char propname[16];
+ int len = strlen(expr_table[i].result) + 1;
+
+ sprintf(propname, "expression-%d", i);
+ res = fdt_getprop(fdt, 0, propname, &reslen);
+
+ if (reslen != len)
+ FAIL("Incorrect length for expression %s,"
+ " %d instead of %d\n",
+ expr_table[i].expr, reslen, len);
+
+ if (memcmp(res, expr_table[i].result, len) != 0)
+ FAIL("Incorrect result for expression %s,"
+ " \"%s\" instead of \"%s\"\n",
+ expr_table[i].expr, res,
+ expr_table[i].result);
+ }
+ }
+
+ PASS();
+}
--
1.8.5.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [RFC PATCH v4 3/8] staging: imx-drm: Document updated imx-drm device tree bindings
From: Russell King - ARM Linux @ 2014-02-27 11:56 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: devel, devicetree, kernel, Greg Kroah-Hartman, dri-devel,
Grant Likely, linux-arm-kernel
In-Reply-To: <530F1C4C.2010504@ti.com>
On Thu, Feb 27, 2014 at 01:06:52PM +0200, Tomi Valkeinen wrote:
> On 25/02/14 16:23, Philipp Zabel wrote:
>
> > +Freescale i.MX DRM master device
> > +================================
> > +
> > +The freescale i.MX DRM master device is a virtual device needed to list all
> > +IPU or other display interface nodes that comprise the graphics subsystem.
> > +
> > +Required properties:
> > +- compatible: Should be "fsl,imx-drm"
> > +- ports: Should contain a list of phandles pointing to display interface ports
> > + of IPU devices
> > +
> > +example:
> > +
> > +imx-drm {
> > + compatible = "fsl,imx-drm";
> > + ports = <&ipu_di0>;
> > +};
>
> I'm not a fan of having non-hardware related things in the DT data.
> Especially if it makes direct references to our SW, in this case DRM.
> There's no DRM on the board. I wanted to avoid all that with OMAP
> display bindings.
>
> Is there even need for such a master device? You can find all the
> connected display devices from any single display device, by just
> following the endpoint links.
Please read up on what has been discussed over previous years:
http://lists.freedesktop.org/archives/dri-devel/2013-July/041159.html
and please, let's not endlessly rehash old discussions because someone
wasn't involved and has a different opinion, otherwise we're never going
to get anywhere.
Thanks.
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
^ permalink raw reply
* Re: [PATCH 1/4] ARM: STi: add stid127 soc support
From: Maxime Coquelin @ 2014-02-27 12:23 UTC (permalink / raw)
To: Patrice CHOTARD, Srinivas Kandagatla, Stuart Menefy, Russell King,
linux-arm-kernel, kernel, linux-kernel, Linus Walleij,
Grant Likely, Rob Herring, devicetree
Cc: Giuseppe Cavallaro, alexandre.torgue
In-Reply-To: <1391093744-19905-2-git-send-email-patrice.chotard@st.com>
Hi Patrice,
Could you add an overview documentation as it has been done for other
STi platforms?
See Documentation/arm/sti/stih416-overview.txt
Thanks,
Maxime
On 01/30/2014 03:55 PM, Patrice CHOTARD wrote:
> From: Alexandre TORGUE <alexandre.torgue@st.com>
>
> This patch adds support to STiD127 SoC.
> The main adaptation is the L2 cache way size compare to STiH41x SoCs.
>
> Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
> arch/arm/mach-sti/board-dt.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c
> index 1217fb5..be018a9 100644
> --- a/arch/arm/mach-sti/board-dt.c
> +++ b/arch/arm/mach-sti/board-dt.c
> @@ -9,6 +9,7 @@
>
> #include <linux/irq.h>
> #include <linux/of_platform.h>
> +#include <linux/of.h>
> #include <asm/hardware/cache-l2x0.h>
> #include <asm/mach/arch.h>
>
> @@ -18,6 +19,10 @@ void __init stih41x_l2x0_init(void)
> {
> u32 way_size = 0x4;
> u32 aux_ctrl;
> +
> + if (of_machine_is_compatible("st,stid127"))
> + way_size = 0x3;
> +
> /* may be this can be encoded in macros like BIT*() */
> aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
> (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
> @@ -36,6 +41,7 @@ static void __init stih41x_machine_init(void)
> static const char *stih41x_dt_match[] __initdata = {
> "st,stih415",
> "st,stih416",
> + "st,stid127",
> NULL
> };
>
>
^ permalink raw reply
* Re: [PATCH 1/4] ARM: STi: add stid127 soc support
From: Patrice Chotard @ 2014-02-27 12:27 UTC (permalink / raw)
To: Maxime Coquelin, Srinivas Kandagatla, Stuart Menefy, Russell King,
linux-arm-kernel, kernel, linux-kernel, Linus Walleij,
Grant Likely, Rob Herring, devicetree
Cc: Giuseppe Cavallaro, alexandre.torgue
In-Reply-To: <530F2E26.1040304@st.com>
Hi Maxime
Thanks for reviewing.
Yes for sure, i will add additional board informations.
Patrice
On 02/27/2014 01:23 PM, Maxime Coquelin wrote:
> Hi Patrice,
>
> Could you add an overview documentation as it has been done for other
> STi platforms?
>
> See Documentation/arm/sti/stih416-overview.txt
>
> Thanks,
> Maxime
>
> On 01/30/2014 03:55 PM, Patrice CHOTARD wrote:
>> From: Alexandre TORGUE <alexandre.torgue@st.com>
>>
>> This patch adds support to STiD127 SoC.
>> The main adaptation is the L2 cache way size compare to STiH41x SoCs.
>>
>> Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
>> ---
>> arch/arm/mach-sti/board-dt.c | 6 ++++++
>> 1 file changed, 6 insertions(+)
>>
>> diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c
>> index 1217fb5..be018a9 100644
>> --- a/arch/arm/mach-sti/board-dt.c
>> +++ b/arch/arm/mach-sti/board-dt.c
>> @@ -9,6 +9,7 @@
>>
>> #include <linux/irq.h>
>> #include <linux/of_platform.h>
>> +#include <linux/of.h>
>> #include <asm/hardware/cache-l2x0.h>
>> #include <asm/mach/arch.h>
>>
>> @@ -18,6 +19,10 @@ void __init stih41x_l2x0_init(void)
>> {
>> u32 way_size = 0x4;
>> u32 aux_ctrl;
>> +
>> + if (of_machine_is_compatible("st,stid127"))
>> + way_size = 0x3;
>> +
>> /* may be this can be encoded in macros like BIT*() */
>> aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
>> (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
>> @@ -36,6 +41,7 @@ static void __init stih41x_machine_init(void)
>> static const char *stih41x_dt_match[] __initdata = {
>> "st,stih415",
>> "st,stih416",
>> + "st,stid127",
>> NULL
>> };
>>
>>
^ permalink raw reply
* [PATCH] spi: sh-msiof: Remove "renesas,msiof-sh7724" from bindings
From: Geert Uytterhoeven @ 2014-02-27 12:47 UTC (permalink / raw)
To: Mark Brown
Cc: Laurent Pinchart, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-spi-u79uwXL29TY76Z2rM5mHXA, linux-sh-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
From: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
It's not implemented in the driver, so it's a bad example.
Signed-off-by: Geert Uytterhoeven <geert+renesas-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org>
---
Documentation/devicetree/bindings/spi/sh-msiof.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt
index 1f0cb33763a1..f24baf3b6cc1 100644
--- a/Documentation/devicetree/bindings/spi/sh-msiof.txt
+++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt
@@ -5,7 +5,6 @@ Required properties:
"renesas,sh-msiof" for SuperH, or
"renesas,sh-mobile-msiof" for SH Mobile series.
Examples with soctypes are:
- "renesas,msiof-sh7724" (SH)
"renesas,msiof-r8a7790" (R-Car H2)
"renesas,msiof-r8a7791" (R-Car M2)
- reg : Offset and length of the register set for the device
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH] phy-rcar-gen2-usb: add device tree support
From: Ben Dooks @ 2014-02-27 12:57 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: balbi, linux-usb, robh+dt, pawel.moll, mark.rutland,
ijc+devicetree, galak, grant.likely, devicetree, gregkh, linux-sh,
valentine.barshak, rob, linux-doc
In-Reply-To: <201402270312.51588.sergei.shtylyov@cogentembedded.com>
On 27/02/14 00:12, Sergei Shtylyov wrote:
> Add support of the device tree probing for the Renesas R-Car generation 2 SoCs
> documenting the device tree binding as necessary.
So what happened w.r.t to my last set of patches for this?
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
^ permalink raw reply
* Re: [RFC PATCH v4 3/8] staging: imx-drm: Document updated imx-drm device tree bindings
From: Russell King - ARM Linux @ 2014-02-27 13:00 UTC (permalink / raw)
To: Philipp Zabel
Cc: devel, devicetree, David Airlie, Greg Kroah-Hartman, dri-devel,
Tomi Valkeinen, kernel, Grant Likely, Shawn Guo, linux-arm-kernel
In-Reply-To: <1393506385.4507.49.camel@paszta.hi.pengutronix.de>
On Thu, Feb 27, 2014 at 02:06:25PM +0100, Philipp Zabel wrote:
> For the i.MX6 display subsystem there is no clear single master device,
> and the physical configuration changes across the SoC family. The
> i.MX6Q/i.MX6D SoCs have two separate display controller devices IPU1 and
> IPU2, with two output ports each.
Not also forgetting that there's another scenario too: you may wish
to drive IPU1 and IPU2 as two completely separate display subsystems
in some hardware, but as a combined display subsystem in others.
Here's another scenario. You may have these two IPUs on the SoC, but
there's only one display output. You want to leave the second IPU
disabled, as you wouldn't want it to be probed or even exposed to
userland.
On the face of it, the top-level super-device node doesn't look very
hardware-y, but it actually is - it's about how a board uses the
hardware provided. This is entirely in keeping with the spirit of DT,
which is to describe what hardware is present and how it's connected
together, whether it be at the chip or board level.
If this wasn't the case, we wouldn't even attempt to describe what devices
we have on which I2C buses - we'd just list the hardware on the board
without giving any information about how it's wired together.
This is no different - however, it doesn't have (and shouldn't) be
subsystem specific... but - and this is the challenge we then face - how
do you decide that on one board with a single zImage kernel, with both
DRM and fbdev built-in, whether to use the DRM interfaces or the fbdev
interfaces? We could have both matching the same compatible string, but
we'd also need some way to tell each other that they're not allowed to
bind.
Before anyone argues against "it isn't hardware-y", stop and think.
What if I design a board with two Epson LCD controllers on board and
put a muxing arrangement on their output. Is that one or two devices?
What if I want them to operate as one combined system? What if I have
two different LCD controllers on a board. How is this any different
from the two independent IPU hardware blocks integrated inside an iMX6
SoC with a muxing arrangement on their output?
It's very easy to look at a SoC and make the wrong decision...
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
^ permalink raw reply
* Re: [RFC PATCH v4 3/8] staging: imx-drm: Document updated imx-drm device tree bindings
From: Philipp Zabel @ 2014-02-27 13:06 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: devel, devicetree, Russell King - ARM Linux, David Airlie,
Greg Kroah-Hartman, dri-devel, kernel, Grant Likely, Shawn Guo,
linux-arm-kernel
In-Reply-To: <530F1C4C.2010504@ti.com>
Am Donnerstag, den 27.02.2014, 13:06 +0200 schrieb Tomi Valkeinen:
> On 25/02/14 16:23, Philipp Zabel wrote:
>
> > +Freescale i.MX DRM master device
> > +================================
> > +
> > +The freescale i.MX DRM master device is a virtual device needed to list all
> > +IPU or other display interface nodes that comprise the graphics subsystem.
> > +
> > +Required properties:
> > +- compatible: Should be "fsl,imx-drm"
> > +- ports: Should contain a list of phandles pointing to display interface ports
> > + of IPU devices
> > +
> > +example:
> > +
> > +imx-drm {
> > + compatible = "fsl,imx-drm";
> > + ports = <&ipu_di0>;
> > +};
>
> I'm not a fan of having non-hardware related things in the DT data.
> Especially if it makes direct references to our SW, in this case DRM.
> There's no DRM on the board. I wanted to avoid all that with OMAP
> display bindings.
>
> Is there even need for such a master device? You can find all the
> connected display devices from any single display device, by just
> following the endpoint links.
I don't particularly like this either, but it kind of has been decided.
For the i.MX6 display subsystem there is no clear single master device,
and the physical configuration changes across the SoC family. The
i.MX6Q/i.MX6D SoCs have two separate display controller devices IPU1 and
IPU2, with two output ports each. The i.MX6DL/i.MX6S SoCs only have one
IPU1, but it is accompanied by separate lower-power LCDIF display
controller with a single output. These may or may not be connected
indirectly across the encoder input multiplexers, so collecting them
would require scanning the whole device tree from an always-enabled
imx-drm platform device if we didn't have this node.
Also, we are free to just ignore this node in the future, if a better
way is found.
> > display@di0 {
> > compatible = "fsl,imx-parallel-display";
> > edid = [edid-data];
> > - crtc = <&ipu 0>;
> > interface-pix-fmt = "rgb24";
> > +
> > + port {
> > + display_in: endpoint {
> > + remote-endpoint = <&ipu_di0_disp0>;
> > + };
> > + };
> > };
>
> Shouldn't the pix-fmt be defined in the endpoint node? It is about pixel
> format for a particular endpoint, isn't it?
>
> > diff --git a/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt b/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
> > index ed93778..578a1fc 100644
> > --- a/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
> > +++ b/Documentation/devicetree/bindings/staging/imx-drm/ldb.txt
> > @@ -50,12 +50,14 @@ have a look at Documentation/devicetree/bindings/video/display-timing.txt.
> >
> > Required properties:
> > - reg : should be <0> or <1>
> > - - crtcs : a list of phandles with index pointing to the IPU display interfaces
> > - that can be used as video source for this channel.
> > - fsl,data-mapping : should be "spwg" or "jeida"
> > This describes how the color bits are laid out in the
> > serialized LVDS signal.
> > - fsl,data-width : should be <18> or <24>
> > + - port: A port node with endpoint definitions as defined in
> > + Documentation/devicetree/bindings/media/video-interfaces.txt.
> > + On i.MX6, there should be four ports (port@[0-3]) that correspond
> > + to the four LVDS multiplexer inputs.
>
> Is the ldb something that's on the imx SoC?
Yes. It consists of two LVDS encoders. On i.MX5 each channel is
connected to one display interface of the single IPU.
On i.MX6Q its parallel input can be connected to any of the four IPU1/2
display interfaces using a 4-port multiplexer (and on i.MX6DL it can be
connected to IPU1 or LCDIF).
> Do you have a public branch somewhere? It'd be easier to look at the
> final result, as I'm not familiar with imx.
Not yet, I will prepare a branch with the next version.
regards
Philipp
^ permalink raw reply
* [PATCH v2 0/4] [RFC] Support for creating generic host_bridge from device tree
From: Liviu Dudau @ 2014-02-27 13:06 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Catalin Marinas, Will Deacon,
linaro-kernel
Cc: LKML, devicetree@vger.kernel.org, LAKML
This is v2 of my attempt to add support for a generic pci_host_bridge controller created
from a description passed in the device tree.
Changes from v1:
- Add patch to fix conversion of IO ranges into IO resources.
- Added a domain_nr member to pci_host_bridge structure, and a new function
to create a root bus in a given domain number. In order to facilitate that
I propose changing the order of initialisation between pci_host_bridge and
it's related bus in pci_create_root_bus() as sort of a rever of 7b5436635800.
This is done in patch 1/4 and 2/4.
- Added a simple allocator of domain numbers in drivers/pci/host-bridge.c. The
code will first try to get a domain id from of_alias_get_id(..., "pci-domain")
and if that fails assign the next unallocated domain id.
- Changed the name of the function that creates the generic host bridge from
pci_host_bridge_of_init to of_create_pci_host_bridge and exported as GPL symbol.
v1 thread here: https://lkml.org/lkml/2014/2/3/380
The following is an edit of the original blurb:
Following the discussion started here [1], I now have a proposal for tackling
generic support for host bridges described via device tree. It is an initial
stab at it, to try to get feedback and suggestions, but it is functional enough
that I have PCI Express for arm64 working on an FPGA using the patch that I am
also publishing that adds support for PCI for that platform.
Looking at the existing architectures that fit the requirements (use of device
tree and PCI) yields the powerpc and microblaze as generic enough to make them
candidates for conversion. I have a tentative patch for microblaze that I can
only compile test it, unfortunately using qemu-microblaze leads to an early
crash in the kernel.
As Bjorn has mentioned in the previous discussion, the idea is to add to
struct pci_host_bridge enough data to be able to reduce the size or remove the
architecture specific pci_controller structure. arm64 support actually manages
to get rid of all the architecture static data and has no pci_controller structure
defined. For host bridge drivers that means a change of API unless architectures
decide to provide a compatibility layer (comments here please).
In order to initialise a host bridge with the new API, the following example
code is sufficient for a _probe() function:
static int myhostbridge_probe(struct platform_device *pdev)
{
int err;
struct device_node *dev;
struct pci_host_bridge *bridge;
struct myhostbridge_port *pp;
resource_size_t lastbus;
dev = pdev->dev.of_node;
if (!of_device_is_available(dev)) {
pr_warn("%s: disabled\n", dev->full_name);
return -ENODEV;
}
pp = kzalloc(sizeof(struct myhostbridge_port), GFP_KERNEL);
if (!pp)
return -ENOMEM;
bridge = of_create_pci_host_bridge(&pdev->dev, &myhostbridge_ops, pp);
if (!bridge) {
err = -EINVAL;
goto bridge_init_fail;
}
err = myhostbridge_setup(bridge->bus);
if (err)
goto bridge_init_fail;
/* We always enable PCI domains and we keep domain 0 backward
* compatible in /proc for video cards
*/
pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);
lastbus = pci_scan_child_bus(bridge->bus);
pci_bus_update_busn_res_end(bridge->bus, lastbus);
pci_assign_unassigned_bus_resources(bridge->bus);
pci_bus_add_devices(bridge->bus);
return 0;
bridge_init_fail:
kfree(pp);
return err;
}
[1] http://thread.gmane.org/gmane.linux.kernel.pci/25946
Best regards,
Liviu
Liviu Dudau (4):
pci: OF: Fix the conversion of IO ranges into IO resources.
pci: Create pci_host_bridge before its associated bus in pci_create_root_bus.
pci: Introduce a domain number for pci_host_bridge.
pci: Add support for creating a generic host_bridge from device tree
drivers/of/address.c | 31 +++++++++++
drivers/pci/host-bridge.c | 134 +++++++++++++++++++++++++++++++++++++++++++++
drivers/pci/probe.c | 66 ++++++++++++++--------
include/linux/of_address.h | 13 +----
include/linux/pci.h | 17 ++++++
5 files changed, 227 insertions(+), 34 deletions(-)
--
1.9.0
^ permalink raw reply
* [PATCH v2 1/4] pci: OF: Fix the conversion of IO ranges into IO resources.
From: Liviu Dudau @ 2014-02-27 13:06 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Catalin Marinas, Will Deacon,
linaro-kernel
Cc: LKML, devicetree@vger.kernel.org, LAKML
In-Reply-To: <1393506402-11474-1-git-send-email-Liviu.Dudau@arm.com>
The ranges property for a host bridge controller in DT describes
the mapping between the PCI bus address and the CPU physical address.
The resources framework however expects that the IO resources start
at a pseudo "port" address 0 (zero) and have a maximum size of 64kb.
The conversion from pci ranges to resources failed to take that into
account.
In the process move the function into drivers/of/address.c as it
now depends on pci_address_to_pio() code.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 1a54f1f..7cf2b16 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -719,3 +719,34 @@ void __iomem *of_iomap(struct device_node *np, int index)
return ioremap(res.start, resource_size(&res));
}
EXPORT_SYMBOL(of_iomap);
+
+/**
+ * of_pci_range_to_resource - Create a resource from an of_pci_range
+ * @range: the PCI range that describes the resource
+ * @np: device node where the range belongs to
+ * @res: pointer to a valid resource that will be updated to
+ * reflect the values contained in the range.
+ * Note that if the range is an IO range, the resource will be converted
+ * using pci_address_to_pio() which can fail if it is called to early or
+ * if the range cannot be matched to any host bridge IO space.
+ */
+void of_pci_range_to_resource(struct of_pci_range *range,
+ struct device_node *np, struct resource *res)
+{
+ res->flags = range->flags;
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long port;
+ port = pci_address_to_pio(range->pci_addr);
+ if (port == (unsigned long)-1) {
+ res->start = (resource_size_t)OF_BAD_ADDR;
+ res->end = (resource_size_t)OF_BAD_ADDR;
+ return;
+ }
+ res->start = port;
+ } else {
+ res->start = range->cpu_addr;
+ }
+ res->end = res->start + range->size - 1;
+ res->parent = res->child = res->sibling = NULL;
+ res->name = np->full_name;
+}
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 5f6ed6b..a667762 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -23,17 +23,8 @@ struct of_pci_range {
#define for_each_of_pci_range(parser, range) \
for (; of_pci_range_parser_one(parser, range);)
-static inline void of_pci_range_to_resource(struct of_pci_range *range,
- struct device_node *np,
- struct resource *res)
-{
- res->flags = range->flags;
- res->start = range->cpu_addr;
- res->end = range->cpu_addr + range->size - 1;
- res->parent = res->child = res->sibling = NULL;
- res->name = np->full_name;
-}
-
+extern void of_pci_range_to_resource(struct of_pci_range *range,
+ struct device_node *np, struct resource *res);
/* Translate a DMA address from device space to CPU space */
extern u64 of_translate_dma_address(struct device_node *dev,
const __be32 *in_addr);
--
1.9.0
^ permalink raw reply related
* [PATCH v2 2/4] pci: Create pci_host_bridge before its associated bus in pci_create_root_bus.
From: Liviu Dudau @ 2014-02-27 13:06 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Catalin Marinas, Will Deacon,
linaro-kernel
Cc: devicetree@vger.kernel.org, LKML, LAKML
In-Reply-To: <1393506402-11474-1-git-send-email-Liviu.Dudau@arm.com>
Before commit 7b5436635800 the pci_host_bridge was created before the root bus.
As that commit has added a needless dependency on the bus for pci_alloc_host_bridge()
the creation order has been changed for no good reason. Revert the order of
creation as we are going to depend on the pci_host_bridge structure to retrieve the
domain number of the root bus.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6e34498..78ccba0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -505,7 +505,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
kfree(bridge);
}
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+static struct pci_host_bridge *pci_alloc_host_bridge(void)
{
struct pci_host_bridge *bridge;
@@ -514,7 +514,6 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
return NULL;
INIT_LIST_HEAD(&bridge->windows);
- bridge->bus = b;
return bridge;
}
@@ -1727,9 +1726,21 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
char bus_addr[64];
char *fmt;
+ bridge = pci_alloc_host_bridge();
+ if (!bridge)
+ return NULL;
+
+ bridge->dev.parent = parent;
+ bridge->dev.release = pci_release_host_bridge_dev;
+ error = pcibios_root_bridge_prepare(bridge);
+ if (error) {
+ kfree(bridge);
+ return NULL;
+ }
+
b = pci_alloc_bus();
if (!b)
- return NULL;
+ goto err_out;
b->sysdata = sysdata;
b->ops = ops;
@@ -1738,26 +1749,15 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
dev_dbg(&b2->dev, "bus already known\n");
- goto err_out;
+ goto err_bus_out;
}
- bridge = pci_alloc_host_bridge(b);
- if (!bridge)
- goto err_out;
-
- bridge->dev.parent = parent;
- bridge->dev.release = pci_release_host_bridge_dev;
+ bridge->bus = b;
dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
- error = pcibios_root_bridge_prepare(bridge);
- if (error) {
- kfree(bridge);
- goto err_out;
- }
-
error = device_register(&bridge->dev);
if (error) {
put_device(&bridge->dev);
- goto err_out;
+ goto err_bus_out;
}
b->bridge = get_device(&bridge->dev);
device_enable_async_suspend(b->bridge);
@@ -1814,8 +1814,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
class_dev_reg_err:
put_device(&bridge->dev);
device_unregister(&bridge->dev);
-err_out:
+err_bus_out:
kfree(b);
+err_out:
+ kfree(bridge);
return NULL;
}
--
1.9.0
^ permalink raw reply related
* [PATCH v2 3/4] pci: Introduce a domain number for pci_host_bridge.
From: Liviu Dudau @ 2014-02-27 13:06 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Catalin Marinas, Will Deacon,
linaro-kernel
Cc: devicetree@vger.kernel.org, LKML, LAKML
In-Reply-To: <1393506402-11474-1-git-send-email-Liviu.Dudau@arm.com>
Make it easier to discover the domain number of a bus by storing
the number in pci_host_bridge for the root bus. Several architectures
have their own way of storing this information, so it makes sense
to try to unify the code. While at this, add a new function that
creates a root bus in a given domain and make pci_create_root_bus()
a wrapper around this function.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 78ccba0..1b2f45c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1714,8 +1714,9 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
{
}
-struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *pci_create_root_bus_in_domain(struct device *parent,
+ int domain, int bus, struct pci_ops *ops, void *sysdata,
+ struct list_head *resources)
{
int error;
struct pci_host_bridge *bridge;
@@ -1732,6 +1733,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
bridge->dev.parent = parent;
bridge->dev.release = pci_release_host_bridge_dev;
+ bridge->domain_nr = domain;
error = pcibios_root_bridge_prepare(bridge);
if (error) {
kfree(bridge);
@@ -1745,7 +1747,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b->sysdata = sysdata;
b->ops = ops;
b->number = b->busn_res.start = bus;
- b2 = pci_find_bus(pci_domain_nr(b), bus);
+ b2 = pci_find_bus(bridge->domain_nr, bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
dev_dbg(&b2->dev, "bus already known\n");
@@ -1753,7 +1755,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
}
bridge->bus = b;
- dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ dev_set_name(&bridge->dev, "pci%04x:%02x", bridge->domain_nr, bus);
error = device_register(&bridge->dev);
if (error) {
put_device(&bridge->dev);
@@ -1768,7 +1770,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
b->dev.class = &pcibus_class;
b->dev.parent = b->bridge;
- dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+ dev_set_name(&b->dev, "%04x:%02x", bridge->domain_nr, bus);
error = device_register(&b->dev);
if (error)
goto class_dev_reg_err;
@@ -1821,6 +1823,22 @@ err_out:
return NULL;
}
+struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+ int domain_nr;
+ struct pci_bus *b = pci_alloc_bus();
+ if (!b)
+ return NULL;
+
+ b->sysdata = sysdata;
+ domain_nr = pci_domain_nr(b);
+ kfree(b);
+
+ return pci_create_root_bus_in_domain(parent, domain_nr, bus,
+ ops, sysdata, resources);
+}
+
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
{
struct resource *res = &b->busn_res;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33aa2ca..1eed009 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -394,6 +394,7 @@ struct pci_host_bridge_window {
struct pci_host_bridge {
struct device dev;
struct pci_bus *bus; /* root bus */
+ int domain_nr;
struct list_head windows; /* pci_host_bridge_windows */
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
@@ -747,6 +748,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
+struct pci_bus *pci_create_root_bus_in_domain(struct device *parent,
+ int domain, int bus, struct pci_ops *ops,
+ void *sysdata, struct list_head *resources);
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
void pci_bus_release_busn_res(struct pci_bus *b);
--
1.9.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox