Skip to content

Commit d58c67d

Browse files
Fabrice Gasnierjic23
authored andcommitted
iio: adc: stm32-adc: add support for STM32MP1
Add support for STM32MP1 ADC. It's quite similar to STM32H7 ADC. Introduce new compatible to handle variants of this hardware such as vregready flag, trigger list, interrupts, clock rate. Signed-off-by: Fabrice Gasnier <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 92a3737 commit d58c67d

File tree

2 files changed

+91
-22
lines changed

2 files changed

+91
-22
lines changed

drivers/iio/adc/stm32-adc-core.c

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
#define STM32F4_ADC_ADCPRE_SHIFT 16
3535
#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
3636

37-
/* STM32 F4 maximum analog clock rate (from datasheet) */
38-
#define STM32F4_ADC_MAX_CLK_RATE 36000000
39-
4037
/* STM32H7 - common registers for all ADC instances */
4138
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
4239
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
@@ -51,9 +48,6 @@
5148
#define STM32H7_CKMODE_SHIFT 16
5249
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
5350

54-
/* STM32 H7 maximum analog clock rate (from datasheet) */
55-
#define STM32H7_ADC_MAX_CLK_RATE 36000000
56-
5751
/**
5852
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
5953
* @csr: common status register offset
@@ -74,15 +68,17 @@ struct stm32_adc_priv;
7468
* stm32_adc_priv_cfg - stm32 core compatible configuration data
7569
* @regs: common registers for all instances
7670
* @clk_sel: clock selection routine
71+
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
7772
*/
7873
struct stm32_adc_priv_cfg {
7974
const struct stm32_adc_common_regs *regs;
8075
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
76+
u32 max_clk_rate_hz;
8177
};
8278

8379
/**
8480
* struct stm32_adc_priv - stm32 ADC core private data
85-
* @irq: irq for ADC block
81+
* @irq: irq(s) for ADC block
8682
* @domain: irq domain reference
8783
* @aclk: clock reference for the analog circuitry
8884
* @bclk: bus clock common for all ADCs, depends on part used
@@ -91,7 +87,7 @@ struct stm32_adc_priv_cfg {
9187
* @common: common data for all ADC instances
9288
*/
9389
struct stm32_adc_priv {
94-
int irq;
90+
int irq[STM32_ADC_MAX_ADCS];
9591
struct irq_domain *domain;
9692
struct clk *aclk;
9793
struct clk *bclk;
@@ -133,7 +129,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
133129
}
134130

135131
for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
136-
if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
132+
if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz)
137133
break;
138134
}
139135
if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
@@ -222,7 +218,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
222218
if (ckmode)
223219
continue;
224220

225-
if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
221+
if ((rate / div) <= priv->cfg->max_clk_rate_hz)
226222
goto out;
227223
}
228224
}
@@ -242,7 +238,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
242238
if (!ckmode)
243239
continue;
244240

245-
if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
241+
if ((rate / div) <= priv->cfg->max_clk_rate_hz)
246242
goto out;
247243
}
248244

@@ -328,11 +324,24 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
328324
struct stm32_adc_priv *priv)
329325
{
330326
struct device_node *np = pdev->dev.of_node;
327+
unsigned int i;
328+
329+
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
330+
priv->irq[i] = platform_get_irq(pdev, i);
331+
if (priv->irq[i] < 0) {
332+
/*
333+
* At least one interrupt must be provided, make others
334+
* optional:
335+
* - stm32f4/h7 shares a common interrupt.
336+
* - stm32mp1, has one line per ADC (either for ADC1,
337+
* ADC2 or both).
338+
*/
339+
if (i && priv->irq[i] == -ENXIO)
340+
continue;
341+
dev_err(&pdev->dev, "failed to get irq\n");
331342

332-
priv->irq = platform_get_irq(pdev, 0);
333-
if (priv->irq < 0) {
334-
dev_err(&pdev->dev, "failed to get irq\n");
335-
return priv->irq;
343+
return priv->irq[i];
344+
}
336345
}
337346

338347
priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
@@ -343,8 +352,12 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
343352
return -ENOMEM;
344353
}
345354

346-
irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
347-
irq_set_handler_data(priv->irq, priv);
355+
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
356+
if (priv->irq[i] < 0)
357+
continue;
358+
irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler);
359+
irq_set_handler_data(priv->irq[i], priv);
360+
}
348361

349362
return 0;
350363
}
@@ -353,11 +366,17 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
353366
struct stm32_adc_priv *priv)
354367
{
355368
int hwirq;
369+
unsigned int i;
356370

357371
for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
358372
irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
359373
irq_domain_remove(priv->domain);
360-
irq_set_chained_handler(priv->irq, NULL);
374+
375+
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
376+
if (priv->irq[i] < 0)
377+
continue;
378+
irq_set_chained_handler(priv->irq[i], NULL);
379+
}
361380
}
362381

