Message ID | 1297379530-23487-13-git-send-email-michael@walle.cc |
---|---|
State | New |
Headers | show |
On Fri, Feb 11, 2011 at 1:12 AM, Michael Walle <michael@walle.cc> wrote: > This patch adds helper functions to create a ROM, which contains a hardware > description of a board. This is used in Theobromas LM32 Linux port. > > Signed-off-by: Michael Walle <michael@walle.cc> > --- > hw/lm32_hwsetup.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 172 insertions(+), 0 deletions(-) > create mode 100644 hw/lm32_hwsetup.h > > diff --git a/hw/lm32_hwsetup.h b/hw/lm32_hwsetup.h > new file mode 100644 > index 0000000..c7d4e05 > --- /dev/null > +++ b/hw/lm32_hwsetup.h > @@ -0,0 +1,172 @@ > +/* > + * LatticeMico32 hwsetup helper functions. > + * > + * Copyright (c) 2010 Michael Walle <michael@walle.cc> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +/* > + * These are helper functions for creating the hardware description blob used > + * in the Theobroma's uClinux port. > + */ Please add #ifndef QEMU_HW_LM32_HWSETUP_H etc. > + > +#include "qemu-common.h" > +#include "loader.h" > + > +struct hwsetup { > + void *data; > + void *ptr; > +}; HWSetup, with typedef. > + > +enum hwsetup_tag { > + HWSETUP_TAG_EOL = 0, > + HWSETUP_TAG_CPU = 1, > + HWSETUP_TAG_ASRAM = 2, > + HWSETUP_TAG_FLASH = 3, > + HWSETUP_TAG_SDRAM = 4, > + HWSETUP_TAG_OCM = 5, > + HWSETUP_TAG_DDR_SDRAM = 6, > + HWSETUP_TAG_DDR2_SDRAM = 7, > + HWSETUP_TAG_TIMER = 8, > + HWSETUP_TAG_UART = 9, > + HWSETUP_TAG_GPIO = 10, > + HWSETUP_TAG_TRISPEEDMAC = 11, > + HWSETUP_TAG_I2CM = 12, > + HWSETUP_TAG_LEDS = 13, > + HWSETUP_TAG_7SEG = 14, > + HWSETUP_TAG_SPI_S = 15, > + HWSETUP_TAG_SPI_M = 16, > +}; > + > +static inline struct hwsetup *hwsetup_init(void) > +{ > + struct hwsetup *hw; > + > + hw = qemu_malloc(sizeof(struct hwsetup)); > + hw->data = qemu_mallocz(TARGET_PAGE_SIZE); > + hw->ptr = hw->data; > + > + return hw; > +} > + > +static inline void hwsetup_free(struct hwsetup *hw) > +{ > + qemu_free(hw->data); > + qemu_free(hw); > +} > + > +static inline void hwsetup_create_rom(struct hwsetup *hw, ram_addr_t base) > +{ > + rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base); > +} > + > +static inline void hwsetup_add_u8(struct hwsetup *hw, uint8_t u) > +{ > + stb_p(hw->ptr, u); > + hw->ptr += 1; > +} > + > +static inline void hwsetup_add_u32(struct hwsetup *hw, uint32_t u) > +{ > + stl_p(hw->ptr, u); > + hw->ptr += 4; > +} > + > +static inline void hwsetup_add_tag(struct hwsetup *hw, enum hwsetup_tag t) > +{ > + stl_p(hw->ptr, t); > + hw->ptr += 4; > +} > + > +static inline void hwsetup_add_str(struct hwsetup *hw, const char *str) > +{ > + strncpy(hw->ptr, str, 31); /* make sure last byte is zero */ > + hw->ptr += 32; > +} > + > +static inline void hwsetup_add_trailer(struct hwsetup *hw) > +{ > + hwsetup_add_u32(hw, 8); /* size */ > + hwsetup_add_tag(hw, HWSETUP_TAG_EOL); > +} > + > +static inline void hwsetup_add_cpu(struct hwsetup *hw, > + const char *name, uint32_t frequency) > +{ > + hwsetup_add_u32(hw, 44); /* size */ > + hwsetup_add_tag(hw, HWSETUP_TAG_CPU); > + hwsetup_add_str(hw, name); > + hwsetup_add_u32(hw, frequency); > +} > + > +static inline void hwsetup_add_flash(struct hwsetup *hw, > + const char *name, uint32_t base, uint32_t size) > +{ > + hwsetup_add_u32(hw, 52); /* size */ > + hwsetup_add_tag(hw, HWSETUP_TAG_FLASH); > + hwsetup_add_str(hw, name); > + hwsetup_add_u32(hw, base); > + hwsetup_add_u32(hw, size); > + hwsetup_add_u8(hw, 8); /* read latency */ > + hwsetup_add_u8(hw, 8); /* write latency */ > + hwsetup_add_u8(hw, 25); /* address width */ > + hwsetup_add_u8(hw, 32); /* data width */ > +} > + > +static inline void hwsetup_add_ddr_sdram(struct hwsetup *hw, > + const char *name, uint32_t base, uint32_t size) > +{ > + hwsetup_add_u32(hw, 48); /* size */ > + hwsetup_add_tag(hw, HWSETUP_TAG_DDR_SDRAM); > + hwsetup_add_str(hw, name); > + hwsetup_add_u32(hw, base); > + hwsetup_add_u32(hw, size); > +} > + > +static inline void hwsetup_add_timer(struct hwsetup *hw, > + const char *name, uint32_t base, uint32_t irq) > +{ > + hwsetup_add_u32(hw, 56); /* size */ > + hwsetup_add_tag(hw, HWSETUP_TAG_TIMER); > + hwsetup_add_str(hw, name); > + hwsetup_add_u32(hw, base); > + hwsetup_add_u8(hw, 1); /* wr_tickcount */ > + hwsetup_add_u8(hw, 1); /* rd_tickcount */ > + hwsetup_add_u8(hw, 1); /* start_stop_control */ > + hwsetup_add_u8(hw, 32); /* counter_width */ > + hwsetup_add_u32(hw, 20); /* reload_ticks */ > + hwsetup_add_u8(hw, irq); > + hwsetup_add_u8(hw, 0); /* padding */ > + hwsetup_add_u8(hw, 0); /* padding */ > + hwsetup_add_u8(hw, 0); /* padding */ > +} > + > +static inline void hwsetup_add_uart(struct hwsetup *hw, > + const char *name, uint32_t base, uint32_t irq) > +{ > + hwsetup_add_u32(hw, 56); /* size */ > + hwsetup_add_tag(hw, HWSETUP_TAG_UART); > + hwsetup_add_str(hw, name); > + hwsetup_add_u32(hw, base); > + hwsetup_add_u32(hw, 115200); /* baudrate */ > + hwsetup_add_u8(hw, 8); /* databits */ > + hwsetup_add_u8(hw, 1); /* stopbits */ > + hwsetup_add_u8(hw, 1); /* use_interrupt */ > + hwsetup_add_u8(hw, 1); /* block_on_transmit */ > + hwsetup_add_u8(hw, 1); /* block_on_receive */ > + hwsetup_add_u8(hw, 4); /* rx_buffer_size */ > + hwsetup_add_u8(hw, 4); /* tx_buffer_size */ > + hwsetup_add_u8(hw, irq); > +} Overall, this seems to replicate fw_cfg functions, does it match real HW or is this just for QEMU?
Am Freitag 11 Februar 2011, 21:52:17 schrieb Blue Swirl: > > +static inline void hwsetup_add_uart(struct hwsetup *hw, > > + const char *name, uint32_t base, uint32_t irq) > > +{ > > + hwsetup_add_u32(hw, 56); /* size */ > > + hwsetup_add_tag(hw, HWSETUP_TAG_UART); > > + hwsetup_add_str(hw, name); > > + hwsetup_add_u32(hw, base); > > + hwsetup_add_u32(hw, 115200); /* baudrate */ > > + hwsetup_add_u8(hw, 8); /* databits */ > > + hwsetup_add_u8(hw, 1); /* stopbits */ > > + hwsetup_add_u8(hw, 1); /* use_interrupt */ > > + hwsetup_add_u8(hw, 1); /* block_on_transmit */ > > + hwsetup_add_u8(hw, 1); /* block_on_receive */ > > + hwsetup_add_u8(hw, 4); /* rx_buffer_size */ > > + hwsetup_add_u8(hw, 4); /* tx_buffer_size */ > > + hwsetup_add_u8(hw, irq); > > +} > > Overall, this seems to replicate fw_cfg functions, does it match real > HW or is this just for QEMU? It is some kind of (proprietary) device tree for the linux port done by Theobroma Systems. Maybe i should drop support for it and concentrate only on the non-linux BSP and on the milkymist platform...
On Sat, Feb 12, 2011 at 12:40 AM, Michael Walle <michael@walle.cc> wrote: > Am Freitag 11 Februar 2011, 21:52:17 schrieb Blue Swirl: >> > +static inline void hwsetup_add_uart(struct hwsetup *hw, >> > + const char *name, uint32_t base, uint32_t irq) >> > +{ >> > + hwsetup_add_u32(hw, 56); /* size */ >> > + hwsetup_add_tag(hw, HWSETUP_TAG_UART); >> > + hwsetup_add_str(hw, name); >> > + hwsetup_add_u32(hw, base); >> > + hwsetup_add_u32(hw, 115200); /* baudrate */ >> > + hwsetup_add_u8(hw, 8); /* databits */ >> > + hwsetup_add_u8(hw, 1); /* stopbits */ >> > + hwsetup_add_u8(hw, 1); /* use_interrupt */ >> > + hwsetup_add_u8(hw, 1); /* block_on_transmit */ >> > + hwsetup_add_u8(hw, 1); /* block_on_receive */ >> > + hwsetup_add_u8(hw, 4); /* rx_buffer_size */ >> > + hwsetup_add_u8(hw, 4); /* tx_buffer_size */ >> > + hwsetup_add_u8(hw, irq); >> > +} >> >> Overall, this seems to replicate fw_cfg functions, does it match real >> HW or is this just for QEMU? > > It is some kind of (proprietary) device tree for the linux port done by > Theobroma Systems. Maybe i should drop support for it and concentrate only on > the non-linux BSP and on the milkymist platform... No, it's OK then. I was just worried about reinventing the wheel.
diff --git a/hw/lm32_hwsetup.h b/hw/lm32_hwsetup.h new file mode 100644 index 0000000..c7d4e05 --- /dev/null +++ b/hw/lm32_hwsetup.h @@ -0,0 +1,172 @@ +/* + * LatticeMico32 hwsetup helper functions. + * + * Copyright (c) 2010 Michael Walle <michael@walle.cc> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +/* + * These are helper functions for creating the hardware description blob used + * in the Theobroma's uClinux port. + */ + +#include "qemu-common.h" +#include "loader.h" + +struct hwsetup { + void *data; + void *ptr; +}; + +enum hwsetup_tag { + HWSETUP_TAG_EOL = 0, + HWSETUP_TAG_CPU = 1, + HWSETUP_TAG_ASRAM = 2, + HWSETUP_TAG_FLASH = 3, + HWSETUP_TAG_SDRAM = 4, + HWSETUP_TAG_OCM = 5, + HWSETUP_TAG_DDR_SDRAM = 6, + HWSETUP_TAG_DDR2_SDRAM = 7, + HWSETUP_TAG_TIMER = 8, + HWSETUP_TAG_UART = 9, + HWSETUP_TAG_GPIO = 10, + HWSETUP_TAG_TRISPEEDMAC = 11, + HWSETUP_TAG_I2CM = 12, + HWSETUP_TAG_LEDS = 13, + HWSETUP_TAG_7SEG = 14, + HWSETUP_TAG_SPI_S = 15, + HWSETUP_TAG_SPI_M = 16, +}; + +static inline struct hwsetup *hwsetup_init(void) +{ + struct hwsetup *hw; + + hw = qemu_malloc(sizeof(struct hwsetup)); + hw->data = qemu_mallocz(TARGET_PAGE_SIZE); + hw->ptr = hw->data; + + return hw; +} + +static inline void hwsetup_free(struct hwsetup *hw) +{ + qemu_free(hw->data); + qemu_free(hw); +} + +static inline void hwsetup_create_rom(struct hwsetup *hw, ram_addr_t base) +{ + rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base); +} + +static inline void hwsetup_add_u8(struct hwsetup *hw, uint8_t u) +{ + stb_p(hw->ptr, u); + hw->ptr += 1; +} + +static inline void hwsetup_add_u32(struct hwsetup *hw, uint32_t u) +{ + stl_p(hw->ptr, u); + hw->ptr += 4; +} + +static inline void hwsetup_add_tag(struct hwsetup *hw, enum hwsetup_tag t) +{ + stl_p(hw->ptr, t); + hw->ptr += 4; +} + +static inline void hwsetup_add_str(struct hwsetup *hw, const char *str) +{ + strncpy(hw->ptr, str, 31); /* make sure last byte is zero */ + hw->ptr += 32; +} + +static inline void hwsetup_add_trailer(struct hwsetup *hw) +{ + hwsetup_add_u32(hw, 8); /* size */ + hwsetup_add_tag(hw, HWSETUP_TAG_EOL); +} + +static inline void hwsetup_add_cpu(struct hwsetup *hw, + const char *name, uint32_t frequency) +{ + hwsetup_add_u32(hw, 44); /* size */ + hwsetup_add_tag(hw, HWSETUP_TAG_CPU); + hwsetup_add_str(hw, name); + hwsetup_add_u32(hw, frequency); +} + +static inline void hwsetup_add_flash(struct hwsetup *hw, + const char *name, uint32_t base, uint32_t size) +{ + hwsetup_add_u32(hw, 52); /* size */ + hwsetup_add_tag(hw, HWSETUP_TAG_FLASH); + hwsetup_add_str(hw, name); + hwsetup_add_u32(hw, base); + hwsetup_add_u32(hw, size); + hwsetup_add_u8(hw, 8); /* read latency */ + hwsetup_add_u8(hw, 8); /* write latency */ + hwsetup_add_u8(hw, 25); /* address width */ + hwsetup_add_u8(hw, 32); /* data width */ +} + +static inline void hwsetup_add_ddr_sdram(struct hwsetup *hw, + const char *name, uint32_t base, uint32_t size) +{ + hwsetup_add_u32(hw, 48); /* size */ + hwsetup_add_tag(hw, HWSETUP_TAG_DDR_SDRAM); + hwsetup_add_str(hw, name); + hwsetup_add_u32(hw, base); + hwsetup_add_u32(hw, size); +} + +static inline void hwsetup_add_timer(struct hwsetup *hw, + const char *name, uint32_t base, uint32_t irq) +{ + hwsetup_add_u32(hw, 56); /* size */ + hwsetup_add_tag(hw, HWSETUP_TAG_TIMER); + hwsetup_add_str(hw, name); + hwsetup_add_u32(hw, base); + hwsetup_add_u8(hw, 1); /* wr_tickcount */ + hwsetup_add_u8(hw, 1); /* rd_tickcount */ + hwsetup_add_u8(hw, 1); /* start_stop_control */ + hwsetup_add_u8(hw, 32); /* counter_width */ + hwsetup_add_u32(hw, 20); /* reload_ticks */ + hwsetup_add_u8(hw, irq); + hwsetup_add_u8(hw, 0); /* padding */ + hwsetup_add_u8(hw, 0); /* padding */ + hwsetup_add_u8(hw, 0); /* padding */ +} + +static inline void hwsetup_add_uart(struct hwsetup *hw, + const char *name, uint32_t base, uint32_t irq) +{ + hwsetup_add_u32(hw, 56); /* size */ + hwsetup_add_tag(hw, HWSETUP_TAG_UART); + hwsetup_add_str(hw, name); + hwsetup_add_u32(hw, base); + hwsetup_add_u32(hw, 115200); /* baudrate */ + hwsetup_add_u8(hw, 8); /* databits */ + hwsetup_add_u8(hw, 1); /* stopbits */ + hwsetup_add_u8(hw, 1); /* use_interrupt */ + hwsetup_add_u8(hw, 1); /* block_on_transmit */ + hwsetup_add_u8(hw, 1); /* block_on_receive */ + hwsetup_add_u8(hw, 4); /* rx_buffer_size */ + hwsetup_add_u8(hw, 4); /* tx_buffer_size */ + hwsetup_add_u8(hw, irq); +}
This patch adds helper functions to create a ROM, which contains a hardware description of a board. This is used in Theobromas LM32 Linux port. Signed-off-by: Michael Walle <michael@walle.cc> --- hw/lm32_hwsetup.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 172 insertions(+), 0 deletions(-) create mode 100644 hw/lm32_hwsetup.h