From d4590da43666443aaf0c7c59e5f245352989bd9d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 17 Oct 2011 05:38:58 +0000 Subject: powerpc: cpm2 boards: update fcc register logic In the recent dropping of !NET_MULTI code (commit e2a53458a7ab37523304), I misread the logic in include/net.h. Some of it was used by NET_MULTI code as glue between the multi/non-multi worlds for cpm2 boards. Rather than restore the block of code, push the logic to the board config headers where it all belongs. Signed-off-by: Mike Frysinger --- include/configs/CPU86.h | 8 ++++---- include/configs/CPU87.h | 8 ++++---- include/configs/IDS8247.h | 4 ++-- include/configs/IPHASE4539.h | 4 ++-- include/configs/ISPAN.h | 4 ++-- include/configs/MPC8260ADS.h | 10 +++++----- include/configs/MPC8266ADS.h | 4 ++-- include/configs/MPC8560ADS.h | 4 ++-- include/configs/RPXsuper.h | 4 ++-- include/configs/Rattler.h | 8 ++++---- include/configs/SBC8540.h | 4 ++-- include/configs/SCM.h | 8 ++++---- include/configs/TQM8260.h | 6 +++--- include/configs/TQM8272.h | 4 ++-- include/configs/ZPC1900.h | 4 ++-- include/configs/ep8260.h | 4 ++-- include/configs/gw8260.h | 8 ++++---- include/configs/hymod.h | 12 ++++++------ include/configs/muas3001.h | 4 ++-- include/configs/ppmc8260.h | 4 ++-- include/configs/rsdproto.h | 4 ++-- include/configs/sacsng.h | 6 +++--- include/configs/sbc8560.h | 4 ++-- include/configs/stxgp3.h | 4 ++-- include/configs/stxssa.h | 4 ++-- 25 files changed, 69 insertions(+), 69 deletions(-) diff --git a/include/configs/CPU86.h b/include/configs/CPU86.h index ab64adae0e..abf4ef4212 100644 --- a/include/configs/CPU86.h +++ b/include/configs/CPU86.h @@ -89,8 +89,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK11|CMXFCR_TF1CS_CLK12) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK11|CMXFCR_TF1CS_CLK12) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) @@ -102,8 +102,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/CPU87.h b/include/configs/CPU87.h index 2b1716afee..723bdf3fd5 100644 --- a/include/configs/CPU87.h +++ b/include/configs/CPU87.h @@ -93,8 +93,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK11|CMXFCR_TF1CS_CLK12) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK11|CMXFCR_TF1CS_CLK12) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) @@ -106,8 +106,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/IDS8247.h b/include/configs/IDS8247.h index 8552250412..be778fe809 100644 --- a/include/configs/IDS8247.h +++ b/include/configs/IDS8247.h @@ -154,8 +154,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK9) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK9) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/IPHASE4539.h b/include/configs/IPHASE4539.h index 0af43b667d..d9663062b9 100644 --- a/include/configs/IPHASE4539.h +++ b/include/configs/IPHASE4539.h @@ -82,8 +82,8 @@ * - Select bus for bd/buffers (see 28-13) * - Half duplex */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3 | CMXFCR_RF3CS_MSK | CMXFCR_TF3CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK14 | CMXFCR_TF3CS_CLK16) +# define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3 | CMXFCR_RF3CS_MSK | CMXFCR_TF3CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK14 | CMXFCR_TF3CS_CLK16) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/ISPAN.h b/include/configs/ISPAN.h index 49c6510703..922b0798cf 100644 --- a/include/configs/ISPAN.h +++ b/include/configs/ISPAN.h @@ -72,8 +72,8 @@ #if CONFIG_ETHER_INDEX == 3 #define CONFIG_SYS_PHY_ADDR 0 -#define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK14 | CMXFCR_TF3CS_CLK16) -#define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3 | CMXFCR_RF3CS_MSK | CMXFCR_TF3CS_MSK) +#define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK14 | CMXFCR_TF3CS_CLK16) +#define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3 | CMXFCR_RF3CS_MSK | CMXFCR_TF3CS_MSK) #endif /* CONFIG_ETHER_INDEX == 3 */ diff --git a/include/configs/MPC8260ADS.h b/include/configs/MPC8260ADS.h index 2225b46b28..e4ea178f5e 100644 --- a/include/configs/MPC8260ADS.h +++ b/include/configs/MPC8260ADS.h @@ -128,20 +128,20 @@ #if CONFIG_ETHER_INDEX == 1 # define CONFIG_SYS_PHY_ADDR 0 -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK11 | CMXFCR_TF1CS_CLK10) -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1 | CMXFCR_RF1CS_MSK | CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK11 | CMXFCR_TF1CS_CLK10) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1 | CMXFCR_RF1CS_MSK | CMXFCR_TF1CS_MSK) #elif CONFIG_ETHER_INDEX == 2 #if CONFIG_ADSTYPE == CONFIG_SYS_8272ADS /* RxCLK is CLK15, TxCLK is CLK16 */ # define CONFIG_SYS_PHY_ADDR 3 -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK15 | CMXFCR_TF2CS_CLK16) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK15 | CMXFCR_TF2CS_CLK16) #else /* RxCLK is CLK13, TxCLK is CLK14 */ # define CONFIG_SYS_PHY_ADDR 0 -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) #endif /* CONFIG_ADSTYPE == CONFIG_SYS_8272ADS */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) #endif /* CONFIG_ETHER_INDEX */ diff --git a/include/configs/MPC8266ADS.h b/include/configs/MPC8266ADS.h index 5794473368..0474140fb3 100644 --- a/include/configs/MPC8266ADS.h +++ b/include/configs/MPC8266ADS.h @@ -122,8 +122,8 @@ * - Select bus for bd/buffers (see 28-13) * - Half duplex */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) diff --git a/include/configs/MPC8560ADS.h b/include/configs/MPC8560ADS.h index 8cf2bf2b3c..84a5bccbc2 100644 --- a/include/configs/MPC8560ADS.h +++ b/include/configs/MPC8560ADS.h @@ -333,8 +333,8 @@ * - Select bus for bd/buffers * - Full duplex */ - #define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) - #define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) + #define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) + #define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE) #define FETH2_RST 0x01 diff --git a/include/configs/RPXsuper.h b/include/configs/RPXsuper.h index 9d97f2fd37..c1865fc636 100644 --- a/include/configs/RPXsuper.h +++ b/include/configs/RPXsuper.h @@ -107,8 +107,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Half Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) +# define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 /*#define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) */ # define CONFIG_SYS_FCC_PSMR 0 diff --git a/include/configs/Rattler.h b/include/configs/Rattler.h index 4844fba885..9ddf626eb9 100644 --- a/include/configs/Rattler.h +++ b/include/configs/Rattler.h @@ -80,8 +80,8 @@ * - BDs/buffers on 60x bus * - Full duplex */ -#define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1 | CMXFCR_RF1CS_MSK | CMXFCR_TF1CS_MSK) -#define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK11 | CMXFCR_TF1CS_CLK10) +#define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1 | CMXFCR_RF1CS_MSK | CMXFCR_TF1CS_MSK) +#define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK11 | CMXFCR_TF1CS_CLK10) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) @@ -92,8 +92,8 @@ * - BDs/buffers on 60x bus * - Full duplex */ -#define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) -#define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK15 | CMXFCR_TF2CS_CLK14) +#define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) +#define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK15 | CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) diff --git a/include/configs/SBC8540.h b/include/configs/SBC8540.h index 7a96530803..434b96b1d3 100644 --- a/include/configs/SBC8540.h +++ b/include/configs/SBC8540.h @@ -260,8 +260,8 @@ * - Select bus for bd/buffers * - Full duplex */ - #define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) - #define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) + #define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) + #define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE) diff --git a/include/configs/SCM.h b/include/configs/SCM.h index ec26290be0..73216dc799 100644 --- a/include/configs/SCM.h +++ b/include/configs/SCM.h @@ -153,8 +153,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK12|CMXFCR_TF1CS_CLK11) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK12|CMXFCR_TF1CS_CLK11) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) @@ -166,8 +166,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) +# define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/TQM8260.h b/include/configs/TQM8260.h index 36ecbd8b52..626cf19bd0 100644 --- a/include/configs/TQM8260.h +++ b/include/configs/TQM8260.h @@ -181,7 +181,7 @@ * - RX clk is CLK11 * - TX clk is CLK12 */ -# define CONFIG_SYS_CMXSCR_VALUE (CMXSCR_RS1CS_CLK11 | CMXSCR_TS1CS_CLK12) +# define CONFIG_SYS_CMXSCR_VALUE1 (CMXSCR_RS1CS_CLK11 | CMXSCR_TS1CS_CLK12) #elif defined(CONFIG_ETHER_ON_FCC) && (CONFIG_ETHER_INDEX == 2) @@ -191,8 +191,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/TQM8272.h b/include/configs/TQM8272.h index d1d9e8e68d..413ce640af 100644 --- a/include/configs/TQM8272.h +++ b/include/configs/TQM8272.h @@ -208,8 +208,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/ZPC1900.h b/include/configs/ZPC1900.h index 265b1112fe..4cda22fe4b 100644 --- a/include/configs/ZPC1900.h +++ b/include/configs/ZPC1900.h @@ -76,8 +76,8 @@ * - Select bus for bd/buffers (see 28-13) * - Full duplex */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) diff --git a/include/configs/ep8260.h b/include/configs/ep8260.h index b15659d918..f19360d501 100644 --- a/include/configs/ep8260.h +++ b/include/configs/ep8260.h @@ -200,8 +200,8 @@ * - RAM for BD/Buffers is on the local Bus (see 28-13) * - Enable Half Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) +# define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) /* * - RAM for BD/Buffers is on the local Bus (see 28-13) diff --git a/include/configs/gw8260.h b/include/configs/gw8260.h index 93d688581f..2a40de1fae 100644 --- a/include/configs/gw8260.h +++ b/include/configs/gw8260.h @@ -240,8 +240,8 @@ * - Select bus for bd/buffers (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) @@ -253,8 +253,8 @@ * - Select bus for bd/buffers (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) +# define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) diff --git a/include/configs/hymod.h b/include/configs/hymod.h index 7c4c2ba4ea..8c9f3d1f5a 100644 --- a/include/configs/hymod.h +++ b/include/configs/hymod.h @@ -89,8 +89,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK11) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1|CMXFCR_RF1CS_MSK|CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK11) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) @@ -110,8 +110,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) @@ -131,8 +131,8 @@ * - RAM for BD/Buffers is on the 60x Bus (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) +# define CONFIG_SYS_CMXFCR_MASK3 (CMXFCR_FC3|CMXFCR_RF3CS_MSK|CMXFCR_TF3CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE3 (CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB) diff --git a/include/configs/muas3001.h b/include/configs/muas3001.h index 8b3022b2c0..18bd37e91c 100644 --- a/include/configs/muas3001.h +++ b/include/configs/muas3001.h @@ -83,8 +83,8 @@ * - Rx-CLK is CLK11 * - Tx-CLK is CLK12 */ -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF1CS_CLK11 | CMXFCR_TF1CS_CLK12) -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC1 | CMXFCR_RF1CS_MSK | CMXFCR_TF1CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE1 (CMXFCR_RF1CS_CLK11 | CMXFCR_TF1CS_CLK12) +# define CONFIG_SYS_CMXFCR_MASK1 (CMXFCR_FC1 | CMXFCR_RF1CS_MSK | CMXFCR_TF1CS_MSK) /* * - RAM for BD/Buffers is on the 60x Bus (see 28-13) */ diff --git a/include/configs/ppmc8260.h b/include/configs/ppmc8260.h index 68c62770f2..327863ec90 100644 --- a/include/configs/ppmc8260.h +++ b/include/configs/ppmc8260.h @@ -372,8 +372,8 @@ * - Select bus for bd/buffers (see 28-13) * - Enable Full Duplex in FSMR */ -#define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -#define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +#define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +#define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) #endif /* CONFIG_ETHER_INDEX */ diff --git a/include/configs/rsdproto.h b/include/configs/rsdproto.h index 2ed189ef67..3a700419f2 100644 --- a/include/configs/rsdproto.h +++ b/include/configs/rsdproto.h @@ -82,8 +82,8 @@ * - Select bus for bd/buffers (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE (0) # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) diff --git a/include/configs/sacsng.h b/include/configs/sacsng.h index 914767ac1b..43036b2d3b 100644 --- a/include/configs/sacsng.h +++ b/include/configs/sacsng.h @@ -203,7 +203,7 @@ * - RX clk is CLK11 * - TX clk is CLK12 */ -# define CONFIG_SYS_CMXSCR_VALUE (CMXSCR_RS1CS_CLK11 | CMXSCR_TS1CS_CLK12) +# define CONFIG_SYS_CMXSCR_VALUE1 (CMXSCR_RS1CS_CLK11 | CMXSCR_TS1CS_CLK12) #elif defined(CONFIG_ETHER_ON_FCC) && (CONFIG_ETHER_INDEX == 2) @@ -213,8 +213,8 @@ * - Select bus for bd/buffers (see 28-13) * - Enable Full Duplex in FSMR */ -# define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) -# define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) +# define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK) +# define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14) # define CONFIG_SYS_CPMFCR_RAMTYPE 0 # define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE | FCC_PSMR_LPB) diff --git a/include/configs/sbc8560.h b/include/configs/sbc8560.h index d2199257f8..f928622f27 100644 --- a/include/configs/sbc8560.h +++ b/include/configs/sbc8560.h @@ -260,8 +260,8 @@ * - Select bus for bd/buffers * - Full duplex */ - #define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) - #define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) + #define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) + #define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE) diff --git a/include/configs/stxgp3.h b/include/configs/stxgp3.h index 90d249b964..6f611be900 100644 --- a/include/configs/stxgp3.h +++ b/include/configs/stxgp3.h @@ -255,8 +255,8 @@ * - Select bus for bd/buffers * - Full duplex */ - #define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) - #define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) + #define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) + #define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #if 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE) diff --git a/include/configs/stxssa.h b/include/configs/stxssa.h index 3d385b4253..50a615fc7a 100644 --- a/include/configs/stxssa.h +++ b/include/configs/stxssa.h @@ -285,8 +285,8 @@ * - Select bus for bd/buffers * - Full duplex */ - #define CONFIG_SYS_CMXFCR_MASK (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) - #define CONFIG_SYS_CMXFCR_VALUE (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) + #define CONFIG_SYS_CMXFCR_MASK2 (CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK) + #define CONFIG_SYS_CMXFCR_VALUE2 (CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14) #define CONFIG_SYS_CPMFCR_RAMTYPE 0 #if 0 #define CONFIG_SYS_FCC_PSMR (FCC_PSMR_FDE) -- cgit From 3c59e3986c1dea477cad8f1967843c0da0d9b174 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 22 Aug 2011 10:54:02 -0500 Subject: video: update the Freescale DIU driver to use linux/fb.h Update the Freescale DIU video driver (fsl_diu_fb.c) to use linux/fb.h. Some data structures from this header file were just copied into fsl_diu_fb.c. Signed-off-by: Timur Tabi --- drivers/video/fsl_diu_fb.c | 54 +++++----------------------------------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/drivers/video/fsl_diu_fb.c b/drivers/video/fsl_diu_fb.c index e1d6c2614c..cb439044fb 100644 --- a/drivers/video/fsl_diu_fb.c +++ b/drivers/video/fsl_diu_fb.c @@ -31,52 +31,8 @@ #include "videomodes.h" #include #include - -struct fb_var_screeninfo { - unsigned int xres; /* visible resolution */ - unsigned int yres; - - unsigned int bits_per_pixel; /* guess what */ - - /* Timing: All values in pixclocks, except pixclock (of course) */ - unsigned int pixclock; /* pixel clock in ps (pico seconds) */ - unsigned int left_margin; /* time from sync to picture */ - unsigned int right_margin; /* time from picture to sync */ - unsigned int upper_margin; /* time from sync to picture */ - unsigned int lower_margin; - unsigned int hsync_len; /* length of horizontal sync */ - unsigned int vsync_len; /* length of vertical sync */ - unsigned int sync; /* see FB_SYNC_* */ - unsigned int vmode; /* see FB_VMODE_* */ - unsigned int rotate; /* angle we rotate counter clockwise */ -}; - -struct fb_info { - struct fb_var_screeninfo var; /* Current var */ - unsigned int smem_len; /* Length of frame buffer mem */ - unsigned int type; /* see FB_TYPE_* */ - unsigned int line_length; /* length of a line in bytes */ - - void *screen_base; - unsigned long screen_size; -}; - -struct fb_videomode { - const char *name; /* optional */ - unsigned int refresh; /* optional */ - unsigned int xres; - unsigned int yres; - unsigned int pixclock; - unsigned int left_margin; - unsigned int right_margin; - unsigned int upper_margin; - unsigned int lower_margin; - unsigned int hsync_len; - unsigned int vsync_len; - unsigned int sync; - unsigned int vmode; - unsigned int flag; -}; +#include +#include /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */ static struct fb_videomode fsl_diu_mode_800_480 = { @@ -248,7 +204,7 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) * point to the framebuffer memory. Memory is aligned as needed. */ static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres, - unsigned int depth, void **fb) + unsigned int depth, char **fb) { unsigned long size = xres * yres * depth; struct diu_addr addr; @@ -327,10 +283,10 @@ int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix) info.var.vsync_len = fsl_diu_mode_db->vsync_len; info.var.sync = fsl_diu_mode_db->sync; info.var.vmode = fsl_diu_mode_db->vmode; - info.line_length = info.var.xres * info.var.bits_per_pixel / 8; + info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8; /* Memory allocation for framebuffer */ - info.smem_len = + info.screen_size = info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8); ad = allocate_fb(info.var.xres, info.var.yres, info.var.bits_per_pixel / 8, &info.screen_base); -- cgit From 63f832fbb89d519ee61bff4fa299b1c83ae8eed2 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Wed, 28 Sep 2011 11:21:15 +0200 Subject: VIDEO: MX5: Switch MX5 to CONFIG_VIDEO The framebuffer driver for MX5 is based on CONFIG_LCD. In the current implementation, there is a serious bug because the required memory is allocated before relocation, but the driver knows only later which is the resolution of the display. The patch switches the driver to CONFIG_VIDEO and the memory is allocated by the driver itself. We also need to switch the vision2 board code and config file in the same commit so that this commit will be bisectable. Signed-off-by: Stefano Babic CC: Anatolij Gustschin Tested-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- board/ttcontrol/vision2/vision2.c | 36 +++++++------ drivers/video/mxc_ipuv3_fb.c | 110 +++++++++++++------------------------- include/configs/vision2.h | 11 ++-- 3 files changed, 62 insertions(+), 95 deletions(-) diff --git a/board/ttcontrol/vision2/vision2.c b/board/ttcontrol/vision2/vision2.c index ebca7b6f36..ca0c100d11 100644 --- a/board/ttcontrol/vision2/vision2.c +++ b/board/ttcontrol/vision2/vision2.c @@ -600,6 +600,21 @@ int board_mmc_init(bd_t *bis) } #endif +void lcd_enable(void) +{ + int ret; + + mxc_request_iomux(MX51_PIN_DI1_PIN2, IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_DI1_PIN3, IOMUX_CONFIG_ALT0); + + gpio_set_value(2, 1); + mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT0); + + ret = mx51_fb_init(&nec_nl6448bc26_09c); + if (ret) + puts("LCD cannot be configured\n"); +} + int board_early_init_f(void) { @@ -636,26 +651,15 @@ static void backlight(int on) } } -void lcd_enable(void) -{ - int ret; - - mxc_request_iomux(MX51_PIN_DI1_PIN2, IOMUX_CONFIG_ALT0); - mxc_request_iomux(MX51_PIN_DI1_PIN3, IOMUX_CONFIG_ALT0); - - gpio_set_value(2, 1); - mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT0); - - ret = mx51_fb_init(&nec_nl6448bc26_09c); - if (ret) - puts("LCD cannot be configured\n"); -} - int board_init(void) { /* address of boot parameters */ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + lcd_enable(); + + backlight(1); + return 0; } @@ -676,6 +680,8 @@ int board_late_init(void) udelay(2000); #endif + setenv("stdout", "serial"); + return 0; } diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c index a66981c27c..eafacef530 100644 --- a/drivers/video/mxc_ipuv3_fb.c +++ b/drivers/video/mxc_ipuv3_fb.c @@ -27,7 +27,6 @@ * MA 02111-1307 USA */ -/* #define DEBUG */ #include #include #include @@ -35,43 +34,17 @@ #include #include #include -#include +#include #include "videomodes.h" #include "ipu.h" #include "mxcfb.h" -DECLARE_GLOBAL_DATA_PTR; - -void *lcd_base; /* Start of framebuffer memory */ -void *lcd_console_address; /* Start of console buffer */ - -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -short console_col; -short console_row; - -vidinfo_t panel_info; - static int mxcfb_map_video_memory(struct fb_info *fbi); static int mxcfb_unmap_video_memory(struct fb_info *fbi); -void lcd_initcolregs(void) -{ -} - -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) -{ -} - -void lcd_disable(void) -{ -} - -void lcd_panel_disable(void) -{ -} +/* graphics setup */ +static GraphicDevice panel; +struct fb_videomode *gmode; void fb_videomode_to_var(struct fb_var_screeninfo *var, const struct fb_videomode *mode) @@ -440,8 +413,8 @@ static int mxcfb_map_video_memory(struct fb_info *fbi) fbi->fix.line_length; } - fbi->screen_base = (char *)lcd_base; - fbi->fix.smem_start = (unsigned long)lcd_base; + fbi->screen_base = (char *)malloc(fbi->fix.smem_len); + fbi->fix.smem_start = (unsigned long)fbi->screen_base; if (fbi->screen_base == 0) { puts("Unable to allocate framebuffer memory\n"); fbi->fix.smem_len = 0; @@ -561,12 +534,12 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfb_info[mxcfbi->ipu_di] = fbi; /* Need dummy values until real panel is configured */ - fbi->var.xres = 640; - fbi->var.yres = 480; - fbi->var.bits_per_pixel = 16; mxcfbi->ipu_di_pix_fmt = interface_pix_fmt; fb_videomode_to_var(&fbi->var, mode); + fbi->var.bits_per_pixel = 16; + fbi->fix.line_length = fbi->var.xres * (fbi->var.bits_per_pixel / 8); + fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length; mxcfb_check_var(&fbi->var, fbi); @@ -581,19 +554,16 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfb_set_par(fbi); - /* Setting panel_info for lcd */ - panel_info.cmap = NULL; - panel_info.vl_col = fbi->var.xres; - panel_info.vl_row = fbi->var.yres; - panel_info.vl_bpix = LCD_BPP; + panel.winSizeX = mode->xres; + panel.winSizeY = mode->yres; + panel.plnSizeX = mode->xres; + panel.plnSizeY = mode->yres; - lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; + panel.frameAdrs = (u32)fbi->screen_base; + panel.memSize = fbi->screen_size; - debug("MXC IPUV3 configured\n" - "XRES = %d YRES = %d BitsXpixel = %d\n", - panel_info.vl_col, - panel_info.vl_row, - panel_info.vl_bpix); + panel.gdfBytesPP = 2; + panel.gdfIndex = GDF_16BIT_565RGB; ipu_dump_registers(); @@ -603,29 +573,7 @@ err0: return ret; } -int overwrite_console(void) -{ - /* Keep stdout / stderr on serial, our LCD is for splashscreen only */ - return 1; -} - -void lcd_ctrl_init(void *lcdbase) -{ - u32 mem_len = panel_info.vl_col * - panel_info.vl_row * - NBITS(panel_info.vl_bpix) / 8; - - /* - * We rely on lcdbase being a physical address, i.e., either MMU off, - * or 1-to-1 mapping. Might want to add some virt2phys here. - */ - if (!lcdbase) - return; - - memset(lcdbase, 0, mem_len); -} - -int mx51_fb_init(struct fb_videomode *mode) +void *video_hw_init(void) { int ret; @@ -633,10 +581,24 @@ int mx51_fb_init(struct fb_videomode *mode) if (ret) puts("Error initializing IPU\n"); - lcd_base += 56; + ret = mxcfb_probe(IPU_PIX_FMT_RGB666, gmode); + debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs); - debug("Framebuffer at 0x%x\n", (unsigned int)lcd_base); - ret = mxcfb_probe(IPU_PIX_FMT_RGB666, mode); + return (void *)&panel; +} - return ret; +void video_set_lut(unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ) +{ + return; +} + +int mx51_fb_init(struct fb_videomode *mode) +{ + gmode = mode; + + return 0; } diff --git a/include/configs/vision2.h b/include/configs/vision2.h index 540dfa9f6b..3b42afc923 100644 --- a/include/configs/vision2.h +++ b/include/configs/vision2.h @@ -46,7 +46,7 @@ /* * Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (2048 * 1024) +#define CONFIG_SYS_MALLOC_LEN (10 * 1024 * 1024) /* * Hardware drivers @@ -207,12 +207,11 @@ * Framebuffer and LCD */ #define CONFIG_PREBOOT -#define CONFIG_LCD +#define CONFIG_VIDEO #define CONFIG_VIDEO_MX5 -#define CONFIG_SYS_CONSOLE_ENV_OVERWRITE -#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE -#define CONFIG_SYS_CONSOLE_IS_IN_ENV -#define LCD_BPP LCD_COLOR16 +#define CONFIG_CFB_CONSOLE +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_VIDEO_BMP_RLE8 #define CONFIG_SPLASH_SCREEN #define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP -- cgit From 3d1d5e2379d4dd31a7637d16a35405358d44da3a Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Wed, 28 Sep 2011 11:21:16 +0200 Subject: VIDEO: MX5: export pix format Pixel format defines must be available for boards to set up the right display. Move them and export in a new file. Signed-off-by: Stefano Babic CC: Anatolij Gustschin CC: Marek Vasut Tested-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- drivers/video/ipu.h | 46 +------------------------------ include/ipu_pixfmt.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 include/ipu_pixfmt.h diff --git a/drivers/video/ipu.h b/drivers/video/ipu.h index d8bc287d84..99a2491cf5 100644 --- a/drivers/video/ipu.h +++ b/drivers/video/ipu.h @@ -31,6 +31,7 @@ #define __ASM_ARCH_IPU_H__ #include +#include #define IDMA_CHAN_INVALID 0xFF #define HIGH_RESOLUTION_WIDTH 1024 @@ -89,51 +90,6 @@ typedef enum { IPU_PANEL_TFT, } ipu_panel_t; -/* IPU Pixel format definitions */ -#define fourcc(a, b, c, d)\ - (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) - -/* - * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are - * the same used by V4L2 API. - */ - -#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0') -#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1') -#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6') -#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8') - -#define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*< 8 RGB-3-3-2 */ -#define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*< 16 RGB-5-5-5 */ -#define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*< 1 6 RGB-5-6-5 */ -#define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*< 18 RGB-6-6-6 */ -#define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*< 18 BGR-6-6-6 */ -#define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*< 24 BGR-8-8-8 */ -#define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*< 24 RGB-8-8-8 */ -#define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*< 32 BGR-8-8-8-8 */ -#define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*< 32 BGR-8-8-8-8 */ -#define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*< 32 RGB-8-8-8-8 */ -#define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*< 32 RGB-8-8-8-8 */ -#define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*< 32 ABGR-8-8-8-8 */ - -/* YUV Interleaved Formats */ -#define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*< 16 YUV 4:2:2 */ -#define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*< 16 YUV 4:2:2 */ -#define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*< 12 YUV 4:1:1 */ -#define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*< 24 YUV 4:4:4 */ - -/* two planes -- one Y, one Cb + Cr interleaved */ -#define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ - -#define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*< 8 Greyscale */ -#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*< 9 YVU 4:1:0 */ -#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*< 9 YUV 4:1:0 */ -#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*< 12 YVU 4:2:0 */ -#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*< 12 YUV 4:2:0 */ -#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*< 12 YUV 4:2:0 */ -#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*< 16 YVU 4:2:2 */ -#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*< 16 YUV 4:2:2 */ - /* * IPU Driver channels definitions. * Note these are different from IDMA channels diff --git a/include/ipu_pixfmt.h b/include/ipu_pixfmt.h new file mode 100644 index 0000000000..0497bff2d2 --- /dev/null +++ b/include/ipu_pixfmt.h @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2011 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de + * + * Based on Linux IPU driver for MX51 (ipu.h): + * + * (C) Copyright 2005-2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#ifndef __IPU_PIXFMT_H__ +#define __IPU_PIXFMT_H__ + +/* IPU Pixel format definitions */ +#define fourcc(a, b, c, d)\ + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + +/* + * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are + * the same used by V4L2 API. + */ + +#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0') +#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1') +#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6') +#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8') + +#define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*< 8 RGB-3-3-2 */ +#define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*< 16 RGB-5-5-5 */ +#define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*< 1 6 RGB-5-6-5 */ +#define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*< 18 RGB-6-6-6 */ +#define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*< 18 BGR-6-6-6 */ +#define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*< 24 BGR-8-8-8 */ +#define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*< 24 RGB-8-8-8 */ +#define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*< 32 BGR-8-8-8-8 */ +#define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*< 32 BGR-8-8-8-8 */ +#define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*< 32 RGB-8-8-8-8 */ +#define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*< 32 RGB-8-8-8-8 */ +#define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*< 32 ABGR-8-8-8-8 */ + +/* YUV Interleaved Formats */ +#define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*< 16 YUV 4:2:2 */ +#define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*< 16 YUV 4:2:2 */ +#define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*< 12 YUV 4:1:1 */ +#define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*< 24 YUV 4:4:4 */ + +/* two planes -- one Y, one Cb + Cr interleaved */ +#define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ + +#define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*< 8 Greyscale */ +#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*< 9 YVU 4:1:0 */ +#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*< 9 YUV 4:1:0 */ +#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*< 12 YVU 4:2:0 */ +#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*< 12 YUV 4:2:0 */ +#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*< 12 YUV 4:2:0 */ +#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*< 16 YVU 4:2:2 */ +#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*< 16 YUV 4:2:2 */ + +#endif -- cgit From 711a6722f97d21404d04c7a36ccfdc6e2b442229 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 6 Oct 2011 00:25:03 +0200 Subject: MX5: Make IPU display output and pixel format configurable Signed-off-by: Marek Vasut Signed-off-by: Stefano Babic Tested-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- board/ttcontrol/vision2/vision2.c | 6 +++--- drivers/video/mxc_ipuv3_fb.c | 15 ++++++++++----- include/ipu_pixfmt.h | 5 +++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/board/ttcontrol/vision2/vision2.c b/board/ttcontrol/vision2/vision2.c index ca0c100d11..e496f64312 100644 --- a/board/ttcontrol/vision2/vision2.c +++ b/board/ttcontrol/vision2/vision2.c @@ -39,12 +39,12 @@ #include #include +#include + DECLARE_GLOBAL_DATA_PTR; static u32 system_rev; -extern int mx51_fb_init(struct fb_videomode *mode); - static struct fb_videomode nec_nl6448bc26_09c = { "NEC_NL6448BC26-09C", 60, /* Refresh */ @@ -610,7 +610,7 @@ void lcd_enable(void) gpio_set_value(2, 1); mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT0); - ret = mx51_fb_init(&nec_nl6448bc26_09c); + ret = mx51_fb_init(&nec_nl6448bc26_09c, 0, IPU_PIX_FMT_RGB666); if (ret) puts("LCD cannot be configured\n"); } diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c index eafacef530..1bee54c1a1 100644 --- a/drivers/video/mxc_ipuv3_fb.c +++ b/drivers/video/mxc_ipuv3_fb.c @@ -44,7 +44,9 @@ static int mxcfb_unmap_video_memory(struct fb_info *fbi); /* graphics setup */ static GraphicDevice panel; -struct fb_videomode *gmode; +static struct fb_videomode *gmode; +static uint8_t gdisp; +static uint32_t gpixfmt; void fb_videomode_to_var(struct fb_var_screeninfo *var, const struct fb_videomode *mode) @@ -499,7 +501,8 @@ static struct fb_info *mxcfb_init_fbinfo(void) * * @return Appropriate error code to the kernel common code */ -static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) +static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp, + struct fb_videomode *mode) { struct fb_info *fbi; struct mxcfb_info *mxcfbi; @@ -523,7 +526,7 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfbi->blank = FB_BLANK_POWERDOWN; } - mxcfbi->ipu_di = 0; + mxcfbi->ipu_di = disp; ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80); ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0); @@ -581,7 +584,7 @@ void *video_hw_init(void) if (ret) puts("Error initializing IPU\n"); - ret = mxcfb_probe(IPU_PIX_FMT_RGB666, gmode); + ret = mxcfb_probe(gpixfmt, gdisp, gmode); debug("Framebuffer at 0x%x\n", (unsigned int)panel.frameAdrs); return (void *)&panel; @@ -596,9 +599,11 @@ void video_set_lut(unsigned int index, /* color number */ return; } -int mx51_fb_init(struct fb_videomode *mode) +int mx51_fb_init(struct fb_videomode *mode, uint8_t disp, uint32_t pixfmt) { gmode = mode; + gdisp = disp; + gpixfmt = pixfmt; return 0; } diff --git a/include/ipu_pixfmt.h b/include/ipu_pixfmt.h index 0497bff2d2..656f605462 100644 --- a/include/ipu_pixfmt.h +++ b/include/ipu_pixfmt.h @@ -28,6 +28,9 @@ #ifndef __IPU_PIXFMT_H__ #define __IPU_PIXFMT_H__ +#include +#include + /* IPU Pixel format definitions */ #define fourcc(a, b, c, d)\ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) @@ -73,4 +76,6 @@ #define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*< 16 YVU 4:2:2 */ #define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*< 16 YUV 4:2:2 */ +int mx51_fb_init(struct fb_videomode *mode, uint8_t disp, uint32_t pixfmt); + #endif -- cgit From 3f480bf7c3852ab5ec0d7a1a10f95e50135ac9f5 Mon Sep 17 00:00:00 2001 From: Helmut Raiger Date: Wed, 12 Oct 2011 23:08:30 +0200 Subject: mx31: make HSP clock for mx3fb driver available This additionally updates mx31/generic.c by - replacing __REG() macro accesses with readl() and writel() - providing macros for PDR0 and PLL bit accesses Signed-off-by: Helmut Raiger Acked-by: Marek Vasut Cc: Stefano Babic Acked-by: Stefano Babic Signed-off-by: Anatolij Gustschin --- arch/arm/cpu/arm1136/mx31/generic.c | 40 +++++++++++++++++++++---------- arch/arm/include/asm/arch-mx31/clock.h | 1 + arch/arm/include/asm/arch-mx31/imx-regs.h | 14 +++++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c index c6def5df9b..5524b23275 100644 --- a/arch/arm/cpu/arm1136/mx31/generic.c +++ b/arch/arm/cpu/arm1136/mx31/generic.c @@ -28,10 +28,10 @@ static u32 mx31_decode_pll(u32 reg, u32 infreq) { - u32 mfi = (reg >> 10) & 0xf; - u32 mfn = reg & 0x3ff; - u32 mfd = (reg >> 16) & 0x3ff; - u32 pd = (reg >> 26) & 0xf; + u32 mfi = GET_PLL_MFI(reg); + u32 mfn = GET_PLL_MFN(reg); + u32 mfd = GET_PLL_MFD(reg); + u32 pd = GET_PLL_PD(reg); mfi = mfi <= 5 ? 5 : mfi; mfd += 1; @@ -45,12 +45,12 @@ static u32 mx31_get_mpl_dpdgck_clk(void) { u32 infreq; - if ((__REG(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) + if ((readl(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) infreq = CONFIG_MX31_CLK32 * 1024; else infreq = CONFIG_MX31_HCLK_FREQ; - return mx31_decode_pll(__REG(CCM_MPCTL), infreq); + return mx31_decode_pll(readl(CCM_MPCTL), infreq); } static u32 mx31_get_mcu_main_clk(void) @@ -64,10 +64,21 @@ static u32 mx31_get_mcu_main_clk(void) static u32 mx31_get_ipg_clk(void) { u32 freq = mx31_get_mcu_main_clk(); - u32 pdr0 = __REG(CCM_PDR0); + u32 pdr0 = readl(CCM_PDR0); - freq /= ((pdr0 >> 3) & 0x7) + 1; - freq /= ((pdr0 >> 6) & 0x3) + 1; + freq /= GET_PDR0_MAX_PODF(pdr0) + 1; + freq /= GET_PDR0_IPG_PODF(pdr0) + 1; + + return freq; +} + +/* hsp is the clock for the ipu */ +static u32 mx31_get_hsp_clk(void) +{ + u32 freq = mx31_get_mcu_main_clk(); + u32 pdr0 = readl(CCM_PDR0); + + freq /= GET_PDR0_HSP_PODF(pdr0) + 1; return freq; } @@ -77,6 +88,7 @@ void mx31_dump_clocks(void) u32 cpufreq = mx31_get_mcu_main_clk(); printf("mx31 cpu clock: %dMHz\n",cpufreq / 1000000); printf("ipg clock : %dHz\n", mx31_get_ipg_clk()); + printf("hsp clock : %dHz\n", mx31_get_hsp_clk()); } unsigned int mxc_get_clock(enum mxc_clock clk) @@ -89,6 +101,8 @@ unsigned int mxc_get_clock(enum mxc_clock clk) case MXC_CSPI_CLK: case MXC_UART_CLK: return mx31_get_ipg_clk(); + case MXC_IPU_CLK: + return mx31_get_hsp_clk(); } return -1; } @@ -105,10 +119,10 @@ void mx31_gpio_mux(unsigned long mode) reg = IOMUXC_BASE + (mode & 0x1fc); shift = (~mode & 0x3) * 8; - tmp = __REG(reg); + tmp = readl(reg); tmp &= ~(0xff << shift); tmp |= ((mode >> IOMUX_MODE_POS) & 0xff) << shift; - __REG(reg) = tmp; + writel(tmp, reg); } void mx31_set_pad(enum iomux_pins pin, u32 config) @@ -119,10 +133,10 @@ void mx31_set_pad(enum iomux_pins pin, u32 config) reg = (IOMUXC_BASE + 0x154) + (pin + 2) / 3 * 4; field = (pin + 2) % 3; - l = __REG(reg); + l = readl(reg); l &= ~(0x1ff << (field * 10)); l |= config << (field * 10); - __REG(reg) = l; + writel(l, reg); } diff --git a/arch/arm/include/asm/arch-mx31/clock.h b/arch/arm/include/asm/arch-mx31/clock.h index cc99a75e92..2e3bce2c31 100644 --- a/arch/arm/include/asm/arch-mx31/clock.h +++ b/arch/arm/include/asm/arch-mx31/clock.h @@ -30,6 +30,7 @@ enum mxc_clock { MXC_IPG_PERCLK, MXC_CSPI_CLK, MXC_UART_CLK, + MXC_IPU_CLK }; unsigned int mxc_get_clock(enum mxc_clock clk); diff --git a/arch/arm/include/asm/arch-mx31/imx-regs.h b/arch/arm/include/asm/arch-mx31/imx-regs.h index 0dcd9fe7eb..f263e6bcfa 100644 --- a/arch/arm/include/asm/arch-mx31/imx-regs.h +++ b/arch/arm/include/asm/arch-mx31/imx-regs.h @@ -513,6 +513,20 @@ enum iomux_pins { #define PLL_MFI(x) (((x) & 0xf) << 10) #define PLL_MFN(x) (((x) & 0x3ff) << 0) +#define GET_PDR0_CSI_PODF(x) (((x) >> 23) & 0x1ff) +#define GET_PDR0_PER_PODF(x) (((x) >> 16) & 0x1f) +#define GET_PDR0_HSP_PODF(x) (((x) >> 11) & 0x7) +#define GET_PDR0_NFC_PODF(x) (((x) >> 8) & 0x7) +#define GET_PDR0_IPG_PODF(x) (((x) >> 6) & 0x3) +#define GET_PDR0_MAX_PODF(x) (((x) >> 3) & 0x7) +#define GET_PDR0_MCU_PODF(x) ((x) & 0x7) + +#define GET_PLL_PD(x) (((x) >> 26) & 0xf) +#define GET_PLL_MFD(x) (((x) >> 16) & 0x3ff) +#define GET_PLL_MFI(x) (((x) >> 10) & 0xf) +#define GET_PLL_MFN(x) (((x) >> 0) & 0x3ff) + + #define WEIM_ESDCTL0 0xB8001000 #define WEIM_ESDCFG0 0xB8001004 #define WEIM_ESDCTL1 0xB8001008 -- cgit From 82a04900a5613d62a778436388e42f4fddf6c469 Mon Sep 17 00:00:00 2001 From: Helmut Raiger Date: Wed, 12 Oct 2011 23:16:29 +0000 Subject: video: Moving mx3fb.c to CONFIG_VIDEO mx3fb.c was based on CONFIG_LCD and is moved by this patch to CONFIG_VIDEO, which has greater freedom in selecting videomodes even at runtime. This renders the accumulating list of display defines (CONFIG_DISPLAY_VBEST..., CONFIG_DISPLAY_C057...) obsolete as these may be setup through env variables: uboot> setenv mydisplay 'video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925, le:9,ri:17,up:7,lo:10,hs:1,vs:1,sync:100663296,vmode:0' uboot> setenv videomode ${mydisplay} This commit also fixes the board config files for qong and imx31_phycore boards as needed. The videomode settings of previously supported displays are added to CONFIG_EXTRA_ENV_SETTINGS now. CONFIG_SYS_MALLOC_LEN for imx31_phycore board is increased to make the frame buffer allocation working with the changed driver. Signed-off-by: Helmut Raiger Signed-off-by: Anatolij Gustschin Cc: Stefano Babic --- drivers/video/Makefile | 2 +- drivers/video/cfb_console.c | 7 + drivers/video/mx3fb.c | 459 +++++++++++++++++++++++----------------- include/configs/imx31_phycore.h | 24 ++- include/configs/qong.h | 14 +- 5 files changed, 297 insertions(+), 209 deletions(-) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 3790f91e72..ecc1896d57 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -35,7 +35,7 @@ COBJS-$(CONFIG_VIDEO_AMBA) += amba.o COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o COBJS-$(CONFIG_VIDEO_MB86R0xGDC) += mb86r0xgdc.o videomodes.o -COBJS-$(CONFIG_VIDEO_MX3) += mx3fb.o +COBJS-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o COBJS-$(CONFIG_VIDEO_MX5) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o COBJS-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o videomodes.o COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 3a93b64dad..4e653b8279 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -160,6 +160,13 @@ #endif #endif +/* + * Defines for the i.MX31 driver (mx3fb.c) + */ +#ifdef CONFIG_VIDEO_MX3 +#define VIDEO_FB_16BPP_WORD_SWAP +#endif + /* * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc. */ diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 0c925a03f3..f30deb3922 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1,6 +1,8 @@ /* * Copyright (C) 2009 * Guennadi Liakhovetski, DENX Software Engineering, + * Copyright (C) 2011 + * HALE electronic GmbH, * * See file CREDITS for list of people who contributed to this * project. @@ -21,100 +23,20 @@ * MA 02111-1307 USA */ #include -#include -#include +#include +#include + #include +#include #include +#include -DECLARE_GLOBAL_DATA_PTR; - -void *lcd_base; /* Start of framebuffer memory */ -void *lcd_console_address; /* Start of console buffer */ - -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -short console_col; -short console_row; - -void lcd_initcolregs(void) -{ -} - -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) -{ -} - -void lcd_disable(void) -{ -} - -void lcd_panel_disable(void) -{ -} +#include "videomodes.h" -#define msleep(a) udelay(a * 1000) - -#if defined(CONFIG_DISPLAY_VBEST_VGG322403) -#define XRES 320 -#define YRES 240 -#define PANEL_TYPE IPU_PANEL_TFT -#define PIXEL_CLK 156000 -#define PIXEL_FMT IPU_PIX_FMT_RGB666 -#define H_START_WIDTH 20 /* left_margin */ -#define H_SYNC_WIDTH 30 /* hsync_len */ -#define H_END_WIDTH (38 + 30) /* right_margin + hsync_len */ -#define V_START_WIDTH 7 /* upper_margin */ -#define V_SYNC_WIDTH 3 /* vsync_len */ -#define V_END_WIDTH (26 + 3) /* lower_margin + vsync_len */ -#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) +/* this might need panel specific set-up as-well */ #define IF_CONF 0 -#define IF_CLK_DIV 0x175 -#elif defined(CONFIG_DISPLAY_COM57H5M10XRC) -#define XRES 640 -#define YRES 480 -#define PANEL_TYPE IPU_PANEL_TFT -#define PIXEL_CLK 40000 -#define PIXEL_FMT IPU_PIX_FMT_RGB666 -#define H_START_WIDTH 120 /* left_margin */ -#define H_SYNC_WIDTH 30 /* hsync_len */ -#define H_END_WIDTH (10 + 30) /* right_margin + hsync_len */ -#define V_START_WIDTH 35 /* upper_margin */ -#define V_SYNC_WIDTH 3 /* vsync_len */ -#define V_END_WIDTH (7 + 3) /* lower_margin + vsync_len */ -#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) -#define IF_CONF 0 -#define IF_CLK_DIV 0x55 -#else -#define XRES 240 -#define YRES 320 -#define PANEL_TYPE IPU_PANEL_TFT -#define PIXEL_CLK 185925 -#define PIXEL_FMT IPU_PIX_FMT_RGB666 -#define H_START_WIDTH 9 /* left_margin */ -#define H_SYNC_WIDTH 1 /* hsync_len */ -#define H_END_WIDTH (16 + 1) /* right_margin + hsync_len */ -#define V_START_WIDTH 7 /* upper_margin */ -#define V_SYNC_WIDTH 1 /* vsync_len */ -#define V_END_WIDTH (9 + 1) /* lower_margin + vsync_len */ -#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) -#define IF_CONF 0 -#define IF_CLK_DIV 0x175 -#endif - -#define LCD_COLOR_IPU LCD_COLOR16 - -static ushort colormap[256]; - -vidinfo_t panel_info = { - .vl_col = XRES, - .vl_row = YRES, - .vl_bpix = LCD_COLOR_IPU, - .cmap = colormap, -}; -#define BIT_PER_PIXEL NBITS(LCD_COLOR_IPU) +/* -------------- controller specific stuff -------------- */ /* IPU DMA Controller channel definitions. */ enum ipu_channel { @@ -438,89 +360,134 @@ union chan_param_mem { struct chan_param_mem_interleaved ip; }; -static inline u32 reg_read(unsigned long reg) -{ - return __REG(reg); -} +DECLARE_GLOBAL_DATA_PTR; -static inline void reg_write(u32 value, unsigned long reg) -{ - __REG(reg) = value; -} +/* graphics setup */ +static GraphicDevice panel; +static struct ctfb_res_modes *mode; +static struct ctfb_res_modes var_mode; /* * sdc_init_panel() - initialize a synchronous LCD panel. * @width: width of panel in pixels. * @height: height of panel in pixels. - * @pixel_fmt: pixel format of buffer as FOURCC ASCII code. + * @di_setup: pixel format of the frame buffer + * @di_panel: either SHARP or normal TFT * @return: 0 on success or negative error code on failure. */ -static int sdc_init_panel(u16 width, u16 height, enum pixel_fmt pixel_fmt) +static int sdc_init_panel(u16 width, u16 height, + enum pixel_fmt di_setup, enum ipu_panel di_panel) { - u32 reg; + u32 reg, div; uint32_t old_conf; + int clock; + + debug("%s(width=%d, height=%d)\n", __func__, width, height); + + /* Init clocking, the IPU receives its clock from the hsp divder */ + clock = mxc_get_clock(MXC_IPU_CLK); + if (clock < 0) + return -EACCES; /* Init panel size and blanking periods */ - reg = ((H_SYNC_WIDTH - 1) << 26) | - ((u32)(width + H_START_WIDTH + H_END_WIDTH - 1) << 16); - reg_write(reg, SDC_HOR_CONF); + reg = width + mode->left_margin + mode->right_margin - 1; + if (reg > 1023) { + printf("mx3fb: Display width too large, coerced to 1023!"); + reg = 1023; + } + reg = ((mode->hsync_len - 1) << 26) | (reg << 16); + writel(reg, SDC_HOR_CONF); - reg = ((V_SYNC_WIDTH - 1) << 26) | SDC_V_SYNC_WIDTH_L | - ((u32)(height + V_START_WIDTH + V_END_WIDTH - 1) << 16); - reg_write(reg, SDC_VER_CONF); + reg = height + mode->upper_margin + mode->lower_margin - 1; + if (reg > 1023) { + printf("mx3fb: Display height too large, coerced to 1023!"); + reg = 1023; + } + reg = ((mode->vsync_len - 1) << 26) | SDC_V_SYNC_WIDTH_L | (reg << 16); + writel(reg, SDC_VER_CONF); - switch (PANEL_TYPE) { + switch (di_panel) { case IPU_PANEL_SHARP_TFT: - reg_write(0x00FD0102L, SDC_SHARP_CONF_1); - reg_write(0x00F500F4L, SDC_SHARP_CONF_2); - reg_write(SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); + writel(0x00FD0102L, SDC_SHARP_CONF_1); + writel(0x00F500F4L, SDC_SHARP_CONF_2); + writel(SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); + /* TODO: probably IF_CONF must be adapted (see below)! */ break; case IPU_PANEL_TFT: - reg_write(SDC_COM_TFT_COLOR, SDC_COM_CONF); + writel(SDC_COM_TFT_COLOR, SDC_COM_CONF); break; default: return -EINVAL; } - /* Init clocking */ - /* - * Calculate divider: fractional part is 4 bits so simply multiple by - * 2^4 to get fractional part, as long as we stay under ~250MHz and on - * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz + * Calculate divider: The fractional part is 4 bits so simply + * multiple by 2^4 to get it. + * + * Opposed to the kernel driver mode->pixclock is the time of one + * pixel in pico seconds, so: + * pixel_clk = 1e12 / mode->pixclock + * div = ipu_clk * 16 / pixel_clk + * leads to: + * div = ipu_clk * 16 / (1e12 / mode->pixclock) + * or: + * div = ipu_clk * 16 * mode->pixclock / 1e12 + * + * To avoid integer overflows this is split into 2 shifts and + * one divide with sufficient accuracy: + * 16*1024*128*476837 = 0.9999996682e12 + */ + div = ((clock/1024) * (mode->pixclock/128)) / 476837; + debug("hsp_clk is %d, div=%d\n", clock, div); + /* coerce to not less than 4.0, not more than 255.9375 */ + if (div < 0x40) + div = 0x40; + else if (div > 0xFFF) + div = 0xFFF; + /* DISP3_IF_CLK_DOWN_WR is half the divider value and 2 less + * fraction bits. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR + * based on timing debug DISP3_IF_CLK_UP_WR is 0 */ + writel((((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF); - reg_write((((IF_CLK_DIV / 8) - 1) << 22) | - IF_CLK_DIV, DI_DISP3_TIME_CONF); + /* DI settings for display 3: clock idle (bit 26) during vsync */ + old_conf = readl(DI_DISP_IF_CONF) & 0x78FFFFFF; + writel(old_conf | IF_CONF, DI_DISP_IF_CONF); - /* DI settings */ - old_conf = reg_read(DI_DISP_IF_CONF) & 0x78FFFFFF; - reg_write(old_conf | IF_CONF, DI_DISP_IF_CONF); + /* only set display 3 polarity bits */ + old_conf = readl(DI_DISP_SIG_POL) & 0xE0FFFFFF; + writel(old_conf | mode->sync, DI_DISP_SIG_POL); - old_conf = reg_read(DI_DISP_SIG_POL) & 0xE0FFFFFF; - reg_write(old_conf | SIG_POL, DI_DISP_SIG_POL); + writel(fmt_cfg[di_setup].b0, DI_DISP3_B0_MAP); + writel(fmt_cfg[di_setup].b1, DI_DISP3_B1_MAP); + writel(fmt_cfg[di_setup].b2, DI_DISP3_B2_MAP); + writel(readl(DI_DISP_ACC_CC) | + ((fmt_cfg[di_setup].acc - 1) << 12), DI_DISP_ACC_CC); - reg_write(fmt_cfg[pixel_fmt].b0, DI_DISP3_B0_MAP); - reg_write(fmt_cfg[pixel_fmt].b1, DI_DISP3_B1_MAP); - reg_write(fmt_cfg[pixel_fmt].b2, DI_DISP3_B2_MAP); - reg_write(reg_read(DI_DISP_ACC_CC) | - ((fmt_cfg[pixel_fmt].acc - 1) << 12), DI_DISP_ACC_CC); + debug("DI_DISP_IF_CONF = 0x%08X\n", readl(DI_DISP_IF_CONF)); + debug("DI_DISP_SIG_POL = 0x%08X\n", readl(DI_DISP_SIG_POL)); + debug("DI_DISP3_TIME_CONF = 0x%08X\n", readl(DI_DISP3_TIME_CONF)); + debug("SDC_HOR_CONF = 0x%08X\n", readl(SDC_HOR_CONF)); + debug("SDC_VER_CONF = 0x%08X\n", readl(SDC_VER_CONF)); return 0; } static void ipu_ch_param_set_size(union chan_param_mem *params, - uint32_t pixel_fmt, uint16_t width, + uint pixelfmt, uint16_t width, uint16_t height, uint16_t stride) { + debug("%s(pixelfmt=%d, width=%d, height=%d, stride=%d)\n", + __func__, pixelfmt, width, height, stride); + params->pp.fw = width - 1; params->pp.fh_l = height - 1; params->pp.fh_h = (height - 1) >> 8; params->pp.sl = stride - 1; /* See above, for further formats see the Linux driver */ - switch (pixel_fmt) { - case IPU_PIX_FMT_RGB565: + switch (pixelfmt) { + case GDF_16BIT_565RGB: params->ip.bpp = 2; params->ip.pfs = 4; params->ip.npb = 7; @@ -533,7 +500,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, params->ip.wid1 = 5; /* Green bit width - 1 */ params->ip.wid2 = 4; /* Blue bit width - 1 */ break; - case IPU_PIX_FMT_RGB24: + case GDF_32BIT_X888RGB: params->ip.bpp = 1; /* 24 BPP & RGB PFS */ params->ip.pfs = 4; params->ip.npb = 7; @@ -547,6 +514,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, params->ip.wid2 = 7; /* Blue bit width - 1 */ break; default: + printf("mx3fb: Pixel format not supported!\n"); break; } @@ -564,8 +532,8 @@ static void ipu_write_param_mem(uint32_t addr, uint32_t *data, uint32_t num_words) { for (; num_words > 0; num_words--) { - reg_write(addr, IPU_IMA_ADDR); - reg_write(*data++, IPU_IMA_DATA); + writel(addr, IPU_IMA_ADDR); + writel(*data++, IPU_IMA_DATA); addr++; if ((addr & 0x7) == 5) { addr &= ~0x7; /* set to word 0 */ @@ -574,16 +542,6 @@ static void ipu_write_param_mem(uint32_t addr, uint32_t *data, } } -static uint32_t bpp_to_pixfmt(int bpp) -{ - switch (bpp) { - case 16: - return IPU_PIX_FMT_RGB565; - default: - return 0; - } -} - static uint32_t dma_param_addr(enum ipu_channel channel) { /* Channel Parameter Memory */ @@ -596,11 +554,13 @@ static void ipu_init_channel_buffer(enum ipu_channel channel, void *fbmem) uint32_t reg; uint32_t stride_bytes; - stride_bytes = (XRES * ((BIT_PER_PIXEL + 7) / 8) + 3) & ~3; + stride_bytes = (panel.plnSizeX * panel.gdfBytesPP + 3) & ~3; + + debug("%s(channel=%d, fbmem=%p)\n", __func__, channel, fbmem); /* Build parameter memory data for DMA channel */ - ipu_ch_param_set_size(¶ms, bpp_to_pixfmt(BIT_PER_PIXEL), - XRES, YRES, stride_bytes); + ipu_ch_param_set_size(¶ms, panel.gdfIndex, + panel.plnSizeX, panel.plnSizeY, stride_bytes); ipu_ch_param_set_buffer(¶ms, fbmem, NULL); params.pp.bam = 0; /* Some channels (rotation) have restriction on burst length */ @@ -617,22 +577,22 @@ static void ipu_init_channel_buffer(enum ipu_channel channel, void *fbmem) ipu_write_param_mem(dma_param_addr(channel), (uint32_t *)¶ms, 10); /* Disable double-buffering */ - reg = reg_read(IPU_CHA_DB_MODE_SEL); + reg = readl(IPU_CHA_DB_MODE_SEL); reg &= ~(1UL << channel); - reg_write(reg, IPU_CHA_DB_MODE_SEL); + writel(reg, IPU_CHA_DB_MODE_SEL); } static void ipu_channel_set_priority(enum ipu_channel channel, int prio) { - u32 reg = reg_read(IDMAC_CHA_PRI); + u32 reg = readl(IDMAC_CHA_PRI); if (prio) reg |= 1UL << channel; else reg &= ~(1UL << channel); - reg_write(reg, IDMAC_CHA_PRI); + writel(reg, IDMAC_CHA_PRI); } /* @@ -645,7 +605,7 @@ static int ipu_enable_channel(enum ipu_channel channel) uint32_t reg; /* Reset to buffer 0 */ - reg_write(1UL << channel, IPU_CHA_CUR_BUF); + writel(1UL << channel, IPU_CHA_CUR_BUF); switch (channel) { case IDMAC_SDC_0: @@ -655,8 +615,8 @@ static int ipu_enable_channel(enum ipu_channel channel) break; } - reg = reg_read(IDMAC_CHA_EN); - reg_write(reg | (1UL << channel), IDMAC_CHA_EN); + reg = readl(IDMAC_CHA_EN); + writel(reg | (1UL << channel), IDMAC_CHA_EN); return 0; } @@ -665,13 +625,13 @@ static int ipu_update_channel_buffer(enum ipu_channel channel, void *buf) { uint32_t reg; - reg = reg_read(IPU_CHA_BUF0_RDY); + reg = readl(IPU_CHA_BUF0_RDY); if (reg & (1UL << channel)) return -EACCES; /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 0) */ - reg_write(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); - reg_write((u32)buf, IPU_IMA_DATA); + writel(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); + writel((u32)buf, IPU_IMA_DATA); return 0; } @@ -690,7 +650,7 @@ static int idmac_tx_submit(enum ipu_channel channel, void *buf) /* ipu_idmac.c::ipu_select_buffer() */ /* Mark buffer 0 as ready. */ - reg_write(1UL << channel, IPU_CHA_BUF0_RDY); + writel(1UL << channel, IPU_CHA_BUF0_RDY); ret = ipu_enable_channel(channel); @@ -706,8 +666,8 @@ static void sdc_enable_channel(void *fbmem) /* mx3fb.c::sdc_fb_init() */ if (ret >= 0) { - reg = reg_read(SDC_COM_CONF); - reg_write(reg | SDC_COM_BG_EN, SDC_COM_CONF); + reg = readl(SDC_COM_CONF); + writel(reg | SDC_COM_BG_EN, SDC_COM_CONF); } /* @@ -715,31 +675,33 @@ static void sdc_enable_channel(void *fbmem) * interrupts. Next sdc_set_brightness() is going to be called * from mx3fb_blank(). */ - msleep(2); + udelay(2000); } /* * mx3fb_set_par() - set framebuffer parameters and change the operating mode. * @return: 0 on success or negative error code on failure. + * TODO: currently only 666 and TFT as DI setup supported */ static int mx3fb_set_par(void) { int ret; - ret = sdc_init_panel(XRES, YRES, PIXEL_FMT); + ret = sdc_init_panel(panel.plnSizeX, panel.plnSizeY, + IPU_PIX_FMT_RGB666, IPU_PANEL_TFT); if (ret < 0) return ret; - reg_write((H_START_WIDTH << 16) | V_START_WIDTH, SDC_BG_POS); + writel((mode->left_margin << 16) | mode->upper_margin, SDC_BG_POS); return 0; } -/* References in this function refer to respective Linux kernel sources */ -void lcd_enable(void) +static void ll_disp3_enable(void *base) { u32 reg; + debug("%s(base=0x%x)\n", __func__, (u32) base); /* pcm037.c::mxc_board_init() */ /* Display Interface #3 */ @@ -780,78 +742,191 @@ void lcd_enable(void) /* ipu_idmac.c::ipu_idmac_init() */ /* Service request counter to maximum - shouldn't be needed */ - reg_write(0x00000070, IDMAC_CONF); + writel(0x00000070, IDMAC_CONF); /* ipu_idmac.c::ipu_init_channel() */ /* Enable IPU sub modules */ - reg = reg_read(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; - reg_write(reg, IPU_CONF); + reg = readl(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; + writel(reg, IPU_CONF); /* mx3fb.c::init_fb_chan() */ /* set Display Interface clock period */ - reg_write(0x00100010L, DI_HSP_CLK_PER); + writel(0x00100010L, DI_HSP_CLK_PER); /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ /* mx3fb.c::sdc_set_brightness() */ /* This might be board-specific */ - reg_write(0x03000000UL | 255 << 16, SDC_PWM_CTRL); + writel(0x03000000UL | 255 << 16, SDC_PWM_CTRL); /* mx3fb.c::sdc_set_global_alpha() */ /* Use global - not per-pixel - Alpha-blending */ - reg = reg_read(SDC_GW_CTRL) & 0x00FFFFFFL; - reg_write(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); + reg = readl(SDC_GW_CTRL) & 0x00FFFFFFL; + writel(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); - reg = reg_read(SDC_COM_CONF); - reg_write(reg | SDC_COM_GLB_A, SDC_COM_CONF); + reg = readl(SDC_COM_CONF); + writel(reg | SDC_COM_GLB_A, SDC_COM_CONF); /* mx3fb.c::sdc_set_color_key() */ /* Disable colour-keying for background */ - reg = reg_read(SDC_COM_CONF) & + reg = readl(SDC_COM_CONF) & ~(SDC_COM_GWSEL | SDC_COM_KEY_COLOR_G); - reg_write(reg, SDC_COM_CONF); + writel(reg, SDC_COM_CONF); mx3fb_set_par(); - sdc_enable_channel(lcd_base); + sdc_enable_channel(base); /* * Linux driver calls sdc_set_brightness() here again, * once is enough for us */ + debug("%s() done\n", __func__); } -void lcd_ctrl_init(void *lcdbase) +/* ------------------------ public part ------------------- */ +ulong calc_fbsize(void) { - u32 mem_len = XRES * YRES * BIT_PER_PIXEL / 8; - /* - * We rely on lcdbase being a physical address, i.e., either MMU off, - * or 1-to-1 mapping. Might want to add some virt2phys here. - */ - if (!lcdbase) - return; - - memset(lcdbase, 0, mem_len); + return panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP; } -ulong calc_fbsize(void) +/* + * The current implementation is only tested for GDF_16BIT_565RGB! + * It was switched from the original CONFIG_LCD setup to CONFIG_VIDEO, + * because the lcd code seemed loaded with color table stuff, that + * does not relate to most modern TFTs. cfb_console.c looks more + * straight forward. + * This is the environment setting for the original setup + * "unknown=video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925,le:9,ri:17, + * up:7,lo:10,hs:1,vs:1,sync:100663296,vmode:0" + * "videomode=unknown" + * + * Settings for VBEST VGG322403 display: + * "videomode=video=ctfb:x:320,y:240,depth:16,mode:0,pclk:156000, + * "le:20,ri:68,up:7,lo:29,hs:30,vs:3,sync:100663296,vmode:0" + * + * Settings for COM57H5M10XRC display: + * "videomode=video=ctfb:x:640,y:480,depth:16,mode:0,pclk:40000, + * "le:120,ri:40,up:35,lo:10,hs:30,vs:3,sync:100663296,vmode:0" + */ +void *video_hw_init(void) { - return ((panel_info.vl_col * panel_info.vl_row * - NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; + char *penv; + u32 memsize; + unsigned long t1, hsynch, vsynch; + int bits_per_pixel, i, tmp, vesa_idx = 0, videomode; + + tmp = 0; + + puts("Video: "); + + videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE; + /* get video mode via environment */ + penv = getenv("videomode"); + if (penv) { + /* decide if it is a string */ + if (penv[0] <= '9') { + videomode = (int) simple_strtoul(penv, NULL, 16); + tmp = 1; + } + } else { + tmp = 1; + } + if (tmp) { + /* parameter are vesa modes */ + /* search params */ + for (i = 0; i < VESA_MODES_COUNT; i++) { + if (vesa_modes[i].vesanr == videomode) + break; + } + if (i == VESA_MODES_COUNT) { + printf("No VESA Mode found, switching to mode 0x%x ", + CONFIG_SYS_DEFAULT_VIDEO_MODE); + i = 0; + } + mode = (struct ctfb_res_modes *) + &res_mode_init[vesa_modes[i].resindex]; + bits_per_pixel = vesa_modes[i].bits_per_pixel; + vesa_idx = vesa_modes[i].resindex; + } else { + mode = (struct ctfb_res_modes *) &var_mode; + bits_per_pixel = video_get_params(mode, penv); + } + + /* calculate hsynch and vsynch freq (info only) */ + t1 = (mode->left_margin + mode->xres + + mode->right_margin + mode->hsync_len) / 8; + t1 *= 8; + t1 *= mode->pixclock; + t1 /= 1000; + hsynch = 1000000000L / t1; + t1 *= (mode->upper_margin + mode->yres + + mode->lower_margin + mode->vsync_len); + t1 /= 1000; + vsynch = 1000000000L / t1; + + /* fill in Graphic device struct */ + sprintf(panel.modeIdent, "%dx%dx%d %ldkHz %ldHz", + mode->xres, mode->yres, + bits_per_pixel, (hsynch / 1000), (vsynch / 1000)); + printf("%s\n", panel.modeIdent); + panel.winSizeX = mode->xres; + panel.winSizeY = mode->yres; + panel.plnSizeX = mode->xres; + panel.plnSizeY = mode->yres; + + switch (bits_per_pixel) { + case 24: + panel.gdfBytesPP = 4; + panel.gdfIndex = GDF_32BIT_X888RGB; + break; + case 16: + panel.gdfBytesPP = 2; + panel.gdfIndex = GDF_16BIT_565RGB; + break; + default: + panel.gdfBytesPP = 1; + panel.gdfIndex = GDF__8BIT_INDEX; + break; + } + + /* set up Hardware */ + memsize = calc_fbsize(); + + debug("%s() allocating %d bytes\n", __func__, memsize); + + /* fill in missing Graphic device struct */ + panel.frameAdrs = (u32) malloc(memsize); + if (panel.frameAdrs == 0) { + printf("%s() malloc(%d) failed\n", __func__, memsize); + return 0; + } + panel.memSize = memsize; + + ll_disp3_enable((void *) panel.frameAdrs); + memset((void *) panel.frameAdrs, 0, memsize); + + debug("%s() done, framebuffer at 0x%x, size=%d cleared\n", + __func__, panel.frameAdrs, memsize); + + return (void *) &panel; } -int overwrite_console(void) +void video_set_lut(unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ) { - /* Keep stdout / stderr on serial, our LCD is for splashscreen only */ - return 1; + return; } diff --git a/include/configs/imx31_phycore.h b/include/configs/imx31_phycore.h index 61f05345b0..48bd50bb7f 100644 --- a/include/configs/imx31_phycore.h +++ b/include/configs/imx31_phycore.h @@ -53,7 +53,7 @@ /* * Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) /* * Hardware drivers @@ -104,7 +104,8 @@ "mtdparts=" MTDPARTS_DEFAULT "\0" \ "prg_uboot=tftpboot 0x80000000 $(uboot); protect off 0xa0000000 +0x20000; erase 0xa0000000 +0x20000; cp.b 0x80000000 0xa0000000 $(filesize)\0" \ "prg_kernel=tftpboot 0x80000000 $(uimage); erase 0xa0040000 +0x180000; cp.b 0x80000000 0xa0040000 $(filesize)\0" \ - "prg_jffs2=tftpboot 0x80000000 $(jffs2); erase 0xa01c0000 0xa1ffffff; cp.b 0x80000000 0xa01c0000 $(filesize)\0" + "prg_jffs2=tftpboot 0x80000000 $(jffs2); erase 0xa01c0000 0xa1ffffff; cp.b 0x80000000 0xa01c0000 $(filesize)\0" \ + "videomode=video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925,le:9,ri:17,up:7,lo:10,hs:1,vs:1,sync:1241513985,vmode:0\0" #define CONFIG_SMC911X 1 @@ -201,15 +202,16 @@ #define CONFIG_S6E63D6 1 -#define CONFIG_LCD 1 -#define CONFIG_VIDEO_MX3 1 -#define CONFIG_SYS_WHITE_ON_BLACK 1 -#define LCD_BPP LCD_COLOR8 -#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE 1 -#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1 - -#define CONFIG_SPLASH_SCREEN 1 -#define CONFIG_CMD_BMP 1 +#define CONFIG_VIDEO +#define CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO_MX3 +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_SPLASH_SCREEN +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP #endif #endif /* __CONFIG_H */ diff --git a/include/configs/qong.h b/include/configs/qong.h index e4bc1d0be2..b1fc80c527 100644 --- a/include/configs/qong.h +++ b/include/configs/qong.h @@ -79,15 +79,16 @@ #define CONFIG_DNET_BASE (CS1_BASE + QONG_FPGA_PERIPH_SIZE) /* Framebuffer and LCD */ -#define CONFIG_LCD +#define CONFIG_VIDEO +#define CONFIG_CFB_CONSOLE #define CONFIG_VIDEO_MX3 -#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VGA_AS_SINGLE_DEVICE #define CONFIG_SYS_CONSOLE_IS_IN_ENV -#define LCD_BPP LCD_COLOR16 -#define CONFIG_SPLASH_SCREEN +#define CONFIG_SPLASH_SCREEN #define CONFIG_CMD_BMP #define CONFIG_BMP_16BPP -#define CONFIG_DISPLAY_COM57H5M10XRC /* USB */ #define CONFIG_CMD_USB @@ -177,6 +178,9 @@ " +${filesize};cp.b ${fileaddr} " \ xstr(CONFIG_SYS_MONITOR_BASE) " ${filesize}\0" \ "upd=run load update\0" \ + "videomode=video=ctfb:x:640,y:480,depth:16,mode:0,pclk:40000," \ + "le:120,ri:40,up:35,lo:10,hs:30,vs:3,sync:100663296," \ + "vmode:0\0" \ /* * Miscellaneous configurable options -- cgit From 5aa5b88404b2b3610d36a9626ec36dcc81194aa9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 12 Oct 2011 20:16:31 -0400 Subject: Blackfin: define CONFIG_SYS_CACHELINE_SIZE Common U-Boot API wants this define, so import asm/cache.h from Linux to provide suitable defines. Acked-by: Anton Staaf Signed-off-by: Mike Frysinger --- arch/blackfin/include/asm/blackfin_local.h | 1 + arch/blackfin/include/asm/cache.h | 70 ++++++++++++++++++++++++++++++ arch/blackfin/include/asm/config.h | 3 ++ 3 files changed, 74 insertions(+) create mode 100644 arch/blackfin/include/asm/cache.h diff --git a/arch/blackfin/include/asm/blackfin_local.h b/arch/blackfin/include/asm/blackfin_local.h index 27034d3d06..71207b697a 100644 --- a/arch/blackfin/include/asm/blackfin_local.h +++ b/arch/blackfin/include/asm/blackfin_local.h @@ -49,6 +49,7 @@ #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #include +#include #ifndef __ASSEMBLY__ # ifdef SHARED_RESOURCES diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h new file mode 100644 index 0000000000..482e4b52b6 --- /dev/null +++ b/arch/blackfin/include/asm/cache.h @@ -0,0 +1,70 @@ +/* + * Copyright 2004-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __ARCH_BLACKFIN_CACHE_H +#define __ARCH_BLACKFIN_CACHE_H + +#include /* for asmlinkage */ + +/* + * Bytes per L1 cache line + * Blackfin loads 32 bytes for cache + */ +#define L1_CACHE_SHIFT 5 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define SMP_CACHE_BYTES L1_CACHE_BYTES + +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +#ifdef CONFIG_SMP +#define __cacheline_aligned +#else +#define ____cacheline_aligned + +/* + * Put cacheline_aliged data to L1 data memory + */ +#ifdef CONFIG_CACHELINE_ALIGNED_L1 +#define __cacheline_aligned \ + __attribute__((__aligned__(L1_CACHE_BYTES), \ + __section__(".data_l1.cacheline_aligned"))) +#endif + +#endif + +/* + * largest L1 which this arch supports + */ +#define L1_CACHE_SHIFT_MAX 5 + +#if defined(CONFIG_SMP) && \ + !defined(CONFIG_BFIN_CACHE_COHERENT) +# if defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) || defined(CONFIG_BFIN_L2_ICACHEABLE) +# define __ARCH_SYNC_CORE_ICACHE +# endif +# if defined(CONFIG_BFIN_EXTMEM_DCACHEABLE) || defined(CONFIG_BFIN_L2_DCACHEABLE) +# define __ARCH_SYNC_CORE_DCACHE +# endif +#ifndef __ASSEMBLY__ +asmlinkage void __raw_smp_mark_barrier_asm(void); +asmlinkage void __raw_smp_check_barrier_asm(void); + +static inline void smp_mark_barrier(void) +{ + __raw_smp_mark_barrier_asm(); +} +static inline void smp_check_barrier(void) +{ + __raw_smp_check_barrier_asm(); +} + +void resync_core_dcache(void); +void resync_core_icache(void); +#endif +#endif + + +#endif diff --git a/arch/blackfin/include/asm/config.h b/arch/blackfin/include/asm/config.h index 53af310ecf..1a8de4906d 100644 --- a/arch/blackfin/include/asm/config.h +++ b/arch/blackfin/include/asm/config.h @@ -21,6 +21,9 @@ # define CONFIG_BFIN_SCRATCH_REG retn #endif +/* U-Boot wants this config name */ +#define CONFIG_SYS_CACHELINE_SIZE L1_CACHE_BYTES + /* Make sure the structure is properly aligned */ #if ((CONFIG_SYS_GBL_DATA_ADDR & -4) != CONFIG_SYS_GBL_DATA_ADDR) # error CONFIG_SYS_GBL_DATA_ADDR: must be 4 byte aligned -- cgit From 0d2b0a8f451a31e8d84e3d4866e78951ad6535f2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 3 Oct 2011 20:51:13 -0400 Subject: Blackfin: bfin_spi: fix build error when DEBUG is defined The new debug() changes pointed out debug code that rotted a little. Signed-off-by: Mike Frysinger --- drivers/spi/bfin_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index 213e79281a..e080bec705 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -197,7 +197,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, spi_set_speed(&bss->slave, max_hz); debug("%s: bus:%i cs:%i mmr:%x ctl:%x baud:%i flg:%i\n", __func__, - bus, cs, mmr_base, bss->ctl, baud, bss->flg); + bus, cs, mmr_base, bss->ctl, bss->baud, bss->flg); return &bss->slave; } -- cgit From e5afdf584c1e217b19579ba88e415ff8eb657fd8 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Sun, 21 Aug 2011 23:21:06 +0000 Subject: kw_gpio: fix error in kw_gpio_direction_input The function kw_gpio_is_valid returns zero on success, so adapt the error check accordingly. Signed-off-by: Holger Brunck cc: Prafulla Wadaskar cc: Dieter Kiermaier --- drivers/gpio/kw_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/kw_gpio.c b/drivers/gpio/kw_gpio.c index 56383c2875..2de179e827 100644 --- a/drivers/gpio/kw_gpio.c +++ b/drivers/gpio/kw_gpio.c @@ -109,7 +109,7 @@ void kw_gpio_set_valid(unsigned pin, int mode) */ int kw_gpio_direction_input(unsigned pin) { - if (!kw_gpio_is_valid(pin, GPIO_INPUT_OK)) + if (kw_gpio_is_valid(pin, GPIO_INPUT_OK) != 0) return 1; /* Configure GPIO direction. */ -- cgit From 5c1d082b145527ac7c10bfe794cd72643e045d8d Mon Sep 17 00:00:00 2001 From: Jason Jin Date: Thu, 25 Aug 2011 15:46:43 +0800 Subject: DM9000:Add a byte swap macro for dm9000 io operation. commit a45dde2293c816138e53c26eca6fd0322583f9a6 changed the dm9000 direct register access to standard IO. This should work on the ColdFire platform as there are corresponding macros for the LE devices. But the hardware settings on some ColdFire boards had swapped the byte order which make the original macros such as out_le16 cannot work. To avoid changing the common io access code on ColdFire platform, the DM9000_BYTE_SWAPPED define was added to make the dm9000 use __raw* IO access on some ColdFire boards. Signed-off-by: Jason Jin --- drivers/net/dm9000x.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index b5c55738f7..04241109cc 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -116,13 +116,21 @@ static u8 DM9000_ior(int); static void DM9000_iow(int reg, u8 value); /* DM9000 network board routine ---------------------------- */ - +#ifndef CONFIG_DM9000_BYTE_SWAPPED #define DM9000_outb(d,r) writeb(d, (volatile u8 *)(r)) #define DM9000_outw(d,r) writew(d, (volatile u16 *)(r)) #define DM9000_outl(d,r) writel(d, (volatile u32 *)(r)) #define DM9000_inb(r) readb((volatile u8 *)(r)) #define DM9000_inw(r) readw((volatile u16 *)(r)) #define DM9000_inl(r) readl((volatile u32 *)(r)) +#else +#define DM9000_outb(d, r) __raw_writeb(d, r) +#define DM9000_outw(d, r) __raw_writew(d, r) +#define DM9000_outl(d, r) __raw_writel(d, r) +#define DM9000_inb(r) __raw_readb(r) +#define DM9000_inw(r) __raw_readw(r) +#define DM9000_inl(r) __raw_readl(r) +#endif #ifdef CONFIG_DM9000_DEBUG static void -- cgit From b69bf52dfe34b9d7b2a20845c8a7e7e5978c2d2f Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Tue, 23 Aug 2011 11:06:49 +0000 Subject: Add generic, reusable menu code This will be used first by the pxe code, but is intended to be generic and reusable for other jobs in U-boot. Signed-off-by: Jason Hobbs --- common/Makefile | 1 + common/menu.c | 393 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/README.menu | 119 +++++++++++++++++ include/menu.h | 30 +++++ 4 files changed, 543 insertions(+) create mode 100644 common/menu.c create mode 100644 doc/README.menu create mode 100644 include/menu.h diff --git a/common/Makefile b/common/Makefile index fdc4206853..8e8dad4c91 100644 --- a/common/Makefile +++ b/common/Makefile @@ -177,6 +177,7 @@ COBJS-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o COBJS-$(CONFIG_KALLSYMS) += kallsyms.o COBJS-$(CONFIG_LCD) += lcd.o COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o +COBJS-$(CONFIG_MENU) += menu.o COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o diff --git a/common/menu.c b/common/menu.c new file mode 100644 index 0000000000..56439374f7 --- /dev/null +++ b/common/menu.c @@ -0,0 +1,393 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * + * 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 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, see . + */ + +#include +#include +#include +#include + +#include "menu.h" + +/* + * Internally, each item in a menu is represented by a struct menu_item. + * + * These items will be alloc'd and initialized by menu_item_add and destroyed + * by menu_item_destroy, and the consumer of the interface never sees that + * this struct is used at all. + */ +struct menu_item { + char *key; + void *data; + struct list_head list; +}; + +/* + * The menu is composed of a list of items along with settings and callbacks + * provided by the user. An incomplete definition of this struct is available + * in menu.h, but the full definition is here to prevent consumers from + * relying on its contents. + */ +struct menu { + struct menu_item *default_item; + char *title; + int prompt; + void (*item_data_print)(void *); + struct list_head items; +}; + +/* + * An iterator function for menu items. callback will be called for each item + * in m, with m, a pointer to the item, and extra being passed to callback. If + * callback returns a value other than NULL, iteration stops and the value + * return by callback is returned from menu_items_iter. This allows it to be + * used for search type operations. It is also safe for callback to remove the + * item from the list of items. + */ +static inline void *menu_items_iter(struct menu *m, + void *(*callback)(struct menu *, struct menu_item *, void *), + void *extra) +{ + struct list_head *pos, *n; + struct menu_item *item; + void *ret; + + list_for_each_safe(pos, n, &m->items) { + item = list_entry(pos, struct menu_item, list); + + ret = callback(m, item, extra); + + if (ret) + return ret; + } + + return NULL; +} + +/* + * Print a menu_item. If the consumer provided an item_data_print function + * when creating the menu, call it with a pointer to the item's private data. + * Otherwise, print the key of the item. + */ +static inline void *menu_item_print(struct menu *m, + struct menu_item *item, + void *extra) +{ + if (!m->item_data_print) + printf("%s\n", item->key); + else + m->item_data_print(item->data); + + return NULL; +} + +/* + * Free the memory used by a menu item. This includes the memory used by its + * key. + */ +static inline void *menu_item_destroy(struct menu *m, + struct menu_item *item, + void *extra) +{ + if (item->key) + free(item->key); + + free(item); + + return NULL; +} + +/* + * Display a menu so the user can make a choice of an item. First display its + * title, if any, and then each item in the menu. + */ +static inline void menu_display(struct menu *m) +{ + if (m->title) + printf("%s:\n", m->title); + + menu_items_iter(m, menu_item_print, NULL); +} + +/* + * Check if an item's key matches a provided string, pointed to by extra. If + * extra is NULL, an item with a NULL key will match. Otherwise, the item's + * key has to match according to strcmp. + * + * This is called via menu_items_iter, so it returns a pointer to the item if + * the key matches, and returns NULL otherwise. + */ +static inline void *menu_item_key_match(struct menu *m, + struct menu_item *item, void *extra) +{ + char *item_key = extra; + + if (!item_key || !item->key) { + if (item_key == item->key) + return item; + + return NULL; + } + + if (strcmp(item->key, item_key) == 0) + return item; + + return NULL; +} + +/* + * Find the first item with a key matching item_key, if any exists. + */ +static inline struct menu_item *menu_item_by_key(struct menu *m, + char *item_key) +{ + return menu_items_iter(m, menu_item_key_match, item_key); +} + +/* + * Checks whether or not the default menu item should be used without + * prompting for a user choice. If the menu is set to always prompt, return + * 0. Otherwise, return 1 to indicate we should use the default menu item. + */ +static inline int menu_use_default(struct menu *m) +{ + return !m->prompt; +} + +/* + * Set *choice to point to the default item's data, if any default item was + * set, and returns 1. If no default item was set, returns -ENOENT. + */ +static inline int menu_default_choice(struct menu *m, void **choice) +{ + if (m->default_item) { + *choice = m->default_item->data; + return 1; + } + + return -ENOENT; +} + +/* + * Displays the menu and asks the user to choose an item. *choice will point + * to the private data of the item the user chooses. The user makes a choice + * by inputting a string matching the key of an item. Invalid choices will + * cause the user to be prompted again, repeatedly, until the user makes a + * valid choice. The user can exit the menu without making a choice via ^c. + * + * Returns 1 if the user made a choice, or -EINTR if they bail via ^c. + */ +static inline int menu_interactive_choice(struct menu *m, void **choice) +{ + char cbuf[CONFIG_SYS_CBSIZE]; + struct menu_item *choice_item = NULL; + int readret; + + while (!choice_item) { + cbuf[0] = '\0'; + + menu_display(m); + + readret = readline_into_buffer("Enter choice: ", cbuf); + + if (readret >= 0) { + choice_item = menu_item_by_key(m, cbuf); + + if (!choice_item) + printf("%s not found\n", cbuf); + } else { + printf("^C\n"); + return -EINTR; + } + } + + *choice = choice_item->data; + + return 1; +} + +/* + * menu_default_set() - Sets the default choice for the menu. This is safe to + * call more than once on a menu. + * + * m - Points to a menu created by menu_create(). + * + * item_key - Points to a string that, when compared using strcmp, matches the + * key for an existing item in the menu. + * + * Returns 1 if successful, -EINVAL if m is NULL, or -ENOENT if no item with a + * key matching item_key is found. + */ +int menu_default_set(struct menu *m, char *item_key) +{ + struct menu_item *item; + + if (!m) + return -EINVAL; + + item = menu_item_by_key(m, item_key); + + if (!item) + return -ENOENT; + + m->default_item = item; + + return 1; +} + +/* + * menu_get_choice() - Returns the user's selected menu entry, or the default + * if the menu is set to not prompt. This is safe to call more than once. + * + * m - Points to a menu created by menu_create(). + * + * choice - Points to a location that will store a pointer to the selected + * menu item. If no item is selected or there is an error, no value will be + * written at the location it points to. + * + * Returns 1 if successful, -EINVAL if m or choice is NULL, -ENOENT if no + * default has been set and the menu is set to not prompt, or -EINTR if the + * user exits the menu via ^c. + */ +int menu_get_choice(struct menu *m, void **choice) +{ + if (!m || !choice) + return -EINVAL; + + if (menu_use_default(m)) + return menu_default_choice(m, choice); + + return menu_interactive_choice(m, choice); +} + +/* + * menu_item_add() - Adds or replaces a menu item. Note that this replaces the + * data of an item if it already exists, but doesn't change the order of the + * item. + * + * m - Points to a menu created by menu_create(). + * + * item_key - Points to a string that will uniquely identify the item. The + * string will be copied to internal storage, and is safe to discard after + * passing to menu_item_add. + * + * item_data - An opaque pointer associated with an item. It is never + * dereferenced internally, but will be passed to the item_data_print, and + * will be returned from menu_get_choice if the menu item is selected. + * + * Returns 1 if successful, -EINVAL if m is NULL, or -ENOMEM if there is + * insufficient memory to add the menu item. + */ +int menu_item_add(struct menu *m, char *item_key, void *item_data) +{ + struct menu_item *item; + + if (!m) + return -EINVAL; + + item = menu_item_by_key(m, item_key); + + if (item) { + item->data = item_data; + return 1; + } + + item = malloc(sizeof *item); + if (!item) + return -ENOMEM; + + item->key = strdup(item_key); + + if (!item->key) { + free(item); + return -ENOMEM; + } + + item->data = item_data; + + list_add_tail(&item->list, &m->items); + + return 1; +} + +/* + * menu_create() - Creates a menu handle with default settings + * + * title - If not NULL, points to a string that will be displayed before the + * list of menu items. It will be copied to internal storage, and is safe to + * discard after passing to menu_create(). + * + * prompt - If 0, don't ask for user input. + * + * item_data_print - If not NULL, will be called for each item when the menu + * is displayed, with the pointer to the item's data passed as the argument. + * If NULL, each item's key will be printed instead. Since an item's key is + * what must be entered to select an item, the item_data_print function should + * make it obvious what the key for each entry is. + * + * Returns a pointer to the menu if successful, or NULL if there is + * insufficient memory available to create the menu. + */ +struct menu *menu_create(char *title, int prompt, + void (*item_data_print)(void *)) +{ + struct menu *m; + + m = malloc(sizeof *m); + + if (!m) + return NULL; + + m->default_item = NULL; + m->prompt = prompt; + m->item_data_print = item_data_print; + + if (title) { + m->title = strdup(title); + if (!m->title) { + free(m); + return NULL; + } + } else + m->title = NULL; + + + INIT_LIST_HEAD(&m->items); + + return m; +} + +/* + * menu_destroy() - frees the memory used by a menu and its items. + * + * m - Points to a menu created by menu_create(). + * + * Returns 1 if successful, or -EINVAL if m is NULL. + */ +int menu_destroy(struct menu *m) +{ + if (!m) + return -EINVAL; + + menu_items_iter(m, menu_item_destroy, NULL); + + if (m->title) + free(m->title); + + free(m); + + return 1; +} diff --git a/doc/README.menu b/doc/README.menu new file mode 100644 index 0000000000..f55eb801b9 --- /dev/null +++ b/doc/README.menu @@ -0,0 +1,119 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * + * 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 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, see . + */ + +U-boot provides a set of interfaces for creating and using simple, text +based menus. Menus are displayed as lists of labeled entries on the +console, and an entry can be selected by entering its label. + +To use the menu code, enable CONFIG_MENU, and include "menu.h" where +the interfaces should be available. + +Menus are composed of items. Each item has a key used to identify it in +the menu, and an opaque pointer to data controlled by the consumer. + +Interfaces +---------- +#include "menu.h" + +/* + * Consumers of the menu interfaces will use a struct menu * as the + * handle for a menu. struct menu is only fully defined in menu.c, + * preventing consumers of the menu interfaces from accessing its + * contents directly. + */ +struct menu; + +/* + * NOTE: See comments in common/menu.c for more detailed documentation on + * these interfaces. + */ + +/* + * menu_create() - Creates a menu handle with default settings + */ +struct menu *menu_create(char *title, int prompt, + void (*item_data_print)(void *)); + +/* + * menu_item_add() - Adds or replaces a menu item + */ +int menu_item_add(struct menu *m, char *item_key, void *item_data); + +/* + * menu_default_set() - Sets the default choice for the menu + */ +int menu_default_set(struct menu *m, char *item_key); + +/* + * menu_get_choice() - Returns the user's selected menu entry, or the + * default if the menu is set to not prompt. + */ +int menu_get_choice(struct menu *m, void **choice); + +/* + * menu_destroy() - frees the memory used by a menu and its items. + */ +int menu_destroy(struct menu *m); + + +Example Code +------------ +This example creates a menu that always prompts, and allows the user +to pick from a list of tools. The item key and data are the same. + +#include "menu.h" + +char *tools[] = { + "Hammer", + "Screwdriver", + "Nail gun", + NULL +}; + +char *pick_a_tool(void) +{ + struct menu *m; + int i; + char *tool = NULL; + + m = menu_create("Tools", 1, NULL); + + for(i = 0; tools[i]; i++) { + if (menu_item_add(m, tools[i], tools[i]) != 1) { + printf("failed to add item!"); + menu_destroy(m); + return NULL; + } + } + + if (menu_get_choice(m, (void **)&tool) != 1) + printf("Problem picking tool!\n"); + + menu_destroy(m); + + return tool; +} + +void caller(void) +{ + char *tool = pick_a_tool(); + + if (tool) { + printf("picked a tool: %s\n", tool); + use_tool(tool); + } +} diff --git a/include/menu.h b/include/menu.h new file mode 100644 index 0000000000..d47e1a029c --- /dev/null +++ b/include/menu.h @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * + * 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 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, see . + */ + +#ifndef __MENU_H__ +#define __MENU_H__ + +struct menu; + +struct menu *menu_create(char *title, int prompt, + void (*item_data_print)(void *)); +int menu_default_set(struct menu *m, char *item_key); +int menu_get_choice(struct menu *m, void **choice); +int menu_item_add(struct menu *m, char *item_key, void *item_data); +int menu_destroy(struct menu *m); + +#endif /* __MENU_H__ */ -- cgit From b41bc5a82d8a67d347f2fc12cf2106b8a37e4336 Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Tue, 23 Aug 2011 11:06:50 +0000 Subject: common, menu: use abortboot for menu timeout Signed-off-by: Jason Hobbs --- common/main.c | 10 ++++++++-- common/menu.c | 40 ++++++++++++++++++++++++++++++++-------- doc/README.menu | 6 +++--- include/common.h | 3 +++ include/menu.h | 2 +- 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/common/main.c b/common/main.c index 3324d9d6e4..b97d89e589 100644 --- a/common/main.c +++ b/common/main.c @@ -88,7 +88,10 @@ extern void mdm_init(void); /* defined in board.c */ */ #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) # if defined(CONFIG_AUTOBOOT_KEYED) -static inline int abortboot(int bootdelay) +#ifndef CONFIG_MENU +static inline +#endif +int abortboot(int bootdelay) { int abort = 0; uint64_t etime = endtick(bootdelay); @@ -202,7 +205,10 @@ static inline int abortboot(int bootdelay) static int menukey = 0; #endif -static inline int abortboot(int bootdelay) +#ifndef CONFIG_MENU +static inline +#endif +int abortboot(int bootdelay) { int abort = 0; diff --git a/common/menu.c b/common/menu.c index 56439374f7..f004823363 100644 --- a/common/menu.c +++ b/common/menu.c @@ -43,6 +43,7 @@ struct menu_item { */ struct menu { struct menu_item *default_item; + int timeout; char *title; int prompt; void (*item_data_print)(void *); @@ -157,14 +158,30 @@ static inline struct menu_item *menu_item_by_key(struct menu *m, return menu_items_iter(m, menu_item_key_match, item_key); } +/* + * Wait for the user to hit a key according to the timeout set for the menu. + * Returns 1 if the user hit a key, or 0 if the timeout expired. + */ +static inline int menu_interrupted(struct menu *m) +{ + if (!m->timeout) + return 0; + + if (abortboot(m->timeout/10)) + return 1; + + return 0; +} + /* * Checks whether or not the default menu item should be used without - * prompting for a user choice. If the menu is set to always prompt, return - * 0. Otherwise, return 1 to indicate we should use the default menu item. + * prompting for a user choice. If the menu is set to always prompt, or the + * user hits a key during the timeout period, return 0. Otherwise, return 1 to + * indicate we should use the default menu item. */ static inline int menu_use_default(struct menu *m) { - return !m->prompt; + return !m->prompt && !menu_interrupted(m); } /* @@ -250,7 +267,8 @@ int menu_default_set(struct menu *m, char *item_key) /* * menu_get_choice() - Returns the user's selected menu entry, or the default - * if the menu is set to not prompt. This is safe to call more than once. + * if the menu is set to not prompt or the timeout expires. This is safe to + * call more than once. * * m - Points to a menu created by menu_create(). * @@ -259,8 +277,8 @@ int menu_default_set(struct menu *m, char *item_key) * written at the location it points to. * * Returns 1 if successful, -EINVAL if m or choice is NULL, -ENOENT if no - * default has been set and the menu is set to not prompt, or -EINTR if the - * user exits the menu via ^c. + * default has been set and the menu is set to not prompt or the timeout + * expires, or -EINTR if the user exits the menu via ^c. */ int menu_get_choice(struct menu *m, void **choice) { @@ -330,7 +348,12 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data) * list of menu items. It will be copied to internal storage, and is safe to * discard after passing to menu_create(). * - * prompt - If 0, don't ask for user input. + * timeout - A delay in seconds to wait for user input. If 0, timeout is + * disabled, and the default choice will be returned unless prompt is 1. + * + * prompt - If 0, don't ask for user input unless there is an interrupted + * timeout. If 1, the user will be prompted for input regardless of the value + * of timeout. * * item_data_print - If not NULL, will be called for each item when the menu * is displayed, with the pointer to the item's data passed as the argument. @@ -341,7 +364,7 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data) * Returns a pointer to the menu if successful, or NULL if there is * insufficient memory available to create the menu. */ -struct menu *menu_create(char *title, int prompt, +struct menu *menu_create(char *title, int timeout, int prompt, void (*item_data_print)(void *)) { struct menu *m; @@ -353,6 +376,7 @@ struct menu *menu_create(char *title, int prompt, m->default_item = NULL; m->prompt = prompt; + m->timeout = timeout; m->item_data_print = item_data_print; if (title) { diff --git a/doc/README.menu b/doc/README.menu index f55eb801b9..1259c6ad57 100644 --- a/doc/README.menu +++ b/doc/README.menu @@ -45,7 +45,7 @@ struct menu; /* * menu_create() - Creates a menu handle with default settings */ -struct menu *menu_create(char *title, int prompt, +struct menu *menu_create(char *title, int timeout, int prompt, void (*item_data_print)(void *)); /* @@ -60,7 +60,7 @@ int menu_default_set(struct menu *m, char *item_key); /* * menu_get_choice() - Returns the user's selected menu entry, or the - * default if the menu is set to not prompt. + * default if the menu is set to not prompt or the timeout expires. */ int menu_get_choice(struct menu *m, void **choice); @@ -90,7 +90,7 @@ char *pick_a_tool(void) int i; char *tool = NULL; - m = menu_create("Tools", 1, NULL); + m = menu_create("Tools", 0, 1, NULL); for(i = 0; tools[i]; i++) { if (menu_item_add(m, tools[i], tools[i]) != 1) { diff --git a/include/common.h b/include/common.h index a55600b182..f9fea08115 100644 --- a/include/common.h +++ b/include/common.h @@ -260,6 +260,9 @@ int readline_into_buffer (const char *const prompt, char * buffer); int parse_line (char *, char *[]); void init_cmd_timeout(void); void reset_cmd_timeout(void); +#ifdef CONFIG_MENU +int abortboot(int bootdelay); +#endif /* arch/$(ARCH)/lib/board.c */ void board_init_f (ulong) __attribute__ ((noreturn)); diff --git a/include/menu.h b/include/menu.h index d47e1a029c..cf14a9cca3 100644 --- a/include/menu.h +++ b/include/menu.h @@ -20,7 +20,7 @@ struct menu; -struct menu *menu_create(char *title, int prompt, +struct menu *menu_create(char *title, int timeout, int prompt, void (*item_data_print)(void *)); int menu_default_set(struct menu *m, char *item_key); int menu_get_choice(struct menu *m, void **choice); -- cgit From c8a2079e49ee15dde10278865425ec9c36215f31 Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Wed, 31 Aug 2011 05:37:24 +0000 Subject: common: add run_command2 for running simple or hush commands Signed-off-by: Jason Hobbs Cc: Mike Frysinger Acked-by: Mike Frysinger --- common/hush.c | 2 +- common/main.c | 56 +++++++++++++++++++++++++++----------------------------- include/hush.h | 2 +- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/common/hush.c b/common/hush.c index 85a603071f..940889b898 100644 --- a/common/hush.c +++ b/common/hush.c @@ -3217,7 +3217,7 @@ int parse_stream_outer(struct in_str *inp, int flag) #ifndef __U_BOOT__ static int parse_string_outer(const char *s, int flag) #else -int parse_string_outer(char *s, int flag) +int parse_string_outer(const char *s, int flag) #endif /* __U_BOOT__ */ { struct in_str input; diff --git a/common/main.c b/common/main.c index b97d89e589..3adadfdaa0 100644 --- a/common/main.c +++ b/common/main.c @@ -83,8 +83,7 @@ extern void mdm_init(void); /* defined in board.c */ /*************************************************************************** * Watch for 'delay' seconds for autoboot stop or autoboot delay string. - * returns: 0 - no key string, allow autoboot - * 1 - got key string, abort + * returns: 0 - no key string, allow autoboot 1 - got key string, abort */ #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) # if defined(CONFIG_AUTOBOOT_KEYED) @@ -266,6 +265,26 @@ int abortboot(int bootdelay) # endif /* CONFIG_AUTOBOOT_KEYED */ #endif /* CONFIG_BOOTDELAY >= 0 */ +/* + * Return 0 on success, or != 0 on error. + */ +static inline +int run_command2(const char *cmd, int flag) +{ +#ifndef CONFIG_SYS_HUSH_PARSER + /* + * run_command can return 0 or 1 for success, so clean up its result. + */ + if (run_command(cmd, flag) == -1) + return 1; + + return 0; +#else + return parse_string_outer(cmd, + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); +#endif +} + /****************************************************************************/ void main_loop (void) @@ -332,12 +351,7 @@ void main_loop (void) int prev = disable_ctrlc(1); /* disable Control C checking */ # endif -# ifndef CONFIG_SYS_HUSH_PARSER - run_command (p, 0); -# else - parse_string_outer(p, FLAG_PARSE_SEMICOLON | - FLAG_EXIT_FROM_LOOP); -# endif + run_command2(p, 0); # ifdef CONFIG_AUTOBOOT_KEYED disable_ctrlc(prev); /* restore Control C checking */ @@ -382,12 +396,7 @@ void main_loop (void) int prev = disable_ctrlc(1); /* disable Control C checking */ # endif -# ifndef CONFIG_SYS_HUSH_PARSER - run_command (s, 0); -# else - parse_string_outer(s, FLAG_PARSE_SEMICOLON | - FLAG_EXIT_FROM_LOOP); -# endif + run_command2(s, 0); # ifdef CONFIG_AUTOBOOT_KEYED disable_ctrlc(prev); /* restore Control C checking */ @@ -397,14 +406,8 @@ void main_loop (void) # ifdef CONFIG_MENUKEY if (menukey == CONFIG_MENUKEY) { s = getenv("menucmd"); - if (s) { -# ifndef CONFIG_SYS_HUSH_PARSER - run_command(s, 0); -# else - parse_string_outer(s, FLAG_PARSE_SEMICOLON | - FLAG_EXIT_FROM_LOOP); -# endif - } + if (s) + run_command2(s, 0); } #endif /* CONFIG_MENUKEY */ #endif /* CONFIG_BOOTDELAY */ @@ -1403,14 +1406,9 @@ int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) printf ("## Error: \"%s\" not defined\n", argv[i]); return 1; } -#ifndef CONFIG_SYS_HUSH_PARSER - if (run_command (arg, flag) == -1) - return 1; -#else - if (parse_string_outer(arg, - FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) + + if (run_command2(arg, flag) != 0) return 1; -#endif } return 0; } diff --git a/include/hush.h b/include/hush.h index 5c566cc8da..ecf9222d27 100644 --- a/include/hush.h +++ b/include/hush.h @@ -29,7 +29,7 @@ #define FLAG_REPARSING (1 << 2) /* >=2nd pass */ extern int u_boot_hush_start(void); -extern int parse_string_outer(char *, int); +extern int parse_string_outer(const char *, int); extern int parse_file_outer(void); int set_local_var(const char *s, int flg_export); -- cgit From 93337abbfe2951c63a4e7b450da1848c6c69217f Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Tue, 23 Aug 2011 11:06:52 +0000 Subject: Add isblank Existing ctype checks are implemented using a 256 byte lookup table, allowing each character to be in any of 8 character classes. Since there are 8 existing character classes without the blank class, I implemented isblank without using the lookup table. Since there are only two blank characters - tab and space - this is a more reasonable approach than doubling the size of the lookup table to accommodate one more class. Signed-off-by: Jason Hobbs --- include/linux/ctype.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/ctype.h b/include/linux/ctype.h index 6dec944a37..42f9305a02 100644 --- a/include/linux/ctype.h +++ b/include/linux/ctype.h @@ -31,6 +31,12 @@ extern const unsigned char _ctype[]; #define isupper(c) ((__ismask(c)&(_U)) != 0) #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) +/* + * Rather than doubling the size of the _ctype lookup table to hold a 'blank' + * flag, just check for space or tab. + */ +#define isblank(c) (c == ' ' || c == '\t') + #define isascii(c) (((unsigned char)(c))<=0x7f) #define toascii(c) (((unsigned char)(c))&0x7f) -- cgit From ce2d4c9532b338e39f033ef75ae57bcb71c3389e Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Tue, 23 Aug 2011 11:06:53 +0000 Subject: cosmetic: remove unneeded curly braces This prevents a checkpatch warning in the patch to use isblank Signed-off-by: Jason Hobbs --- common/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/main.c b/common/main.c index 3adadfdaa0..d812aa186c 100644 --- a/common/main.c +++ b/common/main.c @@ -1097,9 +1097,8 @@ int parse_line (char *line, char *argv[]) while (nargs < CONFIG_SYS_MAXARGS) { /* skip any white space */ - while ((*line == ' ') || (*line == '\t')) { + while ((*line == ' ') || (*line == '\t')) ++line; - } if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL; @@ -1112,9 +1111,8 @@ int parse_line (char *line, char *argv[]) argv[nargs++] = line; /* begin of argument string */ /* find end of string */ - while (*line && (*line != ' ') && (*line != '\t')) { + while (*line && (*line != ' ') && (*line != '\t')) ++line; - } if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL; -- cgit From 4d91a6ecabd10652abba696e55e952676db0aae1 Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Tue, 23 Aug 2011 11:06:54 +0000 Subject: Replace space and tab checks with isblank These are various places I found that checked for conditions equivalent to isblank. Signed-off-by: Jason Hobbs --- board/hymod/env.c | 9 +++++---- common/command.c | 9 +++++---- common/main.c | 5 +++-- drivers/bios_emulator/x86emu/debug.c | 7 ++++--- examples/standalone/smc911x_eeprom.c | 5 +++-- lib/hashtable.c | 4 +++- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/board/hymod/env.c b/board/hymod/env.c index c0e2cd5d68..fde428d979 100644 --- a/board/hymod/env.c +++ b/board/hymod/env.c @@ -22,6 +22,7 @@ */ #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -45,7 +46,7 @@ env_callback (uchar *name, uchar *value) nn++; } - while (*nn == ' ' || *nn == '\t') + while (isblank(*nn)) nn++; if ((nnl = strlen (nn)) == 0) { @@ -61,7 +62,7 @@ env_callback (uchar *name, uchar *value) nn[--nnl] = '\0'; } - while (nnl > 0 && ((c = nn[nnl - 1]) == ' ' || c == '\t')) + while (nnl > 0 && isblank(nn[nnl - 1])) nn[--nnl] = '\0'; if (nnl == 0) { printf ("Empty name in global env file\n"); @@ -71,11 +72,11 @@ env_callback (uchar *name, uchar *value) p = (char *)value; q = nv; - while ((c = *p) == ' ' || c == '\t') + while (isblank(*p)) p++; nvl = strlen (p); - while (nvl > 0 && ((c = p[nvl - 1]) == ' ' || c == '\t')) + while (nvl > 0 && isblank(p[nvl - 1])) p[--nvl] = '\0'; while ((*q = *p++) != '\0') { diff --git a/common/command.c b/common/command.c index ed931d748c..2c0bf53449 100644 --- a/common/command.c +++ b/common/command.c @@ -27,6 +27,7 @@ #include #include +#include /* * Use puts() instead of printf() to avoid printf buffer overflow @@ -165,7 +166,7 @@ int var_complete(int argc, char * const argv[], char last_char, int maxv, char * static char tmp_buf[512]; int space; - space = last_char == '\0' || last_char == ' ' || last_char == '\t'; + space = last_char == '\0' || isblank(last_char); if (space && argc == 1) return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf); @@ -206,7 +207,7 @@ static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv } /* more than one arg or one but the start of the next */ - if (argc > 1 || (last_char == '\0' || last_char == ' ' || last_char == '\t')) { + if (argc > 1 || (last_char == '\0' || isblank(last_char))) { cmdtp = find_cmd(argv[0]); if (cmdtp == NULL || cmdtp->complete == NULL) { cmdv[0] = NULL; @@ -257,7 +258,7 @@ static int make_argv(char *s, int argvsz, char *argv[]) while (argc < argvsz - 1) { /* skip any white space */ - while ((*s == ' ') || (*s == '\t')) + while (isblank(*s)) ++s; if (*s == '\0') /* end of s, no more args */ @@ -266,7 +267,7 @@ static int make_argv(char *s, int argvsz, char *argv[]) argv[argc++] = s; /* begin of argument string */ /* find end of string */ - while (*s && (*s != ' ') && (*s != '\t')) + while (*s && !isblank(*s)) ++s; if (*s == '\0') /* end of s, no more args */ diff --git a/common/main.c b/common/main.c index d812aa186c..7be295528f 100644 --- a/common/main.c +++ b/common/main.c @@ -40,6 +40,7 @@ #endif #include +#include #if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING) DECLARE_GLOBAL_DATA_PTR; @@ -1097,7 +1098,7 @@ int parse_line (char *line, char *argv[]) while (nargs < CONFIG_SYS_MAXARGS) { /* skip any white space */ - while ((*line == ' ') || (*line == '\t')) + while (isblank(*line)) ++line; if (*line == '\0') { /* end of line, no more args */ @@ -1111,7 +1112,7 @@ int parse_line (char *line, char *argv[]) argv[nargs++] = line; /* begin of argument string */ /* find end of string */ - while (*line && (*line != ' ') && (*line != '\t')) + while (*line && !isblank(*line)) ++line; if (*line == '\0') { /* end of line, no more args */ diff --git a/drivers/bios_emulator/x86emu/debug.c b/drivers/bios_emulator/x86emu/debug.c index 241acf3a89..6417d09998 100644 --- a/drivers/bios_emulator/x86emu/debug.c +++ b/drivers/bios_emulator/x86emu/debug.c @@ -39,6 +39,7 @@ #include #include +#include #include "x86emu/x86emui.h" /*----------------------------- Implementation ----------------------------*/ @@ -333,7 +334,7 @@ static int x86emu_parse_line(char *s, int *ps, int *n) int cmd; *n = 0; - while (*s == ' ' || *s == '\t') + while (isblank(*s)) s++; ps[*n] = *s; switch (*s) { @@ -346,13 +347,13 @@ static int x86emu_parse_line(char *s, int *ps, int *n) } while (1) { - while (*s != ' ' && *s != '\t' && *s != '\n') + while (!isblank(*s) && *s != '\n') s++; if (*s == '\n') return cmd; - while (*s == ' ' || *s == '\t') + while (isblank(*s)) s++; *n += 1; diff --git a/examples/standalone/smc911x_eeprom.c b/examples/standalone/smc911x_eeprom.c index 00e826689f..6c79c5f65a 100644 --- a/examples/standalone/smc911x_eeprom.c +++ b/examples/standalone/smc911x_eeprom.c @@ -16,6 +16,7 @@ #include #include +#include #include "../drivers/net/smc911x.h" /** @@ -128,7 +129,7 @@ static int write_eeprom_reg(struct eth_device *dev, u8 value, u8 reg) */ static char *skip_space(char *buf) { - while (buf[0] == ' ' || buf[0] == '\t') + while (isblank(buf[0])) ++buf; return buf; } @@ -357,7 +358,7 @@ int smc911x_eeprom(int argc, char * const argv[]) continue; /* Only accept 1 letter commands */ - if (line[0] && line[1] && line[1] != ' ' && line[1] != '\t') + if (line[0] && line[1] && !isblank(line[1])) goto unknown_cmd; /* Now parse the command */ diff --git a/lib/hashtable.c b/lib/hashtable.c index 026dbca2fa..6895550d3c 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -32,6 +32,7 @@ #ifdef USE_HOSTCC /* HOST build */ # include # include +# include # ifndef debug # ifdef DEBUG @@ -43,6 +44,7 @@ #else /* U-Boot build */ # include # include +# include #endif #ifndef CONFIG_ENV_MIN_ENTRIES /* minimum number of entries */ @@ -690,7 +692,7 @@ int himport_r(struct hsearch_data *htab, ENTRY e, *rv; /* skip leading white space */ - while ((*dp == ' ') || (*dp == '\t')) + while (isblank(*dp)) ++dp; /* skip comment lines */ -- cgit From dc0b7b0e619e3f1413e626dde193fe21427ac831 Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Wed, 31 Aug 2011 05:37:28 +0000 Subject: README: document standard image variables With these documented, we can start pushing towards standardizing their use across boards. Signed-off-by: Jason Hobbs Cc: Mike Frysinger --- README | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README b/README index 7e032a91be..eb9ade9ad4 100644 --- a/README +++ b/README @@ -3558,6 +3558,25 @@ List of environment variables (most likely not complete): Ethernet is encapsulated/received over 802.1q VLAN tagged frames. +The following image location variables contain the location of images +used in booting. The "Image" column gives the role of the image and is +not an environment variable name. The other columns are environment +variable names. "File Name" gives the name of the file on a TFTP +server, "RAM Address" gives the location in RAM the image will be +loaded to, and "Flash Location" gives the image's address in NOR +flash or offset in NAND flash. + +*Note* - these variables don't have to be defined for all boards, some +boards currenlty use other variables for these purposes, and some +boards use these variables for other purposes. + +Image File Name RAM Address Flash Location +----- --------- ----------- -------------- +u-boot u-boot u-boot_addr_r u-boot_addr +Linux kernel bootfile kernel_addr_r kernel_addr +device tree blob fdtfile fdt_addr_r fdt_addr +ramdisk ramdiskfile ramdisk_addr_r ramdisk_addr + The following environment variables may be used and automatically updated by the network boot commands ("bootp" and "rarpboot"), depending the information provided by your boot server: -- cgit From e11938eabc17de35822de1a0a1102213c326f788 Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Tue, 23 Aug 2011 11:06:56 +0000 Subject: lib: add uuid_str_to_bin for use with bootp and PXE uuid Signed-off-by: Jason Hobbs --- include/common.h | 4 +++ lib/Makefile | 1 + lib/uuid.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 lib/uuid.c diff --git a/include/common.h b/include/common.h index f9fea08115..7950c8bded 100644 --- a/include/common.h +++ b/include/common.h @@ -694,6 +694,10 @@ int strcmp_compar(const void *, const void *); /* lib/time.c */ void udelay (unsigned long); +/* lib/uuid.c */ +void uuid_str_to_bin(const char *uuid, unsigned char *out); +int uuid_str_valid(const char *uuid); + /* lib/vsprintf.c */ ulong simple_strtoul(const char *cp,char **endp,unsigned int base); int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); diff --git a/lib/Makefile b/lib/Makefile index 884f64c00a..075bb8c284 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -55,6 +55,7 @@ COBJS-y += ctype.o COBJS-y += div64.o COBJS-y += string.o COBJS-y += time.o +COBJS-$(CONFIG_BOOTP_PXE) += uuid.o COBJS-y += vsprintf.o COBJS := $(COBJS-y) diff --git a/lib/uuid.c b/lib/uuid.c new file mode 100644 index 0000000000..10b022fcb8 --- /dev/null +++ b/lib/uuid.c @@ -0,0 +1,85 @@ +/* + * Copyright 2011 Calxeda, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 +#include "common.h" + +/* + * This is what a UUID string looks like. + * + * x is a hexadecimal character. fields are separated by '-'s. When converting + * to a binary UUID, le means the field should be converted to little endian, + * and be means it should be converted to big endian. + * + * 0 9 14 19 24 + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + * le le le be be + */ + +int uuid_str_valid(const char *uuid) +{ + int i, valid; + + if (uuid == NULL) + return 0; + + for (i = 0, valid = 1; uuid[i] && valid; i++) { + switch (i) { + case 8: case 13: case 18: case 23: + valid = (uuid[i] == '-'); + break; + default: + valid = isxdigit(uuid[i]); + break; + } + } + + if (i != 36 || !valid) + return 0; + + return 1; +} + +void uuid_str_to_bin(const char *uuid, unsigned char *out) +{ + uint16_t tmp16; + uint32_t tmp32; + uint64_t tmp64; + + if (!uuid || !out) + return; + + tmp32 = cpu_to_le32(simple_strtoul(uuid, NULL, 16)); + memcpy(out, &tmp32, 4); + + tmp16 = cpu_to_le16(simple_strtoul(uuid + 9, NULL, 16)); + memcpy(out + 4, &tmp16, 2); + + tmp16 = cpu_to_le16(simple_strtoul(uuid + 14, NULL, 16)); + memcpy(out + 6, &tmp16, 2); + + tmp16 = cpu_to_be16(simple_strtoul(uuid + 19, NULL, 16)); + memcpy(out + 8, &tmp16, 2); + + tmp64 = cpu_to_be64(simple_strtoull(uuid + 24, NULL, 16)); + memcpy(out + 10, (char *)&tmp64 + 2, 6); +} -- cgit From 06283a6401f652e709b7b27d02238d0c6f92cb0c Mon Sep 17 00:00:00 2001 From: Jason Hobbs Date: Wed, 31 Aug 2011 10:37:30 -0500 Subject: Add pxe command Add pxe command, which is intended to mimic PXELINUX functionality. 'pxe get' uses tftp to retrieve a file based on UUID, MAC address or IP address. 'pxe boot' interprets the contents of PXELINUX config like file to boot using a specific initrd, kernel and kernel command line. This patch also adds a README.pxe file - see it for more details on the pxe command. Signed-off-by: Jason Hobbs --- common/Makefile | 1 + common/cmd_pxe.c | 1355 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/main.c | 2 + doc/README.pxe | 240 ++++++++++ include/common.h | 6 + 5 files changed, 1604 insertions(+) create mode 100644 common/cmd_pxe.c create mode 100644 doc/README.pxe diff --git a/common/Makefile b/common/Makefile index 8e8dad4c91..e53c125e0d 100644 --- a/common/Makefile +++ b/common/Makefile @@ -136,6 +136,7 @@ COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o endif COBJS-y += cmd_pcmcia.o COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o +COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c new file mode 100644 index 0000000000..3efd7008e9 --- /dev/null +++ b/common/cmd_pxe.c @@ -0,0 +1,1355 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * + * 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 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, see . + */ +#include +#include +#include +#include +#include +#include +#include + +#include "menu.h" + +#define MAX_TFTP_PATH_LEN 127 + + +/* + * Like getenv, but prints an error if envvar isn't defined in the + * environment. It always returns what getenv does, so it can be used in + * place of getenv without changing error handling otherwise. + */ +static char *from_env(char *envvar) +{ + char *ret; + + ret = getenv(envvar); + + if (!ret) + printf("missing environment variable: %s\n", envvar); + + return ret; +} + +/* + * Convert an ethaddr from the environment to the format used by pxelinux + * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to + * the beginning of the ethernet address to indicate a hardware type of + * Ethernet. Also converts uppercase hex characters into lowercase, to match + * pxelinux's behavior. + * + * Returns 1 for success, -ENOENT if 'ethaddr' is undefined in the + * environment, or some other value < 0 on error. + */ +static int format_mac_pxe(char *outbuf, size_t outbuf_len) +{ + size_t ethaddr_len; + char *p, *ethaddr; + + ethaddr = from_env("ethaddr"); + + if (!ethaddr) + return -ENOENT; + + ethaddr_len = strlen(ethaddr); + + /* + * ethaddr_len + 4 gives room for "01-", ethaddr, and a NUL byte at + * the end. + */ + if (outbuf_len < ethaddr_len + 4) { + printf("outbuf is too small (%d < %d)\n", + outbuf_len, ethaddr_len + 4); + + return -EINVAL; + } + + strcpy(outbuf, "01-"); + + for (p = outbuf + 3; *ethaddr; ethaddr++, p++) { + if (*ethaddr == ':') + *p = '-'; + else + *p = tolower(*ethaddr); + } + + *p = '\0'; + + return 1; +} + +/* + * Returns the directory the file specified in the bootfile env variable is + * in. If bootfile isn't defined in the environment, return NULL, which should + * be interpreted as "don't prepend anything to paths". + */ +static int get_bootfile_path(char *bootfile_path, size_t bootfile_path_size) +{ + char *bootfile, *last_slash; + size_t path_len; + + bootfile = from_env("bootfile"); + + if (!bootfile) { + bootfile_path[0] = '\0'; + return 1; + } + + last_slash = strrchr(bootfile, '/'); + + if (last_slash == NULL) { + bootfile_path[0] = '\0'; + return 1; + } + + path_len = (last_slash - bootfile) + 1; + + if (bootfile_path_size < path_len) { + printf("bootfile_path too small. (%d < %d)\n", + bootfile_path_size, path_len); + + return -1; + } + + strncpy(bootfile_path, bootfile, path_len); + + bootfile_path[path_len] = '\0'; + + return 1; +} + +/* + * As in pxelinux, paths to files referenced from files we retrieve are + * relative to the location of bootfile. get_relfile takes such a path and + * joins it with the bootfile path to get the full path to the target file. If + * the bootfile path is NULL, we use file_path as is. + * + * Returns 1 for success, or < 0 on error. + */ +static int get_relfile(char *file_path, void *file_addr) +{ + size_t path_len; + char relfile[MAX_TFTP_PATH_LEN+1]; + char addr_buf[10]; + char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; + int err; + + err = get_bootfile_path(relfile, sizeof(relfile)); + + if (err < 0) + return err; + + path_len = strlen(file_path); + path_len += strlen(relfile); + + if (path_len > MAX_TFTP_PATH_LEN) { + printf("Base path too long (%s%s)\n", + relfile, + file_path); + + return -ENAMETOOLONG; + } + + strcat(relfile, file_path); + + printf("Retrieving file: %s\n", relfile); + + sprintf(addr_buf, "%p", file_addr); + + tftp_argv[1] = addr_buf; + tftp_argv[2] = relfile; + + if (do_tftpb(NULL, 0, 3, tftp_argv)) + return -ENOENT; + + return 1; +} + +/* + * Retrieve the file at 'file_path' to the locate given by 'file_addr'. If + * 'bootfile' was specified in the environment, the path to bootfile will be + * prepended to 'file_path' and the resulting path will be used. + * + * Returns 1 on success, or < 0 for error. + */ +static int get_pxe_file(char *file_path, void *file_addr) +{ + unsigned long config_file_size; + char *tftp_filesize; + int err; + + err = get_relfile(file_path, file_addr); + + if (err < 0) + return err; + + /* + * the file comes without a NUL byte at the end, so find out its size + * and add the NUL byte. + */ + tftp_filesize = from_env("filesize"); + + if (!tftp_filesize) + return -ENOENT; + + if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0) + return -EINVAL; + + *(char *)(file_addr + config_file_size) = '\0'; + + return 1; +} + +#define PXELINUX_DIR "pxelinux.cfg/" + +/* + * Retrieves a file in the 'pxelinux.cfg' folder. Since this uses get_pxe_file + * to do the hard work, the location of the 'pxelinux.cfg' folder is generated + * from the bootfile path, as described above. + * + * Returns 1 on success or < 0 on error. + */ +static int get_pxelinux_path(char *file, void *pxefile_addr_r) +{ + size_t base_len = strlen(PXELINUX_DIR); + char path[MAX_TFTP_PATH_LEN+1]; + + if (base_len + strlen(file) > MAX_TFTP_PATH_LEN) { + printf("path (%s%s) too long, skipping\n", + PXELINUX_DIR, file); + return -ENAMETOOLONG; + } + + sprintf(path, PXELINUX_DIR "%s", file); + + return get_pxe_file(path, pxefile_addr_r); +} + +/* + * Looks for a pxe file with a name based on the pxeuuid environment variable. + * + * Returns 1 on success or < 0 on error. + */ +static int pxe_uuid_path(void *pxefile_addr_r) +{ + char *uuid_str; + + uuid_str = from_env("pxeuuid"); + + if (!uuid_str) + return -ENOENT; + + return get_pxelinux_path(uuid_str, pxefile_addr_r); +} + +/* + * Looks for a pxe file with a name based on the 'ethaddr' environment + * variable. + * + * Returns 1 on success or < 0 on error. + */ +static int pxe_mac_path(void *pxefile_addr_r) +{ + char mac_str[21]; + int err; + + err = format_mac_pxe(mac_str, sizeof(mac_str)); + + if (err < 0) + return err; + + return get_pxelinux_path(mac_str, pxefile_addr_r); +} + +/* + * Looks for pxe files with names based on our IP address. See pxelinux + * documentation for details on what these file names look like. We match + * that exactly. + * + * Returns 1 on success or < 0 on error. + */ +static int pxe_ipaddr_paths(void *pxefile_addr_r) +{ + char ip_addr[9]; + int mask_pos, err; + + sprintf(ip_addr, "%08X", ntohl(NetOurIP)); + + for (mask_pos = 7; mask_pos >= 0; mask_pos--) { + err = get_pxelinux_path(ip_addr, pxefile_addr_r); + + if (err > 0) + return err; + + ip_addr[mask_pos] = '\0'; + } + + return -ENOENT; +} + +/* + * Entry point for the 'pxe get' command. + * This Follows pxelinux's rules to download a config file from a tftp server. + * The file is stored at the location given by the pxefile_addr_r environment + * variable, which must be set. + * + * UUID comes from pxeuuid env variable, if defined + * MAC addr comes from ethaddr env variable, if defined + * IP + * + * see http://syslinux.zytor.com/wiki/index.php/PXELINUX + * + * Returns 0 on success or 1 on error. + */ +static int +do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *pxefile_addr_str; + void *pxefile_addr_r; + int err; + + if (argc != 1) + return cmd_usage(cmdtp); + + + pxefile_addr_str = from_env("pxefile_addr_r"); + + if (!pxefile_addr_str) + return 1; + + err = strict_strtoul(pxefile_addr_str, 16, + (unsigned long *)&pxefile_addr_r); + if (err < 0) + return 1; + + /* + * Keep trying paths until we successfully get a file we're looking + * for. + */ + if (pxe_uuid_path(pxefile_addr_r) > 0 + || pxe_mac_path(pxefile_addr_r) > 0 + || pxe_ipaddr_paths(pxefile_addr_r) > 0 + || get_pxelinux_path("default", pxefile_addr_r) > 0) { + + printf("Config file found\n"); + + return 0; + } + + printf("Config file not found\n"); + + return 1; +} + +/* + * Wrapper to make it easier to store the file at file_path in the location + * specified by envaddr_name. file_path will be joined to the bootfile path, + * if any is specified. + * + * Returns 1 on success or < 0 on error. + */ +static int get_relfile_envaddr(char *file_path, char *envaddr_name) +{ + void *file_addr; + char *envaddr; + + envaddr = from_env(envaddr_name); + + if (!envaddr) + return -ENOENT; + + if (strict_strtoul(envaddr, 16, (unsigned long *)&file_addr) < 0) + return -EINVAL; + + return get_relfile(file_path, file_addr); +} + +/* + * A note on the pxe file parser. + * + * We're parsing files that use syslinux grammar, which has a few quirks. + * String literals must be recognized based on context - there is no + * quoting or escaping support. There's also nothing to explicitly indicate + * when a label section completes. We deal with that by ending a label + * section whenever we see a line that doesn't include. + * + * As with the syslinux family, this same file format could be reused in the + * future for non pxe purposes. The only action it takes during parsing that + * would throw this off is handling of include files. It assumes we're using + * pxe, and does a tftp download of a file listed as an include file in the + * middle of the parsing operation. That could be handled by refactoring it to + * take a 'include file getter' function. + */ + +/* + * Describes a single label given in a pxe file. + * + * Create these with the 'label_create' function given below. + * + * name - the name of the menu as given on the 'menu label' line. + * kernel - the path to the kernel file to use for this label. + * append - kernel command line to use when booting this label + * initrd - path to the initrd to use for this label. + * attempted - 0 if we haven't tried to boot this label, 1 if we have. + * localboot - 1 if this label specified 'localboot', 0 otherwise. + * list - lets these form a list, which a pxe_menu struct will hold. + */ +struct pxe_label { + char *name; + char *kernel; + char *append; + char *initrd; + int attempted; + int localboot; + struct list_head list; +}; + +/* + * Describes a pxe menu as given via pxe files. + * + * title - the name of the menu as given by a 'menu title' line. + * default_label - the name of the default label, if any. + * timeout - time in tenths of a second to wait for a user key-press before + * booting the default label. + * prompt - if 0, don't prompt for a choice unless the timeout period is + * interrupted. If 1, always prompt for a choice regardless of + * timeout. + * labels - a list of labels defined for the menu. + */ +struct pxe_menu { + char *title; + char *default_label; + int timeout; + int prompt; + struct list_head labels; +}; + +/* + * Allocates memory for and initializes a pxe_label. This uses malloc, so the + * result must be free()'d to reclaim the memory. + * + * Returns NULL if malloc fails. + */ +static struct pxe_label *label_create(void) +{ + struct pxe_label *label; + + label = malloc(sizeof(struct pxe_label)); + + if (!label) + return NULL; + + memset(label, 0, sizeof(struct pxe_label)); + + return label; +} + +/* + * Free the memory used by a pxe_label, including that used by its name, + * kernel, append and initrd members, if they're non NULL. + * + * So - be sure to only use dynamically allocated memory for the members of + * the pxe_label struct, unless you want to clean it up first. These are + * currently only created by the pxe file parsing code. + */ +static void label_destroy(struct pxe_label *label) +{ + if (label->name) + free(label->name); + + if (label->kernel) + free(label->kernel); + + if (label->append) + free(label->append); + + if (label->initrd) + free(label->initrd); + + free(label); +} + +/* + * Print a label and its string members if they're defined. + * + * This is passed as a callback to the menu code for displaying each + * menu entry. + */ +static void label_print(void *data) +{ + struct pxe_label *label = data; + + printf("Label: %s\n", label->name); + + if (label->kernel) + printf("\tkernel: %s\n", label->kernel); + + if (label->append) + printf("\tappend: %s\n", label->append); + + if (label->initrd) + printf("\tinitrd: %s\n", label->initrd); +} + +/* + * Boot a label that specified 'localboot'. This requires that the 'localcmd' + * environment variable is defined. Its contents will be executed as U-boot + * command. If the label specified an 'append' line, its contents will be + * used to overwrite the contents of the 'bootargs' environment variable prior + * to running 'localcmd'. + * + * Returns 1 on success or < 0 on error. + */ +static int label_localboot(struct pxe_label *label) +{ + char *localcmd, *dupcmd; + int ret; + + localcmd = from_env("localcmd"); + + if (!localcmd) + return -ENOENT; + + /* + * dup the command to avoid any issues with the version of it existing + * in the environment changing during the execution of the command. + */ + dupcmd = strdup(localcmd); + + if (!dupcmd) + return -ENOMEM; + + if (label->append) + setenv("bootargs", label->append); + + printf("running: %s\n", dupcmd); + + ret = run_command2(dupcmd, 0); + + free(dupcmd); + + return ret; +} + +/* + * Boot according to the contents of a pxe_label. + * + * If we can't boot for any reason, we return. A successful boot never + * returns. + * + * The kernel will be stored in the location given by the 'kernel_addr_r' + * environment variable. + * + * If the label specifies an initrd file, it will be stored in the location + * given by the 'ramdisk_addr_r' environment variable. + * + * If the label specifies an 'append' line, its contents will overwrite that + * of the 'bootargs' environment variable. + */ +static void label_boot(struct pxe_label *label) +{ + char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; + int bootm_argc = 3; + + label_print(label); + + label->attempted = 1; + + if (label->localboot) { + label_localboot(label); + return; + } + + if (label->kernel == NULL) { + printf("No kernel given, skipping %s\n", + label->name); + return; + } + + if (label->initrd) { + if (get_relfile_envaddr(label->initrd, "ramdisk_addr_r") < 0) { + printf("Skipping %s for failure retrieving initrd\n", + label->name); + return; + } + + bootm_argv[2] = getenv("ramdisk_addr_r"); + } else { + bootm_argv[2] = "-"; + } + + if (get_relfile_envaddr(label->kernel, "kernel_addr_r") < 0) { + printf("Skipping %s for failure retrieving kernel\n", + label->name); + return; + } + + if (label->append) + setenv("bootargs", label->append); + + bootm_argv[1] = getenv("kernel_addr_r"); + + /* + * fdt usage is optional. If there is an fdt_addr specified, we will + * pass it along to bootm, and adjust argc appropriately. + */ + bootm_argv[3] = getenv("fdt_addr"); + + if (bootm_argv[3]) + bootm_argc = 4; + + do_bootm(NULL, 0, bootm_argc, bootm_argv); +} + +/* + * Tokens for the pxe file parser. + */ +enum token_type { + T_EOL, + T_STRING, + T_EOF, + T_MENU, + T_TITLE, + T_TIMEOUT, + T_LABEL, + T_KERNEL, + T_APPEND, + T_INITRD, + T_LOCALBOOT, + T_DEFAULT, + T_PROMPT, + T_INCLUDE, + T_INVALID +}; + +/* + * A token - given by a value and a type. + */ +struct token { + char *val; + enum token_type type; +}; + +/* + * Keywords recognized. + */ +static const struct token keywords[] = { + {"menu", T_MENU}, + {"title", T_TITLE}, + {"timeout", T_TIMEOUT}, + {"default", T_DEFAULT}, + {"prompt", T_PROMPT}, + {"label", T_LABEL}, + {"kernel", T_KERNEL}, + {"localboot", T_LOCALBOOT}, + {"append", T_APPEND}, + {"initrd", T_INITRD}, + {"include", T_INCLUDE}, + {NULL, T_INVALID} +}; + +/* + * Since pxe(linux) files don't have a token to identify the start of a + * literal, we have to keep track of when we're in a state where a literal is + * expected vs when we're in a state a keyword is expected. + */ +enum lex_state { + L_NORMAL = 0, + L_KEYWORD, + L_SLITERAL +}; + +/* + * get_string retrieves a string from *p and stores it as a token in + * *t. + * + * get_string used for scanning both string literals and keywords. + * + * Characters from *p are copied into t-val until a character equal to + * delim is found, or a NUL byte is reached. If delim has the special value of + * ' ', any whitespace character will be used as a delimiter. + * + * If lower is unequal to 0, uppercase characters will be converted to + * lowercase in the result. This is useful to make keywords case + * insensitive. + * + * The location of *p is updated to point to the first character after the end + * of the token - the ending delimiter. + * + * On success, the new value of t->val is returned. Memory for t->val is + * allocated using malloc and must be free()'d to reclaim it. If insufficient + * memory is available, NULL is returned. + */ +static char *get_string(char **p, struct token *t, char delim, int lower) +{ + char *b, *e; + size_t len, i; + + /* + * b and e both start at the beginning of the input stream. + * + * e is incremented until we find the ending delimiter, or a NUL byte + * is reached. Then, we take e - b to find the length of the token. + */ + b = e = *p; + + while (*e) { + if ((delim == ' ' && isspace(*e)) || delim == *e) + break; + e++; + } + + len = e - b; + + /* + * Allocate memory to hold the string, and copy it in, converting + * characters to lowercase if lower is != 0. + */ + t->val = malloc(len + 1); + if (!t->val) + return NULL; + + for (i = 0; i < len; i++, b++) { + if (lower) + t->val[i] = tolower(*b); + else + t->val[i] = *b; + } + + t->val[len] = '\0'; + + /* + * Update *p so the caller knows where to continue scanning. + */ + *p = e; + + t->type = T_STRING; + + return t->val; +} + +/* + * Populate a keyword token with a type and value. + */ +static void get_keyword(struct token *t) +{ + int i; + + for (i = 0; keywords[i].val; i++) { + if (!strcmp(t->val, keywords[i].val)) { + t->type = keywords[i].type; + break; + } + } +} + +/* + * Get the next token. We have to keep track of which state we're in to know + * if we're looking to get a string literal or a keyword. + * + * *p is updated to point at the first character after the current token. + */ +static void get_token(char **p, struct token *t, enum lex_state state) +{ + char *c = *p; + + t->type = T_INVALID; + + /* eat non EOL whitespace */ + while (isblank(*c)) + c++; + + /* + * eat comments. note that string literals can't begin with #, but + * can contain a # after their first character. + */ + if (*c == '#') { + while (*c && *c != '\n') + c++; + } + + if (*c == '\n') { + t->type = T_EOL; + c++; + } else if (*c == '\0') { + t->type = T_EOF; + c++; + } else if (state == L_SLITERAL) { + get_string(&c, t, '\n', 0); + } else if (state == L_KEYWORD) { + /* + * when we expect a keyword, we first get the next string + * token delimited by whitespace, and then check if it + * matches a keyword in our keyword list. if it does, it's + * converted to a keyword token of the appropriate type, and + * if not, it remains a string token. + */ + get_string(&c, t, ' ', 1); + get_keyword(t); + } + + *p = c; +} + +/* + * Increment *c until we get to the end of the current line, or EOF. + */ +static void eol_or_eof(char **c) +{ + while (**c && **c != '\n') + (*c)++; +} + +/* + * All of these parse_* functions share some common behavior. + * + * They finish with *c pointing after the token they parse, and return 1 on + * success, or < 0 on error. + */ + +/* + * Parse a string literal and store a pointer it at *dst. String literals + * terminate at the end of the line. + */ +static int parse_sliteral(char **c, char **dst) +{ + struct token t; + char *s = *c; + + get_token(c, &t, L_SLITERAL); + + if (t.type != T_STRING) { + printf("Expected string literal: %.*s\n", (int)(*c - s), s); + return -EINVAL; + } + + *dst = t.val; + + return 1; +} + +/* + * Parse a base 10 (unsigned) integer and store it at *dst. + */ +static int parse_integer(char **c, int *dst) +{ + struct token t; + char *s = *c; + unsigned long temp; + + get_token(c, &t, L_SLITERAL); + + if (t.type != T_STRING) { + printf("Expected string: %.*s\n", (int)(*c - s), s); + return -EINVAL; + } + + if (strict_strtoul(t.val, 10, &temp) < 0) { + printf("Expected unsigned integer: %s\n", t.val); + return -EINVAL; + } + + *dst = (int)temp; + + free(t.val); + + return 1; +} + +static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level); + +/* + * Parse an include statement, and retrieve and parse the file it mentions. + * + * base should point to a location where it's safe to store the file, and + * nest_level should indicate how many nested includes have occurred. For this + * include, nest_level has already been incremented and doesn't need to be + * incremented here. + */ +static int handle_include(char **c, char *base, + struct pxe_menu *cfg, int nest_level) +{ + char *include_path; + char *s = *c; + int err; + + err = parse_sliteral(c, &include_path); + + if (err < 0) { + printf("Expected include path: %.*s\n", + (int)(*c - s), s); + return err; + } + + err = get_pxe_file(include_path, base); + + if (err < 0) { + printf("Couldn't retrieve %s\n", include_path); + return err; + } + + return parse_pxefile_top(base, cfg, nest_level); +} + +/* + * Parse lines that begin with 'menu'. + * + * b and nest are provided to handle the 'menu include' case. + * + * b should be the address where the file currently being parsed is stored. + * + * nest_level should be 1 when parsing the top level pxe file, 2 when parsing + * a file it includes, 3 when parsing a file included by that file, and so on. + */ +static int parse_menu(char **c, struct pxe_menu *cfg, char *b, int nest_level) +{ + struct token t; + char *s = *c; + int err; + + get_token(c, &t, L_KEYWORD); + + switch (t.type) { + case T_TITLE: + err = parse_sliteral(c, &cfg->title); + + break; + + case T_INCLUDE: + err = handle_include(c, b + strlen(b) + 1, cfg, + nest_level + 1); + break; + + default: + printf("Ignoring malformed menu command: %.*s\n", + (int)(*c - s), s); + } + + if (err < 0) + return err; + + eol_or_eof(c); + + return 1; +} + +/* + * Handles parsing a 'menu line' when we're parsing a label. + */ +static int parse_label_menu(char **c, struct pxe_menu *cfg, + struct pxe_label *label) +{ + struct token t; + char *s; + + s = *c; + + get_token(c, &t, L_KEYWORD); + + switch (t.type) { + case T_DEFAULT: + if (cfg->default_label) + free(cfg->default_label); + + cfg->default_label = strdup(label->name); + + if (!cfg->default_label) + return -ENOMEM; + + break; + default: + printf("Ignoring malformed menu command: %.*s\n", + (int)(*c - s), s); + } + + eol_or_eof(c); + + return 0; +} + +/* + * Parses a label and adds it to the list of labels for a menu. + * + * A label ends when we either get to the end of a file, or + * get some input we otherwise don't have a handler defined + * for. + * + */ +static int parse_label(char **c, struct pxe_menu *cfg) +{ + struct token t; + char *s = *c; + struct pxe_label *label; + int err; + + label = label_create(); + if (!label) + return -ENOMEM; + + err = parse_sliteral(c, &label->name); + if (err < 0) { + printf("Expected label name: %.*s\n", (int)(*c - s), s); + label_destroy(label); + return -EINVAL; + } + + list_add_tail(&label->list, &cfg->labels); + + while (1) { + s = *c; + get_token(c, &t, L_KEYWORD); + + err = 0; + switch (t.type) { + case T_MENU: + err = parse_label_menu(c, cfg, label); + break; + + case T_KERNEL: + err = parse_sliteral(c, &label->kernel); + break; + + case T_APPEND: + err = parse_sliteral(c, &label->append); + break; + + case T_INITRD: + err = parse_sliteral(c, &label->initrd); + break; + + case T_LOCALBOOT: + err = parse_integer(c, &label->localboot); + break; + + case T_EOL: + break; + + default: + /* + * put the token back! we don't want it - it's the end + * of a label and whatever token this is, it's + * something for the menu level context to handle. + */ + *c = s; + return 1; + } + + if (err < 0) + return err; + } +} + +/* + * This 16 comes from the limit pxelinux imposes on nested includes. + * + * There is no reason at all we couldn't do more, but some limit helps prevent + * infinite (until crash occurs) recursion if a file tries to include itself. + */ +#define MAX_NEST_LEVEL 16 + +/* + * Entry point for parsing a menu file. nest_level indicates how many times + * we've nested in includes. It will be 1 for the top level menu file. + * + * Returns 1 on success, < 0 on error. + */ +static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level) +{ + struct token t; + char *s, *b, *label_name; + int err; + + b = p; + + if (nest_level > MAX_NEST_LEVEL) { + printf("Maximum nesting (%d) exceeded\n", MAX_NEST_LEVEL); + return -EMLINK; + } + + while (1) { + s = p; + + get_token(&p, &t, L_KEYWORD); + + err = 0; + switch (t.type) { + case T_MENU: + err = parse_menu(&p, cfg, b, nest_level); + break; + + case T_TIMEOUT: + err = parse_integer(&p, &cfg->timeout); + break; + + case T_LABEL: + err = parse_label(&p, cfg); + break; + + case T_DEFAULT: + err = parse_sliteral(&p, &label_name); + + if (label_name) { + if (cfg->default_label) + free(cfg->default_label); + + cfg->default_label = label_name; + } + + break; + + case T_PROMPT: + err = parse_integer(&p, &cfg->prompt); + break; + + case T_EOL: + break; + + case T_EOF: + return 1; + + default: + printf("Ignoring unknown command: %.*s\n", + (int)(p - s), s); + eol_or_eof(&p); + } + + if (err < 0) + return err; + } +} + +/* + * Free the memory used by a pxe_menu and its labels. + */ +static void destroy_pxe_menu(struct pxe_menu *cfg) +{ + struct list_head *pos, *n; + struct pxe_label *label; + + if (cfg->title) + free(cfg->title); + + if (cfg->default_label) + free(cfg->default_label); + + list_for_each_safe(pos, n, &cfg->labels) { + label = list_entry(pos, struct pxe_label, list); + + label_destroy(label); + } + + free(cfg); +} + +/* + * Entry point for parsing a pxe file. This is only used for the top level + * file. + * + * Returns NULL if there is an error, otherwise, returns a pointer to a + * pxe_menu struct populated with the results of parsing the pxe file (and any + * files it includes). The resulting pxe_menu struct can be free()'d by using + * the destroy_pxe_menu() function. + */ +static struct pxe_menu *parse_pxefile(char *menucfg) +{ + struct pxe_menu *cfg; + + cfg = malloc(sizeof(struct pxe_menu)); + + if (!cfg) + return NULL; + + memset(cfg, 0, sizeof(struct pxe_menu)); + + INIT_LIST_HEAD(&cfg->labels); + + if (parse_pxefile_top(menucfg, cfg, 1) < 0) { + destroy_pxe_menu(cfg); + return NULL; + } + + return cfg; +} + +/* + * Converts a pxe_menu struct into a menu struct for use with U-boot's generic + * menu code. + */ +static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg) +{ + struct pxe_label *label; + struct list_head *pos; + struct menu *m; + int err; + + /* + * Create a menu and add items for all the labels. + */ + m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print); + + if (!m) + return NULL; + + list_for_each(pos, &cfg->labels) { + label = list_entry(pos, struct pxe_label, list); + + if (menu_item_add(m, label->name, label) != 1) { + menu_destroy(m); + return NULL; + } + } + + /* + * After we've created items for each label in the menu, set the + * menu's default label if one was specified. + */ + if (cfg->default_label) { + err = menu_default_set(m, cfg->default_label); + if (err != 1) { + if (err != -ENOENT) { + menu_destroy(m); + return NULL; + } + + printf("Missing default: %s\n", cfg->default_label); + } + } + + return m; +} + +/* + * Try to boot any labels we have yet to attempt to boot. + */ +static void boot_unattempted_labels(struct pxe_menu *cfg) +{ + struct list_head *pos; + struct pxe_label *label; + + list_for_each(pos, &cfg->labels) { + label = list_entry(pos, struct pxe_label, list); + + if (!label->attempted) + label_boot(label); + } +} + +/* + * Boot the system as prescribed by a pxe_menu. + * + * Use the menu system to either get the user's choice or the default, based + * on config or user input. If there is no default or user's choice, + * attempted to boot labels in the order they were given in pxe files. + * If the default or user's choice fails to boot, attempt to boot other + * labels in the order they were given in pxe files. + * + * If this function returns, there weren't any labels that successfully + * booted, or the user interrupted the menu selection via ctrl+c. + */ +static void handle_pxe_menu(struct pxe_menu *cfg) +{ + void *choice; + struct menu *m; + int err; + + m = pxe_menu_to_menu(cfg); + if (!m) + return; + + err = menu_get_choice(m, &choice); + + menu_destroy(m); + + if (err < 1) + return; + + label_boot(choice); + + boot_unattempted_labels(cfg); +} + +/* + * Boots a system using a pxe file + * + * Returns 0 on success, 1 on error. + */ +static int +do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned long pxefile_addr_r; + struct pxe_menu *cfg; + char *pxefile_addr_str; + + if (argc == 1) { + pxefile_addr_str = from_env("pxefile_addr_r"); + if (!pxefile_addr_str) + return 1; + + } else if (argc == 2) { + pxefile_addr_str = argv[1]; + } else { + return cmd_usage(cmdtp); + } + + if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) { + printf("Invalid pxefile address: %s\n", pxefile_addr_str); + return 1; + } + + cfg = parse_pxefile((char *)(pxefile_addr_r)); + + if (cfg == NULL) { + printf("Error parsing config file\n"); + return 1; + } + + handle_pxe_menu(cfg); + + destroy_pxe_menu(cfg); + + return 0; +} + +static cmd_tbl_t cmd_pxe_sub[] = { + U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""), + U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "") +}; + +int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *cp; + + if (argc < 2) + return cmd_usage(cmdtp); + + /* drop initial "pxe" arg */ + argc--; + argv++; + + cp = find_cmd_tbl(argv[0], cmd_pxe_sub, ARRAY_SIZE(cmd_pxe_sub)); + + if (cp) + return cp->cmd(cmdtp, flag, argc, argv); + + return cmd_usage(cmdtp); +} + +U_BOOT_CMD( + pxe, 3, 1, do_pxe, + "commands to get and boot from pxe files", + "get - try to retrieve a pxe file using tftp\npxe " + "boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n" +); diff --git a/common/main.c b/common/main.c index 7be295528f..e96c95a038 100644 --- a/common/main.c +++ b/common/main.c @@ -269,7 +269,9 @@ int abortboot(int bootdelay) /* * Return 0 on success, or != 0 on error. */ +#ifndef CONFIG_CMD_PXE static inline +#endif int run_command2(const char *cmd, int flag) { #ifndef CONFIG_SYS_HUSH_PARSER diff --git a/doc/README.pxe b/doc/README.pxe new file mode 100644 index 0000000000..9026d9c9df --- /dev/null +++ b/doc/README.pxe @@ -0,0 +1,240 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * + * 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 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, see . + */ + +The 'pxe' commands provide a near subset of the functionality provided by +the PXELINUX boot loader. This allows U-boot based systems to be controlled +remotely using the same PXE based techniques that many non U-boot based servers +use. + +Commands +======== + +pxe get +------- + syntax: pxe get + + follows PXELINUX's rules for retrieving configuration files from a tftp + server, and supports a subset of PXELINUX's config file syntax. + + Environment + ----------- + 'pxe get' requires two environment variables to be set: + + pxefile_addr_r - should be set to a location in RAM large enough to hold + pxe files while they're being processed. Up to 16 config files may be + held in memory at once. The exact number and size of the files varies with + how the system is being used. A typical config file is a few hundred bytes + long. + + bootfile,serverip - these two are typically set in the DHCP response + handler, and correspond to fields in the DHCP response. + + 'pxe get' optionally supports these two environment variables being set: + + ethaddr - this is the standard MAC address for the ethernet adapter in use. + 'pxe get' uses it to look for a configuration file specific to a system's + MAC address. + + pxeuuid - this is a UUID in standard form using lower case hexadecimal + digits, for example, 550e8400-e29b-41d4-a716-446655440000. 'pxe get' uses + it to look for a configuration file based on the system's UUID. + + File Paths + ---------- + 'pxe get' repeatedly tries to download config files until it either + successfully downloads one or runs out of paths to try. The order and + contents of paths it tries mirrors exactly that of PXELINUX - you can + read in more detail about it at: + + http://syslinux.zytor.com/wiki/index.php/Doc/pxelinux + +pxe boot +-------- + syntax: pxe boot [pxefile_addr_r] + + Interprets a pxe file stored in memory. + + pxefile_addr_r is an optional argument giving the location of the pxe file. + The file must be terminated with a NUL byte. + + Environment + ----------- + There are some environment variables that may need to be set, depending + on conditions. + + pxefile_addr_r - if the optional argument pxefile_addr_r is not supplied, + an environment variable named pxefile_addr_r must be supplied. This is + typically the same value as is used for the 'pxe get' command. + + bootfile - typically set in the DHCP response handler based on the + same field in the DHCP respone, this path is used to generate the base + directory that all other paths to files retrieved by 'pxe boot' will use. + If no bootfile is specified, paths used in pxe files will be used as is. + + serverip - typically set in the DHCP response handler, this is the IP + address of the tftp server from which other files will be retrieved. + + kernel_addr_r, initrd_addr_r - locations in RAM at which 'pxe boot' will + store the kernel and initrd it retrieves from tftp. These locations will + be passed to the bootm command to boot the kernel. These environment + variables are required to be set. + + fdt_addr - the location of a fdt blob. If this is set, it will be passed + to bootm when booting a kernel. + +pxe file format +=============== +The pxe file format is nearly a subset of the PXELINUX file format; see +http://syslinux.zytor.com/wiki/index.php/PXELINUX. It's composed of one line +commands - global commands, and commands specific to labels. Lines begining +with # are treated as comments. White space between and at the beginning of +lines is ignored. + +The size of pxe files and the number of labels is only limited by the amount +of RAM available to U-boot. Memory for labels is dynamically allocated as +they're parsed, and memory for pxe files is statically allocated, and its +location is given by the pxefile_addr_r environment variable. The pxe code is +not aware of the size of the pxefile memory and will outgrow it if pxe files +are too large. + +Supported global commands +------------------------- +Unrecognized commands are ignored. + +default