-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
STM32 Low-Power Timer hardware block can be used for: - PWM generation - IIO trigger (in sync with PWM) - IIO quadrature encoder counter PWM and IIO timer configuration are mixed in the same registers so we need a multi fonction driver to be able to share those registers. Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
- Loading branch information
Fabrice Gasnier
authored and
Lee Jones
committed
Sep 4, 2017
1 parent
a7a0db0
commit e892400
Showing
4 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* STM32 Low-Power Timer parent driver. | ||
* | ||
* Copyright (C) STMicroelectronics 2017 | ||
* | ||
* Author: Fabrice Gasnier <fabrice.gasnier@st.com> | ||
* | ||
* Inspired by Benjamin Gaignard's stm32-timers driver | ||
* | ||
* License terms: GNU General Public License (GPL), version 2 | ||
*/ | ||
|
||
#include <linux/mfd/stm32-lptimer.h> | ||
#include <linux/module.h> | ||
#include <linux/of_platform.h> | ||
|
||
#define STM32_LPTIM_MAX_REGISTER 0x3fc | ||
|
||
static const struct regmap_config stm32_lptimer_regmap_cfg = { | ||
.reg_bits = 32, | ||
.val_bits = 32, | ||
.reg_stride = sizeof(u32), | ||
.max_register = STM32_LPTIM_MAX_REGISTER, | ||
}; | ||
|
||
static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata) | ||
{ | ||
u32 val; | ||
int ret; | ||
|
||
/* | ||
* Quadrature encoder mode bit can only be written and read back when | ||
* Low-Power Timer supports it. | ||
*/ | ||
ret = regmap_update_bits(ddata->regmap, STM32_LPTIM_CFGR, | ||
STM32_LPTIM_ENC, STM32_LPTIM_ENC); | ||
if (ret) | ||
return ret; | ||
|
||
ret = regmap_read(ddata->regmap, STM32_LPTIM_CFGR, &val); | ||
if (ret) | ||
return ret; | ||
|
||
ret = regmap_update_bits(ddata->regmap, STM32_LPTIM_CFGR, | ||
STM32_LPTIM_ENC, 0); | ||
if (ret) | ||
return ret; | ||
|
||
ddata->has_encoder = !!(val & STM32_LPTIM_ENC); | ||
|
||
return 0; | ||
} | ||
|
||
static int stm32_lptimer_probe(struct platform_device *pdev) | ||
{ | ||
struct device *dev = &pdev->dev; | ||
struct stm32_lptimer *ddata; | ||
struct resource *res; | ||
void __iomem *mmio; | ||
int ret; | ||
|
||
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); | ||
if (!ddata) | ||
return -ENOMEM; | ||
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
mmio = devm_ioremap_resource(dev, res); | ||
if (IS_ERR(mmio)) | ||
return PTR_ERR(mmio); | ||
|
||
ddata->regmap = devm_regmap_init_mmio_clk(dev, "mux", mmio, | ||
&stm32_lptimer_regmap_cfg); | ||
if (IS_ERR(ddata->regmap)) | ||
return PTR_ERR(ddata->regmap); | ||
|
||
ddata->clk = devm_clk_get(dev, NULL); | ||
if (IS_ERR(ddata->clk)) | ||
return PTR_ERR(ddata->clk); | ||
|
||
ret = stm32_lptimer_detect_encoder(ddata); | ||
if (ret) | ||
return ret; | ||
|
||
platform_set_drvdata(pdev, ddata); | ||
|
||
return devm_of_platform_populate(&pdev->dev); | ||
} | ||
|
||
static const struct of_device_id stm32_lptimer_of_match[] = { | ||
{ .compatible = "st,stm32-lptimer", }, | ||
{}, | ||
}; | ||
MODULE_DEVICE_TABLE(of, stm32_lptimer_of_match); | ||
|
||
static struct platform_driver stm32_lptimer_driver = { | ||
.probe = stm32_lptimer_probe, | ||
.driver = { | ||
.name = "stm32-lptimer", | ||
.of_match_table = stm32_lptimer_of_match, | ||
}, | ||
}; | ||
module_platform_driver(stm32_lptimer_driver); | ||
|
||
MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); | ||
MODULE_DESCRIPTION("STMicroelectronics STM32 Low-Power Timer"); | ||
MODULE_ALIAS("platform:stm32-lptimer"); | ||
MODULE_LICENSE("GPL v2"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* STM32 Low-Power Timer parent driver. | ||
* | ||
* Copyright (C) STMicroelectronics 2017 | ||
* | ||
* Author: Fabrice Gasnier <fabrice.gasnier@st.com> | ||
* | ||
* Inspired by Benjamin Gaignard's stm32-timers driver | ||
* | ||
* License terms: GNU General Public License (GPL), version 2 | ||
*/ | ||
|
||
#ifndef _LINUX_STM32_LPTIMER_H_ | ||
#define _LINUX_STM32_LPTIMER_H_ | ||
|
||
#include <linux/clk.h> | ||
#include <linux/regmap.h> | ||
|
||
#define STM32_LPTIM_ISR 0x00 /* Interrupt and Status Reg */ | ||
#define STM32_LPTIM_ICR 0x04 /* Interrupt Clear Reg */ | ||
#define STM32_LPTIM_IER 0x08 /* Interrupt Enable Reg */ | ||
#define STM32_LPTIM_CFGR 0x0C /* Configuration Reg */ | ||
#define STM32_LPTIM_CR 0x10 /* Control Reg */ | ||
#define STM32_LPTIM_CMP 0x14 /* Compare Reg */ | ||
#define STM32_LPTIM_ARR 0x18 /* Autoreload Reg */ | ||
#define STM32_LPTIM_CNT 0x1C /* Counter Reg */ | ||
|
||
/* STM32_LPTIM_ISR - bit fields */ | ||
#define STM32_LPTIM_CMPOK_ARROK GENMASK(4, 3) | ||
#define STM32_LPTIM_ARROK BIT(4) | ||
#define STM32_LPTIM_CMPOK BIT(3) | ||
|
||
/* STM32_LPTIM_ICR - bit fields */ | ||
#define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3) | ||
|
||
/* STM32_LPTIM_CR - bit fields */ | ||
#define STM32_LPTIM_CNTSTRT BIT(2) | ||
#define STM32_LPTIM_ENABLE BIT(0) | ||
|
||
/* STM32_LPTIM_CFGR - bit fields */ | ||
#define STM32_LPTIM_ENC BIT(24) | ||
#define STM32_LPTIM_COUNTMODE BIT(23) | ||
#define STM32_LPTIM_WAVPOL BIT(21) | ||
#define STM32_LPTIM_PRESC GENMASK(11, 9) | ||
#define STM32_LPTIM_CKPOL GENMASK(2, 1) | ||
|
||
/* STM32_LPTIM_ARR */ | ||
#define STM32_LPTIM_MAX_ARR 0xFFFF | ||
|
||
/** | ||
* struct stm32_lptimer - STM32 Low-Power Timer data assigned by parent device | ||
* @clk: clock reference for this instance | ||
* @regmap: register map reference for this instance | ||
* @has_encoder: indicates this Low-Power Timer supports encoder mode | ||
*/ | ||
struct stm32_lptimer { | ||
struct clk *clk; | ||
struct regmap *regmap; | ||
bool has_encoder; | ||
}; | ||
|
||
#endif |