[U-Boot] [PATCH 00/15] x86: minnowmax: Add interrupt support

This series brings in interrupt support for Minnowmax, so that PCI interrupts are correctly set up for Linux. It also includes a few small improvements to the PCI driver model implementation and tidies up some nits in the code.
The existing pirq routing code does not seem to support the Atom used in the Minnowmax. I'd like to figure that out before applying the RFC patch.
Simon Glass (15): pci: Add a constant for an invalid interrupt pci: Indicate prefetchable memory allocate when debugging dm: Add a return value comment to device_get_child() dm: pci: Provide friendly config access functions dm: pci: Add a way to iterate through all PCI devices x86: Move Chrome OS options to defconfig x86: Move CONFIG_X86_SERIAL to Kconfig x86: Re-order efi-x86_defconfig x86: Drop CONFIG_DCACHE_RAM_MRC_VAR_SIZE from header file x86: dts: Fix typo in intel,irq-router.txt x86: Tidy up the PIRQ routing code a little x86: Split out fsp_init_phase_pci() code into a new function x86: minnowmax: Drop the old PCI settings RFC: x86: minnowmax: Add interrupt routing setup x86: Update README to explain booting Ubuntu on Minnowmax
arch/x86/cpu/baytrail/valleyview.c | 492 +++++++++++++++++++++ arch/x86/cpu/irq.c | 40 +- arch/x86/dts/minnowmax.dts | 28 ++ arch/x86/include/asm/fsp/fsp_support.h | 7 + arch/x86/lib/fsp/fsp_common.c | 11 +- configs/chromebook_link_defconfig | 3 + configs/chromebox_panther_defconfig | 3 + configs/efi-x86_defconfig | 10 +- doc/README.x86 | 275 ++++++++++++ doc/device-tree-bindings/misc/intel,irq-router.txt | 4 +- drivers/pci/pci-uclass.c | 134 ++++++ drivers/pci/pci.c | 3 +- drivers/pci/pci_auto.c | 5 +- drivers/serial/Kconfig | 10 + include/configs/crownbay.h | 1 - include/configs/galileo.h | 2 - include/configs/minnowmax.h | 14 +- include/configs/qemu-x86.h | 2 - include/configs/x86-chromebook.h | 6 - include/dm/device.h | 2 + include/pci.h | 44 ++ 21 files changed, 1032 insertions(+), 64 deletions(-)

Rather than using 0xff in the code, add a constant.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci.c | 3 ++- include/pci.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 157491c..9dd245c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -269,7 +269,8 @@ int pci_hose_config_device(struct pci_controller *hose, /* Disable interrupt line, if device says it wants to use interrupts */ pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); if (pin != 0) { - pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff); + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, + PCI_INTERRUPT_LINE_DISABLE); }
pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command); diff --git a/include/pci.h b/include/pci.h index 94bca97..26cd80b 100644 --- a/include/pci.h +++ b/include/pci.h @@ -228,6 +228,8 @@ #define PCI_MIN_GNT 0x3e /* 8 bits */ #define PCI_MAX_LAT 0x3f /* 8 bits */
+#define PCI_INTERRUPT_LINE_DISABLE 0xff + /* Header type 1 (PCI-to-PCI bridges) */ #define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ #define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Rather than using 0xff in the code, add a constant.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci.c | 3 ++- include/pci.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 157491c..9dd245c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -269,7 +269,8 @@ int pci_hose_config_device(struct pci_controller *hose, /* Disable interrupt line, if device says it wants to use interrupts */ pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); if (pin != 0) {
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff);
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
PCI_INTERRUPT_LINE_DISABLE); } pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);
diff --git a/include/pci.h b/include/pci.h index 94bca97..26cd80b 100644 --- a/include/pci.h +++ b/include/pci.h @@ -228,6 +228,8 @@ #define PCI_MIN_GNT 0x3e /* 8 bits */ #define PCI_MAX_LAT 0x3f /* 8 bits */
+#define PCI_INTERRUPT_LINE_DISABLE 0xff
/* Header type 1 (PCI-to-PCI bridges) */ #define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 28 July 2015 at 01:46, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Rather than using 0xff in the code, add a constant.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci.c | 3 ++- include/pci.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 157491c..9dd245c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -269,7 +269,8 @@ int pci_hose_config_device(struct pci_controller *hose, /* Disable interrupt line, if device says it wants to use interrupts */ pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); if (pin != 0) {
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff);
pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
PCI_INTERRUPT_LINE_DISABLE); } pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);
diff --git a/include/pci.h b/include/pci.h index 94bca97..26cd80b 100644 --- a/include/pci.h +++ b/include/pci.h @@ -228,6 +228,8 @@ #define PCI_MIN_GNT 0x3e /* 8 bits */ #define PCI_MAX_LAT 0x3f /* 8 bits */
+#define PCI_INTERRUPT_LINE_DISABLE 0xff
/* Header type 1 (PCI-to-PCI bridges) */ #define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

At present the PCI output displays 'Mem' when it allocates memory for a PCI device, whether it is prefetchable or not. There is a distinction since the memory comes from separate pools. Use 'Prf' instead of 'Mem' when allocating prefetchable memory.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci_auto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 51d2ac0..41d5447 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -148,8 +148,9 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = mem; #endif
- debug("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", - bar_nr, (unsigned long long)bar_size); + debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", + bar_nr, bar_res == prefetch ? "Prf" : "Mem", + (unsigned long long)bar_size); }
#ifndef CONFIG_PCI_ENUM_ONLY

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present the PCI output displays 'Mem' when it allocates memory for a PCI device, whether it is prefetchable or not. There is a distinction since the memory comes from separate pools. Use 'Prf' instead of 'Mem' when allocating prefetchable memory.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci_auto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 51d2ac0..41d5447 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -148,8 +148,9 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = mem; #endif
debug("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ",
bar_nr, (unsigned long long)bar_size);
debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
bar_nr, bar_res == prefetch ? "Prf" : "Mem",
(unsigned long long)bar_size); }
#ifndef CONFIG_PCI_ENUM_ONLY
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 28 July 2015 at 01:47, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present the PCI output displays 'Mem' when it allocates memory for a PCI device, whether it is prefetchable or not. There is a distinction since the memory comes from separate pools. Use 'Prf' instead of 'Mem' when allocating prefetchable memory.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci_auto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 51d2ac0..41d5447 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -148,8 +148,9 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = mem; #endif
debug("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ",
bar_nr, (unsigned long long)bar_size);
debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
bar_nr, bar_res == prefetch ? "Prf" : "Mem",
(unsigned long long)bar_size); }
#ifndef CONFIG_PCI_ENUM_ONLY
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

At present this function does not specify its return value. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/dm/device.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/dm/device.h b/include/dm/device.h index 9fa0048..dd9cef4 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -318,6 +318,8 @@ const char *dev_get_uclass_name(struct udevice *dev); * @dev: Parent device to check * @index: Child index * @devp: Returns pointer to device + * @return 0 if OK, -ENODEV if no such device, other error if the device fails + * to probe */ int device_get_child(struct udevice *parent, int index, struct udevice **devp);

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present this function does not specify its return value. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But please see comments below.
include/dm/device.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/dm/device.h b/include/dm/device.h index 9fa0048..dd9cef4 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -318,6 +318,8 @@ const char *dev_get_uclass_name(struct udevice *dev);
- @dev: Parent device to check
- @index: Child index
- @devp: Returns pointer to device
- @return 0 if OK, -ENODEV if no such device, other error if the device fails
*/
to probe
int device_get_child(struct udevice *parent, int index, struct udevice **devp);
--
Can we also fix the wrong comment of device_find_next_child()?
/** * device_find_first_child() - Find the first child of a device
This line should be changed to describe device_find_next_child()
* * @devp: Pointer to previous child device on entry. Returns pointer to next * child device, or NULL if none * @return 0 */ int device_find_next_child(struct udevice **devp);
Regards, Bin

On 28 July 2015 at 01:47, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present this function does not specify its return value. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But please see comments below.
include/dm/device.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/dm/device.h b/include/dm/device.h index 9fa0048..dd9cef4 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -318,6 +318,8 @@ const char *dev_get_uclass_name(struct udevice *dev);
- @dev: Parent device to check
- @index: Child index
- @devp: Returns pointer to device
- @return 0 if OK, -ENODEV if no such device, other error if the device fails
*/
to probe
int device_get_child(struct udevice *parent, int index, struct udevice **devp);
--
Can we also fix the wrong comment of device_find_next_child()?
/**
- device_find_first_child() - Find the first child of a device
This line should be changed to describe device_find_next_child()
OK done
- @devp: Pointer to previous child device on entry. Returns pointer to next
child device, or NULL if none
- @return 0
*/ int device_find_next_child(struct udevice **devp);
Regards, Bin
Applied to u-boot-x86.

