Skip to content

Commit 4a58f60

Browse files
committed
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
2 parents 4e92abd + abc9a34 commit 4a58f60

3 files changed

Lines changed: 83 additions & 29 deletions

File tree

Documentation/devicetree/bindings/spi/fsl,spi-fsl-qspi.yaml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ title: Freescale Quad Serial Peripheral Interface (QuadSPI)
99
maintainers:
1010
- Han Xu <han.xu@nxp.com>
1111

12-
allOf:
13-
- $ref: spi-controller.yaml#
14-
1512
properties:
1613
compatible:
1714
oneOf:
@@ -22,6 +19,7 @@ properties:
2219
- fsl,imx6ul-qspi
2320
- fsl,ls1021a-qspi
2421
- fsl,ls2080a-qspi
22+
- spacemit,k1-qspi
2523
- items:
2624
- enum:
2725
- fsl,ls1043a-qspi
@@ -54,6 +52,11 @@ properties:
5452
- const: qspi_en
5553
- const: qspi
5654

55+
resets:
56+
items:
57+
- description: SoC QSPI reset
58+
- description: SoC QSPI bus reset
59+
5760
required:
5861
- compatible
5962
- reg
@@ -62,6 +65,18 @@ required:
6265
- clocks
6366
- clock-names
6467

68+
allOf:
69+
- $ref: spi-controller.yaml#
70+
- if:
71+
properties:
72+
compatible:
73+
not:
74+
contains:
75+
const: spacemit,k1-qspi
76+
then:
77+
properties:
78+
resets: false
79+
6580
unevaluatedProperties: false
6681

6782
examples:

drivers/spi/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ config SPI_FSL_LPSPI
435435

436436
config SPI_FSL_QUADSPI
437437
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
439440
depends on HAS_IOMEM
440441
help
441442
This enables support for the Quad SPI controller in master mode.

drivers/spi/spi-fsl-qspi.c

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/of.h>
3737
#include <linux/platform_device.h>
3838
#include <linux/pm_qos.h>
39+
#include <linux/reset.h>
3940
#include <linux/sizes.h>
4041

4142
#include <linux/spi/spi.h>
@@ -196,11 +197,17 @@
196197
*/
197198
#define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5)
198199

200+
/*
201+
* Do not disable the "qspi" clock when changing its rate.
202+
*/
203+
#define QUADSPI_QUIRK_SKIP_CLK_DISABLE BIT(6)
204+
199205
struct fsl_qspi_devtype_data {
200206
unsigned int rxfifo;
201207
unsigned int txfifo;
202208
int invalid_mstrid;
203209
unsigned int ahb_buf_size;
210+
unsigned int sfa_size;
204211
unsigned int quirks;
205212
bool little_endian;
206213
};
@@ -261,47 +268,63 @@ static const struct fsl_qspi_devtype_data ls2080a_data = {
261268
.little_endian = true,
262269
};
263270

271+
static const struct fsl_qspi_devtype_data spacemit_k1_data = {
272+
.rxfifo = SZ_128,
273+
.txfifo = SZ_256,
274+
.ahb_buf_size = SZ_512,
275+
.sfa_size = SZ_1K,
276+
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
277+
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_SKIP_CLK_DISABLE,
278+
.little_endian = true,
279+
};
280+
264281
struct fsl_qspi {
265282
void __iomem *iobase;
266283
void __iomem *ahb_addr;
267284
const struct fsl_qspi_devtype_data *devtype_data;
268285
struct mutex lock;
269286
struct completion c;
287+
struct reset_control *resets;
270288
struct clk *clk, *clk_en;
271289
struct pm_qos_request pm_qos_req;
272290
struct device *dev;
273291
int selected;
274292
u32 memmap_phy;
275293
};
276294

277-
static inline int needs_swap_endian(struct fsl_qspi *q)
295+
static bool needs_swap_endian(struct fsl_qspi *q)
278296
{
279-
return q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN;
297+
return !!(q->devtype_data->quirks & QUADSPI_QUIRK_SWAP_ENDIAN);
280298
}
281299

282-
static inline int needs_4x_clock(struct fsl_qspi *q)
300+
static bool needs_4x_clock(struct fsl_qspi *q)
283301
{
284-
return q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK;
302+
return !!(q->devtype_data->quirks & QUADSPI_QUIRK_4X_INT_CLK);
285303
}
286304

287-
static inline int needs_fill_txfifo(struct fsl_qspi *q)
305+
static bool needs_fill_txfifo(struct fsl_qspi *q)
288306
{
289-
return q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890;
307+
return !!(q->devtype_data->quirks & QUADSPI_QUIRK_TKT253890);
290308
}
291309

292-
static inline int needs_wakeup_wait_mode(struct fsl_qspi *q)
310+
static bool needs_wakeup_wait_mode(struct fsl_qspi *q)
293311
{
294-
return q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618;
312+
return !!(q->devtype_data->quirks & QUADSPI_QUIRK_TKT245618);
295313
}
296314

