diff options
Diffstat (limited to 'drivers/rtc/rtc-bd70528.c')
| -rw-r--r-- | drivers/rtc/rtc-bd70528.c | 104 | 
1 files changed, 64 insertions, 40 deletions
| diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index 17cb67f5bf6e..6454afca02a6 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -6,6 +6,7 @@  #include <linux/bcd.h>  #include <linux/mfd/rohm-bd70528.h> +#include <linux/mfd/rohm-bd71815.h>  #include <linux/mfd/rohm-bd71828.h>  #include <linux/module.h>  #include <linux/of.h> @@ -14,6 +15,12 @@  #include <linux/rtc.h>  /* + * On BD71828 and BD71815 the ALM0 MASK is 14 bytes after the ALM0 + * block start + */ +#define BD718XX_ALM_EN_OFFSET 14 + +/*   * We read regs RTC_SEC => RTC_YEAR   * this struct is ordered according to chip registers.   * Keep it u8 only (or packed) to avoid padding issues. @@ -52,8 +59,10 @@ struct bd70528_rtc_alm {  struct bd70528_rtc {  	struct rohm_regmap_dev *parent; +	struct regmap *regmap;  	struct device *dev;  	u8 reg_time_start; +	u8 bd718xx_alm_block_start;  	bool has_rtc_timers;  }; @@ -234,10 +243,9 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)  	int ret;  	struct bd71828_rtc_alm alm;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -250,8 +258,8 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)  	else  		alm.alm_mask |= BD70528_MASK_ALM_EN; -	ret = regmap_bulk_write(parent->regmap, BD71828_REG_RTC_ALM_START, -				&alm, sizeof(alm)); +	ret = regmap_bulk_write(r->regmap, r->bd718xx_alm_block_start, &alm, +				sizeof(alm));  	if (ret)  		dev_err(dev, "Failed to set alarm time\n"); @@ -265,17 +273,16 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)  	struct bd70528_rtc_alm alm;  	int ret;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START, -			       &wake, sizeof(wake)); +	ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_WAKE_START, &wake, +			       sizeof(wake));  	if (ret) {  		dev_err(dev, "Failed to read wake regs\n");  		return ret;  	} -	ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -292,15 +299,14 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)  		wake.ctrl &= ~BD70528_MASK_WAKE_EN;  	} -	ret = regmap_bulk_write(parent->regmap, -				BD70528_REG_RTC_WAKE_START, &wake, +	ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_WAKE_START, &wake,  				sizeof(wake));  	if (ret) {  		dev_err(dev, "Failed to set wake time\n");  		return ret;  	} -	ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START, -				&alm, sizeof(alm)); +	ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_ALM_START, &alm, +				sizeof(alm));  	if (ret)  		dev_err(dev, "Failed to set alarm time\n"); @@ -312,10 +318,9 @@ static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)  	int ret;  	struct bd71828_rtc_alm alm;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -336,10 +341,9 @@ static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)  	struct bd70528_rtc_alm alm;  	int ret;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent; -	ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, -			       &alm, sizeof(alm)); +	ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm, +			       sizeof(alm));  	if (ret) {  		dev_err(dev, "Failed to read alarm regs\n");  		return ret; @@ -360,14 +364,12 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)  	int ret, tmpret, old_states;  	struct bd70528_rtc_data rtc_data;  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent;  	ret = bd70528_disable_rtc_based_timers(r, &old_states);  	if (ret)  		return ret; -	tmpret = regmap_bulk_read(parent->regmap, -				  r->reg_time_start, &rtc_data, +	tmpret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,  				  sizeof(rtc_data));  	if (tmpret) {  		dev_err(dev, "Failed to read RTC time registers\n"); @@ -375,8 +377,7 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)  	}  	tm2rtc(t, &rtc_data); -	tmpret = regmap_bulk_write(parent->regmap, -				   r->reg_time_start, &rtc_data, +	tmpret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data,  				   sizeof(rtc_data));  	if (tmpret) {  		dev_err(dev, "Failed to set RTC time\n"); @@ -410,13 +411,11 @@ static int bd70528_set_time(struct device *dev, struct rtc_time *t)  static int bd70528_get_time(struct device *dev, struct rtc_time *t)  {  	struct bd70528_rtc *r = dev_get_drvdata(dev); -	struct rohm_regmap_dev *parent = r->parent;  	struct bd70528_rtc_data rtc_data;  	int ret;  	/* read the RTC date and time registers all at once */ -	ret = regmap_bulk_read(parent->regmap, -			       r->reg_time_start, &rtc_data, +	ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,  			       sizeof(rtc_data));  	if (ret) {  		dev_err(dev, "Failed to read RTC time (err %d)\n", ret); @@ -443,7 +442,7 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled)  		dev_err(dev, "Failed to change wake state\n");  		goto out_unlock;  	} -	ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK, +	ret = regmap_update_bits(r->regmap, BD70528_REG_RTC_ALM_MASK,  				 BD70528_MASK_ALM_EN, enableval);  	if (ret)  		dev_err(dev, "Failed to change alarm state\n"); @@ -462,8 +461,9 @@ static int bd71828_alm_enable(struct device *dev, unsigned int enabled)  	if (!enabled)  		enableval = 0; -	ret = regmap_update_bits(r->parent->regmap, BD71828_REG_RTC_ALM0_MASK, -				 BD70528_MASK_ALM_EN, enableval); +	ret = regmap_update_bits(r->regmap, r->bd718xx_alm_block_start + +				 BD718XX_ALM_EN_OFFSET, BD70528_MASK_ALM_EN, +				 enableval);  	if (ret)  		dev_err(dev, "Failed to change alarm state\n"); @@ -498,7 +498,6 @@ static int bd70528_probe(struct platform_device *pdev)  {  	struct bd70528_rtc *bd_rtc;  	const struct rtc_class_ops *rtc_ops; -	struct rohm_regmap_dev *parent;  	const char *irq_name;  	int ret;  	struct rtc_device *rtc; @@ -508,20 +507,25 @@ static int bd70528_probe(struct platform_device *pdev)  	u8 hour_reg;  	enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; -	parent = dev_get_drvdata(pdev->dev.parent); -	if (!parent) { -		dev_err(&pdev->dev, "No MFD driver data\n"); -		return -EINVAL; -	}  	bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);  	if (!bd_rtc)  		return -ENOMEM; -	bd_rtc->parent = parent; +	bd_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL); +	if (!bd_rtc->regmap) { +		dev_err(&pdev->dev, "No regmap\n"); +		return -EINVAL; +	} +  	bd_rtc->dev = &pdev->dev;  	switch (chip) {  	case ROHM_CHIP_TYPE_BD70528: +		bd_rtc->parent = dev_get_drvdata(pdev->dev.parent); +		if (!bd_rtc->parent) { +			dev_err(&pdev->dev, "No MFD data\n"); +			return -EINVAL; +		}  		irq_name = "bd70528-rtc-alm";  		bd_rtc->has_rtc_timers = true;  		bd_rtc->reg_time_start = BD70528_REG_RTC_START; @@ -529,9 +533,28 @@ static int bd70528_probe(struct platform_device *pdev)  		enable_main_irq = true;  		rtc_ops = &bd70528_rtc_ops;  		break; +	case ROHM_CHIP_TYPE_BD71815: +		irq_name = "bd71815-rtc-alm-0"; +		bd_rtc->reg_time_start = BD71815_REG_RTC_START; + +		/* +		 * See also BD718XX_ALM_EN_OFFSET: +		 * This works for BD71828 and BD71815 as they have same offset +		 * between ALM0 start and ALM0_MASK. If new ICs are to be +		 * added this requires proper check as ALM0_MASK is not located +		 * at the end of ALM0 block - but after all ALM blocks so if +		 * amount of ALMs differ the offset to enable/disable is likely +		 * to be incorrect and enable/disable must be given as own +		 * reg address here. +		 */ +		bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START; +		hour_reg = BD71815_REG_HOUR; +		rtc_ops = &bd71828_rtc_ops; +		break;  	case ROHM_CHIP_TYPE_BD71828:  		irq_name = "bd71828-rtc-alm-0";  		bd_rtc->reg_time_start = BD71828_REG_RTC_START; +		bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;  		hour_reg = BD71828_REG_RTC_HOUR;  		rtc_ops = &bd71828_rtc_ops;  		break; @@ -547,7 +570,7 @@ static int bd70528_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, bd_rtc); -	ret = regmap_read(parent->regmap, hour_reg, &hr); +	ret = regmap_read(bd_rtc->regmap, hour_reg, &hr);  	if (ret) {  		dev_err(&pdev->dev, "Failed to reag RTC clock\n"); @@ -595,7 +618,7 @@ static int bd70528_probe(struct platform_device *pdev)  	 *  from sub-registers when IRQ is disabled or freed.  	 */  	if (enable_main_irq) { -		ret = regmap_update_bits(parent->regmap, +		ret = regmap_update_bits(bd_rtc->regmap,  				 BD70528_REG_INT_MAIN_MASK,  				 BD70528_INT_RTC_MASK, 0);  		if (ret) { @@ -610,6 +633,7 @@ static int bd70528_probe(struct platform_device *pdev)  static const struct platform_device_id bd718x7_rtc_id[] = {  	{ "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },  	{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 }, +	{ "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },  	{ },  };  MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id); | 
