33 * NAND Controller Driver for Loongson family chips
44 *
55 * Copyright (C) 2015-2025 Keguang Zhang <keguang.zhang@gmail.com>
6+ * Copyright (C) 2025 Binbin Zhou <zhoubinbin@loongson.cn>
67 */
78
89#include <linux/kernel.h>
2627#define LOONGSON_NAND_IDH_STATUS 0x14
2728#define LOONGSON_NAND_PARAM 0x18
2829#define LOONGSON_NAND_OP_NUM 0x1c
30+ #define LOONGSON_NAND_CS_RDY_MAP 0x20
2931
3032/* Bitfields of nand command register */
3133#define LOONGSON_NAND_CMD_OP_DONE BIT(10)
4042#define LOONGSON_NAND_CMD_READ BIT(1)
4143#define LOONGSON_NAND_CMD_VALID BIT(0)
4244
45+ /* Bitfields of nand cs/rdy map register */
46+ #define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8)
47+ #define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12)
48+ #define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16)
49+ #define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20)
50+ #define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24)
51+ #define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28)
52+
53+ #define LOONGSON_NAND_CS_SEL0 BIT(0)
54+ #define LOONGSON_NAND_CS_SEL1 BIT(1)
55+ #define LOONGSON_NAND_CS_SEL2 BIT(2)
56+ #define LOONGSON_NAND_CS_SEL3 BIT(3)
57+ #define LOONGSON_NAND_CS_RDY0 BIT(0)
58+ #define LOONGSON_NAND_CS_RDY1 BIT(1)
59+ #define LOONGSON_NAND_CS_RDY2 BIT(2)
60+ #define LOONGSON_NAND_CS_RDY3 BIT(3)
61+
4362/* Bitfields of nand timing register */
4463#define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)
4564#define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
@@ -83,6 +102,7 @@ struct loongson_nand_data {
83102 unsigned int hold_cycle ;
84103 unsigned int wait_cycle ;
85104 unsigned int nand_cs ;
105+ unsigned int dma_bits ;
86106 void (* set_addr )(struct loongson_nand_host * host , struct loongson_nand_op * op );
87107};
88108
@@ -744,7 +764,7 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
744764 struct device * dev = host -> dev ;
745765 struct dma_chan * chan ;
746766 struct dma_slave_config cfg = {};
747- int ret ;
767+ int ret , val ;
748768
749769 host -> regmap = devm_regmap_init_mmio (dev , host -> reg_base , & loongson_nand_regmap_config );
750770 if (IS_ERR (host -> regmap ))
@@ -754,6 +774,19 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
754774 regmap_update_bits (host -> regmap , LOONGSON_NAND_PARAM , host -> data -> id_cycle_field ,
755775 host -> data -> max_id_cycle << __ffs (host -> data -> id_cycle_field ));
756776
777+ ret = dma_set_mask_and_coherent (dev , DMA_BIT_MASK (host -> data -> dma_bits ));
778+ if (ret )
779+ return dev_err_probe (dev , ret , "failed to set DMA mask\n" );
780+
781+ val = FIELD_PREP (LOONGSON_NAND_MAP_CS1_SEL , LOONGSON_NAND_CS_SEL1 ) |
782+ FIELD_PREP (LOONGSON_NAND_MAP_RDY1_SEL , LOONGSON_NAND_CS_RDY1 ) |
783+ FIELD_PREP (LOONGSON_NAND_MAP_CS2_SEL , LOONGSON_NAND_CS_SEL2 ) |
784+ FIELD_PREP (LOONGSON_NAND_MAP_RDY2_SEL , LOONGSON_NAND_CS_RDY2 ) |
785+ FIELD_PREP (LOONGSON_NAND_MAP_CS3_SEL , LOONGSON_NAND_CS_SEL3 ) |
786+ FIELD_PREP (LOONGSON_NAND_MAP_RDY3_SEL , LOONGSON_NAND_CS_RDY3 );
787+
788+ regmap_write (host -> regmap , LOONGSON_NAND_CS_RDY_MAP , val );
789+
757790 chan = dma_request_chan (dev , "rxtx" );
758791 if (IS_ERR (chan ))
759792 return dev_err_probe (dev , PTR_ERR (chan ), "failed to request DMA channel\n" );
@@ -882,6 +915,7 @@ static const struct loongson_nand_data ls1b_nand_data = {
882915 .status_field = GENMASK (15 , 8 ),
883916 .hold_cycle = 0x2 ,
884917 .wait_cycle = 0xc ,
918+ .dma_bits = 32 ,
885919 .set_addr = ls1b_nand_set_addr ,
886920};
887921
@@ -892,6 +926,18 @@ static const struct loongson_nand_data ls1c_nand_data = {
892926 .op_scope_field = GENMASK (29 , 16 ),
893927 .hold_cycle = 0x2 ,
894928 .wait_cycle = 0xc ,
929+ .dma_bits = 32 ,
930+ .set_addr = ls1c_nand_set_addr ,
931+ };
932+
933+ static const struct loongson_nand_data ls2k0500_nand_data = {
934+ .max_id_cycle = 6 ,
935+ .id_cycle_field = GENMASK (14 , 12 ),
936+ .status_field = GENMASK (23 , 16 ),
937+ .op_scope_field = GENMASK (29 , 16 ),
938+ .hold_cycle = 0x4 ,
939+ .wait_cycle = 0x12 ,
940+ .dma_bits = 64 ,
895941 .set_addr = ls1c_nand_set_addr ,
896942};
897943
@@ -904,6 +950,10 @@ static const struct of_device_id loongson_nand_match[] = {
904950 .compatible = "loongson,ls1c-nand-controller" ,
905951 .data = & ls1c_nand_data ,
906952 },
953+ {
954+ .compatible = "loongson,ls2k0500-nand-controller" ,
955+ .data = & ls2k0500_nand_data ,
956+ },
907957 { /* sentinel */ }
908958};
909959MODULE_DEVICE_TABLE (of , loongson_nand_match );
@@ -920,5 +970,6 @@ static struct platform_driver loongson_nand_driver = {
920970module_platform_driver (loongson_nand_driver );
921971
922972MODULE_AUTHOR ("Keguang Zhang <keguang.zhang@gmail.com>" );
973+ MODULE_AUTHOR ("Binbin Zhou <zhoubinbin@loongson.cn>" );
923974MODULE_DESCRIPTION ("Loongson NAND Controller Driver" );
924975MODULE_LICENSE ("GPL" );
0 commit comments