Skip to content

Commit fe120d4

Browse files
Lucas Tanurebroonie
authored andcommitted
ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
ASoC and HDA will do the same cs35l41_otp_unpack, so move it to shared code Signed-off-by: Lucas Tanure <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent a87d422 commit fe120d4

File tree

3 files changed

+122
-128
lines changed

3 files changed

+122
-128
lines changed

include/sound/cs35l41.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,6 @@
534534
#define CS35L41_MAX_CACHE_REG 36
535535
#define CS35L41_OTP_SIZE_WORDS 32
536536
#define CS35L41_NUM_OTP_ELEM 100
537-
#define CS35L41_NUM_OTP_MAPS 5
538537

539538
#define CS35L41_VALID_PDATA 0x80000000
540539
#define CS35L41_NUM_SUPPLIES 2
@@ -760,8 +759,9 @@ struct cs35l41_otp_map_element_t {
760759
u32 word_offset;
761760
};
762761

763-
extern const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
764762
extern struct regmap_config cs35l41_regmap_i2c;
765763
extern struct regmap_config cs35l41_regmap_spi;
766764

765+
int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
766+
767767
#endif /* __CS35L41_H */

sound/soc/codecs/cs35l41-lib.c

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
// Author: David Rhodes <[email protected]>
88
// Author: Lucas Tanure <[email protected]>
99

10+
#include <linux/dev_printk.h>
1011
#include <linux/module.h>
1112
#include <linux/regmap.h>
13+
#include <linux/regulator/consumer.h>
14+
#include <linux/slab.h>
1215

1316
#include <sound/cs35l41.h>
1417

@@ -655,7 +658,7 @@ static const struct cs35l41_otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM]
655658
{ 0x00017044, 0, 24 }, /*LOT_NUMBER*/
656659
};
657660

658-
const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS] = {
661+
static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
659662
{
660663
.id = 0x01,
661664
.map = otp_map_1,
@@ -692,7 +695,6 @@ const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS]
692695
.word_offset = 2,
693696
},
694697
};
695-
EXPORT_SYMBOL_GPL(cs35l41_otp_map_map);
696698