At present there are no PCI functions which allow access to PCI configuration using a struct udevice. This is a sad situation for driver model as it makes use of PCI harder. Add these functions.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci-uclass.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 17 +++++++++++ 2 files changed, 93 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index c7d93f9..8d3536c 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -210,6 +210,17 @@ int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, return pci_bus_write_config(bus, bdf, offset, value, size); }
+int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, + enum pci_size_t size) +{ + struct udevice *bus; + + for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;) + bus = bus->parent; + return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size); +} + + int pci_write_config32(pci_dev_t bdf, int offset, u32 value) { return pci_write_config(bdf, offset, value, PCI_SIZE_32); @@ -225,6 +236,21 @@ int pci_write_config8(pci_dev_t bdf, int offset, u8 value) return pci_write_config(bdf, offset, value, PCI_SIZE_8); }
+int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) +{ + return dm_pci_write_config(dev, offset, value, PCI_SIZE_8); +} + +int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) +{ + return dm_pci_write_config(dev, offset, value, PCI_SIZE_16); +} + +int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) +{ + return dm_pci_write_config(dev, offset, value, PCI_SIZE_32); +} + int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long *valuep, enum pci_size_t size) { @@ -249,6 +275,17 @@ int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, return pci_bus_read_config(bus, bdf, offset, valuep, size); }
+int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, + enum pci_size_t size) +{ + struct udevice *bus; + + for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;) + bus = bus->parent; + return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep, + size); +} + int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) { unsigned long value; @@ -288,6 +325,45 @@ int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) return 0; }
+int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) +{ + unsigned long value; + int ret; + + ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); + if (ret) + return ret; + *valuep = value; + + return 0; +} + +int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) +{ + unsigned long value; + int ret; + + ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); + if (ret) + return ret; + *valuep = value; + + return 0; +} + +int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) +{ + unsigned long value; + int ret; + + ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); + if (ret) + return ret; + *valuep = value; + + return 0; +} + int pci_auto_config_devices(struct udevice *bus) { struct pci_controller *hose = bus->uclass_priv; diff --git a/include/pci.h b/include/pci.h index 26cd80b..0bb3090 100644 --- a/include/pci.h +++ b/include/pci.h @@ -947,6 +947,23 @@ int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long value, enum pci_size_t size);
+/** + * Driver mode PCI config access functions. Use these in preference to others + * when you have a valid device + */ +int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, + enum pci_size_t size); +int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep); +int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep); +int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep); + +int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, + enum pci_size_t size); + +int dm_pci_write_config8(struct udevice *dev, int offset, u8 value); +int dm_pci_write_config16(struct udevice *dev, int offset, u16 value); +int dm_pci_write_config32(struct udevice *dev, int offset, u32 value); + /* * The following functions provide access to the above without needing the * size parameter. We are trying to encourage the use of the 8/16/32-style

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present there are no PCI functions which allow access to PCI configuration using a struct udevice. This is a sad situation for driver model as it makes use of PCI harder. Add these functions.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci-uclass.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 17 +++++++++++ 2 files changed, 93 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index c7d93f9..8d3536c 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -210,6 +210,17 @@ int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, return pci_bus_write_config(bus, bdf, offset, value, size); }
+int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
enum pci_size_t size)
+{
struct udevice *bus;
for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
bus = bus->parent;
I think we can simplify this by just doing:
int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, enum pci_size_t size) { return pci_write_config(pci_get_bdf(dev), offset, value, size); }
return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size);
+}
int pci_write_config32(pci_dev_t bdf, int offset, u32 value) { return pci_write_config(bdf, offset, value, PCI_SIZE_32); @@ -225,6 +236,21 @@ int pci_write_config8(pci_dev_t bdf, int offset, u8 value) return pci_write_config(bdf, offset, value, PCI_SIZE_8); }
+int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) +{
return dm_pci_write_config(dev, offset, value, PCI_SIZE_8);
+}
+int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) +{
return dm_pci_write_config(dev, offset, value, PCI_SIZE_16);
+}
+int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) +{
return dm_pci_write_config(dev, offset, value, PCI_SIZE_32);
+}
int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long *valuep, enum pci_size_t size) { @@ -249,6 +275,17 @@ int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, return pci_bus_read_config(bus, bdf, offset, valuep, size); }
+int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
enum pci_size_t size)
+{
struct udevice *bus;
for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
bus = bus->parent;
Ditto.
return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep,
size);
+}
int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) { unsigned long value; @@ -288,6 +325,45 @@ int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) return 0; }
+int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) +{
unsigned long value;
int ret;
ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8);
if (ret)
return ret;
*valuep = value;
return 0;
+}
+int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) +{
unsigned long value;
int ret;
ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16);
if (ret)
return ret;
*valuep = value;
return 0;
+}
+int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) +{
unsigned long value;
int ret;
ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32);
if (ret)
return ret;
*valuep = value;
return 0;
+}
int pci_auto_config_devices(struct udevice *bus) { struct pci_controller *hose = bus->uclass_priv; diff --git a/include/pci.h b/include/pci.h index 26cd80b..0bb3090 100644 --- a/include/pci.h +++ b/include/pci.h @@ -947,6 +947,23 @@ int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long value, enum pci_size_t size);
+/**
- Driver mode PCI config access functions. Use these in preference to others
Driver model
- when you have a valid device
- */
+int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
enum pci_size_t size);
+int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep); +int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep); +int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep);
+int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
enum pci_size_t size);
Please either remove blank line here, or add a blank line between dm_pci_read_config() and dm_pci_read_config8() above.
+int dm_pci_write_config8(struct udevice *dev, int offset, u8 value); +int dm_pci_write_config16(struct udevice *dev, int offset, u16 value); +int dm_pci_write_config32(struct udevice *dev, int offset, u32 value);
/*
- The following functions provide access to the above without needing the
- size parameter. We are trying to encourage the use of the 8/16/32-style
--
Regards, Bin

Hi Bin,
On 28 July 2015 at 01:47, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present there are no PCI functions which allow access to PCI configuration using a struct udevice. This is a sad situation for driver model as it makes use of PCI harder. Add these functions.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci-uclass.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 17 +++++++++++ 2 files changed, 93 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index c7d93f9..8d3536c 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -210,6 +210,17 @@ int pci_write_config(pci_dev_t bdf, int offset, unsigned long value, return pci_bus_write_config(bus, bdf, offset, value, size); }
+int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
enum pci_size_t size)
+{
struct udevice *bus;
for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
bus = bus->parent;
I think we can simplify this by just doing:
int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, enum pci_size_t size) { return pci_write_config(pci_get_bdf(dev), offset, value, size); }
Yes but actually I want to remove those old functions. We should support multiple PCI controllers and reference everything from a device, I think.
return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size);
+}
int pci_write_config32(pci_dev_t bdf, int offset, u32 value) { return pci_write_config(bdf, offset, value, PCI_SIZE_32); @@ -225,6 +236,21 @@ int pci_write_config8(pci_dev_t bdf, int offset, u8 value) return pci_write_config(bdf, offset, value, PCI_SIZE_8); }
+int dm_pci_write_config8(struct udevice *dev, int offset, u8 value) +{
return dm_pci_write_config(dev, offset, value, PCI_SIZE_8);
+}
+int dm_pci_write_config16(struct udevice *dev, int offset, u16 value) +{
return dm_pci_write_config(dev, offset, value, PCI_SIZE_16);
+}
+int dm_pci_write_config32(struct udevice *dev, int offset, u32 value) +{
return dm_pci_write_config(dev, offset, value, PCI_SIZE_32);
+}
int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long *valuep, enum pci_size_t size) { @@ -249,6 +275,17 @@ int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, return pci_bus_read_config(bus, bdf, offset, valuep, size); }
+int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
enum pci_size_t size)
+{
struct udevice *bus;
for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
bus = bus->parent;
Ditto.
return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep,
size);
+}
int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) { unsigned long value; @@ -288,6 +325,45 @@ int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) return 0; }
+int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep) +{
unsigned long value;
int ret;
ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8);
if (ret)
return ret;
*valuep = value;
return 0;
+}
+int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep) +{
unsigned long value;
int ret;
ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16);
if (ret)
return ret;
*valuep = value;
return 0;
+}
+int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep) +{
unsigned long value;
int ret;
ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32);
if (ret)
return ret;
*valuep = value;
return 0;
+}
int pci_auto_config_devices(struct udevice *bus) { struct pci_controller *hose = bus->uclass_priv; diff --git a/include/pci.h b/include/pci.h index 26cd80b..0bb3090 100644 --- a/include/pci.h +++ b/include/pci.h @@ -947,6 +947,23 @@ int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset, int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long value, enum pci_size_t size);
+/**
- Driver mode PCI config access functions. Use these in preference to others
Driver model
- when you have a valid device
- */
+int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
enum pci_size_t size);
+int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep); +int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep); +int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep);
+int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
enum pci_size_t size);
Please either remove blank line here, or add a blank line between dm_pci_read_config() and dm_pci_read_config8() above.
+int dm_pci_write_config8(struct udevice *dev, int offset, u8 value); +int dm_pci_write_config16(struct udevice *dev, int offset, u16 value); +int dm_pci_write_config32(struct udevice *dev, int offset, u32 value);
/*
- The following functions provide access to the above without needing the
- size parameter. We are trying to encourage the use of the 8/16/32-style
--
Regards, Bin
Regards, Simon

These functions allow iteration through all PCI devices including bridges. The children of each PCI bus are returned in turn. This can be useful for configuring, checking or enumerating all the devices.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci-uclass.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 25 +++++++++++++++++++++ 2 files changed, 83 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 8d3536c..da724ca 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -779,6 +779,64 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); }
+static int skip_to_next_device(struct udevice *bus, struct udevice **devp) +{ + struct udevice *dev; + int ret = 0; + + do { + do { + device_find_first_child(bus, &dev); + if (dev) { + *devp = dev; + return 0; + } + } while (dev); + ret = uclass_next_device(&bus); + if (ret) + return ret; + } while (bus); + + return 0; +} + +int pci_find_next_device(struct udevice **devp) +{ + struct udevice *child = *devp; + struct udevice *bus = child->parent; + int ret; + + /* First try all the siblings */ + *devp = NULL; + while (child) { + device_find_next_child(&child); + if (child) { + *devp = child; + return 0; + } + } + + /* We ran out of siblings. Try the next bus */ + ret = uclass_next_device(&bus); + if (ret) + return ret; + + return bus ? skip_to_next_device(bus, devp) : 0; +} + +int pci_find_first_device(struct udevice **devp) +{ + struct udevice *bus; + int ret; + + *devp = NULL; + ret = uclass_first_device(UCLASS_PCI, &bus); + if (ret) + return ret; + + return skip_to_next_device(bus, devp); +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/include/pci.h b/include/pci.h index 0bb3090..c842f78 100644 --- a/include/pci.h +++ b/include/pci.h @@ -869,6 +869,31 @@ int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, struct udevice **devp);
/** + * pci_find_first_device() - return the first available PCI device + * + * This function and pci_find_first_device() allow iteration through all + * available PCI devices on all buses. Assuming there are any, this will + * return the first one. + * + * @devp: Set to the first available device, or NULL if no more are left + * or we got an error + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe) + */ +int pci_find_first_device(struct udevice **devp); + +/** + * pci_find_next_device() - return the next available PCI device + * + * Finds the next available PCI device after the one supplied, or sets @devp + * to NULL if there are no more. + * + * @devp: On entry, the last device returned. Set to the next available + * device, or NULL if no more are left or we got an error + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe) + */ +int pci_find_next_device(struct udevice **devp); + +/** * pci_get_ff() - Returns a mask for the given access size * * @size: Access size

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
These functions allow iteration through all PCI devices including bridges. The children of each PCI bus are returned in turn. This can be useful for configuring, checking or enumerating all the devices.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci-uclass.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 25 +++++++++++++++++++++ 2 files changed, 83 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 8d3536c..da724ca 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -779,6 +779,64 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); }
+static int skip_to_next_device(struct udevice *bus, struct udevice **devp) +{
struct udevice *dev;
int ret = 0;
do {
do {
device_find_first_child(bus, &dev);
if (dev) {
*devp = dev;
return 0;
}
} while (dev);
There is no need to do a 'do..while' here.
ret = uclass_next_device(&bus);
I don't understand. If there is no child device of the root pci bus, why do we bother doing this uclass_next_device()? No child device of the root pci bus means there will not be another bus device which is attached to the root pci bus.
if (ret)
return ret;
} while (bus);
return 0;
+}
+int pci_find_next_device(struct udevice **devp) +{
struct udevice *child = *devp;
struct udevice *bus = child->parent;
int ret;
/* First try all the siblings */
*devp = NULL;
while (child) {
device_find_next_child(&child);
if (child) {
*devp = child;
return 0;
}
}
/* We ran out of siblings. Try the next bus */
ret = uclass_next_device(&bus);
if (ret)
return ret;
return bus ? skip_to_next_device(bus, devp) : 0;
+}
+int pci_find_first_device(struct udevice **devp) +{
struct udevice *bus;
int ret;
*devp = NULL;
ret = uclass_first_device(UCLASS_PCI, &bus);
if (ret)
return ret;
return skip_to_next_device(bus, devp);
+}
UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/include/pci.h b/include/pci.h index 0bb3090..c842f78 100644 --- a/include/pci.h +++ b/include/pci.h @@ -869,6 +869,31 @@ int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, struct udevice **devp);
/**
- pci_find_first_device() - return the first available PCI device
- This function and pci_find_first_device() allow iteration through all
- available PCI devices on all buses. Assuming there are any, this will
- return the first one.
- @devp: Set to the first available device, or NULL if no more are left
or we got an error
- @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe)
- */
+int pci_find_first_device(struct udevice **devp);
+/**
- pci_find_next_device() - return the next available PCI device
- Finds the next available PCI device after the one supplied, or sets @devp
- to NULL if there are no more.
- @devp: On entry, the last device returned. Set to the next available
device, or NULL if no more are left or we got an error
- @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe)
- */
+int pci_find_next_device(struct udevice **devp);
+/**
- pci_get_ff() - Returns a mask for the given access size
- @size: Access size
--
Regards, Bin

Hi Bin,
On 28 July 2015 at 01:48, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
These functions allow iteration through all PCI devices including bridges. The children of each PCI bus are returned in turn. This can be useful for configuring, checking or enumerating all the devices.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci-uclass.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 25 +++++++++++++++++++++ 2 files changed, 83 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 8d3536c..da724ca 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -779,6 +779,64 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); }
+static int skip_to_next_device(struct udevice *bus, struct udevice **devp) +{
struct udevice *dev;
int ret = 0;
do {
do {
device_find_first_child(bus, &dev);
if (dev) {
*devp = dev;
return 0;
}
} while (dev);
There is no need to do a 'do..while' here.
ret = uclass_next_device(&bus);
I don't understand. If there is no child device of the root pci bus, why do we bother doing this uclass_next_device()? No child device of the root pci bus means there will not be another bus device which is attached to the root pci bus.
That's true on x86, but other hardware may have multiple PCI controllers. I will add a comment.
[snip]
Regards, Simon

Drop these from the header file and use Kconfig instead.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/chromebook_link_defconfig | 3 +++ configs/chromebox_panther_defconfig | 3 +++ include/configs/x86-chromebook.h | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index e394dab..b987f3f 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index 340510f..e82c8ec 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index 408cbb1..e8f0bac 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -45,9 +45,6 @@ #define VIDEO_IO_OFFSET 0 #define CONFIG_X86EMU_RAW_IO
-#define CONFIG_CROS_EC -#define CONFIG_CROS_EC_LPC -#define CONFIG_CMD_CROS_EC #define CONFIG_ARCH_EARLY_INIT_R
#undef CONFIG_ENV_IS_NOWHERE

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Drop these from the header file and use Kconfig instead.
Signed-off-by: Simon Glass sjg@chromium.org
configs/chromebook_link_defconfig | 3 +++ configs/chromebox_panther_defconfig | 3 +++ include/configs/x86-chromebook.h | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index e394dab..b987f3f 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index 340510f..e82c8ec 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index 408cbb1..e8f0bac 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -45,9 +45,6 @@ #define VIDEO_IO_OFFSET 0 #define CONFIG_X86EMU_RAW_IO
-#define CONFIG_CROS_EC -#define CONFIG_CROS_EC_LPC -#define CONFIG_CMD_CROS_EC #define CONFIG_ARCH_EARLY_INIT_R
#undef CONFIG_ENV_IS_NOWHERE
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 28 July 2015 at 01:48, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Drop these from the header file and use Kconfig instead.
Signed-off-by: Simon Glass sjg@chromium.org
configs/chromebook_link_defconfig | 3 +++ configs/chromebox_panther_defconfig | 3 +++ include/configs/x86-chromebook.h | 3 --- 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index e394dab..b987f3f 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index 340510f..e82c8ec 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -14,6 +14,9 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index 408cbb1..e8f0bac 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -45,9 +45,6 @@ #define VIDEO_IO_OFFSET 0 #define CONFIG_X86EMU_RAW_IO
-#define CONFIG_CROS_EC -#define CONFIG_CROS_EC_LPC -#define CONFIG_CMD_CROS_EC #define CONFIG_ARCH_EARLY_INIT_R
#undef CONFIG_ENV_IS_NOWHERE
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

Move this config option to Kconfig and tidy up.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/efi-x86_defconfig | 1 + drivers/serial/Kconfig | 10 ++++++++++ include/configs/crownbay.h | 1 - include/configs/galileo.h | 2 -- include/configs/minnowmax.h | 1 - include/configs/qemu-x86.h | 2 -- include/configs/x86-chromebook.h | 2 -- 7 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index f07305c..199f320 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -14,3 +14,4 @@ CONFIG_DEBUG_UART_BASE=0 CONFIG_DEBUG_UART_CLOCK=0 # CONFIG_CMD_NET is not set # CONFIG_CMD_BOOTM is not set +# CONFIG_X86_SERIAL is not set diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f874837..773075b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -110,3 +110,13 @@ config UNIPHIER_SERIAL help If you have a UniPhier based board and want to use the on-chip serial ports, say Y to this option. If unsure, say N. + +config X86_SERIAL + bool "Support for 16550 serial port on x86 machines" + depends on X86 + default y + help + Most x86 machines have a ns16550 UART or compatible. This can be + enabled in the device tree with the correct input clock frequency + provided (default 1843200). Enable this to obtain serial console + output. diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h index 6cf53a3..1ea320b 100644 --- a/include/configs/crownbay.h +++ b/include/configs/crownbay.h @@ -17,7 +17,6 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_X86_SERIAL #define CONFIG_SMSC_LPC47M
#define CONFIG_PCI_MEM_BUS 0x40000000 diff --git a/include/configs/galileo.h b/include/configs/galileo.h index fd89bf3..3c3c6e9 100644 --- a/include/configs/galileo.h +++ b/include/configs/galileo.h @@ -17,8 +17,6 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_X86_SERIAL - /* ns16550 UART is memory-mapped in Quark SoC */ #undef CONFIG_SYS_NS16550_PORT_MAPPED
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 4781e79..6dad2b1 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -17,7 +17,6 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_EARLY_INIT_R
-#define CONFIG_X86_SERIAL #define CONFIG_SMSC_LPC47M
#define CONFIG_PCI_MEM_BUS 0xd0000000 diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index 78c296f..c25e331 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -16,8 +16,6 @@ #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_X86_SERIAL - #define CONFIG_PCI_MEM_BUS 0xc0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS #define CONFIG_PCI_MEM_SIZE 0x10000000 diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index e8f0bac..d5dd619 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -17,8 +17,6 @@ #define CONFIG_X86_MRC_ADDR 0xfffa0000 #define CONFIG_CACHE_MRC_SIZE_KB 512
-#define CONFIG_X86_SERIAL - #define CONFIG_SCSI_DEV_LIST \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_NM10_AHCI}, \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Move this config option to Kconfig and tidy up.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But please see nits below.
configs/efi-x86_defconfig | 1 +
This has dependencies to the efi series. I think we should remove this change if we apply this series first.
drivers/serial/Kconfig | 10 ++++++++++ include/configs/crownbay.h | 1 - include/configs/galileo.h | 2 -- include/configs/minnowmax.h | 1 - include/configs/qemu-x86.h | 2 -- include/configs/x86-chromebook.h | 2 -- 7 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index f07305c..199f320 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -14,3 +14,4 @@ CONFIG_DEBUG_UART_BASE=0 CONFIG_DEBUG_UART_CLOCK=0 # CONFIG_CMD_NET is not set # CONFIG_CMD_BOOTM is not set +# CONFIG_X86_SERIAL is not set diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f874837..773075b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -110,3 +110,13 @@ config UNIPHIER_SERIAL help If you have a UniPhier based board and want to use the on-chip serial ports, say Y to this option. If unsure, say N.
+config X86_SERIAL
bool "Support for 16550 serial port on x86 machines"
depends on X86
default y
help
Most x86 machines have a ns16550 UART or compatible. This can be
enabled in the device tree with the correct input clock frequency
provided (default 1843200). Enable this to obtain serial console
output.
diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h index 6cf53a3..1ea320b 100644 --- a/include/configs/crownbay.h +++ b/include/configs/crownbay.h @@ -17,7 +17,6 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_X86_SERIAL #define CONFIG_SMSC_LPC47M
#define CONFIG_PCI_MEM_BUS 0x40000000 diff --git a/include/configs/galileo.h b/include/configs/galileo.h index fd89bf3..3c3c6e9 100644 --- a/include/configs/galileo.h +++ b/include/configs/galileo.h @@ -17,8 +17,6 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_X86_SERIAL
/* ns16550 UART is memory-mapped in Quark SoC */ #undef CONFIG_SYS_NS16550_PORT_MAPPED
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 4781e79..6dad2b1 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -17,7 +17,6 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_EARLY_INIT_R
-#define CONFIG_X86_SERIAL #define CONFIG_SMSC_LPC47M
#define CONFIG_PCI_MEM_BUS 0xd0000000 diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index 78c296f..c25e331 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -16,8 +16,6 @@ #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_X86_SERIAL
#define CONFIG_PCI_MEM_BUS 0xc0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS #define CONFIG_PCI_MEM_SIZE 0x10000000 diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index e8f0bac..d5dd619 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -17,8 +17,6 @@ #define CONFIG_X86_MRC_ADDR 0xfffa0000 #define CONFIG_CACHE_MRC_SIZE_KB 512
-#define CONFIG_X86_SERIAL
#define CONFIG_SCSI_DEV_LIST \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_NM10_AHCI}, \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \ --
Regards, Bin

