Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'ib-mfd-iio-input-5.7' and 'ib-mfd-iio-rtc-5.7' into ibs-for-mfd-merged

+851 -11
+4
Documentation/devicetree/bindings/mfd/rn5t618.txt
··· 15 15 - reg: the I2C slave address of the device 16 16 17 17 Optional properties: 18 + - interrupts: interrupt mapping for IRQ 19 + See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt 18 20 - system-power-controller: 19 21 See Documentation/devicetree/bindings/power/power-controller.txt 20 22 ··· 34 32 pmic@32 { 35 33 compatible = "ricoh,rn5t618"; 36 34 reg = <0x32>; 35 + interrupt-parent = <&gpio5>; 36 + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; 37 37 system-power-controller; 38 38 39 39 regulators {
+10
drivers/iio/adc/Kconfig
··· 783 783 To compile this driver as a module, choose M here: the 784 784 module will be called rcar-gyroadc. 785 785 786 + config RN5T618_ADC 787 + tristate "ADC for the RN5T618/RC5T619 family of chips" 788 + depends on MFD_RN5T618 789 + help 790 + Say yes here to build support for the integrated ADC inside the 791 + RN5T618/619 series PMICs: 792 + 793 + This driver can also be built as a module. If so, the module 794 + will be called rn5t618-adc. 795 + 786 796 config ROCKCHIP_SARADC 787 797 tristate "Rockchip SARADC driver" 788 798 depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
+1
drivers/iio/adc/Makefile
··· 74 74 obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o 75 75 obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o 76 76 obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o 77 + obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o 77 78 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o 78 79 obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o 79 80 obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
+256
drivers/iio/adc/rn5t618-adc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * ADC driver for the RICOH RN5T618 power management chip family 4 + * 5 + * Copyright (C) 2019 Andreas Kemnade 6 + */ 7 + 8 + #include <linux/kernel.h> 9 + #include <linux/device.h> 10 + #include <linux/errno.h> 11 + #include <linux/interrupt.h> 12 + #include <linux/init.h> 13 + #include <linux/module.h> 14 + #include <linux/mfd/rn5t618.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/completion.h> 17 + #include <linux/regmap.h> 18 + #include <linux/iio/iio.h> 19 + #include <linux/slab.h> 20 + 21 + #define RN5T618_ADC_CONVERSION_TIMEOUT (msecs_to_jiffies(500)) 22 + #define RN5T618_REFERENCE_VOLT 2500 23 + 24 + /* mask for selecting channels for single conversion */ 25 + #define RN5T618_ADCCNT3_CHANNEL_MASK 0x7 26 + /* average 4-time conversion mode */ 27 + #define RN5T618_ADCCNT3_AVG BIT(3) 28 + /* set for starting a single conversion, gets cleared by hw when done */ 29 + #define RN5T618_ADCCNT3_GODONE BIT(4) 30 + /* automatic conversion, period is in ADCCNT2, selected channels are 31 + * in ADCCNT1 32 + */ 33 + #define RN5T618_ADCCNT3_AUTO BIT(5) 34 + #define RN5T618_ADCEND_IRQ BIT(0) 35 + 36 + struct rn5t618_adc_data { 37 + struct device *dev; 38 + struct rn5t618 *rn5t618; 39 + struct completion conv_completion; 40 + int irq; 41 + }; 42 + 43 + struct rn5t618_channel_ratios { 44 + u16 numerator; 45 + u16 denominator; 46 + }; 47 + 48 + enum rn5t618_channels { 49 + LIMMON = 0, 50 + VBAT, 51 + VADP, 52 + VUSB, 53 + VSYS, 54 + VTHM, 55 + AIN1, 56 + AIN0 57 + }; 58 + 59 + static const struct rn5t618_channel_ratios rn5t618_ratios[8] = { 60 + [LIMMON] = {50, 32}, /* measured across 20mOhm, amplified by 32 */ 61 + [VBAT] = {2, 1}, 62 + [VADP] = {3, 1}, 63 + [VUSB] = {3, 1}, 64 + [VSYS] = {3, 1}, 65 + [VTHM] = {1, 1}, 66 + [AIN1] = {1, 1}, 67 + [AIN0] = {1, 1}, 68 + }; 69 + 70 + static int rn5t618_read_adc_reg(struct rn5t618 *rn5t618, int reg, u16 *val) 71 + { 72 + u8 data[2]; 73 + int ret; 74 + 75 + ret = regmap_bulk_read(rn5t618->regmap, reg, data, sizeof(data)); 76 + if (ret < 0) 77 + return ret; 78 + 79 + *val = (data[0] << 4) | (data[1] & 0xF); 80 + 81 + return 0; 82 + } 83 + 84 + static irqreturn_t rn5t618_adc_irq(int irq, void *data) 85 + { 86 + struct rn5t618_adc_data *adc = data; 87 + unsigned int r = 0; 88 + int ret; 89 + 90 + /* clear low & high threshold irqs */ 91 + regmap_write(adc->rn5t618->regmap, RN5T618_IR_ADC1, 0); 92 + regmap_write(adc->rn5t618->regmap, RN5T618_IR_ADC2, 0); 93 + 94 + ret = regmap_read(adc->rn5t618->regmap, RN5T618_IR_ADC3, &r); 95 + if (ret < 0) 96 + dev_err(adc->dev, "failed to read IRQ status: %d\n", ret); 97 + 98 + regmap_write(adc->rn5t618->regmap, RN5T618_IR_ADC3, 0); 99 + 100 + if (r & RN5T618_ADCEND_IRQ) 101 + complete(&adc->conv_completion); 102 + 103 + return IRQ_HANDLED; 104 + } 105 + 106 + static int rn5t618_adc_read(struct iio_dev *iio_dev, 107 + const struct iio_chan_spec *chan, 108 + int *val, int *val2, long mask) 109 + { 110 + struct rn5t618_adc_data *adc = iio_priv(iio_dev); 111 + u16 raw; 112 + int ret; 113 + 114 + if (mask == IIO_CHAN_INFO_SCALE) { 115 + *val = RN5T618_REFERENCE_VOLT * 116 + rn5t618_ratios[chan->channel].numerator; 117 + *val2 = rn5t618_ratios[chan->channel].denominator * 4095; 118 + 119 + return IIO_VAL_FRACTIONAL; 120 + } 121 + 122 + /* select channel */ 123 + ret = regmap_update_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, 124 + RN5T618_ADCCNT3_CHANNEL_MASK, 125 + chan->channel); 126 + if (ret < 0) 127 + return ret; 128 + 129 + ret = regmap_write(adc->rn5t618->regmap, RN5T618_EN_ADCIR3, 130 + RN5T618_ADCEND_IRQ); 131 + if (ret < 0) 132 + return ret; 133 + 134 + ret = regmap_update_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, 135 + RN5T618_ADCCNT3_AVG, 136 + mask == IIO_CHAN_INFO_AVERAGE_RAW ? 137 + RN5T618_ADCCNT3_AVG : 0); 138 + if (ret < 0) 139 + return ret; 140 + 141 + init_completion(&adc->conv_completion); 142 + /* single conversion */ 143 + ret = regmap_update_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, 144 + RN5T618_ADCCNT3_GODONE, 145 + RN5T618_ADCCNT3_GODONE); 146 + if (ret < 0) 147 + return ret; 148 + 149 + ret = wait_for_completion_timeout(&adc->conv_completion, 150 + RN5T618_ADC_CONVERSION_TIMEOUT); 151 + if (ret == 0) { 152 + dev_warn(adc->dev, "timeout waiting for adc result\n"); 153 + return -ETIMEDOUT; 154 + } 155 + 156 + ret = rn5t618_read_adc_reg(adc->rn5t618, 157 + RN5T618_ILIMDATAH + 2 * chan->channel, 158 + &raw); 159 + if (ret < 0) 160 + return ret; 161 + 162 + *val = raw; 163 + 164 + return IIO_VAL_INT; 165 + } 166 + 167 + static const struct iio_info rn5t618_adc_iio_info = { 168 + .read_raw = &rn5t618_adc_read, 169 + }; 170 + 171 + #define RN5T618_ADC_CHANNEL(_channel, _type, _name) { \ 172 + .type = _type, \ 173 + .channel = _channel, \ 174 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 175 + BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \ 176 + BIT(IIO_CHAN_INFO_SCALE), \ 177 + .datasheet_name = _name, \ 178 + .indexed = 1. \ 179 + } 180 + 181 + static const struct iio_chan_spec rn5t618_adc_iio_channels[] = { 182 + RN5T618_ADC_CHANNEL(LIMMON, IIO_CURRENT, "LIMMON"), 183 + RN5T618_ADC_CHANNEL(VBAT, IIO_VOLTAGE, "VBAT"), 184 + RN5T618_ADC_CHANNEL(VADP, IIO_VOLTAGE, "VADP"), 185 + RN5T618_ADC_CHANNEL(VUSB, IIO_VOLTAGE, "VUSB"), 186 + RN5T618_ADC_CHANNEL(VSYS, IIO_VOLTAGE, "VSYS"), 187 + RN5T618_ADC_CHANNEL(VTHM, IIO_VOLTAGE, "VTHM"), 188 + RN5T618_ADC_CHANNEL(AIN1, IIO_VOLTAGE, "AIN1"), 189 + RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0") 190 + }; 191 + 192 + static int rn5t618_adc_probe(struct platform_device *pdev) 193 + { 194 + int ret; 195 + struct iio_dev *iio_dev; 196 + struct rn5t618_adc_data *adc; 197 + struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent); 198 + 199 + iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); 200 + if (!iio_dev) { 201 + dev_err(&pdev->dev, "failed allocating iio device\n"); 202 + return -ENOMEM; 203 + } 204 + 205 + adc = iio_priv(iio_dev); 206 + adc->dev = &pdev->dev; 207 + adc->rn5t618 = rn5t618; 208 + 209 + if (rn5t618->irq_data) 210 + adc->irq = regmap_irq_get_virq(rn5t618->irq_data, 211 + RN5T618_IRQ_ADC); 212 + 213 + if (adc->irq <= 0) { 214 + dev_err(&pdev->dev, "get virq failed\n"); 215 + return -EINVAL; 216 + } 217 + 218 + init_completion(&adc->conv_completion); 219 + 220 + iio_dev->name = dev_name(&pdev->dev); 221 + iio_dev->dev.parent = &pdev->dev; 222 + iio_dev->info = &rn5t618_adc_iio_info; 223 + iio_dev->modes = INDIO_DIRECT_MODE; 224 + iio_dev->channels = rn5t618_adc_iio_channels; 225 + iio_dev->num_channels = ARRAY_SIZE(rn5t618_adc_iio_channels); 226 + 227 + /* stop any auto-conversion */ 228 + ret = regmap_write(rn5t618->regmap, RN5T618_ADCCNT3, 0); 229 + if (ret < 0) 230 + return ret; 231 + 232 + platform_set_drvdata(pdev, iio_dev); 233 + 234 + ret = devm_request_threaded_irq(adc->dev, adc->irq, NULL, 235 + rn5t618_adc_irq, 236 + IRQF_ONESHOT, dev_name(adc->dev), 237 + adc); 238 + if (ret < 0) { 239 + dev_err(adc->dev, "request irq %d failed: %d\n", adc->irq, ret); 240 + return ret; 241 + } 242 + 243 + return devm_iio_device_register(adc->dev, iio_dev); 244 + } 245 + 246 + static struct platform_driver rn5t618_adc_driver = { 247 + .driver = { 248 + .name = "rn5t618-adc", 249 + }, 250 + .probe = rn5t618_adc_probe, 251 + }; 252 + 253 + module_platform_driver(rn5t618_adc_driver); 254 + MODULE_ALIAS("platform:rn5t618-adc"); 255 + MODULE_DESCRIPTION("RICOH RN5T618 ADC driver"); 256 + MODULE_LICENSE("GPL");
+1
drivers/mfd/Kconfig
··· 1071 1071 depends on OF 1072 1072 select MFD_CORE 1073 1073 select REGMAP_I2C 1074 + select REGMAP_IRQ 1074 1075 help 1075 1076 Say yes here to add support for the Ricoh RN5T567, 1076 1077 RN5T618, RC5T619 PMIC.
+98 -11
drivers/mfd/rn5t618.c
··· 8 8 9 9 #include <linux/delay.h> 10 10 #include <linux/i2c.h> 11 + #include <linux/interrupt.h> 12 + #include <linux/irq.h> 11 13 #include <linux/mfd/core.h> 12 14 #include <linux/mfd/rn5t618.h> 13 15 #include <linux/module.h> 14 16 #include <linux/of_device.h> 17 + #include <linux/platform_device.h> 15 18 #include <linux/reboot.h> 16 19 #include <linux/regmap.h> 17 20 18 21 static const struct mfd_cell rn5t618_cells[] = { 19 22 { .name = "rn5t618-regulator" }, 23 + { .name = "rn5t618-wdt" }, 24 + }; 25 + 26 + static const struct mfd_cell rc5t619_cells[] = { 27 + { .name = "rn5t618-adc" }, 28 + { .name = "rn5t618-regulator" }, 29 + { .name = "rc5t619-rtc" }, 20 30 { .name = "rn5t618-wdt" }, 21 31 }; 22 32 ··· 42 32 case RN5T618_IR_GPF: 43 33 case RN5T618_MON_IOIN: 44 34 case RN5T618_INTMON: 35 + case RN5T618_RTC_CTRL1 ... RN5T618_RTC_CTRL2: 36 + case RN5T618_RTC_SECONDS ... RN5T618_RTC_YEAR: 45 37 return true; 46 38 default: 47 39 return false; ··· 58 46 .cache_type = REGCACHE_RBTREE, 59 47 }; 60 48 49 + static const struct regmap_irq rc5t619_irqs[] = { 50 + REGMAP_IRQ_REG(RN5T618_IRQ_SYS, 0, BIT(0)), 51 + REGMAP_IRQ_REG(RN5T618_IRQ_DCDC, 0, BIT(1)), 52 + REGMAP_IRQ_REG(RN5T618_IRQ_RTC, 0, BIT(2)), 53 + REGMAP_IRQ_REG(RN5T618_IRQ_ADC, 0, BIT(3)), 54 + REGMAP_IRQ_REG(RN5T618_IRQ_GPIO, 0, BIT(4)), 55 + REGMAP_IRQ_REG(RN5T618_IRQ_CHG, 0, BIT(6)), 56 + }; 57 + 58 + static const struct regmap_irq_chip rc5t619_irq_chip = { 59 + .name = "rc5t619", 60 + .irqs = rc5t619_irqs, 61 + .num_irqs = ARRAY_SIZE(rc5t619_irqs), 62 + .num_regs = 1, 63 + .status_base = RN5T618_INTMON, 64 + .mask_base = RN5T618_INTEN, 65 + .mask_invert = true, 66 + }; 67 + 61 68 static struct rn5t618 *rn5t618_pm_power_off; 62 69 static struct notifier_block rn5t618_restart_handler; 70 + 71 + static int rn5t618_irq_init(struct rn5t618 *rn5t618) 72 + { 73 + const struct regmap_irq_chip *irq_chip = NULL; 74 + int ret; 75 + 76 + if (!rn5t618->irq) 77 + return 0; 78 + 79 + switch (rn5t618->variant) { 80 + case RC5T619: 81 + irq_chip = &rc5t619_irq_chip; 82 + break; 83 + default: 84 + dev_err(rn5t618->dev, "Currently no IRQ support for variant %d\n", 85 + (int)rn5t618->variant); 86 + return -ENOENT; 87 + } 88 + 89 + ret = devm_regmap_add_irq_chip(rn5t618->dev, rn5t618->regmap, 90 + rn5t618->irq, 91 + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 92 + 0, irq_chip, &rn5t618->irq_data); 93 + if (ret) 94 + dev_err(rn5t618->dev, "Failed to register IRQ chip\n"); 95 + 96 + return ret; 97 + } 63 98 64 99 static void rn5t618_trigger_poweroff_sequence(bool repower) 65 100 { ··· 146 87 }; 147 88 MODULE_DEVICE_TABLE(of, rn5t618_of_match); 148 89 149 - static int rn5t618_i2c_probe(struct i2c_client *i2c, 150 - const struct i2c_device_id *id) 90 + static int rn5t618_i2c_probe(struct i2c_client *i2c) 151 91 { 152 92 const struct of_device_id *of_id; 153 93 struct rn5t618 *priv; ··· 164 106 165 107 i2c_set_clientdata(i2c, priv); 166 108 priv->variant = (long)of_id->data; 109 + priv->irq = i2c->irq; 110 + priv->dev = &i2c->dev; 167 111 168 112 priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config); 169 113 if (IS_ERR(priv->regmap)) { ··· 174 114 return ret; 175 115 } 176 116 177 - ret = devm_mfd_add_devices(&i2c->dev, -1, rn5t618_cells, 178 - ARRAY_SIZE(rn5t618_cells), NULL, 0, NULL); 117 + if (priv->variant == RC5T619) 118 + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, 119 + rc5t619_cells, 120 + ARRAY_SIZE(rc5t619_cells), 121 + NULL, 0, NULL); 122 + else 123 + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_NONE, 124 + rn5t618_cells, 125 + ARRAY_SIZE(rn5t618_cells), 126 + NULL, 0, NULL); 179 127 if (ret) { 180 128 dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); 181 129 return ret; ··· 206 138 return ret; 207 139 } 208 140 209 - return 0; 141 + return rn5t618_irq_init(priv); 210 142 } 211 143 212 144 static int rn5t618_i2c_remove(struct i2c_client *i2c) ··· 223 155 return 0; 224 156 } 225 157 226 - static const struct i2c_device_id rn5t618_i2c_id[] = { 227 - { } 228 - }; 229 - MODULE_DEVICE_TABLE(i2c, rn5t618_i2c_id); 158 + static int __maybe_unused rn5t618_i2c_suspend(struct device *dev) 159 + { 160 + struct rn5t618 *priv = dev_get_drvdata(dev); 161 + 162 + if (priv->irq) 163 + disable_irq(priv->irq); 164 + 165 + return 0; 166 + } 167 + 168 + static int __maybe_unused rn5t618_i2c_resume(struct device *dev) 169 + { 170 + struct rn5t618 *priv = dev_get_drvdata(dev); 171 + 172 + if (priv->irq) 173 + enable_irq(priv->irq); 174 + 175 + return 0; 176 + } 177 + 178 + static SIMPLE_DEV_PM_OPS(rn5t618_i2c_dev_pm_ops, 179 + rn5t618_i2c_suspend, 180 + rn5t618_i2c_resume); 230 181 231 182 static struct i2c_driver rn5t618_i2c_driver = { 232 183 .driver = { 233 184 .name = "rn5t618", 234 185 .of_match_table = of_match_ptr(rn5t618_of_match), 186 + .pm = &rn5t618_i2c_dev_pm_ops, 235 187 }, 236 - .probe = rn5t618_i2c_probe, 188 + .probe_new = rn5t618_i2c_probe, 237 189 .remove = rn5t618_i2c_remove, 238 - .id_table = rn5t618_i2c_id, 239 190 }; 240 191 241 192 module_i2c_driver(rn5t618_i2c_driver);
+10
drivers/rtc/Kconfig
··· 591 591 This driver can also be built as a module. If so, the module 592 592 will be called rtc-rc5t583. 593 593 594 + config RTC_DRV_RC5T619 595 + tristate "RICOH RC5T619 RTC driver" 596 + depends on MFD_RN5T618 597 + help 598 + If you say yes here you get support for the RTC on the 599 + RICOH RC5T619 chips. 600 + 601 + This driver can also be built as a module. If so, the module 602 + will be called rtc-rc5t619. 603 + 594 604 config RTC_DRV_S35390A 595 605 tristate "Seiko Instruments S-35390A" 596 606 select BITREVERSE
+1
drivers/rtc/Makefile
··· 137 137 obj-$(CONFIG_RTC_DRV_R7301) += rtc-r7301.o 138 138 obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o 139 139 obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o 140 + obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-rc5t619.o 140 141 obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o 141 142 obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o 142 143 obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
+444
drivers/rtc/rtc-rc5t619.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * drivers/rtc/rtc-rc5t619.c 4 + * 5 + * Real time clock driver for RICOH RC5T619 power management chip. 6 + * 7 + * Copyright (C) 2019 Andreas Kemnade 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/device.h> 12 + #include <linux/errno.h> 13 + #include <linux/init.h> 14 + #include <linux/module.h> 15 + #include <linux/mfd/rn5t618.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/regmap.h> 18 + #include <linux/bcd.h> 19 + #include <linux/rtc.h> 20 + #include <linux/slab.h> 21 + #include <linux/irqdomain.h> 22 + 23 + struct rc5t619_rtc { 24 + int irq; 25 + struct rtc_device *rtc; 26 + struct rn5t618 *rn5t618; 27 + }; 28 + 29 + #define CTRL1_ALARM_ENABLED 0x40 30 + #define CTRL1_24HR 0x20 31 + #define CTRL1_PERIODIC_MASK 0xf 32 + 33 + #define CTRL2_PON 0x10 34 + #define CTRL2_ALARM_STATUS 0x80 35 + #define CTRL2_CTFG 0x4 36 + #define CTRL2_CTC 0x1 37 + 38 + #define MONTH_CENTFLAG 0x80 39 + #define HOUR_PMFLAG 0x20 40 + #define MDAY_DAL_EXT 0x80 41 + 42 + static uint8_t rtc5t619_12hour_bcd2bin(uint8_t hour) 43 + { 44 + if (hour & HOUR_PMFLAG) { 45 + hour = bcd2bin(hour & ~HOUR_PMFLAG); 46 + return hour == 12 ? 12 : 12 + hour; 47 + } 48 + 49 + hour = bcd2bin(hour); 50 + return hour == 12 ? 0 : hour; 51 + } 52 + 53 + static uint8_t rtc5t619_12hour_bin2bcd(uint8_t hour) 54 + { 55 + if (!hour) 56 + return 0x12; 57 + 58 + if (hour < 12) 59 + return bin2bcd(hour); 60 + 61 + if (hour == 12) 62 + return 0x12 | HOUR_PMFLAG; 63 + 64 + return bin2bcd(hour - 12) | HOUR_PMFLAG; 65 + } 66 + 67 + static int rc5t619_rtc_periodic_disable(struct device *dev) 68 + { 69 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 70 + int err; 71 + 72 + /* disable function */ 73 + err = regmap_update_bits(rtc->rn5t618->regmap, 74 + RN5T618_RTC_CTRL1, CTRL1_PERIODIC_MASK, 0); 75 + if (err < 0) 76 + return err; 77 + 78 + /* clear alarm flag and CTFG */ 79 + err = regmap_update_bits(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, 80 + CTRL2_ALARM_STATUS | CTRL2_CTFG | CTRL2_CTC, 81 + 0); 82 + if (err < 0) 83 + return err; 84 + 85 + return 0; 86 + } 87 + 88 + /* things to be done once after power on */ 89 + static int rc5t619_rtc_pon_setup(struct device *dev) 90 + { 91 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 92 + int err; 93 + unsigned int reg_data; 94 + 95 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &reg_data); 96 + if (err < 0) 97 + return err; 98 + 99 + /* clear VDET PON */ 100 + reg_data &= ~(CTRL2_PON | CTRL2_CTC | 0x4a); /* 0101-1011 */ 101 + reg_data |= 0x20; /* 0010-0000 */ 102 + err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, reg_data); 103 + if (err < 0) 104 + return err; 105 + 106 + /* clearing RTC Adjust register */ 107 + err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_ADJUST, 0); 108 + if (err) 109 + return err; 110 + 111 + return regmap_update_bits(rtc->rn5t618->regmap, 112 + RN5T618_RTC_CTRL1, 113 + CTRL1_24HR, CTRL1_24HR); 114 + } 115 + 116 + static int rc5t619_rtc_read_time(struct device *dev, struct rtc_time *tm) 117 + { 118 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 119 + u8 buff[7]; 120 + int err; 121 + int cent_flag; 122 + unsigned int ctrl1; 123 + unsigned int ctrl2; 124 + 125 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2); 126 + if (err < 0) 127 + return err; 128 + 129 + if (ctrl2 & CTRL2_PON) 130 + return -EINVAL; 131 + 132 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 133 + if (err < 0) 134 + return err; 135 + 136 + err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS, 137 + buff, sizeof(buff)); 138 + if (err < 0) 139 + return err; 140 + 141 + if (buff[5] & MONTH_CENTFLAG) 142 + cent_flag = 1; 143 + else 144 + cent_flag = 0; 145 + 146 + tm->tm_sec = bcd2bin(buff[0]); 147 + tm->tm_min = bcd2bin(buff[1]); 148 + 149 + if (ctrl1 & CTRL1_24HR) 150 + tm->tm_hour = bcd2bin(buff[2]); 151 + else 152 + tm->tm_hour = rtc5t619_12hour_bcd2bin(buff[2]); 153 + 154 + tm->tm_wday = bcd2bin(buff[3]); 155 + tm->tm_mday = bcd2bin(buff[4]); 156 + tm->tm_mon = bcd2bin(buff[5] & 0x1f) - 1; /* back to system 0-11 */ 157 + tm->tm_year = bcd2bin(buff[6]) + 100 * cent_flag; 158 + 159 + return 0; 160 + } 161 + 162 + static int rc5t619_rtc_set_time(struct device *dev, struct rtc_time *tm) 163 + { 164 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 165 + u8 buff[7]; 166 + int err; 167 + int cent_flag; 168 + unsigned int ctrl1; 169 + unsigned int ctrl2; 170 + 171 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2); 172 + if (err < 0) 173 + return err; 174 + 175 + if (ctrl2 & CTRL2_PON) 176 + rc5t619_rtc_pon_setup(dev); 177 + 178 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 179 + if (err < 0) 180 + return err; 181 + 182 + if (tm->tm_year >= 100) 183 + cent_flag = 1; 184 + else 185 + cent_flag = 0; 186 + 187 + buff[0] = bin2bcd(tm->tm_sec); 188 + buff[1] = bin2bcd(tm->tm_min); 189 + 190 + if (ctrl1 & CTRL1_24HR) 191 + buff[2] = bin2bcd(tm->tm_hour); 192 + else 193 + buff[2] = rtc5t619_12hour_bin2bcd(tm->tm_hour); 194 + 195 + buff[3] = bin2bcd(tm->tm_wday); 196 + buff[4] = bin2bcd(tm->tm_mday); 197 + buff[5] = bin2bcd(tm->tm_mon + 1); /* system set 0-11 */ 198 + buff[6] = bin2bcd(tm->tm_year - cent_flag * 100); 199 + 200 + if (cent_flag) 201 + buff[5] |= MONTH_CENTFLAG; 202 + 203 + err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS, 204 + buff, sizeof(buff)); 205 + if (err < 0) { 206 + dev_err(dev, "failed to program new time: %d\n", err); 207 + return err; 208 + } 209 + 210 + return 0; 211 + } 212 + 213 + /* 0-disable, 1-enable */ 214 + static int rc5t619_rtc_alarm_enable(struct device *dev, unsigned int enabled) 215 + { 216 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 217 + 218 + return regmap_update_bits(rtc->rn5t618->regmap, 219 + RN5T618_RTC_CTRL1, 220 + CTRL1_ALARM_ENABLED, 221 + enabled ? CTRL1_ALARM_ENABLED : 0); 222 + } 223 + 224 + static int rc5t619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 225 + { 226 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 227 + u8 buff[6]; 228 + unsigned int buff_cent; 229 + int err; 230 + int cent_flag; 231 + unsigned int ctrl1; 232 + 233 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 234 + if (err) 235 + return err; 236 + 237 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_MONTH, &buff_cent); 238 + if (err < 0) { 239 + dev_err(dev, "failed to read time: %d\n", err); 240 + return err; 241 + } 242 + 243 + if (buff_cent & MONTH_CENTFLAG) 244 + cent_flag = 1; 245 + else 246 + cent_flag = 0; 247 + 248 + err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC, 249 + buff, sizeof(buff)); 250 + if (err) 251 + return err; 252 + 253 + buff[3] = buff[3] & 0x3f; 254 + 255 + alrm->time.tm_sec = bcd2bin(buff[0]); 256 + alrm->time.tm_min = bcd2bin(buff[1]); 257 + 258 + if (ctrl1 & CTRL1_24HR) 259 + alrm->time.tm_hour = bcd2bin(buff[2]); 260 + else 261 + alrm->time.tm_hour = rtc5t619_12hour_bcd2bin(buff[2]); 262 + 263 + alrm->time.tm_mday = bcd2bin(buff[3]); 264 + alrm->time.tm_mon = bcd2bin(buff[4]) - 1; 265 + alrm->time.tm_year = bcd2bin(buff[5]) + 100 * cent_flag; 266 + alrm->enabled = !!(ctrl1 & CTRL1_ALARM_ENABLED); 267 + dev_dbg(dev, "read alarm: %ptR\n", &alrm->time); 268 + 269 + return 0; 270 + } 271 + 272 + static int rc5t619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 273 + { 274 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 275 + u8 buff[6]; 276 + int err; 277 + int cent_flag; 278 + unsigned int ctrl1; 279 + 280 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 281 + if (err) 282 + return err; 283 + 284 + err = rc5t619_rtc_alarm_enable(dev, 0); 285 + if (err < 0) 286 + return err; 287 + 288 + if (rtc->irq == -1) 289 + return -EINVAL; 290 + 291 + if (alrm->enabled == 0) 292 + return 0; 293 + 294 + if (alrm->time.tm_year >= 100) 295 + cent_flag = 1; 296 + else 297 + cent_flag = 0; 298 + 299 + alrm->time.tm_mon += 1; 300 + buff[0] = bin2bcd(alrm->time.tm_sec); 301 + buff[1] = bin2bcd(alrm->time.tm_min); 302 + 303 + if (ctrl1 & CTRL1_24HR) 304 + buff[2] = bin2bcd(alrm->time.tm_hour); 305 + else 306 + buff[2] = rtc5t619_12hour_bin2bcd(alrm->time.tm_hour); 307 + 308 + buff[3] = bin2bcd(alrm->time.tm_mday); 309 + buff[4] = bin2bcd(alrm->time.tm_mon); 310 + buff[5] = bin2bcd(alrm->time.tm_year - 100 * cent_flag); 311 + buff[3] |= MDAY_DAL_EXT; 312 + 313 + err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC, 314 + buff, sizeof(buff)); 315 + if (err < 0) 316 + return err; 317 + 318 + return rc5t619_rtc_alarm_enable(dev, alrm->enabled); 319 + } 320 + 321 + static const struct rtc_class_ops rc5t619_rtc_ops = { 322 + .read_time = rc5t619_rtc_read_time, 323 + .set_time = rc5t619_rtc_set_time, 324 + .set_alarm = rc5t619_rtc_set_alarm, 325 + .read_alarm = rc5t619_rtc_read_alarm, 326 + .alarm_irq_enable = rc5t619_rtc_alarm_enable, 327 + }; 328 + 329 + static int rc5t619_rtc_alarm_flag_clr(struct device *dev) 330 + { 331 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 332 + 333 + /* clear alarm-D status bits.*/ 334 + return regmap_update_bits(rtc->rn5t618->regmap, 335 + RN5T618_RTC_CTRL2, 336 + CTRL2_ALARM_STATUS | CTRL2_CTC, 0); 337 + } 338 + 339 + static irqreturn_t rc5t619_rtc_irq(int irq, void *data) 340 + { 341 + struct device *dev = data; 342 + struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 343 + 344 + rc5t619_rtc_alarm_flag_clr(dev); 345 + 346 + rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); 347 + return IRQ_HANDLED; 348 + } 349 + 350 + static int rc5t619_rtc_probe(struct platform_device *pdev) 351 + { 352 + struct device *dev = &pdev->dev; 353 + struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent); 354 + struct rc5t619_rtc *rtc; 355 + unsigned int ctrl2; 356 + int err; 357 + 358 + rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); 359 + if (IS_ERR(rtc)) { 360 + err = PTR_ERR(rtc); 361 + return -ENOMEM; 362 + } 363 + 364 + rtc->rn5t618 = rn5t618; 365 + 366 + dev_set_drvdata(dev, rtc); 367 + rtc->irq = -1; 368 + 369 + if (rn5t618->irq_data) 370 + rtc->irq = regmap_irq_get_virq(rn5t618->irq_data, 371 + RN5T618_IRQ_RTC); 372 + 373 + if (rtc->irq < 0) 374 + rtc->irq = -1; 375 + 376 + err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2); 377 + if (err < 0) 378 + return err; 379 + 380 + /* disable rtc periodic function */ 381 + err = rc5t619_rtc_periodic_disable(&pdev->dev); 382 + if (err) 383 + return err; 384 + 385 + if (ctrl2 & CTRL2_PON) { 386 + err = rc5t619_rtc_alarm_flag_clr(&pdev->dev); 387 + if (err) 388 + return err; 389 + } 390 + 391 + rtc->rtc = devm_rtc_allocate_device(&pdev->dev); 392 + if (IS_ERR(rtc->rtc)) { 393 + err = PTR_ERR(rtc->rtc); 394 + dev_err(dev, "RTC device register: err %d\n", err); 395 + return err; 396 + } 397 + 398 + rtc->rtc->ops = &rc5t619_rtc_ops; 399 + rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900; 400 + rtc->rtc->range_max = RTC_TIMESTAMP_END_2099; 401 + 402 + /* set interrupt and enable it */ 403 + if (rtc->irq != -1) { 404 + err = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, 405 + rc5t619_rtc_irq, 406 + IRQF_ONESHOT, 407 + "rtc-rc5t619", 408 + &pdev->dev); 409 + if (err < 0) { 410 + dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq); 411 + rtc->irq = -1; 412 + 413 + err = rc5t619_rtc_alarm_enable(&pdev->dev, 0); 414 + if (err) 415 + return err; 416 + 417 + } else { 418 + /* enable wake */ 419 + device_init_wakeup(&pdev->dev, 1); 420 + enable_irq_wake(rtc->irq); 421 + } 422 + } else { 423 + /* system don't want to using alarm interrupt, so close it */ 424 + err = rc5t619_rtc_alarm_enable(&pdev->dev, 0); 425 + if (err) 426 + return err; 427 + 428 + dev_warn(&pdev->dev, "rc5t619 interrupt is disabled\n"); 429 + } 430 + 431 + return rtc_register_device(rtc->rtc); 432 + } 433 + 434 + static struct platform_driver rc5t619_rtc_driver = { 435 + .driver = { 436 + .name = "rc5t619-rtc", 437 + }, 438 + .probe = rc5t619_rtc_probe, 439 + }; 440 + 441 + module_platform_driver(rc5t619_rtc_driver); 442 + MODULE_ALIAS("platform:rc5t619-rtc"); 443 + MODULE_DESCRIPTION("RICOH RC5T619 RTC driver"); 444 + MODULE_LICENSE("GPL");
+26
include/linux/mfd/rn5t618.h
··· 139 139 #define RN5T618_INTPOL 0x9c 140 140 #define RN5T618_INTEN 0x9d 141 141 #define RN5T618_INTMON 0x9e 142 + 143 + #define RN5T618_RTC_SECONDS 0xA0 144 + #define RN5T618_RTC_MDAY 0xA4 145 + #define RN5T618_RTC_MONTH 0xA5 146 + #define RN5T618_RTC_YEAR 0xA6 147 + #define RN5T618_RTC_ADJUST 0xA7 148 + #define RN5T618_RTC_ALARM_Y_SEC 0xA8 149 + #define RN5T618_RTC_DAL_MONTH 0xAC 150 + #define RN5T618_RTC_CTRL1 0xAE 151 + #define RN5T618_RTC_CTRL2 0xAF 152 + 142 153 #define RN5T618_PREVINDAC 0xb0 143 154 #define RN5T618_BATDAC 0xb1 144 155 #define RN5T618_CHGCTL1 0xb3 ··· 253 242 RC5T619, 254 243 }; 255 244 245 + /* RN5T618 IRQ definitions */ 246 + enum { 247 + RN5T618_IRQ_SYS = 0, 248 + RN5T618_IRQ_DCDC, 249 + RN5T618_IRQ_RTC, 250 + RN5T618_IRQ_ADC, 251 + RN5T618_IRQ_GPIO, 252 + RN5T618_IRQ_CHG, 253 + RN5T618_NR_IRQS, 254 + }; 255 + 256 256 struct rn5t618 { 257 257 struct regmap *regmap; 258 + struct device *dev; 258 259 long variant; 260 + 261 + int irq; 262 + struct regmap_irq_chip_data *irq_data; 259 263 }; 260 264 261 265 #endif /* __LINUX_MFD_RN5T618_H */