Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support

The Loongson-2K0500 NAND controller is similar to the Loongson-1C.

It supports a maximum capacity of 16GB FLASH per chip with a maximum
page size of 8KB, and it supports up to 4 chip selects and 4 RDY
signals.

Its DMA controller is defaulted to APBDMA0.

Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

authored by

Binbin Zhou and committed by
Miquel Raynal
e55bbdd4 4a2bab7c

+53 -2
+1 -1
drivers/mtd/nand/raw/Kconfig
··· 438 438 439 439 config MTD_NAND_LOONGSON 440 440 tristate "Loongson NAND controller" 441 - depends on LOONGSON1_APB_DMA || COMPILE_TEST 441 + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST 442 442 select REGMAP_MMIO 443 443 help 444 444 Enables support for NAND controller on Loongson family chips.
+52 -1
drivers/mtd/nand/raw/loongson-nand-controller.c
··· 3 3 * NAND Controller Driver for Loongson family chips 4 4 * 5 5 * Copyright (C) 2015-2025 Keguang Zhang <keguang.zhang@gmail.com> 6 + * Copyright (C) 2025 Binbin Zhou <zhoubinbin@loongson.cn> 6 7 */ 7 8 8 9 #include <linux/kernel.h> ··· 27 26 #define LOONGSON_NAND_IDH_STATUS 0x14 28 27 #define LOONGSON_NAND_PARAM 0x18 29 28 #define LOONGSON_NAND_OP_NUM 0x1c 29 + #define LOONGSON_NAND_CS_RDY_MAP 0x20 30 30 31 31 /* Bitfields of nand command register */ 32 32 #define LOONGSON_NAND_CMD_OP_DONE BIT(10) ··· 41 39 #define LOONGSON_NAND_CMD_WRITE BIT(2) 42 40 #define LOONGSON_NAND_CMD_READ BIT(1) 43 41 #define LOONGSON_NAND_CMD_VALID BIT(0) 42 + 43 + /* Bitfields of nand cs/rdy map register */ 44 + #define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8) 45 + #define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12) 46 + #define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16) 47 + #define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20) 48 + #define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24) 49 + #define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28) 50 + 51 + #define LOONGSON_NAND_CS_SEL0 BIT(0) 52 + #define LOONGSON_NAND_CS_SEL1 BIT(1) 53 + #define LOONGSON_NAND_CS_SEL2 BIT(2) 54 + #define LOONGSON_NAND_CS_SEL3 BIT(3) 55 + #define LOONGSON_NAND_CS_RDY0 BIT(0) 56 + #define LOONGSON_NAND_CS_RDY1 BIT(1) 57 + #define LOONGSON_NAND_CS_RDY2 BIT(2) 58 + #define LOONGSON_NAND_CS_RDY3 BIT(3) 44 59 45 60 /* Bitfields of nand timing register */ 46 61 #define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0) ··· 102 83 unsigned int hold_cycle; 103 84 unsigned int wait_cycle; 104 85 unsigned int nand_cs; 86 + unsigned int dma_bits; 105 87 void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op); 106 88 }; 107 89 ··· 764 744 struct device *dev = host->dev; 765 745 struct dma_chan *chan; 766 746 struct dma_slave_config cfg = {}; 767 - int ret; 747 + int ret, val; 768 748 769 749 host->regmap = devm_regmap_init_mmio(dev, host->reg_base, &loongson_nand_regmap_config); 770 750 if (IS_ERR(host->regmap)) ··· 773 753 if (host->data->id_cycle_field) 774 754 regmap_update_bits(host->regmap, LOONGSON_NAND_PARAM, host->data->id_cycle_field, 775 755 host->data->max_id_cycle << __ffs(host->data->id_cycle_field)); 756 + 757 + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(host->data->dma_bits)); 758 + if (ret) 759 + return dev_err_probe(dev, ret, "failed to set DMA mask\n"); 760 + 761 + val = FIELD_PREP(LOONGSON_NAND_MAP_CS1_SEL, LOONGSON_NAND_CS_SEL1) | 762 + FIELD_PREP(LOONGSON_NAND_MAP_RDY1_SEL, LOONGSON_NAND_CS_RDY1) | 763 + FIELD_PREP(LOONGSON_NAND_MAP_CS2_SEL, LOONGSON_NAND_CS_SEL2) | 764 + FIELD_PREP(LOONGSON_NAND_MAP_RDY2_SEL, LOONGSON_NAND_CS_RDY2) | 765 + FIELD_PREP(LOONGSON_NAND_MAP_CS3_SEL, LOONGSON_NAND_CS_SEL3) | 766 + FIELD_PREP(LOONGSON_NAND_MAP_RDY3_SEL, LOONGSON_NAND_CS_RDY3); 767 + 768 + regmap_write(host->regmap, LOONGSON_NAND_CS_RDY_MAP, val); 776 769 777 770 chan = dma_request_chan(dev, "rxtx"); 778 771 if (IS_ERR(chan)) ··· 915 882 .status_field = GENMASK(15, 8), 916 883 .hold_cycle = 0x2, 917 884 .wait_cycle = 0xc, 885 + .dma_bits = 32, 918 886 .set_addr = ls1b_nand_set_addr, 919 887 }; 920 888 ··· 926 892 .op_scope_field = GENMASK(29, 16), 927 893 .hold_cycle = 0x2, 928 894 .wait_cycle = 0xc, 895 + .dma_bits = 32, 896 + .set_addr = ls1c_nand_set_addr, 897 + }; 898 + 899 + static const struct loongson_nand_data ls2k0500_nand_data = { 900 + .max_id_cycle = 6, 901 + .id_cycle_field = GENMASK(14, 12), 902 + .status_field = GENMASK(23, 16), 903 + .op_scope_field = GENMASK(29, 16), 904 + .hold_cycle = 0x4, 905 + .wait_cycle = 0x12, 906 + .dma_bits = 64, 929 907 .set_addr = ls1c_nand_set_addr, 930 908 }; 931 909 ··· 949 903 { 950 904 .compatible = "loongson,ls1c-nand-controller", 951 905 .data = &ls1c_nand_data, 906 + }, 907 + { 908 + .compatible = "loongson,ls2k0500-nand-controller", 909 + .data = &ls2k0500_nand_data, 952 910 }, 953 911 { /* sentinel */ } 954 912 }; ··· 970 920 module_platform_driver(loongson_nand_driver); 971 921 972 922 MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>"); 923 + MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>"); 973 924 MODULE_DESCRIPTION("Loongson NAND Controller Driver"); 974 925 MODULE_LICENSE("GPL");