diff mbox series

[rc4,24/29] hw/avr: Add some ATmega microcontrollers

Message ID 1580428993-4767-25-git-send-email-aleksandar.markovic@rt-rk.com (mailing list archive)
State New, archived
Headers show
Series target/avr merger | expand

Commit Message

Aleksandar Markovic Jan. 31, 2020, 12:03 a.m. UTC
From: Philippe Mathieu-Daudé <f4bug@amsat.org>

Add some AVR microcontrollers from the ATmega family:

  - middle range: ATmega168 and ATmega328
  - high range: ATmega1280 and ATmega2560

For product comparison:
  https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
  https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560

Datasheets:
  http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
  http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf

[AM: Remove word 'Atmel' from filenames and all elements of code]
Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
---
 hw/avr/Kconfig       |   5 +
 hw/avr/Makefile.objs |   1 +
 hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/avr/atmega.h      |  48 ++++++
 4 files changed, 524 insertions(+)
 create mode 100644 hw/avr/Kconfig
 create mode 100644 hw/avr/atmega.c
 create mode 100644 hw/avr/atmega.h

Comments

Aleksandar Markovic Jan. 31, 2020, 1:56 a.m. UTC | #1
On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
<aleksandar.markovic@rt-rk.com> wrote:
>
> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
>
> Add some AVR microcontrollers from the ATmega family:
>
>   - middle range: ATmega168 and ATmega328
>   - high range: ATmega1280 and ATmega2560
>
> For product comparison:
>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
>
> Datasheets:
>   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
>   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
>
> [AM: Remove word 'Atmel' from filenames and all elements of code]
> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
>
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> ---
>  hw/avr/Kconfig       |   5 +
>  hw/avr/Makefile.objs |   1 +
>  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/avr/atmega.h      |  48 ++++++
>  4 files changed, 524 insertions(+)
>  create mode 100644 hw/avr/Kconfig
>  create mode 100644 hw/avr/atmega.c
>  create mode 100644 hw/avr/atmega.h
>
> diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> new file mode 100644
> index 0000000..9e6527e
> --- /dev/null
> +++ b/hw/avr/Kconfig
> @@ -0,0 +1,5 @@
> +config AVR_ATMEGA_MCU
> +    bool
> +    select AVR_TIMER16
> +    select AVR_USART
> +    select AVR_POWER
> diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> index 123f174..af0fdde 100644
> --- a/hw/avr/Makefile.objs
> +++ b/hw/avr/Makefile.objs
> @@ -1 +1,2 @@
>  obj-y += boot.o
> +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> new file mode 100644
> index 0000000..8cdf28b
> --- /dev/null
> +++ b/hw/avr/atmega.c
> @@ -0,0 +1,470 @@
> +/*
> + * QEMU ATmega MCU
> + *
> + * Copyright (c) 2019 Philippe Mathieu-Daudé
> + *
> + * This work is licensed under the terms of the GNU GPLv2 or later.
> + * See the COPYING file in the top-level directory.
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */

Philippe,

Michael and I already agreed at some moment that the whole target AVR
should have harmonized licenses, and Sarrah agreed to change her
license to achieve this. Do you agree to harmonize your licenses with
the rest of the project? (This would mean changing the preable, but of
course you remain copyright carrier as is now.)

Thanks,
Aleksandar

