Lines Matching +full:spi +full:- +full:nor
4 * Copyright (c) 2015-2016, IBM Corporation.
19 #include <linux/mtd/spi-nor.h>
25 #define DEVICE_NAME "aspeed-smc"
28 * The driver only support SPI flash
104 struct spi_nor nor; member
113 void __iomem *ahb_base; /* per-chip windows resource */
120 * SPI Flash Configuration Register (AST2500 SPI)
123 * CE0 and CE1 can only be of type SPI. CE2 can be of type NOR but the
160 #define CONTROL_IO_ADDRESS_4B BIT(13) /* AST2400 SPI */
190 * and the end address of the mapping window of a flash SPI slave :
193 * +--------+--------+--------+--------+
202 ((controller)->regs + SEGMENT_ADDR_REG0 + (cs) * 4)
206 * range are transferred to or from the SPI bus. The range is treated as a
209 * sending bytes to the SPI bus.
239 len -= offset; in aspeed_smc_read_from_ahb()
254 len -= offset; in aspeed_smc_write_to_ahb()
262 return BIT(chip->controller->info->we0 + chip->cs); in aspeed_smc_chip_write_bit()
267 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_check_config()
270 reg = readl(controller->regs + CONFIG_REG); in aspeed_smc_chip_check_config()
275 dev_dbg(controller->dev, "config write is not set ! @%p: 0x%08x\n", in aspeed_smc_chip_check_config()
276 controller->regs + CONFIG_REG, reg); in aspeed_smc_chip_check_config()
278 writel(reg, controller->regs + CONFIG_REG); in aspeed_smc_chip_check_config()
281 static void aspeed_smc_start_user(struct spi_nor *nor) in aspeed_smc_start_user() argument
283 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_start_user()
284 u32 ctl = chip->ctl_val[smc_base]; in aspeed_smc_start_user()
294 writel(ctl, chip->ctl); in aspeed_smc_start_user()
297 writel(ctl, chip->ctl); in aspeed_smc_start_user()
300 static void aspeed_smc_stop_user(struct spi_nor *nor) in aspeed_smc_stop_user() argument
302 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_stop_user()
304 u32 ctl = chip->ctl_val[smc_read]; in aspeed_smc_stop_user()
308 writel(ctl2, chip->ctl); /* stop user CE control */ in aspeed_smc_stop_user()
309 writel(ctl, chip->ctl); /* default to fread or read mode */ in aspeed_smc_stop_user()
312 static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops) in aspeed_smc_prep() argument
314 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_prep()
316 mutex_lock(&chip->controller->mutex); in aspeed_smc_prep()
320 static void aspeed_smc_unprep(struct spi_nor *nor, enum spi_nor_ops ops) in aspeed_smc_unprep() argument
322 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_unprep()
324 mutex_unlock(&chip->controller->mutex); in aspeed_smc_unprep()
327 static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) in aspeed_smc_read_reg() argument
329 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_read_reg()
331 aspeed_smc_start_user(nor); in aspeed_smc_read_reg()
332 aspeed_smc_write_to_ahb(chip->ahb_base, &opcode, 1); in aspeed_smc_read_reg()
333 aspeed_smc_read_from_ahb(buf, chip->ahb_base, len); in aspeed_smc_read_reg()
334 aspeed_smc_stop_user(nor); in aspeed_smc_read_reg()
338 static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, in aspeed_smc_write_reg() argument
341 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_write_reg()
343 aspeed_smc_start_user(nor); in aspeed_smc_write_reg()
344 aspeed_smc_write_to_ahb(chip->ahb_base, &opcode, 1); in aspeed_smc_write_reg()
345 aspeed_smc_write_to_ahb(chip->ahb_base, buf, len); in aspeed_smc_write_reg()
346 aspeed_smc_stop_user(nor); in aspeed_smc_write_reg()
350 static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr) in aspeed_smc_send_cmd_addr() argument
352 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_send_cmd_addr()
356 switch (nor->addr_width) { in aspeed_smc_send_cmd_addr()
359 nor->addr_width); in aspeed_smc_send_cmd_addr()
366 aspeed_smc_write_to_ahb(chip->ahb_base, &temp, 4); in aspeed_smc_send_cmd_addr()
370 aspeed_smc_write_to_ahb(chip->ahb_base, &cmd, 1); in aspeed_smc_send_cmd_addr()
371 aspeed_smc_write_to_ahb(chip->ahb_base, &temp, 4); in aspeed_smc_send_cmd_addr()
376 static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, in aspeed_smc_read_user() argument
379 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_read_user()
383 aspeed_smc_start_user(nor); in aspeed_smc_read_user()
384 aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from); in aspeed_smc_read_user()
385 for (i = 0; i < chip->nor.read_dummy / 8; i++) in aspeed_smc_read_user()
386 aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); in aspeed_smc_read_user()
388 aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len); in aspeed_smc_read_user()
389 aspeed_smc_stop_user(nor); in aspeed_smc_read_user()
393 static ssize_t aspeed_smc_write_user(struct spi_nor *nor, loff_t to, in aspeed_smc_write_user() argument
396 struct aspeed_smc_chip *chip = nor->priv; in aspeed_smc_write_user()
398 aspeed_smc_start_user(nor); in aspeed_smc_write_user()
399 aspeed_smc_send_cmd_addr(nor, nor->program_opcode, to); in aspeed_smc_write_user()
400 aspeed_smc_write_to_ahb(chip->ahb_base, write_buf, len); in aspeed_smc_write_user()
401 aspeed_smc_stop_user(nor); in aspeed_smc_write_user()
410 for (n = 0; n < controller->info->nce; n++) { in aspeed_smc_unregister()
411 chip = controller->chips[n]; in aspeed_smc_unregister()
413 mtd_device_unregister(&chip->nor.mtd); in aspeed_smc_unregister()
425 { .compatible = "aspeed,ast2400-fmc", .data = &fmc_2400_info },
426 { .compatible = "aspeed,ast2400-spi", .data = &spi_2400_info },
427 { .compatible = "aspeed,ast2500-fmc", .data = &fmc_2500_info },
428 { .compatible = "aspeed,ast2500-spi", .data = &spi_2500_info },
443 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_base()
447 if (controller->info->nce > 1) { in aspeed_smc_chip_base()
448 reg = readl(SEGMENT_ADDR_REG(controller, chip->cs)); in aspeed_smc_chip_base()
453 offset = SEGMENT_ADDR_START(reg) - res->start; in aspeed_smc_chip_base()
456 return controller->ahb_base + offset; in aspeed_smc_chip_base()
469 struct aspeed_smc_controller *controller = chip->controller; in chip_set_segment()
484 size = SEGMENT_ADDR_END(seg_oldval) - start; in chip_set_segment()
490 if (start + size > ahb_base_phy + controller->ahb_window_size) { in chip_set_segment()
491 size = ahb_base_phy + controller->ahb_window_size - start; in chip_set_segment()
492 dev_warn(chip->nor.dev, "CE%d window resized to %dMB", in chip_set_segment()
506 dev_err(chip->nor.dev, "CE%d window invalid", cs); in chip_set_segment()
510 size = end - start; in chip_set_segment()
513 dev_info(chip->nor.dev, "CE%d window [ 0x%.8x - 0x%.8x ] %dMB", in chip_set_segment()
529 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_set_segment()
531 u32 size = chip->nor.mtd.size; in aspeed_smc_chip_set_segment()
537 if (size > controller->info->maxsize) in aspeed_smc_chip_set_segment()
538 size = controller->info->maxsize; in aspeed_smc_chip_set_segment()
541 * The AST2400 SPI controller only handles one chip and does in aspeed_smc_chip_set_segment()
545 if (controller->info == &spi_2400_info) in aspeed_smc_chip_set_segment()
549 * The AST2500 SPI controller has a HW bug when the CE0 chip in aspeed_smc_chip_set_segment()
554 if (chip->cs == 0 && controller->info == &spi_2500_info && in aspeed_smc_chip_set_segment()
557 dev_info(chip->nor.dev, in aspeed_smc_chip_set_segment()
559 chip->cs, size >> 20); in aspeed_smc_chip_set_segment()
569 if (chip->cs) { in aspeed_smc_chip_set_segment()
570 u32 prev = readl(SEGMENT_ADDR_REG(controller, chip->cs - 1)); in aspeed_smc_chip_set_segment()
577 size = chip_set_segment(chip, chip->cs, start, size); in aspeed_smc_chip_set_segment()
580 chip->ahb_base = controller->ahb_base + (start - ahb_base_phy); in aspeed_smc_chip_set_segment()
587 if (chip->cs < controller->info->nce - 1) in aspeed_smc_chip_set_segment()
588 chip_set_segment(chip, chip->cs + 1, start + size, 0); in aspeed_smc_chip_set_segment()
591 if (size < chip->nor.mtd.size) in aspeed_smc_chip_set_segment()
592 dev_warn(chip->nor.dev, in aspeed_smc_chip_set_segment()
594 chip->cs, (u32)chip->nor.mtd.size >> 20); in aspeed_smc_chip_set_segment()
601 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_enable_write()
604 reg = readl(controller->regs + CONFIG_REG); in aspeed_smc_chip_enable_write()
607 writel(reg, controller->regs + CONFIG_REG); in aspeed_smc_chip_enable_write()
612 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_set_type()
615 chip->type = type; in aspeed_smc_chip_set_type()
617 reg = readl(controller->regs + CONFIG_REG); in aspeed_smc_chip_set_type()
618 reg &= ~(3 << (chip->cs * 2)); in aspeed_smc_chip_set_type()
619 reg |= chip->type << (chip->cs * 2); in aspeed_smc_chip_set_type()
620 writel(reg, controller->regs + CONFIG_REG); in aspeed_smc_chip_set_type()
630 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_set_4b()
633 reg = readl(controller->regs + CE_CONTROL_REG); in aspeed_smc_chip_set_4b()
634 reg |= 1 << chip->cs; in aspeed_smc_chip_set_4b()
635 writel(reg, controller->regs + CE_CONTROL_REG); in aspeed_smc_chip_set_4b()
639 * The AST2400 SPI flash controller does not have a CE Control
645 chip->ctl_val[smc_base] |= CONTROL_IO_ADDRESS_4B; in aspeed_smc_chip_set_4b_spi_2400()
646 chip->ctl_val[smc_read] |= CONTROL_IO_ADDRESS_4B; in aspeed_smc_chip_set_4b_spi_2400()
652 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_setup_init()
653 const struct aspeed_smc_info *info = controller->info; in aspeed_smc_chip_setup_init()
662 /* The driver only supports SPI type flash */ in aspeed_smc_chip_setup_init()
663 if (info->hastype) in aspeed_smc_chip_setup_init()
669 chip->ahb_base = aspeed_smc_chip_base(chip, res); in aspeed_smc_chip_setup_init()
670 if (!chip->ahb_base) { in aspeed_smc_chip_setup_init()
671 dev_warn(chip->nor.dev, "CE%d window closed", chip->cs); in aspeed_smc_chip_setup_init()
672 return -EINVAL; in aspeed_smc_chip_setup_init()
676 * Get value of the inherited control register. U-Boot usually in aspeed_smc_chip_setup_init()
681 reg = readl(chip->ctl); in aspeed_smc_chip_setup_init()
682 dev_dbg(controller->dev, "control register: %08x\n", reg); in aspeed_smc_chip_setup_init()
686 dev_dbg(controller->dev, in aspeed_smc_chip_setup_init()
690 chip->ctl_val[smc_base] = base_reg; in aspeed_smc_chip_setup_init()
699 chip->ctl_val[smc_read] = reg; in aspeed_smc_chip_setup_init()
701 chip->ctl_val[smc_read] = chip->ctl_val[smc_base] | in aspeed_smc_chip_setup_init()
704 dev_dbg(controller->dev, "default control register: %08x\n", in aspeed_smc_chip_setup_init()
705 chip->ctl_val[smc_read]); in aspeed_smc_chip_setup_init()
711 struct aspeed_smc_controller *controller = chip->controller; in aspeed_smc_chip_setup_finish()
712 const struct aspeed_smc_info *info = controller->info; in aspeed_smc_chip_setup_finish()
715 if (chip->nor.addr_width == 4 && info->set_4b) in aspeed_smc_chip_setup_finish()
716 info->set_4b(chip); in aspeed_smc_chip_setup_finish()
719 chip->ahb_window_size = aspeed_smc_chip_set_segment(chip); in aspeed_smc_chip_setup_finish()
724 chip->ctl_val[smc_write] = chip->ctl_val[smc_base] | in aspeed_smc_chip_setup_finish()
725 chip->nor.program_opcode << CONTROL_COMMAND_SHIFT | in aspeed_smc_chip_setup_finish()
728 dev_dbg(controller->dev, "write control register: %08x\n", in aspeed_smc_chip_setup_finish()
729 chip->ctl_val[smc_write]); in aspeed_smc_chip_setup_finish()
733 * SPI-NOR flags to adjust controller settings. in aspeed_smc_chip_setup_finish()
735 if (chip->nor.read_proto == SNOR_PROTO_1_1_1) { in aspeed_smc_chip_setup_finish()
736 if (chip->nor.read_dummy == 0) in aspeed_smc_chip_setup_finish()
741 dev_err(chip->nor.dev, "unsupported SPI read mode\n"); in aspeed_smc_chip_setup_finish()
742 return -EINVAL; in aspeed_smc_chip_setup_finish()
745 chip->ctl_val[smc_read] |= cmd | in aspeed_smc_chip_setup_finish()
746 CONTROL_IO_DUMMY_SET(chip->nor.read_dummy / 8); in aspeed_smc_chip_setup_finish()
748 dev_dbg(controller->dev, "base control register: %08x\n", in aspeed_smc_chip_setup_finish()
749 chip->ctl_val[smc_read]); in aspeed_smc_chip_setup_finish()
761 const struct aspeed_smc_info *info = controller->info; in aspeed_smc_setup_flash()
762 struct device *dev = controller->dev; in aspeed_smc_setup_flash()
765 int ret = -ENODEV; in aspeed_smc_setup_flash()
769 struct spi_nor *nor; in aspeed_smc_setup_flash() local
772 /* This driver does not support NAND or NOR flash devices. */ in aspeed_smc_setup_flash()
773 if (!of_device_is_compatible(child, "jedec,spi-nor")) in aspeed_smc_setup_flash()
782 if (cs >= info->nce) { in aspeed_smc_setup_flash()
785 ret = -ERANGE; in aspeed_smc_setup_flash()
789 if (controller->chips[cs]) { in aspeed_smc_setup_flash()
791 cs, dev_name(controller->chips[cs]->nor.dev)); in aspeed_smc_setup_flash()
792 ret = -EBUSY; in aspeed_smc_setup_flash()
796 chip = devm_kzalloc(controller->dev, sizeof(*chip), GFP_KERNEL); in aspeed_smc_setup_flash()
798 ret = -ENOMEM; in aspeed_smc_setup_flash()
802 chip->controller = controller; in aspeed_smc_setup_flash()
803 chip->ctl = controller->regs + info->ctl0 + cs * 4; in aspeed_smc_setup_flash()
804 chip->cs = cs; in aspeed_smc_setup_flash()
806 nor = &chip->nor; in aspeed_smc_setup_flash()
807 mtd = &nor->mtd; in aspeed_smc_setup_flash()
809 nor->dev = dev; in aspeed_smc_setup_flash()
810 nor->priv = chip; in aspeed_smc_setup_flash()
811 spi_nor_set_flash_node(nor, child); in aspeed_smc_setup_flash()
812 nor->read = aspeed_smc_read_user; in aspeed_smc_setup_flash()
813 nor->write = aspeed_smc_write_user; in aspeed_smc_setup_flash()
814 nor->read_reg = aspeed_smc_read_reg; in aspeed_smc_setup_flash()
815 nor->write_reg = aspeed_smc_write_reg; in aspeed_smc_setup_flash()
816 nor->prepare = aspeed_smc_prep; in aspeed_smc_setup_flash()
817 nor->unprepare = aspeed_smc_unprep; in aspeed_smc_setup_flash()
824 * TODO: Add support for Dual and Quad SPI protocols in aspeed_smc_setup_flash()
828 ret = spi_nor_scan(nor, NULL, &hwcaps); in aspeed_smc_setup_flash()
840 controller->chips[cs] = chip; in aspeed_smc_setup_flash()
851 struct device_node *np = pdev->dev.of_node; in aspeed_smc_probe()
852 struct device *dev = &pdev->dev; in aspeed_smc_probe()
859 match = of_match_device(aspeed_smc_matches, &pdev->dev); in aspeed_smc_probe()
860 if (!match || !match->data) in aspeed_smc_probe()
861 return -ENODEV; in aspeed_smc_probe()
862 info = match->data; in aspeed_smc_probe()
864 controller = devm_kzalloc(&pdev->dev, in aspeed_smc_probe()
865 struct_size(controller, chips, info->nce), in aspeed_smc_probe()
868 return -ENOMEM; in aspeed_smc_probe()
869 controller->info = info; in aspeed_smc_probe()
870 controller->dev = dev; in aspeed_smc_probe()
872 mutex_init(&controller->mutex); in aspeed_smc_probe()
876 controller->regs = devm_ioremap_resource(dev, res); in aspeed_smc_probe()
877 if (IS_ERR(controller->regs)) in aspeed_smc_probe()
878 return PTR_ERR(controller->regs); in aspeed_smc_probe()
881 controller->ahb_base = devm_ioremap_resource(dev, res); in aspeed_smc_probe()
882 if (IS_ERR(controller->ahb_base)) in aspeed_smc_probe()
883 return PTR_ERR(controller->ahb_base); in aspeed_smc_probe()
885 controller->ahb_window_size = resource_size(res); in aspeed_smc_probe()