Patchwork [U-Boot] add initial support for bluegiga apx4devkit

login
register
mail settings
Submitter Veli-Pekka Peltola
Date Dec. 13, 2011, 2:54 p.m.
Message ID <1323788072-19803-1-git-send-email-veli-pekka.peltola@bluegiga.com>
Download mbox | patch
Permalink /patch/131115/
State Changes Requested
Delegated to: Stefano Babic
Headers show

Comments

Veli-Pekka Peltola - Dec. 13, 2011, 2:54 p.m.
Add initial support for Bluegiga APX4 CoM and development kit.

Signed-off-by: Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
Cc: Stefano Babic <sbabic@denx.de>
---
 board/bluegiga/apx4devkit/Makefile     |   45 +++++++
 board/bluegiga/apx4devkit/apx4devkit.c |  204 ++++++++++++++++++++++++++++++++
 boards.cfg                             |    1 +
 include/configs/apx4devkit.h           |  176 +++++++++++++++++++++++++++
 4 files changed, 426 insertions(+), 0 deletions(-)
 create mode 100644 board/bluegiga/apx4devkit/Makefile
 create mode 100644 board/bluegiga/apx4devkit/apx4devkit.c
 create mode 100644 include/configs/apx4devkit.h
Fabio Estevam - Dec. 13, 2011, 3:59 p.m.
On Tue, Dec 13, 2011 at 12:54 PM, Veli-Pekka Peltola
<veli-pekka.peltola@bluegiga.com> wrote:
> Add initial support for Bluegiga APX4 CoM and development kit.
>
> Signed-off-by: Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
> Cc: Stefano Babic <sbabic@denx.de>

I applied  this patch on top of head U-boot and got build errors when
building "make u-boot.sb".

Can you please try it and let me know if you are able to boot it?

I am rebasing my mx28evk on top of the latest U-boot and I am facing
some issues.

Would be interested to know if your mx28 board can boot with the
latest origin/master.

Thanks,

Fabio Estevam
Stefano Babic - Dec. 14, 2011, 1:20 p.m.
On 13/12/2011 15:54, Veli-Pekka Peltola wrote:
> Add initial support for Bluegiga APX4 CoM and development kit.
> 
> Signed-off-by: Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
> Cc: Stefano Babic <sbabic@denx.de>
> ---

Hi Veli-Pekka,

>  board/bluegiga/apx4devkit/Makefile     |   45 +++++++
>  board/bluegiga/apx4devkit/apx4devkit.c |  204 ++++++++++++++++++++++++++++++++
>  boards.cfg                             |    1 +
>  include/configs/apx4devkit.h           |  176 +++++++++++++++++++++++++++

You should also update the MAINTAINERS file, adding your name as board
maintainer.

>  4 files changed, 426 insertions(+), 0 deletions(-)
>  create mode 100644 board/bluegiga/apx4devkit/Makefile
>  create mode 100644 board/bluegiga/apx4devkit/apx4devkit.c
>  create mode 100644 include/configs/apx4devkit.h
> 

your board configuration file does not set any SPL constant. I cannot
understand how it works. Only u-boot.bin can be built, and this is only
a part of the system. What about the first boot loader (SPL) ?

Please add also in the commit message which components (Ethernet, MMC,
I2C, SPI,...) you support with your patch.

> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define MUX_CONFIG_GENERIC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
> +#define MUX_CONFIG_GPMI	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
> +#define MUX_CONFIG_GPMI_12MA	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
> +
> +const iomux_cfg_t iomux_setup[] = {
> +	/* GPMI NAND */
> +	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
> +	MX28_PAD_GPMI_RDN__GPMI_RDN | MUX_CONFIG_GPMI_12MA,
> +	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI_12MA,
> +	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI_12MA,
> +
> +	/* MMC0 */
> +	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_GENERIC,
> +	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
> +		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_NOPULL),
> +	MX28_PAD_SSP0_SCK__SSP0_SCK |
> +		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
> +
> +	/* FEC Ethernet */
> +	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_GENERIC,
> +	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_GENERIC,
> +};
> +
> +/*
> + * Functions
> + */
> +int board_early_init_f(void)
> +{
> +	/* Setup only pads needed by U-Boot that are not initialized before */
> +	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));