> +
> +#include "qemu/osdep.h"
> +#include "qemu/module.h"
> +#include "qemu/units.h"
> +#include "qapi/error.h"
> +#include "exec/memory.h"
> +#include "exec/address-spaces.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/sysbus.h"
> +#include "hw/boards.h" /* FIXME memory_region_allocate_system_memory for sram */
> +#include "hw/misc/unimp.h"
> +#include "atmega.h"
> +
> +enum AtmegaPeripheral {
> +    POWER0, POWER1,
> +    GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF,
> +    GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL,
> +    USART0, USART1, USART2, USART3,
> +    TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5,
> +    PERIFMAX
> +};
> +
> +#define GPIO(n)     (n + GPIOA)
> +#define USART(n)    (n + USART0)
> +#define TIMER(n)    (n + TIMER0)
> +#define POWER(n)    (n + POWER0)
> +
> +typedef struct {
> +    uint16_t addr;
> +    enum AtmegaPeripheral power_index;
> +    uint8_t power_bit;
> +    /* timer specific */
> +    uint16_t intmask_addr;
> +    uint16_t intflag_addr;
> +    bool is_timer16;
> +} peripheral_cfg;
> +
> +typedef struct AtmegaMcuClass {
> +    /*< private >*/
> +    SysBusDeviceClass parent_class;
> +    /*< public >*/
> +    const char *uc_name;
> +    const char *cpu_type;
> +    size_t flash_size;
> +    size_t eeprom_size;
> +    size_t sram_size;
> +    size_t io_size;
> +    size_t gpio_count;
> +    size_t adc_count;
> +    const uint8_t *irq;
> +    const peripheral_cfg *dev;
> +} AtmegaMcuClass;
> +
> +#define ATMEGA_MCU_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(AtmegaMcuClass, (klass), TYPE_ATMEGA_MCU)
> +#define ATMEGA_MCU_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(AtmegaMcuClass, (obj), TYPE_ATMEGA_MCU)
> +
> +static const peripheral_cfg dev168_328[PERIFMAX] = {
> +    [USART0]        = {  0xc0, POWER0, 1 },
> +    [TIMER2]        = {  0xb0, POWER0, 6, 0x70, 0x37, false },
> +    [TIMER1]        = {  0x80, POWER0, 3, 0x6f, 0x36, true },
> +    [POWER0]        = {  0x64 },
> +    [TIMER0]        = {  0x44, POWER0, 5, 0x6e, 0x35, false },
> +    [GPIOD]         = {  0x29 },
> +    [GPIOC]         = {  0x26 },
> +    [GPIOB]         = {  0x23 },
> +}, dev1280_2560[PERIFMAX] = {
> +    [USART3]        = { 0x130, POWER1, 2 },
> +    [TIMER5]        = { 0x120, POWER1, 5, 0x73, 0x3a, true },
> +    [GPIOL]         = { 0x109 },
> +    [GPIOK]         = { 0x106 },
> +    [GPIOJ]         = { 0x103 },
> +    [GPIOH]         = { 0x100 },
> +    [USART2]        = {  0xd0, POWER1, 1 },
> +    [USART1]        = {  0xc8, POWER1, 0 },
> +    [USART0]        = {  0xc0, POWER0, 1 },
> +    [TIMER2]        = {  0xb0, POWER0, 6, 0x70, 0x37, false }, /* TODO async */
> +    [TIMER4]        = {  0xa0, POWER1, 4, 0x72, 0x39, true },
> +    [TIMER3]        = {  0x90, POWER1, 3, 0x71, 0x38, true },
> +    [TIMER1]        = {  0x80, POWER0, 3, 0x6f, 0x36, true },
> +    [POWER1]        = {  0x65 },
> +    [POWER0]        = {  0x64 },
> +    [TIMER0]        = {  0x44, POWER0, 5, 0x6e, 0x35, false },
> +    [GPIOG]         = {  0x32 },
> +    [GPIOF]         = {  0x2f },
> +    [GPIOE]         = {  0x2c },
> +    [GPIOD]         = {  0x29 },
> +    [GPIOC]         = {  0x26 },
> +    [GPIOB]         = {  0x23 },
> +    [GPIOA]         = {  0x20 },
> +};
> +
> +enum AtmegaIrq {
> +    USART0_RXC_IRQ, USART0_DRE_IRQ, USART0_TXC_IRQ,
> +    USART1_RXC_IRQ, USART1_DRE_IRQ, USART1_TXC_IRQ,
> +    USART2_RXC_IRQ, USART2_DRE_IRQ, USART2_TXC_IRQ,
> +    USART3_RXC_IRQ, USART3_DRE_IRQ, USART3_TXC_IRQ,
> +    TIMER0_CAPT_IRQ, TIMER0_COMPA_IRQ, TIMER0_COMPB_IRQ,
> +        TIMER0_COMPC_IRQ, TIMER0_OVF_IRQ,
> +    TIMER1_CAPT_IRQ, TIMER1_COMPA_IRQ, TIMER1_COMPB_IRQ,
> +        TIMER1_COMPC_IRQ, TIMER1_OVF_IRQ,
> +    TIMER2_CAPT_IRQ, TIMER2_COMPA_IRQ, TIMER2_COMPB_IRQ,
> +        TIMER2_COMPC_IRQ, TIMER2_OVF_IRQ,
> +    TIMER3_CAPT_IRQ, TIMER3_COMPA_IRQ, TIMER3_COMPB_IRQ,
> +        TIMER3_COMPC_IRQ, TIMER3_OVF_IRQ,
> +    TIMER4_CAPT_IRQ, TIMER4_COMPA_IRQ, TIMER4_COMPB_IRQ,
> +        TIMER4_COMPC_IRQ, TIMER4_OVF_IRQ,
> +    TIMER5_CAPT_IRQ, TIMER5_COMPA_IRQ, TIMER5_COMPB_IRQ,
> +        TIMER5_COMPC_IRQ, TIMER5_OVF_IRQ,
> +    IRQ_COUNT
> +};
> +
> +#define USART_IRQ_COUNT     3
> +#define USART_RXC_IRQ(n)    (n * USART_IRQ_COUNT + USART0_RXC_IRQ)
> +#define USART_DRE_IRQ(n)    (n * USART_IRQ_COUNT + USART0_DRE_IRQ)
> +#define USART_TXC_IRQ(n)    (n * USART_IRQ_COUNT + USART0_TXC_IRQ)
> +#define TIMER_IRQ_COUNT     5
> +#define TIMER_CAPT_IRQ(n)   (n * TIMER_IRQ_COUNT + TIMER0_CAPT_IRQ)
> +#define TIMER_COMPA_IRQ(n)  (n * TIMER_IRQ_COUNT + TIMER0_COMPA_IRQ)
> +#define TIMER_COMPB_IRQ(n)  (n * TIMER_IRQ_COUNT + TIMER0_COMPB_IRQ)
> +#define TIMER_COMPC_IRQ(n)  (n * TIMER_IRQ_COUNT + TIMER0_COMPC_IRQ)
> +#define TIMER_OVF_IRQ(n)    (n * TIMER_IRQ_COUNT + TIMER0_OVF_IRQ)
> +
> +static const uint8_t irq168_328[IRQ_COUNT] = {
> +    [TIMER2_COMPA_IRQ]      = 8,
> +    [TIMER2_COMPB_IRQ]      = 9,
> +    [TIMER2_OVF_IRQ]        = 10,
> +    [TIMER1_CAPT_IRQ]       = 11,
> +    [TIMER1_COMPA_IRQ]      = 12,
> +    [TIMER1_COMPB_IRQ]      = 13,
> +    [TIMER1_OVF_IRQ]        = 14,
> +    [TIMER0_COMPA_IRQ]      = 15,
> +    [TIMER0_COMPB_IRQ]      = 16,
> +    [TIMER0_OVF_IRQ]        = 17,
> +    [USART0_RXC_IRQ]        = 19,
> +    [USART0_DRE_IRQ]        = 20,
> +    [USART0_TXC_IRQ]        = 21,
> +}, irq1280_2560[IRQ_COUNT] = {
> +    [TIMER2_COMPA_IRQ]      = 14,
> +    [TIMER2_COMPB_IRQ]      = 15,
> +    [TIMER2_OVF_IRQ]        = 16,
> +    [TIMER1_CAPT_IRQ]       = 17,
> +    [TIMER1_COMPA_IRQ]      = 18,
> +    [TIMER1_COMPB_IRQ]      = 19,
> +    [TIMER1_COMPC_IRQ]      = 20,
> +    [TIMER1_OVF_IRQ]        = 21,
> +    [TIMER0_COMPA_IRQ]      = 22,
> +    [TIMER0_COMPB_IRQ]      = 23,
> +    [TIMER0_OVF_IRQ]        = 24,
> +    [USART0_RXC_IRQ]        = 26,
> +    [USART0_DRE_IRQ]        = 27,
> +    [USART0_TXC_IRQ]        = 28,
> +    [TIMER3_CAPT_IRQ]       = 32,
> +    [TIMER3_COMPA_IRQ]      = 33,
> +    [TIMER3_COMPB_IRQ]      = 34,
> +    [TIMER3_COMPC_IRQ]      = 35,
> +    [TIMER3_OVF_IRQ]        = 36,
> +    [USART1_RXC_IRQ]        = 37,
> +    [USART1_DRE_IRQ]        = 38,
> +    [USART1_TXC_IRQ]        = 39,
> +    [TIMER4_CAPT_IRQ]       = 42,
> +    [TIMER4_COMPA_IRQ]      = 43,
> +    [TIMER4_COMPB_IRQ]      = 44,
> +    [TIMER4_COMPC_IRQ]      = 45,
> +    [TIMER4_OVF_IRQ]        = 46,
> +    [TIMER5_CAPT_IRQ]       = 47,
> +    [TIMER5_COMPA_IRQ]      = 48,
> +    [TIMER5_COMPB_IRQ]      = 49,
> +    [TIMER5_COMPC_IRQ]      = 50,
> +    [TIMER5_OVF_IRQ]        = 51,
> +    [USART2_RXC_IRQ]        = 52,
> +    [USART2_DRE_IRQ]        = 53,
> +    [USART2_TXC_IRQ]        = 54,
> +    [USART3_RXC_IRQ]        = 55,
> +    [USART3_DRE_IRQ]        = 56,
> +    [USART3_TXC_IRQ]        = 57,
> +};
> +
> +static void connect_peripheral_irq(const AtmegaMcuClass *mc,
> +                                   SysBusDevice *sbd,
> +                                   DeviceState *dev, int n,
> +                                   unsigned peripheral_irq)
> +{
> +    int irq = mc->irq[peripheral_irq];
> +
> +    if (!irq) {
> +        return;
> +    }
> +    /* FIXME move that to avr_cpu_set_int() once 'sample' board is removed */
> +    assert(irq >= 2);
> +    irq -= 2;
> +
> +    sysbus_connect_irq(sbd, n, qdev_get_gpio_in(dev, irq));
> +}
> +
> +static void connect_power_reduction_gpio(AtmegaMcuState *s,
> +                                         const AtmegaMcuClass *mc,
> +                                         DeviceState *dev,
> +                                         int peripheral_index)
> +{
> +    unsigned power_index = mc->dev[peripheral_index].power_index;
> +    assert(mc->dev[power_index].addr);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwr[power_index - POWER0]),
> +                       mc->dev[peripheral_index].power_bit,
> +                       qdev_get_gpio_in(dev, 0));
> +}
> +
> +static void atmega_realize(DeviceState *dev, Error **errp)
> +{
> +    AtmegaMcuState *s = ATMEGA_MCU(dev);
> +    const AtmegaMcuClass *mc = ATMEGA_MCU_GET_CLASS(dev);
> +    DeviceState *cpudev;
> +    SysBusDevice *sbd;
> +    Error *err = NULL;
> +    char *devname;
> +    size_t i;
> +
> +    assert(mc->io_size <= 0x200);
> +
> +    if (!s->xtal_freq_hz) {
> +        error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
> +        return;
> +    }
> +
> +    /* CPU */
> +    object_initialize_child(OBJECT(dev), "cpu", &s->cpu, sizeof(s->cpu),
> +                            mc->cpu_type, &err, NULL);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &error_abort);
> +    cpudev = DEVICE(&s->cpu);
> +
> +    /* SRAM */
> +    memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size,
> +                           &error_abort);
> +    memory_region_add_subregion(get_system_memory(),
> +                                OFFSET_DATA + mc->io_size, &s->sram);
> +
> +    /* Flash */
> +    memory_region_init_rom(&s->flash, OBJECT(dev),
> +                           "flash", mc->flash_size, &error_fatal);
> +    memory_region_add_subregion(get_system_memory(), OFFSET_CODE, &s->flash);
> +
> +    /*
> +     * I/O
> +     *
> +     * 0x00 - 0x1f: Registers
> +     * 0x20 - 0x5f: I/O memory
> +     * 0x60 - 0xff: Extended I/O
> +     */
> +    s->io = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE);
> +    qdev_prop_set_string(s->io, "name", "I/O");
> +    qdev_prop_set_uint64(s->io, "size", mc->io_size);
> +    qdev_init_nofail(s->io);
> +    sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->io), 0, OFFSET_DATA, -1234);
> +
> +    /* Power Reduction */
> +    for (i = 0; i < POWER_MAX; i++) {
> +        int idx = POWER(i);
> +        if (!mc->dev[idx].addr) {
> +            continue;
> +        }
> +        devname = g_strdup_printf("power%zu", i);
> +        object_initialize_child(OBJECT(dev), devname,
> +                                &s->pwr[i], sizeof(s->pwr[i]),
> +                                TYPE_AVR_MASK, &error_abort, NULL);
> +        object_property_set_bool(OBJECT(&s->pwr[i]), true, "realized",
> +                                 &error_abort);
> +        sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwr[i]), 0,
> +                        OFFSET_DATA + mc->dev[idx].addr);
> +        g_free(devname);
> +    }
> +
> +    /* GPIO */
> +    for (i = 0; i < GPIO_MAX; i++) {
> +        int idx = GPIO(i);
> +        if (!mc->dev[idx].addr) {
> +            continue;
> +        }
> +        devname = g_strdup_printf("avr-gpio-%c", 'a' + (char)i);
> +        create_unimplemented_device(devname,
> +                                    OFFSET_DATA + mc->dev[idx].addr, 3);
> +        g_free(devname);
> +    }
> +
> +    /* USART */
> +    for (i = 0; i < USART_MAX; i++) {
> +        int idx = USART(i);
> +        if (!mc->dev[idx].addr) {
> +            continue;
> +        }
> +        devname = g_strdup_printf("usart%zu", i);
> +        object_initialize_child(OBJECT(dev), devname,
> +                                &s->usart[i], sizeof(s->usart[i]),
> +                                TYPE_AVR_USART, &error_abort, NULL);
> +        qdev_prop_set_chr(DEVICE(&s->usart[i]), "chardev", serial_hd(i));
> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized",
> +                                 &error_abort);
> +        sbd = SYS_BUS_DEVICE(&s->usart[i]);
> +        sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[USART(i)].addr);
> +        connect_peripheral_irq(mc, sbd, cpudev, 0, USART_RXC_IRQ(i));
> +        connect_peripheral_irq(mc, sbd, cpudev, 1, USART_DRE_IRQ(i));
> +        connect_peripheral_irq(mc, sbd, cpudev, 2, USART_TXC_IRQ(i));
> +        connect_power_reduction_gpio(s, mc, DEVICE(&s->usart[i]), idx);
> +        g_free(devname);
> +    }
> +
> +    /* Timer */
> +    for (i = 0; i < TIMER_MAX; i++) {
> +        int idx = TIMER(i);
> +        if (!mc->dev[idx].addr) {
> +            continue;
> +        }
> +        if (!mc->dev[idx].is_timer16) {
> +            create_unimplemented_device("avr-timer8",
> +                                        OFFSET_DATA + mc->dev[idx].addr, 5);
> +            create_unimplemented_device("avr-timer8-intmask",
> +                                        OFFSET_DATA
> +                                        + mc->dev[idx].intmask_addr, 1);
> +            create_unimplemented_device("avr-timer8-intflag",
> +                                        OFFSET_DATA
> +                                        + mc->dev[idx].intflag_addr, 1);
> +            continue;
> +        }
> +        devname = g_strdup_printf("timer%zu", i);
> +        object_initialize_child(OBJECT(dev), devname,
> +                                &s->timer[i], sizeof(s->timer[i]),
> +                                TYPE_AVR_TIMER16, &error_abort, NULL);
> +        object_property_set_uint(OBJECT(&s->timer[i]), s->xtal_freq_hz,
> +                                 "cpu-frequency-hz", &error_abort);
> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized",
> +                                 &error_abort);
> +        sbd = SYS_BUS_DEVICE(&s->timer[i]);
> +        sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[idx].addr);
> +        sysbus_mmio_map(sbd, 1, OFFSET_DATA + mc->dev[idx].intmask_addr);
> +        sysbus_mmio_map(sbd, 2, OFFSET_DATA + mc->dev[idx].intflag_addr);
> +        connect_peripheral_irq(mc, sbd, cpudev, 0, TIMER_CAPT_IRQ(i));
> +        connect_peripheral_irq(mc, sbd, cpudev, 1, TIMER_COMPA_IRQ(i));
> +        connect_peripheral_irq(mc, sbd, cpudev, 2, TIMER_COMPB_IRQ(i));
> +        connect_peripheral_irq(mc, sbd, cpudev, 3, TIMER_COMPC_IRQ(i));
> +        connect_peripheral_irq(mc, sbd, cpudev, 4, TIMER_OVF_IRQ(i));
> +        connect_power_reduction_gpio(s, mc, DEVICE(&s->timer[i]), idx);
> +        g_free(devname);
> +    }
> +
> +    create_unimplemented_device("avr-twi",          OFFSET_DATA + 0x0b8, 6);
> +    create_unimplemented_device("avr-adc",          OFFSET_DATA + 0x078, 8);
> +    create_unimplemented_device("avr-ext-mem-ctrl", OFFSET_DATA + 0x074, 2);
> +    create_unimplemented_device("avr-watchdog",     OFFSET_DATA + 0x060, 1);
> +    create_unimplemented_device("avr-spi",          OFFSET_DATA + 0x04c, 3);
> +    create_unimplemented_device("avr-eeprom",       OFFSET_DATA + 0x03f, 3);
> +}
> +
> +static Property atmega_props[] = {
> +    DEFINE_PROP_UINT64("xtal-frequency-hz", AtmegaMcuState,
> +                       xtal_freq_hz, 0),
> +    DEFINE_PROP_END_OF_LIST()
> +};
> +
> +static void atmega_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->realize = atmega_realize;
> +    device_class_set_props(dc, atmega_props);
> +    /* Reason: Mapped at fixed location on the system bus */
> +    dc->user_creatable = false;
> +}
> +
> +static void atmega168_class_init(ObjectClass *oc, void *data)
> +{
> +    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
> +
> +    amc->cpu_type = AVR_CPU_TYPE_NAME("avr5");
> +    amc->flash_size = 16 * KiB;
> +    amc->eeprom_size = 512;
> +    amc->sram_size = 1 * KiB;
> +    amc->io_size = 256;
> +    amc->gpio_count = 23;
> +    amc->adc_count = 6;
> +    amc->irq = irq168_328;
> +    amc->dev = dev168_328;
> +};
> +
> +static void atmega328_class_init(ObjectClass *oc, void *data)
> +{
> +    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
> +
> +    amc->cpu_type = AVR_CPU_TYPE_NAME("avr5");
> +    amc->flash_size = 32 * KiB;
> +    amc->eeprom_size = 1 * KiB;
> +    amc->sram_size = 2 * KiB;
> +    amc->io_size = 256;
> +    amc->gpio_count = 23;
> +    amc->adc_count = 6;
> +    amc->irq = irq168_328;
> +    amc->dev = dev168_328;
> +};
> +
> +static void atmega1280_class_init(ObjectClass *oc, void *data)
> +{
> +    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
> +
> +    amc->cpu_type = AVR_CPU_TYPE_NAME("avr6");
> +    amc->flash_size = 128 * KiB;
> +    amc->eeprom_size = 4 * KiB;
> +    amc->sram_size = 8 * KiB;
> +    amc->io_size = 512;
> +    amc->gpio_count = 86;
> +    amc->adc_count = 16;
> +    amc->irq = irq1280_2560;
> +    amc->dev = dev1280_2560;
> +};
> +
> +static void atmega2560_class_init(ObjectClass *oc, void *data)
> +{
> +    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
> +
> +    amc->cpu_type = AVR_CPU_TYPE_NAME("avr6");
> +    amc->flash_size = 256 * KiB;
> +    amc->eeprom_size = 4 * KiB;
> +    amc->sram_size = 8 * KiB;
> +    amc->io_size = 512;
> +    amc->gpio_count = 54;
> +    amc->adc_count = 16;
> +    amc->irq = irq1280_2560;
> +    amc->dev = dev1280_2560;
> +};
> +
> +static const TypeInfo atmega_mcu_types[] = {
> +    {
> +        .name           = TYPE_ATMEGA168_MCU,
> +        .parent         = TYPE_ATMEGA_MCU,
> +        .class_init     = atmega168_class_init,
> +    }, {
> +        .name           = TYPE_ATMEGA328_MCU,
> +        .parent         = TYPE_ATMEGA_MCU,
> +        .class_init     = atmega328_class_init,
> +    }, {
> +        .name           = TYPE_ATMEGA1280_MCU,
> +        .parent         = TYPE_ATMEGA_MCU,
> +        .class_init     = atmega1280_class_init,
> +    }, {
> +        .name           = TYPE_ATMEGA2560_MCU,
> +        .parent         = TYPE_ATMEGA_MCU,
> +        .class_init     = atmega2560_class_init,
> +    }, {
> +        .name           = TYPE_ATMEGA_MCU,
> +        .parent         = TYPE_SYS_BUS_DEVICE,
> +        .instance_size  = sizeof(AtmegaMcuState),
> +        .class_size     = sizeof(AtmegaMcuClass),
> +        .class_init     = atmega_class_init,
> +        .abstract       = true,
> +    }
> +};
> +
> +DEFINE_TYPES(atmega_mcu_types)
> diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h
> new file mode 100644
> index 0000000..1cfbb6b
> --- /dev/null
> +++ b/hw/avr/atmega.h
> @@ -0,0 +1,48 @@
> +/*
> + * QEMU ATmega MCU
> + *
> + * Copyright (c) 2019 Philippe Mathieu-Daudé
> + *
> + * This work is licensed under the terms of the GNU GPLv2 or later.
> + * See the COPYING file in the top-level directory.
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef HW_AVR_ATMEGA_H
> +#define HW_AVR_ATMEGA_H
> +
> +#include "hw/char/avr_usart.h"
> +#include "hw/timer/avr_timer16.h"
> +#include "hw/misc/avr_power.h"
> +#include "target/avr/cpu.h"
> +
> +#define TYPE_ATMEGA_MCU     "ATmega"
> +#define TYPE_ATMEGA168_MCU  "ATmega168"
> +#define TYPE_ATMEGA328_MCU  "ATmega328"
> +#define TYPE_ATMEGA1280_MCU "ATmega1280"
> +#define TYPE_ATMEGA2560_MCU "ATmega2560"
> +
> +#define ATMEGA_MCU(obj) OBJECT_CHECK(AtmegaMcuState, (obj), TYPE_ATMEGA_MCU)
> +
> +#define POWER_MAX 2
> +#define USART_MAX 4
> +#define TIMER_MAX 6
> +#define GPIO_MAX 12
> +
> +typedef struct AtmegaMcuState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    AVRCPU cpu;
> +    MemoryRegion flash;
> +    MemoryRegion eeprom;
> +    MemoryRegion sram;
> +    DeviceState *io;
> +    AVRMaskState pwr[POWER_MAX];
> +    AVRUsartState usart[USART_MAX];
> +    AVRTimer16State timer[TIMER_MAX];
> +    uint64_t xtal_freq_hz;
> +} AtmegaMcuState;
> +
> +#endif /* HW_AVR_ATMEGA_H */
> --
> 2.7.4
>
Philippe Mathieu-Daudé Jan. 31, 2020, 3:09 a.m. UTC | #2
Hi Aleksandar,

Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
times how licensing works.

