# SPDX-License-Identifier: GPL-2.0

-include arch/avr/devs/devices.Makefile

export CPU := $(cpu-y)

CONFIG_OPTIMIZATION := $(patsubst "%",%,$(CONFIG_OPTIMIZATION))

KBUILD_CFLAGS += -O$(CONFIG_OPTIMIZATION)
KBUILD_CFLAGS += -fpack-struct -fshort-enums
KBUILD_CFLAGS += -fno-unroll-loops
KBUILD_CFLAGS += -Iarch/$(ARCH) $(CFLAGS-y)

# stack
ifeq ($(CONFIG_SCHEDULER),y)
KBUILD_CFLAGS += -fno-defer-pop
KBUILD_CFLAGS += -fconserve-stack
endif

# Optimizations which seem useful:
KBUILD_CFLAGS += -frename-registers
ifeq ($(CONFIG_OPTIMIZATION_LTO),y)
KBUILD_CFLAGS += -flto
endif


# Not supported by all compilers:
# KBUILD_CFLAGS_Os += -frtl-abstract-sequences
KBUILD_CFLAGS_O3 += -fipa-cp

KBUILD_CFLAGS += $(KBUILD_CFLAGS_O$(CONFIG_OPTIMIZATION))

KBUILD_CFLAGS  += -mmcu=$(CPU)
KBUILD_CFLAGS  += -I arch/avr/devs/$(CPU)/include
KBUILD_AFLAGS  := -mmcu=$(CPU) $(KBUILD_AFLAGS)
KBUILD_AFLAGS  += -I arch/avr/devs/$(CPU)/include

# LINKER_CPU := avr$(shell touch .empty.c ; $(CC) -dM -E -mmcu=$(CPU) .empty.c | grep "__AVR_ARCH__" | sed s/\#define\ __AVR_ARCH__\ // ; rm .empty.c)
KBUILD_LDFLAGS += -mmcu=$(CPU)
KBUILD_LDFLAGS += -nostartfiles
ifeq ($(CONFIG_OPTIMIZATION_LTO),y)
KBUILD_LDFLAGS += -flto
endif

# FIXME: check if this is not yet provided by the main Makefile
KBUILD_CPPFLAGS	+= -Iarch/$(SRCARCH)/include
KBUILD_AFLAGS	+= -Iarch/$(SRCARCH)/include

core-y                    += arch/avr/kernel/
# head-$(CONFIG_IRQ)        += arch/avr/kernel/head.o
head-y                    += arch/avr/kernel/init.o
head-$(CONFIG_IRQ_COMMON) += arch/avr/kernel/interrupt.o

BOOT_TARGETS := rupsched.bin rupsched.hex

PHONY += $(BOOT_TARGETS)

# all: rupsched.hex
#KBUILD_IMAGE := rupsched.bin

$(BOOT_TARGETS): rupsched.o

OBJCOPY := $(ARCH)-objcopy
ifneq ($(V),1)
MYMSG := @echo
else
MYMSG := @true
endif

rupsched.hex:
	$(MYMSG) "  OBJDUMP rupsched.dump"
	$(Q)$(OBJDUMP) -s -d rupsched.o >rupsched.dump
	$(MYMSG) "  OBJCOPY $@"
ifeq ($(CONFIG_COMPRESS_DATA),y)
	$(Q)$(OBJCOPY) -j .text -j .compressed_data -O ihex rupsched.o rupsched.hex
else
	$(Q)$(OBJCOPY) -j .text -j .data -O ihex rupsched.o rupsched.hex
endif
ifeq ($(CONFIG_OPTIMIZATION_LTO),y)
	@size rupsched.o
else
	@find kernel arch drivers lib apps tests rupsched.o -name "*.o" | xargs size --common
endif

rupsched.bin:
	$(MYMSG) "  OBJDUMP rupsched.dump"
	$(Q)$(OBJDUMP) -s -d rupsched.o >rupsched.dump
# 	$(MYMSG) "  OBJDUMP rupsched.reloc"
# 	$(Q)$(OBJDUMP) -r rupsched.o >rupsched.reloc
ifeq ($(CONFIG_TIMER)-$(CONFIG_DYNAMIC_TICK),y-)
	$(MYMSG) "  CALC_PRESCALER"
	$(Q)arch/avr/scripts/calc_prescaler
endif
	$(MYMSG) "  OBJCOPY $@"