On 28 July 2015 at 01:48, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Move this config option to Kconfig and tidy up.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But please see nits below.
Nits fixed and
Applied to u-boot-x86.
configs/efi-x86_defconfig | 1 +
This has dependencies to the efi series. I think we should remove this change if we apply this series first.
drivers/serial/Kconfig | 10 ++++++++++ include/configs/crownbay.h | 1 - include/configs/galileo.h | 2 -- include/configs/minnowmax.h | 1 - include/configs/qemu-x86.h | 2 -- include/configs/x86-chromebook.h | 2 -- 7 files changed, 11 insertions(+), 8 deletions(-)
[snip]

Use savedefconfig to get this file into the correct order.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/efi-x86_defconfig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index 199f320..d4530dd 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -1,17 +1,16 @@ CONFIG_X86=y CONFIG_VENDOR_EFI=y +CONFIG_DEFAULT_DEVICE_TREE="efi" CONFIG_TARGET_EFI=y CONFIG_TSC_CALIBRATION_BYPASS=y +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_NET is not set CONFIG_OF_CONTROL=y CONFIG_OF_EMBED=y CONFIG_DM_PCI=y -CONFIG_DEFAULT_DEVICE_TREE="efi" -CONFIG_EFI=y -CONFIG_ARCH_EFI=y CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_EFI=y CONFIG_DEBUG_UART_BASE=0 CONFIG_DEBUG_UART_CLOCK=0 -# CONFIG_CMD_NET is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_X86_SERIAL is not set +CONFIG_EFI=y

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Use savedefconfig to get this file into the correct order.
Signed-off-by: Simon Glass sjg@chromium.org
Since efi series is not applied, can you move this to your efi v2 series?
configs/efi-x86_defconfig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index 199f320..d4530dd 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -1,17 +1,16 @@ CONFIG_X86=y CONFIG_VENDOR_EFI=y +CONFIG_DEFAULT_DEVICE_TREE="efi" CONFIG_TARGET_EFI=y CONFIG_TSC_CALIBRATION_BYPASS=y +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_NET is not set CONFIG_OF_CONTROL=y CONFIG_OF_EMBED=y CONFIG_DM_PCI=y -CONFIG_DEFAULT_DEVICE_TREE="efi" -CONFIG_EFI=y -CONFIG_ARCH_EFI=y CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_EFI=y CONFIG_DEBUG_UART_BASE=0 CONFIG_DEBUG_UART_CLOCK=0 -# CONFIG_CMD_NET is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_X86_SERIAL is not set
+CONFIG_EFI=y
Regards, Bin

Hi Bin,
On 28 July 2015 at 01:48, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Use savedefconfig to get this file into the correct order.
Signed-off-by: Simon Glass sjg@chromium.org
Since efi series is not applied, can you move this to your efi v2 series?
Er yes, that would have been smarter. I forgot to come back to this.
configs/efi-x86_defconfig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index 199f320..d4530dd 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -1,17 +1,16 @@ CONFIG_X86=y CONFIG_VENDOR_EFI=y +CONFIG_DEFAULT_DEVICE_TREE="efi" CONFIG_TARGET_EFI=y CONFIG_TSC_CALIBRATION_BYPASS=y +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_NET is not set CONFIG_OF_CONTROL=y CONFIG_OF_EMBED=y CONFIG_DM_PCI=y -CONFIG_DEFAULT_DEVICE_TREE="efi" -CONFIG_EFI=y -CONFIG_ARCH_EFI=y CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_EFI=y CONFIG_DEBUG_UART_BASE=0 CONFIG_DEBUG_UART_CLOCK=0 -# CONFIG_CMD_NET is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_X86_SERIAL is not set
+CONFIG_EFI=y
Regards, Bin
Regards, Simon

This is provided in Kconfig so we don't need it here.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/configs/x86-chromebook.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index d5dd619..2be8850 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -10,7 +10,6 @@
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
-#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_MISC_INIT_R

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
This is provided in Kconfig so we don't need it here.
Signed-off-by: Simon Glass sjg@chromium.org
include/configs/x86-chromebook.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index d5dd619..2be8850 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -10,7 +10,6 @@
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
-#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_MISC_INIT_R
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 28 July 2015 at 01:48, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
This is provided in Kconfig so we don't need it here.
Signed-off-by: Simon Glass sjg@chromium.org
include/configs/x86-chromebook.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index d5dd619..2be8850 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -10,7 +10,6 @@
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
-#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_MISC_INIT_R
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

Fix a small typo in this binding file.
Signed-off-by: Simon Glass sjg@chromium.org ---
doc/device-tree-bindings/misc/intel,irq-router.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/device-tree-bindings/misc/intel,irq-router.txt b/doc/device-tree-bindings/misc/intel,irq-router.txt index 598b4b1..e4d8ead 100644 --- a/doc/device-tree-bindings/misc/intel,irq-router.txt +++ b/doc/device-tree-bindings/misc/intel,irq-router.txt @@ -17,8 +17,8 @@ Required properties : - intel,pirq-link : Specifies the PIRQ link information with two cells. The first cell is the register offset that controls the first PIRQ link routing. The second cell is the total number of PIRQ links the router supports. -- intel,pirq-mask : Specifies the IRQ mask reprenting the 16 IRQs in 8259 PIC. - Bit N is 1 means IRQ N is available to be routed. +- intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the + 8259 PIC. Bit N is 1 means IRQ N is available to be routed. - intel,pirq-routing : Specifies all PCI devices' IRQ routing information, encoded as 3 cells a group for a device. The first cell is the device's PCI bus number, device number and function number encoding with PCI_BDF() macro.

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Fix a small typo in this binding file.
Signed-off-by: Simon Glass sjg@chromium.org
doc/device-tree-bindings/misc/intel,irq-router.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/device-tree-bindings/misc/intel,irq-router.txt b/doc/device-tree-bindings/misc/intel,irq-router.txt index 598b4b1..e4d8ead 100644 --- a/doc/device-tree-bindings/misc/intel,irq-router.txt +++ b/doc/device-tree-bindings/misc/intel,irq-router.txt @@ -17,8 +17,8 @@ Required properties :
- intel,pirq-link : Specifies the PIRQ link information with two cells. The first cell is the register offset that controls the first PIRQ link routing. The second cell is the total number of PIRQ links the router supports.
-- intel,pirq-mask : Specifies the IRQ mask reprenting the 16 IRQs in 8259 PIC.
- Bit N is 1 means IRQ N is available to be routed.
+- intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the
- 8259 PIC. Bit N is 1 means IRQ N is available to be routed.
- intel,pirq-routing : Specifies all PCI devices' IRQ routing information, encoded as 3 cells a group for a device. The first cell is the device's PCI bus number, device number and function number encoding with PCI_BDF() macro.
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 28 July 2015 at 01:48, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
Fix a small typo in this binding file.
Signed-off-by: Simon Glass sjg@chromium.org
doc/device-tree-bindings/misc/intel,irq-router.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/device-tree-bindings/misc/intel,irq-router.txt b/doc/device-tree-bindings/misc/intel,irq-router.txt index 598b4b1..e4d8ead 100644 --- a/doc/device-tree-bindings/misc/intel,irq-router.txt +++ b/doc/device-tree-bindings/misc/intel,irq-router.txt @@ -17,8 +17,8 @@ Required properties :
- intel,pirq-link : Specifies the PIRQ link information with two cells. The first cell is the register offset that controls the first PIRQ link routing. The second cell is the total number of PIRQ links the router supports.
-- intel,pirq-mask : Specifies the IRQ mask reprenting the 16 IRQs in 8259 PIC.
- Bit N is 1 means IRQ N is available to be routed.
+- intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the
- 8259 PIC. Bit N is 1 means IRQ N is available to be routed.
- intel,pirq-routing : Specifies all PCI devices' IRQ routing information, encoded as 3 cells a group for a device. The first cell is the device's PCI bus number, device number and function number encoding with PCI_BDF() macro.
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