On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
<aleksandar.m.mail@gmail.com> wrote:
> On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
> <aleksandar.markovic@rt-rk.com> wrote:
> >
> > From: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >
> > Add some AVR microcontrollers from the ATmega family:
> >
> >   - middle range: ATmega168 and ATmega328
> >   - high range: ATmega1280 and ATmega2560
> >
> > For product comparison:
> >   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
> >   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
> >
> > Datasheets:
> >   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
> >   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
> >
> > [AM: Remove word 'Atmel' from filenames and all elements of code]
> > Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> >
> > Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> > Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > ---
> >  hw/avr/Kconfig       |   5 +
> >  hw/avr/Makefile.objs |   1 +
> >  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/avr/atmega.h      |  48 ++++++
> >  4 files changed, 524 insertions(+)
> >  create mode 100644 hw/avr/Kconfig
> >  create mode 100644 hw/avr/atmega.c
> >  create mode 100644 hw/avr/atmega.h
> >
> > diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> > new file mode 100644
> > index 0000000..9e6527e
> > --- /dev/null
> > +++ b/hw/avr/Kconfig
> > @@ -0,0 +1,5 @@
> > +config AVR_ATMEGA_MCU
> > +    bool
> > +    select AVR_TIMER16
> > +    select AVR_USART
> > +    select AVR_POWER
> > diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> > index 123f174..af0fdde 100644
> > --- a/hw/avr/Makefile.objs
> > +++ b/hw/avr/Makefile.objs
> > @@ -1 +1,2 @@
> >  obj-y += boot.o
> > +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> > diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> > new file mode 100644
> > index 0000000..8cdf28b
> > --- /dev/null
> > +++ b/hw/avr/atmega.c
> > @@ -0,0 +1,470 @@
> > +/*
> > + * QEMU ATmega MCU
> > + *
> > + * Copyright (c) 2019 Philippe Mathieu-Daudé
> > + *
> > + * This work is licensed under the terms of the GNU GPLv2 or later.
> > + * See the COPYING file in the top-level directory.
> > + * SPDX-License-Identifier: GPL-2.0-or-later
> > + */
>
> Philippe,
>
> Michael and I already agreed at some moment that the whole target AVR
> should have harmonized licenses, and Sarrah agreed to change her
> license to achieve this. Do you agree to harmonize your licenses with
> the rest of the project? (This would mean changing the preable, but of
> course you remain copyright carrier as is now.)

What license do you want to use? I always use "GPLv2 or later" with
QEMU, mostly following what the others do.

Per https://wiki.qemu.org/License:

  Source files with no licensing information are released under the
GNU General Public License, version 2 or (at your option) any later
version.