697699
struct regmap_config cs35l41_regmap_i2c = {
698700
.reg_bits = 32,
@@ -727,6 +729,121 @@ struct regmap_config cs35l41_regmap_spi = {
727729
};
728730
EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
729731

732+
static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
733+
{
734+
int i;
735+
736+
for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
737+
if (cs35l41_otp_map_map[i].id == otp_id)
738+
return &cs35l41_otp_map_map[i];
739+
}
740+
741+
return NULL;
742+
}
743+
744+
int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
745+
{
746+
const struct cs35l41_otp_map_element_t *otp_map_match;
747+
const struct cs35l41_otp_packed_element_t *otp_map;
748+
int bit_offset, word_offset, ret, i;
749+
unsigned int bit_sum = 8;
750+
u32 otp_val, otp_id_reg;
751+
u32 *otp_mem;
752+
753+
otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
754+
if (!otp_mem)
755+
return -ENOMEM;
756+
757+
ret = regmap_read(regmap, CS35L41_OTPID, &otp_id_reg);
758+
if (ret) {
759+
dev_err(dev, "Read OTP ID failed: %d\n", ret);
760+
goto err_otp_unpack;
761+
}
762+
763+
otp_map_match = cs35l41_find_otp_map(otp_id_reg);
764+
765+
if (!otp_map_match) {
766+
dev_err(dev, "OTP Map matching ID %d not found\n", otp_id_reg);
767+
ret = -EINVAL;
768+
goto err_otp_unpack;
769+
}
770+
771+
ret = regmap_bulk_read(regmap, CS35L41_OTP_MEM0, otp_mem, CS35L41_OTP_SIZE_WORDS);
772+
if (ret) {
773+
dev_err(dev, "Read OTP Mem failed: %d\n", ret);
774+
goto err_otp_unpack;
775+
}
776+
777+
otp_map = otp_map_match->map;
778+
779+
bit_offset = otp_map_match->bit_offset;
780+
word_offset = otp_map_match->word_offset;
781+
782+
ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
783+
if (ret) {
784+
dev_err(dev, "Write Unlock key failed 1/2: %d\n", ret);
785+
goto err_otp_unpack;
786+
}
787+
ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
788+
if (ret) {
789+
dev_err(dev, "Write Unlock key failed 2/2: %d\n", ret);
790+
goto err_otp_unpack;
791+
}
792+
793+
for (i = 0; i < otp_map_match->num_elements; i++) {
794+
dev_dbg(dev, "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
795+
bit_offset, word_offset, bit_sum % 32);
796+
if (bit_offset + otp_map[i].size - 1 >= 32) {
797+
otp_val = (otp_mem[word_offset] &
798+
GENMASK(31, bit_offset)) >> bit_offset;
799+
otp_val |= (otp_mem[++word_offset] &
800+
GENMASK(bit_offset + otp_map[i].size - 33, 0)) <<
801+
(32 - bit_offset);
802+
bit_offset += otp_map[i].size - 32;
803+
} else {
804+
otp_val = (otp_mem[word_offset] &
805+
GENMASK(bit_offset + otp_map[i].size - 1, bit_offset)
806+
) >> bit_offset;
807+
bit_offset += otp_map[i].size;
808+
}
809+
bit_sum += otp_map[i].size;
810+
811+
if (bit_offset == 32) {
812+
bit_offset = 0;
813+
word_offset++;
814+
}
815+
816+
if (otp_map[i].reg != 0) {
817+
ret = regmap_update_bits(regmap, otp_map[i].reg,
818+
GENMASK(otp_map[i].shift + otp_map[i].size - 1,
819+
otp_map[i].shift),
820+
otp_val << otp_map[i].shift);
821+
if (ret < 0) {
822+
dev_err(dev, "Write OTP val failed: %d\n", ret);
823+
goto err_otp_unpack;
824+
}
825+
}
826+
}
827+
828+
ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
829+
if (ret) {
830+
dev_err(dev, "Write Lock key failed 1/2: %d\n", ret);
831+
goto err_otp_unpack;
832+
}
833+
ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
834+
if (ret) {
835+
dev_err(dev, "Write Lock key failed 2/2: %d\n", ret);
836+
goto err_otp_unpack;
837+
}
838+
ret = 0;
839+
840+
err_otp_unpack:
841+
kfree(otp_mem);
842+
843+
return ret;
844+
}
845+
EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
846+
730847
MODULE_DESCRIPTION("CS35L41 library");
731848
MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <[email protected]>");
732849
MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <[email protected]>");

sound/soc/codecs/cs35l41.c

Lines changed: 1 addition & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/moduleparam.h>
1515
#include <linux/of_device.h>
1616
#include <linux/property.h>
17-
#include <linux/slab.h>
1817
#include <sound/initval.h>
1918
#include <sound/pcm.h>
2019
#include <sound/pcm_params.h>
@@ -420,128 +419,6 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
420419
WM_ADSP_FW_CONTROL("DSP1", 0),
421420
};
422421

