* [PATCH 1/2] qe: add function qe_clock_source
From: Timur Tabi @ 2007-10-10 22:12 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: Timur Tabi
Add function qe_clock_source() which takes a string containing the name of a
QE clock source (as is typically found in device trees) and returns the
matching enum qe_clock value.
Update booting-without-of.txt to indicate that the UCC properties rx-clock
and tx-clock are deprecated and replaced with rx-clock-name and tx-clock-name,
which use strings instead of numbers to indicate QE clock sources.
Update qe_setbrg() to take an enum qe_clock instead of an integer as its
first paramter.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch applies to Kumar's for-2.6.24 branch.
arch/powerpc/sysdev/qe_lib/qe.c | 13 +++--
include/asm-powerpc/qe.h | 98 +++++++++++++++++++--------------------
2 files changed, 56 insertions(+), 55 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 3ccd360..8551e74 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -167,7 +167,7 @@ unsigned int get_brg_clk(void)
/* Program the BRG to the given sampling rate and multiplier
*
- * @brg: the BRG, 1-16
+ * @brg: the BRG, QE_BRG1 - QE_BRG16
* @rate: the desired sampling rate
* @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
* GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
@@ -175,11 +175,14 @@ unsigned int get_brg_clk(void)
*
* Also note that the value programmed into the BRGC register must be even.
*/
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
+void qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
{
u32 divisor, tempval;
u32 div16 = 0;
+ if ((brg < QE_BRG1) || (brg > QE_BRG16))
+ return;
+
divisor = get_brg_clk() / (rate * multiplier);
if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
@@ -196,7 +199,7 @@ void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
QE_BRGC_ENABLE | div16;
- out_be32(&qe_immr->brg.brgc[brg - 1], tempval);
+ out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
}
/* Convert a string to a QE clock source enum
@@ -214,7 +217,7 @@ enum qe_clock qe_clock_source(const char *source)
if (strncasecmp(source, "brg", 3) == 0) {
i = simple_strtoul(source + 3, NULL, 10);
if ((i >= 1) && (i <= 16))
- return QE_BRG1 + i - 1;
+ return (QE_BRG1 - 1) + i;
else
return QE_CLK_DUMMY;
}
@@ -222,7 +225,7 @@ enum qe_clock qe_clock_source(const char *source)
if (strncasecmp(source, "clk", 3) == 0) {
i = simple_strtoul(source + 3, NULL, 10);
if ((i >= 1) && (i <= 24))
- return QE_CLK1 + i - 1;
+ return (QE_CLK1 - 1) + i;
else
return QE_CLK_DUMMY;
}
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 7d53750..81403ee 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -28,6 +28,52 @@
#define MEM_PART_SECONDARY 1
#define MEM_PART_MURAM 2
+/* Clocks and BRGs */
+enum qe_clock {
+ QE_CLK_NONE = 0,
+ QE_BRG1, /* Baud Rate Generator 1 */
+ QE_BRG2, /* Baud Rate Generator 2 */
+ QE_BRG3, /* Baud Rate Generator 3 */
+ QE_BRG4, /* Baud Rate Generator 4 */
+ QE_BRG5, /* Baud Rate Generator 5 */
+ QE_BRG6, /* Baud Rate Generator 6 */
+ QE_BRG7, /* Baud Rate Generator 7 */
+ QE_BRG8, /* Baud Rate Generator 8 */
+ QE_BRG9, /* Baud Rate Generator 9 */
+ QE_BRG10, /* Baud Rate Generator 10 */
+ QE_BRG11, /* Baud Rate Generator 11 */
+ QE_BRG12, /* Baud Rate Generator 12 */
+ QE_BRG13, /* Baud Rate Generator 13 */
+ QE_BRG14, /* Baud Rate Generator 14 */
+ QE_BRG15, /* Baud Rate Generator 15 */
+ QE_BRG16, /* Baud Rate Generator 16 */
+ QE_CLK1, /* Clock 1 */
+ QE_CLK2, /* Clock 2 */
+ QE_CLK3, /* Clock 3 */
+ QE_CLK4, /* Clock 4 */
+ QE_CLK5, /* Clock 5 */
+ QE_CLK6, /* Clock 6 */
+ QE_CLK7, /* Clock 7 */
+ QE_CLK8, /* Clock 8 */
+ QE_CLK9, /* Clock 9 */
+ QE_CLK10, /* Clock 10 */
+ QE_CLK11, /* Clock 11 */
+ QE_CLK12, /* Clock 12 */
+ QE_CLK13, /* Clock 13 */
+ QE_CLK14, /* Clock 14 */
+ QE_CLK15, /* Clock 15 */
+ QE_CLK16, /* Clock 16 */
+ QE_CLK17, /* Clock 17 */
+ QE_CLK18, /* Clock 18 */
+ QE_CLK19, /* Clock 19 */
+ QE_CLK20, /* Clock 20 */
+ QE_CLK21, /* Clock 21 */
+ QE_CLK22, /* Clock 22 */
+ QE_CLK23, /* Clock 23 */
+ QE_CLK24, /* Clock 24 */
+ QE_CLK_DUMMY
+};
+
/* Export QE common operations */
extern void qe_reset(void);
extern int par_io_init(struct device_node *np);
@@ -38,7 +84,8 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
/* QE internal API */
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier);
+enum qe_clock qe_clock_source(const char *source);
+void qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
int qe_get_snum(void);
void qe_put_snum(u8 snum);
unsigned long qe_muram_alloc(int size, int align);
@@ -129,55 +176,6 @@ enum comm_dir {
COMM_DIR_RX_AND_TX = 3
};
-/* Clocks and BRGs */
-enum qe_clock {
- QE_CLK_NONE = 0,
- QE_BRG1, /* Baud Rate Generator 1 */
- QE_BRG2, /* Baud Rate Generator 2 */
- QE_BRG3, /* Baud Rate Generator 3 */
- QE_BRG4, /* Baud Rate Generator 4 */
- QE_BRG5, /* Baud Rate Generator 5 */
- QE_BRG6, /* Baud Rate Generator 6 */
- QE_BRG7, /* Baud Rate Generator 7 */
- QE_BRG8, /* Baud Rate Generator 8 */
- QE_BRG9, /* Baud Rate Generator 9 */
- QE_BRG10, /* Baud Rate Generator 10 */
- QE_BRG11, /* Baud Rate Generator 11 */
- QE_BRG12, /* Baud Rate Generator 12 */
- QE_BRG13, /* Baud Rate Generator 13 */
- QE_BRG14, /* Baud Rate Generator 14 */
- QE_BRG15, /* Baud Rate Generator 15 */
- QE_BRG16, /* Baud Rate Generator 16 */
- QE_CLK1, /* Clock 1 */
- QE_CLK2, /* Clock 2 */
- QE_CLK3, /* Clock 3 */
- QE_CLK4, /* Clock 4 */
- QE_CLK5, /* Clock 5 */
- QE_CLK6, /* Clock 6 */
- QE_CLK7, /* Clock 7 */
- QE_CLK8, /* Clock 8 */
- QE_CLK9, /* Clock 9 */
- QE_CLK10, /* Clock 10 */
- QE_CLK11, /* Clock 11 */
- QE_CLK12, /* Clock 12 */
- QE_CLK13, /* Clock 13 */
- QE_CLK14, /* Clock 14 */
- QE_CLK15, /* Clock 15 */
- QE_CLK16, /* Clock 16 */
- QE_CLK17, /* Clock 17 */
- QE_CLK18, /* Clock 18 */
- QE_CLK19, /* Clock 19 */
- QE_CLK20, /* Clock 20 */
- QE_CLK21, /* Clock 21 */
- QE_CLK22, /* Clock 22 */
- QE_CLK23, /* Clock 23 */
- QE_CLK24, /* Clock 24 */
- QE_CLK_DUMMY
-};
-
-/* Convert a string to a QE clock source enum */
-enum qe_clock qe_clock_source(const char *source);
-
/* QE CMXUCR Registers.
* There are two UCCs represented in each of the four CMXUCR registers.
* These values are for the UCC in the LSBs
--
1.5.2.4
^ permalink raw reply related
* [PATCH 0/2] QE clock source improvements
From: Timur Tabi @ 2007-10-10 22:18 UTC (permalink / raw)
To: galak, linuxppc-dev, netdev
This patch set adds a new property to make specifying QE clock sources
easier, adds a function to help parse the property, updates some other
functions to use an enum instead of an integer, and updates the ucc_geth
driver to take advantage of all this.
^ permalink raw reply
* [PATCH 2/2] ucc_geth: use rx-clock-name and tx-clock-name device tree properties
From: Timur Tabi @ 2007-10-10 22:18 UTC (permalink / raw)
To: galak, linuxppc-dev, netdev; +Cc: Timur Tabi
In-Reply-To: <11920547093580-git-send-email-timur@freescale.com>
This patch updates the ucc_geth device driver to check the new rx-clock-name
and tx-clock-name properties first. If present, it uses the new function
qe_clock_source() to obtain the clock source. Otherwise, it checks the
deprecated rx-clock and tx-clock properties.
The device trees for 832x, 836x, and 8568 have been updated to contain the
new property names only.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch applies to Kumar's for-2.6.24 branch, on top of my other patch titled
"qe: add function qe_clock_source".
arch/powerpc/boot/dts/mpc832x_mds.dts | 8 ++++----
arch/powerpc/boot/dts/mpc832x_rdb.dts | 8 ++++----
arch/powerpc/boot/dts/mpc836x_mds.dts | 8 ++++----
arch/powerpc/boot/dts/mpc8568mds.dts | 8 ++++----
drivers/net/ucc_geth.c | 12 +++++-------
5 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index fcd333c..b57485b 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -217,8 +217,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <19>;
- tx-clock = <1a>;
+ rx-clock-name = "clk9";
+ tx-clock-name = "clk10";
phy-handle = < &phy3 >;
pio-handle = < &pio3 >;
};
@@ -238,8 +238,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <17>;
- tx-clock = <18>;
+ rx-clock-name = "clk7";
+ tx-clock-name = "clk8";
phy-handle = < &phy4 >;
pio-handle = < &pio4 >;
};
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 388c8a7..e68a08b 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -202,8 +202,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <20>;
- tx-clock = <13>;
+ rx-clock-name = "clk16";
+ tx-clock-name = "clk3";
phy-handle = <&phy00>;
pio-handle = <&ucc2pio>;
};
@@ -223,8 +223,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <19>;
- tx-clock = <1a>;
+ rx-clock-name = "clk9";
+ tx-clock-name = "clk10";
phy-handle = <&phy04>;
pio-handle = <&ucc3pio>;
};
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index fbd1573..7a54072 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -245,8 +245,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <19>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk9";
phy-handle = < &phy0 >;
phy-connection-type = "rgmii-id";
pio-handle = < &pio1 >;
@@ -267,8 +267,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <14>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk4";
phy-handle = < &phy1 >;
phy-connection-type = "rgmii-id";
pio-handle = < &pio2 >;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 5439437..cf45aab 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -333,8 +333,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <20>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk16";
pio-handle = <&pio1>;
phy-handle = <&phy0>;
phy-connection-type = "rgmii-id";
@@ -355,8 +355,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <20>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk16";
pio-handle = <&pio2>;
phy-handle = <&phy1>;
phy-connection-type = "rgmii-id";
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index a147d6e..9308397 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3863,7 +3863,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
sprop = of_get_property(np, "rx-clock-name", NULL);
if (sprop) {
ug_info->uf_info.rx_clock = qe_clock_source(sprop);
- if ((ug_info->uf_info.rx_clock < QE_CLK1) ||
+ if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) ||
(ug_info->uf_info.rx_clock > QE_CLK24)) {
printk(KERN_ERR
"ucc_geth: invalid rx-clock-name property\n");
@@ -3873,12 +3873,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
prop = of_get_property(np, "rx-clock", NULL);
if (!prop) {
/* If both rx-clock-name and rx-clock are missing,
- we want to tell people to use rx-clock-name. */
+ we want to tell people to use rx-clock-name. */
printk(KERN_ERR
"ucc_geth: missing rx-clock-name property\n");
return -EINVAL;
}
- if ((*prop < QE_CLK1) || (*prop > QE_CLK24)) {
+ if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
printk(KERN_ERR
"ucc_geth: invalid rx-clock propperty\n");
return -EINVAL;
@@ -3889,7 +3889,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
sprop = of_get_property(np, "tx-clock-name", NULL);
if (sprop) {
ug_info->uf_info.tx_clock = qe_clock_source(sprop);
- if ((ug_info->uf_info.tx_clock < QE_CLK1) ||
+ if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) ||
(ug_info->uf_info.tx_clock > QE_CLK24)) {
printk(KERN_ERR
"ucc_geth: invalid tx-clock-name property\n");
@@ -3902,7 +3902,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
"ucc_geth: mising tx-clock-name property\n");
return -EINVAL;
}
- if ((*prop < QE_CLK1) || (*prop > QE_CLK24)) {
+ if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
printk(KERN_ERR
"ucc_geth: invalid tx-clock property\n");
return -EINVAL;
@@ -3910,8 +3910,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ug_info->uf_info.tx_clock = *prop;
}
- prop = of_get_property(np, "tx-clock", NULL);
- ug_info->uf_info.tx_clock = *prop;
err = of_address_to_resource(np, 0, &res);
if (err)
return -EINVAL;
--
1.5.2.4
^ permalink raw reply related
* [PATCH 1/2] qe: add function qe_clock_source
From: Timur Tabi @ 2007-10-10 22:18 UTC (permalink / raw)
To: galak, linuxppc-dev, netdev; +Cc: Timur Tabi
In-Reply-To: <1192054708946-git-send-email-timur@freescale.com>
Add function qe_clock_source() which takes a string containing the name of a
QE clock source (as is typically found in device trees) and returns the
matching enum qe_clock value.
Update booting-without-of.txt to indicate that the UCC properties rx-clock
and tx-clock are deprecated and replaced with rx-clock-name and tx-clock-name,
which use strings instead of numbers to indicate QE clock sources.
Update qe_setbrg() to take an enum qe_clock instead of an integer as its
first paramter.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch applies to Kumar's for-2.6.24 branch.
arch/powerpc/sysdev/qe_lib/qe.c | 13 +++--
include/asm-powerpc/qe.h | 98 +++++++++++++++++++--------------------
2 files changed, 56 insertions(+), 55 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 3ccd360..8551e74 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -167,7 +167,7 @@ unsigned int get_brg_clk(void)
/* Program the BRG to the given sampling rate and multiplier
*
- * @brg: the BRG, 1-16
+ * @brg: the BRG, QE_BRG1 - QE_BRG16
* @rate: the desired sampling rate
* @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
* GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
@@ -175,11 +175,14 @@ unsigned int get_brg_clk(void)
*
* Also note that the value programmed into the BRGC register must be even.
*/
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
+void qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
{
u32 divisor, tempval;
u32 div16 = 0;
+ if ((brg < QE_BRG1) || (brg > QE_BRG16))
+ return;
+
divisor = get_brg_clk() / (rate * multiplier);
if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
@@ -196,7 +199,7 @@ void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
QE_BRGC_ENABLE | div16;
- out_be32(&qe_immr->brg.brgc[brg - 1], tempval);
+ out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
}
/* Convert a string to a QE clock source enum
@@ -214,7 +217,7 @@ enum qe_clock qe_clock_source(const char *source)
if (strncasecmp(source, "brg", 3) == 0) {
i = simple_strtoul(source + 3, NULL, 10);
if ((i >= 1) && (i <= 16))
- return QE_BRG1 + i - 1;
+ return (QE_BRG1 - 1) + i;
else
return QE_CLK_DUMMY;
}
@@ -222,7 +225,7 @@ enum qe_clock qe_clock_source(const char *source)
if (strncasecmp(source, "clk", 3) == 0) {
i = simple_strtoul(source + 3, NULL, 10);
if ((i >= 1) && (i <= 24))
- return QE_CLK1 + i - 1;
+ return (QE_CLK1 - 1) + i;
else
return QE_CLK_DUMMY;
}
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 7d53750..81403ee 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -28,6 +28,52 @@
#define MEM_PART_SECONDARY 1
#define MEM_PART_MURAM 2
+/* Clocks and BRGs */
+enum qe_clock {
+ QE_CLK_NONE = 0,
+ QE_BRG1, /* Baud Rate Generator 1 */
+ QE_BRG2, /* Baud Rate Generator 2 */
+ QE_BRG3, /* Baud Rate Generator 3 */
+ QE_BRG4, /* Baud Rate Generator 4 */
+ QE_BRG5, /* Baud Rate Generator 5 */
+ QE_BRG6, /* Baud Rate Generator 6 */
+ QE_BRG7, /* Baud Rate Generator 7 */
+ QE_BRG8, /* Baud Rate Generator 8 */
+ QE_BRG9, /* Baud Rate Generator 9 */
+ QE_BRG10, /* Baud Rate Generator 10 */
+ QE_BRG11, /* Baud Rate Generator 11 */
+ QE_BRG12, /* Baud Rate Generator 12 */
+ QE_BRG13, /* Baud Rate Generator 13 */
+ QE_BRG14, /* Baud Rate Generator 14 */
+ QE_BRG15, /* Baud Rate Generator 15 */
+ QE_BRG16, /* Baud Rate Generator 16 */
+ QE_CLK1, /* Clock 1 */
+ QE_CLK2, /* Clock 2 */
+ QE_CLK3, /* Clock 3 */
+ QE_CLK4, /* Clock 4 */
+ QE_CLK5, /* Clock 5 */
+ QE_CLK6, /* Clock 6 */
+ QE_CLK7, /* Clock 7 */
+ QE_CLK8, /* Clock 8 */
+ QE_CLK9, /* Clock 9 */
+ QE_CLK10, /* Clock 10 */
+ QE_CLK11, /* Clock 11 */
+ QE_CLK12, /* Clock 12 */
+ QE_CLK13, /* Clock 13 */
+ QE_CLK14, /* Clock 14 */
+ QE_CLK15, /* Clock 15 */
+ QE_CLK16, /* Clock 16 */
+ QE_CLK17, /* Clock 17 */
+ QE_CLK18, /* Clock 18 */
+ QE_CLK19, /* Clock 19 */
+ QE_CLK20, /* Clock 20 */
+ QE_CLK21, /* Clock 21 */
+ QE_CLK22, /* Clock 22 */
+ QE_CLK23, /* Clock 23 */
+ QE_CLK24, /* Clock 24 */
+ QE_CLK_DUMMY
+};
+
/* Export QE common operations */
extern void qe_reset(void);
extern int par_io_init(struct device_node *np);
@@ -38,7 +84,8 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
/* QE internal API */
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier);
+enum qe_clock qe_clock_source(const char *source);
+void qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
int qe_get_snum(void);
void qe_put_snum(u8 snum);
unsigned long qe_muram_alloc(int size, int align);
@@ -129,55 +176,6 @@ enum comm_dir {
COMM_DIR_RX_AND_TX = 3
};
-/* Clocks and BRGs */
-enum qe_clock {
- QE_CLK_NONE = 0,
- QE_BRG1, /* Baud Rate Generator 1 */
- QE_BRG2, /* Baud Rate Generator 2 */
- QE_BRG3, /* Baud Rate Generator 3 */
- QE_BRG4, /* Baud Rate Generator 4 */
- QE_BRG5, /* Baud Rate Generator 5 */
- QE_BRG6, /* Baud Rate Generator 6 */
- QE_BRG7, /* Baud Rate Generator 7 */
- QE_BRG8, /* Baud Rate Generator 8 */
- QE_BRG9, /* Baud Rate Generator 9 */
- QE_BRG10, /* Baud Rate Generator 10 */
- QE_BRG11, /* Baud Rate Generator 11 */
- QE_BRG12, /* Baud Rate Generator 12 */
- QE_BRG13, /* Baud Rate Generator 13 */
- QE_BRG14, /* Baud Rate Generator 14 */
- QE_BRG15, /* Baud Rate Generator 15 */
- QE_BRG16, /* Baud Rate Generator 16 */
- QE_CLK1, /* Clock 1 */
- QE_CLK2, /* Clock 2 */
- QE_CLK3, /* Clock 3 */
- QE_CLK4, /* Clock 4 */
- QE_CLK5, /* Clock 5 */
- QE_CLK6, /* Clock 6 */
- QE_CLK7, /* Clock 7 */
- QE_CLK8, /* Clock 8 */
- QE_CLK9, /* Clock 9 */
- QE_CLK10, /* Clock 10 */
- QE_CLK11, /* Clock 11 */
- QE_CLK12, /* Clock 12 */
- QE_CLK13, /* Clock 13 */
- QE_CLK14, /* Clock 14 */
- QE_CLK15, /* Clock 15 */
- QE_CLK16, /* Clock 16 */
- QE_CLK17, /* Clock 17 */
- QE_CLK18, /* Clock 18 */
- QE_CLK19, /* Clock 19 */
- QE_CLK20, /* Clock 20 */
- QE_CLK21, /* Clock 21 */
- QE_CLK22, /* Clock 22 */
- QE_CLK23, /* Clock 23 */
- QE_CLK24, /* Clock 24 */
- QE_CLK_DUMMY
-};
-
-/* Convert a string to a QE clock source enum */
-enum qe_clock qe_clock_source(const char *source);
-
/* QE CMXUCR Registers.
* There are two UCCs represented in each of the four CMXUCR registers.
* These values are for the UCC in the LSBs
--
1.5.2.4
^ permalink raw reply related
* Re: [PATCH 0/2] QE clock source improvements
From: Timur Tabi @ 2007-10-10 22:31 UTC (permalink / raw)
To: Timur Tabi; +Cc: linuxppc-dev, netdev
In-Reply-To: <1192054708946-git-send-email-timur@freescale.com>
Sorry, please ignore this set. Something got screwed up with the patches.
I'm going to resend.
Timur Tabi wrote:
> This patch set adds a new property to make specifying QE clock sources
> easier, adds a function to help parse the property, updates some other
> functions to use an enum instead of an integer, and updates the ucc_geth
> driver to take advantage of all this.
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* [PATCH 0/2] QE clock source improvements
From: Timur Tabi @ 2007-10-10 22:37 UTC (permalink / raw)
To: galak, linuxppc-dev, netdev
(Replaces all previous versions of this patch)
This patch set adds a new property to make specifying QE clock sources
easier, adds a function to help parse the property, updates some other
functions to use an enum instead of an integer, and updates the ucc_geth
driver to take advantage of all this.
^ permalink raw reply
* [PATCH 1/2] qe: add function qe_clock_source
From: Timur Tabi @ 2007-10-10 22:37 UTC (permalink / raw)
To: galak, linuxppc-dev, netdev; +Cc: Timur Tabi
In-Reply-To: <11920558283326-git-send-email-timur@freescale.com>
Add function qe_clock_source() which takes a string containing the name of a
QE clock source (as is typically found in device trees) and returns the
matching enum qe_clock value.
Update booting-without-of.txt to indicate that the UCC properties rx-clock
and tx-clock are deprecated and replaced with rx-clock-name and tx-clock-name,
which use strings instead of numbers to indicate QE clock sources.
Update qe_setbrg() to take an enum qe_clock instead of an integer as its
first paramter.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch applies to Kumar's for-2.6.24 branch.
Documentation/powerpc/booting-without-of.txt | 13 ++++
arch/powerpc/sysdev/qe_lib/qe.c | 41 ++++++++++-
include/asm-powerpc/qe.h | 95 +++++++++++++-------------
3 files changed, 99 insertions(+), 50 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 7a6c5f2..d8306ee 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1615,6 +1615,19 @@ platforms are moved over to use the flattened-device-tree model.
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
- pio-handle : The phandle for the Parallel I/O port configuration.
+ - rx-clock-name: the UCC receive clock source
+ "none": clock source is disabled
+ "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+ "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+ - tx-clock-name: the UCC transmit clock source
+ "none": clock source is disabled
+ "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+ "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+ The following two properties are deprecated. rx-clock has been replaced
+ with rx-clock-name, and tx-clock has been replaced with tx-clock-name.
+ Drivers that currently use the deprecated properties should continue to
+ do so, in order to support older device trees, but they should be updated
+ to check for the new properties first.
- rx-clock : represents the UCC receive clock source.
0x00 : clock source is disabled;
0x1~0x10 : clock source is BRG1~BRG16 respectively;
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 3d57d38..8551e74 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -167,7 +167,7 @@ unsigned int get_brg_clk(void)
/* Program the BRG to the given sampling rate and multiplier
*
- * @brg: the BRG, 1-16
+ * @brg: the BRG, QE_BRG1 - QE_BRG16
* @rate: the desired sampling rate
* @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
* GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
@@ -175,11 +175,14 @@ unsigned int get_brg_clk(void)
*
* Also note that the value programmed into the BRGC register must be even.
*/
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
+void qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
{
u32 divisor, tempval;
u32 div16 = 0;
+ if ((brg < QE_BRG1) || (brg > QE_BRG16))
+ return;
+
divisor = get_brg_clk() / (rate * multiplier);
if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
@@ -196,8 +199,40 @@ void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
QE_BRGC_ENABLE | div16;
- out_be32(&qe_immr->brg.brgc[brg - 1], tempval);
+ out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
+}
+
+/* Convert a string to a QE clock source enum
+ *
+ * This function takes a string, typically from a property in the device
+ * tree, and returns the corresponding "enum qe_clock" value.
+*/
+enum qe_clock qe_clock_source(const char *source)
+{
+ unsigned int i;
+
+ if (strcasecmp(source, "none") == 0)
+ return QE_CLK_NONE;
+
+ if (strncasecmp(source, "brg", 3) == 0) {
+ i = simple_strtoul(source + 3, NULL, 10);
+ if ((i >= 1) && (i <= 16))
+ return (QE_BRG1 - 1) + i;
+ else
+ return QE_CLK_DUMMY;
+ }
+
+ if (strncasecmp(source, "clk", 3) == 0) {
+ i = simple_strtoul(source + 3, NULL, 10);
+ if ((i >= 1) && (i <= 24))
+ return (QE_CLK1 - 1) + i;
+ else
+ return QE_CLK_DUMMY;
+ }
+
+ return QE_CLK_DUMMY;
}
+EXPORT_SYMBOL(qe_clock_source);
/* Initialize SNUMs (thread serial numbers) according to
* QE Module Control chapter, SNUM table
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 0dabe46..81403ee 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -28,6 +28,52 @@
#define MEM_PART_SECONDARY 1
#define MEM_PART_MURAM 2
+/* Clocks and BRGs */
+enum qe_clock {
+ QE_CLK_NONE = 0,
+ QE_BRG1, /* Baud Rate Generator 1 */
+ QE_BRG2, /* Baud Rate Generator 2 */
+ QE_BRG3, /* Baud Rate Generator 3 */
+ QE_BRG4, /* Baud Rate Generator 4 */
+ QE_BRG5, /* Baud Rate Generator 5 */
+ QE_BRG6, /* Baud Rate Generator 6 */
+ QE_BRG7, /* Baud Rate Generator 7 */
+ QE_BRG8, /* Baud Rate Generator 8 */
+ QE_BRG9, /* Baud Rate Generator 9 */
+ QE_BRG10, /* Baud Rate Generator 10 */
+ QE_BRG11, /* Baud Rate Generator 11 */
+ QE_BRG12, /* Baud Rate Generator 12 */
+ QE_BRG13, /* Baud Rate Generator 13 */
+ QE_BRG14, /* Baud Rate Generator 14 */
+ QE_BRG15, /* Baud Rate Generator 15 */
+ QE_BRG16, /* Baud Rate Generator 16 */
+ QE_CLK1, /* Clock 1 */
+ QE_CLK2, /* Clock 2 */
+ QE_CLK3, /* Clock 3 */
+ QE_CLK4, /* Clock 4 */
+ QE_CLK5, /* Clock 5 */
+ QE_CLK6, /* Clock 6 */
+ QE_CLK7, /* Clock 7 */
+ QE_CLK8, /* Clock 8 */
+ QE_CLK9, /* Clock 9 */
+ QE_CLK10, /* Clock 10 */
+ QE_CLK11, /* Clock 11 */
+ QE_CLK12, /* Clock 12 */
+ QE_CLK13, /* Clock 13 */
+ QE_CLK14, /* Clock 14 */
+ QE_CLK15, /* Clock 15 */
+ QE_CLK16, /* Clock 16 */
+ QE_CLK17, /* Clock 17 */
+ QE_CLK18, /* Clock 18 */
+ QE_CLK19, /* Clock 19 */
+ QE_CLK20, /* Clock 20 */
+ QE_CLK21, /* Clock 21 */
+ QE_CLK22, /* Clock 22 */
+ QE_CLK23, /* Clock 23 */
+ QE_CLK24, /* Clock 24 */
+ QE_CLK_DUMMY
+};
+
/* Export QE common operations */
extern void qe_reset(void);
extern int par_io_init(struct device_node *np);
@@ -38,7 +84,8 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
/* QE internal API */
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier);
+enum qe_clock qe_clock_source(const char *source);
+void qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
int qe_get_snum(void);
void qe_put_snum(u8 snum);
unsigned long qe_muram_alloc(int size, int align);
@@ -129,52 +176,6 @@ enum comm_dir {
COMM_DIR_RX_AND_TX = 3
};
-/* Clocks and BRGs */
-enum qe_clock {
- QE_CLK_NONE = 0,
- QE_BRG1, /* Baud Rate Generator 1 */
- QE_BRG2, /* Baud Rate Generator 2 */
- QE_BRG3, /* Baud Rate Generator 3 */
- QE_BRG4, /* Baud Rate Generator 4 */
- QE_BRG5, /* Baud Rate Generator 5 */
- QE_BRG6, /* Baud Rate Generator 6 */
- QE_BRG7, /* Baud Rate Generator 7 */
- QE_BRG8, /* Baud Rate Generator 8 */
- QE_BRG9, /* Baud Rate Generator 9 */
- QE_BRG10, /* Baud Rate Generator 10 */
- QE_BRG11, /* Baud Rate Generator 11 */
- QE_BRG12, /* Baud Rate Generator 12 */
- QE_BRG13, /* Baud Rate Generator 13 */
- QE_BRG14, /* Baud Rate Generator 14 */
- QE_BRG15, /* Baud Rate Generator 15 */
- QE_BRG16, /* Baud Rate Generator 16 */
- QE_CLK1, /* Clock 1 */
- QE_CLK2, /* Clock 2 */
- QE_CLK3, /* Clock 3 */
- QE_CLK4, /* Clock 4 */
- QE_CLK5, /* Clock 5 */
- QE_CLK6, /* Clock 6 */
- QE_CLK7, /* Clock 7 */
- QE_CLK8, /* Clock 8 */
- QE_CLK9, /* Clock 9 */
- QE_CLK10, /* Clock 10 */
- QE_CLK11, /* Clock 11 */
- QE_CLK12, /* Clock 12 */
- QE_CLK13, /* Clock 13 */
- QE_CLK14, /* Clock 14 */
- QE_CLK15, /* Clock 15 */
- QE_CLK16, /* Clock 16 */
- QE_CLK17, /* Clock 17 */
- QE_CLK18, /* Clock 18 */
- QE_CLK19, /* Clock 19 */
- QE_CLK20, /* Clock 20 */
- QE_CLK21, /* Clock 21 */
- QE_CLK22, /* Clock 22 */
- QE_CLK23, /* Clock 23 */
- QE_CLK24, /* Clock 24 */
- QE_CLK_DUMMY,
-};
-
/* QE CMXUCR Registers.
* There are two UCCs represented in each of the four CMXUCR registers.
* These values are for the UCC in the LSBs
--
1.5.2.4
^ permalink raw reply related
* [PATCH 2/2] ucc_geth: use rx-clock-name and tx-clock-name device tree properties
From: Timur Tabi @ 2007-10-10 22:37 UTC (permalink / raw)
To: galak, linuxppc-dev, netdev; +Cc: Timur Tabi
In-Reply-To: <11920558291655-git-send-email-timur@freescale.com>
This patch updates the ucc_geth device driver to check the new rx-clock-name
and tx-clock-name properties first. If present, it uses the new function
qe_clock_source() to obtain the clock source. Otherwise, it checks the
deprecated rx-clock and tx-clock properties.
The device trees for 832x, 836x, and 8568 have been updated to contain the
new property names only.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch applies to Kumar's for-2.6.24 branch, on top of my other patch titled
"qe: add function qe_clock_source".
arch/powerpc/boot/dts/mpc832x_mds.dts | 8 ++--
arch/powerpc/boot/dts/mpc832x_rdb.dts | 8 ++--
arch/powerpc/boot/dts/mpc836x_mds.dts | 8 ++--
arch/powerpc/boot/dts/mpc8568mds.dts | 8 ++--
drivers/net/ucc_geth.c | 55 ++++++++++++++++++++++++++++++--
5 files changed, 67 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index fcd333c..b57485b 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -217,8 +217,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <19>;
- tx-clock = <1a>;
+ rx-clock-name = "clk9";
+ tx-clock-name = "clk10";
phy-handle = < &phy3 >;
pio-handle = < &pio3 >;
};
@@ -238,8 +238,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <17>;
- tx-clock = <18>;
+ rx-clock-name = "clk7";
+ tx-clock-name = "clk8";
phy-handle = < &phy4 >;
pio-handle = < &pio4 >;
};
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 388c8a7..e68a08b 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -202,8 +202,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <20>;
- tx-clock = <13>;
+ rx-clock-name = "clk16";
+ tx-clock-name = "clk3";
phy-handle = <&phy00>;
pio-handle = <&ucc2pio>;
};
@@ -223,8 +223,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <19>;
- tx-clock = <1a>;
+ rx-clock-name = "clk9";
+ tx-clock-name = "clk10";
phy-handle = <&phy04>;
pio-handle = <&ucc3pio>;
};
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index fbd1573..7a54072 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -245,8 +245,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <19>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk9";
phy-handle = < &phy0 >;
phy-connection-type = "rgmii-id";
pio-handle = < &pio1 >;
@@ -267,8 +267,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <14>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk4";
phy-handle = < &phy1 >;
phy-connection-type = "rgmii-id";
pio-handle = < &pio2 >;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 5439437..cf45aab 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -333,8 +333,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <20>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk16";
pio-handle = <&pio1>;
phy-handle = <&phy0>;
phy-connection-type = "rgmii-id";
@@ -355,8 +355,8 @@
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
- rx-clock = <0>;
- tx-clock = <20>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk16";
pio-handle = <&pio2>;
phy-handle = <&phy1>;
phy-connection-type = "rgmii-id";
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 7dedc96..9308397 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3827,6 +3827,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
int err, ucc_num, max_speed = 0;
const phandle *ph;
const unsigned int *prop;
+ const char *sprop;
const void *mac_addr;
phy_interface_t phy_interface;
static const int enet_to_speed[] = {
@@ -3859,10 +3860,56 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ug_info->uf_info.ucc_num = ucc_num;
- prop = of_get_property(np, "rx-clock", NULL);
- ug_info->uf_info.rx_clock = *prop;
- prop = of_get_property(np, "tx-clock", NULL);
- ug_info->uf_info.tx_clock = *prop;
+ sprop = of_get_property(np, "rx-clock-name", NULL);
+ if (sprop) {
+ ug_info->uf_info.rx_clock = qe_clock_source(sprop);
+ if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) ||
+ (ug_info->uf_info.rx_clock > QE_CLK24)) {
+ printk(KERN_ERR
+ "ucc_geth: invalid rx-clock-name property\n");
+ return -EINVAL;
+ }
+ } else {
+ prop = of_get_property(np, "rx-clock", NULL);
+ if (!prop) {
+ /* If both rx-clock-name and rx-clock are missing,
+ we want to tell people to use rx-clock-name. */
+ printk(KERN_ERR
+ "ucc_geth: missing rx-clock-name property\n");
+ return -EINVAL;
+ }
+ if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
+ printk(KERN_ERR
+ "ucc_geth: invalid rx-clock propperty\n");
+ return -EINVAL;
+ }
+ ug_info->uf_info.rx_clock = *prop;
+ }
+
+ sprop = of_get_property(np, "tx-clock-name", NULL);
+ if (sprop) {
+ ug_info->uf_info.tx_clock = qe_clock_source(sprop);
+ if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) ||
+ (ug_info->uf_info.tx_clock > QE_CLK24)) {
+ printk(KERN_ERR
+ "ucc_geth: invalid tx-clock-name property\n");
+ return -EINVAL;
+ }
+ } else {
+ prop = of_get_property(np, "rx-clock", NULL);
+ if (!prop) {
+ printk(KERN_ERR
+ "ucc_geth: mising tx-clock-name property\n");
+ return -EINVAL;
+ }
+ if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
+ printk(KERN_ERR
+ "ucc_geth: invalid tx-clock property\n");
+ return -EINVAL;
+ }
+ ug_info->uf_info.tx_clock = *prop;
+ }
+
err = of_address_to_resource(np, 0, &res);
if (err)
return -EINVAL;
--
1.5.2.4
^ permalink raw reply related
* Re: Hard hang in hypervisor!?
From: Paul Mackerras @ 2007-10-11 0:04 UTC (permalink / raw)
To: Linas Vepstas; +Cc: linuxppc-dev, Nathan Lynch
In-Reply-To: <20071009212810.GN4350@austin.ibm.com>
Linas Vepstas writes:
> Err .. it was cpu 0 that was spinlocked. Are interrupts not
> distributed?
We have some bogosities in the xics code that I noticed a couple of
days ago. Basically we only set the xics to distribute interrupts to
all cpus if (a) the affinity mask is equal to CPU_MASK_ALL (which has
ones in every bit position from 0 to NR_CPUS-1) and (b) all present
cpus are online (cpu_online_map == cpu_present_map). Otherwise we
direct interrupts to the first cpu in the affinity map. So you can
easily have the affinity mask containing all the online cpus and still
not get distributed interrupts.
So in your case it's quite possible that all interrupts were directed
to cpu 0.
Paul.
^ permalink raw reply
* Re: Build failure on treeboot-walnut.cg
From: Paul Mackerras @ 2007-10-11 0:12 UTC (permalink / raw)
To: Timur Tabi; +Cc: linuxppc-dev, David Gibson
In-Reply-To: <470BA6ED.3020504@freescale.com>
Timur Tabi writes:
> Is this a new policy? Modules in the kernel are not built unless you want
> them. Even in arch/powerpc/platforms, only the specific platform file I'm
> targeting is built. So I don't really understand why you claim it's normal
> for platform-specific files to be built, regardless of the actual platform.
The wrapper script is intended to be a standalone tool which is
independent of the kernel configuration, and can be used separately
from the kernel build process.
> And frankly, I don't like this "policy". Build bugs for 4xx should not
> interfere in my 83xx development. I can't build any kernels now because of
> this bug!
I'm sure you're not actually that helpless. :) Just carry a patch to
arch/powerpc/boot/Makefile in your local tree.
Paul.
^ permalink raw reply
* Re: [PATCH 3/9] add Freescale SerDes PHY support
From: Stephen Rothwell @ 2007-10-11 0:59 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, paulus
In-Reply-To: <1192010804-20071-3-git-send-email-leoli@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 303 bytes --]
On Wed, 10 Oct 2007 18:06:38 +0800 Li Yang <leoli@freescale.com> wrote:
>
> +++ b/arch/powerpc/sysdev/fsl_serdes.c
>
> +#include <asm/prom.h>
You actually want linux/of.h not asm/prom.h
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 4/9] add platform support for MPC837x MDS board
From: Stephen Rothwell @ 2007-10-11 1:05 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev, paulus
In-Reply-To: <1192010804-20071-4-git-send-email-leoli@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 372 bytes --]
On Wed, 10 Oct 2007 18:06:39 +0800 Li Yang <leoli@freescale.com> wrote:
>
> +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
>
> +#include <asm/of_platform.h>
You actually neeed linux/of.h (for of_ routines) and asm/prom.h (for
of_flat_dt_is_compatible).
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] Bootwrapper: Enable debug info on boot wrapper
From: David Gibson @ 2007-10-11 1:34 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40710101256q3783994dr854e2bdecddf9820@mail.gmail.com>
On Wed, Oct 10, 2007 at 01:56:05PM -0600, Grant Likely wrote:
> Any comments on this one? Scott? David?
Seems reasonable AFAICT.
> On 10/3/07, Grant Likely <grant.likely@secretlab.ca> wrote:
> > From: Grant Likely <grant.likely@secretlab.ca>
> >
> > Add '-g' to BOOTCFLAGS if CONFIG_DEBUG_INFO is set.
> >
> > Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> > ---
> >
> > arch/powerpc/boot/Makefile | 4 ++++
> > 1 files changed, 4 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
> > index cf80db3..9dfe79b 100644
> > --- a/arch/powerpc/boot/Makefile
> > +++ b/arch/powerpc/boot/Makefile
> > @@ -25,6 +25,10 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
> > -isystem $(shell $(CROSS32CC) -print-file-name=include)
> > BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
> >
> > +ifdef CONFIG_DEBUG_INFO
> > +BOOTCFLAGS += -g
> > +endif
> > +
> > ifeq ($(call cc-option-yn, -fstack-protector),y)
> > BOOTCFLAGS += -fno-stack-protector
> > endif
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-dev
> >
>
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] Device tree bindings for Xilinx devices
From: David Gibson @ 2007-10-11 1:38 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <1192048682.5534.92.camel@localhost.localdomain>
On Wed, Oct 10, 2007 at 03:38:02PM -0500, Josh Boyer wrote:
> On Mon, 2007-10-08 at 01:53 -0600, Grant Likely wrote:
> > From: Grant Likely <grant.likely@secretlab.ca>
> >
> > Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> > ---
> >
> > This is a first draft, please review and comment.
>
> I'll start off with the fact that I hardly consider myself a DT expert,
> so take what I say with a grain of salt.
>
> > On a side node, I think booting-without-of.txt could get really unwieldly
> > in the near future. Perhaps the device tree bindings should be organized
> > differently and separated from the functional description of device tree
> > usage. Thoughts?
> >
> > Cheers,
> > g.
> >
> > Documentation/powerpc/booting-without-of.txt | 58 ++++++++++++++++++++++++++
> > 1 files changed, 58 insertions(+), 0 deletions(-)
> >
> > diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
> > index 20e0e6c..a6d6056 100644
> > --- a/Documentation/powerpc/booting-without-of.txt
> > +++ b/Documentation/powerpc/booting-without-of.txt
> > @@ -1850,6 +1850,64 @@ platforms are moved over to use the flattened-device-tree model.
> >
> > More devices will be defined as this spec matures.
> >
> > + l) Xilinx ML300 Framebuffer
> > +
> > + Simple framebuffer device from the ML300 reference design (also on the
> > + ML403 reference design as well as others).
> > +
> > + Required properties:
> > + - compatible : Must include "xilinx,ml300-fb"
>
> Similarly, "xilinx,ml403-fb" will be required for ML403 correct? Or do
> they share exact identical implementations?
>
> > + - reg : offset and length of the framebuffer register set
> > +
> > + Optional properties:
> > + - resolution : <xres yres> pixel resolution of framebuffer. Some
> > + implementations use a different resolution. Default
> > + is <d#640 d#480>
> > + - virt-resolution : <xvirt yvirt> Size of framebuffer in memory.
> > + Default is <d#1024 d#480>.
> > + - rotate-display : rotate display 180 degrees.
> > + - display-number : Logical number of display
> > +
> > + m) Xilinx SystemACE
> > +
> > + The Xilinx SystemACE device is used to program FPGAs from an FPGA
> > + bitstream stored on a CF card. It can also be used as a generic CF
> > + interface device.
> > +
> > + Required properties:
> > + - compatible : Must include "xilinx,sysace"
> > + - reg : offset and length of SystemACE register set
> > +
> > + Recommended properties:
> > + - interrupt-parent, interrupts : Connection of device irq signal.
> > +
> > + Optional properties:
> > + - number : logical number of the SystemACE device based at 0.
>
> "number" seems a bit to generic to me. logical-number seems a bit more
> descriptive.
We've used 'cell-index' for similar purposes on other 4xx.
>
> > + - 8-bit (empty) : Set this property if the SystemACE must be in 8 bit mode
> > +
> > + n) Xilinx EMAC and Xilinx TEMAC
> > +
> > + Xilinx Ethernet devices. Uses common properties from other Ethernet
> > + devices with the following constraints:
> > +
> > + Required properties:
> > + - compatible : Must include one of: "xilinx,plb-temac",
> > + "xilinx,plb-emac", "xilinx-opb-emac"
>
> I think you mean "xilinx,opb-emac" on that last one.
>
> > + - dma-mode : Must be one of "none", "simple", "sg" (sg == scatter gather)
> > +
> > + o) Xilinx Uartlite
> > +
> > + Xilinx uartlite devices are simple fixed speed serial ports. Uartlite
> > + ports should be described in a node with the following properties.
> > +
> > + Requred properties:
> > + - compatible : Must include "xilinx,uartlite"
> > + - reg : offset and length of uartlite register set
> > +
> > + Recommended properties:
> > + - port-number : logical port number of uartlite device based at 0.
> > + - interrupt-parent, interrupts : Connection of device irq signal.
> > +
>
> josh
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] Device tree bindings for Xilinx devices
From: Grant Likely @ 2007-10-11 2:25 UTC (permalink / raw)
To: Josh Boyer, Grant Likely, linuxppc-dev
In-Reply-To: <20071011013817.GB14873@localhost.localdomain>
On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> On Wed, Oct 10, 2007 at 03:38:02PM -0500, Josh Boyer wrote:
> > On Mon, 2007-10-08 at 01:53 -0600, Grant Likely wrote:
> > > From: Grant Likely <grant.likely@secretlab.ca>
> > >
> > > Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> > > ---
> > >
> > > This is a first draft, please review and comment.
> >
> > I'll start off with the fact that I hardly consider myself a DT expert,
> > so take what I say with a grain of salt.
> >
> > > On a side node, I think booting-without-of.txt could get really unwieldly
> > > in the near future. Perhaps the device tree bindings should be organized
> > > differently and separated from the functional description of device tree
> > > usage. Thoughts?
> > >
> > > Cheers,
> > > g.
> > >
> > > Documentation/powerpc/booting-without-of.txt | 58 ++++++++++++++++++++++++++
> > > 1 files changed, 58 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
> > > index 20e0e6c..a6d6056 100644
> > > --- a/Documentation/powerpc/booting-without-of.txt
> > > +++ b/Documentation/powerpc/booting-without-of.txt
> > > @@ -1850,6 +1850,64 @@ platforms are moved over to use the flattened-device-tree model.
> > >
> > > More devices will be defined as this spec matures.
> > >
> > > + l) Xilinx ML300 Framebuffer
> > > +
> > > + Simple framebuffer device from the ML300 reference design (also on the
> > > + ML403 reference design as well as others).
> > > +
> > > + Required properties:
> > > + - compatible : Must include "xilinx,ml300-fb"
> >
> > Similarly, "xilinx,ml403-fb" will be required for ML403 correct? Or do
> > they share exact identical implementations?
> >
> > > + - reg : offset and length of the framebuffer register set
> > > +
> > > + Optional properties:
> > > + - resolution : <xres yres> pixel resolution of framebuffer. Some
> > > + implementations use a different resolution. Default
> > > + is <d#640 d#480>
> > > + - virt-resolution : <xvirt yvirt> Size of framebuffer in memory.
> > > + Default is <d#1024 d#480>.
> > > + - rotate-display : rotate display 180 degrees.
> > > + - display-number : Logical number of display
> > > +
> > > + m) Xilinx SystemACE
> > > +
> > > + The Xilinx SystemACE device is used to program FPGAs from an FPGA
> > > + bitstream stored on a CF card. It can also be used as a generic CF
> > > + interface device.
> > > +
> > > + Required properties:
> > > + - compatible : Must include "xilinx,sysace"
> > > + - reg : offset and length of SystemACE register set
> > > +
> > > + Recommended properties:
> > > + - interrupt-parent, interrupts : Connection of device irq signal.
> > > +
> > > + Optional properties:
> > > + - number : logical number of the SystemACE device based at 0.
> >
> > "number" seems a bit to generic to me. logical-number seems a bit more
> > descriptive.
>
> We've used 'cell-index' for similar purposes on other 4xx.
Unfortunately, 'cell' has been used in the sense of a logic cell in an
SoC. In the case of the SystemACE, it is an external chip.
What about "device-number"?
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Re: [PATCH] Device tree bindings for Xilinx devices
From: David Gibson @ 2007-10-11 4:06 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40710101925x6b005aa7paaeb072ba492c81f@mail.gmail.com>
On Wed, Oct 10, 2007 at 08:25:36PM -0600, Grant Likely wrote:
> On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> > On Wed, Oct 10, 2007 at 03:38:02PM -0500, Josh Boyer wrote:
[snip]
> > > "number" seems a bit to generic to me. logical-number seems a bit more
> > > descriptive.
> >
> > We've used 'cell-index' for similar purposes on other 4xx.
>
> Unfortunately, 'cell' has been used in the sense of a logic cell in an
> SoC. In the case of the SystemACE, it is an external chip.
>
> What about "device-number"?
Ok, I misunderstood. If it's not on chip, what significance does this
serial number have? Where would a driver need it?
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] Device tree bindings for Xilinx devices
From: Grant Likely @ 2007-10-11 4:18 UTC (permalink / raw)
To: Grant Likely, Josh Boyer, linuxppc-dev
In-Reply-To: <20071011040622.GE14873@localhost.localdomain>
On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> On Wed, Oct 10, 2007 at 08:25:36PM -0600, Grant Likely wrote:
> > On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> > > We've used 'cell-index' for similar purposes on other 4xx.
> >
> > Unfortunately, 'cell' has been used in the sense of a logic cell in an
> > SoC. In the case of the SystemACE, it is an external chip.
> >
> > What about "device-number"?
>
> Ok, I misunderstood. If it's not on chip, what significance does this
> serial number have? Where would a driver need it?
If there were 2 systemace devices on board; one attached to a CF slot
labeled "1" and the other to one labeled "2". :-) Same problem as
lining up serial device files to physical port numbers.
The driver doesn't technically need it, but the information does need
to flow through to the creation of logically numbered device files.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Re: [PATCH] Device tree bindings for Xilinx devices
From: David Gibson @ 2007-10-11 4:24 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40710102118p3e62d06eqff8db252772eb58c@mail.gmail.com>
On Wed, Oct 10, 2007 at 10:18:50PM -0600, Grant Likely wrote:
> On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> > On Wed, Oct 10, 2007 at 08:25:36PM -0600, Grant Likely wrote:
> > > On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> > > > We've used 'cell-index' for similar purposes on other 4xx.
> > >
> > > Unfortunately, 'cell' has been used in the sense of a logic cell in an
> > > SoC. In the case of the SystemACE, it is an external chip.
> > >
> > > What about "device-number"?
> >
> > Ok, I misunderstood. If it's not on chip, what significance does this
> > serial number have? Where would a driver need it?
>
> If there were 2 systemace devices on board; one attached to a CF slot
> labeled "1" and the other to one labeled "2". :-) Same problem as
> lining up serial device files to physical port numbers.
>
> The driver doesn't technically need it, but the information does need
> to flow through to the creation of logically numbered device files.
Ah. Then, I'm afraid it doesn't belong in the core binding.
Preferably, you should just figure out something without help of this
property - plenty of other things have to figure out device names
without assistance like this.
If you really must you could do this in analogy with the
"linux,network-index" property - but this would be, as that is, an
ugly hack, and should be recognized as such.
Segher's suggestion of using OF-style aliases for this is a fairly
good one, actually. I just need to get to implementing it...
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] Device tree bindings for Xilinx devices
From: Grant Likely @ 2007-10-11 4:58 UTC (permalink / raw)
To: Josh Boyer, linuxppc-dev
In-Reply-To: <20071011042441.GG14873@localhost.localdomain>
On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> On Wed, Oct 10, 2007 at 10:18:50PM -0600, Grant Likely wrote:
> > On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> > > On Wed, Oct 10, 2007 at 08:25:36PM -0600, Grant Likely wrote:
> > > > On 10/10/07, David Gibson <dwg@au1.ibm.com> wrote:
> > > > > We've used 'cell-index' for similar purposes on other 4xx.
> > > >
> > > > Unfortunately, 'cell' has been used in the sense of a logic cell in an
> > > > SoC. In the case of the SystemACE, it is an external chip.
> > > >
> > > > What about "device-number"?
> > >
> > > Ok, I misunderstood. If it's not on chip, what significance does this
> > > serial number have? Where would a driver need it?
> >
> > If there were 2 systemace devices on board; one attached to a CF slot
> > labeled "1" and the other to one labeled "2". :-) Same problem as
> > lining up serial device files to physical port numbers.
> >
> > The driver doesn't technically need it, but the information does need
> > to flow through to the creation of logically numbered device files.
>
> Ah. Then, I'm afraid it doesn't belong in the core binding.
>
> Preferably, you should just figure out something without help of this
> property - plenty of other things have to figure out device names
> without assistance like this.
I'm not too stuck on the method used, but I do think it is appropriate
to encode this kind of data in the device tree in some form...
However, for this particular device I'm probably just borrowing
trouble. I'll drop the property.
My main concern is that I don't like the implicit numbering that
occurs simply based on the order of devices in the device tree. If
the probe algorithm ever changes to parse in reverse order or
something reorders the tree, then the device numbers also change. :-(
I'd rather be explicit. In fact I've already been bitten by this
where the mpc5200 has 6 PSC, each of which can be configured as a
serial port. However, I've got access to 3 different boards; each of
which has the logical port numbers 100% unrelated to the 'cell'
number.
> If you really must you could do this in analogy with the
> "linux,network-index" property - but this would be, as that is, an
> ugly hack, and should be recognized as such
>
> Segher's suggestion of using OF-style aliases for this is a fairly
> good one, actually. I just need to get to implementing it...
/me needs to look up what that look like and how I would use it. My
knowledge of OF is sadly lacking.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* [PATCH 1/7] [POWERPC] Clean up vio.h
From: Stephen Rothwell @ 2007-10-11 4:48 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Remove vio_dma_ops declaration (since it no longer exists) and some
unused fields from struct vio_driver.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/vio.c | 11 -----------
include/asm-powerpc/vio.h | 5 -----
2 files changed, 0 insertions(+), 16 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 1d7b272..fd631d4 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -168,16 +168,6 @@ static int vio_bus_remove(struct device *dev)
return 1;
}
-/* convert from struct device to struct vio_dev and pass to driver. */
-static void vio_bus_shutdown(struct device *dev)
-{
- struct vio_dev *viodev = to_vio_dev(dev);
- struct vio_driver *viodrv = to_vio_driver(dev->driver);
-
- if (dev->driver && viodrv->shutdown)
- viodrv->shutdown(viodev);
-}
-
/**
* vio_register_driver: - Register a new vio driver
* @drv: The vio_driver structure to be registered.
@@ -397,7 +387,6 @@ static struct bus_type vio_bus_type = {
.match = vio_bus_match,
.probe = vio_bus_probe,
.remove = vio_bus_remove,
- .shutdown = vio_bus_shutdown,
};
/**
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h
index 598d111..9204c15 100644
--- a/include/asm-powerpc/vio.h
+++ b/include/asm-powerpc/vio.h
@@ -53,17 +53,12 @@ struct vio_dev {
};
struct vio_driver {
- struct list_head node;
const struct vio_device_id *id_table;
int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
int (*remove)(struct vio_dev *dev);
- void (*shutdown)(struct vio_dev *dev);
- unsigned long driver_data;
struct device_driver driver;
};
-extern struct dma_mapping_ops vio_dma_ops;
-
extern int vio_register_driver(struct vio_driver *drv);
extern void vio_unregister_driver(struct vio_driver *drv);
--
1.5.3.4
^ permalink raw reply related
* [PATCH 2/7] [POWERPC] iSeries: simplify viocd initialisation
From: Stephen Rothwell @ 2007-10-11 4:50 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, Jens Axboe
In-Reply-To: <20071011144824.a5e3de59.sfr@canb.auug.org.au>
We don't need to keep a lump of dma coherent memory around for the life
of the module.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
---
drivers/cdrom/viocd.c | 37 +++++++++++++------------------------
1 files changed, 13 insertions(+), 24 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index e51550d..b88fdeb 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -136,17 +136,12 @@ struct cdrom_info {
char type[4];
char model[3];
};
-/*
- * This needs to be allocated since it is passed to the
- * Hypervisor and we may be a module.
- */
-static struct cdrom_info *viocd_unitinfo;
-static dma_addr_t unitinfo_dmaaddr;
struct disk_info {
struct gendisk *viocd_disk;
struct cdrom_device_info viocd_info;
struct device *dev;
+ struct cdrom_info unitinfo;
};
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
@@ -164,9 +159,9 @@ static int proc_viocd_show(struct seq_file *m, void *v)
for (i = 0; i < viocd_numdev; i++) {
seq_printf(m, "viocd device %d is iSeries resource %10.10s"
"type %4.4s, model %3.3s\n",
- i, viocd_unitinfo[i].rsrcname,
- viocd_unitinfo[i].type,
- viocd_unitinfo[i].model);
+ i, viocd_diskinfo[i].unitinfo.rsrcname,
+ viocd_diskinfo[i].unitinfo.type,
+ viocd_diskinfo[i].unitinfo.model);
}
return 0;
}
@@ -222,6 +217,8 @@ static void __init get_viocd_info(void)
HvLpEvent_Rc hvrc;
int i;
struct viocd_waitevent we;
+ struct cdrom_info *viocd_unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
@@ -259,16 +256,15 @@ static void __init get_viocd_info(void)
goto error_ret;
}
- for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++)
+ for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) {
+ viocd_diskinfo[viocd_numdev].unitinfo = viocd_unitinfo[i];
viocd_numdev++;
+ }
error_ret:
- if (viocd_numdev == 0) {
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
- viocd_unitinfo = NULL;
- }
+ dma_free_coherent(iSeries_vio_dev,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
+ viocd_unitinfo, unitinfo_dmaaddr);
}
static int viocd_open(struct cdrom_device_info *cdi, int purpose)
@@ -674,7 +670,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
d = &viocd_diskinfo[deviceno];
c = &d->viocd_info;
- ci = &viocd_unitinfo[deviceno];
+ ci = &d->unitinfo;
c->ops = &viocd_dops;
c->speed = 4;
@@ -816,9 +812,6 @@ static int __init viocd_init(void)
return 0;
out_free_info:
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
vio_clearHandler(viomajorsubtype_cdio);
viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
out_unregister:
@@ -830,10 +823,6 @@ static void __exit viocd_exit(void)
{
remove_proc_entry("iSeries/viocd", NULL);
vio_unregister_driver(&viocd_driver);
- if (viocd_unitinfo != NULL)
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
vio_clearHandler(viomajorsubtype_cdio);
unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
--
1.5.3.4
^ permalink raw reply related
* [PATCH 3/7] [POWERPC] remove iSeries_vio_dev
From: Stephen Rothwell @ 2007-10-11 4:53 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, Jens Axboe
In-Reply-To: <20071011145055.1de13742.sfr@canb.auug.org.au>
It was only being used to carry around dma_iommu_ops and vio_iommu_table
which we can use directly instead. This also means that vio_bus_device
doesn't need to refer to them either.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
---
arch/powerpc/kernel/vio.c | 7 +-----
arch/powerpc/platforms/iseries/iommu.c | 30 +++++++++++++++++++++++++++
arch/powerpc/platforms/iseries/mf.c | 23 ++++++++------------
arch/powerpc/platforms/iseries/viopath.c | 6 +---
drivers/cdrom/viocd.c | 5 +--
drivers/char/viotape.c | 7 ++---
include/asm-powerpc/iseries/hv_call_event.h | 10 +++++++++
include/asm-powerpc/iseries/vio.h | 4 ---
8 files changed, 57 insertions(+), 35 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index fd631d4..eaf7f69 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -49,11 +49,8 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */
};
#ifdef CONFIG_PPC_ISERIES
-struct device *iSeries_vio_dev = &vio_bus_device.dev;
-EXPORT_SYMBOL(iSeries_vio_dev);
-
static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
+struct iommu_table vio_iommu_table;
static void __init iommu_vio_init(void)
{
@@ -66,8 +63,6 @@ static void __init iommu_vio_init(void)
printk("Virtual Bus VETH TCE table failed.\n");
if (!iommu_init_table(&vio_iommu_table, -1))
printk("Virtual Bus VIO TCE table failed.\n");
- vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
- vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
}
#else
static void __init iommu_vio_init(void)
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 3b6a966..3281f10 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -28,6 +28,7 @@
#include <linux/dma-mapping.h>
#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <asm/iommu.h>
#include <asm/tce.h>
@@ -36,6 +37,7 @@
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/hv_call_event.h>
#include <asm/iseries/iommu.h>
static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
@@ -189,6 +191,34 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
}
#endif
+extern struct iommu_table vio_iommu_table;
+
+void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
+{
+ return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
+ DMA_32BIT_MASK, flag, -1);
+}
+EXPORT_SYMBOL_GPL(iseries_hv_alloc);
+
+void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle);
+}
+EXPORT_SYMBOL_GPL(iseries_hv_free);
+
+dma_addr_t iseries_hv_map(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ return iommu_map_single(&vio_iommu_table, vaddr, size,
+ DMA_32BIT_MASK, direction);
+}
+
+void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction);
+}
+
void iommu_init_early_iSeries(void)
{
ppc_md.tce_build = tce_build_iSeries;
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index b1187d9..c0f2433 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -39,9 +39,9 @@
#include <asm/paca.h>
#include <asm/abs_addr.h>
#include <asm/firmware.h>
-#include <asm/iseries/vio.h>
#include <asm/iseries/mf.h>
#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/it_lp_queue.h>
#include "setup.h"
@@ -870,8 +870,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
if ((off + count) > 256)
count = 256 - off;
- dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,
- DMA_FROM_DEVICE);
+ dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE);
if (dma_mapping_error(dma_addr))
return -ENOMEM;
memset(page, 0, off + count);
@@ -883,8 +882,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
vsp_cmd.sub_data.kern.length = off + count;
mb();
rc = signal_vsp_instruction(&vsp_cmd);
- dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,
- DMA_FROM_DEVICE);
+ iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE);
if (rc)
return rc;
if (vsp_cmd.result_code != 0)
@@ -919,8 +917,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
int len = *size;
dma_addr_t dma_addr;
- dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,
- DMA_FROM_DEVICE);
+ dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE);
memset(buffer, 0, len);
memset(&vsp_cmd, 0, sizeof(vsp_cmd));
vsp_cmd.cmd = 32;
@@ -938,7 +935,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
rc = -ENOMEM;
}
- dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);
+ iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE);
return rc;
}
@@ -1149,8 +1146,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
goto out;
dma_addr = 0;
- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
- GFP_ATOMIC);
+ page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
ret = -ENOMEM;
if (page == NULL)
goto out;
@@ -1170,7 +1166,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
ret = count;
out_free:
- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+ iseries_hv_free(count, page, dma_addr);
out:
return ret;
}
@@ -1190,8 +1186,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
goto out;
dma_addr = 0;
- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
- GFP_ATOMIC);
+ page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
rc = -ENOMEM;
if (page == NULL) {
printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
@@ -1219,7 +1214,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
*ppos += count;
rc = count;
out_free:
- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+ iseries_hv_free(count, page, dma_addr);
out:
return rc;
}
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 45f2fe3..df23331 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -124,8 +124,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
if (!buf)
return 0;
- handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE,
- DMA_FROM_DEVICE);
+ handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE);
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo,
@@ -146,8 +145,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
buf[HW_PAGE_SIZE-1] = '\0';
seq_printf(m, "%s", buf);
- dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE,
- DMA_FROM_DEVICE);
+ iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE);
kfree(buf);
seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index b88fdeb..c081e54 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -220,7 +220,7 @@ static void __init get_viocd_info(void)
struct cdrom_info *viocd_unitinfo;
dma_addr_t unitinfo_dmaaddr;
- viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
+ viocd_unitinfo = iseries_hv_alloc(
sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
&unitinfo_dmaaddr, GFP_ATOMIC);
if (viocd_unitinfo == NULL) {
@@ -262,8 +262,7 @@ static void __init get_viocd_info(void)
}
error_ret:
- dma_free_coherent(iSeries_vio_dev,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
+ iseries_hv_free(sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
viocd_unitinfo, unitinfo_dmaaddr);
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index e12275d..064c091 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -392,8 +392,8 @@ static int get_viotape_info(void)
if (op == NULL)
return -ENOMEM;
- viotape_unitinfo = dma_alloc_coherent(iSeries_vio_dev, len,
- &viotape_unitinfo_token, GFP_ATOMIC);
+ viotape_unitinfo = iseries_hv_alloc(len, &viotape_unitinfo_token,
+ GFP_ATOMIC);
if (viotape_unitinfo == NULL) {
free_op_struct(op);
return -ENOMEM;
@@ -1103,8 +1103,7 @@ static void __exit viotap_exit(void)
class_destroy(tape_class);
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
if (viotape_unitinfo)
- dma_free_coherent(iSeries_vio_dev,
- sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
+ iseries_hv_free(sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
viotape_unitinfo, viotape_unitinfo_token);
viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
vio_clearHandler(viomajorsubtype_tape);
diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h
index 4cec476..cc029d3 100644
--- a/include/asm-powerpc/iseries/hv_call_event.h
+++ b/include/asm-powerpc/iseries/hv_call_event.h
@@ -21,6 +21,9 @@
#ifndef _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H
#define _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
#include <asm/iseries/hv_call_sc.h>
#include <asm/iseries/hv_types.h>
#include <asm/abs_addr.h>
@@ -113,6 +116,13 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
eventData3, eventData4, eventData5);
}
+extern void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag);
+extern void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle);
+extern dma_addr_t iseries_hv_map(void *vaddr, size_t size,
+ enum dma_data_direction direction);
+extern void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction);
+
static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
{
return HvCall1(HvCallEventAckLpEvent, virt_to_abs(event));
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index 7a95d29..5a5cd0f 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -150,8 +150,4 @@ enum viochar_rc {
viochar_rc_ebusy = 1
};
-struct device;
-
-extern struct device *iSeries_vio_dev;
-
#endif /* _ASM_POWERPC_ISERIES_VIO_H */
--
1.5.3.4
^ permalink raw reply related
* [PATCH 4/7] [POWERPC] Remove more iSeries specific stuff from vio.c
From: Stephen Rothwell @ 2007-10-11 4:55 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20071011145332.e3638c2e.sfr@canb.auug.org.au>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/vio.c | 78 ++++++++++---------------------
arch/powerpc/platforms/iseries/iommu.c | 24 +++++++++-
include/asm-powerpc/iseries/iommu.h | 4 ++
3 files changed, 52 insertions(+), 54 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index eaf7f69..b7c9e44 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -48,61 +48,33 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */
.dev.bus = &vio_bus_type,
};
-#ifdef CONFIG_PPC_ISERIES
-static struct iommu_table veth_iommu_table;
-struct iommu_table vio_iommu_table;
-
-static void __init iommu_vio_init(void)
-{
- iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
- veth_iommu_table.it_size /= 2;
- vio_iommu_table = veth_iommu_table;
- vio_iommu_table.it_offset += veth_iommu_table.it_size;
-
- if (!iommu_init_table(&veth_iommu_table, -1))
- printk("Virtual Bus VETH TCE table failed.\n");
- if (!iommu_init_table(&vio_iommu_table, -1))
- printk("Virtual Bus VIO TCE table failed.\n");
-}
-#else
-static void __init iommu_vio_init(void)
-{
-}
-#endif
-
static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
{
-#ifdef CONFIG_PPC_ISERIES
- if (firmware_has_feature(FW_FEATURE_ISERIES)) {
- if (strcmp(dev->type, "network") == 0)
- return &veth_iommu_table;
- return &vio_iommu_table;
- } else
-#endif
- {
- const unsigned char *dma_window;
- struct iommu_table *tbl;
- unsigned long offset, size;
-
- dma_window = of_get_property(dev->dev.archdata.of_node,
- "ibm,my-dma-window", NULL);
- if (!dma_window)
- return NULL;
-
- tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
-
- of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
- &tbl->it_index, &offset, &size);
-
- /* TCE table size - measured in tce entries */
- tbl->it_size = size >> IOMMU_PAGE_SHIFT;
- /* offset for VIO should always be 0 */
- tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
- tbl->it_busno = 0;
- tbl->it_type = TCE_VB;
-
- return iommu_init_table(tbl, -1);
- }
+ const unsigned char *dma_window;
+ struct iommu_table *tbl;
+ unsigned long offset, size;
+
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return vio_build_iommu_table_iseries(dev);
+
+ dma_window = of_get_property(dev->dev.archdata.of_node,
+ "ibm,my-dma-window", NULL);
+ if (!dma_window)
+ return NULL;
+
+ tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+
+ of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
+ &tbl->it_index, &offset, &size);
+
+ /* TCE table size - measured in tce entries */
+ tbl->it_size = size >> IOMMU_PAGE_SHIFT;
+ /* offset for VIO should always be 0 */
+ tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
+ tbl->it_busno = 0;
+ tbl->it_type = TCE_VB;
+
+ return iommu_init_table(tbl, -1);
}
/**
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 3281f10..49e9c66 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <asm/iommu.h>
+#include <asm/vio.h>
#include <asm/tce.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
@@ -191,7 +192,8 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
}
#endif
-extern struct iommu_table vio_iommu_table;
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
{
@@ -219,6 +221,26 @@ void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction);
}
+void __init iommu_vio_init(void)
+{
+ iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
+ veth_iommu_table.it_size /= 2;
+ vio_iommu_table = veth_iommu_table;
+ vio_iommu_table.it_offset += veth_iommu_table.it_size;
+
+ if (!iommu_init_table(&veth_iommu_table, -1))
+ printk("Virtual Bus VETH TCE table failed.\n");
+ if (!iommu_init_table(&vio_iommu_table, -1))
+ printk("Virtual Bus VIO TCE table failed.\n");
+}
+
+struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev)
+{
+ if (strcmp(dev->type, "network") == 0)
+ return &veth_iommu_table;
+ return &vio_iommu_table;
+}
+
void iommu_init_early_iSeries(void)
{
ppc_md.tce_build = tce_build_iSeries;
diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h
index 6e323a1..c59ee7e 100644
--- a/include/asm-powerpc/iseries/iommu.h
+++ b/include/asm-powerpc/iseries/iommu.h
@@ -22,6 +22,7 @@
*/
struct pci_dev;
+struct vio_dev;
struct device_node;
struct iommu_table;
@@ -34,4 +35,7 @@ extern void iommu_table_getparms_iSeries(unsigned long busno,
unsigned char slotno, unsigned char virtbus,
struct iommu_table *tbl);
+extern struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev);
+extern void iommu_vio_init(void);
+
#endif /* _ASM_POWERPC_ISERIES_IOMMU_H */
--
1.5.3.4
^ permalink raw reply related
* [PATCH 5/7] [POWERPC] iSeries: move detection of virtual cdroms
From: Stephen Rothwell @ 2007-10-11 4:57 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, Jens Axboe
In-Reply-To: <20071011145502.49a16436.sfr@canb.auug.org.au>
Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties). This way viocd.c gets all
the information about the devices from the device tree.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
---
arch/powerpc/kernel/vio.c | 3 -
arch/powerpc/platforms/iseries/Makefile | 2 +-
arch/powerpc/platforms/iseries/dt.c | 4 -
arch/powerpc/platforms/iseries/vio.c | 317 +++++++++++++++++++++++++++++++
drivers/cdrom/viocd.c | 116 ++----------
include/asm-powerpc/iseries/vio.h | 24 +++
6 files changed, 361 insertions(+), 105 deletions(-)
create mode 100644 arch/powerpc/platforms/iseries/vio.c
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index b7c9e44..cb22a35 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -247,9 +247,6 @@ static int __init vio_bus_init(void)
int err;
struct device_node *node_vroot;
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iommu_vio_init();
-
err = bus_register(&vio_bus_type);
if (err) {
printk(KERN_ERR "failed to register VIO bus\n");
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 60db509..a65f1b4 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -7,7 +7,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
hvcall.o proc.o htab.o iommu.o misc.o irq.o
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_VIOPATH) += viopath.o
+obj-$(CONFIG_VIOPATH) += viopath.o vio.o
obj-$(CONFIG_MODULES) += ksyms.o
quiet_cmd_dt_strings = DT_STR $@
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 9e8a334..84fcee1 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -381,10 +381,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
"IBM,iSeries-viodasd", 1);
reg += HVMAXARCHITECTEDVIRTUALDISKS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
- dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
- "IBM,iSeries-viocd", 1);
reg += HVMAXARCHITECTEDVIRTUALCDROMS;
for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
new file mode 100644
index 0000000..08f6884
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -0,0 +1,317 @@
+/*
+ * Legacy iSeries specific vio initialisation
+ * that needs to be built in (not a module).
+ *
+ * © Copyright 2007 IBM Corporation
+ * Author: Stephen Rothwell
+ * Some parts collected from various other files
+ *
+ * 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 <linux/of.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/completion.h>
+#include <linux/proc_fs.h>
+
+#include <asm/firmware.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/iommu.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
+
+#define FIRST_VTY 0
+#define NUM_VTYS 1
+#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
+#define NUM_VSCSIS 1
+#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
+#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
+#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
+#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
+#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
+#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
+#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
+#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
+
+static struct property * __init new_property(const char *name, int length,
+ const void *value)
+{
+ struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
+ GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->name = (char *)(np + 1);
+ np->value = np->name + strlen(name) + 1;
+ strcpy(np->name, name);
+ memcpy(np->value, value, length);
+ np->length = length;
+ return np;
+}
+
+static void __init free_property(struct property *np)
+{
+ kfree(np);
+}
+
+static struct device_node * __init new_node(const char *path,
+ struct device_node *parent)
+{
+ struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+ if (!np->full_name) {
+ kfree(np);
+ return NULL;
+ }
+ strcpy(np->full_name, path);
+ of_node_set_flag(np, OF_DYNAMIC);
+ kref_init(&np->kref);
+ np->parent = of_node_get(parent);
+ return np;
+}
+
+static void __init free_node(struct device_node *np)
+{
+ struct property *next;
+ struct property *prop;
+
+ next = np->properties;
+ while (next) {
+ prop = next;
+ next = prop->next;
+ free_property(prop);
+ }
+ of_node_put(np->parent);
+ kfree(np->full_name);
+ kfree(np);
+}
+
+static int __init add_string_property(struct device_node *np, const char *name,
+ const char *value)
+{
+ struct property *nprop = new_property(name, strlen(value) + 1, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+static int __init add_raw_property(struct device_node *np, const char *name,
+ int length, const void *value)
+{
+ struct property *nprop = new_property(name, length, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+struct viocd_waitevent {
+ struct completion com;
+ int rc;
+ u16 sub_result;
+};
+
+struct cdrom_info {
+ char rsrcname[10];
+ char type[4];
+ char model[3];
+};
+
+static void __init handle_cd_event(struct HvLpEvent *event)
+{
+ struct viocdlpevent *bevent;
+ struct viocd_waitevent *pwe;
+
+ if (!event)
+ /* Notification that a partition went away! */
+ return;
+
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ bevent = (struct viocdlpevent *)event;
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viocdgetinfo:
+ pwe = (struct viocd_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+
+ default:
+ printk(KERN_WARNING "handle_cd_event: "
+ "message with unexpected subtype %0x04X!\n",
+ event->xSubtype & VIOMINOR_SUBTYPE_MASK);
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init get_viocd_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct viocd_waitevent we;
+ struct cdrom_info *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
+ if (ret) {
+ printk(KERN_WARNING
+ "get_viocd_info: error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
+
+ unitinfo = iseries_hv_alloc(
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo) {
+ printk(KERN_WARNING
+ "get_viocd_info: error allocating unitinfo\n");
+ goto clear_handler;
+ }
+
+ memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
+
+ init_completion(&we.com);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_cdio | viocdgetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING
+ "get_viocd_info: cdrom error sending event. rc %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc) {
+ printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
+ we.rc, we.sub_result);
+ goto hv_free;
+ }
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ struct device_node *np;
+ char name[64];
+ u32 reg = FIRST_VIOCD + unit;
+
+ snprintf(name, sizeof(name), "/vdevice/viocd@%08x", reg);
+ np = new_node(name, vio_root);
+ if (!np)
+ goto hv_free;
+ if (!add_string_property(np, "name", "viocd") ||
+ !add_string_property(np, "device_type", "block") ||
+ !add_string_property(np, "compatible",
+ "IBM,iSeries-viocd") ||
+ !add_raw_property(np, "reg", sizeof(reg), ®) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit) ||
+ !add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(unitinfo[unit].rsrcname),
+ unitinfo[unit].rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(unitinfo[unit].type),
+ unitinfo[unit].type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(unitinfo[unit].model),
+ unitinfo[unit].model))
+ goto node_free;
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (vio_root->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
+ vio_root->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ continue;
+
+ node_free:
+ free_node(np);
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_cdio);
+ viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
+}
+
+static int __init iseries_vio_init(void)
+{
+ struct device_node *vio_root;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
+ iommu_vio_init();
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return -ENODEV;
+
+ if (viopath_hostLp == HvLpIndexInvalid) {
+ vio_set_hostlp();
+ /* If we don't have a host, bail out */
+ if (viopath_hostLp == HvLpIndexInvalid)
+ goto put_node;
+ }
+
+ get_viocd_info(vio_root);
+
+ return 0;
+
+ put_node:
+ of_node_put(vio_root);
+ return -ENODEV;
+}
+arch_initcall(iseries_vio_init);
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index c081e54..880b5dc 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -56,30 +56,6 @@
#define VIOCD_KERN_WARNING KERN_WARNING "viocd: "
#define VIOCD_KERN_INFO KERN_INFO "viocd: "
-struct viocdlpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_result;
- u16 disk;
- u16 flags;
- u32 token;
- u64 offset; /* On open, max number of disks */
- u64 len; /* On open, size of the disk */
- u32 block_size; /* Only set on open */
- u32 media_size; /* Only set on open */
-};
-
-enum viocdsubtype {
- viocdopen = 0x0001,
- viocdclose = 0x0002,
- viocdread = 0x0003,
- viocdwrite = 0x0004,
- viocdlockdoor = 0x0005,
- viocdgetinfo = 0x0006,
- viocdcheck = 0x0007
-};
-
/*
* Should probably make this a module parameter....sigh
*/
@@ -131,17 +107,13 @@ static struct capability_entry capability_table[] __initdata = {
/* These are our internal structures for keeping track of devices */
static int viocd_numdev;
-struct cdrom_info {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
struct disk_info {
struct gendisk *viocd_disk;
struct cdrom_device_info viocd_info;
struct device *dev;
- struct cdrom_info unitinfo;
+ const char *rsrcname;
+ const char *type;
+ const char *model;
};
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
@@ -159,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v)
for (i = 0; i < viocd_numdev; i++) {
seq_printf(m, "viocd device %d is iSeries resource %10.10s"
"type %4.4s, model %3.3s\n",
- i, viocd_diskinfo[i].unitinfo.rsrcname,
- viocd_diskinfo[i].unitinfo.type,
- viocd_diskinfo[i].unitinfo.model);
+ i, viocd_diskinfo[i].rsrcname,
+ viocd_diskinfo[i].type,
+ viocd_diskinfo[i].model);
}
return 0;
}
@@ -211,61 +183,6 @@ struct block_device_operations viocd_fops = {
.media_changed = viocd_blk_media_changed,
};
-/* Get info on CD devices from OS/400 */
-static void __init get_viocd_info(void)
-{
- HvLpEvent_Rc hvrc;
- int i;
- struct viocd_waitevent we;
- struct cdrom_info *viocd_unitinfo;
- dma_addr_t unitinfo_dmaaddr;
-
- viocd_unitinfo = iseries_hv_alloc(
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- &unitinfo_dmaaddr, GFP_ATOMIC);
- if (viocd_unitinfo == NULL) {
- printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
- return;
- }
-
- memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
-
- init_completion(&we.com);
-
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_cdio | viocdgetinfo,
- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
- if (hvrc != HvLpEvent_Rc_Good) {
- printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
- (int)hvrc);
- goto error_ret;
- }
-
- wait_for_completion(&we.com);
-
- if (we.rc) {
- const struct vio_error_entry *err =
- vio_lookup_rc(viocd_err_table, we.sub_result);
- printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
- we.rc, we.sub_result, err->msg);
- goto error_ret;
- }
-
- for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) {
- viocd_diskinfo[viocd_numdev].unitinfo = viocd_unitinfo[i];
- viocd_numdev++;
- }
-
-error_ret:
- iseries_hv_free(sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
-}
-
static int viocd_open(struct cdrom_device_info *cdi, int purpose)
{
struct disk_info *diskinfo = cdi->handle;
@@ -576,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
bevent->block_size / 512);
}
/* FALLTHROUGH !! */
- case viocdgetinfo:
case viocdlockdoor:
pwe = (struct viocd_waitevent *)event->xCorrelationToken;
return_complete:
@@ -660,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
int deviceno;
struct disk_info *d;
struct cdrom_device_info *c;
- struct cdrom_info *ci;
struct request_queue *q;
+ struct device_node *node = vdev->dev.archdata.of_node;
deviceno = vdev->unit_address;
- if (deviceno >= viocd_numdev)
+ if (deviceno > VIOCD_MAX_CD)
return -ENODEV;
+ if (!node)
+ return -ENODEV;
+
+ if (deviceno >= viocd_numdev)
+ viocd_numdev = deviceno + 1;
d = &viocd_diskinfo[deviceno];
+ d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL);
+ d->type = of_get_property(node, "linux,vio_type", NULL);
+ d->model = of_get_property(node, "linux,vio_model", NULL);
+
c = &d->viocd_info;
- ci = &d->unitinfo;
c->ops = &viocd_dops;
c->speed = 4;
c->capacity = 1;
c->handle = d;
- c->mask = ~find_capability(ci->type);
+ c->mask = ~find_capability(d->type);
sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno);
if (register_cdrom(c) != 0) {
@@ -685,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s "
"type %4.4s, model %3.3s\n",
- c->name, ci->rsrcname, ci->type, ci->model);
+ c->name, d->rsrcname, d->type, d->model);
q = blk_init_queue(do_viocd_request, &viocd_reqlock);
if (q == NULL) {
printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n",
@@ -794,8 +718,6 @@ static int __init viocd_init(void)
/* Initialize our request handler */
vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event);
- get_viocd_info();
-
spin_lock_init(&viocd_reqlock);
ret = vio_register_driver(&viocd_driver);
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index 5a5cd0f..e5a405b 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -51,6 +51,30 @@
*/
#define VIO_MAX_SUBTYPES 8
+struct viocdlpevent {
+ struct HvLpEvent event;
+ u32 reserved;
+ u16 version;
+ u16 sub_result;
+ u16 disk;
+ u16 flags;
+ u32 token;
+ u64 offset; /* On open, max number of disks */
+ u64 len; /* On open, size of the disk */
+ u32 block_size; /* Only set on open */
+ u32 media_size; /* Only set on open */
+};
+
+enum viocdsubtype {
+ viocdopen = 0x0001,
+ viocdclose = 0x0002,
+ viocdread = 0x0003,
+ viocdwrite = 0x0004,
+ viocdlockdoor = 0x0005,
+ viocdgetinfo = 0x0006,
+ viocdcheck = 0x0007
+};
+
/*
* Each subtype can register a handler to process their events.
* The handler must have this interface.
--
1.5.3.4
^ permalink raw reply related
* [PATCH 6/7] [POWERPC] iSeries: move detection of virtual tapes
From: Stephen Rothwell @ 2007-10-11 4:58 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20071011145726.59bcbc02.sfr@canb.auug.org.au>
Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties). This way viotape.c gets
all the information about the devices from the device tree.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/dt.c | 7 --
arch/powerpc/platforms/iseries/vio.c | 149 ++++++++++++++++++++++++++++++----
drivers/char/viotape.c | 124 ++++------------------------
include/asm-powerpc/iseries/vio.h | 41 +++++++++
4 files changed, 192 insertions(+), 129 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 84fcee1..2e4ad6b 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -73,7 +73,6 @@ static char __initdata device_type_memory[] = "memory";
static char __initdata device_type_serial[] = "serial";
static char __initdata device_type_network[] = "network";
static char __initdata device_type_block[] = "block";
-static char __initdata device_type_byte[] = "byte";
static char __initdata device_type_pci[] = "pci";
static char __initdata device_type_vdevice[] = "vdevice";
static char __initdata device_type_vscsi[] = "vscsi";
@@ -380,12 +379,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
"IBM,iSeries-viodasd", 1);
- reg += HVMAXARCHITECTEDVIRTUALDISKS;
- reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
- dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
- "IBM,iSeries-viotape", 1);
dt_end_node(dt);
}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 08f6884..b4f7433 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -45,6 +45,18 @@
#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
+struct vio_waitevent {
+ struct completion com;
+ int rc;
+ u16 sub_result;
+};
+
+struct vio_resource {
+ char rsrcname[10];
+ char type[4];
+ char model[3];
+};
+
static struct property * __init new_property(const char *name, int length,
const void *value)
{
@@ -123,22 +135,10 @@ static int __init add_raw_property(struct device_node *np, const char *name,
return 1;
}
-struct viocd_waitevent {
- struct completion com;
- int rc;
- u16 sub_result;
-};
-
-struct cdrom_info {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
static void __init handle_cd_event(struct HvLpEvent *event)
{
struct viocdlpevent *bevent;
- struct viocd_waitevent *pwe;
+ struct vio_waitevent *pwe;
if (!event)
/* Notification that a partition went away! */
@@ -158,7 +158,7 @@ static void __init handle_cd_event(struct HvLpEvent *event)
switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
case viocdgetinfo:
- pwe = (struct viocd_waitevent *)event->xCorrelationToken;
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
pwe->rc = event->xRc;
pwe->sub_result = bevent->sub_result;
complete(&pwe->com);
@@ -179,8 +179,8 @@ static void __init get_viocd_info(struct device_node *vio_root)
{
HvLpEvent_Rc hvrc;
u32 unit;
- struct viocd_waitevent we;
- struct cdrom_info *unitinfo;
+ struct vio_waitevent we;
+ struct vio_resource *unitinfo;
dma_addr_t unitinfo_dmaaddr;
int ret;
@@ -286,6 +286,122 @@ static void __init get_viocd_info(struct device_node *vio_root)
viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
}
+/* Handle interrupt events for tape */
+static void __init handle_tape_event(struct HvLpEvent *event)
+{
+ struct vio_waitevent *we;
+ struct viotapelpevent *tevent = (struct viotapelpevent *)event;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+
+ we = (struct vio_waitevent *)event->xCorrelationToken;
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viotapegetinfo:
+ we->rc = tevent->sub_type_result;
+ complete(&we->com);
+ break;
+ default:
+ printk(KERN_WARNING "handle_tape_event: weird ack\n");
+ }
+}
+
+static void __init get_viotape_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct vio_resource *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
+ struct vio_waitevent we;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
+ if (ret) {
+ printk(KERN_WARNING "get_viotape_info: "
+ "error on viopath_open to hostlp %d\n", ret);
+ return;
+ }
+
+ vio_setHandler(viomajorsubtype_tape, handle_tape_event);
+
+ unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo)
+ goto clear_handler;
+
+ memset(unitinfo, 0, len);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_tape | viotapegetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ unitinfo_dmaaddr, len, 0, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ struct device_node *np;
+ char name[64];
+ u32 reg = FIRST_VIOTAPE + unit;
+
+ snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
+ np = new_node(name, vio_root);
+ if (!np)
+ goto hv_free;
+ if (!add_string_property(np, "name", "viotape") ||
+ !add_string_property(np, "device_type", "byte") ||
+ !add_string_property(np, "compatible",
+ "IBM,iSeries-viotape") ||
+ !add_raw_property(np, "reg", sizeof(reg), ®) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit) ||
+ !add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(unitinfo[unit].rsrcname),
+ unitinfo[unit].rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(unitinfo[unit].type),
+ unitinfo[unit].type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(unitinfo[unit].model),
+ unitinfo[unit].model))
+ goto node_free;
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (vio_root->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
+ vio_root->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ continue;
+
+ node_free:
+ free_node(np);
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_tape);
+ viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
+}
+
static int __init iseries_vio_init(void)
{
struct device_node *vio_root;
@@ -307,6 +423,7 @@ static int __init iseries_vio_init(void)
}
get_viocd_info(vio_root);
+ get_viotape_info(vio_root);
return 0;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 064c091..f1d60f0 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -92,47 +92,6 @@ struct viot_devinfo_struct {
#define VIOTAPOP_SETPART 14
#define VIOTAPOP_UNLOAD 15
-struct viotapelpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_type_result;
- u16 tape;
- u16 flags;
- u32 token;
- u64 len;
- union {
- struct {
- u32 tape_op;
- u32 count;
- } op;
- struct {
- u32 type;
- u32 resid;
- u32 dsreg;
- u32 gstat;
- u32 erreg;
- u32 file_no;
- u32 block_no;
- } get_status;
- struct {
- u32 block_no;
- } get_pos;
- } u;
-};
-
-enum viotapesubtype {
- viotapeopen = 0x0001,
- viotapeclose = 0x0002,
- viotaperead = 0x0003,
- viotapewrite = 0x0004,
- viotapegetinfo = 0x0005,
- viotapeop = 0x0006,
- viotapegetpos = 0x0007,
- viotapesetpos = 0x0008,
- viotapegetstatus = 0x0009
-};
-
enum viotaperc {
viotape_InvalidRange = 0x0601,
viotape_InvalidToken = 0x0602,
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
#define VIOT_WRITING 2
/* Our info on the tapes */
-struct tape_descr {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
-static struct tape_descr *viotape_unitinfo;
-static dma_addr_t viotape_unitinfo_token;
+static struct {
+ const char *rsrcname;
+ const char *type;
+ const char *model;
+} viotape_unitinfo[VIOTAPE_MAX_TAPE];
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
return -err->errno;
}
-/* Get info on all tapes from OS/400 */
-static int get_viotape_info(void)
-{
- HvLpEvent_Rc hvrc;
- int i;
- size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
- struct op_struct *op = get_op_struct();
-
- if (op == NULL)
- return -ENOMEM;
-
- viotape_unitinfo = iseries_hv_alloc(len, &viotape_unitinfo_token,
- GFP_ATOMIC);
- if (viotape_unitinfo == NULL) {
- free_op_struct(op);
- return -ENOMEM;
- }
-
- memset(viotape_unitinfo, 0, len);
-
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_tape | viotapegetinfo,
- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64) (unsigned long) op, VIOVERSION << 16,
- viotape_unitinfo_token, len, 0, 0);
- if (hvrc != HvLpEvent_Rc_Good) {
- printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
- (int)hvrc);
- free_op_struct(op);
- return -EIO;
- }
-
- wait_for_completion(&op->com);
-
- free_op_struct(op);
-
- for (i = 0;
- ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
- i++)
- viotape_numdev++;
- return 0;
-}
-
-
/* Write */
static ssize_t viotap_write(struct file *file, const char *buf,
size_t count, loff_t * ppos)
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
op = (struct op_struct *)event->xCorrelationToken;
switch (tapeminor) {
- case viotapegetinfo:
case viotapeopen:
case viotapeclose:
op->rc = tevent->sub_type_result;
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
{
int i = vdev->unit_address;
int j;
+ struct device_node *node = vdev->dev.archdata.of_node;
- if (i >= viotape_numdev)
+ if (i > VIOTAPE_MAX_TAPE)
+ return -ENODEV;
+ if (!node)
return -ENODEV;
+ if (i >= viotape_numdev)
+ viotape_numdev = i + 1;
+
tape_device[i] = &vdev->dev;
+ viotape_unitinfo[i].rsrcname = of_get_property(node,
+ "linux,vio_rsrcname", NULL);
+ viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
+ NULL);
+ viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
+ NULL);
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
@@ -1044,11 +964,6 @@ int __init viotap_init(void)
goto unreg_chrdev;
}
- if ((ret = get_viotape_info()) < 0) {
- printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
- goto unreg_class;
- }
-
ret = vio_register_driver(&viotape_driver);
if (ret)
goto unreg_class;
@@ -1102,9 +1017,6 @@ static void __exit viotap_exit(void)
vio_unregister_driver(&viotape_driver);
class_destroy(tape_class);
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
- if (viotape_unitinfo)
- iseries_hv_free(sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
- viotape_unitinfo, viotape_unitinfo_token);
viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
vio_clearHandler(viomajorsubtype_tape);
clear_op_struct_pool();
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index e5a405b..2555dfd 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -75,6 +75,47 @@ enum viocdsubtype {
viocdcheck = 0x0007
};
+struct viotapelpevent {
+ struct HvLpEvent event;
+ u32 reserved;
+ u16 version;
+ u16 sub_type_result;
+ u16 tape;
+ u16 flags;
+ u32 token;
+ u64 len;
+ union {
+ struct {
+ u32 tape_op;
+ u32 count;
+ } op;
+ struct {
+ u32 type;
+ u32 resid;
+ u32 dsreg;
+ u32 gstat;
+ u32 erreg;
+ u32 file_no;
+ u32 block_no;
+ } get_status;
+ struct {
+ u32 block_no;
+ } get_pos;
+ } u;
+};
+
+enum viotapesubtype {
+ viotapeopen = 0x0001,
+ viotapeclose = 0x0002,
+ viotaperead = 0x0003,
+ viotapewrite = 0x0004,
+ viotapegetinfo = 0x0005,
+ viotapeop = 0x0006,
+ viotapegetpos = 0x0007,
+ viotapesetpos = 0x0008,
+ viotapegetstatus = 0x0009
+};
+
/*
* Each subtype can register a handler to process their events.
* The handler must have this interface.
--
1.5.3.4
^ 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