Commit 71ed4bdd authored by Olivier Moysan's avatar Olivier Moysan Committed by Mark Brown

ASoC: stm32: i2s: manage identification registers

Add support of identification registers in STM32 I2S.
Signed-off-by: default avatarOlivier Moysan <olivier.moysan@st.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 0cf4610b
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* details. * details.
*/ */
#include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -37,6 +38,10 @@ ...@@ -37,6 +38,10 @@
#define STM32_I2S_TXDR_REG 0X20 #define STM32_I2S_TXDR_REG 0X20
#define STM32_I2S_RXDR_REG 0x30 #define STM32_I2S_RXDR_REG 0x30
#define STM32_I2S_CGFR_REG 0X50 #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 */ /* Bit definition for SPI2S_CR1 register */
#define I2S_CR1_SPE BIT(0) #define I2S_CR1_SPE BIT(0)
...@@ -143,6 +148,23 @@ ...@@ -143,6 +148,23 @@
#define I2S_CGFR_ODD BIT(I2S_CGFR_ODD_SHIFT) #define I2S_CGFR_ODD BIT(I2S_CGFR_ODD_SHIFT)
#define I2S_CGFR_MCKOE BIT(25) #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 { enum i2s_master_mode {
I2S_MS_NOT_SET, I2S_MS_NOT_SET,
I2S_MS_MASTER, I2S_MS_MASTER,
...@@ -280,6 +302,10 @@ static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg) ...@@ -280,6 +302,10 @@ static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg)
case STM32_I2S_SR_REG: case STM32_I2S_SR_REG:
case STM32_I2S_RXDR_REG: case STM32_I2S_RXDR_REG:
case STM32_I2S_CGFR_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; return true;
default: default:
return false; return false;
...@@ -711,10 +737,11 @@ static const struct regmap_config stm32_h7_i2s_regmap_conf = { ...@@ -711,10 +737,11 @@ static const struct regmap_config stm32_h7_i2s_regmap_conf = {
.reg_bits = 32, .reg_bits = 32,
.reg_stride = 4, .reg_stride = 4,
.val_bits = 32, .val_bits = 32,
.max_register = STM32_I2S_CGFR_REG, .max_register = STM32_I2S_SIDR_REG,
.readable_reg = stm32_i2s_readable_reg, .readable_reg = stm32_i2s_readable_reg,
.volatile_reg = stm32_i2s_volatile_reg, .volatile_reg = stm32_i2s_volatile_reg,
.writeable_reg = stm32_i2s_writeable_reg, .writeable_reg = stm32_i2s_writeable_reg,
.num_reg_defaults_raw = STM32_I2S_SIDR_REG / sizeof(u32) + 1,
.fast_io = true, .fast_io = true,
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
...@@ -864,6 +891,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, ...@@ -864,6 +891,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
static int stm32_i2s_probe(struct platform_device *pdev) static int stm32_i2s_probe(struct platform_device *pdev)
{ {
struct stm32_i2s_data *i2s; struct stm32_i2s_data *i2s;
u32 val;
int ret; int ret;
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
...@@ -902,8 +930,34 @@ static int stm32_i2s_probe(struct platform_device *pdev) ...@@ -902,8 +930,34 @@ static int stm32_i2s_probe(struct platform_device *pdev)
return ret; return ret;
/* Set SPI/I2S in i2s mode */ /* Set SPI/I2S in i2s mode */
return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD); 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); MODULE_DEVICE_TABLE(of, stm32_i2s_ids);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment