Skip to content

Commit

Permalink
mfd: da9063: Add support for AD silicon variant
Browse files Browse the repository at this point in the history
Add register definitions for DA9063 AD (0x3) silicon variant ID
the ability to choose the silicon variant at run-time using regmap
configuration. This patch also adds RTC support for the AD silicon
changes.

It adds both BB and AD support as regmap ranges and then makes the
distinction between the two tables at run-time. This allows both AD
and BB silicon variants to be supported at the same time.

Suggested-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
  • Loading branch information
Opensource [Steve Twiss] authored and Lee Jones committed Jul 28, 2014
1 parent 5fc6c39 commit 9cb42e2
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 90 deletions.
6 changes: 3 additions & 3 deletions drivers/mfd/da9063-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
"Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
model, variant_id);

if (variant_code != PMIC_DA9063_BB) {
dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
variant_code);
if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
dev_err(da9063->dev,
"Cannot support variant code: 0x%02X\n", variant_code);
return -ENODEV;
}

Expand Down
134 changes: 109 additions & 25 deletions drivers/mfd/da9063-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>

static const struct regmap_range da9063_readable_ranges[] = {
static const struct regmap_range da9063_ad_readable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_SECOND_D,
.range_max = DA9063_AD_REG_SECOND_D,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
Expand All @@ -37,14 +37,14 @@ static const struct regmap_range da9063_readable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_T_OFFSET,
.range_max = DA9063_REG_GP_ID_19,
.range_max = DA9063_AD_REG_GP_ID_19,
}, {
.range_min = DA9063_REG_CHIP_ID,
.range_max = DA9063_REG_CHIP_VARIANT,
},
};

static const struct regmap_range da9063_writeable_ranges[] = {
static const struct regmap_range da9063_ad_writeable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_PAGE_CON,
Expand All @@ -53,7 +53,7 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_VSYS_MON,
}, {
.range_min = DA9063_REG_COUNT_S,
.range_max = DA9063_REG_ALARM_Y,
.range_max = DA9063_AD_REG_ALARM_Y,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
Expand All @@ -62,14 +62,14 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_CONFIG_I,
.range_max = DA9063_REG_MON_REG_4,
.range_max = DA9063_AD_REG_MON_REG_4,
}, {
.range_min = DA9063_REG_GP_ID_0,
.range_max = DA9063_REG_GP_ID_19,
.range_min = DA9063_AD_REG_GP_ID_0,
.range_max = DA9063_AD_REG_GP_ID_19,
},
};