Mmmhh..die Pins are setup in the SPL code, checks in
arch/arm/cpu/arm926ejs/mx28/spl_boot.c.

You are adding a lot of pins that are maybe duplicated, are'nt they ?

> +#ifdef CONFIG_CMD_NET
> +
> +#define MII_PHY_CTRL2	0x1f
> +
> +int fecmxc_mii_postcall(int phy)
> +{
> +	miiphy_write("FEC", 0, MII_PHY_CTRL2, 0x8180);
> +	return 0;
> +}

So you have only one ethernet interface - add also this info in your
commit message.

> +void imx_get_mac_from_fuse(char *mac)
> +{
> +	memset(mac, 0, 6);
> +}

This is wrong, and surely you do not get the address from fuses.

> +#ifdef CONFIG_SERIAL_TAG
> +#define MXS_OCOTP_MAX_TIMEOUT	1000000
> +void get_board_serial(struct tag_serialnr *serialnr)
> +{
> +	struct mx28_ocotp_regs *ocotp_regs =
> +		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
> +
> +	serialnr->high = 0;
> +	serialnr->low = 0;
> +
> +	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
> +
> +	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
> +				MXS_OCOTP_MAX_TIMEOUT)) {
> +		printf("MXS: Can't get serial number from OCOTP\n");
> +		return;
> +	}

I think we can factorize some code with m28evk, and putting code to
access OCOTP in a common directory, such as arch/arm/cpu/arm926ejs/mx28.

> +#ifdef CONFIG_REVISION_TAG
> +u32 get_board_rev(void)
> +{
> +	if (getenv("revision#") != NULL)
> +		return simple_strtoul(getenv("revision#"), NULL, 10);
> +	return 0;
> +}

Do you get the revision from an environment and not from hardware ?
There is a big chance to have the wrong revision number...

> +/* Environment is in NAND */
> +#define CONFIG_ENV_IS_IN_NAND
> +#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
> +#define CONFIG_ENV_SIZE		(128 * 1024)
> +#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
> +#define CONFIG_ENV_OFFSET		0x120000
> +#define CONFIG_ENV_OFFSET_REDUND	\
> +		(CONFIG_ENV_OFFSET + CONFIG_ENV_SECT_SIZE)

You set the environment in NAND, but you reserve only one sector for
each of the two copies. If the single sector becomes bad, you lose the
redundancy. Should you not have more as one sector for the environment ?

Best regards,
Stefano Babic
Veli-Pekka Peltola - Dec. 14, 2011, 2:27 p.m.
Hi Stefano,

Thanks for your review. Please see my comments below.

On 12/14/2011 03:20 PM, Stefano Babic wrote:
> On 13/12/2011 15:54, Veli-Pekka Peltola wrote:
>> Add initial support for Bluegiga APX4 CoM and development kit.
>>
>> Signed-off-by: Veli-Pekka Peltola<veli-pekka.peltola@bluegiga.com>
>> Cc: Stefano Babic<sbabic@denx.de>
>> ---
>
> Hi Veli-Pekka,
>
>>   board/bluegiga/apx4devkit/Makefile     |   45 +++++++
>>   board/bluegiga/apx4devkit/apx4devkit.c |  204 ++++++++++++++++++++++++++++++++
>>   boards.cfg                             |    1 +
>>   include/configs/apx4devkit.h           |  176 +++++++++++++++++++++++++++
>
> You should also update the MAINTAINERS file, adding your name as board
> maintainer.

Will be added to v2.

>>   4 files changed, 426 insertions(+), 0 deletions(-)
>>   create mode 100644 board/bluegiga/apx4devkit/Makefile
>>   create mode 100644 board/bluegiga/apx4devkit/apx4devkit.c
>>   create mode 100644 include/configs/apx4devkit.h
>>
>
> your board configuration file does not set any SPL constant. I cannot
> understand how it works. Only u-boot.bin can be built, and this is only
> a part of the system. What about the first boot loader (SPL) ?

Currently we are using a different strategy to load U-Boot from NAND 
than M28EVK for example. We have very small U-Boot placed to first 
sector in NAND to load this bigger version of U-Boot.