363382
static int stm32_adc_probe(struct platform_device *pdev)
@@ -497,11 +516,19 @@ static int stm32_adc_remove(struct platform_device *pdev)
497516
static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
498517
.regs = &stm32f4_adc_common_regs,
499518
.clk_sel = stm32f4_adc_clk_sel,
519+
.max_clk_rate_hz = 36000000,
500520
};
501521

502522
static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
503523
.regs = &stm32h7_adc_common_regs,
504524
.clk_sel = stm32h7_adc_clk_sel,
525+
.max_clk_rate_hz = 36000000,
526+
};
527+
528+
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
529+
.regs = &stm32h7_adc_common_regs,
530+
.clk_sel = stm32h7_adc_clk_sel,
531+
.max_clk_rate_hz = 40000000,
505532
};
506533

507534
static const struct of_device_id stm32_adc_of_match[] = {
@@ -511,6 +538,9 @@ static const struct of_device_id stm32_adc_of_match[] = {
511538
}, {
512539
.compatible = "st,stm32h7-adc-core",
513540
.data = (void *)&stm32h7_adc_priv_cfg
541+
}, {
542+
.compatible = "st,stm32mp1-adc-core",
543+
.data = (void *)&stm32mp1_adc_priv_cfg
514544
}, {
515545
},
516546
};

drivers/iio/adc/stm32-adc.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
#define STM32H7_ADC_CALFACT2 0xC8
8585

8686
/* STM32H7_ADC_ISR - bit fields */
87+
#define STM32MP1_VREGREADY BIT(12)
8788
#define STM32H7_EOC BIT(2)
8889
#define STM32H7_ADRDY BIT(0)
8990

@@ -249,6 +250,7 @@ struct stm32_adc;
249250
* @adc_info: per instance input channels definitions
250251
* @trigs: external trigger sources
251252
* @clk_required: clock is required
253+
* @has_vregready: vregready status flag presence
252254
* @selfcalib: optional routine for self-calibration
253255
* @prepare: optional prepare routine (power-up, enable)
254256
* @start_conv: routine to start conversions
@@ -261,6 +263,7 @@ struct stm32_adc_cfg {
261263
const struct stm32_adc_info *adc_info;
262264
struct stm32_adc_trig_info *trigs;
263265
bool clk_required;
266+
bool has_vregready;
264267
int (*selfcalib)(struct stm32_adc *);
265268
int (*prepare)(struct stm32_adc *);
266269
void (*start_conv)(struct stm32_adc *, bool dma);
@@ -695,8 +698,12 @@ static void stm32h7_adc_stop_conv(struct stm32_adc *adc)
695698
stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
696699
}
697700

698-
static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
701+
static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
699702
{
703+
struct iio_dev *indio_dev = iio_priv_to_dev(adc);
704+
int ret;
705+
u32 val;
706+
700707
/* Exit deep power down, then enable ADC voltage regulator */
701708
stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
702709
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
@@ -705,7 +712,20 @@ static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
705712
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
706713

707714
/* Wait for startup time */
708-
usleep_range(10, 20);
715+
if (!adc->cfg->has_vregready) {
716+
usleep_range(10, 20);
717+
return 0;
718+
}
719+
720+
ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
721+
val & STM32MP1_VREGREADY, 100,
722+
STM32_ADC_TIMEOUT_US);
723+
if (ret) {
724+
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
725+
dev_err(&indio_dev->dev, "Failed to exit power down\n");
726+
}
727+
728+
return ret;
709729
}
710730

711731
static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
@@ -888,7 +908,9 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
888908
int ret;
889909
u32 val;
890910

891-
stm32h7_adc_exit_pwr_down(adc);
911+
ret = stm32h7_adc_exit_pwr_down(adc);
912+
if (ret)
913+
return ret;
892914

893915
/*
894916
* Select calibration mode:
@@ -952,7 +974,10 @@ static int stm32h7_adc_prepare(struct stm32_adc *adc)
952974
{
953975
int ret;
954976

955-
stm32h7_adc_exit_pwr_down(adc);
977+
ret = stm32h7_adc_exit_pwr_down(adc);
978+
if (ret)
979+
return ret;
980+
956981
stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
957982

958983
ret = stm32h7_adc_enable(adc);
@@ -1944,9 +1969,23 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
19441969
.smp_cycles = stm32h7_adc_smp_cycles,
19451970
};
19461971

1972+
static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
1973+
.regs = &stm32h7_adc_regspec,
1974+
.adc_info = &stm32h7_adc_info,
1975+
.trigs = stm32h7_adc_trigs,
1976+
.has_vregready = true,
1977+
.selfcalib = stm32h7_adc_selfcalib,
1978+
.start_conv = stm32h7_adc_start_conv,
1979+
.stop_conv = stm32h7_adc_stop_conv,
1980+
.prepare = stm32h7_adc_prepare,
1981+
.unprepare = stm32h7_adc_unprepare,
1982+
.smp_cycles = stm32h7_adc_smp_cycles,
1983+
};
1984+
19471985
static const struct of_device_id stm32_adc_of_match[] = {
19481986
{ .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg },
19491987
{ .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
1988+
{ .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg },
19501989
{},
19511990
};
19521991
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);

0 commit comments

Comments
 (0)