Skip to content

Commit 339800d

Browse files
committed
Merge tag 'spi-fix-v6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "A few fixes that came in since my pull request, the Meson fix is a little large since it's fixing all possible cases of the problem that was observed with the driver and clock API trying to share configuration by integrating the device clocking fully with the clock API rather than spot fixing the one instance that was observed" * tag 'spi-fix-v6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: dt-bindings: Drop Pratyush Yadav spi: meson-spicc: add local pow2 clock ops to preserve rate between messages MAINTAINERS: rectify entry for ARM/HPE GXP ARCHITECTURE spi: spi.c: Add missing __percpu annotations in users of spi_statistics
2 parents 15df648 + 2fd92c7 commit 339800d

6 files changed

Lines changed: 112 additions & 39 deletions

File tree

Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ description:
1010
See spi-peripheral-props.yaml for more info.
1111

1212
maintainers:
13-
- Pratyush Yadav <p.yadav@ti.com>
13+
- Vaishnav Achath <vaishnav.a@ti.com>
1414

1515
properties:
1616
# cdns,qspi-nor.yaml

Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
77
title: Cadence Quad SPI controller
88

99
maintainers:
10-
- Pratyush Yadav <p.yadav@ti.com>
10+
- Vaishnav Achath <vaishnav.a@ti.com>
1111

1212
allOf:
1313
- $ref: spi-controller.yaml#

Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ description:
1616
their own separate schema that should be referenced from here.
1717

1818
maintainers:
19-
- Pratyush Yadav <p.yadav@ti.com>
19+
- Mark Brown <broonie@kernel.org>
2020

2121
properties:
2222
reg:

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2178,7 +2178,7 @@ M: Jean-Marie Verdun <verdun@hpe.com>
21782178
M: Nick Hawkins <nick.hawkins@hpe.com>
21792179
S: Maintained
21802180
F: Documentation/devicetree/bindings/arm/hpe,gxp.yaml
2181-
F: Documentation/devicetree/bindings/spi/hpe,gxp-spi.yaml
2181+
F: Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
21822182
F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
21832183
F: arch/arm/boot/dts/hpe-bmc*
21842184
F: arch/arm/boot/dts/hpe-gxp*

drivers/spi/spi-meson-spicc.c