But now I understand that our way is far away from optimal so this will 
be reworked in v2.

> Please add also in the commit message which components (Ethernet, MMC,
> I2C, SPI,...) you support with your patch.

Will be added to v2 commit message.

>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define MUX_CONFIG_GENERIC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
>> +#define MUX_CONFIG_GPMI	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
>> +#define MUX_CONFIG_GPMI_12MA	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
>> +
>> +const iomux_cfg_t iomux_setup[] = {
>> +	/* GPMI NAND */
>> +	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
>> +	MX28_PAD_GPMI_RDN__GPMI_RDN | MUX_CONFIG_GPMI_12MA,
>> +	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI_12MA,
>> +	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI_12MA,
>> +
>> +	/* MMC0 */
>> +	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
>> +		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_NOPULL),
>> +	MX28_PAD_SSP0_SCK__SSP0_SCK |
>> +		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
>> +
>> +	/* FEC Ethernet */
>> +	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_GENERIC,
>> +	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_GENERIC,
>> +};
>> +
>> +/*
>> + * Functions
>> + */
>> +int board_early_init_f(void)
>> +{
>> +	/* Setup only pads needed by U-Boot that are not initialized before */
>> +	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
>
> Mmmhh..die Pins are setup in the SPL code, checks in
> arch/arm/cpu/arm926ejs/mx28/spl_boot.c.
>
> You are adding a lot of pins that are maybe duplicated, are'nt they ?

After we switch to SPL, these will be moved/removed.

>> +#ifdef CONFIG_CMD_NET
>> +
>> +#define MII_PHY_CTRL2	0x1f
>> +
>> +int fecmxc_mii_postcall(int phy)
>> +{
>> +	miiphy_write("FEC", 0, MII_PHY_CTRL2, 0x8180);
>> +	return 0;
>> +}
>
> So you have only one ethernet interface - add also this info in your
> commit message.

Ok. I will also add a comment here why this is needed.

>> +void imx_get_mac_from_fuse(char *mac)
>> +{
>> +	memset(mac, 0, 6);
>> +}
>
> This is wrong, and surely you do not get the address from fuses.

What is correct way to get ethernet mac from environment instead of 
fuses? FEC driver seems to call imx_get_mac_from_fuse always. Should it 
be changed to use a new configuration option? Or should we try to read 
mac from fuses which are zeros and then fall back to environment?

>> +#ifdef CONFIG_SERIAL_TAG
>> +#define MXS_OCOTP_MAX_TIMEOUT	1000000
>> +void get_board_serial(struct tag_serialnr *serialnr)
>> +{
>> +	struct mx28_ocotp_regs *ocotp_regs =
>> +		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
>> +
>> +	serialnr->high = 0;
>> +	serialnr->low = 0;
>> +
>> +	writel(OCOTP_CTRL_RD_BANK_OPEN,&ocotp_regs->hw_ocotp_ctrl_set);
>> +
>> +	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
>> +				MXS_OCOTP_MAX_TIMEOUT)) {
>> +		printf("MXS: Can't get serial number from OCOTP\n");
>> +		return;
>> +	}
>
> I think we can factorize some code with m28evk, and putting code to
> access OCOTP in a common directory, such as arch/arm/cpu/arm926ejs/mx28.

Sounds like a good idea. I will do that.

>> +#ifdef CONFIG_REVISION_TAG
>> +u32 get_board_rev(void)
>> +{
>> +	if (getenv("revision#") != NULL)
>> +		return simple_strtoul(getenv("revision#"), NULL, 10);
>> +	return 0;
>> +}
>
> Do you get the revision from an environment and not from hardware ?

Yes, that's the plan. In the history we have used revision number to 
include information about integrated modem, wifi and so on.

> There is a big chance to have the wrong revision number...

Yes but even with empty environment the board will still boot up.

