Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/linux-sunxi/sunxi-tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Przywara <osp@andrep.de>2022-07-29 13:59:36 +0300
committerGitHub <noreply@github.com>2022-07-29 13:59:36 +0300
commit457c11302e8ac953be6f67f782135da016832307 (patch)
tree757a70ea6f2847aac75ea2809ca1887ad5274635
parentae3db3195de4671c3700791c640e3013302dad96 (diff)
parentc347538a2069e360e08abb1822284792b259d7c7 (diff)
Merge pull request #178 from Icenowy/v853
V853 support
-rw-r--r--fel_lib.c30
-rw-r--r--soc_info.c17
-rw-r--r--soc_info.h2
-rw-r--r--uart0-helloworld-sdboot.c71
4 files changed, 91 insertions, 29 deletions
diff --git a/fel_lib.c b/fel_lib.c
index f038224..2db6154 100644
--- a/fel_lib.c
+++ b/fel_lib.c
@@ -40,6 +40,7 @@ struct _felusb_handle {
libusb_device_handle *handle;
int endpoint_out, endpoint_in;
bool iface_detached;
+ bool icache_hacked;
};
/* a helper function to report libusb errors */
@@ -214,7 +215,7 @@ void aw_fel_read(feldev_handle *dev, uint32_t offset, void *buf, size_t len)
}
/* AW_FEL_1_WRITE request */
-void aw_fel_write(feldev_handle *dev, const void *buf, uint32_t offset, size_t len)
+static void aw_fel_write_raw(feldev_handle *dev, const void *buf, uint32_t offset, size_t len)
{
if (len == 0)
return;
@@ -231,6 +232,33 @@ void aw_fel_execute(feldev_handle *dev, uint32_t offset)
aw_read_fel_status(dev);
}
+static void aw_disable_icache(feldev_handle *dev)
+{
+ soc_info_t *soc_info = dev->soc_info;
+ uint32_t arm_code[] = {
+ /* Clear SCTLR.I */
+ htole32(0xee110f10), /* mrc 15, 0, r0, cr1, cr0, {0} ;SCTLR */
+ htole32(0xe3c00a01), /* bic r0, r0, #0x1000 */
+ htole32(0xee010f10), /* mcr 15, 0, r0, cr1, cr0, {0} ;SCTLR */
+ /* Invalidate I-Cache */
+ htole32(0xee070f15), /* mcr 15, 0, r0, cr7, cr5, {0} ;ICIALLU */
+ /* Barrier to force instruction refetching */
+ htole32(0xf57ff06f), /* isb sy */
+ htole32(0xe12fff1e), /* bx lr */
+ };
+ aw_fel_write_raw(dev, arm_code, soc_info->scratch_addr, sizeof(arm_code));
+ aw_fel_execute(dev, soc_info->scratch_addr);
+}
+
+void aw_fel_write(feldev_handle *dev, const void *buf, uint32_t offset, size_t len)
+{
+ if (dev->soc_info->icache_fix && !dev->usb->icache_hacked) {
+ aw_disable_icache(dev);
+ dev->usb->icache_hacked = true;
+ }
+ aw_fel_write_raw(dev, buf, offset, len);
+}
+
/*
* This function is a higher-level wrapper for the FEL write functionality.
* Unlike aw_fel_write() above - which is reserved for internal use - this
diff --git a/soc_info.c b/soc_info.c
index dbbb052..455f5cf 100644
--- a/soc_info.c
+++ b/soc_info.c
@@ -182,6 +182,11 @@ const watchdog_info wd_h6_compat = {
.reg_mode_value = 1,
};
+const watchdog_info wd_v853_compat = {
+ .reg_mode = 0x020500b8,
+ .reg_mode_value = 0x16aa0001,
+};
+
soc_info_t soc_info_table[] = {
{
.soc_id = 0x1623, /* Allwinner A10 */
@@ -393,6 +398,18 @@ soc_info_t soc_info_table[] = {
.rvbar_reg = 0x08100040,
.watchdog = &wd_h6_compat,
},{
+ .soc_id = 0x1886, /* Allwinner V853 */
+ .name = "V853",
+ .spl_addr = 0x20000,
+ .scratch_addr = 0x21000,
+ .thunk_addr = 0x3A200, .thunk_size = 0x200,
+ .swap_buffers = v831_sram_swap_buffers,
+ .sram_size = 132 * 1024,
+ .sid_base = 0x03006000,
+ .sid_offset = 0x200,
+ .icache_fix = true,
+ .watchdog = &wd_v853_compat,
+ },{
.swap_buffers = NULL /* End of the table */
}
};
diff --git a/soc_info.h b/soc_info.h
index 5609fe6..f7ab8e5 100644
--- a/soc_info.h
+++ b/soc_info.h
@@ -113,6 +113,8 @@ typedef struct {
uint32_t rvbar_reg; /* MMIO address of RVBARADDR0_L register */
const watchdog_info *watchdog; /* Used for reset */
bool sid_fix; /* Use SID workaround (read via register) */
+ /* Use I$ workaround (disable I$ before first write to prevent stale thunk */
+ bool icache_fix;
/* Use SMC workaround (enter secure mode) if can't read from this address */
uint32_t needs_smc_workaround_if_zero_word_at_addr;
uint32_t sram_size; /* Usable contiguous SRAM at spl_addr */
diff --git a/uart0-helloworld-sdboot.c b/uart0-helloworld-sdboot.c
index 019461b..1055512 100644
--- a/uart0-helloworld-sdboot.c
+++ b/uart0-helloworld-sdboot.c
@@ -69,6 +69,8 @@ typedef unsigned int u32;
#define R329_UART0_BASE 0x02500000
#define R329_PIO_BASE 0x02000400
#define R329_CCM_BASE 0x02001000
+
+#define V853_PIO_BASE 0x02000000
/*****************************************************************************
* GPIO code, borrowed from U-Boot *
*****************************************************************************/
@@ -83,26 +85,19 @@ typedef unsigned int u32;
#define SUNXI_GPIO_H 7
#define SUNXI_GPIO_I 8
-struct sunxi_gpio {
- u32 cfg[4];
- u32 dat;
- u32 drv[2];
- u32 pull[2];
-};
-
-struct sunxi_gpio_reg {
- struct sunxi_gpio gpio_bank[10];
-};
-
#define GPIO_BANK(pin) ((pin) >> 5)
#define GPIO_NUM(pin) ((pin) & 0x1F)
+#define GPIO_CFG_BASE(bank) ((u32 *)(pio_base + (bank) * pio_bank_size))
#define GPIO_CFG_INDEX(pin) (((pin) & 0x1F) >> 3)
#define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1F) & 0x7) << 2)
+#define GPIO_PULL_BASE(bank) ((u32 *)(pio_base + (bank) * pio_bank_size + pio_pull_off))
#define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
#define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+#define GPIO_DAT_BASE(bank) ((u32 *)(pio_base + (bank) * pio_bank_size + pio_dat_off))
+
/* GPIO bank sizes */
#define SUNXI_GPIO_A_NR (32)
#define SUNXI_GPIO_B_NR (32)
@@ -148,6 +143,7 @@ enum sunxi_gpio_number {
#define SUN8I_H3_GPA_UART0 (2)
#define SUN8I_V3S_GPB_UART0 (3)
#define SUN8I_V831_GPH_UART0 (5)
+#define SUN8I_V853_GPH_UART0 (5)
#define SUN50I_H5_GPA_UART0 (2)
#define SUN50I_H6_GPH_UART0 (2)
#define SUN50I_H616_GPH_UART0 (2)
@@ -161,6 +157,7 @@ enum sunxi_gpio_number {
#define SUNXI_GPIO_PULL_DOWN (2)
static u32 pio_base;
+static u32 pio_bank_size, pio_dat_off, pio_pull_off;
int sunxi_gpio_set_cfgpin(u32 pin, u32 val)
{
@@ -168,12 +165,11 @@ int sunxi_gpio_set_cfgpin(u32 pin, u32 val)
u32 bank = GPIO_BANK(pin);
u32 index = GPIO_CFG_INDEX(pin);
u32 offset = GPIO_CFG_OFFSET(pin);
- struct sunxi_gpio *pio =
- &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
- cfg = readl(&pio->cfg[0] + index);
+ u32 *addr = GPIO_CFG_BASE(bank) + index;
+ cfg = readl(addr);
cfg &= ~(0xf << offset);
cfg |= val << offset;
- writel(cfg, &pio->cfg[0] + index);
+ writel(cfg, addr);
return 0;
}
@@ -183,12 +179,11 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
u32 bank = GPIO_BANK(pin);
u32 index = GPIO_PULL_INDEX(pin);
u32 offset = GPIO_PULL_OFFSET(pin);
- struct sunxi_gpio *pio =
- &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
- cfg = readl(&pio->pull[0] + index);
+ u32 *addr = GPIO_PULL_BASE(bank) + index;
+ cfg = readl(addr);
cfg &= ~(0x3 << offset);
cfg |= val << offset;
- writel(cfg, &pio->pull[0] + index);
+ writel(cfg, addr);
return 0;
}
@@ -197,14 +192,13 @@ int sunxi_gpio_output(u32 pin, u32 val)
u32 dat;
u32 bank = GPIO_BANK(pin);
u32 num = GPIO_NUM(pin);
- struct sunxi_gpio *pio =
- &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
- dat = readl(&pio->dat);
+ u32 *addr = GPIO_DAT_BASE(bank);
+ dat = readl(addr);
if(val)
dat |= 1 << num;
else
dat &= ~(1 << num);
- writel(dat, &pio->dat);
+ writel(dat, addr);
return 0;
}
@@ -213,9 +207,8 @@ int sunxi_gpio_input(u32 pin)
u32 dat;
u32 bank = GPIO_BANK(pin);
u32 num = GPIO_NUM(pin);
- struct sunxi_gpio *pio =
- &((struct sunxi_gpio_reg *)pio_base)->gpio_bank[bank];
- dat = readl(&pio->dat);
+ u32 *addr = GPIO_DAT_BASE(bank);
+ dat = readl(addr);
dat >>= num;
return (dat & 0x1);
}
@@ -316,6 +309,7 @@ void soc_detection_init(void)
#define soc_is_r40() (soc_id == 0x1701)
#define soc_is_v3s() (soc_id == 0x1681)
#define soc_is_v831() (soc_id == 0x1817)
+#define soc_is_v853() (soc_id == 0x1886)
/* A10s and A13 share the same ID, so we need a little more effort on those */
@@ -402,7 +396,7 @@ void clock_init_uart(void)
{
if (soc_is_h6() || soc_is_v831() || soc_is_h616())
clock_init_uart_h6();
- else if (soc_is_r329())
+ else if (soc_is_r329() || soc_is_v853())
clock_init_uart_r329();
else
clock_init_uart_legacy();
@@ -416,6 +410,18 @@ void clock_init_uart(void)
void gpio_init(void)
{
+ if (soc_is_v853()) {
+ /* GPIO V2 */
+ pio_bank_size = 0x30;
+ pio_dat_off = 0x10;
+ pio_pull_off = 0x24;
+ } else {
+ /* GPIO V1 */
+ pio_bank_size = 0x24;
+ pio_dat_off = 0x10;
+ pio_pull_off = 0x1c;
+ }
+
if (soc_is_a10() || soc_is_a20() || soc_is_r40()) {
sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB_UART0);
@@ -468,6 +474,10 @@ void gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPH(9), SUN8I_V831_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(10), SUN8I_V831_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(10), SUNXI_GPIO_PULL_UP);
+ } else if (soc_is_v853()) {
+ sunxi_gpio_set_cfgpin(SUNXI_GPH(9), SUN8I_V853_GPH_UART0);
+ sunxi_gpio_set_cfgpin(SUNXI_GPH(10), SUN8I_V853_GPH_UART0);
+ sunxi_gpio_set_pull(SUNXI_GPH(10), SUNXI_GPIO_PULL_UP);
} else {
/* Unknown SoC */
while (1) {}
@@ -544,7 +554,7 @@ int get_boot_device(void)
u32 *spl_signature = (void *)0x4;
if (soc_is_a64() || soc_is_a80() || soc_is_h5())
spl_signature = (void *)0x10004;
- if (soc_is_h6() || soc_is_v831() || soc_is_h616())
+ if (soc_is_h6() || soc_is_v831() || soc_is_h616() || soc_is_v853())
spl_signature = (void *)0x20004;
if (soc_is_r329())
spl_signature = (void *)0x100004;
@@ -570,6 +580,9 @@ void bases_init(void)
} else if (soc_is_r329()) {
pio_base = R329_PIO_BASE;
uart0_base = R329_UART0_BASE;
+ } else if (soc_is_v853()) {
+ pio_base = V853_PIO_BASE;
+ uart0_base = R329_UART0_BASE;
} else {
pio_base = SUNXI_PIO_BASE;
uart0_base = SUNXI_UART0_BASE;
@@ -614,6 +627,8 @@ int main(void)
uart0_puts("Allwinner V3s!\n");
else if (soc_is_v831())
uart0_puts("Allwinner V831!\n");
+ else if (soc_is_v853())
+ uart0_puts("Allwinner V853!\n");
else
uart0_puts("unknown Allwinner SoC!\n");