Lines changed: 101 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ struct meson_spicc_device {
156156
void __iomem *base;
157157
struct clk *core;
158158
struct clk *pclk;
159+
struct clk_divider pow2_div;
159160
struct clk *clk;
160161
struct spi_message *message;
161162
struct spi_transfer *xfer;
@@ -168,6 +169,8 @@ struct meson_spicc_device {
168169
unsigned long xfer_remain;
169170
};
170171

172+
#define pow2_clk_to_spicc(_div) container_of(_div, struct meson_spicc_device, pow2_div)
173+
171174
static void meson_spicc_oen_enable(struct meson_spicc_device *spicc)
172175
{
173176
u32 conf;
@@ -421,7 +424,7 @@ static int meson_spicc_prepare_message(struct spi_master *master,
421424
{
422425
struct meson_spicc_device *spicc = spi_master_get_devdata(master);
423426
struct spi_device *spi = message->spi;
424-
u32 conf = 0;
427+
u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK;
425428

426429
/* Store current message */
427430
spicc->message = message;
@@ -458,8 +461,6 @@ static int meson_spicc_prepare_message(struct spi_master *master,
458461
/* Select CS */
459462
conf |= FIELD_PREP(SPICC_CS_MASK, spi->chip_select);
460463

461-
/* Default Clock rate core/4 */
462-
463464
/* Default 8bit word */
464465
conf |= FIELD_PREP(SPICC_BITLENGTH_MASK, 8 - 1);
465466

@@ -476,12 +477,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
476477
static int meson_spicc_unprepare_transfer(struct spi_master *master)
477478
{
478479
struct meson_spicc_device *spicc = spi_master_get_devdata(master);
480+
u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK;
479481

480482
/* Disable all IRQs */
481483
writel(0, spicc->base + SPICC_INTREG);
482484

483485
device_reset_optional(&spicc->pdev->dev);
484486

487+
/* Set default configuration, keeping datarate field */
488+
writel_relaxed(conf, spicc->base + SPICC_CONREG);
489+
485490
return 0;
486491
}
487492

@@ -518,14 +523,60 @@ static void meson_spicc_cleanup(struct spi_device *spi)
518523
* Clk path for G12A series:
519524
* pclk -> pow2 fixed div -> pow2 div -> mux -> out
520525
* pclk -> enh fixed div -> enh div -> mux -> out
526+
*
527+
* The pow2 divider is tied to the controller HW state, and the
528+
* divider is only valid when the controller is initialized.
529+
*
530+
* A set of clock ops is added to make sure we don't read/set this
531+
* clock rate while the controller is in an unknown state.
521532
*/
522533

523-
static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
534+
static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw,
535+
unsigned long parent_rate)
536+
{
537+
struct clk_divider *divider = to_clk_divider(hw);
538+
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
539+
540+
if (!spicc->master->cur_msg || !spicc->master->busy)
541+
return 0;
542+
543+
return clk_divider_ops.recalc_rate(hw, parent_rate);
544+
}
545+
546+
static int meson_spicc_pow2_determine_rate(struct clk_hw *hw,
547+
struct clk_rate_request *req)
548+
{
549+
struct clk_divider *divider = to_clk_divider(hw);
550+
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
551+
552+
if (!spicc->master->cur_msg || !spicc->master->busy)
553+
return -EINVAL;
554+
555+
return clk_divider_ops.determine_rate(hw, req);
556+
}
557+
558+
static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate,
559+
unsigned long parent_rate)
560+
{
561+
struct clk_divider *divider = to_clk_divider(hw);
562+
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
563+
564+
if (!spicc->master->cur_msg || !spicc->master->busy)
565+
return -EINVAL;
566+
567+
return clk_divider_ops.set_rate(hw, rate, parent_rate);
568+
}
569+
570+
const struct clk_ops meson_spicc_pow2_clk_ops = {
571+
.recalc_rate = meson_spicc_pow2_recalc_rate,
572+
.determine_rate = meson_spicc_pow2_determine_rate,
573+
.set_rate = meson_spicc_pow2_set_rate,
574+
};
575+
576+
static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc)
524577
{
525578
struct device *dev = &spicc->pdev->dev;
526-
struct clk_fixed_factor *pow2_fixed_div, *enh_fixed_div;
527-
struct clk_divider *pow2_div, *enh_div;
528-
struct clk_mux *mux;
579+
struct clk_fixed_factor *pow2_fixed_div;
529580
struct clk_init_data init;
530581
struct clk *clk;
531582
struct clk_parent_data parent_data[2];
@@ -560,31 +611,45 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
560611
if (WARN_ON(IS_ERR(clk)))
561612
return PTR_ERR(clk);
562613

563-
pow2_div = devm_kzalloc(dev, sizeof(*pow2_div), GFP_KERNEL);
564-
if (!pow2_div)
565-
return -ENOMEM;
566-
567614
snprintf(name, sizeof(name), "%s#pow2_div", dev_name(dev));
568615
init.name = name;
569-
init.ops = &clk_divider_ops;
570-
init.flags = CLK_SET_RATE_PARENT;
616+
init.ops = &meson_spicc_pow2_clk_ops;
617+
/*
618+
* Set NOCACHE here to make sure we read the actual HW value
619+
* since we reset the HW after each transfer.
620+
*/
621+
init.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
571622
parent_data[0].hw = &pow2_fixed_div->hw;
572623
init.num_parents = 1;
573624

574-
pow2_div->shift = 16,
575-
pow2_div->width = 3,
576-
pow2_div->flags = CLK_DIVIDER_POWER_OF_TWO,
577-
pow2_div->reg = spicc->base + SPICC_CONREG;
578-
pow2_div->hw.init = &init;
625+
spicc->pow2_div.shift = 16,
626+
spicc->pow2_div.width = 3,
627+
spicc->pow2_div.flags = CLK_DIVIDER_POWER_OF_TWO,
628+
spicc->pow2_div.reg = spicc->base + SPICC_CONREG;
629+
spicc->pow2_div.hw.init = &init;
579630

580-
clk = devm_clk_register(dev, &pow2_div->hw);
581-
if (WARN_ON(IS_ERR(clk)))
582-
return PTR_ERR(clk);
631+
spicc->clk = devm_clk_register(dev, &spicc->pow2_div.hw);
632+
if (WARN_ON(IS_ERR(spicc->clk)))
633+
return PTR_ERR(spicc->clk);
583634

584-
if (!spicc->data->has_enhance_clk_div) {
585-
spicc->clk = clk;
586-
return 0;
587-
}
635+
return 0;
636+
}
637+
638+
static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
639+
{
640+
struct device *dev = &spicc->pdev->dev;
641+
struct clk_fixed_factor *enh_fixed_div;
642+
struct clk_divider *enh_div;
643+
struct clk_mux *mux;
644+
struct clk_init_data init;
645+
struct clk *clk;
646+
struct clk_parent_data parent_data[2];
647+
char name[64];
648+
649+
memset(&init, 0, sizeof(init));
650+
memset(&parent_data, 0, sizeof(parent_data));
651+
652+
init.parent_data = parent_data;
588653

589654
/* algorithm for enh div: rate = freq / 2 / (N + 1) */
590655

@@ -637,7 +702,7 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
637702
snprintf(name, sizeof(name), "%s#sel", dev_name(dev));
638703
init.name = name;
639704
init.ops = &clk_mux_ops;
640-
parent_data[0].hw = &pow2_div->hw;
705+
parent_data[0].hw = &spicc->pow2_div.hw;
641706
parent_data[1].hw = &enh_div->hw;
642707
init.num_parents = 2;
643708
init.flags = CLK_SET_RATE_PARENT;
@@ -754,12 +819,20 @@ static int meson_spicc_probe(struct platform_device *pdev)
754819

755820
meson_spicc_oen_enable(spicc);
756821

757-
ret = meson_spicc_clk_init(spicc);
822+
ret = meson_spicc_pow2_clk_init(spicc);
758823
if (ret) {
759-
dev_err(&pdev->dev, "clock registration failed\n");
824+
dev_err(&pdev->dev, "pow2 clock registration failed\n");
760825
goto out_clk;
761826
}
762827

828+
if (spicc->data->has_enhance_clk_div) {
829+
ret = meson_spicc_enh_clk_init(spicc);
830+
if (ret) {
831+
dev_err(&pdev->dev, "clock registration failed\n");
832+
goto out_clk;
833+
}
834+
}
835+
763836
ret = devm_spi_register_master(&pdev->dev, master);
764837
if (ret) {
765838
dev_err(&pdev->dev, "spi master registration failed\n");

drivers/spi/spi.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static ssize_t driver_override_show(struct device *dev,
9595
}
9696
static DEVICE_ATTR_RW(driver_override);
9797

98-
static struct spi_statistics *spi_alloc_pcpu_stats(struct device *dev)
98+
static struct spi_statistics __percpu *spi_alloc_pcpu_stats(struct device *dev)
9999
{
100100
struct spi_statistics __percpu *pcpu_stats;
101101

@@ -162,7 +162,7 @@ static struct device_attribute dev_attr_spi_device_##field = { \
162162
}
163163

164164
#define SPI_STATISTICS_SHOW_NAME(name, file, field) \
165-
static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \
165+
static ssize_t spi_statistics_##name##_show(struct spi_statistics __percpu *stat, \
166166
char *buf) \
167167
{ \
168168
ssize_t len; \
@@ -309,7 +309,7 @@ static const struct attribute_group *spi_master_groups[] = {
309309
NULL,
310310
};
311311

312-
static void spi_statistics_add_transfer_stats(struct spi_statistics *pcpu_stats,
312+
static void spi_statistics_add_transfer_stats(struct spi_statistics __percpu *pcpu_stats,
313313
struct spi_transfer *xfer,
314314
struct spi_controller *ctlr)
315315
{
@@ -1275,8 +1275,8 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
12751275
struct spi_message *msg,
12761276
struct spi_transfer *xfer)
12771277
{
1278-
struct spi_statistics *statm = ctlr->pcpu_statistics;
1279-
struct spi_statistics *stats = msg->spi->pcpu_statistics;
1278+
struct spi_statistics __percpu *statm = ctlr->pcpu_statistics;
1279+
struct spi_statistics __percpu *stats = msg->spi->pcpu_statistics;
12801280
u32 speed_hz = xfer->speed_hz;
12811281
unsigned long long ms;
12821282

@@ -1432,8 +1432,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
14321432
struct spi_transfer *xfer;
14331433
bool keep_cs = false;
14341434
int ret = 0;
1435-
struct spi_statistics *statm = ctlr->pcpu_statistics;
1436-
struct spi_statistics *stats = msg->spi->pcpu_statistics;
1435+
struct spi_statistics __percpu *statm = ctlr->pcpu_statistics;
1436+
struct spi_statistics __percpu *stats = msg->spi->pcpu_statistics;
14371437

14381438
spi_set_cs(msg->spi, true, false);
14391439

0 commit comments

Comments
 (0)