163
/* Read Timing Compensation Register */
164
#define R_TIMINGS (0x94 / 4)
165
166
+/* Data fifo */
167
+#define R_DATA_FIFO (0x200 / 4)
168
+
169
/* SPI controller registers and bits (AST2400) */
170
#define R_SPI_CONF (0x00 / 4)
171
#define SPI_CONF_ENABLE_W0 0
212
#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2
213
#define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4
214
#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08
215
+#define ASPEED_SMC_FEATURE_DATA_FIFO 0x10
216
217
static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc)
218
{
229
return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH);
230
}
231
232
+static inline bool aspeed_smc_has_data_fifo(const AspeedSMCClass *asc)
233
+{
234
+ return !!(asc->features & ASPEED_SMC_FEATURE_DATA_FIFO);
235
+}
236
+
237
#define aspeed_smc_error(fmt, ...) \
238
qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
239
673
{
674
AspeedSMCState *s = ASPEED_SMC(opaque);
675
AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(opaque);
676
+ int cs;
677
678
addr >>= 2;
679
699
trace_aspeed_smc_read(addr << 2, size, s->regs[addr]);
700
701
*data = s->regs[addr];
702
+ } else if (aspeed_smc_has_data_fifo(asc) && addr >= R_DATA_FIFO) {
703
+ cs = asc->data_fifo_offset_to_cs(s, addr << 2);
704
+ if (cs >= 0) {
705
+ /*
706
+ * Data fifo mode only supports SPI user mode.
707
+ * The flash address is provided by the SPI command/address cycles,
708
+ * the MMIO addr parameter is ignored.
709
+ */
710
+ return aspeed_smc_flash_read(&s->flashes[cs], 0, data, size, attrs);
711
+ }
712
+ aspeed_smc_error("Invalid data fifo offset %" HWADDR_PRIx, addr << 2);
713
+ return MEMTX_ERROR;
714
} else {
715
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
716
__func__, addr);
1085
} else if (aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) &&
1086
addr == R_DMA_DRAM_ADDR_HIGH) {
1087
s->regs[addr] = DMA_DRAM_ADDR_HIGH(value);
1088
+ } else if (aspeed_smc_has_data_fifo(asc) && addr >= R_DATA_FIFO) {
1089
+ int cs = asc->data_fifo_offset_to_cs(s, addr << 2);
1090
+ if (cs >= 0) {
1091
+ /*
1092
+ * Data fifo mode only supports SPI user mode.
1093
+ * The flash address is provided by the SPI command/address cycles,
1094
+ * the MMIO addr parameter is ignored.
1095
+ */
1096
+ return aspeed_smc_flash_write(&s->flashes[cs], 0, data, size,
1097
+ attrs);
1098
+ }
1099
+ aspeed_smc_error("Invalid data fifo offset %" HWADDR_PRIx, addr << 2);
1100
+ return MEMTX_ERROR;
1101
} else {
1102
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
1103
__func__, addr);
1218
1219
static const VMStateDescription vmstate_aspeed_smc = {
1220
.name = "aspeed.smc",
1186
- .version_id = 3,
1187
- .minimum_version_id = 1,
1221
+ .version_id = 4,
1222
+ .minimum_version_id = 2,
1223
.fields = (const VMStateField[]) {
1224
VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX),
1225
VMSTATE_UNUSED_V(2, 2), /* was snoop_index/snoop_dummies */
1843
}
1844
}
1845
1846
+/*
1847
+ * Convert a data fifo offset to a chip select (CS).
1848
+ *
1849
+ * Data fifo access starts at 0x200. The data fifo offset index is
1850
+ * calculated by subtracting the data fifo base offset from the MMIO address.
1851
+ *
1852
+ * The data fifo offset index increments by 1 for every 16MB of flash address
1853
+ * space. Each offset step therefore represents a 16MB address decode range.
1854
+ *
1855
+ * The CS is determined by matching the data fifo offset index against the
1856
+ * segment start address of each CS.
1857
+ *
1858
+ * Returns the CS index on success, or -1 if the offset is invalid.
1859
+ */
1860
+static int aspeed_2700_smc_data_fifo_offset_to_cs(const AspeedSMCState *s,
1861
+ uint32_t offset)
1862
+{
1863
+ AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
1864
+ uint32_t start_offset;
1865
+ uint32_t fifo_offset;
1866
+ int i;
1867
+
1868
+ for (i = 0; i < asc->cs_num_max; i++) {
1869
+ start_offset = (s->regs[R_SEG_ADDR0 + i] & 0x0000ffff) << 16;
1870
+ fifo_offset = start_offset / 0x1000000;
1871
+ if (fifo_offset == offset - (R_DATA_FIFO << 2)) {
1872
+ return i;
1873
+ }
1874
+ }
1875
+
1876
+ return -1;
1877
+}
1878
+
1879
static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = {
1880
[R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 |
1881
CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1),
1910
{ 0x0, 0 }, /* disabled */
1911
};
1912
1913
+/*
1914
+ * AST2700 supports data fifo mode with a base data fifo start offset of 0x200.
1915
+ *
1916
+ * The data fifo start offset increments by 1 for every 16MB of flash address
1917
+ * space. Each offset step therefore represents a 16MB address decode range.
1918
+ *
1919
+ * Assuming each chip select (CS) can use the maximum flash size of 256MB:
1920
+ * 256MB / 16MB = 0x10 offset steps per CS.
1921
+ *
1922
+ * Data fifo start offset for CSn:
1923
+ * 0x200 + (n * 0x10)
1924
+ *
1925
+ * Examples:
1926
+ * CS0: 0x200
1927
+ * CS1: 0x210
1928
+ * CS2: 0x220
1929
+ * CS3: 0x230
1930
+ *
1931
+ * asc->nregs should be set to: 0x200 + (asc->cs_num_max * 0x10)
1932
+ * to cover all possible data fifo regions.
1933
+ */
1934
static void aspeed_2700_fmc_class_init(ObjectClass *klass, const void *data)
1935
{
1936
DeviceClass *dc = DEVICE_CLASS(klass);
1950
asc->flash_window_base = 0x100000000;
1951
asc->flash_window_size = 1 * GiB;
1952
asc->features = ASPEED_SMC_FEATURE_DMA |
1864
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
1953
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
1954
+ ASPEED_SMC_FEATURE_DATA_FIFO;
1955
asc->dma_flash_mask = 0x2FFFFFFC;
1956
asc->dma_dram_mask = 0xFFFFFFFC;
1957
asc->dma_start_length = 1;
1868
- asc->nregs = ASPEED_SMC_R_MAX;
1958
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
1959
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
1960
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
1961
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
1962
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
1963
asc->reg_ops = &aspeed_2700_smc_flash_ops;
1964
}
1965
1987
asc->flash_window_base = 0x180000000;
1988
asc->flash_window_size = 1 * GiB;
1989
asc->features = ASPEED_SMC_FEATURE_DMA |
1899
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
1990
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
1991
+ ASPEED_SMC_FEATURE_DATA_FIFO;
1992
asc->dma_flash_mask = 0x2FFFFFFC;
1993
asc->dma_dram_mask = 0xFFFFFFFC;
1994
asc->dma_start_length = 1;
1903
- asc->nregs = ASPEED_SMC_R_MAX;
1995
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
1996
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
1997
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
1998
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
1999
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
2000
asc->reg_ops = &aspeed_2700_smc_flash_ops;
2001
}
2002
2023
asc->flash_window_base = 0x200000000;
2024
asc->flash_window_size = 1 * GiB;
2025
asc->features = ASPEED_SMC_FEATURE_DMA |
1933
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
2026
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
2027
+ ASPEED_SMC_FEATURE_DATA_FIFO;
2028
asc->dma_flash_mask = 0x2FFFFFFC;
2029
asc->dma_dram_mask = 0xFFFFFFFC;
2030
asc->dma_start_length = 1;
1937
- asc->nregs = ASPEED_SMC_R_MAX;
2031
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
2032
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
2033
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
2034
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
2035
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
2036
asc->reg_ops = &aspeed_2700_smc_flash_ops;
2037
}
2038
2059
asc->flash_window_base = 0x280000000;
2060
asc->flash_window_size = 1 * GiB;
2061
asc->features = ASPEED_SMC_FEATURE_DMA |
1967
- ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH;
2062
+ ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH |
2063
+ ASPEED_SMC_FEATURE_DATA_FIFO;
2064
asc->dma_flash_mask = 0x0FFFFFFC;
2065
asc->dma_dram_mask = 0xFFFFFFFC;
2066
asc->dma_start_length = 1;
1971
- asc->nregs = ASPEED_SMC_R_MAX;
2067
+ asc->nregs = (0x200 + (asc->cs_num_max * 0x10)) >> 2;
2068
asc->segment_to_reg = aspeed_2700_smc_segment_to_reg;
2069
asc->reg_to_segment = aspeed_2700_smc_reg_to_segment;
2070
asc->dma_ctrl = aspeed_2600_smc_dma_ctrl;
2071
+ asc->data_fifo_offset_to_cs = aspeed_2700_smc_data_fifo_offset_to_cs;
2072
asc->reg_ops = &aspeed_2700_smc_flash_ops;
2073
}
2074