>> +/* Environment is in NAND */
>> +#define CONFIG_ENV_IS_IN_NAND
>> +#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
>> +#define CONFIG_ENV_SIZE		(128 * 1024)
>> +#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
>> +#define CONFIG_ENV_OFFSET		0x120000
>> +#define CONFIG_ENV_OFFSET_REDUND	\
>> +		(CONFIG_ENV_OFFSET + CONFIG_ENV_SECT_SIZE)
>
> You set the environment in NAND, but you reserve only one sector for
> each of the two copies. If the single sector becomes bad, you lose the
> redundancy. Should you not have more as one sector for the environment ?

Statistically this has not been a problem so far. But I see the risk and 
I will increase environment size a little bit.

> Best regards,
> Stefano Babic

--
Veli-Pekka Peltola
Stefano Babic - Dec. 14, 2011, 3:04 p.m.
On 14/12/2011 15:27, Veli-Pekka Peltola wrote:
> 
> But now I understand that our way is far away from optimal so this will
> be reworked in v2.
> 

In this way you can also profit of the work already done in the SPL code.

>>> +void imx_get_mac_from_fuse(char *mac)
>>> +{
>>> +    memset(mac, 0, 6);
>>> +}
>>
>> This is wrong, and surely you do not get the address from fuses.
> 
> What is correct way to get ethernet mac from environment instead of
> fuses? FEC driver seems to call imx_get_mac_from_fuse always. Should it
> be changed to use a new configuration option? Or should we try to read
> mac from fuses which are zeros and then fall back to environment?

I have supposed that new Freescale's SOCs are always delivered with a
valid MAC address in the fuses. Some IMX SOCs have no fuse at all, and
the MAC address is only taken from the environment, such as the MX35.

I see here a couple of points. First at all, imx_get_mac_from_fuse
should be factorized between your board and m28evk. Maybe we need some
CONFIG_ to add the vendor part, but reading from fuse itself can be
shared code. and if the values read are all zeroes, we have the fallback
to the environment ethaddr variable.

>>
>> Do you get the revision from an environment and not from hardware ?
> 
> Yes, that's the plan. In the history we have used revision number to
> include information about integrated modem, wifi and so on.
> 
>> There is a big chance to have the wrong revision number...
> 
> Yes but even with empty environment the board will still boot up.

Of course, until you do not do something different in code based on the
revision number, such as setting the MUX differently or putting the gpio
in a different mode...if you only print the revision number, there is no
issue.

>> You set the environment in NAND, but you reserve only one sector for
>> each of the two copies. If the single sector becomes bad, you lose the
>> redundancy. Should you not have more as one sector for the environment ?
> 
> Statistically this has not been a problem so far.

There is no rule - nothing happens until the sector becomes bad. Then
the redundancy feature is not available anymore. It depends on you to
check the risk and decide to increase the size or not.

Best regards,
Stefano Babic
Veli-Pekka Peltola - Dec. 14, 2011, 3:39 p.m.
On 12/14/2011 05:04 PM, Stefano Babic wrote:
>>>> +void imx_get_mac_from_fuse(char *mac)
>>>> +{
>>>> +    memset(mac, 0, 6);
>>>> +}
>>>
>>> This is wrong, and surely you do not get the address from fuses.
>>
>> What is correct way to get ethernet mac from environment instead of
>> fuses? FEC driver seems to call imx_get_mac_from_fuse always. Should it
>> be changed to use a new configuration option? Or should we try to read
>> mac from fuses which are zeros and then fall back to environment?
>
> I have supposed that new Freescale's SOCs are always delivered with a
> valid MAC address in the fuses. Some IMX SOCs have no fuse at all, and
> the MAC address is only taken from the environment, such as the MX35.

At least our i.MX28 SoCs doesn't have any fuses preprogrammed. MX28EVK 
seems to have CUST0 and CUST1 preprogrammed.

> I see here a couple of points. First at all, imx_get_mac_from_fuse
> should be factorized between your board and m28evk. Maybe we need some
> CONFIG_ to add the vendor part, but reading from fuse itself can be
> shared code. and if the values read are all zeroes, we have the fallback
> to the environment ethaddr variable.

I will try to do some factorization.

Our product is more like an OEM thing so we try to avoid programming any 
fuses as our customers might want to do that with their own mac address.

--
Veli-Pekka Peltola

Patch

