ASoC: stm32: i2s: manage identification registers

Add support of identification registers in STM32 I2S.

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Olivier Moysan 2019-05-06 14:54:12 +02:00 коммит произвёл Mark Brown
Родитель 0cf4610b9f
Коммит 71ed4bddde
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 24D68B725D5487D0
1 изменённых файлов: 57 добавлений и 3 удалений

Просмотреть файл

@ -16,6 +16,7 @@
* details.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/module.h>
@ -37,6 +38,10 @@
#define STM32_I2S_TXDR_REG 0X20
#define STM32_I2S_RXDR_REG 0x30
#define STM32_I2S_CGFR_REG 0X50
#define STM32_I2S_HWCFGR_REG 0x3F0
#define STM32_I2S_VERR_REG 0x3F4
#define STM32_I2S_IPIDR_REG 0x3F8
#define STM32_I2S_SIDR_REG 0x3FC
/* Bit definition for SPI2S_CR1 register */
#define I2S_CR1_SPE BIT(0)
@ -143,6 +148,23 @@
#define I2S_CGFR_ODD BIT(I2S_CGFR_ODD_SHIFT)
#define I2S_CGFR_MCKOE BIT(25)
/* Registers below apply to I2S version 1.1 and more */
/* Bit definition for SPI_HWCFGR register */
#define I2S_HWCFGR_I2S_SUPPORT_MASK GENMASK(15, 12)
/* Bit definition for SPI_VERR register */
#define I2S_VERR_MIN_MASK GENMASK(3, 0)
#define I2S_VERR_MAJ_MASK GENMASK(7, 4)
/* Bit definition for SPI_IPIDR register */
#define I2S_IPIDR_ID_MASK GENMASK(31, 0)
/* Bit definition for SPI_SIDR register */
#define I2S_SIDR_ID_MASK GENMASK(31, 0)
#define I2S_IPIDR_NUMBER 0x00130022
enum i2s_master_mode {
I2S_MS_NOT_SET,
I2S_MS_MASTER,
@ -280,6 +302,10 @@ static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg)
case STM32_I2S_SR_REG:
case STM32_I2S_RXDR_REG:
case STM32_I2S_CGFR_REG:
case STM32_I2S_HWCFGR_REG:
case STM32_I2S_VERR_REG:
case STM32_I2S_IPIDR_REG:
case STM32_I2S_SIDR_REG:
return true;
default:
return false;
@ -711,10 +737,11 @@ static const struct regmap_config stm32_h7_i2s_regmap_conf = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = STM32_I2S_CGFR_REG,
.max_register = STM32_I2S_SIDR_REG,
.readable_reg = stm32_i2s_readable_reg,
.volatile_reg = stm32_i2s_volatile_reg,
.writeable_reg = stm32_i2s_writeable_reg,
.num_reg_defaults_raw = STM32_I2S_SIDR_REG / sizeof(u32) + 1,
.fast_io = true,
.cache_type = REGCACHE_FLAT,
};
@ -864,6 +891,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
static int stm32_i2s_probe(struct platform_device *pdev)
{
struct stm32_i2s_data *i2s;
u32 val;
int ret;
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
@ -902,8 +930,34 @@ static int stm32_i2s_probe(struct platform_device *pdev)
return ret;
/* Set SPI/I2S in i2s mode */
return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD);
ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD);
if (ret)
return ret;
ret = regmap_read(i2s->regmap, STM32_I2S_IPIDR_REG, &val);
if (ret)
return ret;
if (val == I2S_IPIDR_NUMBER) {
ret = regmap_read(i2s->regmap, STM32_I2S_HWCFGR_REG, &val);
if (ret)
return ret;
if (!FIELD_GET(I2S_HWCFGR_I2S_SUPPORT_MASK, val)) {
dev_err(&pdev->dev,
"Device does not support i2s mode\n");
return -EPERM;
}
ret = regmap_read(i2s->regmap, STM32_I2S_VERR_REG, &val);
dev_dbg(&pdev->dev, "I2S version: %lu.%lu registered\n",
FIELD_GET(I2S_VERR_MAJ_MASK, val),
FIELD_GET(I2S_VERR_MIN_MASK, val));
}
return ret;
}
MODULE_DEVICE_TABLE(of, stm32_i2s_ids);