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

spi: spi-nxp-fspi: few fix for flexspi

Merge series from Haibo Chen <haibo.chen@nxp.com>:

PATCH 1: different operations maybe require different max frequency, so
add flexspi to handle such case, re-config the clock rate when
new coming operation require new clock frequency.
Patch 2: add workaround for erratum ERR050272. Since only add 4us dealy
in nxp_fspi_dll_calibration(), so do not distinguish different
platforms.
Patch 3: add max frequency limitation for different sample clock source
selection. Datasheet give max 66MHz for mode 0 and 166MHz for
mode 3. And IC suggest to add this limitation on all SoCs for
safety and stability.

+27 -5
+27 -5
drivers/spi/spi-nxp-fspi.c
··· 404 404 #define FSPI_NEED_INIT BIT(0) 405 405 #define FSPI_DTR_MODE BIT(1) 406 406 int flags; 407 + /* save the previous operation clock rate */ 408 + unsigned long pre_op_rate; 409 + /* the max clock rate fspi output to device */ 410 + unsigned long max_rate; 407 411 }; 408 412 409 413 static inline int needs_ip_only(struct nxp_fspi *f) ··· 689 685 * change the mode back to mode 0. 690 686 */ 691 687 reg = fspi_readl(f, f->iobase + FSPI_MCR0); 692 - if (op_is_dtr) 688 + if (op_is_dtr) { 693 689 reg |= FSPI_MCR0_RXCLKSRC(3); 694 - else /*select mode 0 */ 690 + f->max_rate = 166000000; 691 + } else { /*select mode 0 */ 695 692 reg &= ~FSPI_MCR0_RXCLKSRC(3); 693 + f->max_rate = 66000000; 694 + } 696 695 fspi_writel(f, reg, f->iobase + FSPI_MCR0); 697 696 } 698 697 ··· 726 719 0, POLL_TOUT, true); 727 720 if (ret) 728 721 dev_warn(f->dev, "DLL lock failed, please fix it!\n"); 722 + 723 + /* 724 + * For ERR050272, DLL lock status bit is not accurate, 725 + * wait for 4us more as a workaround. 726 + */ 727 + udelay(4); 729 728 } 730 729 731 730 /* ··· 793 780 uint64_t size_kb; 794 781 795 782 /* 796 - * Return, if previously selected target device is same as current 797 - * requested target device. Also the DTR or STR mode do not change. 783 + * Return when following condition all meet, 784 + * 1, if previously selected target device is same as current 785 + * requested target device. 786 + * 2, the DTR or STR mode do not change. 787 + * 3, previous operation max rate equals current one. 788 + * 789 + * For other case, need to re-config. 798 790 */ 799 791 if ((f->selected == spi_get_chipselect(spi, 0)) && 800 - (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr)) 792 + (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr) && 793 + (f->pre_op_rate == op->max_freq)) 801 794 return; 802 795 803 796 /* Reset FLSHxxCR0 registers */ ··· 821 802 dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0)); 822 803 823 804 nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr); 805 + rate = min(f->max_rate, op->max_freq); 824 806 825 807 if (op_is_dtr) { 826 808 f->flags |= FSPI_DTR_MODE; ··· 851 831 nxp_fspi_dll_calibration(f); 852 832 else 853 833 nxp_fspi_dll_override(f); 834 + 835 + f->pre_op_rate = op->max_freq; 854 836 855 837 f->selected = spi_get_chipselect(spi, 0); 856 838 }