Reading about licensing is not fun :(

>
> Thanks,
> Aleksandar
Aleksandar Markovic Jan. 31, 2020, 3:45 a.m. UTC | #3
On Fri, Jan 31, 2020 at 4:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> Hi Aleksandar,
>
> Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
> times how licensing works.
>
> On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
> <aleksandar.m.mail@gmail.com> wrote:
> > On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
> > <aleksandar.markovic@rt-rk.com> wrote:
> > >
> > > From: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > >
> > > Add some AVR microcontrollers from the ATmega family:
> > >
> > >   - middle range: ATmega168 and ATmega328
> > >   - high range: ATmega1280 and ATmega2560
> > >
> > > For product comparison:
> > >   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
> > >   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
> > >
> > > Datasheets:
> > >   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
> > >   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
> > >
> > > [AM: Remove word 'Atmel' from filenames and all elements of code]
> > > Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > >
> > > Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> > > Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > > ---
> > >  hw/avr/Kconfig       |   5 +
> > >  hw/avr/Makefile.objs |   1 +
> > >  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  hw/avr/atmega.h      |  48 ++++++
> > >  4 files changed, 524 insertions(+)
> > >  create mode 100644 hw/avr/Kconfig
> > >  create mode 100644 hw/avr/atmega.c
> > >  create mode 100644 hw/avr/atmega.h
> > >
> > > diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> > > new file mode 100644
> > > index 0000000..9e6527e
> > > --- /dev/null
> > > +++ b/hw/avr/Kconfig
> > > @@ -0,0 +1,5 @@
> > > +config AVR_ATMEGA_MCU
> > > +    bool
> > > +    select AVR_TIMER16
> > > +    select AVR_USART
> > > +    select AVR_POWER
> > > diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> > > index 123f174..af0fdde 100644
> > > --- a/hw/avr/Makefile.objs
> > > +++ b/hw/avr/Makefile.objs
> > > @@ -1 +1,2 @@
> > >  obj-y += boot.o
> > > +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> > > diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> > > new file mode 100644
> > > index 0000000..8cdf28b
> > > --- /dev/null
> > > +++ b/hw/avr/atmega.c
> > > @@ -0,0 +1,470 @@
> > > +/*
> > > + * QEMU ATmega MCU
> > > + *
> > > + * Copyright (c) 2019 Philippe Mathieu-Daudé
> > > + *
> > > + * This work is licensed under the terms of the GNU GPLv2 or later.
> > > + * See the COPYING file in the top-level directory.
> > > + * SPDX-License-Identifier: GPL-2.0-or-later
> > > + */
> >
> > Philippe,
> >
> > Michael and I already agreed at some moment that the whole target AVR
> > should have harmonized licenses, and Sarrah agreed to change her
> > license to achieve this. Do you agree to harmonize your licenses with
> > the rest of the project? (This would mean changing the preable, but of
> > course you remain copyright carrier as is now.)
>
> What license do you want to use? I always use "GPLv2 or later" with
> QEMU, mostly following what the others do.
>
> Per https://wiki.qemu.org/License:
>
>   Source files with no licensing information are released under the
> GNU General Public License, version 2 or (at your option) any later
> version.
>
> Reading about licensing is not fun :(
>

Philippe, here is the deal: All new files for AVR platform has the
following preamble, that Michael chose from the outset:

+ * 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.1 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/lgpl-2.1.html>

Now, it is preferable that licenses are harmonized within a module,
and I ask you to change the preamble to be the same as the rest of the
module, that is all. This practically means LGPL2.1+later instead
LGPL2.0+later. I think it is reasonable that we want to simplify out
license stuff, not complicate it with different licenses within a
module. There are examples of complications in cases of different
license within the same module, so it would be ideal if we avoid such
situations.

Aleksandar

> >
> > Thanks,
> > Aleksandar
Aleksandar Markovic Jan. 31, 2020, 4:11 a.m. UTC | #4
On Fri, Jan 31, 2020 at 4:45 AM Aleksandar Markovic
<aleksandar.m.mail@gmail.com> wrote:
>
> On Fri, Jan 31, 2020 at 4:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >
> > Hi Aleksandar,
> >
> > Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
> > times how licensing works.
> >
> > On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
> > <aleksandar.m.mail@gmail.com> wrote:
> > > On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
> > > <aleksandar.markovic@rt-rk.com> wrote:
> > > >
> > > > From: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > > >
> > > > Add some AVR microcontrollers from the ATmega family:
> > > >
> > > >   - middle range: ATmega168 and ATmega328
> > > >   - high range: ATmega1280 and ATmega2560
> > > >
> > > > For product comparison:
> > > >   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
> > > >   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
> > > >
> > > > Datasheets:
> > > >   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
> > > >   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
> > > >
> > > > [AM: Remove word 'Atmel' from filenames and all elements of code]
> > > > Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > > >
> > > > Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> > > > Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > > > ---
> > > >  hw/avr/Kconfig       |   5 +
> > > >  hw/avr/Makefile.objs |   1 +
> > > >  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  hw/avr/atmega.h      |  48 ++++++
> > > >  4 files changed, 524 insertions(+)
> > > >  create mode 100644 hw/avr/Kconfig
> > > >  create mode 100644 hw/avr/atmega.c
> > > >  create mode 100644 hw/avr/atmega.h
> > > >
> > > > diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> > > > new file mode 100644
> > > > index 0000000..9e6527e
> > > > --- /dev/null
> > > > +++ b/hw/avr/Kconfig
> > > > @@ -0,0 +1,5 @@
> > > > +config AVR_ATMEGA_MCU
> > > > +    bool
> > > > +    select AVR_TIMER16
> > > > +    select AVR_USART
> > > > +    select AVR_POWER
> > > > diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> > > > index 123f174..af0fdde 100644
> > > > --- a/hw/avr/Makefile.objs
> > > > +++ b/hw/avr/Makefile.objs
> > > > @@ -1 +1,2 @@
> > > >  obj-y += boot.o
> > > > +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> > > > diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> > > > new file mode 100644
> > > > index 0000000..8cdf28b
> > > > --- /dev/null
> > > > +++ b/hw/avr/atmega.c
> > > > @@ -0,0 +1,470 @@
> > > > +/*
> > > > + * QEMU ATmega MCU
> > > > + *
> > > > + * Copyright (c) 2019 Philippe Mathieu-Daudé
> > > > + *
> > > > + * This work is licensed under the terms of the GNU GPLv2 or later.
> > > > + * See the COPYING file in the top-level directory.
> > > > + * SPDX-License-Identifier: GPL-2.0-or-later
> > > > + */
> > >
> > > Philippe,
> > >
> > > Michael and I already agreed at some moment that the whole target AVR
> > > should have harmonized licenses, and Sarrah agreed to change her
> > > license to achieve this. Do you agree to harmonize your licenses with
> > > the rest of the project? (This would mean changing the preable, but of
> > > course you remain copyright carrier as is now.)
> >
> > What license do you want to use? I always use "GPLv2 or later" with
> > QEMU, mostly following what the others do.
> >
> > Per https://wiki.qemu.org/License:
> >
> >   Source files with no licensing information are released under the
> > GNU General Public License, version 2 or (at your option) any later
> > version.
> >
> > Reading about licensing is not fun :(
> >
>
> Philippe, here is the deal: All new files for AVR platform has the
> following preamble, that Michael chose from the outset:
>
> + * 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.1 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/lgpl-2.1.html>
>
> Now, it is preferable that licenses are harmonized within a module,
> and I ask you to change the preamble to be the same as the rest of the
> module, that is all. This practically means LGPL2.1+later instead
> LGPL2.0+later. I think it is reasonable that we want to simplify out
> license stuff, not complicate it with different licenses within a
> module. There are examples of complications in cases of different
> license within the same module, so it would be ideal if we avoid such
> situations.
>

I didn't mean to scare you, I am just a developer like you, and I want
to avoid thinking about licenses, and think of our real work, so, I
gather, in my layman terms, it is better to have the same license for
the new platform in its entirety, if possible, that is all. :)

> Aleksandar
>
> > >
> > > Thanks,
> > > Aleksandar
Thomas Huth Jan. 31, 2020, 9:35 a.m. UTC | #5
On 31/01/2020 05.11, Aleksandar Markovic wrote:
> On Fri, Jan 31, 2020 at 4:45 AM Aleksandar Markovic
> <aleksandar.m.mail@gmail.com> wrote:
>>
>> On Fri, Jan 31, 2020 at 4:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>
>>> Hi Aleksandar,
>>>
>>> Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
>>> times how licensing works.
>>>
>>> On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
>>> <aleksandar.m.mail@gmail.com> wrote:
>>>> On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
>>>> <aleksandar.markovic@rt-rk.com> wrote:
>>>>>
>>>>> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>>>
>>>>> Add some AVR microcontrollers from the ATmega family:
>>>>>
>>>>>   - middle range: ATmega168 and ATmega328
>>>>>   - high range: ATmega1280 and ATmega2560
>>>>>
>>>>> For product comparison:
>>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
>>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
>>>>>
>>>>> Datasheets:
>>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
>>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
>>>>>
>>>>> [AM: Remove word 'Atmel' from filenames and all elements of code]
>>>>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
>>>>>
>>>>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>>>>> Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
>>>>> ---
>>>>>  hw/avr/Kconfig       |   5 +
>>>>>  hw/avr/Makefile.objs |   1 +
>>>>>  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>>>  hw/avr/atmega.h      |  48 ++++++
>>>>>  4 files changed, 524 insertions(+)
>>>>>  create mode 100644 hw/avr/Kconfig
>>>>>  create mode 100644 hw/avr/atmega.c
>>>>>  create mode 100644 hw/avr/atmega.h
>>>>>
>>>>> diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
>>>>> new file mode 100644
>>>>> index 0000000..9e6527e
>>>>> --- /dev/null
>>>>> +++ b/hw/avr/Kconfig
>>>>> @@ -0,0 +1,5 @@
>>>>> +config AVR_ATMEGA_MCU
>>>>> +    bool
>>>>> +    select AVR_TIMER16
>>>>> +    select AVR_USART
>>>>> +    select AVR_POWER
>>>>> diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
>>>>> index 123f174..af0fdde 100644
>>>>> --- a/hw/avr/Makefile.objs
>>>>> +++ b/hw/avr/Makefile.objs
>>>>> @@ -1 +1,2 @@
>>>>>  obj-y += boot.o
>>>>> +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
>>>>> diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
>>>>> new file mode 100644
>>>>> index 0000000..8cdf28b
>>>>> --- /dev/null
>>>>> +++ b/hw/avr/atmega.c
>>>>> @@ -0,0 +1,470 @@
>>>>> +/*
>>>>> + * QEMU ATmega MCU
>>>>> + *
>>>>> + * Copyright (c) 2019 Philippe Mathieu-Daudé
>>>>> + *
>>>>> + * This work is licensed under the terms of the GNU GPLv2 or later.
>>>>> + * See the COPYING file in the top-level directory.
>>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
>>>>> + */
>>>>
>>>> Philippe,
>>>>
>>>> Michael and I already agreed at some moment that the whole target AVR
>>>> should have harmonized licenses, and Sarrah agreed to change her
>>>> license to achieve this. Do you agree to harmonize your licenses with
>>>> the rest of the project? (This would mean changing the preable, but of
>>>> course you remain copyright carrier as is now.)
>>>
>>> What license do you want to use? I always use "GPLv2 or later" with
>>> QEMU, mostly following what the others do.
>>>
>>> Per https://wiki.qemu.org/License:
>>>
>>>   Source files with no licensing information are released under the
>>> GNU General Public License, version 2 or (at your option) any later
>>> version.
>>>
>>> Reading about licensing is not fun :(
>>>
>>
>> Philippe, here is the deal: All new files for AVR platform has the
>> following preamble, that Michael chose from the outset:
>>
>> + * 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.1 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/lgpl-2.1.html>
>>
>> Now, it is preferable that licenses are harmonized within a module,
>> and I ask you to change the preamble to be the same as the rest of the
>> module, that is all. This practically means LGPL2.1+later instead
>> LGPL2.0+later. I think it is reasonable that we want to simplify out
>> license stuff, not complicate it with different licenses within a
>> module. There are examples of complications in cases of different
>> license within the same module, so it would be ideal if we avoid such
>> situations.
>>
> 
> I didn't mean to scare you, I am just a developer like you, and I want
> to avoid thinking about licenses, and think of our real work, so, I
> gather, in my layman terms, it is better to have the same license for
> the new platform in its entirety, if possible, that is all. :)

This is all part of QEMU, and QEMU is licensed under the GPLv2. If
someone wants to use a less strict license for their own code that is
still compatible with the GPLv2, like the LGPLv2.1, that's fine. But I
think if Philippe does not like to release his code under the LGPL, and
wants to use GPL instead, you can not force him to use LGPL here. It's
the decision of Philippe what he wants to use for his code.

 Thomas
Aleksandar Markovic Jan. 31, 2020, 9:40 a.m. UTC | #6
On Fri, Jan 31, 2020 at 10:35 AM Thomas Huth <thuth@redhat.com> wrote:
>
> On 31/01/2020 05.11, Aleksandar Markovic wrote:
> > On Fri, Jan 31, 2020 at 4:45 AM Aleksandar Markovic
> > <aleksandar.m.mail@gmail.com> wrote:
> >>
> >> On Fri, Jan 31, 2020 at 4:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>
> >>> Hi Aleksandar,
> >>>
> >>> Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
> >>> times how licensing works.
> >>>
> >>> On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
> >>> <aleksandar.m.mail@gmail.com> wrote:
> >>>> On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
> >>>> <aleksandar.markovic@rt-rk.com> wrote:
> >>>>>
> >>>>> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>>>>
> >>>>> Add some AVR microcontrollers from the ATmega family:
> >>>>>
> >>>>>   - middle range: ATmega168 and ATmega328
> >>>>>   - high range: ATmega1280 and ATmega2560
> >>>>>
> >>>>> For product comparison:
> >>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
> >>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
> >>>>>
> >>>>> Datasheets:
> >>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
> >>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
> >>>>>
> >>>>> [AM: Remove word 'Atmel' from filenames and all elements of code]
> >>>>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> >>>>>
> >>>>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> >>>>> Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> >>>>> ---
> >>>>>  hw/avr/Kconfig       |   5 +
> >>>>>  hw/avr/Makefile.objs |   1 +
> >>>>>  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >>>>>  hw/avr/atmega.h      |  48 ++++++
> >>>>>  4 files changed, 524 insertions(+)
> >>>>>  create mode 100644 hw/avr/Kconfig
> >>>>>  create mode 100644 hw/avr/atmega.c
> >>>>>  create mode 100644 hw/avr/atmega.h
> >>>>>
> >>>>> diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> >>>>> new file mode 100644
> >>>>> index 0000000..9e6527e
> >>>>> --- /dev/null
> >>>>> +++ b/hw/avr/Kconfig
> >>>>> @@ -0,0 +1,5 @@
> >>>>> +config AVR_ATMEGA_MCU
> >>>>> +    bool
> >>>>> +    select AVR_TIMER16
> >>>>> +    select AVR_USART
> >>>>> +    select AVR_POWER
> >>>>> diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> >>>>> index 123f174..af0fdde 100644
> >>>>> --- a/hw/avr/Makefile.objs
> >>>>> +++ b/hw/avr/Makefile.objs
> >>>>> @@ -1 +1,2 @@
> >>>>>  obj-y += boot.o
> >>>>> +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> >>>>> diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> >>>>> new file mode 100644
> >>>>> index 0000000..8cdf28b
> >>>>> --- /dev/null
> >>>>> +++ b/hw/avr/atmega.c
> >>>>> @@ -0,0 +1,470 @@
> >>>>> +/*
> >>>>> + * QEMU ATmega MCU
> >>>>> + *
> >>>>> + * Copyright (c) 2019 Philippe Mathieu-Daudé
> >>>>> + *
> >>>>> + * This work is licensed under the terms of the GNU GPLv2 or later.
> >>>>> + * See the COPYING file in the top-level directory.
> >>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
> >>>>> + */
> >>>>
> >>>> Philippe,
> >>>>
> >>>> Michael and I already agreed at some moment that the whole target AVR
> >>>> should have harmonized licenses, and Sarrah agreed to change her
> >>>> license to achieve this. Do you agree to harmonize your licenses with
> >>>> the rest of the project? (This would mean changing the preable, but of
> >>>> course you remain copyright carrier as is now.)
> >>>
> >>> What license do you want to use? I always use "GPLv2 or later" with
> >>> QEMU, mostly following what the others do.
> >>>
> >>> Per https://wiki.qemu.org/License:
> >>>
> >>>   Source files with no licensing information are released under the
> >>> GNU General Public License, version 2 or (at your option) any later
> >>> version.
> >>>
> >>> Reading about licensing is not fun :(
> >>>
> >>
> >> Philippe, here is the deal: All new files for AVR platform has the
> >> following preamble, that Michael chose from the outset:
> >>
> >> + * 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.1 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/lgpl-2.1.html>
> >>
> >> Now, it is preferable that licenses are harmonized within a module,
> >> and I ask you to change the preamble to be the same as the rest of the
> >> module, that is all. This practically means LGPL2.1+later instead
> >> LGPL2.0+later. I think it is reasonable that we want to simplify out
> >> license stuff, not complicate it with different licenses within a
> >> module. There are examples of complications in cases of different
> >> license within the same module, so it would be ideal if we avoid such
> >> situations.
> >>
> >
> > I didn't mean to scare you, I am just a developer like you, and I want
> > to avoid thinking about licenses, and think of our real work, so, I
> > gather, in my layman terms, it is better to have the same license for
> > the new platform in its entirety, if possible, that is all. :)
>
> This is all part of QEMU, and QEMU is licensed under the GPLv2. If
> someone wants to use a less strict license for their own code that is
> still compatible with the GPLv2, like the LGPLv2.1, that's fine. But I
> think if Philippe does not like to release his code under the LGPL, and
> wants to use GPL instead, you can not force him to use LGPL here. It's
> the decision of Philippe what he wants to use for his code.
>

It is his decision, but it can be reasonable or not so reasonable. I
think it is logical that he follows the license model of the module he
contributes to, isn't it?

Aleksandar

>  Thomas
>
Philippe Mathieu-Daudé Jan. 31, 2020, 10:45 a.m. UTC | #7
On Fri, Jan 31, 2020 at 10:40 AM Aleksandar Markovic
<aleksandar.m.mail@gmail.com> wrote:
> On Fri, Jan 31, 2020 at 10:35 AM Thomas Huth <thuth@redhat.com> wrote:
> > On 31/01/2020 05.11, Aleksandar Markovic wrote:
> > > On Fri, Jan 31, 2020 at 4:45 AM Aleksandar Markovic
> > > <aleksandar.m.mail@gmail.com> wrote:
> > >>
> > >> On Fri, Jan 31, 2020 at 4:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> > >>>
> > >>> Hi Aleksandar,
> > >>>
> > >>> Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
> > >>> times how licensing works.
> > >>>
> > >>> On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
> > >>> <aleksandar.m.mail@gmail.com> wrote:
> > >>>> On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
> > >>>> <aleksandar.markovic@rt-rk.com> wrote:
> > >>>>>
> > >>>>> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > >>>>>
> > >>>>> Add some AVR microcontrollers from the ATmega family:
> > >>>>>
> > >>>>>   - middle range: ATmega168 and ATmega328
> > >>>>>   - high range: ATmega1280 and ATmega2560
> > >>>>>
> > >>>>> For product comparison:
> > >>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
> > >>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
> > >>>>>
> > >>>>> Datasheets:
> > >>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
> > >>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
> > >>>>>
> > >>>>> [AM: Remove word 'Atmel' from filenames and all elements of code]
> > >>>>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > >>>>>
> > >>>>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > >>>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> > >>>>> Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > >>>>> ---
> > >>>>>  hw/avr/Kconfig       |   5 +
> > >>>>>  hw/avr/Makefile.objs |   1 +
> > >>>>>  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > >>>>>  hw/avr/atmega.h      |  48 ++++++
> > >>>>>  4 files changed, 524 insertions(+)
> > >>>>>  create mode 100644 hw/avr/Kconfig
> > >>>>>  create mode 100644 hw/avr/atmega.c
> > >>>>>  create mode 100644 hw/avr/atmega.h
> > >>>>>
> > >>>>> diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> > >>>>> new file mode 100644
> > >>>>> index 0000000..9e6527e
> > >>>>> --- /dev/null
> > >>>>> +++ b/hw/avr/Kconfig
> > >>>>> @@ -0,0 +1,5 @@
> > >>>>> +config AVR_ATMEGA_MCU
> > >>>>> +    bool
> > >>>>> +    select AVR_TIMER16
> > >>>>> +    select AVR_USART
> > >>>>> +    select AVR_POWER
> > >>>>> diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> > >>>>> index 123f174..af0fdde 100644
> > >>>>> --- a/hw/avr/Makefile.objs
> > >>>>> +++ b/hw/avr/Makefile.objs
> > >>>>> @@ -1 +1,2 @@
> > >>>>>  obj-y += boot.o
> > >>>>> +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> > >>>>> diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> > >>>>> new file mode 100644
> > >>>>> index 0000000..8cdf28b
> > >>>>> --- /dev/null
> > >>>>> +++ b/hw/avr/atmega.c
> > >>>>> @@ -0,0 +1,470 @@
> > >>>>> +/*
> > >>>>> + * QEMU ATmega MCU
> > >>>>> + *
> > >>>>> + * Copyright (c) 2019 Philippe Mathieu-Daudé
> > >>>>> + *
> > >>>>> + * This work is licensed under the terms of the GNU GPLv2 or later.
> > >>>>> + * See the COPYING file in the top-level directory.
> > >>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
> > >>>>> + */
> > >>>>
> > >>>> Philippe,
> > >>>>
> > >>>> Michael and I already agreed at some moment that the whole target AVR
> > >>>> should have harmonized licenses, and Sarrah agreed to change her
> > >>>> license to achieve this. Do you agree to harmonize your licenses with
> > >>>> the rest of the project? (This would mean changing the preable, but of
> > >>>> course you remain copyright carrier as is now.)

Note I'm not worried about my authorship but than other contributors
being able to reuse and modify this code.

> > >>>
> > >>> What license do you want to use? I always use "GPLv2 or later" with
> > >>> QEMU, mostly following what the others do.
> > >>>
> > >>> Per https://wiki.qemu.org/License:
> > >>>
> > >>>   Source files with no licensing information are released under the
> > >>> GNU General Public License, version 2 or (at your option) any later
> > >>> version.
> > >>>
> > >>> Reading about licensing is not fun :(
> > >>>
> > >>
> > >> Philippe, here is the deal: All new files for AVR platform has the
> > >> following preamble, that Michael chose from the outset:
> > >>
> > >> + * 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.1 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/lgpl-2.1.html>
> > >>
> > >> Now, it is preferable that licenses are harmonized within a module,
> > >> and I ask you to change the preamble to be the same as the rest of the
> > >> module, that is all. This practically means LGPL2.1+later instead
> > >> LGPL2.0+later. I think it is reasonable that we want to simplify out
> > >> license stuff, not complicate it with different licenses within a
> > >> module. There are examples of complications in cases of different
> > >> license within the same module, so it would be ideal if we avoid such
> > >> situations.

I don't use QEMU as a library, it is my main application.
I tried to make this file clean/easy to read so it can be reused by
other archs when implementing boards able to use multiple SoCs, this
is not AVR-only.

I see LGPLv2.1 is deprecated for version 3, why use 2.1?

https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html

```
You can use it too, but we suggest you first think carefully about
whether this license or the ordinary General Public License is the
better strategy to use in any particular case, based on the
explanations below.
...
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
```

Personally I don't care about non-free programs using QEMU as a
library, and I don't think a such program would use the default QEMU
config anyway.

You can build the AVR (tcg) cpus without GPLv2+ hardware with this patch:

---
--- a/default-configs/avr-softmmu.mak
+++ b/default-configs/avr-softmmu.mak
@@ -2,4 +2,4 @@

 # Boards:
 #
-CONFIG_ARDUINO=y
+CONFIG_ARDUINO=n
---

But I doubt you can build QEMU without GPLv2+ components.

See also:
https://www.gnu.org/licenses/why-not-lgpl.html

```
Which license is best for a given library is a matter of strategy ...
Using the ordinary GPL for a library gives free software developers an
advantage over proprietary developers: a library that they can use,
while proprietary developers cannot use it ... When a free library's
features are readily available for proprietary software through other
alternative libraries ... the library cannot give free software any
particular advantage, so it is better to use the Lesser GPL for that
library.
```

> > > I didn't mean to scare you, I am just a developer like you, and I want
> > > to avoid thinking about licenses, and think of our real work, so, I
> > > gather, in my layman terms, it is better to have the same license for
> > > the new platform in its entirety, if possible, that is all. :)
> >
> > This is all part of QEMU, and QEMU is licensed under the GPLv2. If
> > someone wants to use a less strict license for their own code that is
> > still compatible with the GPLv2, like the LGPLv2.1, that's fine. But I
> > think if Philippe does not like to release his code under the LGPL, and
> > wants to use GPL instead, you can not force him to use LGPL here. It's
> > the decision of Philippe what he wants to use for his code.
> >
>
> It is his decision, but it can be reasonable or not so reasonable. I
> think it is logical that he follows the license model of the module he
> contributes to, isn't it?
>
> Aleksandar
>
> >  Thomas
> >
Aleksandar Markovic Jan. 31, 2020, 11:07 a.m. UTC | #8
On Fri, Jan 31, 2020 at 11:45 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On Fri, Jan 31, 2020 at 10:40 AM Aleksandar Markovic
> <aleksandar.m.mail@gmail.com> wrote:
> > On Fri, Jan 31, 2020 at 10:35 AM Thomas Huth <thuth@redhat.com> wrote:
> > > On 31/01/2020 05.11, Aleksandar Markovic wrote:
> > > > On Fri, Jan 31, 2020 at 4:45 AM Aleksandar Markovic
> > > > <aleksandar.m.mail@gmail.com> wrote:
> > > >>
> > > >> On Fri, Jan 31, 2020 at 4:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> > > >>>
> > > >>> Hi Aleksandar,
> > > >>>
> > > >>> Cc'ing Thomas & Daniel who are not lawyers but tried to explain me few
> > > >>> times how licensing works.
> > > >>>
> > > >>> On Fri, Jan 31, 2020 at 2:56 AM Aleksandar Markovic
> > > >>> <aleksandar.m.mail@gmail.com> wrote:
> > > >>>> On Fri, Jan 31, 2020 at 1:03 AM Aleksandar Markovic
> > > >>>> <aleksandar.markovic@rt-rk.com> wrote:
> > > >>>>>
> > > >>>>> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > > >>>>>
> > > >>>>> Add some AVR microcontrollers from the ATmega family:
> > > >>>>>
> > > >>>>>   - middle range: ATmega168 and ATmega328
> > > >>>>>   - high range: ATmega1280 and ATmega2560
> > > >>>>>
> > > >>>>> For product comparison:
> > > >>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
> > > >>>>>   https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560
> > > >>>>>
> > > >>>>> Datasheets:
> > > >>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
> > > >>>>>   http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
> > > >>>>>
> > > >>>>> [AM: Remove word 'Atmel' from filenames and all elements of code]
> > > >>>>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > > >>>>>
> > > >>>>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > > >>>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> > > >>>>> Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> > > >>>>> ---
> > > >>>>>  hw/avr/Kconfig       |   5 +
> > > >>>>>  hw/avr/Makefile.objs |   1 +
> > > >>>>>  hw/avr/atmega.c      | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >>>>>  hw/avr/atmega.h      |  48 ++++++
> > > >>>>>  4 files changed, 524 insertions(+)
> > > >>>>>  create mode 100644 hw/avr/Kconfig
> > > >>>>>  create mode 100644 hw/avr/atmega.c
> > > >>>>>  create mode 100644 hw/avr/atmega.h
> > > >>>>>
> > > >>>>> diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
> > > >>>>> new file mode 100644
> > > >>>>> index 0000000..9e6527e
> > > >>>>> --- /dev/null
> > > >>>>> +++ b/hw/avr/Kconfig
> > > >>>>> @@ -0,0 +1,5 @@
> > > >>>>> +config AVR_ATMEGA_MCU
> > > >>>>> +    bool
> > > >>>>> +    select AVR_TIMER16
> > > >>>>> +    select AVR_USART
> > > >>>>> +    select AVR_POWER
> > > >>>>> diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
> > > >>>>> index 123f174..af0fdde 100644
> > > >>>>> --- a/hw/avr/Makefile.objs
> > > >>>>> +++ b/hw/avr/Makefile.objs
> > > >>>>> @@ -1 +1,2 @@
> > > >>>>>  obj-y += boot.o
> > > >>>>> +obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
> > > >>>>> diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
> > > >>>>> new file mode 100644
> > > >>>>> index 0000000..8cdf28b
> > > >>>>> --- /dev/null
> > > >>>>> +++ b/hw/avr/atmega.c
> > > >>>>> @@ -0,0 +1,470 @@
> > > >>>>> +/*
> > > >>>>> + * QEMU ATmega MCU
> > > >>>>> + *
> > > >>>>> + * Copyright (c) 2019 Philippe Mathieu-Daudé
> > > >>>>> + *
> > > >>>>> + * This work is licensed under the terms of the GNU GPLv2 or later.
> > > >>>>> + * See the COPYING file in the top-level directory.
> > > >>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
> > > >>>>> + */
> > > >>>>
> > > >>>> Philippe,
> > > >>>>
> > > >>>> Michael and I already agreed at some moment that the whole target AVR
> > > >>>> should have harmonized licenses, and Sarrah agreed to change her
> > > >>>> license to achieve this. Do you agree to harmonize your licenses with
> > > >>>> the rest of the project? (This would mean changing the preable, but of
> > > >>>> course you remain copyright carrier as is now.)
>
> Note I'm not worried about my authorship but than other contributors
> being able to reuse and modify this code.
>
> > > >>>
> > > >>> What license do you want to use? I always use "GPLv2 or later" with
> > > >>> QEMU, mostly following what the others do.
> > > >>>
> > > >>> Per https://wiki.qemu.org/License:
> > > >>>
> > > >>>   Source files with no licensing information are released under the
> > > >>> GNU General Public License, version 2 or (at your option) any later
> > > >>> version.
> > > >>>
> > > >>> Reading about licensing is not fun :(
> > > >>>
> > > >>
> > > >> Philippe, here is the deal: All new files for AVR platform has the
> > > >> following preamble, that Michael chose from the outset:
> > > >>
> > > >> + * 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.1 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/lgpl-2.1.html>
> > > >>
> > > >> Now, it is preferable that licenses are harmonized within a module,
> > > >> and I ask you to change the preamble to be the same as the rest of the
> > > >> module, that is all. This practically means LGPL2.1+later instead
> > > >> LGPL2.0+later. I think it is reasonable that we want to simplify out
> > > >> license stuff, not complicate it with different licenses within a
> > > >> module. There are examples of complications in cases of different
> > > >> license within the same module, so it would be ideal if we avoid such
> > > >> situations.
>
> I don't use QEMU as a library, it is my main application.
> I tried to make this file clean/easy to read so it can be reused by
> other archs when implementing boards able to use multiple SoCs, this
> is not AVR-only.
>
> I see LGPLv2.1 is deprecated for version 3, why use 2.1?
>
> https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
>
> ```
> You can use it too, but we suggest you first think carefully about
> whether this license or the ordinary General Public License is the
> better strategy to use in any particular case, based on the
> explanations below.
> ...
> Most GNU software, including some libraries, is covered by the
> ordinary GNU General Public License. This license, the GNU Lesser
> General Public License, applies to certain designated libraries, and
> is quite different from the ordinary General Public License. We use
> this license for certain libraries in order to permit linking those
> libraries into non-free programs.
> ```
>
> Personally I don't care about non-free programs using QEMU as a
> library, and I don't think a such program would use the default QEMU
> config anyway.
>
> You can build the AVR (tcg) cpus without GPLv2+ hardware with this patch:
>
> ---
> --- a/default-configs/avr-softmmu.mak
> +++ b/default-configs/avr-softmmu.mak
> @@ -2,4 +2,4 @@
>
>  # Boards:
>  #
> -CONFIG_ARDUINO=y
> +CONFIG_ARDUINO=n
> ---
>
> But I doubt you can build QEMU without GPLv2+ components.
>
> See also:
> https://www.gnu.org/licenses/why-not-lgpl.html
>
> ```
> Which license is best for a given library is a matter of strategy ...
> Using the ordinary GPL for a library gives free software developers an
> advantage over proprietary developers: a library that they can use,
> while proprietary developers cannot use it ... When a free library's
> features are readily available for proprietary software through other
> alternative libraries ... the library cannot give free software any
> particular advantage, so it is better to use the Lesser GPL for that
> library.
> ```
>

Philippe,

You are just overly complicating the license stuff.

The original and main AVR contributor chose LGPL2.1+later, which is
compatible with QEMU. For that reason alone, I think anyone
contributing to this target in a substantial way should respect that
and continue using that license. I am just politely asking you, for
the sake of simplicity and common sense, to harmonize your
contributions. That is all.

Thanks,
Aleksandar

> > > > I didn't mean to scare you, I am just a developer like you, and I want
> > > > to avoid thinking about licenses, and think of our real work, so, I
> > > > gather, in my layman terms, it is better to have the same license for
> > > > the new platform in its entirety, if possible, that is all. :)
> > >
> > > This is all part of QEMU, and QEMU is licensed under the GPLv2. If
> > > someone wants to use a less strict license for their own code that is
> > > still compatible with the GPLv2, like the LGPLv2.1, that's fine. But I
> > > think if Philippe does not like to release his code under the LGPL, and
> > > wants to use GPL instead, you can not force him to use LGPL here. It's
> > > the decision of Philippe what he wants to use for his code.
> > >
> >
> > It is his decision, but it can be reasonable or not so reasonable. I
> > think it is logical that he follows the license model of the module he
> > contributes to, isn't it?
> >
> > Aleksandar
> >
> > >  Thomas
> > >
diff mbox series

Patch

diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
new file mode 100644
index 0000000..9e6527e
--- /dev/null
+++ b/hw/avr/Kconfig
@@ -0,0 +1,5 @@ 
+config AVR_ATMEGA_MCU
+    bool
+    select AVR_TIMER16
+    select AVR_USART
+    select AVR_POWER
diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
index 123f174..af0fdde 100644
--- a/hw/avr/Makefile.objs
+++ b/hw/avr/Makefile.objs
@@ -1 +1,2 @@ 
 obj-y += boot.o
+obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
new file mode 100644
index 0000000..8cdf28b
--- /dev/null
+++ b/hw/avr/atmega.c
@@ -0,0 +1,470 @@ 
+/*
+ * QEMU ATmega MCU
+ *
+ * Copyright (c) 2019 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h" /* FIXME memory_region_allocate_system_memory for sram */
+#include "hw/misc/unimp.h"
+#include "atmega.h"
+
+enum AtmegaPeripheral {
+    POWER0, POWER1,
+    GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF,
+    GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL,
+    USART0, USART1, USART2, USART3,
+    TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5,
+    PERIFMAX
+};
+
+#define GPIO(n)     (n + GPIOA)
+#define USART(n)    (n + USART0)
+#define TIMER(n)    (n + TIMER0)
+#define POWER(n)    (n + POWER0)
+
+typedef struct {
+    uint16_t addr;
+    enum AtmegaPeripheral power_index;
+    uint8_t power_bit;
+    /* timer specific */
+    uint16_t intmask_addr;
+    uint16_t intflag_addr;
+    bool is_timer16;
+} peripheral_cfg;
+
+typedef struct AtmegaMcuClass {
+    /*< private >*/
+    SysBusDeviceClass parent_class;
+    /*< public >*/
+    const char *uc_name;
+    const char *cpu_type;
+    size_t flash_size;
+    size_t eeprom_size;
+    size_t sram_size;
+    size_t io_size;
+    size_t gpio_count;
+    size_t adc_count;
+    const uint8_t *irq;
+    const peripheral_cfg *dev;
+} AtmegaMcuClass;
+
+#define ATMEGA_MCU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(AtmegaMcuClass, (klass), TYPE_ATMEGA_MCU)
+#define ATMEGA_MCU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(AtmegaMcuClass, (obj), TYPE_ATMEGA_MCU)
+
+static const peripheral_cfg dev168_328[PERIFMAX] = {
+    [USART0]        = {  0xc0, POWER0, 1 },
+    [TIMER2]        = {  0xb0, POWER0, 6, 0x70, 0x37, false },
+    [TIMER1]        = {  0x80, POWER0, 3, 0x6f, 0x36, true },
+    [POWER0]        = {  0x64 },
+    [TIMER0]        = {  0x44, POWER0, 5, 0x6e, 0x35, false },
+    [GPIOD]         = {  0x29 },
+    [GPIOC]         = {  0x26 },
+    [GPIOB]         = {  0x23 },
+}, dev1280_2560[PERIFMAX] = {
+    [USART3]        = { 0x130, POWER1, 2 },
+    [TIMER5]        = { 0x120, POWER1, 5, 0x73, 0x3a, true },
+    [GPIOL]         = { 0x109 },
+    [GPIOK]         = { 0x106 },
+    [GPIOJ]         = { 0x103 },
+    [GPIOH]         = { 0x100 },
+    [USART2]        = {  0xd0, POWER1, 1 },
+    [USART1]        = {  0xc8, POWER1, 0 },
+    [USART0]        = {  0xc0, POWER0, 1 },
+    [TIMER2]        = {  0xb0, POWER0, 6, 0x70, 0x37, false }, /* TODO async */
+    [TIMER4]        = {  0xa0, POWER1, 4, 0x72, 0x39, true },
+    [TIMER3]        = {  0x90, POWER1, 3, 0x71, 0x38, true },
+    [TIMER1]        = {  0x80, POWER0, 3, 0x6f, 0x36, true },
+    [POWER1]        = {  0x65 },
+    [POWER0]        = {  0x64 },
+    [TIMER0]        = {  0x44, POWER0, 5, 0x6e, 0x35, false },
+    [GPIOG]         = {  0x32 },
+    [GPIOF]         = {  0x2f },
+    [GPIOE]         = {  0x2c },
+    [GPIOD]         = {  0x29 },
+    [GPIOC]         = {  0x26 },
+    [GPIOB]         = {  0x23 },
+    [GPIOA]         = {  0x20 },
+};
+
+enum AtmegaIrq {
+    USART0_RXC_IRQ, USART0_DRE_IRQ, USART0_TXC_IRQ,
+    USART1_RXC_IRQ, USART1_DRE_IRQ, USART1_TXC_IRQ,
+    USART2_RXC_IRQ, USART2_DRE_IRQ, USART2_TXC_IRQ,
+    USART3_RXC_IRQ, USART3_DRE_IRQ, USART3_TXC_IRQ,
+    TIMER0_CAPT_IRQ, TIMER0_COMPA_IRQ, TIMER0_COMPB_IRQ,
+        TIMER0_COMPC_IRQ, TIMER0_OVF_IRQ,
+    TIMER1_CAPT_IRQ, TIMER1_COMPA_IRQ, TIMER1_COMPB_IRQ,
+        TIMER1_COMPC_IRQ, TIMER1_OVF_IRQ,
+    TIMER2_CAPT_IRQ, TIMER2_COMPA_IRQ, TIMER2_COMPB_IRQ,
+        TIMER2_COMPC_IRQ, TIMER2_OVF_IRQ,
+    TIMER3_CAPT_IRQ, TIMER3_COMPA_IRQ, TIMER3_COMPB_IRQ,
+        TIMER3_COMPC_IRQ, TIMER3_OVF_IRQ,
+    TIMER4_CAPT_IRQ, TIMER4_COMPA_IRQ, TIMER4_COMPB_IRQ,
+        TIMER4_COMPC_IRQ, TIMER4_OVF_IRQ,
+    TIMER5_CAPT_IRQ, TIMER5_COMPA_IRQ, TIMER5_COMPB_IRQ,
+        TIMER5_COMPC_IRQ, TIMER5_OVF_IRQ,
+    IRQ_COUNT
+};
+
+#define USART_IRQ_COUNT     3
+#define USART_RXC_IRQ(n)    (n * USART_IRQ_COUNT + USART0_RXC_IRQ)
+#define USART_DRE_IRQ(n)    (n * USART_IRQ_COUNT + USART0_DRE_IRQ)
+#define USART_TXC_IRQ(n)    (n * USART_IRQ_COUNT + USART0_TXC_IRQ)
+#define TIMER_IRQ_COUNT     5
+#define TIMER_CAPT_IRQ(n)   (n * TIMER_IRQ_COUNT + TIMER0_CAPT_IRQ)
+#define TIMER_COMPA_IRQ(n)  (n * TIMER_IRQ_COUNT + TIMER0_COMPA_IRQ)
+#define TIMER_COMPB_IRQ(n)  (n * TIMER_IRQ_COUNT + TIMER0_COMPB_IRQ)
+#define TIMER_COMPC_IRQ(n)  (n * TIMER_IRQ_COUNT + TIMER0_COMPC_IRQ)
+#define TIMER_OVF_IRQ(n)    (n * TIMER_IRQ_COUNT + TIMER0_OVF_IRQ)
+
+static const uint8_t irq168_328[IRQ_COUNT] = {
+    [TIMER2_COMPA_IRQ]      = 8,
+    [TIMER2_COMPB_IRQ]      = 9,
+    [TIMER2_OVF_IRQ]        = 10,
+    [TIMER1_CAPT_IRQ]       = 11,
+    [TIMER1_COMPA_IRQ]      = 12,
+    [TIMER1_COMPB_IRQ]      = 13,
+    [TIMER1_OVF_IRQ]        = 14,
+    [TIMER0_COMPA_IRQ]      = 15,
+    [TIMER0_COMPB_IRQ]      = 16,
+    [TIMER0_OVF_IRQ]        = 17,
+    [USART0_RXC_IRQ]        = 19,
+    [USART0_DRE_IRQ]        = 20,
+    [USART0_TXC_IRQ]        = 21,
+}, irq1280_2560[IRQ_COUNT] = {
+    [TIMER2_COMPA_IRQ]      = 14,
+    [TIMER2_COMPB_IRQ]      = 15,
+    [TIMER2_OVF_IRQ]        = 16,
+    [TIMER1_CAPT_IRQ]       = 17,
+    [TIMER1_COMPA_IRQ]      = 18,
+    [TIMER1_COMPB_IRQ]      = 19,
+    [TIMER1_COMPC_IRQ]      = 20,
+    [TIMER1_OVF_IRQ]        = 21,
+    [TIMER0_COMPA_IRQ]      = 22,
+    [TIMER0_COMPB_IRQ]      = 23,
+    [TIMER0_OVF_IRQ]        = 24,
+    [USART0_RXC_IRQ]        = 26,
+    [USART0_DRE_IRQ]        = 27,
+    [USART0_TXC_IRQ]        = 28,
+    [TIMER3_CAPT_IRQ]       = 32,
+    [TIMER3_COMPA_IRQ]      = 33,
+    [TIMER3_COMPB_IRQ]      = 34,
+    [TIMER3_COMPC_IRQ]      = 35,
+    [TIMER3_OVF_IRQ]        = 36,
+    [USART1_RXC_IRQ]        = 37,
+    [USART1_DRE_IRQ]        = 38,
+    [USART1_TXC_IRQ]        = 39,
+    [TIMER4_CAPT_IRQ]       = 42,
+    [TIMER4_COMPA_IRQ]      = 43,
+    [TIMER4_COMPB_IRQ]      = 44,
+    [TIMER4_COMPC_IRQ]      = 45,
+    [TIMER4_OVF_IRQ]        = 46,
+    [TIMER5_CAPT_IRQ]       = 47,
+    [TIMER5_COMPA_IRQ]      = 48,
+    [TIMER5_COMPB_IRQ]      = 49,
+    [TIMER5_COMPC_IRQ]      = 50,
+    [TIMER5_OVF_IRQ]        = 51,
+    [USART2_RXC_IRQ]        = 52,
+    [USART2_DRE_IRQ]        = 53,
+    [USART2_TXC_IRQ]        = 54,
+    [USART3_RXC_IRQ]        = 55,
+    [USART3_DRE_IRQ]        = 56,
+    [USART3_TXC_IRQ]        = 57,
+};
+
+static void connect_peripheral_irq(const AtmegaMcuClass *mc,
+                                   SysBusDevice *sbd,
+                                   DeviceState *dev, int n,
+                                   unsigned peripheral_irq)
+{
+    int irq = mc->irq[peripheral_irq];
+
+    if (!irq) {
+        return;
+    }
+    /* FIXME move that to avr_cpu_set_int() once 'sample' board is removed */
+    assert(irq >= 2);
+    irq -= 2;
+
+    sysbus_connect_irq(sbd, n, qdev_get_gpio_in(dev, irq));
+}
+
+static void connect_power_reduction_gpio(AtmegaMcuState *s,
+                                         const AtmegaMcuClass *mc,
+                                         DeviceState *dev,
+                                         int peripheral_index)
+{
+    unsigned power_index = mc->dev[peripheral_index].power_index;
+    assert(mc->dev[power_index].addr);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pwr[power_index - POWER0]),
+                       mc->dev[peripheral_index].power_bit,
+                       qdev_get_gpio_in(dev, 0));
+}
+
+static void atmega_realize(DeviceState *dev, Error **errp)
+{
+    AtmegaMcuState *s = ATMEGA_MCU(dev);
+    const AtmegaMcuClass *mc = ATMEGA_MCU_GET_CLASS(dev);
+    DeviceState *cpudev;
+    SysBusDevice *sbd;
+    Error *err = NULL;
+    char *devname;
+    size_t i;
+
+    assert(mc->io_size <= 0x200);
+
+    if (!s->xtal_freq_hz) {
+        error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
+        return;
+    }
+
+    /* CPU */
+    object_initialize_child(OBJECT(dev), "cpu", &s->cpu, sizeof(s->cpu),
+                            mc->cpu_type, &err, NULL);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &error_abort);
+    cpudev = DEVICE(&s->cpu);
+
+    /* SRAM */
+    memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size,
+                           &error_abort);
+    memory_region_add_subregion(get_system_memory(),
+                                OFFSET_DATA + mc->io_size, &s->sram);
+
+    /* Flash */
+    memory_region_init_rom(&s->flash, OBJECT(dev),
+                           "flash", mc->flash_size, &error_fatal);
+    memory_region_add_subregion(get_system_memory(), OFFSET_CODE, &s->flash);
+
+    /*
+     * I/O
+     *
+     * 0x00 - 0x1f: Registers
+     * 0x20 - 0x5f: I/O memory
+     * 0x60 - 0xff: Extended I/O
+     */
+    s->io = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE);
+    qdev_prop_set_string(s->io, "name", "I/O");
+    qdev_prop_set_uint64(s->io, "size", mc->io_size);
+    qdev_init_nofail(s->io);
+    sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->io), 0, OFFSET_DATA, -1234);
+
+    /* Power Reduction */
+    for (i = 0; i < POWER_MAX; i++) {
+        int idx = POWER(i);
+        if (!mc->dev[idx].addr) {
+            continue;
+        }
+        devname = g_strdup_printf("power%zu", i);
+        object_initialize_child(OBJECT(dev), devname,
+                                &s->pwr[i], sizeof(s->pwr[i]),
+                                TYPE_AVR_MASK, &error_abort, NULL);
+        object_property_set_bool(OBJECT(&s->pwr[i]), true, "realized",
+                                 &error_abort);
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->pwr[i]), 0,
+                        OFFSET_DATA + mc->dev[idx].addr);
+        g_free(devname);
+    }
+
+    /* GPIO */
+    for (i = 0; i < GPIO_MAX; i++) {
+        int idx = GPIO(i);
+        if (!mc->dev[idx].addr) {
+            continue;
+        }
+        devname = g_strdup_printf("avr-gpio-%c", 'a' + (char)i);
+        create_unimplemented_device(devname,
+                                    OFFSET_DATA + mc->dev[idx].addr, 3);
+        g_free(devname);
+    }
+
+    /* USART */
+    for (i = 0; i < USART_MAX; i++) {
+        int idx = USART(i);
+        if (!mc->dev[idx].addr) {
+            continue;
+        }
+        devname = g_strdup_printf("usart%zu", i);
+        object_initialize_child(OBJECT(dev), devname,
+                                &s->usart[i], sizeof(s->usart[i]),
+                                TYPE_AVR_USART, &error_abort, NULL);
+        qdev_prop_set_chr(DEVICE(&s->usart[i]), "chardev", serial_hd(i));
+        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized",
+                                 &error_abort);
+        sbd = SYS_BUS_DEVICE(&s->usart[i]);
+        sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[USART(i)].addr);
+        connect_peripheral_irq(mc, sbd, cpudev, 0, USART_RXC_IRQ(i));
+        connect_peripheral_irq(mc, sbd, cpudev, 1, USART_DRE_IRQ(i));
+        connect_peripheral_irq(mc, sbd, cpudev, 2, USART_TXC_IRQ(i));
+        connect_power_reduction_gpio(s, mc, DEVICE(&s->usart[i]), idx);
+        g_free(devname);
+    }
+
+    /* Timer */
+    for (i = 0; i < TIMER_MAX; i++) {
+        int idx = TIMER(i);
+        if (!mc->dev[idx].addr) {
+            continue;
+        }
+        if (!mc->dev[idx].is_timer16) {
+            create_unimplemented_device("avr-timer8",
+                                        OFFSET_DATA + mc->dev[idx].addr, 5);
+            create_unimplemented_device("avr-timer8-intmask",
+                                        OFFSET_DATA
+                                        + mc->dev[idx].intmask_addr, 1);
+            create_unimplemented_device("avr-timer8-intflag",
+                                        OFFSET_DATA
+                                        + mc->dev[idx].intflag_addr, 1);
+            continue;
+        }
+        devname = g_strdup_printf("timer%zu", i);
+        object_initialize_child(OBJECT(dev), devname,
+                                &s->timer[i], sizeof(s->timer[i]),
+                                TYPE_AVR_TIMER16, &error_abort, NULL);
+        object_property_set_uint(OBJECT(&s->timer[i]), s->xtal_freq_hz,
+                                 "cpu-frequency-hz", &error_abort);
+        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized",
+                                 &error_abort);
+        sbd = SYS_BUS_DEVICE(&s->timer[i]);
+        sysbus_mmio_map(sbd, 0, OFFSET_DATA + mc->dev[idx].addr);
+        sysbus_mmio_map(sbd, 1, OFFSET_DATA + mc->dev[idx].intmask_addr);
+        sysbus_mmio_map(sbd, 2, OFFSET_DATA + mc->dev[idx].intflag_addr);
+        connect_peripheral_irq(mc, sbd, cpudev, 0, TIMER_CAPT_IRQ(i));
+        connect_peripheral_irq(mc, sbd, cpudev, 1, TIMER_COMPA_IRQ(i));
+        connect_peripheral_irq(mc, sbd, cpudev, 2, TIMER_COMPB_IRQ(i));
+        connect_peripheral_irq(mc, sbd, cpudev, 3, TIMER_COMPC_IRQ(i));
+        connect_peripheral_irq(mc, sbd, cpudev, 4, TIMER_OVF_IRQ(i));
+        connect_power_reduction_gpio(s, mc, DEVICE(&s->timer[i]), idx);
+        g_free(devname);
+    }
+
+    create_unimplemented_device("avr-twi",          OFFSET_DATA + 0x0b8, 6);
+    create_unimplemented_device("avr-adc",          OFFSET_DATA + 0x078, 8);
+    create_unimplemented_device("avr-ext-mem-ctrl", OFFSET_DATA + 0x074, 2);
+    create_unimplemented_device("avr-watchdog",     OFFSET_DATA + 0x060, 1);
+    create_unimplemented_device("avr-spi",          OFFSET_DATA + 0x04c, 3);
+    create_unimplemented_device("avr-eeprom",       OFFSET_DATA + 0x03f, 3);
+}
+
+static Property atmega_props[] = {
+    DEFINE_PROP_UINT64("xtal-frequency-hz", AtmegaMcuState,
+                       xtal_freq_hz, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void atmega_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = atmega_realize;
+    device_class_set_props(dc, atmega_props);
+    /* Reason: Mapped at fixed location on the system bus */
+    dc->user_creatable = false;
+}
+
+static void atmega168_class_init(ObjectClass *oc, void *data)
+{
+    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
+
+    amc->cpu_type = AVR_CPU_TYPE_NAME("avr5");
+    amc->flash_size = 16 * KiB;
+    amc->eeprom_size = 512;
+    amc->sram_size = 1 * KiB;
+    amc->io_size = 256;
+    amc->gpio_count = 23;
+    amc->adc_count = 6;
+    amc->irq = irq168_328;
+    amc->dev = dev168_328;
+};
+
+static void atmega328_class_init(ObjectClass *oc, void *data)
+{
+    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
+
+    amc->cpu_type = AVR_CPU_TYPE_NAME("avr5");
+    amc->flash_size = 32 * KiB;
+    amc->eeprom_size = 1 * KiB;
+    amc->sram_size = 2 * KiB;
+    amc->io_size = 256;
+    amc->gpio_count = 23;
+    amc->adc_count = 6;
+    amc->irq = irq168_328;
+    amc->dev = dev168_328;
+};
+
+static void atmega1280_class_init(ObjectClass *oc, void *data)
+{
+    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
+
+    amc->cpu_type = AVR_CPU_TYPE_NAME("avr6");
+    amc->flash_size = 128 * KiB;
+    amc->eeprom_size = 4 * KiB;
+    amc->sram_size = 8 * KiB;
+    amc->io_size = 512;
+    amc->gpio_count = 86;
+    amc->adc_count = 16;
+    amc->irq = irq1280_2560;
+    amc->dev = dev1280_2560;
+};
+
+static void atmega2560_class_init(ObjectClass *oc, void *data)
+{
+    AtmegaMcuClass *amc = ATMEGA_MCU_CLASS(oc);
+
+    amc->cpu_type = AVR_CPU_TYPE_NAME("avr6");
+    amc->flash_size = 256 * KiB;
+    amc->eeprom_size = 4 * KiB;
+    amc->sram_size = 8 * KiB;
+    amc->io_size = 512;
+    amc->gpio_count = 54;
+    amc->adc_count = 16;
+    amc->irq = irq1280_2560;
+    amc->dev = dev1280_2560;
+};
+
+static const TypeInfo atmega_mcu_types[] = {
+    {
+        .name           = TYPE_ATMEGA168_MCU,
+        .parent         = TYPE_ATMEGA_MCU,
+        .class_init     = atmega168_class_init,
+    }, {
+        .name           = TYPE_ATMEGA328_MCU,
+        .parent         = TYPE_ATMEGA_MCU,
+        .class_init     = atmega328_class_init,
+    }, {
+        .name           = TYPE_ATMEGA1280_MCU,
+        .parent         = TYPE_ATMEGA_MCU,
+        .class_init     = atmega1280_class_init,
+    }, {
+        .name           = TYPE_ATMEGA2560_MCU,
+        .parent         = TYPE_ATMEGA_MCU,
+        .class_init     = atmega2560_class_init,
+    }, {
+        .name           = TYPE_ATMEGA_MCU,
+        .parent         = TYPE_SYS_BUS_DEVICE,
+        .instance_size  = sizeof(AtmegaMcuState),
+        .class_size     = sizeof(AtmegaMcuClass),
+        .class_init     = atmega_class_init,
+        .abstract       = true,
+    }
+};
+
+DEFINE_TYPES(atmega_mcu_types)
diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h
new file mode 100644
index 0000000..1cfbb6b
--- /dev/null
+++ b/hw/avr/atmega.h
@@ -0,0 +1,48 @@ 
+/*
+ * QEMU ATmega MCU
+ *
+ * Copyright (c) 2019 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_AVR_ATMEGA_H
+#define HW_AVR_ATMEGA_H
+
+#include "hw/char/avr_usart.h"
+#include "hw/timer/avr_timer16.h"
+#include "hw/misc/avr_power.h"
+#include "target/avr/cpu.h"
+
+#define TYPE_ATMEGA_MCU     "ATmega"
+#define TYPE_ATMEGA168_MCU  "ATmega168"
+#define TYPE_ATMEGA328_MCU  "ATmega328"
+#define TYPE_ATMEGA1280_MCU "ATmega1280"
+#define TYPE_ATMEGA2560_MCU "ATmega2560"
+
+#define ATMEGA_MCU(obj) OBJECT_CHECK(AtmegaMcuState, (obj), TYPE_ATMEGA_MCU)
+
+#define POWER_MAX 2
+#define USART_MAX 4
+#define TIMER_MAX 6
+#define GPIO_MAX 12
+
+typedef struct AtmegaMcuState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    AVRCPU cpu;
+    MemoryRegion flash;
+    MemoryRegion eeprom;
+    MemoryRegion sram;
+    DeviceState *io;
+    AVRMaskState pwr[POWER_MAX];
+    AVRUsartState usart[USART_MAX];
+    AVRTimer16State timer[TIMER_MAX];
+    uint64_t xtal_freq_hz;
+} AtmegaMcuState;
+
+#endif /* HW_AVR_ATMEGA_H */