This code could use a little tightening up. There is some repetition and an odd use of fdtdec_get_int_array().
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/irq.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 97dd000..9d1128a 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -125,10 +125,10 @@ static int create_pirq_routing_table(void) return -EINVAL; }
- ret = fdtdec_get_int_array(blob, node, "intel,pirq-link", - &irq_router.link_base, 1); - if (ret) + ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); + if (ret == -1) return ret; + irq_router.link_base = ret;
irq_router.irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); @@ -156,18 +156,13 @@ static int create_pirq_routing_table(void) }
cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); - if (!cell) - return -EINVAL; - - if ((len % sizeof(struct pirq_routing)) == 0) - count = len / sizeof(struct pirq_routing); - else + if (!cell || len % sizeof(struct pirq_routing)) return -EINVAL; + count = len / sizeof(struct pirq_routing);
- rt = malloc(sizeof(struct irq_routing_table)); + rt = calloc(1, sizeof(struct irq_routing_table)); if (!rt) return -ENOMEM; - memset((char *)rt, 0, sizeof(struct irq_routing_table));
/* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE; @@ -181,7 +176,8 @@ static int create_pirq_routing_table(void) slot_base = rt->slots;
/* Now fill in the irq_info entries in the PIRQ table */ - for (i = 0; i < count; i++) { + for (i = 0; i < count; + i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { struct pirq_routing pr;
pr.bdf = fdt_addr_to_cpu(cell[0]); @@ -212,25 +208,15 @@ static int create_pirq_routing_table(void) if (slot->irq[pr.pin - 1].link != LINK_N2V(pr.pirq, irq_router.link_base)) debug("WARNING: Inconsistent PIRQ routing information\n"); - - cell += sizeof(struct pirq_routing) / - sizeof(u32); - continue; - } else { - debug("writing INT%c\n", 'A' + pr.pin - 1); - fill_irq_info(slot, PCI_BUS(pr.bdf), - PCI_DEV(pr.bdf), pr.pin, pr.pirq); - cell += sizeof(struct pirq_routing) / - sizeof(u32); continue; } + } else { + slot = slot_base + irq_entries; } - - slot = slot_base + irq_entries; - fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), - pr.pin, pr.pirq); + debug("writing INT%c\n", 'A' + pr.pin - 1); + fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin, + pr.pirq); irq_entries++; - cell += sizeof(struct pirq_routing) / sizeof(u32); }
rt->size = irq_entries * sizeof(struct irq_info) + 32;

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
This code could use a little tightening up. There is some repetition and an odd use of fdtdec_get_int_array().
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/irq.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 97dd000..9d1128a 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -125,10 +125,10 @@ static int create_pirq_routing_table(void) return -EINVAL; }
ret = fdtdec_get_int_array(blob, node, "intel,pirq-link",
&irq_router.link_base, 1);
if (ret)
ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1);
if (ret == -1) return ret;
irq_router.link_base = ret; irq_router.irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP);
@@ -156,18 +156,13 @@ static int create_pirq_routing_table(void) }
cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
if (!cell)
return -EINVAL;
if ((len % sizeof(struct pirq_routing)) == 0)
count = len / sizeof(struct pirq_routing);
else
if (!cell || len % sizeof(struct pirq_routing)) return -EINVAL;
count = len / sizeof(struct pirq_routing);
rt = malloc(sizeof(struct irq_routing_table));
rt = calloc(1, sizeof(struct irq_routing_table)); if (!rt) return -ENOMEM;
memset((char *)rt, 0, sizeof(struct irq_routing_table)); /* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE;
@@ -181,7 +176,8 @@ static int create_pirq_routing_table(void) slot_base = rt->slots;
/* Now fill in the irq_info entries in the PIRQ table */
for (i = 0; i < count; i++) {
for (i = 0; i < count;
i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { struct pirq_routing pr; pr.bdf = fdt_addr_to_cpu(cell[0]);
@@ -212,25 +208,15 @@ static int create_pirq_routing_table(void) if (slot->irq[pr.pin - 1].link != LINK_N2V(pr.pirq, irq_router.link_base)) debug("WARNING: Inconsistent PIRQ routing information\n");
cell += sizeof(struct pirq_routing) /
sizeof(u32);
continue;
} else {
debug("writing INT%c\n", 'A' + pr.pin - 1);
fill_irq_info(slot, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), pr.pin, pr.pirq);
cell += sizeof(struct pirq_routing) /
sizeof(u32); continue;
This else case should not be removed. In this case, irq_entries should not be increased.
}
} else {
slot = slot_base + irq_entries; }
slot = slot_base + irq_entries;
fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
pr.pin, pr.pirq);
debug("writing INT%c\n", 'A' + pr.pin - 1);
fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin,
pr.pirq); irq_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32); } rt->size = irq_entries * sizeof(struct irq_info) + 32;
--
Regards, Bin

This code may be useful for boards that use driver model for PCI.
Note: It would be better to have driver model automatically call this function somehow. However for now it is probably safer to have it under board control.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/fsp/fsp_support.h | 7 +++++++ arch/x86/lib/fsp/fsp_common.c | 11 ++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index c6c7dc0..7317dda 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -207,4 +207,11 @@ void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len); */ void update_fsp_upd(struct upd_region *fsp_upd);
+/** + * fsp_init_phase_pci() - Tell the FSP that we have completed PCI init + * + * @return 0 if OK, -EPERM if the FSP gave an error. + */ +int fsp_init_phase_pci(void); + #endif diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index c585710..6f72c6d 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -19,19 +19,24 @@ int print_cpuinfo(void) return default_print_cpuinfo(); }
-int board_pci_post_scan(struct pci_controller *hose) +int fsp_init_phase_pci(void) { u32 status;
/* call into FspNotify */ debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); status = fsp_notify(NULL, INIT_PHASE_PCI); - if (status != FSP_SUCCESS) + if (status) debug("fail, error code %x\n", status); else debug("OK\n");
- return 0; + return status ? -EPERM : 0; +} + +int board_pci_post_scan(struct pci_controller *hose) +{ + return fsp_init_phase_pci(); }
void board_final_cleanup(void)

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
This code may be useful for boards that use driver model for PCI.
Note: It would be better to have driver model automatically call this function somehow. However for now it is probably safer to have it under board control.
See http://lists.denx.de/pipermail/u-boot/2015-July/220544.html Unfortunately with the driver model pci conversion, board_pci_post_scan() is not called anywhere.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/include/asm/fsp/fsp_support.h | 7 +++++++ arch/x86/lib/fsp/fsp_common.c | 11 ++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index c6c7dc0..7317dda 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -207,4 +207,11 @@ void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len); */ void update_fsp_upd(struct upd_region *fsp_upd);
+/**
- fsp_init_phase_pci() - Tell the FSP that we have completed PCI init
- @return 0 if OK, -EPERM if the FSP gave an error.
- */
+int fsp_init_phase_pci(void);
#endif diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index c585710..6f72c6d 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -19,19 +19,24 @@ int print_cpuinfo(void) return default_print_cpuinfo(); }
-int board_pci_post_scan(struct pci_controller *hose) +int fsp_init_phase_pci(void) { u32 status;
/* call into FspNotify */ debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); status = fsp_notify(NULL, INIT_PHASE_PCI);
if (status != FSP_SUCCESS)
if (status) debug("fail, error code %x\n", status); else debug("OK\n");
return 0;
return status ? -EPERM : 0;
+}
+int board_pci_post_scan(struct pci_controller *hose) +{
return fsp_init_phase_pci();
}
void board_final_cleanup(void)
Regards, Bin

These are now in the device tree so we don't need to use the CONFIG options. Drop them.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/configs/minnowmax.h | 12 ------------ 1 file changed, 12 deletions(-)
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 6dad2b1..cdbb65d 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -19,18 +19,6 @@
#define CONFIG_SMSC_LPC47M
-#define CONFIG_PCI_MEM_BUS 0xd0000000 -#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS -#define CONFIG_PCI_MEM_SIZE 0x10000000 - -#define CONFIG_PCI_PREF_BUS 0xc0000000 -#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS -#define CONFIG_PCI_PREF_SIZE 0x10000000 - -#define CONFIG_PCI_IO_BUS 0x2000 -#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS -#define CONFIG_PCI_IO_SIZE 0xe000 - #define CONFIG_PCI_CONFIG_HOST_BRIDGE #define CONFIG_SYS_EARLY_PCI_INIT #define CONFIG_PCI_PNP

