^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2019 Nuvoton Technology corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/bits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/spi/spi-mem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* NPCM7xx GCR module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define NPCM7XX_INTCR3_OFFSET 0x9C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define NPCM7XX_INTCR3_FIU_FIX BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Flash Interface Unit (FIU) Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define NPCM_FIU_DRD_CFG 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define NPCM_FIU_DWR_CFG 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define NPCM_FIU_UMA_CFG 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define NPCM_FIU_UMA_CTS 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define NPCM_FIU_UMA_CMD 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define NPCM_FIU_UMA_ADDR 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define NPCM_FIU_PRT_CFG 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define NPCM_FIU_UMA_DW0 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define NPCM_FIU_UMA_DW1 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define NPCM_FIU_UMA_DW2 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define NPCM_FIU_UMA_DW3 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define NPCM_FIU_UMA_DR0 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define NPCM_FIU_UMA_DR1 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define NPCM_FIU_UMA_DR2 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define NPCM_FIU_UMA_DR3 0x3C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define NPCM_FIU_MAX_REG_LIMIT 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* FIU Direct Read Configuration Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define NPCM_FIU_DRD_CFG_LCK BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define NPCM_FIU_DRD_CFG_R_BURST GENMASK(25, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define NPCM_FIU_DRD_CFG_ADDSIZ GENMASK(17, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define NPCM_FIU_DRD_CFG_DBW GENMASK(13, 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define NPCM_FIU_DRD_CFG_ACCTYPE GENMASK(9, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define NPCM_FIU_DRD_CFG_RDCMD GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define NPCM_FIU_DRD_ADDSIZ_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define NPCM_FIU_DRD_DBW_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define NPCM_FIU_DRD_ACCTYPE_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* FIU Direct Write Configuration Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define NPCM_FIU_DWR_CFG_LCK BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define NPCM_FIU_DWR_CFG_W_BURST GENMASK(25, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define NPCM_FIU_DWR_CFG_ADDSIZ GENMASK(17, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define NPCM_FIU_DWR_CFG_ABPCK GENMASK(11, 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define NPCM_FIU_DWR_CFG_DBPCK GENMASK(9, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define NPCM_FIU_DWR_CFG_WRCMD GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define NPCM_FIU_DWR_ADDSIZ_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define NPCM_FIU_DWR_ABPCK_SHIFT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define NPCM_FIU_DWR_DBPCK_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* FIU UMA Configuration Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define NPCM_FIU_UMA_CFG_LCK BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define NPCM_FIU_UMA_CFG_CMMLCK BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define NPCM_FIU_UMA_CFG_RDATSIZ GENMASK(28, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define NPCM_FIU_UMA_CFG_DBSIZ GENMASK(23, 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define NPCM_FIU_UMA_CFG_WDATSIZ GENMASK(20, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define NPCM_FIU_UMA_CFG_ADDSIZ GENMASK(13, 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define NPCM_FIU_UMA_CFG_CMDSIZ BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define NPCM_FIU_UMA_CFG_RDBPCK GENMASK(9, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define NPCM_FIU_UMA_CFG_DBPCK GENMASK(7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define NPCM_FIU_UMA_CFG_WDBPCK GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define NPCM_FIU_UMA_CFG_ADBPCK GENMASK(3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define NPCM_FIU_UMA_CFG_CMBPCK GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define NPCM_FIU_UMA_CFG_ADBPCK_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define NPCM_FIU_UMA_CFG_WDBPCK_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define NPCM_FIU_UMA_CFG_DBPCK_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define NPCM_FIU_UMA_CFG_RDBPCK_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define NPCM_FIU_UMA_CFG_DBSIZ_SHIFT 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* FIU UMA Control and Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define NPCM_FIU_UMA_CTS_RDYIE BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define NPCM_FIU_UMA_CTS_RDYST BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define NPCM_FIU_UMA_CTS_SW_CS BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define NPCM_FIU_UMA_CTS_DEV_NUM GENMASK(9, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define NPCM_FIU_UMA_CTS_EXEC_DONE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* FIU UMA Command Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define NPCM_FIU_UMA_CMD_DUM3 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define NPCM_FIU_UMA_CMD_DUM2 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define NPCM_FIU_UMA_CMD_DUM1 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define NPCM_FIU_UMA_CMD_CMD GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* FIU UMA Address Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define NPCM_FIU_UMA_ADDR_UMA_ADDR GENMASK(31, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define NPCM_FIU_UMA_ADDR_AB3 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define NPCM_FIU_UMA_ADDR_AB2 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define NPCM_FIU_UMA_ADDR_AB1 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define NPCM_FIU_UMA_ADDR_AB0 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* FIU UMA Write Data Bytes 0-3 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define NPCM_FIU_UMA_DW0_WB3 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define NPCM_FIU_UMA_DW0_WB2 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define NPCM_FIU_UMA_DW0_WB1 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define NPCM_FIU_UMA_DW0_WB0 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* FIU UMA Write Data Bytes 4-7 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define NPCM_FIU_UMA_DW1_WB7 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define NPCM_FIU_UMA_DW1_WB6 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define NPCM_FIU_UMA_DW1_WB5 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define NPCM_FIU_UMA_DW1_WB4 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* FIU UMA Write Data Bytes 8-11 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define NPCM_FIU_UMA_DW2_WB11 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define NPCM_FIU_UMA_DW2_WB10 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define NPCM_FIU_UMA_DW2_WB9 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define NPCM_FIU_UMA_DW2_WB8 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* FIU UMA Write Data Bytes 12-15 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define NPCM_FIU_UMA_DW3_WB15 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define NPCM_FIU_UMA_DW3_WB14 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define NPCM_FIU_UMA_DW3_WB13 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define NPCM_FIU_UMA_DW3_WB12 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* FIU UMA Read Data Bytes 0-3 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define NPCM_FIU_UMA_DR0_RB3 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define NPCM_FIU_UMA_DR0_RB2 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define NPCM_FIU_UMA_DR0_RB1 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define NPCM_FIU_UMA_DR0_RB0 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* FIU UMA Read Data Bytes 4-7 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define NPCM_FIU_UMA_DR1_RB15 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define NPCM_FIU_UMA_DR1_RB14 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define NPCM_FIU_UMA_DR1_RB13 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define NPCM_FIU_UMA_DR1_RB12 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* FIU UMA Read Data Bytes 8-11 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define NPCM_FIU_UMA_DR2_RB15 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define NPCM_FIU_UMA_DR2_RB14 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define NPCM_FIU_UMA_DR2_RB13 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define NPCM_FIU_UMA_DR2_RB12 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* FIU UMA Read Data Bytes 12-15 Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define NPCM_FIU_UMA_DR3_RB15 GENMASK(31, 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define NPCM_FIU_UMA_DR3_RB14 GENMASK(23, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define NPCM_FIU_UMA_DR3_RB13 GENMASK(15, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define NPCM_FIU_UMA_DR3_RB12 GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* FIU Read Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) DRD_SINGLE_WIRE_MODE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) DRD_DUAL_IO_MODE = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) DRD_QUAD_IO_MODE = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) DRD_SPI_X_MODE = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) DWR_ABPCK_BIT_PER_CLK = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) DWR_ABPCK_2_BIT_PER_CLK = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) DWR_ABPCK_4_BIT_PER_CLK = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) DWR_DBPCK_BIT_PER_CLK = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) DWR_DBPCK_2_BIT_PER_CLK = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) DWR_DBPCK_4_BIT_PER_CLK = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define NPCM_FIU_DRD_16_BYTE_BURST 0x3000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define NPCM_FIU_DWR_16_BYTE_BURST 0x3000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define MAP_SIZE_128MB 0x8000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define MAP_SIZE_16MB 0x1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define MAP_SIZE_8MB 0x800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define FIU_DRD_MAX_DUMMY_NUMBER 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define NPCM_MAX_CHIP_NUM 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define CHUNK_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define UMA_MICRO_SEC_TIMEOUT 150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) FIU0 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) FIU3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) FIUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct npcm_fiu_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u32 fiu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u32 max_map_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u32 max_cs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct fiu_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) const struct npcm_fiu_info *npcm_fiu_data_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int fiu_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static const struct npcm_fiu_info npxm7xx_fiu_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {.name = "FIU0", .fiu_id = FIU0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .max_map_size = MAP_SIZE_128MB, .max_cs = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {.name = "FIU3", .fiu_id = FIU3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .max_map_size = MAP_SIZE_128MB, .max_cs = 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {.name = "FIUX", .fiu_id = FIUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .max_map_size = MAP_SIZE_16MB, .max_cs = 2} };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const struct fiu_data npxm7xx_fiu_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .npcm_fiu_data_info = npxm7xx_fiu_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .fiu_max = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct npcm_fiu_spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct npcm_fiu_chip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) void __iomem *flash_region_mapped_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct npcm_fiu_spi *fiu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned long clkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u32 chipselect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct npcm_fiu_spi {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct npcm_fiu_chip chip[NPCM_MAX_CHIP_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) const struct npcm_fiu_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct spi_mem_op drd_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct resource *res_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) unsigned long clkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) bool spix_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static const struct regmap_config npcm_mtd_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .max_register = NPCM_FIU_MAX_REG_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) const struct spi_mem_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) NPCM_FIU_DRD_CFG_ACCTYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ilog2(op->addr.buswidth) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) NPCM_FIU_DRD_ACCTYPE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) fiu->drd_op.addr.buswidth = op->addr.buswidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) NPCM_FIU_DRD_CFG_DBW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ((op->dummy.nbytes * ilog2(op->addr.buswidth)) / BITS_PER_BYTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) << NPCM_FIU_DRD_DBW_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) fiu->drd_op.dummy.nbytes = op->dummy.nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) fiu->drd_op.cmd.opcode = op->cmd.opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) NPCM_FIU_DRD_CFG_ADDSIZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) (op->addr.nbytes - 3) << NPCM_FIU_DRD_ADDSIZ_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) fiu->drd_op.addr.nbytes = op->addr.nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u64 offs, size_t len, void *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) spi_controller_get_devdata(desc->mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) void __iomem *src = (void __iomem *)(chip->flash_region_mapped_ptr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u8 *buf_rx = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (fiu->spix_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) for (i = 0 ; i < len ; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *(buf_rx + i) = ioread8(src + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) memcpy_fromio(buf_rx, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static ssize_t npcm_fiu_direct_write(struct spi_mem_dirmap_desc *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) u64 offs, size_t len, const void *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) spi_controller_get_devdata(desc->mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void __iomem *dst = (void __iomem *)(chip->flash_region_mapped_ptr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) const u8 *buf_tx = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (fiu->spix_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) for (i = 0 ; i < len ; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) iowrite8(*(buf_tx + i), dst + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) memcpy_toio(dst, buf_tx, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static int npcm_fiu_uma_read(struct spi_mem *mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) const struct spi_mem_op *op, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) bool is_address_size, u8 *data, u32 data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) spi_controller_get_devdata(mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) u32 uma_cfg = BIT(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) u32 data_reg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) NPCM_FIU_UMA_CTS_DEV_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) (mem->spi->chip_select <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) NPCM_FIU_UMA_CMD_CMD, op->cmd.opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (is_address_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) uma_cfg |= ilog2(op->cmd.buswidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) uma_cfg |= ilog2(op->addr.buswidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) << NPCM_FIU_UMA_CFG_ADBPCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) uma_cfg |= ilog2(op->dummy.buswidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) << NPCM_FIU_UMA_CFG_DBPCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) uma_cfg |= ilog2(op->data.buswidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) uma_cfg |= data_size << NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) NPCM_FIU_UMA_CTS_EXEC_DONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) NPCM_FIU_UMA_CTS_EXEC_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ret = regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) UMA_MICRO_SEC_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (data_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) regmap_read(fiu->regmap, NPCM_FIU_UMA_DR0 + (i * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) &data_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) memcpy(data, data_reg, data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int npcm_fiu_uma_write(struct spi_mem *mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) const struct spi_mem_op *op, u8 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) bool is_address_size, u8 *data, u32 data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) spi_controller_get_devdata(mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) u32 uma_cfg = BIT(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) u32 data_reg[4] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) NPCM_FIU_UMA_CTS_DEV_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) (mem->spi->chip_select <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) NPCM_FIU_UMA_CMD_CMD, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (data_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) memcpy(data_reg, data, data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) regmap_write(fiu->regmap, NPCM_FIU_UMA_DW0 + (i * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) data_reg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (is_address_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) uma_cfg |= ilog2(op->cmd.buswidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) uma_cfg |= ilog2(op->addr.buswidth) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) NPCM_FIU_UMA_CFG_ADBPCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) uma_cfg |= ilog2(op->data.buswidth) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) NPCM_FIU_UMA_CFG_WDBPCK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, op->addr.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) uma_cfg |= (data_size << NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) NPCM_FIU_UMA_CTS_EXEC_DONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) NPCM_FIU_UMA_CTS_EXEC_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) UMA_MICRO_SEC_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static int npcm_fiu_manualwrite(struct spi_mem *mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) const struct spi_mem_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) spi_controller_get_devdata(mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) u8 *data = (u8 *)op->data.buf.out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) u32 num_data_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) u32 remain_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) u32 idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) num_data_chunks = op->data.nbytes / CHUNK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) remain_data = op->data.nbytes % CHUNK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) NPCM_FIU_UMA_CTS_DEV_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) (mem->spi->chip_select <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) NPCM_FIU_UMA_CTS_SW_CS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, true, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* Starting the data writing loop in multiples of 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) for (idx = 0; idx < num_data_chunks; ++idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ret = npcm_fiu_uma_write(mem, op, data[0], false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) &data[1], CHUNK_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) data += CHUNK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Handling chunk remains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (remain_data > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ret = npcm_fiu_uma_write(mem, op, data[0], false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) &data[1], remain_data - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) NPCM_FIU_UMA_CTS_SW_CS, NPCM_FIU_UMA_CTS_SW_CS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int npcm_fiu_read(struct spi_mem *mem, const struct spi_mem_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) u8 *data = op->data.buf.in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int i, readlen, currlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) u8 *buf_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) currlen = op->data.nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) addr = ((u32)op->addr.val + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (currlen < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) readlen = currlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) readlen = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) buf_ptr = data + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = npcm_fiu_uma_read(mem, op, addr, true, buf_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) readlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) i += readlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) currlen -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) } while (currlen > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void npcm_fiux_set_direct_wr(struct npcm_fiu_spi *fiu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) regmap_write(fiu->regmap, NPCM_FIU_DWR_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) NPCM_FIU_DWR_16_BYTE_BURST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) NPCM_FIU_DWR_CFG_ABPCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) DWR_ABPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_ABPCK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) NPCM_FIU_DWR_CFG_DBPCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) DWR_DBPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_DBPCK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static void npcm_fiux_set_direct_rd(struct npcm_fiu_spi *fiu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) u32 rx_dummy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) regmap_write(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) NPCM_FIU_DRD_16_BYTE_BURST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) NPCM_FIU_DRD_CFG_ACCTYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) DRD_SPI_X_MODE << NPCM_FIU_DRD_ACCTYPE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) NPCM_FIU_DRD_CFG_DBW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) rx_dummy << NPCM_FIU_DRD_DBW_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) spi_controller_get_devdata(mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct npcm_fiu_chip *chip = &fiu->chip[mem->spi->chip_select];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_dbg(fiu->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) op->dummy.buswidth, op->data.buswidth, op->addr.val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) op->data.nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (fiu->spix_mode || op->addr.nbytes > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (fiu->clkrate != chip->clkrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ret = clk_set_rate(fiu->clk, chip->clkrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) dev_warn(fiu->dev, "Failed setting %lu frequency, stay at %lu frequency\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) chip->clkrate, fiu->clkrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) fiu->clkrate = chip->clkrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (op->data.dir == SPI_MEM_DATA_IN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (!op->addr.nbytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) buf = op->data.buf.in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ret = npcm_fiu_uma_read(mem, op, op->addr.val, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) buf, op->data.nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ret = npcm_fiu_read(mem, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (!op->addr.nbytes && !op->data.nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (op->addr.nbytes && !op->data.nbytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) u8 buf_addr[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) u32 addr = op->addr.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) for (i = op->addr.nbytes - 1; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) buf_addr[i] = addr & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) addr >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) buf_addr, op->addr.nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (!op->addr.nbytes && op->data.nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) (u8 *)op->data.buf.out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) op->data.nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (op->addr.nbytes && op->data.nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ret = npcm_fiu_manualwrite(mem, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct npcm_fiu_spi *fiu =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) spi_controller_get_devdata(desc->mem->spi->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct regmap *gcr_regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (!fiu->res_mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) dev_warn(fiu->dev, "Reserved memory not defined, direct read disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) desc->nodirmap = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (!fiu->spix_mode &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) desc->nodirmap = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (!chip->flash_region_mapped_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) chip->flash_region_mapped_ptr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) devm_ioremap(fiu->dev, (fiu->res_mem->start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) (fiu->info->max_map_size *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) desc->mem->spi->chip_select)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) (u32)desc->info.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (!chip->flash_region_mapped_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) dev_warn(fiu->dev, "Error mapping memory region, direct read disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) desc->nodirmap = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (of_device_is_compatible(fiu->dev->of_node, "nuvoton,npcm750-fiu")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) gcr_regmap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (IS_ERR(gcr_regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) dev_warn(fiu->dev, "Didn't find nuvoton,npcm750-gcr, direct read disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) desc->nodirmap = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) regmap_update_bits(gcr_regmap, NPCM7XX_INTCR3_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) NPCM7XX_INTCR3_FIU_FIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) NPCM7XX_INTCR3_FIU_FIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (!fiu->spix_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) npcm_fiu_set_drd(fiu, &desc->info.op_tmpl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) npcm_fiux_set_direct_rd(fiu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) npcm_fiux_set_direct_wr(fiu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int npcm_fiu_setup(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct spi_controller *ctrl = spi->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct npcm_fiu_spi *fiu = spi_controller_get_devdata(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct npcm_fiu_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) chip = &fiu->chip[spi->chip_select];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) chip->fiu = fiu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) chip->chipselect = spi->chip_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) chip->clkrate = spi->max_speed_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) fiu->clkrate = clk_get_rate(fiu->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static const struct spi_controller_mem_ops npcm_fiu_mem_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) .exec_op = npcm_fiu_exec_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) .dirmap_create = npcm_fiu_dirmap_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) .dirmap_read = npcm_fiu_direct_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .dirmap_write = npcm_fiu_direct_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static const struct of_device_id npcm_fiu_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) { .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static int npcm_fiu_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) const struct fiu_data *fiu_data_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct spi_controller *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct npcm_fiu_spi *fiu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) void __iomem *regbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int id, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ctrl = devm_spi_alloc_master(dev, sizeof(*fiu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) fiu = spi_controller_get_devdata(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) match = of_match_device(npcm_fiu_dt_ids, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!match || !match->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) dev_err(dev, "No compatible OF match\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) fiu_data_match = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) id = of_alias_get_id(dev->of_node, "fiu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (id < 0 || id >= fiu_data_match->fiu_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) dev_err(dev, "Invalid platform device id: %d\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) fiu->info = &fiu_data_match->npcm_fiu_data_info[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) platform_set_drvdata(pdev, fiu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) fiu->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) regbase = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (IS_ERR(regbase))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return PTR_ERR(regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) fiu->regmap = devm_regmap_init_mmio(dev, regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) &npcm_mtd_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (IS_ERR(fiu->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) dev_err(dev, "Failed to create regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return PTR_ERR(fiu->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) fiu->res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) fiu->clk = devm_clk_get(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (IS_ERR(fiu->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return PTR_ERR(fiu->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) fiu->spix_mode = of_property_read_bool(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) "nuvoton,spix-mode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) platform_set_drvdata(pdev, fiu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) clk_prepare_enable(fiu->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) | SPI_TX_DUAL | SPI_TX_QUAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ctrl->setup = npcm_fiu_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ctrl->bus_num = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ctrl->mem_ops = &npcm_fiu_mem_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ctrl->num_chipselect = fiu->info->max_cs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ctrl->dev.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ret = devm_spi_register_master(dev, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) clk_disable_unprepare(fiu->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int npcm_fiu_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) struct npcm_fiu_spi *fiu = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) clk_disable_unprepare(fiu->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static struct platform_driver npcm_fiu_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .name = "NPCM-FIU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .bus = &platform_bus_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .of_match_table = npcm_fiu_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .probe = npcm_fiu_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .remove = npcm_fiu_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) module_platform_driver(npcm_fiu_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) MODULE_DESCRIPTION("Nuvoton FLASH Interface Unit SPI Controller Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) MODULE_LICENSE("GPL v2");