Unverified Commit 7cc37c88 authored by Chen-Yu Tsai's avatar Chen-Yu Tsai Committed by GitHub
Browse files

Merge pull request #140 from Icenowy/v831

V831 SoC support
parents e334ccf5 eac43cf7
...@@ -81,6 +81,10 @@ void fel_writel(feldev_handle *dev, uint32_t addr, uint32_t val); ...@@ -81,6 +81,10 @@ void fel_writel(feldev_handle *dev, uint32_t addr, uint32_t val);
#define SUN6I_BUS_SOFT_RST_REG0 (0x01C20000 + 0x2C0) #define SUN6I_BUS_SOFT_RST_REG0 (0x01C20000 + 0x2C0)
#define SUN6I_SPI0_RST (1 << 20) #define SUN6I_SPI0_RST (1 << 20)
#define H6_CCM_SPI0_CLK (0x03001000 + 0x940)
#define H6_CCM_SPI_BGR (0x03001000 + 0x96C)
#define H6_CCM_SPI0_GATE_RESET (1 << 0 | 1 << 16)
#define SUNXI_GPC_SPI0 (3) #define SUNXI_GPC_SPI0 (3)
#define SUN50I_GPC_SPI0 (4) #define SUN50I_GPC_SPI0 (4)
...@@ -92,35 +96,61 @@ void fel_writel(feldev_handle *dev, uint32_t addr, uint32_t val); ...@@ -92,35 +96,61 @@ void fel_writel(feldev_handle *dev, uint32_t addr, uint32_t val);
#define SUN6I_TCR_XCH (1 << 31) #define SUN6I_TCR_XCH (1 << 31)
#define SUN4I_SPI0_CCTL (0x01C05000 + 0x1C) #define SUN4I_SPI0_CCTL (spi_base(dev) + 0x1C)
#define SUN4I_SPI0_CTL (0x01C05000 + 0x08) #define SUN4I_SPI0_CTL (spi_base(dev) + 0x08)
#define SUN4I_SPI0_RX (0x01C05000 + 0x00) #define SUN4I_SPI0_RX (spi_base(dev) + 0x00)
#define SUN4I_SPI0_TX (0x01C05000 + 0x04) #define SUN4I_SPI0_TX (spi_base(dev) + 0x04)
#define SUN4I_SPI0_FIFO_STA (0x01C05000 + 0x28) #define SUN4I_SPI0_FIFO_STA (spi_base(dev) + 0x28)
#define SUN4I_SPI0_BC (0x01C05000 + 0x20) #define SUN4I_SPI0_BC (spi_base(dev) + 0x20)
#define SUN4I_SPI0_TC (0x01C05000 + 0x24) #define SUN4I_SPI0_TC (spi_base(dev) + 0x24)
#define SUN6I_SPI0_CCTL (0x01C68000 + 0x24) #define SUN6I_SPI0_CCTL (spi_base(dev) + 0x24)
#define SUN6I_SPI0_GCR (0x01C68000 + 0x04) #define SUN6I_SPI0_GCR (spi_base(dev) + 0x04)
#define SUN6I_SPI0_TCR (0x01C68000 + 0x08) #define SUN6I_SPI0_TCR (spi_base(dev) + 0x08)
#define SUN6I_SPI0_FIFO_STA (0x01C68000 + 0x1C) #define SUN6I_SPI0_FIFO_STA (spi_base(dev) + 0x1C)
#define SUN6I_SPI0_MBC (0x01C68000 + 0x30) #define SUN6I_SPI0_MBC (spi_base(dev) + 0x30)
#define SUN6I_SPI0_MTC (0x01C68000 + 0x34) #define SUN6I_SPI0_MTC (spi_base(dev) + 0x34)
#define SUN6I_SPI0_BCC (0x01C68000 + 0x38) #define SUN6I_SPI0_BCC (spi_base(dev) + 0x38)
#define SUN6I_SPI0_TXD (0x01C68000 + 0x200) #define SUN6I_SPI0_TXD (spi_base(dev) + 0x200)
#define SUN6I_SPI0_RXD (0x01C68000 + 0x300) #define SUN6I_SPI0_RXD (spi_base(dev) + 0x300)
#define CCM_SPI0_CLK_DIV_BY_2 (0x1000) #define CCM_SPI0_CLK_DIV_BY_2 (0x1000)
#define CCM_SPI0_CLK_DIV_BY_4 (0x1001) #define CCM_SPI0_CLK_DIV_BY_4 (0x1001)
#define CCM_SPI0_CLK_DIV_BY_6 (0x1002) #define CCM_SPI0_CLK_DIV_BY_6 (0x1002)
static uint32_t gpio_base(feldev_handle *dev)
{
soc_info_t *soc_info = dev->soc_info;
switch (soc_info->soc_id) {
case 0x1817: /* V831 */
return 0x0300B000;
default:
return 0x01C28000;
}
}
static uint32_t spi_base(feldev_handle *dev)
{
soc_info_t *soc_info = dev->soc_info;
switch (soc_info->soc_id) {
case 0x1623: /* A10 */
case 0x1625: /* A13 */
case 0x1651: /* A20 */
return 0x01C05000;
case 0x1817: /* V831 */
return 0x05010000;
default:
return 0x01C68000;
}
}
/* /*
* Configure pin function on a GPIO port * Configure pin function on a GPIO port
*/ */
static void gpio_set_cfgpin(feldev_handle *dev, int port_num, int pin_num, static void gpio_set_cfgpin(feldev_handle *dev, int port_num, int pin_num,
int val) int val)
{ {
uint32_t port_base = 0x01C20800 + port_num * 0x24; uint32_t port_base = gpio_base(dev) + port_num * 0x24;
uint32_t cfg_reg = port_base + 4 * (pin_num / 8); uint32_t cfg_reg = port_base + 4 * (pin_num / 8);
uint32_t pin_idx = pin_num % 8; uint32_t pin_idx = pin_num % 8;
uint32_t x = readl(cfg_reg); uint32_t x = readl(cfg_reg);
...@@ -142,6 +172,17 @@ static bool spi_is_sun6i(feldev_handle *dev) ...@@ -142,6 +172,17 @@ static bool spi_is_sun6i(feldev_handle *dev)
} }
} }
static bool soc_is_h6_style(feldev_handle *dev)
{
soc_info_t *soc_info = dev->soc_info;
switch (soc_info->soc_id) {
case 0x1817: /* V831 */
return true;
default:
return false;
}
}
/* /*
* Init the SPI0 controller and setup pins muxing. * Init the SPI0 controller and setup pins muxing.
*/ */
...@@ -179,27 +220,46 @@ static bool spi0_init(feldev_handle *dev) ...@@ -179,27 +220,46 @@ static bool spi0_init(feldev_handle *dev)
gpio_set_cfgpin(dev, PC, 2, SUN50I_GPC_SPI0); gpio_set_cfgpin(dev, PC, 2, SUN50I_GPC_SPI0);
gpio_set_cfgpin(dev, PC, 3, SUN50I_GPC_SPI0); gpio_set_cfgpin(dev, PC, 3, SUN50I_GPC_SPI0);
break; break;
case 0x1817: /* Allwinner V831 */
gpio_set_cfgpin(dev, PC, 0, SUN50I_GPC_SPI0);
gpio_set_cfgpin(dev, PC, 1, SUN50I_GPC_SPI0);
gpio_set_cfgpin(dev, PC, 2, SUN50I_GPC_SPI0);
gpio_set_cfgpin(dev, PC, 3, SUN50I_GPC_SPI0);
break;
default: /* Unknown/Unsupported SoC */ default: /* Unknown/Unsupported SoC */
printf("SPI support not implemented yet for %x (%s)!\n", printf("SPI support not implemented yet for %x (%s)!\n",
soc_info->soc_id, soc_info->name); soc_info->soc_id, soc_info->name);
return false; return false;
} }
reg_val = readl(CCM_AHB_GATING0); if (soc_is_h6_style(dev)) {
reg_val |= CCM_AHB_GATE_SPI0; reg_val = readl(H6_CCM_SPI_BGR);
writel(reg_val, CCM_AHB_GATING0); reg_val |= H6_CCM_SPI0_GATE_RESET;
writel(reg_val, H6_CCM_SPI_BGR);
/* 24MHz from OSC24M */
writel((1 << 31), H6_CCM_SPI0_CLK);
} else {
reg_val = readl(CCM_AHB_GATING0);
reg_val |= CCM_AHB_GATE_SPI0;
writel(reg_val, CCM_AHB_GATING0);
if (spi_is_sun6i(dev)) {
/* Deassert SPI0 reset */
reg_val = readl(SUN6I_BUS_SOFT_RST_REG0);
reg_val |= SUN6I_SPI0_RST;
writel(reg_val, SUN6I_BUS_SOFT_RST_REG0);
}
/* 24MHz from OSC24M */
writel((1 << 31), CCM_SPI0_CLK);
}
/* 24MHz from OSC24M */
writel((1 << 31), CCM_SPI0_CLK);
/* divide by 4 */ /* divide by 4 */
writel(CCM_SPI0_CLK_DIV_BY_4, spi_is_sun6i(dev) ? SUN6I_SPI0_CCTL : writel(CCM_SPI0_CLK_DIV_BY_4, spi_is_sun6i(dev) ? SUN6I_SPI0_CCTL :
SUN4I_SPI0_CCTL); SUN4I_SPI0_CCTL);
if (spi_is_sun6i(dev)) { if (spi_is_sun6i(dev)) {
/* Deassert SPI0 reset */
reg_val = readl(SUN6I_BUS_SOFT_RST_REG0);
reg_val |= SUN6I_SPI0_RST;
writel(reg_val, SUN6I_BUS_SOFT_RST_REG0);
/* Enable SPI in the master mode and do a soft reset */ /* Enable SPI in the master mode and do a soft reset */
reg_val = readl(SUN6I_SPI0_GCR); reg_val = readl(SUN6I_SPI0_GCR);
reg_val |= (1 << 31) | 3; reg_val |= (1 << 31) | 3;
......
...@@ -110,6 +110,21 @@ sram_swap_buffers h6_sram_swap_buffers[] = { ...@@ -110,6 +110,21 @@ sram_swap_buffers h6_sram_swap_buffers[] = {
{ .size = 0 } /* End of the table */ { .size = 0 } /* End of the table */
}; };
/*
* V831 has 96KiB SRAM A1 at 0x20000 where the SPL has to be loaded to.
* SRAM C is continuous with SRAM A1, and both SRAMs are tried to be used
* by BROM. Memory space is allocated both from the start of SRAM A1 and
* the end of SRAM C.
* The start of SRAM C is in between these areas, and can serve as backup
* of IRQ stack, which is inside the first 32KiB of SRAM A1. Other areas
* that are critical on older SoCs seem to be already in SRAM C, which
* we do not need to preserve.
*/
sram_swap_buffers v831_sram_swap_buffers[] = {
{ .buf1 = 0x21000, .buf2 = 0x38000, .size = 0x1000 },
{ .size = 0 } /* End of the table */
};
const watchdog_info wd_a10_compat = { const watchdog_info wd_a10_compat = {
.reg_mode = 0x01C20C94, .reg_mode = 0x01C20C94,
.reg_mode_value = 3, .reg_mode_value = 3,
...@@ -250,6 +265,15 @@ soc_info_t soc_info_table[] = { ...@@ -250,6 +265,15 @@ soc_info_t soc_info_table[] = {
.rvbar_reg = 0x09010040, .rvbar_reg = 0x09010040,
/* Check L.NOP in the OpenRISC reset vector */ /* Check L.NOP in the OpenRISC reset vector */
.needs_smc_workaround_if_zero_word_at_addr = 0x100004, .needs_smc_workaround_if_zero_word_at_addr = 0x100004,
},{
.soc_id = 0x1817, /* Allwinner V831 */
.name = "V831",
.spl_addr = 0x20000,
.scratch_addr = 0x21000,
.thunk_addr = 0x2A200, .thunk_size = 0x200,
.swap_buffers = v831_sram_swap_buffers,
.sid_base = 0x03006000,
.sid_offset = 0x200,
},{ },{
.swap_buffers = NULL /* End of the table */ .swap_buffers = NULL /* End of the table */
} }
......
...@@ -144,6 +144,7 @@ enum sunxi_gpio_number { ...@@ -144,6 +144,7 @@ enum sunxi_gpio_number {
#define SUN6I_GPH_UART0 (2) #define SUN6I_GPH_UART0 (2)
#define SUN8I_H3_GPA_UART0 (2) #define SUN8I_H3_GPA_UART0 (2)
#define SUN8I_V3S_GPB_UART0 (3) #define SUN8I_V3S_GPB_UART0 (3)
#define SUN8I_V831_GPH_UART0 (5)
#define SUN50I_H5_GPA_UART0 (2) #define SUN50I_H5_GPA_UART0 (2)
#define SUN50I_H6_GPH_UART0 (2) #define SUN50I_H6_GPH_UART0 (2)
#define SUN50I_A64_GPB_UART0 (4) #define SUN50I_A64_GPB_UART0 (4)
...@@ -307,6 +308,7 @@ void soc_detection_init(void) ...@@ -307,6 +308,7 @@ void soc_detection_init(void)
#define soc_is_h6() (soc_id == 0x1728) #define soc_is_h6() (soc_id == 0x1728)
#define soc_is_r40() (soc_id == 0x1701) #define soc_is_r40() (soc_id == 0x1701)
#define soc_is_v3s() (soc_id == 0x1681) #define soc_is_v3s() (soc_id == 0x1681)
#define soc_is_v831() (soc_id == 0x1817)
/* A10s and A13 share the same ID, so we need a little more effort on those */ /* A10s and A13 share the same ID, so we need a little more effort on those */
...@@ -382,7 +384,7 @@ void clock_init_uart_h6(void) ...@@ -382,7 +384,7 @@ void clock_init_uart_h6(void)
void clock_init_uart(void) void clock_init_uart(void)
{ {
if (soc_is_h6()) if (soc_is_h6() || soc_is_v831())
clock_init_uart_h6(); clock_init_uart_h6();
else else
clock_init_uart_legacy(); clock_init_uart_legacy();
...@@ -436,6 +438,10 @@ void gpio_init(void) ...@@ -436,6 +438,10 @@ void gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN8I_V3S_GPB_UART0); sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN8I_V3S_GPB_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_V3S_GPB_UART0); sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_V3S_GPB_UART0);
sunxi_gpio_set_pull(SUNXI_GPB(9), SUNXI_GPIO_PULL_UP); sunxi_gpio_set_pull(SUNXI_GPB(9), SUNXI_GPIO_PULL_UP);
} else if (soc_is_v831()) {
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 { } else {
/* Unknown SoC */ /* Unknown SoC */
while (1) {} while (1) {}
...@@ -512,7 +518,7 @@ int get_boot_device(void) ...@@ -512,7 +518,7 @@ int get_boot_device(void)
u32 *spl_signature = (void *)0x4; u32 *spl_signature = (void *)0x4;
if (soc_is_a64() || soc_is_a80() || soc_is_h5()) if (soc_is_a64() || soc_is_a80() || soc_is_h5())
spl_signature = (void *)0x10004; spl_signature = (void *)0x10004;
if (soc_is_h6()) if (soc_is_h6() || soc_is_v831())
spl_signature = (void *)0x20004; spl_signature = (void *)0x20004;
/* Check the eGON.BT0 magic in the SPL header */ /* Check the eGON.BT0 magic in the SPL header */
...@@ -530,7 +536,7 @@ int get_boot_device(void) ...@@ -530,7 +536,7 @@ int get_boot_device(void)
void bases_init(void) void bases_init(void)
{ {
if (soc_is_h6()) { if (soc_is_h6() || soc_is_v831()) {
pio_base = H6_PIO_BASE; pio_base = H6_PIO_BASE;
uart0_base = H6_UART0_BASE; uart0_base = H6_UART0_BASE;
} else { } else {
...@@ -571,6 +577,8 @@ int main(void) ...@@ -571,6 +577,8 @@ int main(void)
uart0_puts("Allwinner R40!\n"); uart0_puts("Allwinner R40!\n");
else if (soc_is_v3s()) else if (soc_is_v3s())
uart0_puts("Allwinner V3s!\n"); uart0_puts("Allwinner V3s!\n");
else if (soc_is_v831())
uart0_puts("Allwinner V831!\n");
else else
uart0_puts("unknown Allwinner SoC!\n"); uart0_puts("unknown Allwinner SoC!\n");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment