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

Configure Feed

Select the types of activity you want to include in your feed.

spi: enable the SpacemiT K1 SoC QSPI

Merge series from Alex Elder <elder@riscstar.com>:

This series adds support for the SpacemiT K1 SoC QSPI. This IP is
generally compatible with the Freescale QSPI driver, requiring three
minor changes to enable it to be supported. The changes are:
- Adding support for optional resets
- Having the clock *not* be disabled when changing its rate
- Allowing the size of storage blocks written to flash chips
to be set to something different from the AHB buffer size

+83 -29
+18 -3
Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml
··· 9 9 maintainers: 10 10 - Han Xu <han.xu@nxp.com> 11 11 12 - allOf: 13 - - $ref: spi-controller.yaml# 14 - 15 12 properties: 16 13 compatible: 17 14 oneOf: ··· 19 22 - fsl,imx6ul-qspi 20 23 - fsl,ls1021a-qspi 21 24 - fsl,ls2080a-qspi 25 + - spacemit,k1-qspi 22 26 - items: 23 27 - enum: 24 28 - fsl,ls1043a-qspi ··· 52 54 - const: qspi_en 53 55 - const: qspi 54 56 57 + resets: 58 + items: 59 + - description: SoC QSPI reset 60 + - description: SoC QSPI bus reset 61 + 55 62 required: 56 63 - compatible 57 64 - reg ··· 64 61 - interrupts 65 62 - clocks 66 63 - clock-names 64 + 65 + allOf: 66 + - $ref: spi-controller.yaml# 67 + - if: 68 + properties: 69 + compatible: 70 + not: 71 + contains: 72 + const: spacemit,k1-qspi 73 + then: 74 + properties: 75 + resets: false 67 76 68 77 unevaluatedProperties: false 69 78
+2 -1
drivers/spi/Kconfig
··· 435 435 436 436 config SPI_FSL_QUADSPI 437 437 tristate "Freescale QSPI controller" 438 - depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST 438 + depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || \ 439 + ARCH_SPACEMIT || COMPILE_TEST 439 440 depends on HAS_IOMEM 440 441 help 441 442 This enables support for the Quad SPI controller in master mode.
+63 -25
drivers/spi/spi-fsl-qspi.c
··· 36 36 #include <linux/of.h> 37 37 #include <linux/platform_device.h> 38 38 #include <linux/pm_qos.h> 39 + #include <linux/reset.h> 39 40 #include <linux/sizes.h> 40 41 41 42 #include <linux/spi/spi.h> ··· 197 196 */ 198 197 #define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5) 199 198 199 + /* 200 + * Do not disable the "qspi" clock when changing its rate. 201 + */ 202 + #define QUADSPI_QUIRK_SKIP_CLK_DISABLE BIT(6) 203 + 200 204 struct fsl_qspi_devtype_data { 201 205 unsigned int rxfifo; 202 206 unsigned int txfifo; 203 207 int invalid_mstrid; 204 208 unsigned int ahb_buf_size; 209 + unsigned int sfa_size; 205 210 unsigned int quirks; 206 211 bool little_endian; 207 212 }; ··· 268 261 .little_endian = true, 269 262 }; 270 263 264 + static const struct fsl_qspi_devtype_data spacemit_k1_data = { 265 + .rxfifo = SZ_128, 266 + .txfifo = SZ_256, 267 + .ahb_buf_size = SZ_512, 268 + .sfa_size = SZ_1K, 269 + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, 270 + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_SKIP_CLK_DISABLE, 271 + .little_endian = true, 272 + }; 273 + 271 274 struct fsl_qspi { 272 275 void __iomem *iobase; 273 276 void __iomem *ahb_addr; 274 277 const struct fsl_qspi_devtype_data *devtype_data; 275 278 struct mutex lock; 276 279 struct completion c; 280 + struct reset_control *resets; 277 281 struct clk *clk, *clk_en; 278 282 struct pm_qos_request pm_qos_req; 279 283 struct device *dev; ··· 292 274 u32 memmap_phy; 293 275 }; 294 276 295 - static inline int needs_swap_endian(struct fsl_qspi *q) 277 + static bool needs_swap_endian(struct fsl_qspi *q) 296 278 { 297 - return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN; 279 + return !!(q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN); 298 280 } 299 281 300 - static inline int needs_4x_clock(struct fsl_qspi *q) 282 + static bool needs_4x_clock(struct fsl_qspi *q) 301 283 { 302 - return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK; 284 + return !!(q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK); 303 285 } 304 286 305 - static inline int needs_fill_txfifo(struct fsl_qspi *q) 287 + static bool needs_fill_txfifo(struct fsl_qspi *q) 306 288 { 307 - return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890; 289 + return !!(q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890); 308 290 } 309 291 310 - static inline int needs_wakeup_wait_mode(struct fsl_qspi *q) 292 + static bool needs_wakeup_wait_mode(struct fsl_qspi *q) 311 293 { 312 - return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618; 294 + return !!(q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618); 313 295 } 314 296 315 - static inline int needs_amba_base_offset(struct fsl_qspi *q) 297 + static bool needs_amba_base_offset(struct fsl_qspi *q) 316 298 { 317 299 return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); 318 300 } 319 301 320 - static inline int needs_tdh_setting(struct fsl_qspi *q) 302 + static bool needs_tdh_setting(struct fsl_qspi *q) 321 303 { 322 - return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; 304 + return !!(q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING); 305 + } 306 + 307 + static bool needs_clk_disable(struct fsl_qspi *q) 308 + { 309 + return !(q->devtype_data->quirks & QUADSPI_QUIRK_SKIP_CLK_DISABLE); 323 310 } 324 311 325 312 /* ··· 557 534 if (needs_4x_clock(q)) 558 535 rate *= 4; 559 536 560 - fsl_qspi_clk_disable_unprep(q); 537 + if (needs_clk_disable(q)) 538 + fsl_qspi_clk_disable_unprep(q); 561 539 562 540 ret = clk_set_rate(q->clk, rate); 563 541 if (ret) 564 542 return; 565 543 566 - ret = fsl_qspi_clk_prep_enable(q); 567 - if (ret) 568 - return; 544 + if (needs_clk_disable(q)) { 545 + ret = fsl_qspi_clk_prep_enable(q); 546 + if (ret) 547 + return; 548 + } 569 549 570 550 q->selected = spi_get_chipselect(spi, 0); 571 551 ··· 748 722 { 749 723 void __iomem *base = q->iobase; 750 724 u32 reg, addr_offset = 0; 725 + u32 sfa_size; 751 726 int ret; 752 727 753 728 /* disable and unprepare clock to avoid glitch pass to controller */ ··· 807 780 * In HW there can be a maximum of four chips on two buses with 808 781 * two chip selects on each bus. We use four chip selects in SW 809 782 * to differentiate between the four chips. 810 - * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD, 811 - * SFB2AD accordingly. 783 + * 784 + * By default we write the AHB buffer size to each chip, but 785 + * a different size can be specified with devtype_data->sfa_size. 786 + * The SFA1AD, SFA2AD, SFB1AD, and SFB2AD registers define the 787 + * top (end) of these four regions. 812 788 */ 813 - qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset, 814 - base + QUADSPI_SFA1AD); 815 - qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset, 816 - base + QUADSPI_SFA2AD); 817 - qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset, 818 - base + QUADSPI_SFB1AD); 819 - qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset, 820 - base + QUADSPI_SFB2AD); 789 + sfa_size = q->devtype_data->sfa_size ? : q->devtype_data->ahb_buf_size; 790 + qspi_writel(q, addr_offset + 1 * sfa_size, base + QUADSPI_SFA1AD); 791 + qspi_writel(q, addr_offset + 2 * sfa_size, base + QUADSPI_SFA2AD); 792 + qspi_writel(q, addr_offset + 3 * sfa_size, base + QUADSPI_SFB1AD); 793 + qspi_writel(q, addr_offset + 4 * sfa_size, base + QUADSPI_SFB2AD); 821 794 822 795 q->selected = -1; 823 796 ··· 884 857 { 885 858 struct fsl_qspi *q = data; 886 859 860 + reset_control_assert(q->resets); 861 + 887 862 fsl_qspi_clk_disable_unprep(q); 888 863 889 864 mutex_destroy(&q->lock); ··· 931 902 if (!q->ahb_addr) 932 903 return -ENOMEM; 933 904 905 + q->resets = devm_reset_control_array_get_optional_exclusive(dev); 906 + if (IS_ERR(q->resets)) 907 + return PTR_ERR(q->resets); 908 + 934 909 /* find the clocks */ 935 910 q->clk_en = devm_clk_get(dev, "qspi_en"); 936 911 if (IS_ERR(q->clk_en)) ··· 953 920 } 954 921 955 922 ret = devm_add_action_or_reset(dev, fsl_qspi_cleanup, q); 923 + if (ret) 924 + return ret; 925 + 926 + ret = reset_control_deassert(q->resets); 956 927 if (ret) 957 928 return ret; 958 929 ··· 1013 976 { .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, }, 1014 977 { .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, }, 1015 978 { .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, }, 979 + { .compatible = "spacemit,k1-qspi", .data = &spacemit_k1_data, }, 1016 980 { /* sentinel */ } 1017 981 }; 1018 982 MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);