static const struct regmap_range da9063_volatile_ranges[] = {
static const struct regmap_range da9063_ad_volatile_ranges[] = {
{
.range_min = DA9063_REG_STATUS_A,
.range_max = DA9063_REG_EVENT_D,
Expand All @@ -81,26 +81,104 @@ static const struct regmap_range da9063_volatile_ranges[] = {
.range_max = DA9063_REG_ADC_MAN,
}, {
.range_min = DA9063_REG_ADC_RES_L,
.range_max = DA9063_REG_SECOND_D,
.range_max = DA9063_AD_REG_SECOND_D,
}, {
.range_min = DA9063_REG_MON_REG_5,
.range_max = DA9063_REG_MON_REG_6,
.range_min = DA9063_AD_REG_MON_REG_5,
.range_max = DA9063_AD_REG_MON_REG_6,
},
};

static const struct regmap_access_table da9063_readable_table = {
.yes_ranges = da9063_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
static const struct regmap_access_table da9063_ad_readable_table = {
.yes_ranges = da9063_ad_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
};

static const struct regmap_access_table da9063_writeable_table = {
.yes_ranges = da9063_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
static const struct regmap_access_table da9063_ad_writeable_table = {
.yes_ranges = da9063_ad_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
};

static const struct regmap_access_table da9063_volatile_table = {
.yes_ranges = da9063_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
static const struct regmap_access_table da9063_ad_volatile_table = {
.yes_ranges = da9063_ad_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
};

static const struct regmap_range da9063_bb_readable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_BB_REG_SECOND_D,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
}, {
.range_min = DA9063_REG_SEQ_A,
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_T_OFFSET,
.range_max = DA9063_BB_REG_GP_ID_19,
}, {
.range_min = DA9063_REG_CHIP_ID,
.range_max = DA9063_REG_CHIP_VARIANT,
},
};

static const struct regmap_range da9063_bb_writeable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_PAGE_CON,
}, {
.range_min = DA9063_REG_FAULT_LOG,
.range_max = DA9063_REG_VSYS_MON,
}, {
.range_min = DA9063_REG_COUNT_S,
.range_max = DA9063_BB_REG_ALARM_Y,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
}, {
.range_min = DA9063_REG_SEQ_A,
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_CONFIG_I,
.range_max = DA9063_BB_REG_MON_REG_4,
}, {
.range_min = DA9063_BB_REG_GP_ID_0,
.range_max = DA9063_BB_REG_GP_ID_19,
},
};

static const struct regmap_range da9063_bb_volatile_ranges[] = {
{
.range_min = DA9063_REG_STATUS_A,
.range_max = DA9063_REG_EVENT_D,
}, {
.range_min = DA9063_REG_CONTROL_F,
.range_max = DA9063_REG_CONTROL_F,
}, {
.range_min = DA9063_REG_ADC_MAN,
.range_max = DA9063_REG_ADC_MAN,
}, {
.range_min = DA9063_REG_ADC_RES_L,
.range_max = DA9063_BB_REG_SECOND_D,
}, {
.range_min = DA9063_BB_REG_MON_REG_5,
.range_max = DA9063_BB_REG_MON_REG_6,
},
};

static const struct regmap_access_table da9063_bb_readable_table = {
.yes_ranges = da9063_bb_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
};

static const struct regmap_access_table da9063_bb_writeable_table = {
.yes_ranges = da9063_bb_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
};

static const struct regmap_access_table da9063_bb_volatile_table = {
.yes_ranges = da9063_bb_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
};

static const struct regmap_range_cfg da9063_range_cfg[] = {
Expand All @@ -123,10 +201,6 @@ static struct regmap_config da9063_regmap_config = {
.max_register = DA9063_REG_CHIP_VARIANT,

.cache_type = REGCACHE_RBTREE,

.rd_table = &da9063_readable_table,
.wr_table = &da9063_writeable_table,
.volatile_table = &da9063_volatile_table,
};

static int da9063_i2c_probe(struct i2c_client *i2c,
Expand All @@ -143,6 +217,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
da9063->dev = &i2c->dev;
da9063->chip_irq = i2c->irq;

if (da9063->variant_code == PMIC_DA9063_AD) {
da9063_regmap_config.rd_table = &da9063_ad_readable_table;
da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
} else {
da9063_regmap_config.rd_table = &da9063_bb_readable_table;
da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
}

da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
if (IS_ERR(da9063->regmap)) {
ret = PTR_ERR(da9063->regmap);
Expand Down
54 changes: 37 additions & 17 deletions drivers/rtc/rtc-da9063.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#define YEARS_FROM_DA9063(year) ((year) + 100)
#define MONTHS_FROM_DA9063(month) ((month) - 1)

#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1)

#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
#define RTC_SEC 0
#define RTC_MIN 1
Expand All @@ -42,6 +44,10 @@ struct da9063_rtc {
struct da9063 *hw;
struct rtc_time alarm_time;
bool rtc_sync;
int alarm_year;
int alarm_start;
int alarm_len;
int data_start;
};

static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
Expand Down Expand Up @@ -83,15 +89,15 @@ static int da9063_rtc_stop_alarm(struct device *dev)
{
struct da9063_rtc *rtc = dev_get_drvdata(dev);

return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, 0);
}

static int da9063_rtc_start_alarm(struct device *dev)
{
struct da9063_rtc *rtc = dev_get_drvdata(dev);

return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, DA9063_ALARM_ON);
}

Expand Down Expand Up @@ -151,8 +157,9 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
int ret;
unsigned int val;

ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S,
&data[RTC_SEC], RTC_DATA_LEN);
data[RTC_SEC] = 0;
ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start,
&data[rtc->data_start], rtc->alarm_len);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -186,14 +193,14 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}

ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S,
data, RTC_DATA_LEN);
ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start,
&data[rtc->data_start], rtc->alarm_len);
if (ret < 0) {
dev_err(dev, "Failed to write alarm: %d\n", ret);
return ret;
}

rtc->alarm_time = alrm->time;
da9063_data_to_tm(data, &rtc->alarm_time);

if (alrm->enabled) {
ret = da9063_rtc_start_alarm(dev);
Expand All @@ -218,7 +225,7 @@ static irqreturn_t da9063_alarm_event(int irq, void *data)
{
struct da9063_rtc *rtc = data;

regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, 0);

rtc->rtc_sync = true;
Expand Down Expand Up @@ -257,41 +264,54 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}

ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;

if (da9063->variant_code == PMIC_DA9063_AD) {
rtc->alarm_year = DA9063_AD_REG_ALARM_Y;
rtc->alarm_start = DA9063_AD_REG_ALARM_MI;
rtc->alarm_len = RTC_ALARM_DATA_LEN;
rtc->data_start = RTC_MIN;
} else {
rtc->alarm_year = DA9063_BB_REG_ALARM_Y;
rtc->alarm_start = DA9063_BB_REG_ALARM_S;
rtc->alarm_len = RTC_DATA_LEN;
rtc->data_start = RTC_SEC;
}

ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
goto err;
}

ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_ALARM,
DA9063_ALARM_STATUS_ALARM);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
goto err;
}

ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y,
ret = regmap_update_bits(da9063->regmap, rtc->alarm_year,
DA9063_TICK_ON, 0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n");
goto err;
}

ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S,
data, RTC_DATA_LEN);
data[RTC_SEC] = 0;
ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start,
&data[rtc->data_start], rtc->alarm_len);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret);
goto err;
}

rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;

platform_set_drvdata(pdev, rtc);

irq_alarm = platform_get_irq_byname(pdev, "ALARM");
Expand Down
3 changes: 2 additions & 1 deletion include/linux/mfd/da9063/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ enum da9063_models {
};

enum da9063_variant_codes {
PMIC_DA9063_BB = 0x5
PMIC_DA9063_AD = 0x3,
PMIC_DA9063_BB = 0x5,
};

/* Interrupts */
Expand Down
Loading

0 comments on commit 9cb42e2

Please sign in to comment.