On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
These are now in the device tree so we don't need to use the CONFIG options. Drop them.
Signed-off-by: Simon Glass sjg@chromium.org
include/configs/minnowmax.h | 12 ------------ 1 file changed, 12 deletions(-)
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 6dad2b1..cdbb65d 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -19,18 +19,6 @@
#define CONFIG_SMSC_LPC47M
-#define CONFIG_PCI_MEM_BUS 0xd0000000 -#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS -#define CONFIG_PCI_MEM_SIZE 0x10000000
-#define CONFIG_PCI_PREF_BUS 0xc0000000 -#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS -#define CONFIG_PCI_PREF_SIZE 0x10000000
-#define CONFIG_PCI_IO_BUS 0x2000 -#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS -#define CONFIG_PCI_IO_SIZE 0xe000
#define CONFIG_PCI_CONFIG_HOST_BRIDGE #define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 28 July 2015 at 01:49, Bin Meng bmeng.cn@gmail.com wrote:
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
These are now in the device tree so we don't need to use the CONFIG options. Drop them.
Signed-off-by: Simon Glass sjg@chromium.org
include/configs/minnowmax.h | 12 ------------ 1 file changed, 12 deletions(-)
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 6dad2b1..cdbb65d 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -19,18 +19,6 @@
#define CONFIG_SMSC_LPC47M
-#define CONFIG_PCI_MEM_BUS 0xd0000000 -#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS -#define CONFIG_PCI_MEM_SIZE 0x10000000
-#define CONFIG_PCI_PREF_BUS 0xc0000000 -#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS -#define CONFIG_PCI_PREF_SIZE 0x10000000
-#define CONFIG_PCI_IO_BUS 0x2000 -#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS -#define CONFIG_PCI_IO_SIZE 0xe000
#define CONFIG_PCI_CONFIG_HOST_BRIDGE #define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_PCI_PNP
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully help figure this out.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/baytrail/valleyview.c | 492 +++++++++++++++++++++++++++++++++++++ arch/x86/dts/minnowmax.dts | 28 +++ include/configs/minnowmax.h | 1 + 3 files changed, 521 insertions(+)
diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c index f1c3578..efbb4a5 100644 --- a/arch/x86/cpu/baytrail/valleyview.c +++ b/arch/x86/cpu/baytrail/valleyview.c @@ -5,9 +5,14 @@ */
#include <common.h> +#include <dm.h> #include <mmc.h> #include <pci_ids.h> +#include <asm/interrupt.h> +#include <asm/irq.h> +#include <asm/ioapic.h> #include <asm/post.h> +#include <asm/fsp/fsp_support.h>
static struct pci_device_id mmc_supported[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO }, @@ -37,3 +42,490 @@ int arch_cpu_init(void) return 0; } #endif + +/* + * TODO(sjg): This code comes from coreboot's fsp_baytrail/southcluster.c. It + * has been cleaned up a little but still has macro stuff like + * PCI_DEV_PIRQ_ROUTE and doesn't use device tree. It needs to be adjusted to + * fit with the existing pirq-routing code. However it isn't clear that that + * code has all the required features. + * + * PIC IRQ settings + */ +#define PIRQ_PIC_IRQ3 0x3 +#define PIRQ_PIC_IRQ4 0x4 +#define PIRQ_PIC_IRQ5 0x5 +#define PIRQ_PIC_IRQ6 0x6 +#define PIRQ_PIC_IRQ7 0x7 +#define PIRQ_PIC_IRQ9 0x9 +#define PIRQ_PIC_IRQ10 0xa +#define PIRQ_PIC_IRQ11 0xb +#define PIRQ_PIC_IRQ12 0xc +#define PIRQ_PIC_IRQ14 0xe +#define PIRQ_PIC_IRQ15 0xf +#define PIRQ_PIC_IRQDISABLE 0x80 + +#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \ + [dev_] = ((PIRQ ## d_) << 12) | ((PIRQ ## c_) << 8) | \ + ((PIRQ ## b_) << 4) | ((PIRQ ## a_) << 0) + +#define PIRQ_PIC(pirq_, pic_irq_) \ + [PIRQ ## pirq_] = PIRQ_PIC_IRQ ## pic_irq_ + +#define NUM_OF_PCI_DEVS 32 +#define NUM_PIRQS 8 + +struct baytrail_irq_route { + /* Per-device configuration */ + uint16_t pcidev[NUM_OF_PCI_DEVS]; + /* Route path for each internal PIRQx in PIC mode */ + uint8_t pic[NUM_PIRQS]; +}; + +static struct baytrail_irq_route irq_info = { + { + PCI_DEV_PIRQ_ROUTE(0x02, A, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x10, D, E, F, G), + PCI_DEV_PIRQ_ROUTE(0x11, B, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x12, C, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x13, D, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x14, E, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x15, F, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x17, F, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x18, B, A, D, C), + PCI_DEV_PIRQ_ROUTE(0x1a, F, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x1b, G, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x1c, E, F, G, H), + PCI_DEV_PIRQ_ROUTE(0x1d, D, A, A, A), + PCI_DEV_PIRQ_ROUTE(0x1e, B, D, E, F), + PCI_DEV_PIRQ_ROUTE(0x1f, H, G, B, C), + }, { + /* + * Route each PIRQ[A-H] to a PIC IRQ[0-15] + * Reserved: 0, 1, 2, 8, 13 + * PS2 keyboard: 12 + * ACPI/SCI: 9 + * Floppy: 6 + */ + PIRQ_PIC(A, 4), + PIRQ_PIC(B, 5), + PIRQ_PIC(C, 7), + PIRQ_PIC(D, 10), + PIRQ_PIC(E, 11), + PIRQ_PIC(F, 12), + PIRQ_PIC(G, 14), + PIRQ_PIC(H, 15), + } +}; + +struct ibase_regs { + u32 actl; + u32 mc; + u8 pirq[8]; + u32 scnt; /* 0x10 */ + u32 kmc; + u32 fs; + u32 bc; + u16 ir[32]; /* 0x20 */ + u32 oic; /* 0x60 */ +}; + +enum { + /* ACTL */ + SCIS_MASK = 0x07, + SCIS_IRQ9 = 0, + SCIS_IRQ10, + SCIS_IRQ11, + SCIS_IRQ20, + SCIS_IRQ21, + SCIS_IRQ22, + SCIS_IRQ23, + + /* OIC */ + AEN = 1 << 8, + + /* SCNT */ + SCNT_CONTINUOUS_MODE = 1 << 7, + SCNT_QUIET_MODE = 0, + SIRQEN = 1 << 12, + + IBASE = 0x50, +}; + +static int valleyview_enable_ioapic(struct udevice *dev, + struct ibase_regs *ibase) +{ + u32 reg32; + int i; + + /* Enable ACPI I/O and power management. Set SCI IRQ to IRQ9 */ + writel(AEN, &ibase->oic); + reg32 = readl(&ibase->oic); /* Read back per BWG */ + writel(SCIS_IRQ9, &ibase->actl); + + io_apic_write(0, 1 << 25); + + /* affirm full set of redirection table entries ("write once") */ + reg32 = io_apic_read(1); + io_apic_write(1, reg32); + + reg32 = io_apic_read(0); + debug("Southbridge APIC ID = %x\n", (reg32 >> 24) & 0x0f); + if (reg32 != (1 << 25)) { + debug("APIC Error\n"); + return -EINVAL; + } + + debug("Dumping IOAPIC registers\n"); + for (i = 0; i < 3; i++) + debug(" reg 0x%04x: 0x%08x\n", i, io_apic_read(i)); + + /* + * 3 = Select Boot Configuration register + * 1 = Use Processor System Bus to deliver interrupts + */ + io_apic_write(3, 1); + + return 0; +} + +static void valleyview_enable_serial_irqs(struct udevice *dev, + struct ibase_regs *ibase) +{ +#ifdef SETUPSERIQ /* NOT defined. Remove when the TODO is done */ + /* + * TODO: SERIRQ seems to have a number of problems on baytrail. + * With it enabled, we get some spurious interrupts (ps2) + * in seabios. It also caused IOCHK# NMIs. Remove it + * until we understand how it needs to be configured. + */ + u8 reg; + + /* Disable the IOCHK# NMI. Let the NMI handler enable it if needed */ + reg = inb(0x61); + reg &= 0x0f; /* Higher Nibble must be 0 */ + reg |= 1 << 3; /* IOCHK# NMI Disable for now */ + outb(reg, 0x61); + + setbits_le32(&ibase->oic, SIRQEN); + writeb(SCNT_CONTINUOUS_MODE, &ibase->scnt); + +#if !IS_ENABLED(CONFIG_SERIRQ_CONTINUOUS_MODE) + /* + * SoC requires that the System BIOS first set the SERIRQ logic to + * continuous mode operation for at least one frame before switching + * it into quiet mode operation. + */ + outb(0x00, 0xed); /* I/O Delay to get the 1 frame */ + writeb(SCNT_QUIET_MODE, &ibase->scnt); +#endif +#endif /* DON'T SET UP IRQS */ +} + +/** + * Take an INT_PIN number (0, 1 - 4) and convert + * it to a string ("NO PIN", "PIN A" - "PIN D") + * + * @param pin PCI Interrupt Pin number (0, 1 - 4) + * @return A string corresponding to the pin number or "Invalid" + */ +static const char *pin_to_str(int pin) +{ + const char *str[5] = { + "NO PIN", + "PIN A", + "PIN B", + "PIN C", + "PIN D", + }; + + if (pin >= 0 && pin <= 4) + return str[pin]; + else + return "Invalid PIN, not 0 - 4"; +} + +/** + * Get the PCI INT_PIN swizzle for a device defined as: + * pin_parent = (pin_child + devn_child) % 4 + 1 + * where PIN A = 1 ... PIN_D = 4 + * + * Given a PCI device structure 'dev', find the interrupt pin + * that will be triggered on its parent bridge device when + * generating an interrupt. For example: Device 1:3.2 may + * use INT_PIN A but will trigger PIN D on its parent bridge + * device. In this case, this function will return 4 (PIN D). + * + * @param dev A PCI device structure to swizzle interrupt pins for + * @param *parent_bridge The PCI device structure for the bridge + * device 'dev' is attached to + * @return The interrupt pin number (1 - 4) that 'dev' will + * trigger when generating an interrupt + */ +static int swizzle_irq_pins(struct udevice *dev, + struct udevice **parent_bridgep) +{ + struct udevice *parent; /* Our current device's parent device */ + struct udevice *child; /* The child device of the parent */ + uint8_t swizzled_pin = 0; /* Pin swizzled across a bridge */ + + /* Start with PIN A = 0 ... D = 3 */ + dm_pci_read_config8(dev, PCI_INTERRUPT_PIN, &swizzled_pin); + swizzled_pin -= 1; + + /* While our current device has parent devices */ + child = dev; + for (parent = child->parent; parent; parent = parent->parent) { + struct pci_child_platdata *pplat, *cplat; + + cplat = dev_get_parent_platdata(child); + pplat = dev_get_parent_platdata(parent); + + /* Swizzle the INT_PIN for any bridges not on root bus */ + swizzled_pin = (PCI_DEV(cplat->devfn) + swizzled_pin) % 4; + debug("\tWith INT_PIN swizzled to %s\n" + "\tAttached to bridge device %01X:%02Xh.%02Xh\n", + pin_to_str(swizzled_pin + 1), parent->seq, + PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); + + /* Continue until we find the root bus */ + if (device_get_uclass_id(parent->parent->parent) == + UCLASS_PCI) { + /* + * We will go on to the next parent so this parent + * becomes the child + */ + child = parent; + continue; + } else { + /* + * Found the root bridge device, + * fill in the structure and exit + */ + *parent_bridgep = parent; + break; + } + } + + /* End with PIN A = 1 ... D = 4 */ + return swizzled_pin + 1; +} + +/** + * get_pci_irq_pins() - Get interrupt pin number for a device + * + * Given a device structure 'dev', find its interrupt pin and its parent bridge + * 'parent_bdg' device structure. If it is behind a bridge, it will return the + * interrupt pin number (1 - 4) of the parent bridge that the device interrupt + * pin has been swizzled to, otherwise it will return the interrupt pin that is + * programmed into the PCI config space of the target device. If 'dev' is + * behind a bridge, it will fill in 'parent_bdg' with the device structure of + * the bridge it is behind, otherwise it will copy 'dev' into 'parent_bdg'. + * + * @param dev Device to check + * @param *parent_bdgp Parent bridge for device + * @return interrupt pin number (1 - 4) that @dev will trigger when + * generating an interrupt, or -EINVAL is the pin is invalid, or + * -ENOENT if there was no paremt bridge + */ +static int get_pci_irq_pins(struct udevice *dev, struct udevice **parent_bdgp) +{ + uint8_t bus = 0; /* The bus this device is on */ + uint16_t devfn = 0; /* This device's device and function numbers */ + uint8_t int_pin = 0; /* Interrupt pin used by the device */ + uint8_t target_pin = 0; /* Interrupt pin we want to assign an IRQ to */ + + bus = dev->parent->seq; + devfn = pci_get_bdf(dev); + + /* Get and validate the interrupt pin used. Only 1-4 are allowed */ + dm_pci_read_config8(dev, PCI_INTERRUPT_PIN, &int_pin); + if (int_pin < 1 || int_pin > 4) + return -EINVAL; + + debug("PCI IRQ: Found device %01X:%02X.%02X using %s\n", bus, + PCI_DEV(devfn), PCI_FUNC(devfn), pin_to_str(int_pin)); + + /* If this device is on a bridge, swizzle its INT_PIN */ + if (bus) { + /* Swizzle its INT_PINs */ + target_pin = swizzle_irq_pins(dev, parent_bdgp); + + /* Make sure the swizzle returned valid structures */ + if (*parent_bdgp == NULL) { + debug("Warning: Could not find parent bridge for this device!\n"); + return -ENOENT; + } + } else { /* Device is not behind a bridge */ + target_pin = int_pin; /* Return its own interrupt pin */ + *parent_bdgp = dev; /* Return its own structure */ + } + + /* Target pin is the interrupt pin we want to assign an IRQ to */ + return target_pin; +} + +/* + * Write PCI config space IRQ assignments. PCI devices have the INT_LINE + * (0x3C) and INT_PIN (0x3D) registers which report interrupt routing + * information to operating systems and drivers. The INT_PIN register is + * generally read only and reports which interrupt pin A - D it uses. The + * INT_LINE register is configurable and reports which IRQ (generally the + * PIC IRQs 1 - 15) it will use. This needs to take interrupt pin swizzling + * on devices that are downstream on a PCI bridge into account. + * + * This function will loop through all enabled PCI devices and program the + * INT_LINE register with the correct PIC IRQ number for the INT_PIN that it + * uses. It then configures each interrupt in the pic to be level triggered. + */ +static void write_pci_config_irqs(const struct baytrail_irq_route *ir) +{ + struct udevice *dev; + + for (pci_find_first_device(&dev); dev; pci_find_next_device(&dev)) { + pci_dev_t current_bdf = pci_get_bdf(dev); + struct udevice *targ_dev; + uint8_t original_int_pin; + pci_dev_t parent_bdf; + uint8_t new_int_pin; + uint8_t device_num; + uint8_t pirq; + uint8_t int_line; + + /* Get the INT_PIN and device structure to look for */ + targ_dev = NULL; + new_int_pin = get_pci_irq_pins(dev, &targ_dev); + if (targ_dev == NULL || new_int_pin < 1) + continue; + + /* Get the original INT_PIN for record keeping */ + dm_pci_read_config8(dev, PCI_INTERRUPT_PIN, &original_int_pin); + + parent_bdf = pci_get_bdf(targ_dev); + device_num = PCI_DEV(parent_bdf); + + if (ir->pcidev[device_num] == 0) { + debug("Warning: PCI Device %d does not have an IRQ entry, skipping it\n", + device_num); + continue; + } + + /* + * Find the PIRQ that is attached to the INT_PIN this device + * uses. + * TODO(sjg): Rationalise this with pirq_route_irqs() and + * pci_assign_irqs(). + */ + pirq = (ir->pcidev[device_num] >> ((new_int_pin - 1) * 4)) & + 0xf; + + /* Get the INT_LINE this device/function will use */ + int_line = ir->pic[pirq]; + + if (int_line != PIRQ_PIC_IRQDISABLE) { + /* + * Set this IRQ to level triggered since it is used by + * a PCI device + */ + configure_irq_trigger(int_line, true); + dm_pci_write_config8(dev, PCI_INTERRUPT_LINE, int_line); + } else { + dm_pci_write_config8(dev, PCI_INTERRUPT_LINE, + PCI_INTERRUPT_LINE_DISABLE); + } + + debug("\tINT_PIN\t\t: %d (%s)\n", + original_int_pin, pin_to_str(original_int_pin)); + if (parent_bdf != current_bdf) { + debug("\tSwizzled to\t: %d (%s)\n", new_int_pin, + pin_to_str(new_int_pin)); + } + debug("\tPIRQ\t\t: %c\n", 'A' + pirq); + debug("\tINT_LINE\t: 0x%X (IRQ %d)\n", int_line, int_line); + } +} + +static void valleyview_pirq_init(const struct baytrail_irq_route *ir, + struct ibase_regs *ibase) +{ + int i; + + /* Set up the PIRQ PIC routing based on static config */ + debug("Start writing IRQ assignments\n" + "PIRQ\tA \tB \tC \tD \tE \tF \tG \tH\n" + "IRQ "); + for (i = 0; i < NUM_PIRQS; i++) { + writeb(ir->pic[i], &ibase->pirq[i]); + debug("\t%d", ir->pic[i]); + } + debug("\n\n"); + + /* Set up the per device PIRQ routing based on static config */ + debug("\t\t\tPIRQ[A-H] routed to each INT_PIN[A-D]\n" + "Dev\tINTA (IRQ)\tINTB (IRQ)\tINTC (IRQ)\tINTD (IRQ)\n"); + + for (i = 0; i < NUM_OF_PCI_DEVS; i++) { + writew(ir->pcidev[i], &ibase->ir[i]); + + /* If the entry is more than just 0, print it out */ + if (ir->pcidev[i]) { + int j, pirq; + + debug(" %d: ", i); + for (j = 0; j < 4; j++) { + pirq = (ir->pcidev[i] >> (j * 4)) & 0xF; + debug("\t%-4c (%d)", 'A' + pirq, ir->pic[pirq]); + } + debug("\n"); + } + } + + /* Write IRQ assignments to PCI config space */ + write_pci_config_irqs(ir); +} + +static int valleyview_init(struct udevice *dev) +{ + int ret; + u32 addr; + struct ibase_regs *ibase; + + debug("%s\n", __func__); + + dm_pci_read_config32(dev, IBASE, &addr); + addr &= ~0xf; + ibase = (struct ibase_regs *)addr; + debug("ibase = %p\n", ibase); + + writeb(0, &ibase->mc); + + /* Enable special cycles */ + dm_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL); + + /* IO APIC initialisation */ + ret = valleyview_enable_ioapic(dev, ibase); + if (ret) + return ret; + + valleyview_enable_serial_irqs(dev, ibase); + + /* Setup the PIRQ */ + valleyview_pirq_init(&irq_info, ibase); + + return fsp_init_phase_pci(); +} + +int arch_misc_init(void) +{ + struct udevice *dev; + int ret; + + ret = pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &dev); + if (ret) { + debug("Cannot find Intel Legacy Block\n"); + return ret; + } + + return valleyview_init(dev); +} diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts index 9527233..fb2510b 100644 --- a/arch/x86/dts/minnowmax.dts +++ b/arch/x86/dts/minnowmax.dts @@ -7,6 +7,7 @@ /dts-v1/;
#include <dt-bindings/gpio/x86-gpio.h> +#include <dt-bindings/interrupt-router/intel-irq.h>
/include/ "skeleton.dtsi" /include/ "serial.dtsi" @@ -120,6 +121,33 @@ ranges = <0x02000000 0x0 0xd0000000 0xd0000000 0 0x10000000 0x42000000 0x0 0xc0000000 0xc0000000 0 0x10000000 0x01000000 0x0 0x2000 0x2000 0 0xe000>; + + /* TODO(sjg@chromium.org): Currently unused */ + irq-router@1f,0 { + reg = <0x0000f800 0 0 0 0>; + compatible = "intel,irq-router"; + intel,pirq-config = "ibase"; + intel,ibase-offset = <0x50>; + intel,pirq-link = <0x20 32>; + intel,pirq-mask = <0xdcb0>; + intel,pirq-routing = < + PCI_BDF(0, 0x02, 0) INTB PIRQA + PCI_BDF(0, 0x10, 0) INTA PIRQD + PCI_BDF(0, 0x11, 0) INTA PIRQB + PCI_BDF(0, 0x12, 0) INTA PIRQC + PCI_BDF(0, 0x13, 0) INTA PIRQD + PCI_BDF(0, 0x14, 0) INTA PIRQE + PCI_BDF(0, 0x15, 0) INTC PIRQF + PCI_BDF(0, 0x17, 0) INTA PIRQF + PCI_BDF(0, 0x18, 0) INTA PIRQB + PCI_BDF(0, 0x1a, 0) INTA PIRQF + PCI_BDF(0, 0x1b, 0) INTA PIRQG + PCI_BDF(0, 0x1c, 0) INTD PIRQE + PCI_BDF(0, 0x1d, 0) INTA PIRQD + PCI_BDF(0, 0x1e, 0) INTB PIRQB + PCI_BDF(0, 0x1f, 0) INTC PIRQH + >; + }; };
spi { diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index cdbb65d..ffa5510 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -16,6 +16,7 @@ #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_EARLY_INIT_R +#define CONFIG_ARCH_MISC_INIT
#define CONFIG_SMSC_LPC47M

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
help figure this out.
Signed-off-by: Simon Glass sjg@chromium.org
[snip]
Regards, Bin

Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
Regards, Simon

Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
Regards, Bin

Hi Bin,
On 28 July 2015 at 18:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
What do you mean by 'leave those register programmed'?
Regards, Simon

Hi Simon,
On Wed, Jul 29, 2015 at 8:42 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
What do you mean by 'leave those register programmed'?
I mean their default value is normally OK, like INTA maps PIRQA, INTB maps PIRQB, INTC maps PIRQC and INTD maps PIRQD.
Regards, Bin

Hi Bin,
On 28 July 2015 at 18:46, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 8:42 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
At present minnowmax does not correct set up PCI interrupts. This should be done in U-Boot so that devices work correctly in Linux.
Note: This code needs to make use of the recent pirq_routing work. It does not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
What do you mean by 'leave those register programmed'?
I mean their default value is normally OK, like INTA maps PIRQA, INTB maps PIRQB, INTC maps PIRQC and INTD maps PIRQD.
OK, so drop writing to the pirq registers?
Should I program the 16-bit registers? If so, I will need to extend the device tree binding, won't I?
Sorry my understanding is limited on this - and I'd like to use your generic code if possible.
Regards, Simon

Hi Simon,
On Wed, Jul 29, 2015 at 8:48 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:46, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 8:42 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote: > At present minnowmax does not correct set up PCI interrupts. This should be > done in U-Boot so that devices work correctly in Linux. > > Note: This code needs to make use of the recent pirq_routing work. It does > not seem to support all the required features, so this RFC will hopefully
What features are missing in the existing PIRQ codes? When I did the PIRQ support, I checked both TunnelCreek and BayTrail chipset datasheet, and found the only difference seems to be the pci configuration space vs. memory-mapped IBASE where the pci irq routing registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
What do you mean by 'leave those register programmed'?
I mean their default value is normally OK, like INTA maps PIRQA, INTB maps PIRQB, INTC maps PIRQC and INTD maps PIRQD.
OK, so drop writing to the pirq registers?
You might need check if BayTrail FSP does any programming on these registers. On Intel Crown Bay, I checked those values are the same values as documented in the TunnelCreek datasheet.
Should I program the 16-bit registers? If so, I will need to extend the device tree binding, won't I?
When I did the device tree binding changes, I did not convert these registers to use device tree, because their offsets, not like the routing registers as programmed in pirq_assign_irq(), is really platform specific thing and does not seem to have a good formula to calculate its offset (it varies from platform to platform). I previously wanted to create some device bindings like below, but I think they are really ugly so I did not go that way:
irq-router@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,irq-router"; ...... dev0-intx-offset = <0x2040>; dev0-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev2-intx-offset = <0x2048>; dev2-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev4-intx-offset = <0x2060>; dev4-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev26-intx-offset = <0x20a0>; dev26-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev31-intx-offset = <0x20c0>; dev31-intx-value = <PIRQA PIRQB PIRQC PIRQD>; ......
Sorry I cannot find a better way to describe this in device tree, so I chose to implement directly in the cpu_irq_init() to program these registers.
Sorry my understanding is limited on this - and I'd like to use your generic code if possible.
Yes, let's try to use the existing codes. If needed, we can have some patches to support new platforms.
Regards, Bin

Hi Simon,
On Wed, Jul 29, 2015 at 9:08 AM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 8:48 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:46, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 8:42 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote: > > Hi Simon, > > On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote: > > At present minnowmax does not correct set up PCI interrupts. This should be > > done in U-Boot so that devices work correctly in Linux. > > > > Note: This code needs to make use of the recent pirq_routing work. It does > > not seem to support all the required features, so this RFC will hopefully > > What features are missing in the existing PIRQ codes? When I did the > PIRQ support, I checked both TunnelCreek and BayTrail chipset > datasheet, and found the only difference seems to be the pci > configuration space vs. memory-mapped IBASE where the pci irq routing > registers reside.
I see that each PCI device can be assigned four routes, making up a 16-bit register. But the code I see in pirq_assign_req() only assigns a single one, using a byte register.
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
What do you mean by 'leave those register programmed'?
I mean their default value is normally OK, like INTA maps PIRQA, INTB maps PIRQB, INTC maps PIRQC and INTD maps PIRQD.
OK, so drop writing to the pirq registers?
You might need check if BayTrail FSP does any programming on these registers. On Intel Crown Bay, I checked those values are the same values as documented in the TunnelCreek datasheet.
Should I program the 16-bit registers? If so, I will need to extend the device tree binding, won't I?
When I did the device tree binding changes, I did not convert these registers to use device tree, because their offsets, not like the routing registers as programmed in pirq_assign_irq(), is really platform specific thing and does not seem to have a good formula to calculate its offset (it varies from platform to platform). I previously wanted to create some device bindings like below, but I think they are really ugly so I did not go that way:
irq-router@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,irq-router"; ...... dev0-intx-offset = <0x2040>; dev0-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev2-intx-offset = <0x2048>; dev2-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev4-intx-offset = <0x2060>; dev4-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev26-intx-offset = <0x20a0>; dev26-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev31-intx-offset = <0x20c0>; dev31-intx-value = <PIRQA PIRQB PIRQC PIRQD>; ......
Sorry I cannot find a better way to describe this in device tree, so I chose to implement directly in the cpu_irq_init() to program these registers.
Sorry my understanding is limited on this - and I'd like to use your generic code if possible.
Yes, let's try to use the existing codes. If needed, we can have some patches to support new platforms.
I just managed to get a BayTrail board (not MinnowMax) and will try to first port U-Boot (assume it won't take much time) then see how PIRQ looks like on this platform.
Regards, Bin

Hi Simon,
On Wed, Jul 29, 2015 at 5:01 PM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 9:08 AM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 8:48 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:46, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jul 29, 2015 at 8:42 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 28 July 2015 at 18:40, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 7:58 PM, Simon Glass sjg@chromium.org wrote: > Hi Bin, > > On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote: >> >> Hi Simon, >> >> On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote: >> > At present minnowmax does not correct set up PCI interrupts. This should be >> > done in U-Boot so that devices work correctly in Linux. >> > >> > Note: This code needs to make use of the recent pirq_routing work. It does >> > not seem to support all the required features, so this RFC will hopefully >> >> What features are missing in the existing PIRQ codes? When I did the >> PIRQ support, I checked both TunnelCreek and BayTrail chipset >> datasheet, and found the only difference seems to be the pci >> configuration space vs. memory-mapped IBASE where the pci irq routing >> registers reside. > > I see that each PCI device can be assigned four routes, making up a > 16-bit register. But the code I see in pirq_assign_req() only assigns > a single one, using a byte register. >
No, the pci irq routing register is still a 8-bit register on BayTrail, where pirq_assign_irq() programs. The 16-bit register you mentioned should be done in the platform codes. See arch/x86/cpu/queensbay/tnc.c::cpu_irq_init(). By the way actually we can leave those register programmed as they have the optimized default values for all pci devices after power up, unless we intentionally want to change them.
What do you mean by 'leave those register programmed'?
I mean their default value is normally OK, like INTA maps PIRQA, INTB maps PIRQB, INTC maps PIRQC and INTD maps PIRQD.
OK, so drop writing to the pirq registers?
You might need check if BayTrail FSP does any programming on these registers. On Intel Crown Bay, I checked those values are the same values as documented in the TunnelCreek datasheet.
Should I program the 16-bit registers? If so, I will need to extend the device tree binding, won't I?
When I did the device tree binding changes, I did not convert these registers to use device tree, because their offsets, not like the routing registers as programmed in pirq_assign_irq(), is really platform specific thing and does not seem to have a good formula to calculate its offset (it varies from platform to platform). I previously wanted to create some device bindings like below, but I think they are really ugly so I did not go that way:
irq-router@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,irq-router"; ...... dev0-intx-offset = <0x2040>; dev0-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev2-intx-offset = <0x2048>; dev2-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev4-intx-offset = <0x2060>; dev4-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev26-intx-offset = <0x20a0>; dev26-intx-value = <PIRQA PIRQB PIRQC PIRQD>; dev31-intx-offset = <0x20c0>; dev31-intx-value = <PIRQA PIRQB PIRQC PIRQD>; ......
Sorry I cannot find a better way to describe this in device tree, so I chose to implement directly in the cpu_irq_init() to program these registers.
Sorry my understanding is limited on this - and I'd like to use your generic code if possible.
Yes, let's try to use the existing codes. If needed, we can have some patches to support new platforms.
I just managed to get a BayTrail board (not MinnowMax) and will try to first port U-Boot (assume it won't take much time) then see how PIRQ looks like on this platform.
It turns out the existing PIRQ codes works pretty well on BayTrail. Please check this patch: http://patchwork.ozlabs.org/patch/502058/
Regards, Bin

The steps required to boot a Linux distribution from U-Boot on x86 are not very complicated, but it is a good idea to have these written down in an accessible place.
Document how to examine the boot media from U-Boot, how to load a kernel, load a ramdisk, set the kernel boot arguments and start the kernel. With these instructions Ubuntu boots mostly normally on Minnowmax.
Note that the TSC timer does not operate correctly and gives warnings in the boot log. I expect that ACPI support will solve this.
Signed-off-by: Simon Glass sjg@chromium.org ---
doc/README.x86 | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index 5d71244..5435d79 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -325,6 +325,278 @@ mtrr - List and set the Memory Type Range Registers (MTRR). These are used to mode to use. U-Boot sets up some reasonable values but you can adjust then with this command.
+Booting Ubuntu +-------------- +As an example of how to set up your boot flow with U-Boot, here are +instructions for starting Ubuntu from U-Boot. These instructions have been +testinged on Minnowboard MAX with a SATA driver but are equally applicable on +other platforms and other media. There are really only four steps and its a +very simple script, but a more detailed explaination is provided here for +completeness. + +Note: It is possible to set up U-Boot to boot automatically using syslinux. +It could also use the grub.cfg file (/efi/ubuntu/grub.cfg) to obtain the +GUID. If you figure these out, please post patches to this README. + +Firstly, you will need Ubunutu installed on an available disk. It should be +possible to make U-Boot start a USB start-up disk but for now let's assume +that you used another boot loader to install Ubuntu. + +Use the U-Boot command line to find the UUID of the partition you want to +boot. For example our disk is SCSI device 0: + +=> part list scsi 0 + +Partition Map for SCSI device 0 -- Partition Type: EFI + + Part Start LBA End LBA Name + Attributes + Type GUID + Partition GUID + 1 0x00000800 0x001007ff "" + attrs: 0x0000000000000000 + type: c12a7328-f81f-11d2-ba4b-00a0c93ec93b + guid: 9d02e8e4-4d59-408f-a9b0-fd497bc9291c + 2 0x00100800 0x037d8fff "" + attrs: 0x0000000000000000 + type: 0fc63daf-8483-4772-8e79-3d69d8477de4 + guid: 965c59ee-1822-4326-90d2-b02446050059 + 3 0x037d9000 0x03ba27ff "" + attrs: 0x0000000000000000 + type: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f + guid: 2c4282bd-1e82-4bcf-a5ff-51dedbf39f17 + => + +This shows that your SCSI disk has three partitions. The really long hex +strings are called Globally Unique Identifiers (GUIDs). You can look up the +'type' ones here [11]. On this disk the first partition is for EFI and is in +VFAT format (DOS/Windows): + + => fatls scsi 0:1 + efi/ + + 0 file(s), 1 dir(s) + + +Partition 2 is 'Linux filesystem data' so that will be our root disk. It is +in ext2 format: + + => ext2ls scsi 0:2 + <DIR> 4096 . + <DIR> 4096 .. + <DIR> 16384 lost+found + <DIR> 4096 boot + <DIR> 12288 etc + <DIR> 4096 media + <DIR> 4096 bin + <DIR> 4096 dev + <DIR> 4096 home + <DIR> 4096 lib + <DIR> 4096 lib64 + <DIR> 4096 mnt + <DIR> 4096 opt + <DIR> 4096 proc + <DIR> 4096 root + <DIR> 4096 run + <DIR> 12288 sbin + <DIR> 4096 srv + <DIR> 4096 sys + <DIR> 4096 tmp + <DIR> 4096 usr + <DIR> 4096 var + <SYM> 33 initrd.img + <SYM> 30 vmlinuz + <DIR> 4096 cdrom + <SYM> 33 initrd.img.old + => + +and if you look in the /boot directory you will see the kernel: + + => ext2ls scsi 0:2 /boot + <DIR> 4096 . + <DIR> 4096 .. + <DIR> 4096 efi + <DIR> 4096 grub + 3381262 System.map-3.13.0-32-generic + 1162712 abi-3.13.0-32-generic + 165611 config-3.13.0-32-generic + 176500 memtest86+.bin + 178176 memtest86+.elf + 178680 memtest86+_multiboot.bin + 5798112 vmlinuz-3.13.0-32-generic + 165762 config-3.13.0-58-generic + 1165129 abi-3.13.0-58-generic + 5823136 vmlinuz-3.13.0-58-generic + 19215259 initrd.img-3.13.0-58-generic + 3391763 System.map-3.13.0-58-generic + 5825048 vmlinuz-3.13.0-58-generic.efi.signed + 28304443 initrd.img-3.13.0-32-generic + => + +The 'vmlinuz' files contain a packaged Linux kernel. The format is a kind of +self-extracting compressed file mixed with some 'setup' configuration data. +Despite its size (uncompressed it is >10MB) this only includes a basic set of +device drivers, enough to boot on most hardware types. + +The 'initrd' files contain a RAM disk. This is something that can be loaded +into RAM and will appear to Linux like a disk. Ubuntu uses this to hold lots +of drivers for whatever hardware you might have. It is loaded before the +real root disk is accessed. + +The numbers after the end of each file are the version. Here it is Linux +version 3.13. You can find the source code for this in the Linux tree with +the tag v3.13. The '.0' allows for additional Linux releases to fix problems, +but normally this is not needed. The '-58' is used by Ubuntu. Each time they +release a new kernel they increment this number. New Ubuntu versions might +include kernel patches to fix reported bugs. Stable kernels can exist for +some years so this number can get quite high. + +The '.efi.signed' kernel is signed for EFI's secure boot. U-Boot has its own +secure boot mechanism - see [12] [13] and cannot read .efi files at present. + +To boot Ubuntu from U-Boot the steps are as follows: + +1. Set up the boot arguments. Use the GUID for the partition you want to +boot: + + => setenv bootargs root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro + +Here root= tells Linux the location of its root disk. The disk is specified +by its GUID, using '/dev/disk/by-partuuid/', a Linux path to a 'directory' +containing all the GUIDs Linux has found. When it starts up, there will be a +file in that directory with this name in it. It is also possible to use a +device name here, see later. + +2. Load the kernel. Since it is an ext2/4 filesystem we can do: + + => ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic + +The address 30000000 is arbitrary, but there seem to be problems with using +small addresses (sometimes Linux cannot find the ramdisk). This is 48MB into +the start of RAM (which is at 0 on x86). + +3. Load the ramdisk (to 64MB): + + => ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic + +4. Start up the kernel. We need to know the size of the ramdisk, but can use +a variable for that. U-Boot sets 'filesize' to the size of the last file it +loaded. + + => zboot 03000000 0 04000000 ${filesize} + +Type 'help zboot' if you want to see what the arguments are. U-Boot on x86 is +quite verbose when it boots a kernel. You should see these messages from +U-Boot: + + Valid Boot Flag + Setup Size = 0x00004400 + Magic signature found + Using boot protocol version 2.0c + Linux kernel version 3.13.0-58-generic (buildd@allspice) #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015 + Building boot_params at 0x00090000 + Loading bzImage at address 100000 (5805728 bytes) + Magic signature found + Initial RAM disk at linear address 0x04000000, size 19215259 bytes + Kernel command line: "console=ttyS0,115200 root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro" + + Starting kernel ... + +U-Boot prints out some bootstage timing. This is more useful if you put the +above commands into a script since then it will be faster. + + Timer summary in microseconds: + Mark Elapsed Stage + 0 0 reset + 241,535 241,535 board_init_r + 2,421,611 2,180,076 id=64 + 2,421,790 179 id=65 + 2,428,215 6,425 main_loop + 48,860,584 46,432,369 start_kernel + + Accumulated time: + 240,329 ahci + 1,422,704 vesa display + +Now the kernel actually starts: + + [ 0.000000] Initializing cgroup subsys cpuset + [ 0.000000] Initializing cgroup subsys cpu + [ 0.000000] Initializing cgroup subsys cpuacct + [ 0.000000] Linux version 3.13.0-58-generic (buildd@allspice) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015 (Ubuntu 3.13.0-58.97-generic 3.13.11-ckt22) + [ 0.000000] Command line: console=ttyS0,115200 root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro + +It continues for a long time. Along the way you will see it pick up your +ramdisk: + + [ 0.000000] RAMDISK: [mem 0x04000000-0x05253fff] +... + [ 0.788540] Trying to unpack rootfs image as initramfs... + [ 1.540111] Freeing initrd memory: 18768K (ffff880004000000 - ffff880005254000) +... + +Later it actually starts using it: + + Begin: Running /scripts/local-premount ... done. + +You should also see your boot disk turn up: + + [ 4.357243] scsi 1:0:0:0: Direct-Access ATA ADATA SP310 5.2 PQ: 0 ANSI: 5 + [ 4.366860] sd 1:0:0:0: [sda] 62533296 512-byte logical blocks: (32.0 GB/29.8 GiB) + [ 4.375677] sd 1:0:0:0: Attached scsi generic sg0 type 0 + [ 4.381859] sd 1:0:0:0: [sda] Write Protect is off + [ 4.387452] sd 1:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA + [ 4.399535] sda: sda1 sda2 sda3 + +Linux has found the three partitions (sda1-3). Mercifully it doesn't print out +the GUIDs. In step 1 above we could have used: + + setenv bootargs root=/dev/sda2 ro + +instead of the GUID. However if you add another drive to your board the +numbering may change whereas the GUIDs will not. So if your boot partition +becomes sdb2, it will still boot. For embedded systems where you just want to +boot the first disk, you have that option. + +The last thing you will see on the console is mention of plymouth (which +displays the Ubuntu start-up screen) and a lot of 'Starting' messages: + + * Starting Mount filesystems on boot [ OK ] + +After a pause you should see a login screen on your display and you are done. + +If you want to put this in a script you can use something like this: + + setenv bootargs root=UUID=b2aaf743-0418-4d90-94cc-3e6108d7d968 ro + setenv boot zboot 03000000 0 04000000 ${filesize} + setenv bootcmd "ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; run boot" + saveenv + +You will also need to add this to your board configuration file, e.g. +include/configs/minnowmax.h: + + #define CONFIG_BOOTDELAY 2 + +Now when you reset your board it wait a few seconds (in case you want to +interrupt) and then should boot straight into Ubuntu. + +You can also bake this behaviour into your build by hard-coding the +environment variables if you add this to minnowmax.h: + +#undef CONFIG_BOOTARGS +#undef CONFIG_BOOTCOMMAND + +#define CONFIG_BOOTARGS \ + "root=/dev/sda2 ro" +#define CONFIG_BOOTCOMMAND \ + "ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; " \ + "ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; " \ + "run boot" + +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS "boot=zboot 03000000 0 04000000 ${filesize}" + + Development Flow ---------------- These notes are for those who want to port U-Boot to a new x86 platform. @@ -406,3 +678,6 @@ References [8] http://en.wikipedia.org/wiki/Microcode [9] http://simplefirmware.org [10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm +[11] https://en.wikipedia.org/wiki/GUID_Partition_Table +[12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... +[13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf

Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
The steps required to boot a Linux distribution from U-Boot on x86 are not very complicated, but it is a good idea to have these written down in an accessible place.
Document how to examine the boot media from U-Boot, how to load a kernel, load a ramdisk, set the kernel boot arguments and start the kernel. With these instructions Ubuntu boots mostly normally on Minnowmax.
Note that the TSC timer does not operate correctly and gives warnings in the boot log. I expect that ACPI support will solve this.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Please see some comments below.
doc/README.x86 | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index 5d71244..5435d79 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -325,6 +325,278 @@ mtrr - List and set the Memory Type Range Registers (MTRR). These are used to mode to use. U-Boot sets up some reasonable values but you can adjust then with this command.
+Booting Ubuntu +-------------- +As an example of how to set up your boot flow with U-Boot, here are +instructions for starting Ubuntu from U-Boot. These instructions have been +testinged on Minnowboard MAX with a SATA driver but are equally applicable on
tested
+other platforms and other media. There are really only four steps and its a +very simple script, but a more detailed explaination is provided here for
explanation
+completeness.
+Note: It is possible to set up U-Boot to boot automatically using syslinux. +It could also use the grub.cfg file (/efi/ubuntu/grub.cfg) to obtain the +GUID. If you figure these out, please post patches to this README.
+Firstly, you will need Ubunutu installed on an available disk. It should be +possible to make U-Boot start a USB start-up disk but for now let's assume +that you used another boot loader to install Ubuntu.
+Use the U-Boot command line to find the UUID of the partition you want to +boot. For example our disk is SCSI device 0:
+=> part list scsi 0
+Partition Map for SCSI device 0 -- Partition Type: EFI
- Part Start LBA End LBA Name
Attributes
Type GUID
Partition GUID
- 1 0x00000800 0x001007ff ""
attrs: 0x0000000000000000
type: c12a7328-f81f-11d2-ba4b-00a0c93ec93b
guid: 9d02e8e4-4d59-408f-a9b0-fd497bc9291c
- 2 0x00100800 0x037d8fff ""
attrs: 0x0000000000000000
type: 0fc63daf-8483-4772-8e79-3d69d8477de4
guid: 965c59ee-1822-4326-90d2-b02446050059
- 3 0x037d9000 0x03ba27ff ""
attrs: 0x0000000000000000
type: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f
guid: 2c4282bd-1e82-4bcf-a5ff-51dedbf39f17
- =>
+This shows that your SCSI disk has three partitions. The really long hex +strings are called Globally Unique Identifiers (GUIDs). You can look up the +'type' ones here [11]. On this disk the first partition is for EFI and is in +VFAT format (DOS/Windows):
- => fatls scsi 0:1
efi/
- 0 file(s), 1 dir(s)
+Partition 2 is 'Linux filesystem data' so that will be our root disk. It is +in ext2 format:
- => ext2ls scsi 0:2
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 16384 lost+found
<DIR> 4096 boot
<DIR> 12288 etc
<DIR> 4096 media
<DIR> 4096 bin
<DIR> 4096 dev
<DIR> 4096 home
<DIR> 4096 lib
<DIR> 4096 lib64
<DIR> 4096 mnt
<DIR> 4096 opt
<DIR> 4096 proc
<DIR> 4096 root
<DIR> 4096 run
<DIR> 12288 sbin
<DIR> 4096 srv
<DIR> 4096 sys
<DIR> 4096 tmp
<DIR> 4096 usr
<DIR> 4096 var
- <SYM> 33 initrd.img
- <SYM> 30 vmlinuz
<DIR> 4096 cdrom
- <SYM> 33 initrd.img.old
- =>
+and if you look in the /boot directory you will see the kernel:
- => ext2ls scsi 0:2 /boot
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 4096 efi
<DIR> 4096 grub
3381262 System.map-3.13.0-32-generic
1162712 abi-3.13.0-32-generic
165611 config-3.13.0-32-generic
176500 memtest86+.bin
178176 memtest86+.elf
178680 memtest86+_multiboot.bin
5798112 vmlinuz-3.13.0-32-generic
165762 config-3.13.0-58-generic
1165129 abi-3.13.0-58-generic
5823136 vmlinuz-3.13.0-58-generic
19215259 initrd.img-3.13.0-58-generic
3391763 System.map-3.13.0-58-generic
5825048 vmlinuz-3.13.0-58-generic.efi.signed
28304443 initrd.img-3.13.0-32-generic
- =>
+The 'vmlinuz' files contain a packaged Linux kernel. The format is a kind of +self-extracting compressed file mixed with some 'setup' configuration data. +Despite its size (uncompressed it is >10MB) this only includes a basic set of +device drivers, enough to boot on most hardware types.
+The 'initrd' files contain a RAM disk. This is something that can be loaded +into RAM and will appear to Linux like a disk. Ubuntu uses this to hold lots +of drivers for whatever hardware you might have. It is loaded before the +real root disk is accessed.
+The numbers after the end of each file are the version. Here it is Linux +version 3.13. You can find the source code for this in the Linux tree with +the tag v3.13. The '.0' allows for additional Linux releases to fix problems, +but normally this is not needed. The '-58' is used by Ubuntu. Each time they +release a new kernel they increment this number. New Ubuntu versions might +include kernel patches to fix reported bugs. Stable kernels can exist for +some years so this number can get quite high.
+The '.efi.signed' kernel is signed for EFI's secure boot. U-Boot has its own +secure boot mechanism - see [12] [13] and cannot read .efi files at present.
+To boot Ubuntu from U-Boot the steps are as follows:
+1. Set up the boot arguments. Use the GUID for the partition you want to +boot:
- => setenv bootargs root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro
+Here root= tells Linux the location of its root disk. The disk is specified +by its GUID, using '/dev/disk/by-partuuid/', a Linux path to a 'directory' +containing all the GUIDs Linux has found. When it starts up, there will be a +file in that directory with this name in it. It is also possible to use a +device name here, see later.
+2. Load the kernel. Since it is an ext2/4 filesystem we can do:
- => ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic
+The address 30000000 is arbitrary, but there seem to be problems with using +small addresses (sometimes Linux cannot find the ramdisk). This is 48MB into +the start of RAM (which is at 0 on x86).
+3. Load the ramdisk (to 64MB):
- => ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic
+4. Start up the kernel. We need to know the size of the ramdisk, but can use +a variable for that. U-Boot sets 'filesize' to the size of the last file it +loaded.
- => zboot 03000000 0 04000000 ${filesize}
+Type 'help zboot' if you want to see what the arguments are. U-Boot on x86 is +quite verbose when it boots a kernel. You should see these messages from +U-Boot:
- Valid Boot Flag
- Setup Size = 0x00004400
- Magic signature found
- Using boot protocol version 2.0c
- Linux kernel version 3.13.0-58-generic (buildd@allspice) #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015
- Building boot_params at 0x00090000
- Loading bzImage at address 100000 (5805728 bytes)
- Magic signature found
- Initial RAM disk at linear address 0x04000000, size 19215259 bytes
- Kernel command line: "console=ttyS0,115200 root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro"
- Starting kernel ...
+U-Boot prints out some bootstage timing. This is more useful if you put the +above commands into a script since then it will be faster.
- Timer summary in microseconds:
Mark Elapsed Stage
0 0 reset
241,535 241,535 board_init_r
2,421,611 2,180,076 id=64
2,421,790 179 id=65
2,428,215 6,425 main_loop
- 48,860,584 46,432,369 start_kernel
- Accumulated time:
240,329 ahci
1,422,704 vesa display
+Now the kernel actually starts:
- [ 0.000000] Initializing cgroup subsys cpuset
- [ 0.000000] Initializing cgroup subsys cpu
- [ 0.000000] Initializing cgroup subsys cpuacct
- [ 0.000000] Linux version 3.13.0-58-generic (buildd@allspice) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015 (Ubuntu 3.13.0-58.97-generic 3.13.11-ckt22)
- [ 0.000000] Command line: console=ttyS0,115200 root=/dev/disk/by-partuuid/965c59ee-1822-4326-90d2-b02446050059 ro
+It continues for a long time. Along the way you will see it pick up your +ramdisk:
- [ 0.000000] RAMDISK: [mem 0x04000000-0x05253fff]
+...
- [ 0.788540] Trying to unpack rootfs image as initramfs...
- [ 1.540111] Freeing initrd memory: 18768K (ffff880004000000 - ffff880005254000)
+...
+Later it actually starts using it:
- Begin: Running /scripts/local-premount ... done.
+You should also see your boot disk turn up:
- [ 4.357243] scsi 1:0:0:0: Direct-Access ATA ADATA SP310 5.2 PQ: 0 ANSI: 5
- [ 4.366860] sd 1:0:0:0: [sda] 62533296 512-byte logical blocks: (32.0 GB/29.8 GiB)
- [ 4.375677] sd 1:0:0:0: Attached scsi generic sg0 type 0
- [ 4.381859] sd 1:0:0:0: [sda] Write Protect is off
- [ 4.387452] sd 1:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
- [ 4.399535] sda: sda1 sda2 sda3
+Linux has found the three partitions (sda1-3). Mercifully it doesn't print out +the GUIDs. In step 1 above we could have used:
- setenv bootargs root=/dev/sda2 ro
+instead of the GUID. However if you add another drive to your board the +numbering may change whereas the GUIDs will not. So if your boot partition +becomes sdb2, it will still boot. For embedded systems where you just want to +boot the first disk, you have that option.
+The last thing you will see on the console is mention of plymouth (which +displays the Ubuntu start-up screen) and a lot of 'Starting' messages:
- Starting Mount filesystems on boot [ OK ]
+After a pause you should see a login screen on your display and you are done.
+If you want to put this in a script you can use something like this:
- setenv bootargs root=UUID=b2aaf743-0418-4d90-94cc-3e6108d7d968 ro
- setenv boot zboot 03000000 0 04000000 ${filesize}
I believe \ is not needed.
- setenv bootcmd "ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; run boot"
- saveenv
+You will also need to add this to your board configuration file, e.g. +include/configs/minnowmax.h:
- #define CONFIG_BOOTDELAY 2
+Now when you reset your board it wait a few seconds (in case you want to +interrupt) and then should boot straight into Ubuntu.
+You can also bake this behaviour into your build by hard-coding the +environment variables if you add this to minnowmax.h:
+#undef CONFIG_BOOTARGS +#undef CONFIG_BOOTCOMMAND
+#define CONFIG_BOOTARGS \
"root=/dev/sda2 ro"
+#define CONFIG_BOOTCOMMAND \
"ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; " \
"ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; " \
"run boot"
+#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS "boot=zboot 03000000 0 04000000 ${filesize}"
Development Flow
These notes are for those who want to port U-Boot to a new x86 platform. @@ -406,3 +678,6 @@ References [8] http://en.wikipedia.org/wiki/Microcode [9] http://simplefirmware.org [10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm +[11] https://en.wikipedia.org/wiki/GUID_Partition_Table +[12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy...
+[13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf
Regards, Bin

On 28 July 2015 at 01:50, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Tue, Jul 28, 2015 at 5:47 AM, Simon Glass sjg@chromium.org wrote:
The steps required to boot a Linux distribution from U-Boot on x86 are not very complicated, but it is a good idea to have these written down in an accessible place.
Document how to examine the boot media from U-Boot, how to load a kernel, load a ramdisk, set the kernel boot arguments and start the kernel. With these instructions Ubuntu boots mostly normally on Minnowmax.
Note that the TSC timer does not operate correctly and gives warnings in the boot log. I expect that ACPI support will solve this.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Please see some comments below.
doc/README.x86 | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index 5d71244..5435d79 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -325,6 +325,278 @@ mtrr - List and set the Memory Type Range Registers (MTRR). These are used to mode to use. U-Boot sets up some reasonable values but you can adjust then with this command.
+Booting Ubuntu +-------------- +As an example of how to set up your boot flow with U-Boot, here are +instructions for starting Ubuntu from U-Boot. These instructions have been +testinged on Minnowboard MAX with a SATA driver but are equally applicable on
tested
Fixed
+other platforms and other media. There are really only four steps and its a +very simple script, but a more detailed explaination is provided here for
explanation
fixed
+completeness.
[snip]
+If you want to put this in a script you can use something like this:
- setenv bootargs root=UUID=b2aaf743-0418-4d90-94cc-3e6108d7d968 ro
- setenv boot zboot 03000000 0 04000000 ${filesize}
I believe \ is not needed.
Otherwise it will set zboot to the value of ${filesize} when you issue the 'setenv' command. I've added a comment. Let me know if we should change it.
- setenv bootcmd "ext2load scsi 0:2 03000000 /boot/vmlinuz-3.13.0-58-generic; ext2load scsi 0:2 04000000 /boot/initrd.img-3.13.0-58-generic; run boot"
- saveenv
[snip]
Applied to u-boot-x86.
participants (2)
-
Bin Meng
-
Simon Glass