1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Copyright (C) 2022 Hewlett-Packard Development Company, L.P. */ 3 4 #include <linux/iopoll.h> 5 #include <linux/of.h> 6 #include <linux/platform_device.h> 7 #include <linux/spi/spi.h> 8 #include <linux/spi/spi-mem.h> 9 10 #define GXP_SPI0_MAX_CHIPSELECT 2 11 #define GXP_SPI_SLEEP_TIME 1 12 #define GXP_SPI_TIMEOUT (130 * 1000000 / GXP_SPI_SLEEP_TIME) 13 14 #define MANUAL_MODE 0 15 #define DIRECT_MODE 1 16 #define SPILDAT_LEN 256 17 18 #define OFFSET_SPIMCFG 0x0 19 #define OFFSET_SPIMCTRL 0x4 20 #define OFFSET_SPICMD 0x5 21 #define OFFSET_SPIDCNT 0x6 22 #define OFFSET_SPIADDR 0x8 23 #define OFFSET_SPIINTSTS 0xc 24 25 #define SPIMCTRL_START 0x01 26 #define SPIMCTRL_BUSY 0x02 27 #define SPIMCTRL_DIR 0x08 28 29 struct gxp_spi; 30 31 struct gxp_spi_chip { 32 struct gxp_spi *spifi; 33 u32 cs; 34 }; 35 36 struct gxp_spi_data { 37 u32 max_cs; 38 u32 mode_bits; 39 }; 40 41 struct gxp_spi { 42 const struct gxp_spi_data *data; 43 void __iomem *reg_base; 44 void __iomem *dat_base; 45 void __iomem *dir_base; 46 struct device *dev; 47 struct gxp_spi_chip chips[GXP_SPI0_MAX_CHIPSELECT]; 48 }; 49 50 static void gxp_spi_set_mode(struct gxp_spi *spifi, int mode) 51 { 52 u8 value; 53 void __iomem *reg_base = spifi->reg_base; 54 55 value = readb(reg_base + OFFSET_SPIMCTRL); 56 57 if (mode == MANUAL_MODE) { 58 writeb(0x55, reg_base + OFFSET_SPICMD); 59 writeb(0xaa, reg_base + OFFSET_SPICMD); 60 value &= ~0x30; 61 } else { 62 value |= 0x30; 63 } 64 writeb(value, reg_base + OFFSET_SPIMCTRL); 65 } 66 67 static int gxp_spi_read_reg(struct gxp_spi_chip *chip, const struct spi_mem_op *op) 68 { 69 int ret; 70 struct gxp_spi *spifi = chip->spifi; 71 void __iomem *reg_base = spifi->reg_base; 72 u32 value; 73 74 value = readl(reg_base + OFFSET_SPIMCFG); 75 value &= ~(1 << 24); 76 value |= (chip->cs << 24); 77 value &= ~(0x07 << 16); 78 value &= ~(0x1f << 19); 79 writel(value, reg_base + OFFSET_SPIMCFG); 80 81 writel(0, reg_base + OFFSET_SPIADDR); 82 83 writeb(op->cmd.opcode, reg_base + OFFSET_SPICMD); 84 85 writew(op->data.nbytes, reg_base + OFFSET_SPIDCNT); 86 87 value = readb(reg_base + OFFSET_SPIMCTRL); 88 value &= ~SPIMCTRL_DIR; 89 value |= SPIMCTRL_START; 90 91 writeb(value, reg_base + OFFSET_SPIMCTRL); 92 93 ret = readb_poll_timeout(reg_base + OFFSET_SPIMCTRL, value, 94 !(value & SPIMCTRL_BUSY), 95 GXP_SPI_SLEEP_TIME, GXP_SPI_TIMEOUT); 96 if (ret) { 97 dev_warn(spifi->dev, "read reg busy time out\n"); 98 return ret; 99 } 100 101 memcpy_fromio(op->data.buf.in, spifi->dat_base, op->data.nbytes); 102 return ret; 103 } 104 105 static int gxp_spi_write_reg(struct gxp_spi_chip *chip, const struct spi_mem_op *op) 106 { 107 int ret; 108 struct gxp_spi *spifi = chip->spifi; 109 void __iomem *reg_base = spifi->reg_base; 110 u32 value; 111 112 value = readl(reg_base + OFFSET_SPIMCFG); 113 value &= ~(1 << 24); 114 value |= (chip->cs << 24); 115 value &= ~(0x07 << 16); 116 value &= ~(0x1f << 19); 117 writel(value, reg_base + OFFSET_SPIMCFG); 118 119 writel(0, reg_base + OFFSET_SPIADDR); 120 121 writeb(op->cmd.opcode, reg_base + OFFSET_SPICMD); 122 123 memcpy_toio(spifi->dat_base, op->data.buf.in, op->data.nbytes); 124 125 writew(op->data.nbytes, reg_base + OFFSET_SPIDCNT); 126 127 value = readb(reg_base + OFFSET_SPIMCTRL); 128 value |= SPIMCTRL_DIR; 129 value |= SPIMCTRL_START; 130 131 writeb(value, reg_base + OFFSET_SPIMCTRL); 132 133 ret = readb_poll_timeout(reg_base + OFFSET_SPIMCTRL, value, 134 !(value & SPIMCTRL_BUSY), 135 GXP_SPI_SLEEP_TIME, GXP_SPI_TIMEOUT); 136 if (ret) 137 dev_warn(spifi->dev, "write reg busy time out\n"); 138 139 return ret; 140 } 141 142 static ssize_t gxp_spi_read(struct gxp_spi_chip *chip, const struct spi_mem_op *op) 143 { 144 struct gxp_spi *spifi = chip->spifi; 145 u32 offset = op->addr.val; 146 147 if (chip->cs == 0) 148 offset += 0x4000000; 149 150 memcpy_fromio(op->data.buf.in, spifi->dir_base + offset, op->data.nbytes); 151 152 return 0; 153 } 154 155 static ssize_t gxp_spi_write(struct gxp_spi_chip *chip, const struct spi_mem_op *op) 156 { 157 struct gxp_spi *spifi = chip->spifi; 158 void __iomem *reg_base = spifi->reg_base; 159 u32 write_len; 160 u32 value; 161 int ret; 162 163 write_len = op->data.nbytes; 164 if (write_len > SPILDAT_LEN) 165 write_len = SPILDAT_LEN; 166 167 value = readl(reg_base + OFFSET_SPIMCFG); 168 value &= ~(1 << 24); 169 value |= (chip->cs << 24); 170 value &= ~(0x07 << 16); 171 value |= (op->addr.nbytes << 16); 172 value &= ~(0x1f << 19); 173 writel(value, reg_base + OFFSET_SPIMCFG); 174 175 writel(op->addr.val, reg_base + OFFSET_SPIADDR); 176 177 writeb(op->cmd.opcode, reg_base + OFFSET_SPICMD); 178 179 writew(write_len, reg_base + OFFSET_SPIDCNT); 180 181 memcpy_toio(spifi->dat_base, op->data.buf.in, write_len); 182 183 value = readb(reg_base + OFFSET_SPIMCTRL); 184 value |= SPIMCTRL_DIR; 185 value |= SPIMCTRL_START; 186 187 writeb(value, reg_base + OFFSET_SPIMCTRL); 188 189 ret = readb_poll_timeout(reg_base + OFFSET_SPIMCTRL, value, 190 !(value & SPIMCTRL_BUSY), 191 GXP_SPI_SLEEP_TIME, GXP_SPI_TIMEOUT); 192 if (ret) { 193 dev_warn(spifi->dev, "write busy time out\n"); 194 return ret; 195 } 196 197 return 0; 198 } 199 200 static int do_gxp_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) 201 { 202 struct gxp_spi *spifi = spi_controller_get_devdata(mem->spi->controller); 203 struct gxp_spi_chip *chip = &spifi->chips[spi_get_chipselect(mem->spi, 0)]; 204 int ret; 205 206 if (op->data.dir == SPI_MEM_DATA_IN) { 207 if (!op->addr.nbytes) 208 ret = gxp_spi_read_reg(chip, op); 209 else 210 ret = gxp_spi_read(chip, op); 211 } else { 212 if (!op->addr.nbytes) 213 ret = gxp_spi_write_reg(chip, op); 214 else 215 ret = gxp_spi_write(chip, op); 216 } 217 218 return ret; 219 } 220 221 static int gxp_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) 222 { 223 int ret; 224 225 ret = do_gxp_exec_mem_op(mem, op); 226 if (ret) 227 dev_err(&mem->spi->dev, "operation failed: %d", ret); 228 229 return ret; 230 } 231 232 static const struct spi_controller_mem_ops gxp_spi_mem_ops = { 233 .exec_op = gxp_exec_mem_op, 234 }; 235 236 static int gxp_spi_setup(struct spi_device *spi) 237 { 238 struct gxp_spi *spifi = spi_controller_get_devdata(spi->controller); 239 unsigned int cs = spi_get_chipselect(spi, 0); 240 struct gxp_spi_chip *chip = &spifi->chips[cs]; 241 242 chip->spifi = spifi; 243 chip->cs = cs; 244 245 gxp_spi_set_mode(spifi, MANUAL_MODE); 246 247 return 0; 248 } 249 250 static int gxp_spifi_probe(struct platform_device *pdev) 251 { 252 struct device *dev = &pdev->dev; 253 const struct gxp_spi_data *data; 254 struct spi_controller *ctlr; 255 struct gxp_spi *spifi; 256 int ret; 257 258 data = of_device_get_match_data(&pdev->dev); 259 260 ctlr = devm_spi_alloc_host(dev, sizeof(*spifi)); 261 if (!ctlr) 262 return -ENOMEM; 263 264 spifi = spi_controller_get_devdata(ctlr); 265 266 platform_set_drvdata(pdev, spifi); 267 spifi->data = data; 268 spifi->dev = dev; 269 270 spifi->reg_base = devm_platform_ioremap_resource(pdev, 0); 271 if (IS_ERR(spifi->reg_base)) 272 return PTR_ERR(spifi->reg_base); 273 274 spifi->dat_base = devm_platform_ioremap_resource(pdev, 1); 275 if (IS_ERR(spifi->dat_base)) 276 return PTR_ERR(spifi->dat_base); 277 278 spifi->dir_base = devm_platform_ioremap_resource(pdev, 2); 279 if (IS_ERR(spifi->dir_base)) 280 return PTR_ERR(spifi->dir_base); 281 282 ctlr->mode_bits = data->mode_bits; 283 ctlr->bus_num = pdev->id; 284 ctlr->mem_ops = &gxp_spi_mem_ops; 285 ctlr->setup = gxp_spi_setup; 286 ctlr->num_chipselect = data->max_cs; 287 ctlr->dev.of_node = dev->of_node; 288 289 ret = devm_spi_register_controller(dev, ctlr); 290 if (ret) { 291 return dev_err_probe(&pdev->dev, ret, 292 "failed to register spi controller\n"); 293 } 294 295 return 0; 296 } 297 298 static const struct gxp_spi_data gxp_spifi_data = { 299 .max_cs = 2, 300 .mode_bits = 0, 301 }; 302 303 static const struct of_device_id gxp_spifi_match[] = { 304 {.compatible = "hpe,gxp-spifi", .data = &gxp_spifi_data }, 305 { /* null */ } 306 }; 307 MODULE_DEVICE_TABLE(of, gxp_spifi_match); 308 309 static struct platform_driver gxp_spifi_driver = { 310 .probe = gxp_spifi_probe, 311 .driver = { 312 .name = "gxp-spifi", 313 .of_match_table = gxp_spifi_match, 314 }, 315 }; 316 module_platform_driver(gxp_spifi_driver); 317 318 MODULE_DESCRIPTION("HPE GXP SPI Flash Interface driver"); 319 MODULE_AUTHOR("Nick Hawkins <nick.hawkins@hpe.com>"); 320 MODULE_LICENSE("GPL"); 321