Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * RTC Driver for X-Powers AC100
0004  *
0005  * Copyright (c) 2016 Chen-Yu Tsai
0006  *
0007  * Chen-Yu Tsai <wens@csie.org>
0008  */
0009 
0010 #include <linux/bcd.h>
0011 #include <linux/clk-provider.h>
0012 #include <linux/device.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/kernel.h>
0015 #include <linux/mfd/ac100.h>
0016 #include <linux/module.h>
0017 #include <linux/mutex.h>
0018 #include <linux/of.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/regmap.h>
0021 #include <linux/rtc.h>
0022 #include <linux/types.h>
0023 
0024 /* Control register */
0025 #define AC100_RTC_CTRL_24HOUR   BIT(0)
0026 
0027 /* Clock output register bits */
0028 #define AC100_CLKOUT_PRE_DIV_SHIFT  5
0029 #define AC100_CLKOUT_PRE_DIV_WIDTH  3
0030 #define AC100_CLKOUT_MUX_SHIFT      4
0031 #define AC100_CLKOUT_MUX_WIDTH      1
0032 #define AC100_CLKOUT_DIV_SHIFT      1
0033 #define AC100_CLKOUT_DIV_WIDTH      3
0034 #define AC100_CLKOUT_EN         BIT(0)
0035 
0036 /* RTC */
0037 #define AC100_RTC_SEC_MASK  GENMASK(6, 0)
0038 #define AC100_RTC_MIN_MASK  GENMASK(6, 0)
0039 #define AC100_RTC_HOU_MASK  GENMASK(5, 0)
0040 #define AC100_RTC_WEE_MASK  GENMASK(2, 0)
0041 #define AC100_RTC_DAY_MASK  GENMASK(5, 0)
0042 #define AC100_RTC_MON_MASK  GENMASK(4, 0)
0043 #define AC100_RTC_YEA_MASK  GENMASK(7, 0)
0044 #define AC100_RTC_YEA_LEAP  BIT(15)
0045 #define AC100_RTC_UPD_TRIGGER   BIT(15)
0046 
0047 /* Alarm (wall clock) */
0048 #define AC100_ALM_INT_ENABLE    BIT(0)
0049 
0050 #define AC100_ALM_SEC_MASK  GENMASK(6, 0)
0051 #define AC100_ALM_MIN_MASK  GENMASK(6, 0)
0052 #define AC100_ALM_HOU_MASK  GENMASK(5, 0)
0053 #define AC100_ALM_WEE_MASK  GENMASK(2, 0)
0054 #define AC100_ALM_DAY_MASK  GENMASK(5, 0)
0055 #define AC100_ALM_MON_MASK  GENMASK(4, 0)
0056 #define AC100_ALM_YEA_MASK  GENMASK(7, 0)
0057 #define AC100_ALM_ENABLE_FLAG   BIT(15)
0058 #define AC100_ALM_UPD_TRIGGER   BIT(15)
0059 
0060 /*
0061  * The year parameter passed to the driver is usually an offset relative to
0062  * the year 1900. This macro is used to convert this offset to another one
0063  * relative to the minimum year allowed by the hardware.
0064  *
0065  * The year range is 1970 - 2069. This range is selected to match Allwinner's
0066  * driver.
0067  */
0068 #define AC100_YEAR_MIN              1970
0069 #define AC100_YEAR_MAX              2069
0070 #define AC100_YEAR_OFF              (AC100_YEAR_MIN - 1900)
0071 
0072 struct ac100_clkout {
0073     struct clk_hw hw;
0074     struct regmap *regmap;
0075     u8 offset;
0076 };
0077 
0078 #define to_ac100_clkout(_hw) container_of(_hw, struct ac100_clkout, hw)
0079 
0080 #define AC100_RTC_32K_NAME  "ac100-rtc-32k"
0081 #define AC100_RTC_32K_RATE  32768
0082 #define AC100_CLKOUT_NUM    3
0083 
0084 static const char * const ac100_clkout_names[AC100_CLKOUT_NUM] = {
0085     "ac100-cko1-rtc",
0086     "ac100-cko2-rtc",
0087     "ac100-cko3-rtc",
0088 };
0089 
0090 struct ac100_rtc_dev {
0091     struct rtc_device *rtc;
0092     struct device *dev;
0093     struct regmap *regmap;
0094     int irq;
0095     unsigned long alarm;
0096 
0097     struct clk_hw *rtc_32k_clk;
0098     struct ac100_clkout clks[AC100_CLKOUT_NUM];
0099     struct clk_hw_onecell_data *clk_data;
0100 };
0101 
0102 /**
0103  * Clock controls for 3 clock output pins
0104  */
0105 
0106 static const struct clk_div_table ac100_clkout_prediv[] = {
0107     { .val = 0, .div = 1 },
0108     { .val = 1, .div = 2 },
0109     { .val = 2, .div = 4 },
0110     { .val = 3, .div = 8 },
0111     { .val = 4, .div = 16 },
0112     { .val = 5, .div = 32 },
0113     { .val = 6, .div = 64 },
0114     { .val = 7, .div = 122 },
0115     { },
0116 };
0117 
0118 /* Abuse the fact that one parent is 32768 Hz, and the other is 4 MHz */
0119 static unsigned long ac100_clkout_recalc_rate(struct clk_hw *hw,
0120                           unsigned long prate)
0121 {
0122     struct ac100_clkout *clk = to_ac100_clkout(hw);
0123     unsigned int reg, div;
0124 
0125     regmap_read(clk->regmap, clk->offset, &reg);
0126 
0127     /* Handle pre-divider first */
0128     if (prate != AC100_RTC_32K_RATE) {
0129         div = (reg >> AC100_CLKOUT_PRE_DIV_SHIFT) &
0130             ((1 << AC100_CLKOUT_PRE_DIV_WIDTH) - 1);
0131         prate = divider_recalc_rate(hw, prate, div,
0132                         ac100_clkout_prediv, 0,
0133                         AC100_CLKOUT_PRE_DIV_WIDTH);
0134     }
0135 
0136     div = (reg >> AC100_CLKOUT_DIV_SHIFT) &
0137         (BIT(AC100_CLKOUT_DIV_WIDTH) - 1);
0138     return divider_recalc_rate(hw, prate, div, NULL,
0139                    CLK_DIVIDER_POWER_OF_TWO,
0140                    AC100_CLKOUT_DIV_WIDTH);
0141 }
0142 
0143 static long ac100_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
0144                     unsigned long prate)
0145 {
0146     unsigned long best_rate = 0, tmp_rate, tmp_prate;
0147     int i;
0148 
0149     if (prate == AC100_RTC_32K_RATE)
0150         return divider_round_rate(hw, rate, &prate, NULL,
0151                       AC100_CLKOUT_DIV_WIDTH,
0152                       CLK_DIVIDER_POWER_OF_TWO);
0153 
0154     for (i = 0; ac100_clkout_prediv[i].div; i++) {
0155         tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[i].val);
0156         tmp_rate = divider_round_rate(hw, rate, &tmp_prate, NULL,
0157                           AC100_CLKOUT_DIV_WIDTH,
0158                           CLK_DIVIDER_POWER_OF_TWO);
0159 
0160         if (tmp_rate > rate)
0161             continue;
0162         if (rate - tmp_rate < best_rate - tmp_rate)
0163             best_rate = tmp_rate;
0164     }
0165 
0166     return best_rate;
0167 }
0168 
0169 static int ac100_clkout_determine_rate(struct clk_hw *hw,
0170                        struct clk_rate_request *req)
0171 {
0172     struct clk_hw *best_parent;
0173     unsigned long best = 0;
0174     int i, num_parents = clk_hw_get_num_parents(hw);
0175 
0176     for (i = 0; i < num_parents; i++) {
0177         struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
0178         unsigned long tmp, prate;
0179 
0180         /*
0181          * The clock has two parents, one is a fixed clock which is
0182          * internally registered by the ac100 driver. The other parent
0183          * is a clock from the codec side of the chip, which we
0184          * properly declare and reference in the devicetree and is
0185          * not implemented in any driver right now.
0186          * If the clock core looks for the parent of that second
0187          * missing clock, it can't find one that is registered and
0188          * returns NULL.
0189          * So we end up in a situation where clk_hw_get_num_parents
0190          * returns the amount of clocks we can be parented to, but
0191          * clk_hw_get_parent_by_index will not return the orphan
0192          * clocks.
0193          * Thus we need to check if the parent exists before
0194          * we get the parent rate, so we could use the RTC
0195          * without waiting for the codec to be supported.
0196          */
0197         if (!parent)
0198             continue;
0199 
0200         prate = clk_hw_get_rate(parent);
0201 
0202         tmp = ac100_clkout_round_rate(hw, req->rate, prate);
0203 
0204         if (tmp > req->rate)
0205             continue;
0206         if (req->rate - tmp < req->rate - best) {
0207             best = tmp;
0208             best_parent = parent;
0209         }
0210     }
0211 
0212     if (!best)
0213         return -EINVAL;
0214 
0215     req->best_parent_hw = best_parent;
0216     req->best_parent_rate = best;
0217     req->rate = best;
0218 
0219     return 0;
0220 }
0221 
0222 static int ac100_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
0223                  unsigned long prate)
0224 {
0225     struct ac100_clkout *clk = to_ac100_clkout(hw);
0226     int div = 0, pre_div = 0;
0227 
0228     do {
0229         div = divider_get_val(rate * ac100_clkout_prediv[pre_div].div,
0230                       prate, NULL, AC100_CLKOUT_DIV_WIDTH,
0231                       CLK_DIVIDER_POWER_OF_TWO);
0232         if (div >= 0)
0233             break;
0234     } while (prate != AC100_RTC_32K_RATE &&
0235          ac100_clkout_prediv[++pre_div].div);
0236 
0237     if (div < 0)
0238         return div;
0239 
0240     pre_div = ac100_clkout_prediv[pre_div].val;
0241 
0242     regmap_update_bits(clk->regmap, clk->offset,
0243                ((1 << AC100_CLKOUT_DIV_WIDTH) - 1) << AC100_CLKOUT_DIV_SHIFT |
0244                ((1 << AC100_CLKOUT_PRE_DIV_WIDTH) - 1) << AC100_CLKOUT_PRE_DIV_SHIFT,
0245                (div - 1) << AC100_CLKOUT_DIV_SHIFT |
0246                (pre_div - 1) << AC100_CLKOUT_PRE_DIV_SHIFT);
0247 
0248     return 0;
0249 }
0250 
0251 static int ac100_clkout_prepare(struct clk_hw *hw)
0252 {
0253     struct ac100_clkout *clk = to_ac100_clkout(hw);
0254 
0255     return regmap_update_bits(clk->regmap, clk->offset, AC100_CLKOUT_EN,
0256                   AC100_CLKOUT_EN);
0257 }
0258 
0259 static void ac100_clkout_unprepare(struct clk_hw *hw)
0260 {
0261     struct ac100_clkout *clk = to_ac100_clkout(hw);
0262 
0263     regmap_update_bits(clk->regmap, clk->offset, AC100_CLKOUT_EN, 0);
0264 }
0265 
0266 static int ac100_clkout_is_prepared(struct clk_hw *hw)
0267 {
0268     struct ac100_clkout *clk = to_ac100_clkout(hw);
0269     unsigned int reg;
0270 
0271     regmap_read(clk->regmap, clk->offset, &reg);
0272 
0273     return reg & AC100_CLKOUT_EN;
0274 }
0275 
0276 static u8 ac100_clkout_get_parent(struct clk_hw *hw)
0277 {
0278     struct ac100_clkout *clk = to_ac100_clkout(hw);
0279     unsigned int reg;
0280 
0281     regmap_read(clk->regmap, clk->offset, &reg);
0282 
0283     return (reg >> AC100_CLKOUT_MUX_SHIFT) & 0x1;
0284 }
0285 
0286 static int ac100_clkout_set_parent(struct clk_hw *hw, u8 index)
0287 {
0288     struct ac100_clkout *clk = to_ac100_clkout(hw);
0289 
0290     return regmap_update_bits(clk->regmap, clk->offset,
0291                   BIT(AC100_CLKOUT_MUX_SHIFT),
0292                   index ? BIT(AC100_CLKOUT_MUX_SHIFT) : 0);
0293 }
0294 
0295 static const struct clk_ops ac100_clkout_ops = {
0296     .prepare    = ac100_clkout_prepare,
0297     .unprepare  = ac100_clkout_unprepare,
0298     .is_prepared    = ac100_clkout_is_prepared,
0299     .recalc_rate    = ac100_clkout_recalc_rate,
0300     .determine_rate = ac100_clkout_determine_rate,
0301     .get_parent = ac100_clkout_get_parent,
0302     .set_parent = ac100_clkout_set_parent,
0303     .set_rate   = ac100_clkout_set_rate,
0304 };
0305 
0306 static int ac100_rtc_register_clks(struct ac100_rtc_dev *chip)
0307 {
0308     struct device_node *np = chip->dev->of_node;
0309     const char *parents[2] = {AC100_RTC_32K_NAME};
0310     int i, ret;
0311 
0312     chip->clk_data = devm_kzalloc(chip->dev,
0313                       struct_size(chip->clk_data, hws,
0314                           AC100_CLKOUT_NUM),
0315                       GFP_KERNEL);
0316     if (!chip->clk_data)
0317         return -ENOMEM;
0318 
0319     chip->rtc_32k_clk = clk_hw_register_fixed_rate(chip->dev,
0320                                AC100_RTC_32K_NAME,
0321                                NULL, 0,
0322                                AC100_RTC_32K_RATE);
0323     if (IS_ERR(chip->rtc_32k_clk)) {
0324         ret = PTR_ERR(chip->rtc_32k_clk);
0325         dev_err(chip->dev, "Failed to register RTC-32k clock: %d\n",
0326             ret);
0327         return ret;
0328     }
0329 
0330     parents[1] = of_clk_get_parent_name(np, 0);
0331     if (!parents[1]) {
0332         dev_err(chip->dev, "Failed to get ADDA 4M clock\n");
0333         return -EINVAL;
0334     }
0335 
0336     for (i = 0; i < AC100_CLKOUT_NUM; i++) {
0337         struct ac100_clkout *clk = &chip->clks[i];
0338         struct clk_init_data init = {
0339             .name = ac100_clkout_names[i],
0340             .ops = &ac100_clkout_ops,
0341             .parent_names = parents,
0342             .num_parents = ARRAY_SIZE(parents),
0343             .flags = 0,
0344         };
0345 
0346         of_property_read_string_index(np, "clock-output-names",
0347                           i, &init.name);
0348         clk->regmap = chip->regmap;
0349         clk->offset = AC100_CLKOUT_CTRL1 + i;
0350         clk->hw.init = &init;
0351 
0352         ret = devm_clk_hw_register(chip->dev, &clk->hw);
0353         if (ret) {
0354             dev_err(chip->dev, "Failed to register clk '%s': %d\n",
0355                 init.name, ret);
0356             goto err_unregister_rtc_32k;
0357         }
0358 
0359         chip->clk_data->hws[i] = &clk->hw;
0360     }
0361 
0362     chip->clk_data->num = i;
0363     ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, chip->clk_data);
0364     if (ret)
0365         goto err_unregister_rtc_32k;
0366 
0367     return 0;
0368 
0369 err_unregister_rtc_32k:
0370     clk_unregister_fixed_rate(chip->rtc_32k_clk->clk);
0371 
0372     return ret;
0373 }
0374 
0375 static void ac100_rtc_unregister_clks(struct ac100_rtc_dev *chip)
0376 {
0377     of_clk_del_provider(chip->dev->of_node);
0378     clk_unregister_fixed_rate(chip->rtc_32k_clk->clk);
0379 }
0380 
0381 /**
0382  * RTC related bits
0383  */
0384 static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
0385 {
0386     struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
0387     struct regmap *regmap = chip->regmap;
0388     u16 reg[7];
0389     int ret;
0390 
0391     ret = regmap_bulk_read(regmap, AC100_RTC_SEC, reg, 7);
0392     if (ret)
0393         return ret;
0394 
0395     rtc_tm->tm_sec  = bcd2bin(reg[0] & AC100_RTC_SEC_MASK);
0396     rtc_tm->tm_min  = bcd2bin(reg[1] & AC100_RTC_MIN_MASK);
0397     rtc_tm->tm_hour = bcd2bin(reg[2] & AC100_RTC_HOU_MASK);
0398     rtc_tm->tm_wday = bcd2bin(reg[3] & AC100_RTC_WEE_MASK);
0399     rtc_tm->tm_mday = bcd2bin(reg[4] & AC100_RTC_DAY_MASK);
0400     rtc_tm->tm_mon  = bcd2bin(reg[5] & AC100_RTC_MON_MASK) - 1;
0401     rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK) +
0402               AC100_YEAR_OFF;
0403 
0404     return 0;
0405 }
0406 
0407 static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
0408 {
0409     struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
0410     struct regmap *regmap = chip->regmap;
0411     int year;
0412     u16 reg[8];
0413 
0414     /* our RTC has a limited year range... */
0415     year = rtc_tm->tm_year - AC100_YEAR_OFF;
0416     if (year < 0 || year > (AC100_YEAR_MAX - 1900)) {
0417         dev_err(dev, "rtc only supports year in range %d - %d\n",
0418             AC100_YEAR_MIN, AC100_YEAR_MAX);
0419         return -EINVAL;
0420     }
0421 
0422     /* convert to BCD */
0423     reg[0] = bin2bcd(rtc_tm->tm_sec)     & AC100_RTC_SEC_MASK;
0424     reg[1] = bin2bcd(rtc_tm->tm_min)     & AC100_RTC_MIN_MASK;
0425     reg[2] = bin2bcd(rtc_tm->tm_hour)    & AC100_RTC_HOU_MASK;
0426     reg[3] = bin2bcd(rtc_tm->tm_wday)    & AC100_RTC_WEE_MASK;
0427     reg[4] = bin2bcd(rtc_tm->tm_mday)    & AC100_RTC_DAY_MASK;
0428     reg[5] = bin2bcd(rtc_tm->tm_mon + 1) & AC100_RTC_MON_MASK;
0429     reg[6] = bin2bcd(year)           & AC100_RTC_YEA_MASK;
0430     /* trigger write */
0431     reg[7] = AC100_RTC_UPD_TRIGGER;
0432 
0433     /* Is it a leap year? */
0434     if (is_leap_year(year + AC100_YEAR_OFF + 1900))
0435         reg[6] |= AC100_RTC_YEA_LEAP;
0436 
0437     return regmap_bulk_write(regmap, AC100_RTC_SEC, reg, 8);
0438 }
0439 
0440 static int ac100_rtc_alarm_irq_enable(struct device *dev, unsigned int en)
0441 {
0442     struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
0443     struct regmap *regmap = chip->regmap;
0444     unsigned int val;
0445 
0446     val = en ? AC100_ALM_INT_ENABLE : 0;
0447 
0448     return regmap_write(regmap, AC100_ALM_INT_ENA, val);
0449 }
0450 
0451 static int ac100_rtc_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0452 {
0453     struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
0454     struct regmap *regmap = chip->regmap;
0455     struct rtc_time *alrm_tm = &alrm->time;
0456     u16 reg[7];
0457     unsigned int val;
0458     int ret;
0459 
0460     ret = regmap_read(regmap, AC100_ALM_INT_ENA, &val);
0461     if (ret)
0462         return ret;
0463 
0464     alrm->enabled = !!(val & AC100_ALM_INT_ENABLE);
0465 
0466     ret = regmap_bulk_read(regmap, AC100_ALM_SEC, reg, 7);
0467     if (ret)
0468         return ret;
0469 
0470     alrm_tm->tm_sec  = bcd2bin(reg[0] & AC100_ALM_SEC_MASK);
0471     alrm_tm->tm_min  = bcd2bin(reg[1] & AC100_ALM_MIN_MASK);
0472     alrm_tm->tm_hour = bcd2bin(reg[2] & AC100_ALM_HOU_MASK);
0473     alrm_tm->tm_wday = bcd2bin(reg[3] & AC100_ALM_WEE_MASK);
0474     alrm_tm->tm_mday = bcd2bin(reg[4] & AC100_ALM_DAY_MASK);
0475     alrm_tm->tm_mon  = bcd2bin(reg[5] & AC100_ALM_MON_MASK) - 1;
0476     alrm_tm->tm_year = bcd2bin(reg[6] & AC100_ALM_YEA_MASK) +
0477                AC100_YEAR_OFF;
0478 
0479     return 0;
0480 }
0481 
0482 static int ac100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0483 {
0484     struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
0485     struct regmap *regmap = chip->regmap;
0486     struct rtc_time *alrm_tm = &alrm->time;
0487     u16 reg[8];
0488     int year;
0489     int ret;
0490 
0491     /* our alarm has a limited year range... */
0492     year = alrm_tm->tm_year - AC100_YEAR_OFF;
0493     if (year < 0 || year > (AC100_YEAR_MAX - 1900)) {
0494         dev_err(dev, "alarm only supports year in range %d - %d\n",
0495             AC100_YEAR_MIN, AC100_YEAR_MAX);
0496         return -EINVAL;
0497     }
0498 
0499     /* convert to BCD */
0500     reg[0] = (bin2bcd(alrm_tm->tm_sec)  & AC100_ALM_SEC_MASK) |
0501             AC100_ALM_ENABLE_FLAG;
0502     reg[1] = (bin2bcd(alrm_tm->tm_min)  & AC100_ALM_MIN_MASK) |
0503             AC100_ALM_ENABLE_FLAG;
0504     reg[2] = (bin2bcd(alrm_tm->tm_hour) & AC100_ALM_HOU_MASK) |
0505             AC100_ALM_ENABLE_FLAG;
0506     /* Do not enable weekday alarm */
0507     reg[3] = bin2bcd(alrm_tm->tm_wday) & AC100_ALM_WEE_MASK;
0508     reg[4] = (bin2bcd(alrm_tm->tm_mday) & AC100_ALM_DAY_MASK) |
0509             AC100_ALM_ENABLE_FLAG;
0510     reg[5] = (bin2bcd(alrm_tm->tm_mon + 1)  & AC100_ALM_MON_MASK) |
0511             AC100_ALM_ENABLE_FLAG;
0512     reg[6] = (bin2bcd(year) & AC100_ALM_YEA_MASK) |
0513             AC100_ALM_ENABLE_FLAG;
0514     /* trigger write */
0515     reg[7] = AC100_ALM_UPD_TRIGGER;
0516 
0517     ret = regmap_bulk_write(regmap, AC100_ALM_SEC, reg, 8);
0518     if (ret)
0519         return ret;
0520 
0521     return ac100_rtc_alarm_irq_enable(dev, alrm->enabled);
0522 }
0523 
0524 static irqreturn_t ac100_rtc_irq(int irq, void *data)
0525 {
0526     struct ac100_rtc_dev *chip = data;
0527     struct regmap *regmap = chip->regmap;
0528     unsigned int val = 0;
0529     int ret;
0530 
0531     rtc_lock(chip->rtc);
0532 
0533     /* read status */
0534     ret = regmap_read(regmap, AC100_ALM_INT_STA, &val);
0535     if (ret)
0536         goto out;
0537 
0538     if (val & AC100_ALM_INT_ENABLE) {
0539         /* signal rtc framework */
0540         rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
0541 
0542         /* clear status */
0543         ret = regmap_write(regmap, AC100_ALM_INT_STA, val);
0544         if (ret)
0545             goto out;
0546 
0547         /* disable interrupt */
0548         ret = ac100_rtc_alarm_irq_enable(chip->dev, 0);
0549         if (ret)
0550             goto out;
0551     }
0552 
0553 out:
0554     rtc_unlock(chip->rtc);
0555     return IRQ_HANDLED;
0556 }
0557 
0558 static const struct rtc_class_ops ac100_rtc_ops = {
0559     .read_time    = ac100_rtc_get_time,
0560     .set_time     = ac100_rtc_set_time,
0561     .read_alarm   = ac100_rtc_get_alarm,
0562     .set_alarm    = ac100_rtc_set_alarm,
0563     .alarm_irq_enable = ac100_rtc_alarm_irq_enable,
0564 };
0565 
0566 static int ac100_rtc_probe(struct platform_device *pdev)
0567 {
0568     struct ac100_dev *ac100 = dev_get_drvdata(pdev->dev.parent);
0569     struct ac100_rtc_dev *chip;
0570     int ret;
0571 
0572     chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
0573     if (!chip)
0574         return -ENOMEM;
0575 
0576     platform_set_drvdata(pdev, chip);
0577     chip->dev = &pdev->dev;
0578     chip->regmap = ac100->regmap;
0579 
0580     chip->irq = platform_get_irq(pdev, 0);
0581     if (chip->irq < 0)
0582         return chip->irq;
0583 
0584     chip->rtc = devm_rtc_allocate_device(&pdev->dev);
0585     if (IS_ERR(chip->rtc))
0586         return PTR_ERR(chip->rtc);
0587 
0588     chip->rtc->ops = &ac100_rtc_ops;
0589 
0590     ret = devm_request_threaded_irq(&pdev->dev, chip->irq, NULL,
0591                     ac100_rtc_irq,
0592                     IRQF_SHARED | IRQF_ONESHOT,
0593                     dev_name(&pdev->dev), chip);
0594     if (ret) {
0595         dev_err(&pdev->dev, "Could not request IRQ\n");
0596         return ret;
0597     }
0598 
0599     /* always use 24 hour mode */
0600     regmap_write_bits(chip->regmap, AC100_RTC_CTRL, AC100_RTC_CTRL_24HOUR,
0601               AC100_RTC_CTRL_24HOUR);
0602 
0603     /* disable counter alarm interrupt */
0604     regmap_write(chip->regmap, AC100_ALM_INT_ENA, 0);
0605 
0606     /* clear counter alarm pending interrupts */
0607     regmap_write(chip->regmap, AC100_ALM_INT_STA, AC100_ALM_INT_ENABLE);
0608 
0609     ret = ac100_rtc_register_clks(chip);
0610     if (ret)
0611         return ret;
0612 
0613     return devm_rtc_register_device(chip->rtc);
0614 }
0615 
0616 static int ac100_rtc_remove(struct platform_device *pdev)
0617 {
0618     struct ac100_rtc_dev *chip = platform_get_drvdata(pdev);
0619 
0620     ac100_rtc_unregister_clks(chip);
0621 
0622     return 0;
0623 }
0624 
0625 static const struct of_device_id ac100_rtc_match[] = {
0626     { .compatible = "x-powers,ac100-rtc" },
0627     { },
0628 };
0629 MODULE_DEVICE_TABLE(of, ac100_rtc_match);
0630 
0631 static struct platform_driver ac100_rtc_driver = {
0632     .probe      = ac100_rtc_probe,
0633     .remove     = ac100_rtc_remove,
0634     .driver     = {
0635         .name       = "ac100-rtc",
0636         .of_match_table = of_match_ptr(ac100_rtc_match),
0637     },
0638 };
0639 module_platform_driver(ac100_rtc_driver);
0640 
0641 MODULE_DESCRIPTION("X-Powers AC100 RTC driver");
0642 MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
0643 MODULE_LICENSE("GPL v2");