mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 08:39:31 +02:00
mtd: rawnand: sunxi: Add support for H616 nand controller
The H616 nand controller has the same base as A10/A23, with some differences: - mdma is based on chained buffers - its ECC supports up to 80bit per 1024bytes - some registers layouts are a bit different, mainly due do the stronger ECC. - it uses USER_DATA_LEN registers along USER_DATA registers. - it needs a specific clock for ECC and MBUS. Introduce the basic support, with ECC and scrambling, but without DMA/MDMA. Tested on Whatsminer H616 board (with and without scrambling, ECC) Signed-off-by: Richard Genoud <richard.genoud@bootlin.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
parent
5ddfbc68ec
commit
88fd4e4dea
|
|
@ -49,17 +49,40 @@
|
|||
#define NFC_REG_A23_IO_DATA 0x0300
|
||||
#define NFC_REG_ECC_CTL 0x0034
|
||||
#define NFC_REG_ECC_ST 0x0038
|
||||
#define NFC_REG_DEBUG 0x003C
|
||||
#define NFC_REG_H6_PAT_FOUND 0x003C
|
||||
#define NFC_REG_A10_ECC_ERR_CNT 0x0040
|
||||
#define NFC_REG_H6_ECC_ERR_CNT 0x0050
|
||||
#define NFC_REG_ECC_ERR_CNT(nfc, x) ((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
|
||||
#define NFC_REG_H6_RDATA_CTL 0x0044
|
||||
#define NFC_REG_H6_RDATA_0 0x0048
|
||||
#define NFC_REG_H6_RDATA_1 0x004C
|
||||
#define NFC_REG_A10_USER_DATA 0x0050
|
||||
#define NFC_REG_H6_USER_DATA 0x0080
|
||||
#define NFC_REG_USER_DATA(nfc, x) (nfc->caps->reg_user_data + ((x) * 4))
|
||||
#define NFC_REG_H6_USER_DATA_LEN 0x0070
|
||||
/* A USER_DATA_LEN register can hold the length of 8 USER_DATA registers */
|
||||
#define NFC_REG_USER_DATA_LEN_CAPACITY 8
|
||||
#define NFC_REG_USER_DATA_LEN(nfc, step) \
|
||||
(nfc->caps->reg_user_data_len + \
|
||||
((step) / NFC_REG_USER_DATA_LEN_CAPACITY) * 4)
|
||||
#define NFC_REG_SPARE_AREA(nfc) (nfc->caps->reg_spare_area)
|
||||
#define NFC_REG_A10_SPARE_AREA 0x00A0
|
||||
#define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id)
|
||||
#define NFC_REG_A10_PAT_ID 0x00A4
|
||||
#define NFC_REG_MDMA_ADDR 0x00C0
|
||||
#define NFC_REG_MDMA_CNT 0x00C4
|
||||
#define NFC_REG_H6_EFNAND_STATUS 0x0110
|
||||
#define NFC_REG_H6_SPARE_AREA 0x0114
|
||||
#define NFC_REG_H6_PAT_ID 0x0118
|
||||
#define NFC_REG_H6_DDR2_SPEC_CTL 0x011C
|
||||
#define NFC_REG_H6_NDMA_MODE_CTL 0x0120
|
||||
#define NFC_REG_H6_MDMA_DLBA_REG 0x0200
|
||||
#define NFC_REG_H6_MDMA_STA 0x0204
|
||||
#define NFC_REG_H6_MDMA_INT_MAS 0x0208
|
||||
#define NFC_REG_H6_MDMA_DESC_ADDR 0x020C
|
||||
#define NFC_REG_H6_MDMA_BUF_ADDR 0x0210
|
||||
#define NFC_REG_H6_MDMA_CNT 0x0214
|
||||
|
||||
#define NFC_RAM0_BASE 0x0400
|
||||
#define NFC_RAM1_BASE 0x0800
|
||||
|
||||
|
|
@ -71,6 +94,7 @@
|
|||
#define NFC_BUS_WIDTH_16 (1 << 2)
|
||||
#define NFC_RB_SEL_MSK BIT(3)
|
||||
#define NFC_RB_SEL(x) ((x) << 3)
|
||||
/* CE_SEL BIT 27 is meant to be used for GPIO chipselect */
|
||||
#define NFC_CE_SEL_MSK GENMASK(26, 24)
|
||||
#define NFC_CE_SEL(x) ((x) << 24)
|
||||
#define NFC_CE_CTL BIT(6)
|
||||
|
|
@ -89,6 +113,9 @@
|
|||
#define NFC_STA BIT(4)
|
||||
#define NFC_NATCH_INT_FLAG BIT(5)
|
||||
#define NFC_RB_STATE(x) BIT(x + 8)
|
||||
#define NFC_RB_STATE_MSK GENMASK(11, 8)
|
||||
#define NDFC_RDATA_STA_1 BIT(12)
|
||||
#define NDFC_RDATA_STA_0 BIT(13)
|
||||
|
||||
/* define bit use in NFC_INT */
|
||||
#define NFC_B2R_INT_ENABLE BIT(0)
|
||||
|
|
@ -100,6 +127,7 @@
|
|||
|
||||
/* define bit use in NFC_TIMING_CTL */
|
||||
#define NFC_TIMING_CTL_EDO BIT(8)
|
||||
#define NFC_TIMING_CTL_E_EDO BIT(9)
|
||||
|
||||
/* define NFC_TIMING_CFG register layout */
|
||||
#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
|
||||
|
|
@ -107,9 +135,15 @@
|
|||
(((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
|
||||
(((tCAD) & 0x7) << 8))
|
||||
|
||||
#define NFC_TIMING_CFG2(tCDQSS, tSC, tCLHZ, tCSS, tWC) \
|
||||
((((tCDQSS) & 0x1) << 11) | (((tSC) & 0x3) << 12) | \
|
||||
(((tCLHZ) & 0x3) << 14) | (((tCSS) & 0x3) << 16) | \
|
||||
(((tWC) & 0x3) << 18))
|
||||
|
||||
/* define bit use in NFC_CMD */
|
||||
#define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0)
|
||||
#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8)
|
||||
#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8) /* 15-10 reserved on H6 */
|
||||
#define NFC_CMD_ADR_NUM_MSK GENMASK(9, 8)
|
||||
#define NFC_CMD(x) (x)
|
||||
#define NFC_ADR_NUM_MSK GENMASK(18, 16)
|
||||
#define NFC_ADR_NUM(x) (((x) - 1) << 16)
|
||||
|
|
@ -122,6 +156,7 @@
|
|||
#define NFC_SEQ BIT(25)
|
||||
#define NFC_DATA_SWAP_METHOD BIT(26)
|
||||
#define NFC_ROW_AUTO_INC BIT(27)
|
||||
#define NFC_H6_SEND_RND_CMD2 BIT(27)
|
||||
#define NFC_SEND_CMD3 BIT(28)
|
||||
#define NFC_SEND_CMD4 BIT(29)
|
||||
#define NFC_CMD_TYPE_MSK GENMASK(31, 30)
|
||||
|
|
@ -133,6 +168,7 @@
|
|||
#define NFC_READ_CMD_MSK GENMASK(7, 0)
|
||||
#define NFC_RND_READ_CMD0_MSK GENMASK(15, 8)
|
||||
#define NFC_RND_READ_CMD1_MSK GENMASK(23, 16)
|
||||
#define NFC_RND_READ_CMD2_MSK GENMASK(31, 24)
|
||||
|
||||
/* define bit use in NFC_WCMD_SET */
|
||||
#define NFC_PROGRAM_CMD_MSK GENMASK(7, 0)
|
||||
|
|
@ -150,6 +186,9 @@
|
|||
#define NFC_RANDOM_DIRECTION(nfc) (nfc->caps->random_dir_mask)
|
||||
#define NFC_ECC_MODE_MSK(nfc) (nfc->caps->ecc_mode_mask)
|
||||
#define NFC_ECC_MODE(nfc, x) field_prep(NFC_ECC_MODE_MSK(nfc), (x))
|
||||
/* RANDOM_PAGE_SIZE: 0: ECC block size 1: page size */
|
||||
#define NFC_A23_RANDOM_PAGE_SIZE BIT(11)
|
||||
#define NFC_H6_RANDOM_PAGE_SIZE BIT(7)
|
||||
#define NFC_RANDOM_SEED_MSK GENMASK(30, 16)
|
||||
#define NFC_RANDOM_SEED(x) ((x) << 16)
|
||||
|
||||
|
|
@ -165,6 +204,9 @@
|
|||
|
||||
#define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff)
|
||||
|
||||
#define NFC_USER_DATA_LEN_MSK(step) \
|
||||
(0xf << (((step) % NFC_REG_USER_DATA_LEN_CAPACITY) * 4))
|
||||
|
||||
#define NFC_DEFAULT_TIMEOUT_MS 1000
|
||||
|
||||
#define NFC_MAX_CS 7
|
||||
|
|
@ -235,9 +277,12 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
|
|||
* @has_mdma: Use mbus dma mode, otherwise general dma
|
||||
* through MBUS on A23/A33 needs extra configuration.
|
||||
* @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks
|
||||
* @has_ecc_clk: If the controller needs an ECC clock.
|
||||
* @has_mbus_clk: If the controller needs a mbus clock.
|
||||
* @reg_io_data: I/O data register
|
||||
* @reg_ecc_err_cnt: ECC error counter register
|
||||
* @reg_user_data: User data register
|
||||
* @reg_user_data_len: User data length register
|
||||
* @reg_spare_area: Spare Area Register
|
||||
* @reg_pat_id: Pattern ID Register
|
||||
* @reg_pat_found: Data Pattern Status Register
|
||||
|
|
@ -249,14 +294,24 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
|
|||
* @dma_maxburst: DMA maxburst
|
||||
* @ecc_strengths: Available ECC strengths array
|
||||
* @nstrengths: Size of @ecc_strengths
|
||||
* @max_ecc_steps: Maximum supported steps for ECC, this is also the
|
||||
* number of user data registers
|
||||
* @user_data_len_tab: Table of lenghts supported by USER_DATA_LEN register
|
||||
* The table index is the value to set in NFC_USER_DATA_LEN
|
||||
* registers, and the corresponding value is the number of
|
||||
* bytes to write
|
||||
* @nuser_data_tab: Size of @user_data_len_tab
|
||||
* @sram_size: Size of the NAND controller SRAM
|
||||
*/
|
||||
struct sunxi_nfc_caps {
|
||||
bool has_mdma;
|
||||
bool has_ecc_block_512;
|
||||
bool has_ecc_clk;
|
||||
bool has_mbus_clk;
|
||||
unsigned int reg_io_data;
|
||||
unsigned int reg_ecc_err_cnt;
|
||||
unsigned int reg_user_data;
|
||||
unsigned int reg_user_data_len;
|
||||
unsigned int reg_spare_area;
|
||||
unsigned int reg_pat_id;
|
||||
unsigned int reg_pat_found;
|
||||
|
|
@ -268,6 +323,9 @@ struct sunxi_nfc_caps {
|
|||
unsigned int dma_maxburst;
|
||||
const u8 *ecc_strengths;
|
||||
unsigned int nstrengths;
|
||||
const u8 *user_data_len_tab;
|
||||
unsigned int nuser_data_tab;
|
||||
unsigned int max_ecc_steps;
|
||||
int sram_size;
|
||||
};
|
||||
|
||||
|
|
@ -279,6 +337,8 @@ struct sunxi_nfc_caps {
|
|||
* @regs: NAND controller registers
|
||||
* @ahb_clk: NAND controller AHB clock
|
||||
* @mod_clk: NAND controller mod clock
|
||||
* @ecc_clk: NAND controller ECC clock
|
||||
* @mbus_clk: NAND controller MBUS clock
|
||||
* @reset: NAND controller reset line
|
||||
* @assigned_cs: bitmask describing already assigned CS lines
|
||||
* @clk_rate: NAND controller current clock rate
|
||||
|
|
@ -294,6 +354,8 @@ struct sunxi_nfc {
|
|||
void __iomem *regs;
|
||||
struct clk *ahb_clk;
|
||||
struct clk *mod_clk;
|
||||
struct clk *ecc_clk;
|
||||
struct clk *mbus_clk;
|
||||
struct reset_control *reset;
|
||||
unsigned long assigned_cs;
|
||||
unsigned long clk_rate;
|
||||
|
|
@ -774,6 +836,53 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
|
|||
sunxi_nfc_randomize_bbm(nand, page, oob);
|
||||
}
|
||||
|
||||
/*
|
||||
* On H6/H6 the user_data length has to be set in specific registers
|
||||
* before writing.
|
||||
*/
|
||||
static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc)
|
||||
{
|
||||
int loop_step = NFC_REG_USER_DATA_LEN_CAPACITY;
|
||||
|
||||
/* not all SoCs have this register */
|
||||
if (!nfc->caps->reg_user_data_len)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step)
|
||||
writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i));
|
||||
}
|
||||
|
||||
static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc,
|
||||
int len, int step)
|
||||
{
|
||||
bool found = false;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
/* not all SoCs have this register */
|
||||
if (!nfc->caps->reg_user_data_len)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nfc->caps->nuser_data_tab; i++) {
|
||||
if (len == nfc->caps->user_data_len_tab[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
dev_warn(nfc->dev,
|
||||
"Unsupported length for user data reg: %d\n", len);
|
||||
return;
|
||||
}
|
||||
|
||||
val = readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
|
||||
|
||||
val &= ~NFC_USER_DATA_LEN_MSK(step);
|
||||
val |= field_prep(NFC_USER_DATA_LEN_MSK(step), i);
|
||||
writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
|
||||
}
|
||||
|
||||
static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
|
||||
const u8 *oob, int step,
|
||||
bool bbm, int page)
|
||||
|
|
@ -868,6 +977,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
sunxi_nfc_reset_user_data_len(nfc);
|
||||
sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0);
|
||||
sunxi_nfc_randomizer_config(nand, page, false);
|
||||
sunxi_nfc_randomizer_enable(nand);
|
||||
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
|
||||
|
|
@ -978,6 +1089,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
|
|||
return ret;
|
||||
|
||||
sunxi_nfc_hw_ecc_enable(nand);
|
||||
sunxi_nfc_reset_user_data_len(nfc);
|
||||
sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0);
|
||||
sunxi_nfc_randomizer_config(nand, page, false);
|
||||
sunxi_nfc_randomizer_enable(nand);
|
||||
|
||||
|
|
@ -1110,6 +1223,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
|
|||
|
||||
sunxi_nfc_randomizer_config(nand, page, false);
|
||||
sunxi_nfc_randomizer_enable(nand);
|
||||
sunxi_nfc_reset_user_data_len(nfc);
|
||||
sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0);
|
||||
sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
|
||||
|
||||
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
|
||||
|
|
@ -1354,10 +1469,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
|
|||
if (ret)
|
||||
goto pio_fallback;
|
||||
|
||||
sunxi_nfc_reset_user_data_len(nfc);
|
||||
for (i = 0; i < ecc->steps; i++) {
|
||||
const u8 *oob = nand->oob_poi + (i * (ecc->bytes + USER_DATA_SZ));
|
||||
|
||||
sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
|
||||
sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, i);
|
||||
}
|
||||
|
||||
nand_prog_page_begin_op(nand, page, 0, NULL, 0);
|
||||
|
|
@ -2158,6 +2275,10 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
|
|||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
nfc->caps = of_device_get_match_data(dev);
|
||||
if (!nfc->caps)
|
||||
return -EINVAL;
|
||||
|
||||
nfc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
|
||||
if (IS_ERR(nfc->ahb_clk)) {
|
||||
dev_err(dev, "failed to retrieve ahb clk\n");
|
||||
|
|
@ -2170,6 +2291,22 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(nfc->mod_clk);
|
||||
}
|
||||
|
||||
if (nfc->caps->has_ecc_clk) {
|
||||
nfc->ecc_clk = devm_clk_get_enabled(dev, "ecc");
|
||||
if (IS_ERR(nfc->ecc_clk)) {
|
||||
dev_err(dev, "failed to retrieve ecc clk\n");
|
||||
return PTR_ERR(nfc->ecc_clk);
|
||||
}
|
||||
}
|
||||
|
||||
if (nfc->caps->has_mbus_clk) {
|
||||
nfc->mbus_clk = devm_clk_get_enabled(dev, "mbus");
|
||||
if (IS_ERR(nfc->mbus_clk)) {
|
||||
dev_err(dev, "failed to retrieve mbus clk\n");
|
||||
return PTR_ERR(nfc->mbus_clk);
|
||||
}
|
||||
}
|
||||
|
||||
nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
|
||||
if (IS_ERR(nfc->reset))
|
||||
return PTR_ERR(nfc->reset);
|
||||
|
|
@ -2180,12 +2317,6 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
nfc->caps = of_device_get_match_data(&pdev->dev);
|
||||
if (!nfc->caps) {
|
||||
ret = -EINVAL;
|
||||
goto out_ahb_reset_reassert;
|
||||
}
|
||||
|
||||
ret = sunxi_nfc_rst(nfc);
|
||||
if (ret)
|
||||
goto out_ahb_reset_reassert;
|
||||
|
|
@ -2236,6 +2367,14 @@ static const u8 sunxi_ecc_strengths_a10[] = {
|
|||
16, 24, 28, 32, 40, 48, 56, 60, 64
|
||||
};
|
||||
|
||||
static const u8 sunxi_ecc_strengths_h6[] = {
|
||||
16, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80
|
||||
};
|
||||
|
||||
static const u8 sunxi_user_data_len_h6[] = {
|
||||
0, 4, 8, 12, 16, 20, 24, 28, 32
|
||||
};
|
||||
|
||||
static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
|
||||
.has_ecc_block_512 = true,
|
||||
.reg_io_data = NFC_REG_A10_IO_DATA,
|
||||
|
|
@ -2252,6 +2391,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
|
|||
.dma_maxburst = 4,
|
||||
.ecc_strengths = sunxi_ecc_strengths_a10,
|
||||
.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
|
||||
.max_ecc_steps = 16,
|
||||
.sram_size = 1024,
|
||||
};
|
||||
|
||||
|
|
@ -2272,9 +2412,34 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
|
|||
.dma_maxburst = 8,
|
||||
.ecc_strengths = sunxi_ecc_strengths_a10,
|
||||
.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
|
||||
.max_ecc_steps = 16,
|
||||
.sram_size = 1024,
|
||||
};
|
||||
|
||||
static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
|
||||
.has_ecc_clk = true,
|
||||
.has_mbus_clk = true,
|
||||
.reg_io_data = NFC_REG_A23_IO_DATA,
|
||||
.reg_ecc_err_cnt = NFC_REG_H6_ECC_ERR_CNT,
|
||||
.reg_user_data = NFC_REG_H6_USER_DATA,
|
||||
.reg_user_data_len = NFC_REG_H6_USER_DATA_LEN,
|
||||
.reg_spare_area = NFC_REG_H6_SPARE_AREA,
|
||||
.reg_pat_id = NFC_REG_H6_PAT_ID,
|
||||
.reg_pat_found = NFC_REG_H6_PAT_FOUND,
|
||||
.random_en_mask = BIT(5),
|
||||
.random_dir_mask = BIT(6),
|
||||
.ecc_mode_mask = GENMASK(15, 8),
|
||||
.ecc_err_mask = GENMASK(31, 0),
|
||||
.pat_found_mask = GENMASK(31, 0),
|
||||
.dma_maxburst = 8,
|
||||
.ecc_strengths = sunxi_ecc_strengths_h6,
|
||||
.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_h6),
|
||||
.user_data_len_tab = sunxi_user_data_len_h6,
|
||||
.nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
|
||||
.max_ecc_steps = 32,
|
||||
.sram_size = 8192,
|
||||
};
|
||||
|
||||
static const struct of_device_id sunxi_nfc_ids[] = {
|
||||
{
|
||||
.compatible = "allwinner,sun4i-a10-nand",
|
||||
|
|
@ -2284,6 +2449,10 @@ static const struct of_device_id sunxi_nfc_ids[] = {
|
|||
.compatible = "allwinner,sun8i-a23-nand-controller",
|
||||
.data = &sunxi_nfc_a23_caps,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun50i-h616-nand-controller",
|
||||
.data = &sunxi_nfc_h616_caps,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user