423-
static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
424-
{
425-
int i;
426-
427-
for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
428-
if (cs35l41_otp_map_map[i].id == otp_id)
429-
return &cs35l41_otp_map_map[i];
430-
}
431-
432-
return NULL;
433-
}
434-
435-
static int cs35l41_otp_unpack(void *data)
436-
{
437-
const struct cs35l41_otp_map_element_t *otp_map_match;
438-
const struct cs35l41_otp_packed_element_t *otp_map;
439-
struct cs35l41_private *cs35l41 = data;
440-
int bit_offset, word_offset, ret, i;
441-
unsigned int bit_sum = 8;
442-
u32 otp_val, otp_id_reg;
443-
u32 *otp_mem;
444-
445-
otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
446-
if (!otp_mem)
447-
return -ENOMEM;
448-
449-
ret = regmap_read(cs35l41->regmap, CS35L41_OTPID, &otp_id_reg);
450-
if (ret < 0) {
451-
dev_err(cs35l41->dev, "Read OTP ID failed: %d\n", ret);
452-
goto err_otp_unpack;
453-
}
454-
455-
otp_map_match = cs35l41_find_otp_map(otp_id_reg);
456-
457-
if (!otp_map_match) {
458-
dev_err(cs35l41->dev, "OTP Map matching ID %d not found\n",
459-
otp_id_reg);
460-
ret = -EINVAL;
461-
goto err_otp_unpack;
462-
}
463-
464-
ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem,
465-
CS35L41_OTP_SIZE_WORDS);
466-
if (ret < 0) {
467-
dev_err(cs35l41->dev, "Read OTP Mem failed: %d\n", ret);
468-
goto err_otp_unpack;
469-
}
470-
471-
otp_map = otp_map_match->map;
472-
473-
bit_offset = otp_map_match->bit_offset;
474-
word_offset = otp_map_match->word_offset;
475-
476-
ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
477-
if (ret < 0) {
478-
dev_err(cs35l41->dev, "Write Unlock key failed 1/2: %d\n", ret);
479-
goto err_otp_unpack;
480-
}
481-
ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
482-
if (ret < 0) {
483-
dev_err(cs35l41->dev, "Write Unlock key failed 2/2: %d\n", ret);
484-
goto err_otp_unpack;
485-
}
486-
487-
for (i = 0; i < otp_map_match->num_elements; i++) {
488-
dev_dbg(cs35l41->dev,
489-
"bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
490-
bit_offset, word_offset, bit_sum % 32);
491-
if (bit_offset + otp_map[i].size - 1 >= 32) {
492-
otp_val = (otp_mem[word_offset] &
493-
GENMASK(31, bit_offset)) >>
494-
bit_offset;
495-
otp_val |= (otp_mem[++word_offset] &
496-
GENMASK(bit_offset +
497-
otp_map[i].size - 33, 0)) <<
498-
(32 - bit_offset);
499-
bit_offset += otp_map[i].size - 32;
500-
} else {
501-
otp_val = (otp_mem[word_offset] &
502-
GENMASK(bit_offset + otp_map[i].size - 1,
503-
bit_offset)) >> bit_offset;
504-
bit_offset += otp_map[i].size;
505-
}
506-
bit_sum += otp_map[i].size;
507-
508-
if (bit_offset == 32) {
509-
bit_offset = 0;
510-
word_offset++;
511-
}
512-
513-
if (otp_map[i].reg != 0) {
514-
ret = regmap_update_bits(cs35l41->regmap,
515-
otp_map[i].reg,
516-
GENMASK(otp_map[i].shift +
517-
otp_map[i].size - 1,
518-
otp_map[i].shift),
519-
otp_val << otp_map[i].shift);
520-
if (ret < 0) {
521-
dev_err(cs35l41->dev, "Write OTP val failed: %d\n",
522-
ret);
523-
goto err_otp_unpack;
524-
}
525-
}
526-
}
527-
528-
ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
529-
if (ret < 0) {
530-
dev_err(cs35l41->dev, "Write Lock key failed 1/2: %d\n", ret);
531-
goto err_otp_unpack;
532-
}
533-
ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
534-
if (ret < 0) {
535-
dev_err(cs35l41->dev, "Write Lock key failed 2/2: %d\n", ret);
536-
goto err_otp_unpack;
537-
}
538-
ret = 0;
539-
540-
err_otp_unpack:
541-
kfree(otp_mem);
542-
return ret;
543-
}
544-
545422
static irqreturn_t cs35l41_irq(int irq, void *data)
546423
{
547424
struct cs35l41_private *cs35l41 = data;
@@ -1667,7 +1544,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
16671544
goto err;
16681545
}
16691546

1670-
ret = cs35l41_otp_unpack(cs35l41);
1547+
ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
16711548
if (ret < 0) {
16721549
dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
16731550
goto err;

0 commit comments

Comments
 (0)