ifeq ($(CONFIG_COMPRESS_DATA),y)
	$(Q)$(OBJCOPY) -j .text -j .compressed_data -O binary rupsched.o rupsched.bin
else
	$(Q)$(OBJCOPY) -j .text -j .data -O binary rupsched.o rupsched.bin
endif
ifeq ($(CONFIG_OPTIMIZATION_LTO),y)
	@size rupsched.o
else
	@find kernel arch drivers lib apps tests rupsched.o -name "*.o" | xargs size --common
endif

archclean:
	rm -f rupsched.bin rupsched.dump rupsched.hex

define archhelp
  @echo '* rupsched.hex    - Build image in intel hex format'
  @echo '* rupsched.bin    - Build image in binary format'
  @echo '  upload          - Upload kernel using avrdude'
  @echo '  fuses           - Calculate fuse values from the config'
  @echo '  read_fuses      - Read fuse values from the controller'
  @echo '  burn_fuses      - Burn fuse values to the controller'
endef


AVRDUDE_OPTS += $(subst $\",,$(CONFIG_AVRDUDE_OPTIONS))
AVRDUDE_OPTS += -p $(CPU)
AVRDUDE_OPTS += -V

upload: rupsched.bin
	$(MYMSG) " AVRDUDE $<"
	$(Q)avrdude $(AVRDUDE_OPTS) -U flash:w:$<:r

xconfig: arch/avr/devs
gconfig: arch/avr/devs
menuconfig: arch/avr/devs
nconfig: arch/avr/devs
oldconfig: arch/avr/devs
syncconfig: arch/avr/devs

arch/avr/devs:
	$(MYMSG) "  GEN     $@"
	$(Q)arch/avr/scripts/decode_packs

ifneq ($(CPU),)
NUM_FUSE_BYTES := $(shell printf "%d" $$[1+$$(grep FUSES_END arch/avr/devs/$(CPU)/include/asm/limits.h | sed "s/\#define\ FUSES_END//")])
endif

.PHONY: fuses
fuses: fuses.hex
	$(eval LFUSE:=$(shell F="$$(cat $^)";echo $${F:9:2}))
	$(eval HFUSE:=$(shell F="$$(cat $^)";echo $${F:11:2}))
ifeq ($(NUM_FUSE_BYTES),3)
	$(eval EFUSE:=$(shell F="$$(cat $^)";echo $${F:13:2}))
endif
	@echo "lfuse = 0x$(LFUSE)"
	@echo "hfuse = 0x$(HFUSE)"
ifeq ($(NUM_FUSE_BYTES),3)
	@echo "efuse = 0x$(EFUSE)"
endif

fuses.hex: arch/avr/fuse/fusecalc.o
	$(MYMSG) "  OBJCOPY $@"
	$(Q)$(OBJCOPY) -j .fuses -O ihex $^ $@

burn_fuses: fuses.hex
	$(eval LFUSE:=$(shell F="$$(cat $^)";echo $${F:9:2}))
	$(eval HFUSE:=$(shell F="$$(cat $^)";echo $${F:11:2}))
ifeq ($(NUM_FUSE_BYTES),3)
	$(eval EFUSE:=$(shell F="$$(cat $^)";echo $${F:13:2}))
	@echo LFUSE=$(LFUSE) HFUSE=$(HFUSE) EFUSE=$(EFUSE)
else
	@echo LFUSE=$(LFUSE) HFUSE=$(HFUSE)
endif
	@echo -n "Are you sure (y/N)?"
	@read answer ; test "$$answer" = "y"
ifeq ($(NUM_FUSE_BYTES),3)
	$(Q)avrdude $(AVRDUDE_OPTS) -U lfuse:w:0x$(LFUSE):m -U hfuse:w:0x$(HFUSE):m -U efuse:w:0x$(EFUSE):m
else
	$(Q)avrdude $(AVRDUDE_OPTS) -U lfuse:w:0x$(LFUSE):m -U hfuse:w:0x$(HFUSE):m
endif

read_fuses:
	$(MYMSG) "  AVRDUDE $<"
	@echo "Your current fuse configuration is:"
ifeq ($(NUM_FUSE_BYTES),3)
	$(Q)avrdude $(AVRDUDE_OPTS) -qq -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h
else
	$(Q)avrdude $(AVRDUDE_OPTS) -qq -U lfuse:r:-:h -U hfuse:r:-:h
endif
