rtc-sun6i.c (fb61bb82cb46a932ef2fc62e1c731c8e7e6640d5) | rtc-sun6i.c (3855c2c3e5461ab5ece9c1578650fcc23dd248c2) |
---|---|
1/* 2 * An RTC driver for Allwinner A31/A23 3 * 4 * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org> 5 * 6 * based on rtc-sunxi.c 7 * 8 * An RTC driver for Allwinner A10/A20 --- 6 unchanged lines hidden (view full) --- 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20 * more details. 21 */ 22 | 1/* 2 * An RTC driver for Allwinner A31/A23 3 * 4 * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org> 5 * 6 * based on rtc-sunxi.c 7 * 8 * An RTC driver for Allwinner A10/A20 --- 6 unchanged lines hidden (view full) --- 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20 * more details. 21 */ 22 |
23#include <linux/clk.h> 24#include <linux/clk-provider.h> |
|
23#include <linux/delay.h> 24#include <linux/err.h> 25#include <linux/fs.h> 26#include <linux/init.h> 27#include <linux/interrupt.h> 28#include <linux/io.h> 29#include <linux/kernel.h> 30#include <linux/module.h> 31#include <linux/of.h> 32#include <linux/of_address.h> 33#include <linux/of_device.h> 34#include <linux/platform_device.h> 35#include <linux/rtc.h> | 25#include <linux/delay.h> 26#include <linux/err.h> 27#include <linux/fs.h> 28#include <linux/init.h> 29#include <linux/interrupt.h> 30#include <linux/io.h> 31#include <linux/kernel.h> 32#include <linux/module.h> 33#include <linux/of.h> 34#include <linux/of_address.h> 35#include <linux/of_device.h> 36#include <linux/platform_device.h> 37#include <linux/rtc.h> |
38#include <linux/slab.h> |
|
36#include <linux/types.h> 37 38/* Control register */ 39#define SUN6I_LOSC_CTRL 0x0000 40#define SUN6I_LOSC_CTRL_KEY (0x16aa << 16) 41#define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) 42#define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) 43#define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) 44#define SUN6I_LOSC_CTRL_EXT_OSC BIT(0) 45#define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) 46 | 39#include <linux/types.h> 40 41/* Control register */ 42#define SUN6I_LOSC_CTRL 0x0000 43#define SUN6I_LOSC_CTRL_KEY (0x16aa << 16) 44#define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) 45#define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) 46#define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) 47#define SUN6I_LOSC_CTRL_EXT_OSC BIT(0) 48#define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) 49 |
50#define SUN6I_LOSC_CLK_PRESCAL 0x0008 51 |
|
47/* RTC */ 48#define SUN6I_RTC_YMD 0x0010 49#define SUN6I_RTC_HMS 0x0014 50 51/* Alarm 0 (counter) */ 52#define SUN6I_ALRM_COUNTER 0x0020 53#define SUN6I_ALRM_CUR_VAL 0x0024 54#define SUN6I_ALRM_EN 0x0028 --- 57 unchanged lines hidden (view full) --- 112 113struct sun6i_rtc_dev { 114 struct rtc_device *rtc; 115 struct device *dev; 116 void __iomem *base; 117 int irq; 118 unsigned long alarm; 119 | 52/* RTC */ 53#define SUN6I_RTC_YMD 0x0010 54#define SUN6I_RTC_HMS 0x0014 55 56/* Alarm 0 (counter) */ 57#define SUN6I_ALRM_COUNTER 0x0020 58#define SUN6I_ALRM_CUR_VAL 0x0024 59#define SUN6I_ALRM_EN 0x0028 --- 57 unchanged lines hidden (view full) --- 117 118struct sun6i_rtc_dev { 119 struct rtc_device *rtc; 120 struct device *dev; 121 void __iomem *base; 122 int irq; 123 unsigned long alarm; 124 |
125 struct clk_hw hw; 126 struct clk_hw *int_osc; 127 struct clk *losc; 128 |
|
120 spinlock_t lock; 121}; 122 | 129 spinlock_t lock; 130}; 131 |
132static struct sun6i_rtc_dev *sun6i_rtc; 133 134static unsigned long sun6i_rtc_osc_recalc_rate(struct clk_hw *hw, 135 unsigned long parent_rate) 136{ 137 struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); 138 u32 val; 139 140 val = readl(rtc->base + SUN6I_LOSC_CTRL); 141 if (val & SUN6I_LOSC_CTRL_EXT_OSC) 142 return parent_rate; 143 144 val = readl(rtc->base + SUN6I_LOSC_CLK_PRESCAL); 145 val &= GENMASK(4, 0); 146 147 return parent_rate / (val + 1); 148} 149 150static u8 sun6i_rtc_osc_get_parent(struct clk_hw *hw) 151{ 152 struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); 153 154 return readl(rtc->base + SUN6I_LOSC_CTRL) & SUN6I_LOSC_CTRL_EXT_OSC; 155} 156 157static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index) 158{ 159 struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw); 160 unsigned long flags; 161 u32 val; 162 163 if (index > 1) 164 return -EINVAL; 165 166 spin_lock_irqsave(&rtc->lock, flags); 167 val = readl(rtc->base + SUN6I_LOSC_CTRL); 168 val &= ~SUN6I_LOSC_CTRL_EXT_OSC; 169 val |= SUN6I_LOSC_CTRL_KEY; 170 val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0; 171 writel(val, rtc->base + SUN6I_LOSC_CTRL); 172 spin_unlock_irqrestore(&rtc->lock, flags); 173 174 return 0; 175} 176 177static const struct clk_ops sun6i_rtc_osc_ops = { 178 .recalc_rate = sun6i_rtc_osc_recalc_rate, 179 180 .get_parent = sun6i_rtc_osc_get_parent, 181 .set_parent = sun6i_rtc_osc_set_parent, 182}; 183 184static void __init sun6i_rtc_clk_init(struct device_node *node) 185{ 186 struct clk_hw_onecell_data *clk_data; 187 struct sun6i_rtc_dev *rtc; 188 struct clk_init_data init = { 189 .ops = &sun6i_rtc_osc_ops, 190 }; 191 const char *parents[2]; 192 193 rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); 194 if (!rtc) 195 return; 196 spin_lock_init(&rtc->lock); 197 198 clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws), 199 GFP_KERNEL); 200 if (!clk_data) 201 return; 202 spin_lock_init(&rtc->lock); 203 204 rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node)); 205 if (!rtc->base) { 206 pr_crit("Can't map RTC registers"); 207 return; 208 } 209 210 /* Switch to the external, more precise, oscillator */ 211 writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC, 212 rtc->base + SUN6I_LOSC_CTRL); 213 214 /* Deal with old DTs */ 215 if (!of_get_property(node, "clocks", NULL)) 216 return; 217 218 rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL, 219 "rtc-int-osc", 220 NULL, 0, 221 667000, 222 300000000); 223 if (IS_ERR(rtc->int_osc)) { 224 pr_crit("Couldn't register the internal oscillator\n"); 225 return; 226 } 227 228 parents[0] = clk_hw_get_name(rtc->int_osc); 229 parents[1] = of_clk_get_parent_name(node, 0); 230 231 rtc->hw.init = &init; 232 233 init.parent_names = parents; 234 init.num_parents = of_clk_get_parent_count(node) + 1; 235 of_property_read_string(node, "clock-output-names", &init.name); 236 237 rtc->losc = clk_register(NULL, &rtc->hw); 238 if (IS_ERR(rtc->losc)) { 239 pr_crit("Couldn't register the LOSC clock\n"); 240 return; 241 } 242 243 clk_data->num = 1; 244 clk_data->hws[0] = &rtc->hw; 245 of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); 246 247 /* Yes, I know, this is ugly. */ 248 sun6i_rtc = rtc; 249} 250CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc", 251 sun6i_rtc_clk_init); 252 |
|
123static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) 124{ 125 struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; 126 irqreturn_t ret = IRQ_NONE; 127 u32 val; 128 129 spin_lock(&chip->lock); 130 val = readl(chip->base + SUN6I_ALRM_IRQ_STA); --- 227 unchanged lines hidden (view full) --- 358 .set_time = sun6i_rtc_settime, 359 .read_alarm = sun6i_rtc_getalarm, 360 .set_alarm = sun6i_rtc_setalarm, 361 .alarm_irq_enable = sun6i_rtc_alarm_irq_enable 362}; 363 364static int sun6i_rtc_probe(struct platform_device *pdev) 365{ | 253static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) 254{ 255 struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; 256 irqreturn_t ret = IRQ_NONE; 257 u32 val; 258 259 spin_lock(&chip->lock); 260 val = readl(chip->base + SUN6I_ALRM_IRQ_STA); --- 227 unchanged lines hidden (view full) --- 488 .set_time = sun6i_rtc_settime, 489 .read_alarm = sun6i_rtc_getalarm, 490 .set_alarm = sun6i_rtc_setalarm, 491 .alarm_irq_enable = sun6i_rtc_alarm_irq_enable 492}; 493 494static int sun6i_rtc_probe(struct platform_device *pdev) 495{ |
366 struct sun6i_rtc_dev *chip; 367 struct resource *res; | 496 struct sun6i_rtc_dev *chip = sun6i_rtc; |
368 int ret; 369 | 497 int ret; 498 |
370 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); | |
371 if (!chip) | 499 if (!chip) |
372 return -ENOMEM; 373 spin_lock_init(&chip->lock); | 500 return -ENODEV; |
374 375 platform_set_drvdata(pdev, chip); 376 chip->dev = &pdev->dev; 377 | 501 502 platform_set_drvdata(pdev, chip); 503 chip->dev = &pdev->dev; 504 |
378 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 379 chip->base = devm_ioremap_resource(&pdev->dev, res); 380 if (IS_ERR(chip->base)) 381 return PTR_ERR(chip->base); 382 | |
383 chip->irq = platform_get_irq(pdev, 0); 384 if (chip->irq < 0) { 385 dev_err(&pdev->dev, "No IRQ resource\n"); 386 return chip->irq; 387 } 388 389 ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, 390 0, dev_name(&pdev->dev), chip); --- 23 unchanged lines hidden (view full) --- 414 415 /* clear week alarm pending interrupts */ 416 writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, 417 chip->base + SUN6I_ALRM1_IRQ_STA); 418 419 /* disable alarm wakeup */ 420 writel(0, chip->base + SUN6I_ALARM_CONFIG); 421 | 505 chip->irq = platform_get_irq(pdev, 0); 506 if (chip->irq < 0) { 507 dev_err(&pdev->dev, "No IRQ resource\n"); 508 return chip->irq; 509 } 510 511 ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, 512 0, dev_name(&pdev->dev), chip); --- 23 unchanged lines hidden (view full) --- 536 537 /* clear week alarm pending interrupts */ 538 writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, 539 chip->base + SUN6I_ALRM1_IRQ_STA); 540 541 /* disable alarm wakeup */ 542 writel(0, chip->base + SUN6I_ALARM_CONFIG); 543 |
422 /* switch to the external, more precise, oscillator */ 423 writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC, 424 chip->base + SUN6I_LOSC_CTRL); | 544 clk_prepare_enable(chip->losc); |
425 426 chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, 427 &sun6i_rtc_ops, THIS_MODULE); 428 if (IS_ERR(chip->rtc)) { 429 dev_err(&pdev->dev, "unable to register device\n"); 430 return PTR_ERR(chip->rtc); 431 } 432 --- 29 unchanged lines hidden --- | 545 546 chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, 547 &sun6i_rtc_ops, THIS_MODULE); 548 if (IS_ERR(chip->rtc)) { 549 dev_err(&pdev->dev, "unable to register device\n"); 550 return PTR_ERR(chip->rtc); 551 } 552 --- 29 unchanged lines hidden --- |