diff --git a/board/bluegiga/apx4devkit/Makefile b/board/bluegiga/apx4devkit/Makefile
new file mode 100644
index 0000000..4fec2f0
--- /dev/null
+++ b/board/bluegiga/apx4devkit/Makefile
@@ -0,0 +1,45 @@ 
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= apx4devkit.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+all:	$(ALL)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/bluegiga/apx4devkit/apx4devkit.c b/board/bluegiga/apx4devkit/apx4devkit.c
new file mode 100644
index 0000000..ef9e039
--- /dev/null
+++ b/board/bluegiga/apx4devkit/apx4devkit.c
@@ -0,0 +1,204 @@ 
+/*
+ * Bluegiga APX4 development kit
+ *
+ * Copyright (C) 2011 Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
+ *
+ * Based on m28evk.c and spl_boot.c:
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/mii.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MUX_CONFIG_GENERIC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
+#define MUX_CONFIG_GPMI	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define MUX_CONFIG_GPMI_12MA	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
+
+const iomux_cfg_t iomux_setup[] = {
+	/* GPMI NAND */
+	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDN__GPMI_RDN | MUX_CONFIG_GPMI_12MA,
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI_12MA,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI_12MA,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_GENERIC,
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+
+	/* FEC Ethernet */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_GENERIC,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_GENERIC,
+};
+
+/*
+ * Functions
+ */
+int board_early_init_f(void)
+{
+	/* Setup only pads needed by U-Boot that are not initialized before */
+	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
+	/* IO0 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK0, 480000);
+	/* IO1 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK1, 480000);
+	/* SSP0 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+
+	return 0;
+}
+
+#ifdef CONFIG_CMD_MMC
+int board_mmc_init(bd_t *bis)
+{
+	return mxsmmc_initialize(bis, 0, NULL);
+}
+#endif
+
+#ifdef CONFIG_CMD_NET
+
+#define MII_PHY_CTRL2	0x1f
+
+int fecmxc_mii_postcall(int phy)
+{
+	miiphy_write("FEC", 0, MII_PHY_CTRL2, 0x8180);
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	int ret;
+	struct eth_device *dev;
+
+	ret = cpu_eth_init(bis);
+
+	ret = fecmxc_initialize(bis);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC MII postcall\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+void imx_get_mac_from_fuse(char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+#ifdef CONFIG_SERIAL_TAG
+#define MXS_OCOTP_MAX_TIMEOUT	1000000
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+	struct mx28_ocotp_regs *ocotp_regs =
+		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
+
+	serialnr->high = 0;
+	serialnr->low = 0;
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS: Can't get serial number from OCOTP\n");
+		return;
+	}
+
+	serialnr->low = readl(&ocotp_regs->hw_ocotp_cust3);
+}
+#endif
+
+#ifdef CONFIG_REVISION_TAG
+u32 get_board_rev(void)
+{
+	if (getenv("revision#") != NULL)
+		return simple_strtoul(getenv("revision#"), NULL, 10);
+	return 0;
+}
+#endif
diff --git a/boards.cfg b/boards.cfg
index 1e5b3e0..214e22f 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -159,6 +159,7 @@  tx25                         arm         arm926ejs   tx25                karo
 zmx25                        arm         arm926ejs   zmx25               syteco         mx25
 imx27lite                    arm         arm926ejs   imx27lite           logicpd        mx27
 magnesium                    arm         arm926ejs   imx27lite           logicpd        mx27
+apx4devkit                   arm         arm926ejs   -                   bluegiga       mx28
 m28evk                       arm         arm926ejs   -                   denx           mx28
 nhk8815                      arm         arm926ejs   nhk8815             st             nomadik
 nhk8815_onenand              arm         arm926ejs   nhk8815             st             nomadik       nhk8815:BOOT_ONENAND
diff --git a/include/configs/apx4devkit.h b/include/configs/apx4devkit.h
new file mode 100644
index 0000000..9f731b7
--- /dev/null
+++ b/include/configs/apx4devkit.h
@@ -0,0 +1,176 @@ 
+/*
+ * Copyright (C) 2011 Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
+ *
+ * Based on m28evk.h:
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __CONFIG_APX4DEVKIT_H__
+#define __CONFIG_APX4DEVKIT_H__
+
+#include <asm/arch/regs-base.h>
+
+/* SoC configuration */
+#define CONFIG_MX28				/* i.MX28 SoC */
+#define CONFIG_MXS_GPIO			/* GPIO control */
+#define CONFIG_SYS_HZ		1000		/* Ticks per second */
+
+/* Define APX4DEVKIT machine type by hand until mach-types gets updated */
+#define MACH_TYPE_APX4DEVKIT	3712
+#define CONFIG_MACH_TYPE	MACH_TYPE_APX4DEVKIT
+
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_SYS_ICACHE_OFF
+#define CONFIG_SYS_DCACHE_OFF
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_CPU_INIT
+
+/* U-Boot Commands */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_USB
+
+/* Memory configuration */
+#define CONFIG_NR_DRAM_BANKS		1		/* 1 bank of DRAM */
+#define PHYS_SDRAM_1			0x40000000	/* Base address */
+#define PHYS_SDRAM_1_SIZE		0x04000000	/* 64 MB */
+#define CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
+#define CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+#define CONFIG_SYS_INIT_SP_ADDR	0x00002000
+#define CONFIG_SYS_TEXT_BASE		0x40000100
+
+/* U-Boot general configuration */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_PROMPT	"=> "
+#define CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define CONFIG_VERSION_VARIABLE		/* U-BOOT version */
+#define CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define CONFIG_CMDLINE_EDITING			/* Command history etc. */
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+
+/* Serial Port */
+#define CONFIG_PL011_SERIAL
+#define CONFIG_PL011_CLOCK		24000000
+#define CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define CONFIG_CONS_INDEX		0
+#define CONFIG_BAUDRATE		115200	/* Default baud rate */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/* MMC */
+#ifdef CONFIG_CMD_MMC
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXS_MMC
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#endif
+
+/* NAND */
+#define CONFIG_NAND_MXS
+#define CONFIG_APBH_DMA
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0x60000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define NAND_MAX_CHIPS			1
+
+/* Environment is in NAND */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define CONFIG_ENV_SIZE		(128 * 1024)
+#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define CONFIG_ENV_OFFSET		0x120000
+#define CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_SECT_SIZE)
+
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_RBTREE
+#define CONFIG_LZO
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define MTDIDS_DEFAULT		"nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT			\
+	"mtdparts=gpmi-nand:"			\
+		"128k(bootstrap),"		\
+		"1m(boot),"			\
+		"256k(env),"			\
+		"-(root)\0"
+
+/* Ethernet (FEC) */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_FEC_MXC
+#define CONFIG_FEC_MXC_PHYADDR	0
+#define IMX_FEC_BASE		MXS_ENET0_BASE
+#define CONFIG_MII
+#define CONFIG_FEC_XCV_TYPE	RMII
+#endif
+
+/* USB */
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MXS
+#define CONFIG_EHCI_MXS_PORT	1
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
+#endif
+
+/* Linux */
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_SERIAL_TAG
+#define CONFIG_REVISION_TAG
+#define CONFIG_BOOTDELAY		1
+#define CONFIG_BOOTFILE		"uImage-apx4devkit.bin"
+#define CONFIG_BOOTARGS		\
+	"console=tty0 console=ttyAMA0,115200 lpj=1130496"
+#define CONFIG_BOOTCOMMAND		"run bootcmd_mmc"
+#define CONFIG_LOADADDR		0x42000000
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+	"mtdparts=" MTDPARTS_DEFAULT \
+	"bootcmd_nand=" \
+		"ubi part root 2048 && " \
+		"ubifsmount rootfs && ubifsload ${loadaddr} boot/kernel && " \
+		"set bootargs ${bootargs} ${mtdparts} ubi.mtd=3 " \
+		"root=ubi0:rootfs rootfstype=ubifs && bootm\0" \
+	"bootcmd_mmc=" \
+		"mmc rescan && " \
+		"ext2load mmc 0:2 ${loadaddr} boot/kernel && " \
+		"set bootargs ${bootargs} ${mtdparts} root=/dev/mmcblk0p2 " \
+		"rootwait && bootm\0"
+
+#endif /* __CONFIG_APX4DEVKIT_H__ */