297-
static inline int needs_amba_base_offset(struct fsl_qspi *q)
315+
static bool needs_amba_base_offset(struct fsl_qspi *q)
298316
{
299317
return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL);
300318
}
301319

302-
static inline int needs_tdh_setting(struct fsl_qspi *q)
320+
static bool needs_tdh_setting(struct fsl_qspi *q)
321+
{
322+
return !!(q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING);
323+
}
324+
325+
static bool needs_clk_disable(struct fsl_qspi *q)
303326
{
304-
return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING;
327+
return !(q->devtype_data->quirks & QUADSPI_QUIRK_SKIP_CLK_DISABLE);
305328
}
306329

307330
/*
@@ -534,15 +557,18 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi,
534557
if (needs_4x_clock(q))
535558
rate *= 4;
536559

537-
fsl_qspi_clk_disable_unprep(q);
560+
if (needs_clk_disable(q))
561+
fsl_qspi_clk_disable_unprep(q);
538562

539563
ret = clk_set_rate(q->clk, rate);
540564
if (ret)
541565
return;
542566

543-
ret = fsl_qspi_clk_prep_enable(q);
544-
if (ret)
545-
return;
567+
if (needs_clk_disable(q)) {
568+
ret = fsl_qspi_clk_prep_enable(q);
569+
if (ret)
570+
return;
571+
}
546572

547573
q->selected = spi_get_chipselect(spi, 0);
548574

@@ -722,6 +748,7 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q)
722748
{
723749
void __iomem *base = q->iobase;
724750
u32 reg, addr_offset = 0;
751+
u32 sfa_size;
725752
int ret;
726753

727754
/* disable and unprepare clock to avoid glitch pass to controller */
@@ -780,17 +807,17 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q)
780807
* In HW there can be a maximum of four chips on two buses with
781808
* two chip selects on each bus. We use four chip selects in SW
782809
* to differentiate between the four chips.
783-
* We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
784-
* SFB2AD accordingly.
810+
*
811+
* By default we write the AHB buffer size to each chip, but
812+
* a different size can be specified with devtype_data->sfa_size.
813+
* The SFA1AD, SFA2AD, SFB1AD, and SFB2AD registers define the
814+
* top (end) of these four regions.
785815
*/
786-
qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset,
787-
base + QUADSPI_SFA1AD);
788-
qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset,
789-
base + QUADSPI_SFA2AD);
790-
qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset,
791-
base + QUADSPI_SFB1AD);
792-
qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset,
793-
base + QUADSPI_SFB2AD);
816+
sfa_size = q->devtype_data->sfa_size ? : q->devtype_data->ahb_buf_size;
817+
qspi_writel(q, addr_offset + 1 * sfa_size, base + QUADSPI_SFA1AD);
818+
qspi_writel(q, addr_offset + 2 * sfa_size, base + QUADSPI_SFA2AD);
819+
qspi_writel(q, addr_offset + 3 * sfa_size, base + QUADSPI_SFB1AD);
820+
qspi_writel(q, addr_offset + 4 * sfa_size, base + QUADSPI_SFB2AD);
794821

795822
q->selected = -1;
796823

@@ -857,6 +884,8 @@ static void fsl_qspi_cleanup(void *data)
857884
{
858885
struct fsl_qspi *q = data;
859886

887+
reset_control_assert(q->resets);
888+
860889
fsl_qspi_clk_disable_unprep(q);
861890

862891
mutex_destroy(&q->lock);
@@ -902,6 +931,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)
902931
if (!q->ahb_addr)
903932
return -ENOMEM;
904933

934+
q->resets = devm_reset_control_array_get_optional_exclusive(dev);
935+
if (IS_ERR(q->resets))
936+
return PTR_ERR(q->resets);
937+
905938
/* find the clocks */
906939
q->clk_en = devm_clk_get(dev, "qspi_en");
907940
if (IS_ERR(q->clk_en))
@@ -923,6 +956,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)
923956
if (ret)
924957
return ret;
925958

959+
ret = reset_control_deassert(q->resets);
960+
if (ret)
961+
return ret;
962+
926963
/* find the irq */
927964
ret = platform_get_irq(pdev, 0);
928965
if (ret < 0)
@@ -976,6 +1013,7 @@ static const struct of_device_id fsl_qspi_dt_ids[] = {
9761013
{ .compatible = "fsl,imx6ul-qspi", .data = &imx6ul_data, },
9771014
{ .compatible = "fsl,ls1021a-qspi", .data = &ls1021a_data, },
9781015
{ .compatible = "fsl,ls2080a-qspi", .data = &ls2080a_data, },
1016+
{ .compatible = "spacemit,k1-qspi", .data = &spacemit_k1_data, },
9791017
{ /* sentinel */ }
9801018
};
9811019
MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);

0 commit comments

Comments
 (0)