diff options
35 files changed, 1956 insertions, 376 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-bq32k b/Documentation/ABI/testing/sysfs-bus-i2c-devices-bq32k new file mode 100644 index 000000000000..398b258fb770 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-bq32k | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | What: /sys/bus/i2c/devices/.../trickle_charge_bypass | ||
| 2 | Date: Jan 2017 | ||
| 3 | KernelVersion: 4.11 | ||
| 4 | Contact: Enric Balletbo i Serra <eballetbo@gmail.com> | ||
| 5 | Description: Attribute for enable/disable the trickle charge bypass | ||
| 6 | The trickle_charge_bypass attribute allows the userspace to | ||
| 7 | enable/disable the Trickle charge FET bypass. | ||
diff --git a/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt b/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt index 2eb9d4ee7dc0..c3c9a1226f9a 100644 --- a/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt | |||
| @@ -1,9 +1,11 @@ | |||
| 1 | * Real Time Clock of the Armada 38x SoCs | 1 | * Real Time Clock of the Armada 38x/7K/8K SoCs |
| 2 | 2 | ||
| 3 | RTC controller for the Armada 38x SoCs | 3 | RTC controller for the Armada 38x, 7K and 8K SoCs |
| 4 | 4 | ||
| 5 | Required properties: | 5 | Required properties: |
| 6 | - compatible : Should be "marvell,armada-380-rtc" | 6 | - compatible : Should be one of the following: |
| 7 | "marvell,armada-380-rtc" for Armada 38x SoC | ||
| 8 | "marvell,armada-8k-rtc" for Aramda 7K/8K SoCs | ||
| 7 | - reg: a list of base address and size pairs, one for each entry in | 9 | - reg: a list of base address and size pairs, one for each entry in |
| 8 | reg-names | 10 | reg-names |
| 9 | - reg names: should contain: | 11 | - reg names: should contain: |
diff --git a/Documentation/devicetree/bindings/rtc/cortina,gemini.txt b/Documentation/devicetree/bindings/rtc/cortina,gemini.txt new file mode 100644 index 000000000000..4ce4e794ddbb --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/cortina,gemini.txt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | * Cortina Systems Gemini RTC | ||
| 2 | |||
| 3 | Gemini SoC real-time clock. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | - compatible : Should be "cortina,gemini-rtc" | ||
| 7 | |||
| 8 | Examples: | ||
| 9 | |||
| 10 | rtc@45000000 { | ||
| 11 | compatible = "cortina,gemini-rtc"; | ||
| 12 | reg = <0x45000000 0x100>; | ||
| 13 | interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; | ||
| 14 | }; | ||
diff --git a/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt index c9d80d7da141..323cf26374cb 100644 --- a/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt | |||
| @@ -8,10 +8,13 @@ Required properties: | |||
| 8 | region. | 8 | region. |
| 9 | - interrupts: rtc alarm interrupt | 9 | - interrupts: rtc alarm interrupt |
| 10 | 10 | ||
| 11 | Optional properties: | ||
| 12 | - interrupts: dryice security violation interrupt | ||
| 13 | |||
| 11 | Example: | 14 | Example: |
| 12 | 15 | ||
| 13 | rtc@80056000 { | 16 | rtc@80056000 { |
| 14 | compatible = "fsl,imx53-rtc", "fsl,imx25-rtc"; | 17 | compatible = "fsl,imx53-rtc", "fsl,imx25-rtc"; |
| 15 | reg = <0x80056000 2000>; | 18 | reg = <0x80056000 2000>; |
| 16 | interrupts = <29>; | 19 | interrupts = <29 56>; |
| 17 | }; | 20 | }; |
diff --git a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt index 1ad4c1c2b3b3..85be53a42180 100644 --- a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt +++ b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | * Maxim DS3231 Real Time Clock | 1 | * Maxim DS3231 Real Time Clock |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst | 4 | - compatible: Should contain "maxim,ds3231". |
| 5 | - reg: I2C address for chip. | ||
| 5 | 6 | ||
| 6 | Optional property: | 7 | Optional property: |
| 7 | - #clock-cells: Should be 1. | 8 | - #clock-cells: Should be 1. |
diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt index 086c998c5561..36984acbb383 100644 --- a/Documentation/devicetree/bindings/rtc/pcf8563.txt +++ b/Documentation/devicetree/bindings/rtc/pcf8563.txt | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | Philips PCF8563/Epson RTC8564 Real Time Clock | 3 | Philips PCF8563/Epson RTC8564 Real Time Clock |
| 4 | 4 | ||
| 5 | Required properties: | 5 | Required properties: |
| 6 | see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst | 6 | - compatible: Should contain "nxp,pcf8563". |
| 7 | - reg: I2C address for chip. | ||
| 7 | 8 | ||
| 8 | Optional property: | 9 | Optional property: |
| 9 | - #clock-cells: Should be 0. | 10 | - #clock-cells: Should be 0. |
diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt new file mode 100644 index 000000000000..e2837b951237 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | STM32 Real Time Clock | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "st,stm32-rtc". | ||
| 5 | - reg: address range of rtc register set. | ||
| 6 | - clocks: reference to the clock entry ck_rtc. | ||
| 7 | - interrupt-parent: phandle for the interrupt controller. | ||
| 8 | - interrupts: rtc alarm interrupt. | ||
| 9 | - st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain | ||
| 10 | (RTC registers) write protection. | ||
| 11 | |||
| 12 | Optional properties (to override default ck_rtc parent clock): | ||
| 13 | - assigned-clocks: reference to the ck_rtc clock entry. | ||
| 14 | - assigned-clock-parents: phandle of the new parent clock of ck_rtc. | ||
| 15 | |||
| 16 | Example: | ||
| 17 | |||
| 18 | rtc: rtc@40002800 { | ||
| 19 | compatible = "st,stm32-rtc"; | ||
| 20 | reg = <0x40002800 0x400>; | ||
| 21 | clocks = <&rcc 1 CLK_RTC>; | ||
| 22 | assigned-clocks = <&rcc 1 CLK_RTC>; | ||
| 23 | assigned-clock-parents = <&rcc 1 CLK_LSE>; | ||
| 24 | interrupt-parent = <&exti>; | ||
| 25 | interrupts = <17 1>; | ||
| 26 | st,syscfg = <&pwrcfg>; | ||
| 27 | }; | ||
diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt index f007e428a1ab..945934918b71 100644 --- a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt | |||
| @@ -8,10 +8,20 @@ Required properties: | |||
| 8 | memory mapped region. | 8 | memory mapped region. |
| 9 | - interrupts : IRQ lines for the RTC alarm 0 and alarm 1, in that order. | 9 | - interrupts : IRQ lines for the RTC alarm 0 and alarm 1, in that order. |
| 10 | 10 | ||
| 11 | Required properties for new device trees | ||
| 12 | - clocks : phandle to the 32kHz external oscillator | ||
| 13 | - clock-output-names : name of the LOSC clock created | ||
| 14 | - #clock-cells : must be equals to 1. The RTC provides two clocks: the | ||
| 15 | LOSC and its external output, with index 0 and 1 | ||
| 16 | respectively. | ||
| 17 | |||
| 11 | Example: | 18 | Example: |
| 12 | 19 | ||
| 13 | rtc: rtc@01f00000 { | 20 | rtc: rtc@01f00000 { |
| 14 | compatible = "allwinner,sun6i-a31-rtc"; | 21 | compatible = "allwinner,sun6i-a31-rtc"; |
| 15 | reg = <0x01f00000 0x54>; | 22 | reg = <0x01f00000 0x54>; |
| 16 | interrupts = <0 40 4>, <0 41 4>; | 23 | interrupts = <0 40 4>, <0 41 4>; |
| 24 | clock-output-names = "osc32k"; | ||
| 25 | clocks = <&ext_osc32k>; | ||
| 26 | #clock-cells = <1>; | ||
| 17 | }; | 27 | }; |
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 3b39ea353d30..8a5b6f059498 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
| 19 | #include <linux/platform_data/rtc-m48t86.h> | ||
| 20 | #include <linux/mtd/nand.h> | 19 | #include <linux/mtd/nand.h> |
| 21 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
| 22 | 21 | ||
| @@ -45,16 +44,6 @@ static struct map_desc ts72xx_io_desc[] __initdata = { | |||
| 45 | .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), | 44 | .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), |
| 46 | .length = TS72XX_OPTIONS2_SIZE, | 45 | .length = TS72XX_OPTIONS2_SIZE, |
| 47 | .type = MT_DEVICE, | 46 | .type = MT_DEVICE, |
| 48 | }, { | ||
| 49 | .virtual = (unsigned long)TS72XX_RTC_INDEX_VIRT_BASE, | ||
| 50 | .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE), | ||
| 51 | .length = TS72XX_RTC_INDEX_SIZE, | ||
| 52 | .type = MT_DEVICE, | ||
| 53 | }, { | ||
| 54 | .virtual = (unsigned long)TS72XX_RTC_DATA_VIRT_BASE, | ||
| 55 | .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE), | ||
| 56 | .length = TS72XX_RTC_DATA_SIZE, | ||
| 57 | .type = MT_DEVICE, | ||
| 58 | } | 47 | } |
| 59 | }; | 48 | }; |
| 60 | 49 | ||
| @@ -179,31 +168,22 @@ static void __init ts72xx_register_flash(void) | |||
| 179 | } | 168 | } |
| 180 | } | 169 | } |
| 181 | 170 | ||
| 171 | /************************************************************************* | ||
| 172 | * RTC M48T86 | ||
| 173 | *************************************************************************/ | ||
| 174 | #define TS72XX_RTC_INDEX_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x00800000) | ||
| 175 | #define TS72XX_RTC_DATA_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x01700000) | ||
| 182 | 176 | ||
| 183 | static unsigned char ts72xx_rtc_readbyte(unsigned long addr) | 177 | static struct resource ts72xx_rtc_resources[] = { |
| 184 | { | 178 | DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01), |
| 185 | __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); | 179 | DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01), |
| 186 | return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr) | ||
| 190 | { | ||
| 191 | __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); | ||
| 192 | __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE); | ||
| 193 | } | ||
| 194 | |||
| 195 | static struct m48t86_ops ts72xx_rtc_ops = { | ||
| 196 | .readbyte = ts72xx_rtc_readbyte, | ||
| 197 | .writebyte = ts72xx_rtc_writebyte, | ||
| 198 | }; | 180 | }; |
| 199 | 181 | ||
| 200 | static struct platform_device ts72xx_rtc_device = { | 182 | static struct platform_device ts72xx_rtc_device = { |
| 201 | .name = "rtc-m48t86", | 183 | .name = "rtc-m48t86", |
| 202 | .id = -1, | 184 | .id = -1, |
| 203 | .dev = { | 185 | .resource = ts72xx_rtc_resources, |
| 204 | .platform_data = &ts72xx_rtc_ops, | 186 | .num_resources = ARRAY_SIZE(ts72xx_rtc_resources), |
| 205 | }, | ||
| 206 | .num_resources = 0, | ||
| 207 | }; | 187 | }; |
| 208 | 188 | ||
| 209 | static struct resource ts72xx_wdt_resources[] = { | 189 | static struct resource ts72xx_wdt_resources[] = { |
diff --git a/arch/arm/mach-ep93xx/ts72xx.h b/arch/arm/mach-ep93xx/ts72xx.h index 071feaa30adc..2255ba29fdd6 100644 --- a/arch/arm/mach-ep93xx/ts72xx.h +++ b/arch/arm/mach-ep93xx/ts72xx.h | |||
| @@ -9,8 +9,6 @@ | |||
| 9 | * febff000 22000000 4K model number register (bits 0-2) | 9 | * febff000 22000000 4K model number register (bits 0-2) |
| 10 | * febfe000 22400000 4K options register | 10 | * febfe000 22400000 4K options register |
| 11 | * febfd000 22800000 4K options register #2 | 11 | * febfd000 22800000 4K options register #2 |
| 12 | * febf9000 10800000 4K TS-5620 RTC index register | ||
| 13 | * febf8000 11700000 4K TS-5620 RTC data register | ||
| 14 | */ | 12 | */ |
| 15 | 13 | ||
| 16 | #define TS72XX_MODEL_PHYS_BASE 0x22000000 | 14 | #define TS72XX_MODEL_PHYS_BASE 0x22000000 |
| @@ -40,15 +38,6 @@ | |||
| 40 | #define TS72XX_OPTIONS2_TS9420 0x04 | 38 | #define TS72XX_OPTIONS2_TS9420 0x04 |
| 41 | #define TS72XX_OPTIONS2_TS9420_BOOT 0x02 | 39 | #define TS72XX_OPTIONS2_TS9420_BOOT 0x02 |
| 42 | 40 | ||
| 43 | |||
| 44 | #define TS72XX_RTC_INDEX_VIRT_BASE IOMEM(0xfebf9000) | ||
| 45 | #define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000 | ||
| 46 | #define TS72XX_RTC_INDEX_SIZE 0x00001000 | ||
| 47 | |||
| 48 | #define TS72XX_RTC_DATA_VIRT_BASE IOMEM(0xfebf8000) | ||
| 49 | #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 | ||
| 50 | #define TS72XX_RTC_DATA_SIZE 0x00001000 | ||
| 51 | |||
| 52 | #define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000 | 41 | #define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000 |
| 53 | #define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000 | 42 | #define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000 |
| 54 | 43 | ||
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 8d597267d0c4..7ef80a8304c0 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/mv643xx_eth.h> | 17 | #include <linux/mv643xx_eth.h> |
| 18 | #include <linux/ata_platform.h> | 18 | #include <linux/ata_platform.h> |
| 19 | #include <linux/platform_data/rtc-m48t86.h> | ||
| 20 | #include <linux/mtd/nand.h> | 19 | #include <linux/mtd/nand.h> |
| 21 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
| 22 | #include <linux/timeriomem-rng.h> | 21 | #include <linux/timeriomem-rng.h> |
| @@ -80,79 +79,38 @@ static struct mv_sata_platform_data ts78xx_sata_data = { | |||
| 80 | /***************************************************************************** | 79 | /***************************************************************************** |
| 81 | * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c | 80 | * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c |
| 82 | ****************************************************************************/ | 81 | ****************************************************************************/ |
| 83 | #define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x808) | 82 | #define TS_RTC_CTRL (TS78XX_FPGA_REGS_PHYS_BASE + 0x808) |
| 84 | #define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE + 0x80c) | 83 | #define TS_RTC_DATA (TS78XX_FPGA_REGS_PHYS_BASE + 0x80c) |
| 85 | 84 | ||
| 86 | static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr) | 85 | static struct resource ts78xx_ts_rtc_resources[] = { |
| 87 | { | 86 | DEFINE_RES_MEM(TS_RTC_CTRL, 0x01), |
| 88 | writeb(addr, TS_RTC_CTRL); | 87 | DEFINE_RES_MEM(TS_RTC_DATA, 0x01), |
| 89 | return readb(TS_RTC_DATA); | ||
| 90 | } | ||
| 91 | |||
| 92 | static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr) | ||
| 93 | { | ||
| 94 | writeb(addr, TS_RTC_CTRL); | ||
| 95 | writeb(value, TS_RTC_DATA); | ||
| 96 | } | ||
| 97 | |||
| 98 | static struct m48t86_ops ts78xx_ts_rtc_ops = { | ||
| 99 | .readbyte = ts78xx_ts_rtc_readbyte, | ||
| 100 | .writebyte = ts78xx_ts_rtc_writebyte, | ||
| 101 | }; | 88 | }; |
| 102 | 89 | ||
| 103 | static struct platform_device ts78xx_ts_rtc_device = { | 90 | static struct platform_device ts78xx_ts_rtc_device = { |
| 104 | .name = "rtc-m48t86", | 91 | .name = "rtc-m48t86", |
| 105 | .id = -1, | 92 | .id = -1, |
| 106 | .dev = { | 93 | .resource = ts78xx_ts_rtc_resources, |
| 107 | .platform_data = &ts78xx_ts_rtc_ops, | 94 | .num_resources = ARRAY_SIZE(ts78xx_ts_rtc_resources), |
| 108 | }, | ||
| 109 | .num_resources = 0, | ||
| 110 | }; | 95 | }; |
| 111 | 96 | ||
| 112 | /* | ||
| 113 | * TS uses some of the user storage space on the RTC chip so see if it is | ||
| 114 | * present; as it's an optional feature at purchase time and not all boards | ||
| 115 | * will have it present | ||
| 116 | * | ||
| 117 | * I've used the method TS use in their rtc7800.c example for the detection | ||
| 118 | * | ||
| 119 | * TODO: track down a guinea pig without an RTC to see if we can work out a | ||
| 120 | * better RTC detection routine | ||
| 121 | */ | ||
| 122 | static int ts78xx_ts_rtc_load(void) | 97 | static int ts78xx_ts_rtc_load(void) |
| 123 | { | 98 | { |
| 124 | int rc; | 99 | int rc; |
| 125 | unsigned char tmp_rtc0, tmp_rtc1; | 100 | |
| 126 | 101 | if (ts78xx_fpga.supports.ts_rtc.init == 0) { | |
| 127 | tmp_rtc0 = ts78xx_ts_rtc_readbyte(126); | 102 | rc = platform_device_register(&ts78xx_ts_rtc_device); |
| 128 | tmp_rtc1 = ts78xx_ts_rtc_readbyte(127); | 103 | if (!rc) |
| 129 | 104 | ts78xx_fpga.supports.ts_rtc.init = 1; | |
| 130 | ts78xx_ts_rtc_writebyte(0x00, 126); | 105 | } else { |
| 131 | ts78xx_ts_rtc_writebyte(0x55, 127); | 106 | rc = platform_device_add(&ts78xx_ts_rtc_device); |
| 132 | if (ts78xx_ts_rtc_readbyte(127) == 0x55) { | ||
| 133 | ts78xx_ts_rtc_writebyte(0xaa, 127); | ||
| 134 | if (ts78xx_ts_rtc_readbyte(127) == 0xaa | ||
| 135 | && ts78xx_ts_rtc_readbyte(126) == 0x00) { | ||
| 136 | ts78xx_ts_rtc_writebyte(tmp_rtc0, 126); | ||
| 137 | ts78xx_ts_rtc_writebyte(tmp_rtc1, 127); | ||
| 138 | |||
| 139 | if (ts78xx_fpga.supports.ts_rtc.init == 0) { | ||
| 140 | rc = platform_device_register(&ts78xx_ts_rtc_device); | ||
| 141 | if (!rc) | ||
| 142 | ts78xx_fpga.supports.ts_rtc.init = 1; | ||
| 143 | } else | ||
| 144 | rc = platform_device_add(&ts78xx_ts_rtc_device); | ||
| 145 | |||
| 146 | if (rc) | ||
| 147 | pr_info("RTC could not be registered: %d\n", | ||
| 148 | rc); | ||
| 149 | return rc; | ||
| 150 | } | ||
| 151 | } | 107 | } |
| 152 | 108 | ||
| 153 | pr_info("RTC not found\n"); | 109 | if (rc) |
| 154 | return -ENODEV; | 110 | pr_info("RTC could not be registered: %d\n", rc); |
| 155 | }; | 111 | |
| 112 | return rc; | ||
| 113 | } | ||
| 156 | 114 | ||
| 157 | static void ts78xx_ts_rtc_unload(void) | 115 | static void ts78xx_ts_rtc_unload(void) |
| 158 | { | 116 | { |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5dc673dc9487..ee1b0e9dde79 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -1434,9 +1434,10 @@ config RTC_DRV_SUN4V | |||
| 1434 | based RTC on SUN4V systems. | 1434 | based RTC on SUN4V systems. |
| 1435 | 1435 | ||
| 1436 | config RTC_DRV_SUN6I | 1436 | config RTC_DRV_SUN6I |
| 1437 | tristate "Allwinner A31 RTC" | 1437 | bool "Allwinner A31 RTC" |
| 1438 | default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST | 1438 | default MACH_SUN6I || MACH_SUN8I |
| 1439 | depends on ARCH_SUNXI | 1439 | depends on COMMON_CLK |
| 1440 | depends on ARCH_SUNXI || COMPILE_TEST | ||
| 1440 | help | 1441 | help |
| 1441 | If you say Y here you will get support for the RTC found in | 1442 | If you say Y here you will get support for the RTC found in |
| 1442 | some Allwinner SoCs like the A31 or the A64. | 1443 | some Allwinner SoCs like the A31 or the A64. |
| @@ -1719,6 +1720,17 @@ config RTC_DRV_R7301 | |||
| 1719 | This driver can also be built as a module. If so, the module | 1720 | This driver can also be built as a module. If so, the module |
| 1720 | will be called rtc-r7301. | 1721 | will be called rtc-r7301. |
| 1721 | 1722 | ||
| 1723 | config RTC_DRV_STM32 | ||
| 1724 | tristate "STM32 RTC" | ||
| 1725 | select REGMAP_MMIO | ||
| 1726 | depends on ARCH_STM32 || COMPILE_TEST | ||
| 1727 | help | ||
| 1728 | If you say yes here you get support for the STM32 On-Chip | ||
| 1729 | Real Time Clock. | ||
| 1730 | |||
| 1731 | This driver can also be built as a module, if so, the module | ||
| 1732 | will be called "rtc-stm32". | ||
| 1733 | |||
| 1722 | comment "HID Sensor RTC drivers" | 1734 | comment "HID Sensor RTC drivers" |
| 1723 | 1735 | ||
| 1724 | config RTC_DRV_HID_SENSOR_TIME | 1736 | config RTC_DRV_HID_SENSOR_TIME |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index f13ab1c5c222..f07297b1460a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -145,6 +145,7 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o | |||
| 145 | obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o | 145 | obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o |
| 146 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | 146 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o |
| 147 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | 147 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o |
| 148 | obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o | ||
| 148 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o | 149 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o |
| 149 | obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o | 150 | obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o |
| 150 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | 151 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o |
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 9a3f2a6f512e..21f355c37eab 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
| 19 | #include <linux/of_device.h> | ||
| 19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 20 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
| 21 | 22 | ||
| @@ -23,17 +24,48 @@ | |||
| 23 | #define RTC_STATUS_ALARM1 BIT(0) | 24 | #define RTC_STATUS_ALARM1 BIT(0) |
| 24 | #define RTC_STATUS_ALARM2 BIT(1) | 25 | #define RTC_STATUS_ALARM2 BIT(1) |
| 25 | #define RTC_IRQ1_CONF 0x4 | 26 | #define RTC_IRQ1_CONF 0x4 |
| 26 | #define RTC_IRQ1_AL_EN BIT(0) | 27 | #define RTC_IRQ2_CONF 0x8 |
| 27 | #define RTC_IRQ1_FREQ_EN BIT(1) | 28 | #define RTC_IRQ_AL_EN BIT(0) |
| 28 | #define RTC_IRQ1_FREQ_1HZ BIT(2) | 29 | #define RTC_IRQ_FREQ_EN BIT(1) |
| 30 | #define RTC_IRQ_FREQ_1HZ BIT(2) | ||
| 31 | |||
| 29 | #define RTC_TIME 0xC | 32 | #define RTC_TIME 0xC |
| 30 | #define RTC_ALARM1 0x10 | 33 | #define RTC_ALARM1 0x10 |
| 31 | 34 | #define RTC_ALARM2 0x14 | |
| 32 | #define SOC_RTC_INTERRUPT 0x8 | 35 | |
| 33 | #define SOC_RTC_ALARM1 BIT(0) | 36 | /* Armada38x SoC registers */ |
| 34 | #define SOC_RTC_ALARM2 BIT(1) | 37 | #define RTC_38X_BRIDGE_TIMING_CTL 0x0 |
| 35 | #define SOC_RTC_ALARM1_MASK BIT(2) | 38 | #define RTC_38X_PERIOD_OFFS 0 |
| 36 | #define SOC_RTC_ALARM2_MASK BIT(3) | 39 | #define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS) |
| 40 | #define RTC_38X_READ_DELAY_OFFS 26 | ||
| 41 | #define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS) | ||
| 42 | |||
| 43 | /* Armada 7K/8K registers */ | ||
| 44 | #define RTC_8K_BRIDGE_TIMING_CTL0 0x0 | ||
| 45 | #define RTC_8K_WRCLK_PERIOD_OFFS 0 | ||
| 46 | #define RTC_8K_WRCLK_PERIOD_MASK (0xFFFF << RTC_8K_WRCLK_PERIOD_OFFS) | ||
| 47 | #define RTC_8K_WRCLK_SETUP_OFFS 16 | ||
| 48 | #define RTC_8K_WRCLK_SETUP_MASK (0xFFFF << RTC_8K_WRCLK_SETUP_OFFS) | ||
| 49 | #define RTC_8K_BRIDGE_TIMING_CTL1 0x4 | ||
| 50 | #define RTC_8K_READ_DELAY_OFFS 0 | ||
| 51 | #define RTC_8K_READ_DELAY_MASK (0xFFFF << RTC_8K_READ_DELAY_OFFS) | ||
| 52 | |||
| 53 | #define RTC_8K_ISR 0x10 | ||
| 54 | #define RTC_8K_IMR 0x14 | ||
| 55 | #define RTC_8K_ALARM2 BIT(0) | ||
| 56 | |||
| 57 | #define SOC_RTC_INTERRUPT 0x8 | ||
| 58 | #define SOC_RTC_ALARM1 BIT(0) | ||
| 59 | #define SOC_RTC_ALARM2 BIT(1) | ||
| 60 | #define SOC_RTC_ALARM1_MASK BIT(2) | ||
| 61 | #define SOC_RTC_ALARM2_MASK BIT(3) | ||
| 62 | |||
| 63 | #define SAMPLE_NR 100 | ||
| 64 | |||
| 65 | struct value_to_freq { | ||
| 66 | u32 value; | ||
| 67 | u8 freq; | ||
| 68 | }; | ||
| 37 | 69 | ||
| 38 | struct armada38x_rtc { | 70 | struct armada38x_rtc { |
| 39 | struct rtc_device *rtc_dev; | 71 | struct rtc_device *rtc_dev; |
| @@ -41,38 +73,153 @@ struct armada38x_rtc { | |||
| 41 | void __iomem *regs_soc; | 73 | void __iomem *regs_soc; |
| 42 | spinlock_t lock; | 74 | spinlock_t lock; |
| 43 | int irq; | 75 | int irq; |
| 76 | struct value_to_freq *val_to_freq; | ||
| 77 | struct armada38x_rtc_data *data; | ||
| 78 | }; | ||
| 79 | |||
| 80 | #define ALARM1 0 | ||
| 81 | #define ALARM2 1 | ||
| 82 | |||
| 83 | #define ALARM_REG(base, alarm) ((base) + (alarm) * sizeof(u32)) | ||
| 84 | |||
| 85 | struct armada38x_rtc_data { | ||
| 86 | /* Initialize the RTC-MBUS bridge timing */ | ||
| 87 | void (*update_mbus_timing)(struct armada38x_rtc *rtc); | ||
| 88 | u32 (*read_rtc_reg)(struct armada38x_rtc *rtc, u8 rtc_reg); | ||
| 89 | void (*clear_isr)(struct armada38x_rtc *rtc); | ||
| 90 | void (*unmask_interrupt)(struct armada38x_rtc *rtc); | ||
| 91 | u32 alarm; | ||
| 44 | }; | 92 | }; |
| 45 | 93 | ||
| 46 | /* | 94 | /* |
| 47 | * According to the datasheet, the OS should wait 5us after every | 95 | * According to the datasheet, the OS should wait 5us after every |
| 48 | * register write to the RTC hard macro so that the required update | 96 | * register write to the RTC hard macro so that the required update |
| 49 | * can occur without holding off the system bus | 97 | * can occur without holding off the system bus |
| 98 | * According to errata RES-3124064, Write to any RTC register | ||
| 99 | * may fail. As a workaround, before writing to RTC | ||
| 100 | * register, issue a dummy write of 0x0 twice to RTC Status | ||
| 101 | * register. | ||
| 50 | */ | 102 | */ |
| 103 | |||
| 51 | static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset) | 104 | static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset) |
| 52 | { | 105 | { |
| 106 | writel(0, rtc->regs + RTC_STATUS); | ||
| 107 | writel(0, rtc->regs + RTC_STATUS); | ||
| 53 | writel(val, rtc->regs + offset); | 108 | writel(val, rtc->regs + offset); |
| 54 | udelay(5); | 109 | udelay(5); |
| 55 | } | 110 | } |
| 56 | 111 | ||
| 112 | /* Update RTC-MBUS bridge timing parameters */ | ||
| 113 | static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc) | ||
| 114 | { | ||
| 115 | u32 reg; | ||
| 116 | |||
| 117 | reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); | ||
| 118 | reg &= ~RTC_38X_PERIOD_MASK; | ||
| 119 | reg |= 0x3FF << RTC_38X_PERIOD_OFFS; /* Maximum value */ | ||
| 120 | reg &= ~RTC_38X_READ_DELAY_MASK; | ||
| 121 | reg |= 0x1F << RTC_38X_READ_DELAY_OFFS; /* Maximum value */ | ||
| 122 | writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); | ||
| 123 | } | ||
| 124 | |||
| 125 | static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc) | ||
| 126 | { | ||
| 127 | u32 reg; | ||
| 128 | |||
| 129 | reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0); | ||
| 130 | reg &= ~RTC_8K_WRCLK_PERIOD_MASK; | ||
| 131 | reg |= 0x3FF << RTC_8K_WRCLK_PERIOD_OFFS; | ||
| 132 | reg &= ~RTC_8K_WRCLK_SETUP_MASK; | ||
| 133 | reg |= 0x29 << RTC_8K_WRCLK_SETUP_OFFS; | ||
| 134 | writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL0); | ||
| 135 | |||
| 136 | reg = readl(rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1); | ||
| 137 | reg &= ~RTC_8K_READ_DELAY_MASK; | ||
| 138 | reg |= 0x3F << RTC_8K_READ_DELAY_OFFS; | ||
| 139 | writel(reg, rtc->regs_soc + RTC_8K_BRIDGE_TIMING_CTL1); | ||
| 140 | } | ||
| 141 | |||
| 142 | static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg) | ||
| 143 | { | ||
| 144 | return readl(rtc->regs + rtc_reg); | ||
| 145 | } | ||
| 146 | |||
| 147 | static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg) | ||
| 148 | { | ||
| 149 | int i, index_max = 0, max = 0; | ||
| 150 | |||
| 151 | for (i = 0; i < SAMPLE_NR; i++) { | ||
| 152 | rtc->val_to_freq[i].value = readl(rtc->regs + rtc_reg); | ||
| 153 | rtc->val_to_freq[i].freq = 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | for (i = 0; i < SAMPLE_NR; i++) { | ||
| 157 | int j = 0; | ||
| 158 | u32 value = rtc->val_to_freq[i].value; | ||
| 159 | |||
| 160 | while (rtc->val_to_freq[j].freq) { | ||
| 161 | if (rtc->val_to_freq[j].value == value) { | ||
| 162 | rtc->val_to_freq[j].freq++; | ||
| 163 | break; | ||
| 164 | } | ||
| 165 | j++; | ||
| 166 | } | ||
| 167 | |||
| 168 | if (!rtc->val_to_freq[j].freq) { | ||
| 169 | rtc->val_to_freq[j].value = value; | ||
| 170 | rtc->val_to_freq[j].freq = 1; | ||
| 171 | } | ||
| 172 | |||
| 173 | if (rtc->val_to_freq[j].freq > max) { | ||
| 174 | index_max = j; | ||
| 175 | max = rtc->val_to_freq[j].freq; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * If a value already has half of the sample this is the most | ||
| 180 | * frequent one and we can stop the research right now | ||
| 181 | */ | ||
| 182 | if (max > SAMPLE_NR / 2) | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | return rtc->val_to_freq[index_max].value; | ||
| 187 | } | ||
| 188 | |||
| 189 | static void armada38x_clear_isr(struct armada38x_rtc *rtc) | ||
| 190 | { | ||
| 191 | u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); | ||
| 192 | |||
| 193 | writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc) | ||
| 197 | { | ||
| 198 | u32 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); | ||
| 199 | |||
| 200 | writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT); | ||
| 201 | } | ||
| 202 | |||
| 203 | static void armada8k_clear_isr(struct armada38x_rtc *rtc) | ||
| 204 | { | ||
| 205 | writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR); | ||
| 206 | } | ||
| 207 | |||
| 208 | static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc) | ||
| 209 | { | ||
| 210 | writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_IMR); | ||
| 211 | } | ||
| 212 | |||
| 57 | static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) | 213 | static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 58 | { | 214 | { |
| 59 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); | 215 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); |
| 60 | unsigned long time, time_check, flags; | 216 | unsigned long time, flags; |
| 61 | 217 | ||
| 62 | spin_lock_irqsave(&rtc->lock, flags); | 218 | spin_lock_irqsave(&rtc->lock, flags); |
| 63 | time = readl(rtc->regs + RTC_TIME); | 219 | time = rtc->data->read_rtc_reg(rtc, RTC_TIME); |
| 64 | /* | ||
| 65 | * WA for failing time set attempts. As stated in HW ERRATA if | ||
| 66 | * more than one second between two time reads is detected | ||
| 67 | * then read once again. | ||
| 68 | */ | ||
| 69 | time_check = readl(rtc->regs + RTC_TIME); | ||
| 70 | if ((time_check - time) > 1) | ||
| 71 | time_check = readl(rtc->regs + RTC_TIME); | ||
| 72 | |||
| 73 | spin_unlock_irqrestore(&rtc->lock, flags); | 220 | spin_unlock_irqrestore(&rtc->lock, flags); |
| 74 | 221 | ||
| 75 | rtc_time_to_tm(time_check, tm); | 222 | rtc_time_to_tm(time, tm); |
| 76 | 223 | ||
| 77 | return 0; | 224 | return 0; |
| 78 | } | 225 | } |
| @@ -87,16 +234,9 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 87 | 234 | ||
| 88 | if (ret) | 235 | if (ret) |
| 89 | goto out; | 236 | goto out; |
| 90 | /* | 237 | |
| 91 | * According to errata FE-3124064, Write to RTC TIME register | ||
| 92 | * may fail. As a workaround, after writing to RTC TIME | ||
| 93 | * register, issue a dummy write of 0x0 twice to RTC Status | ||
| 94 | * register. | ||
| 95 | */ | ||
| 96 | spin_lock_irqsave(&rtc->lock, flags); | 238 | spin_lock_irqsave(&rtc->lock, flags); |
| 97 | rtc_delayed_write(time, rtc, RTC_TIME); | 239 | rtc_delayed_write(time, rtc, RTC_TIME); |
| 98 | rtc_delayed_write(0, rtc, RTC_STATUS); | ||
| 99 | rtc_delayed_write(0, rtc, RTC_STATUS); | ||
| 100 | spin_unlock_irqrestore(&rtc->lock, flags); | 240 | spin_unlock_irqrestore(&rtc->lock, flags); |
| 101 | 241 | ||
| 102 | out: | 242 | out: |
| @@ -107,12 +247,14 @@ static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 107 | { | 247 | { |
| 108 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); | 248 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); |
| 109 | unsigned long time, flags; | 249 | unsigned long time, flags; |
| 250 | u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm); | ||
| 251 | u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); | ||
| 110 | u32 val; | 252 | u32 val; |
| 111 | 253 | ||
| 112 | spin_lock_irqsave(&rtc->lock, flags); | 254 | spin_lock_irqsave(&rtc->lock, flags); |
| 113 | 255 | ||
| 114 | time = readl(rtc->regs + RTC_ALARM1); | 256 | time = rtc->data->read_rtc_reg(rtc, reg); |
| 115 | val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN; | 257 | val = rtc->data->read_rtc_reg(rtc, reg_irq) & RTC_IRQ_AL_EN; |
| 116 | 258 | ||
| 117 | spin_unlock_irqrestore(&rtc->lock, flags); | 259 | spin_unlock_irqrestore(&rtc->lock, flags); |
| 118 | 260 | ||
| @@ -125,9 +267,10 @@ static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 125 | static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 267 | static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 126 | { | 268 | { |
| 127 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); | 269 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); |
| 270 | u32 reg = ALARM_REG(RTC_ALARM1, rtc->data->alarm); | ||
| 271 | u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); | ||
| 128 | unsigned long time, flags; | 272 | unsigned long time, flags; |
| 129 | int ret = 0; | 273 | int ret = 0; |
| 130 | u32 val; | ||
| 131 | 274 | ||
| 132 | ret = rtc_tm_to_time(&alrm->time, &time); | 275 | ret = rtc_tm_to_time(&alrm->time, &time); |
| 133 | 276 | ||
| @@ -136,13 +279,11 @@ static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 136 | 279 | ||
| 137 | spin_lock_irqsave(&rtc->lock, flags); | 280 | spin_lock_irqsave(&rtc->lock, flags); |
| 138 | 281 | ||
| 139 | rtc_delayed_write(time, rtc, RTC_ALARM1); | 282 | rtc_delayed_write(time, rtc, reg); |
| 140 | 283 | ||
| 141 | if (alrm->enabled) { | 284 | if (alrm->enabled) { |
| 142 | rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF); | 285 | rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq); |
| 143 | val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); | 286 | rtc->data->unmask_interrupt(rtc); |
| 144 | writel(val | SOC_RTC_ALARM1_MASK, | ||
| 145 | rtc->regs_soc + SOC_RTC_INTERRUPT); | ||
| 146 | } | 287 | } |
| 147 | 288 | ||
| 148 | spin_unlock_irqrestore(&rtc->lock, flags); | 289 | spin_unlock_irqrestore(&rtc->lock, flags); |
| @@ -155,14 +296,15 @@ static int armada38x_rtc_alarm_irq_enable(struct device *dev, | |||
| 155 | unsigned int enabled) | 296 | unsigned int enabled) |
| 156 | { | 297 | { |
| 157 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); | 298 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); |
| 299 | u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); | ||
| 158 | unsigned long flags; | 300 | unsigned long flags; |
| 159 | 301 | ||
| 160 | spin_lock_irqsave(&rtc->lock, flags); | 302 | spin_lock_irqsave(&rtc->lock, flags); |
| 161 | 303 | ||
| 162 | if (enabled) | 304 | if (enabled) |
| 163 | rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF); | 305 | rtc_delayed_write(RTC_IRQ_AL_EN, rtc, reg_irq); |
| 164 | else | 306 | else |
| 165 | rtc_delayed_write(0, rtc, RTC_IRQ1_CONF); | 307 | rtc_delayed_write(0, rtc, reg_irq); |
| 166 | 308 | ||
| 167 | spin_unlock_irqrestore(&rtc->lock, flags); | 309 | spin_unlock_irqrestore(&rtc->lock, flags); |
| 168 | 310 | ||
| @@ -174,24 +316,23 @@ static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data) | |||
| 174 | struct armada38x_rtc *rtc = data; | 316 | struct armada38x_rtc *rtc = data; |
| 175 | u32 val; | 317 | u32 val; |
| 176 | int event = RTC_IRQF | RTC_AF; | 318 | int event = RTC_IRQF | RTC_AF; |
| 319 | u32 reg_irq = ALARM_REG(RTC_IRQ1_CONF, rtc->data->alarm); | ||
| 177 | 320 | ||
| 178 | dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq); | 321 | dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq); |
| 179 | 322 | ||
| 180 | spin_lock(&rtc->lock); | 323 | spin_lock(&rtc->lock); |
| 181 | 324 | ||
| 182 | val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); | 325 | rtc->data->clear_isr(rtc); |
| 183 | 326 | val = rtc->data->read_rtc_reg(rtc, reg_irq); | |
| 184 | writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT); | 327 | /* disable all the interrupts for alarm*/ |
| 185 | val = readl(rtc->regs + RTC_IRQ1_CONF); | 328 | rtc_delayed_write(0, rtc, reg_irq); |
| 186 | /* disable all the interrupts for alarm 1 */ | ||
| 187 | rtc_delayed_write(0, rtc, RTC_IRQ1_CONF); | ||
| 188 | /* Ack the event */ | 329 | /* Ack the event */ |
| 189 | rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS); | 330 | rtc_delayed_write(1 << rtc->data->alarm, rtc, RTC_STATUS); |
| 190 | 331 | ||
| 191 | spin_unlock(&rtc->lock); | 332 | spin_unlock(&rtc->lock); |
| 192 | 333 | ||
| 193 | if (val & RTC_IRQ1_FREQ_EN) { | 334 | if (val & RTC_IRQ_FREQ_EN) { |
| 194 | if (val & RTC_IRQ1_FREQ_1HZ) | 335 | if (val & RTC_IRQ_FREQ_1HZ) |
| 195 | event |= RTC_UF; | 336 | event |= RTC_UF; |
| 196 | else | 337 | else |
| 197 | event |= RTC_PF; | 338 | event |= RTC_PF; |
| @@ -202,7 +343,7 @@ static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data) | |||
| 202 | return IRQ_HANDLED; | 343 | return IRQ_HANDLED; |
| 203 | } | 344 | } |
| 204 | 345 | ||
| 205 | static struct rtc_class_ops armada38x_rtc_ops = { | 346 | static const struct rtc_class_ops armada38x_rtc_ops = { |
| 206 | .read_time = armada38x_rtc_read_time, | 347 | .read_time = armada38x_rtc_read_time, |
| 207 | .set_time = armada38x_rtc_set_time, | 348 | .set_time = armada38x_rtc_set_time, |
| 208 | .read_alarm = armada38x_rtc_read_alarm, | 349 | .read_alarm = armada38x_rtc_read_alarm, |
| @@ -210,17 +351,65 @@ static struct rtc_class_ops armada38x_rtc_ops = { | |||
| 210 | .alarm_irq_enable = armada38x_rtc_alarm_irq_enable, | 351 | .alarm_irq_enable = armada38x_rtc_alarm_irq_enable, |
| 211 | }; | 352 | }; |
| 212 | 353 | ||
| 354 | static const struct rtc_class_ops armada38x_rtc_ops_noirq = { | ||
| 355 | .read_time = armada38x_rtc_read_time, | ||
| 356 | .set_time = armada38x_rtc_set_time, | ||
| 357 | .read_alarm = armada38x_rtc_read_alarm, | ||
| 358 | }; | ||
| 359 | |||
| 360 | static const struct armada38x_rtc_data armada38x_data = { | ||
| 361 | .update_mbus_timing = rtc_update_38x_mbus_timing_params, | ||
| 362 | .read_rtc_reg = read_rtc_register_38x_wa, | ||
| 363 | .clear_isr = armada38x_clear_isr, | ||
| 364 | .unmask_interrupt = armada38x_unmask_interrupt, | ||
| 365 | .alarm = ALARM1, | ||
| 366 | }; | ||
| 367 | |||
| 368 | static const struct armada38x_rtc_data armada8k_data = { | ||
| 369 | .update_mbus_timing = rtc_update_8k_mbus_timing_params, | ||
| 370 | .read_rtc_reg = read_rtc_register, | ||
| 371 | .clear_isr = armada8k_clear_isr, | ||
| 372 | .unmask_interrupt = armada8k_unmask_interrupt, | ||
| 373 | .alarm = ALARM2, | ||
| 374 | }; | ||
| 375 | |||
| 376 | #ifdef CONFIG_OF | ||
| 377 | static const struct of_device_id armada38x_rtc_of_match_table[] = { | ||
| 378 | { | ||
| 379 | .compatible = "marvell,armada-380-rtc", | ||
| 380 | .data = &armada38x_data, | ||
| 381 | }, | ||
| 382 | { | ||
| 383 | .compatible = "marvell,armada-8k-rtc", | ||
| 384 | .data = &armada8k_data, | ||
| 385 | }, | ||
| 386 | {} | ||
| 387 | }; | ||
| 388 | MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); | ||
| 389 | #endif | ||
| 390 | |||
| 213 | static __init int armada38x_rtc_probe(struct platform_device *pdev) | 391 | static __init int armada38x_rtc_probe(struct platform_device *pdev) |
| 214 | { | 392 | { |
| 393 | const struct rtc_class_ops *ops; | ||
| 215 | struct resource *res; | 394 | struct resource *res; |
| 216 | struct armada38x_rtc *rtc; | 395 | struct armada38x_rtc *rtc; |
| 396 | const struct of_device_id *match; | ||
| 217 | int ret; | 397 | int ret; |
| 218 | 398 | ||
| 399 | match = of_match_device(armada38x_rtc_of_match_table, &pdev->dev); | ||
| 400 | if (!match) | ||
| 401 | return -ENODEV; | ||
| 402 | |||
| 219 | rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc), | 403 | rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc), |
| 220 | GFP_KERNEL); | 404 | GFP_KERNEL); |
| 221 | if (!rtc) | 405 | if (!rtc) |
| 222 | return -ENOMEM; | 406 | return -ENOMEM; |
| 223 | 407 | ||
| 408 | rtc->val_to_freq = devm_kcalloc(&pdev->dev, SAMPLE_NR, | ||
| 409 | sizeof(struct value_to_freq), GFP_KERNEL); | ||
| 410 | if (!rtc->val_to_freq) | ||
| 411 | return -ENOMEM; | ||
| 412 | |||
| 224 | spin_lock_init(&rtc->lock); | 413 | spin_lock_init(&rtc->lock); |
| 225 | 414 | ||
| 226 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); | 415 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); |
| @@ -242,19 +431,27 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) | |||
| 242 | 0, pdev->name, rtc) < 0) { | 431 | 0, pdev->name, rtc) < 0) { |
| 243 | dev_warn(&pdev->dev, "Interrupt not available.\n"); | 432 | dev_warn(&pdev->dev, "Interrupt not available.\n"); |
| 244 | rtc->irq = -1; | 433 | rtc->irq = -1; |
| 434 | } | ||
| 435 | platform_set_drvdata(pdev, rtc); | ||
| 436 | |||
| 437 | if (rtc->irq != -1) { | ||
| 438 | device_init_wakeup(&pdev->dev, 1); | ||
| 439 | ops = &armada38x_rtc_ops; | ||
| 440 | } else { | ||
| 245 | /* | 441 | /* |
| 246 | * If there is no interrupt available then we can't | 442 | * If there is no interrupt available then we can't |
| 247 | * use the alarm | 443 | * use the alarm |
| 248 | */ | 444 | */ |
| 249 | armada38x_rtc_ops.set_alarm = NULL; | 445 | ops = &armada38x_rtc_ops_noirq; |
| 250 | armada38x_rtc_ops.alarm_irq_enable = NULL; | ||
| 251 | } | 446 | } |
| 252 | platform_set_drvdata(pdev, rtc); | 447 | rtc->data = (struct armada38x_rtc_data *)match->data; |
| 253 | if (rtc->irq != -1) | 448 | |
| 254 | device_init_wakeup(&pdev->dev, 1); | 449 | |
| 450 | /* Update RTC-MBUS bridge timing parameters */ | ||
| 451 | rtc->data->update_mbus_timing(rtc); | ||
| 255 | 452 | ||
| 256 | rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, | 453 | rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, |
| 257 | &armada38x_rtc_ops, THIS_MODULE); | 454 | ops, THIS_MODULE); |
| 258 | if (IS_ERR(rtc->rtc_dev)) { | 455 | if (IS_ERR(rtc->rtc_dev)) { |
| 259 | ret = PTR_ERR(rtc->rtc_dev); | 456 | ret = PTR_ERR(rtc->rtc_dev); |
| 260 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | 457 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); |
| @@ -280,6 +477,9 @@ static int armada38x_rtc_resume(struct device *dev) | |||
| 280 | if (device_may_wakeup(dev)) { | 477 | if (device_may_wakeup(dev)) { |
| 281 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); | 478 | struct armada38x_rtc *rtc = dev_get_drvdata(dev); |
| 282 | 479 | ||
| 480 | /* Update RTC-MBUS bridge timing parameters */ | ||
| 481 | rtc->data->update_mbus_timing(rtc); | ||
| 482 | |||
| 283 | return disable_irq_wake(rtc->irq); | 483 | return disable_irq_wake(rtc->irq); |
| 284 | } | 484 | } |
| 285 | 485 | ||
| @@ -290,14 +490,6 @@ static int armada38x_rtc_resume(struct device *dev) | |||
| 290 | static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops, | 490 | static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops, |
| 291 | armada38x_rtc_suspend, armada38x_rtc_resume); | 491 | armada38x_rtc_suspend, armada38x_rtc_resume); |
| 292 | 492 | ||
| 293 | #ifdef CONFIG_OF | ||
| 294 | static const struct of_device_id armada38x_rtc_of_match_table[] = { | ||
| 295 | { .compatible = "marvell,armada-380-rtc", }, | ||
| 296 | {} | ||
| 297 | }; | ||
| 298 | MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); | ||
| 299 | #endif | ||
| 300 | |||
| 301 | static struct platform_driver armada38x_rtc_driver = { | 493 | static struct platform_driver armada38x_rtc_driver = { |
| 302 | .driver = { | 494 | .driver = { |
| 303 | .name = "armada38x-rtc", | 495 | .name = "armada38x-rtc", |
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c index 84d6e026784d..2ba44ccb9c3a 100644 --- a/drivers/rtc/rtc-au1xxx.c +++ b/drivers/rtc/rtc-au1xxx.c | |||
| @@ -56,7 +56,7 @@ static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 56 | return 0; | 56 | return 0; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static struct rtc_class_ops au1xtoy_rtc_ops = { | 59 | static const struct rtc_class_ops au1xtoy_rtc_ops = { |
| 60 | .read_time = au1xtoy_rtc_read_time, | 60 | .read_time = au1xtoy_rtc_read_time, |
| 61 | .set_time = au1xtoy_rtc_set_time, | 61 | .set_time = au1xtoy_rtc_set_time, |
| 62 | }; | 62 | }; |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 535a5f9338d0..15344b7c07c5 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -333,7 +333,7 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 333 | #undef yesno | 333 | #undef yesno |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | static struct rtc_class_ops bfin_rtc_ops = { | 336 | static const struct rtc_class_ops bfin_rtc_ops = { |
| 337 | .read_time = bfin_rtc_read_time, | 337 | .read_time = bfin_rtc_read_time, |
| 338 | .set_time = bfin_rtc_set_time, | 338 | .set_time = bfin_rtc_set_time, |
| 339 | .read_alarm = bfin_rtc_read_alarm, | 339 | .read_alarm = bfin_rtc_read_alarm, |
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 397742446007..2b223935001f 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */ | 34 | #define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */ |
| 35 | #define BQ32K_TCH2 0x08 /* Trickle charge enable */ | 35 | #define BQ32K_TCH2 0x08 /* Trickle charge enable */ |
| 36 | #define BQ32K_CFG2 0x09 /* Trickle charger control */ | 36 | #define BQ32K_CFG2 0x09 /* Trickle charger control */ |
| 37 | #define BQ32K_TCFE BIT(6) /* Trickle charge FET bypass */ | ||
| 37 | 38 | ||
| 38 | struct bq32k_regs { | 39 | struct bq32k_regs { |
| 39 | uint8_t seconds; | 40 | uint8_t seconds; |
| @@ -188,6 +189,65 @@ static int trickle_charger_of_init(struct device *dev, struct device_node *node) | |||
| 188 | return 0; | 189 | return 0; |
| 189 | } | 190 | } |
| 190 | 191 | ||
| 192 | static ssize_t bq32k_sysfs_show_tricklecharge_bypass(struct device *dev, | ||
| 193 | struct device_attribute *attr, | ||
| 194 | char *buf) | ||
| 195 | { | ||
| 196 | int reg, error; | ||
| 197 | |||
| 198 | error = bq32k_read(dev, ®, BQ32K_CFG2, 1); | ||
| 199 | if (error) | ||
| 200 | return error; | ||
| 201 | |||
| 202 | return sprintf(buf, "%d\n", (reg & BQ32K_TCFE) ? 1 : 0); | ||
| 203 | } | ||
| 204 | |||
| 205 | static ssize_t bq32k_sysfs_store_tricklecharge_bypass(struct device *dev, | ||
| 206 | struct device_attribute *attr, | ||
| 207 | const char *buf, size_t count) | ||
| 208 | { | ||
| 209 | int reg, enable, error; | ||
| 210 | |||
| 211 | if (kstrtoint(buf, 0, &enable)) | ||
| 212 | return -EINVAL; | ||
| 213 | |||
| 214 | error = bq32k_read(dev, ®, BQ32K_CFG2, 1); | ||
| 215 | if (error) | ||
| 216 | return error; | ||
| 217 | |||
| 218 | if (enable) { | ||
| 219 | reg |= BQ32K_TCFE; | ||
| 220 | error = bq32k_write(dev, ®, BQ32K_CFG2, 1); | ||
| 221 | if (error) | ||
| 222 | return error; | ||
| 223 | |||
| 224 | dev_info(dev, "Enabled trickle charge FET bypass.\n"); | ||
| 225 | } else { | ||
| 226 | reg &= ~BQ32K_TCFE; | ||
| 227 | error = bq32k_write(dev, ®, BQ32K_CFG2, 1); | ||
| 228 | if (error) | ||
| 229 | return error; | ||
| 230 | |||
| 231 | dev_info(dev, "Disabled trickle charge FET bypass.\n"); | ||
| 232 | } | ||
| 233 | |||
| 234 | return count; | ||
| 235 | } | ||
| 236 | |||
| 237 | static DEVICE_ATTR(trickle_charge_bypass, 0644, | ||
| 238 | bq32k_sysfs_show_tricklecharge_bypass, | ||
| 239 | bq32k_sysfs_store_tricklecharge_bypass); | ||
| 240 | |||
| 241 | static int bq32k_sysfs_register(struct device *dev) | ||
| 242 | { | ||
| 243 | return device_create_file(dev, &dev_attr_trickle_charge_bypass); | ||
| 244 | } | ||
| 245 | |||
| 246 | static void bq32k_sysfs_unregister(struct device *dev) | ||
| 247 | { | ||
| 248 | device_remove_file(dev, &dev_attr_trickle_charge_bypass); | ||
| 249 | } | ||
| 250 | |||
| 191 | static int bq32k_probe(struct i2c_client *client, | 251 | static int bq32k_probe(struct i2c_client *client, |
| 192 | const struct i2c_device_id *id) | 252 | const struct i2c_device_id *id) |
| 193 | { | 253 | { |
| @@ -224,11 +284,26 @@ static int bq32k_probe(struct i2c_client *client, | |||
| 224 | if (IS_ERR(rtc)) | 284 | if (IS_ERR(rtc)) |
| 225 | return PTR_ERR(rtc); | 285 | return PTR_ERR(rtc); |
| 226 | 286 | ||
| 287 | error = bq32k_sysfs_register(&client->dev); | ||
| 288 | if (error) { | ||
| 289 | dev_err(&client->dev, | ||
| 290 | "Unable to create sysfs entries for rtc bq32000\n"); | ||
| 291 | return error; | ||
| 292 | } | ||
| 293 | |||
| 294 | |||
| 227 | i2c_set_clientdata(client, rtc); | 295 | i2c_set_clientdata(client, rtc); |
| 228 | 296 | ||
| 229 | return 0; | 297 | return 0; |
| 230 | } | 298 | } |
| 231 | 299 | ||
| 300 | static int bq32k_remove(struct i2c_client *client) | ||
| 301 | { | ||
| 302 | bq32k_sysfs_unregister(&client->dev); | ||
| 303 | |||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 232 | static const struct i2c_device_id bq32k_id[] = { | 307 | static const struct i2c_device_id bq32k_id[] = { |
| 233 | { "bq32000", 0 }, | 308 | { "bq32000", 0 }, |
| 234 | { } | 309 | { } |
| @@ -240,6 +315,7 @@ static struct i2c_driver bq32k_driver = { | |||
| 240 | .name = "bq32k", | 315 | .name = "bq32k", |
| 241 | }, | 316 | }, |
| 242 | .probe = bq32k_probe, | 317 | .probe = bq32k_probe, |
| 318 | .remove = bq32k_remove, | ||
| 243 | .id_table = bq32k_id, | 319 | .id_table = bq32k_id, |
| 244 | }; | 320 | }; |
| 245 | 321 | ||
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c index 94067f8eeb10..f225cd873ff6 100644 --- a/drivers/rtc/rtc-dm355evm.c +++ b/drivers/rtc/rtc-dm355evm.c | |||
| @@ -116,7 +116,7 @@ static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 116 | return 0; | 116 | return 0; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static struct rtc_class_ops dm355evm_rtc_ops = { | 119 | static const struct rtc_class_ops dm355evm_rtc_ops = { |
| 120 | .read_time = dm355evm_rtc_read_time, | 120 | .read_time = dm355evm_rtc_read_time, |
| 121 | .set_time = dm355evm_rtc_set_time, | 121 | .set_time = dm355evm_rtc_set_time, |
| 122 | }; | 122 | }; |
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index b1f20d8c358f..9bb39a06b994 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c | |||
| @@ -23,28 +23,28 @@ | |||
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
| 25 | 25 | ||
| 26 | #define DS3232_REG_SECONDS 0x00 | 26 | #define DS3232_REG_SECONDS 0x00 |
| 27 | #define DS3232_REG_MINUTES 0x01 | 27 | #define DS3232_REG_MINUTES 0x01 |
| 28 | #define DS3232_REG_HOURS 0x02 | 28 | #define DS3232_REG_HOURS 0x02 |
| 29 | #define DS3232_REG_AMPM 0x02 | 29 | #define DS3232_REG_AMPM 0x02 |
| 30 | #define DS3232_REG_DAY 0x03 | 30 | #define DS3232_REG_DAY 0x03 |
| 31 | #define DS3232_REG_DATE 0x04 | 31 | #define DS3232_REG_DATE 0x04 |
| 32 | #define DS3232_REG_MONTH 0x05 | 32 | #define DS3232_REG_MONTH 0x05 |
| 33 | #define DS3232_REG_CENTURY 0x05 | 33 | #define DS3232_REG_CENTURY 0x05 |
| 34 | #define DS3232_REG_YEAR 0x06 | 34 | #define DS3232_REG_YEAR 0x06 |
| 35 | #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */ | 35 | #define DS3232_REG_ALARM1 0x07 /* Alarm 1 BASE */ |
| 36 | #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */ | 36 | #define DS3232_REG_ALARM2 0x0B /* Alarm 2 BASE */ |
| 37 | #define DS3232_REG_CR 0x0E /* Control register */ | 37 | #define DS3232_REG_CR 0x0E /* Control register */ |
| 38 | # define DS3232_REG_CR_nEOSC 0x80 | 38 | # define DS3232_REG_CR_nEOSC 0x80 |
| 39 | # define DS3232_REG_CR_INTCN 0x04 | 39 | # define DS3232_REG_CR_INTCN 0x04 |
| 40 | # define DS3232_REG_CR_A2IE 0x02 | 40 | # define DS3232_REG_CR_A2IE 0x02 |
| 41 | # define DS3232_REG_CR_A1IE 0x01 | 41 | # define DS3232_REG_CR_A1IE 0x01 |
| 42 | 42 | ||
| 43 | #define DS3232_REG_SR 0x0F /* control/status register */ | 43 | #define DS3232_REG_SR 0x0F /* control/status register */ |
| 44 | # define DS3232_REG_SR_OSF 0x80 | 44 | # define DS3232_REG_SR_OSF 0x80 |
| 45 | # define DS3232_REG_SR_BSY 0x04 | 45 | # define DS3232_REG_SR_BSY 0x04 |
| 46 | # define DS3232_REG_SR_A2F 0x02 | 46 | # define DS3232_REG_SR_A2F 0x02 |
| 47 | # define DS3232_REG_SR_A1F 0x01 | 47 | # define DS3232_REG_SR_A1F 0x01 |
| 48 | 48 | ||
| 49 | struct ds3232 { | 49 | struct ds3232 { |
| 50 | struct device *dev; | 50 | struct device *dev; |
| @@ -363,6 +363,9 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, | |||
| 363 | if (ret) | 363 | if (ret) |
| 364 | return ret; | 364 | return ret; |
| 365 | 365 | ||
| 366 | if (ds3232->irq > 0) | ||
| 367 | device_init_wakeup(dev, 1); | ||
| 368 | |||
| 366 | ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops, | 369 | ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops, |
| 367 | THIS_MODULE); | 370 | THIS_MODULE); |
| 368 | if (IS_ERR(ds3232->rtc)) | 371 | if (IS_ERR(ds3232->rtc)) |
| @@ -374,10 +377,10 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, | |||
| 374 | IRQF_SHARED | IRQF_ONESHOT, | 377 | IRQF_SHARED | IRQF_ONESHOT, |
| 375 | name, dev); | 378 | name, dev); |
| 376 | if (ret) { | 379 | if (ret) { |
| 380 | device_set_wakeup_capable(dev, 0); | ||
| 377 | ds3232->irq = 0; | 381 | ds3232->irq = 0; |
| 378 | dev_err(dev, "unable to request IRQ\n"); | 382 | dev_err(dev, "unable to request IRQ\n"); |
| 379 | } else | 383 | } |
| 380 | device_init_wakeup(dev, 1); | ||
| 381 | } | 384 | } |
| 382 | 385 | ||
| 383 | return 0; | 386 | return 0; |
| @@ -420,6 +423,7 @@ static int ds3232_i2c_probe(struct i2c_client *client, | |||
| 420 | static const struct regmap_config config = { | 423 | static const struct regmap_config config = { |
| 421 | .reg_bits = 8, | 424 | .reg_bits = 8, |
| 422 | .val_bits = 8, | 425 | .val_bits = 8, |
| 426 | .max_register = 0x13, | ||
| 423 | }; | 427 | }; |
| 424 | 428 | ||
| 425 | regmap = devm_regmap_init_i2c(client, &config); | 429 | regmap = devm_regmap_init_i2c(client, &config); |
| @@ -479,6 +483,7 @@ static int ds3234_probe(struct spi_device *spi) | |||
| 479 | static const struct regmap_config config = { | 483 | static const struct regmap_config config = { |
| 480 | .reg_bits = 8, | 484 | .reg_bits = 8, |
| 481 | .val_bits = 8, | 485 | .val_bits = 8, |
| 486 | .max_register = 0x13, | ||
| 482 | .write_flag_mask = 0x80, | 487 | .write_flag_mask = 0x80, |
| 483 | }; | 488 | }; |
| 484 | struct regmap *regmap; | 489 | struct regmap *regmap; |
diff --git a/drivers/rtc/rtc-gemini.c b/drivers/rtc/rtc-gemini.c index 688debc14348..ccf0dbadb62d 100644 --- a/drivers/rtc/rtc-gemini.c +++ b/drivers/rtc/rtc-gemini.c | |||
| @@ -159,9 +159,16 @@ static int gemini_rtc_remove(struct platform_device *pdev) | |||
| 159 | return 0; | 159 | return 0; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | static const struct of_device_id gemini_rtc_dt_match[] = { | ||
| 163 | { .compatible = "cortina,gemini-rtc" }, | ||
| 164 | { } | ||
| 165 | }; | ||
| 166 | MODULE_DEVICE_TABLE(of, gemini_rtc_dt_match); | ||
| 167 | |||
| 162 | static struct platform_driver gemini_rtc_driver = { | 168 | static struct platform_driver gemini_rtc_driver = { |
| 163 | .driver = { | 169 | .driver = { |
| 164 | .name = DRV_NAME, | 170 | .name = DRV_NAME, |
| 171 | .of_match_table = gemini_rtc_dt_match, | ||
| 165 | }, | 172 | }, |
| 166 | .probe = gemini_rtc_probe, | 173 | .probe = gemini_rtc_probe, |
| 167 | .remove = gemini_rtc_remove, | 174 | .remove = gemini_rtc_remove, |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 67b56b80dc70..6b54f6c24c5f 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
| @@ -108,7 +108,6 @@ | |||
| 108 | * @pdev: pionter to platform dev | 108 | * @pdev: pionter to platform dev |
| 109 | * @rtc: pointer to rtc struct | 109 | * @rtc: pointer to rtc struct |
| 110 | * @ioaddr: IO registers pointer | 110 | * @ioaddr: IO registers pointer |
| 111 | * @irq: dryice normal interrupt | ||
| 112 | * @clk: input reference clock | 111 | * @clk: input reference clock |
| 113 | * @dsr: copy of the DSR register | 112 | * @dsr: copy of the DSR register |
| 114 | * @irq_lock: interrupt enable register (DIER) lock | 113 | * @irq_lock: interrupt enable register (DIER) lock |
| @@ -120,7 +119,6 @@ struct imxdi_dev { | |||
| 120 | struct platform_device *pdev; | 119 | struct platform_device *pdev; |
| 121 | struct rtc_device *rtc; | 120 | struct rtc_device *rtc; |
| 122 | void __iomem *ioaddr; | 121 | void __iomem *ioaddr; |
| 123 | int irq; | ||
| 124 | struct clk *clk; | 122 | struct clk *clk; |
| 125 | u32 dsr; | 123 | u32 dsr; |
| 126 | spinlock_t irq_lock; | 124 | spinlock_t irq_lock; |
| @@ -668,7 +666,7 @@ static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 668 | return 0; | 666 | return 0; |
| 669 | } | 667 | } |
| 670 | 668 | ||
| 671 | static struct rtc_class_ops dryice_rtc_ops = { | 669 | static const struct rtc_class_ops dryice_rtc_ops = { |
| 672 | .read_time = dryice_rtc_read_time, | 670 | .read_time = dryice_rtc_read_time, |
| 673 | .set_mmss = dryice_rtc_set_mmss, | 671 | .set_mmss = dryice_rtc_set_mmss, |
| 674 | .alarm_irq_enable = dryice_rtc_alarm_irq_enable, | 672 | .alarm_irq_enable = dryice_rtc_alarm_irq_enable, |
| @@ -677,9 +675,9 @@ static struct rtc_class_ops dryice_rtc_ops = { | |||
| 677 | }; | 675 | }; |
| 678 | 676 | ||
| 679 | /* | 677 | /* |
| 680 | * dryice "normal" interrupt handler | 678 | * interrupt handler for dryice "normal" and security violation interrupt |
| 681 | */ | 679 | */ |
| 682 | static irqreturn_t dryice_norm_irq(int irq, void *dev_id) | 680 | static irqreturn_t dryice_irq(int irq, void *dev_id) |
| 683 | { | 681 | { |
| 684 | struct imxdi_dev *imxdi = dev_id; | 682 | struct imxdi_dev *imxdi = dev_id; |
| 685 | u32 dsr, dier; | 683 | u32 dsr, dier; |
| @@ -765,6 +763,7 @@ static int __init dryice_rtc_probe(struct platform_device *pdev) | |||
| 765 | { | 763 | { |
| 766 | struct resource *res; | 764 | struct resource *res; |
| 767 | struct imxdi_dev *imxdi; | 765 | struct imxdi_dev *imxdi; |
| 766 | int norm_irq, sec_irq; | ||
| 768 | int rc; | 767 | int rc; |
| 769 | 768 | ||
| 770 | imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); | 769 | imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); |
| @@ -780,9 +779,16 @@ static int __init dryice_rtc_probe(struct platform_device *pdev) | |||
| 780 | 779 | ||
| 781 | spin_lock_init(&imxdi->irq_lock); | 780 | spin_lock_init(&imxdi->irq_lock); |
| 782 | 781 | ||
| 783 | imxdi->irq = platform_get_irq(pdev, 0); | 782 | norm_irq = platform_get_irq(pdev, 0); |
| 784 | if (imxdi->irq < 0) | 783 | if (norm_irq < 0) |
| 785 | return imxdi->irq; | 784 | return norm_irq; |
| 785 | |||
| 786 | /* the 2nd irq is the security violation irq | ||
| 787 | * make this optional, don't break the device tree ABI | ||
| 788 | */ | ||
| 789 | sec_irq = platform_get_irq(pdev, 1); | ||
| 790 | if (sec_irq <= 0) | ||
| 791 | sec_irq = IRQ_NOTCONNECTED; | ||
| 786 | 792 | ||
| 787 | init_waitqueue_head(&imxdi->write_wait); | 793 | init_waitqueue_head(&imxdi->write_wait); |
| 788 | 794 | ||
| @@ -808,13 +814,20 @@ static int __init dryice_rtc_probe(struct platform_device *pdev) | |||
| 808 | if (rc != 0) | 814 | if (rc != 0) |
| 809 | goto err; | 815 | goto err; |
| 810 | 816 | ||
| 811 | rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, | 817 | rc = devm_request_irq(&pdev->dev, norm_irq, dryice_irq, |
| 812 | IRQF_SHARED, pdev->name, imxdi); | 818 | IRQF_SHARED, pdev->name, imxdi); |
| 813 | if (rc) { | 819 | if (rc) { |
| 814 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 820 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
| 815 | goto err; | 821 | goto err; |
| 816 | } | 822 | } |
| 817 | 823 | ||
| 824 | rc = devm_request_irq(&pdev->dev, sec_irq, dryice_irq, | ||
| 825 | IRQF_SHARED, pdev->name, imxdi); | ||
| 826 | if (rc) { | ||
| 827 | dev_warn(&pdev->dev, "security violation interrupt not available.\n"); | ||
| 828 | /* this is not an error, see above */ | ||
| 829 | } | ||
| 830 | |||
| 818 | platform_set_drvdata(pdev, imxdi); | 831 | platform_set_drvdata(pdev, imxdi); |
| 819 | imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, | 832 | imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, |
| 820 | &dryice_rtc_ops, THIS_MODULE); | 833 | &dryice_rtc_ops, THIS_MODULE); |
diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c index 22a9ec4f2b83..e04ca54f21e2 100644 --- a/drivers/rtc/rtc-ls1x.c +++ b/drivers/rtc/rtc-ls1x.c | |||
| @@ -138,7 +138,7 @@ err: | |||
| 138 | return ret; | 138 | return ret; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static struct rtc_class_ops ls1x_rtc_ops = { | 141 | static const struct rtc_class_ops ls1x_rtc_ops = { |
| 142 | .read_time = ls1x_rtc_read_time, | 142 | .read_time = ls1x_rtc_read_time, |
| 143 | .set_time = ls1x_rtc_set_time, | 143 | .set_time = ls1x_rtc_set_time, |
| 144 | }; | 144 | }; |
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 0eeb5714c00f..02af045305dd 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c | |||
| @@ -16,62 +16,88 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
| 18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/platform_data/rtc-m48t86.h> | ||
| 20 | #include <linux/bcd.h> | 19 | #include <linux/bcd.h> |
| 20 | #include <linux/io.h> | ||
| 21 | 21 | ||
| 22 | #define M48T86_REG_SEC 0x00 | 22 | #define M48T86_SEC 0x00 |
| 23 | #define M48T86_REG_SECALRM 0x01 | 23 | #define M48T86_SECALRM 0x01 |
| 24 | #define M48T86_REG_MIN 0x02 | 24 | #define M48T86_MIN 0x02 |
| 25 | #define M48T86_REG_MINALRM 0x03 | 25 | #define M48T86_MINALRM 0x03 |
| 26 | #define M48T86_REG_HOUR 0x04 | 26 | #define M48T86_HOUR 0x04 |
| 27 | #define M48T86_REG_HOURALRM 0x05 | 27 | #define M48T86_HOURALRM 0x05 |
| 28 | #define M48T86_REG_DOW 0x06 /* 1 = sunday */ | 28 | #define M48T86_DOW 0x06 /* 1 = sunday */ |
| 29 | #define M48T86_REG_DOM 0x07 | 29 | #define M48T86_DOM 0x07 |
| 30 | #define M48T86_REG_MONTH 0x08 /* 1 - 12 */ | 30 | #define M48T86_MONTH 0x08 /* 1 - 12 */ |
| 31 | #define M48T86_REG_YEAR 0x09 /* 0 - 99 */ | 31 | #define M48T86_YEAR 0x09 /* 0 - 99 */ |
| 32 | #define M48T86_REG_A 0x0A | 32 | #define M48T86_A 0x0a |
| 33 | #define M48T86_REG_B 0x0B | 33 | #define M48T86_B 0x0b |
| 34 | #define M48T86_REG_C 0x0C | 34 | #define M48T86_B_SET BIT(7) |
| 35 | #define M48T86_REG_D 0x0D | 35 | #define M48T86_B_DM BIT(2) |
| 36 | 36 | #define M48T86_B_H24 BIT(1) | |
| 37 | #define M48T86_REG_B_H24 (1 << 1) | 37 | #define M48T86_C 0x0c |
| 38 | #define M48T86_REG_B_DM (1 << 2) | 38 | #define M48T86_D 0x0d |
| 39 | #define M48T86_REG_B_SET (1 << 7) | 39 | #define M48T86_D_VRT BIT(7) |
| 40 | #define M48T86_REG_D_VRT (1 << 7) | 40 | #define M48T86_NVRAM(x) (0x0e + (x)) |
| 41 | #define M48T86_NVRAM_LEN 114 | ||
| 42 | |||
| 43 | struct m48t86_rtc_info { | ||
| 44 | void __iomem *index_reg; | ||
| 45 | void __iomem *data_reg; | ||
| 46 | struct rtc_device *rtc; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static unsigned char m48t86_readb(struct device *dev, unsigned long addr) | ||
| 50 | { | ||
| 51 | struct m48t86_rtc_info *info = dev_get_drvdata(dev); | ||
| 52 | unsigned char value; | ||
| 53 | |||
| 54 | writeb(addr, info->index_reg); | ||
| 55 | value = readb(info->data_reg); | ||
| 56 | |||
| 57 | return value; | ||
| 58 | } | ||
| 59 | |||
| 60 | static void m48t86_writeb(struct device *dev, | ||
| 61 | unsigned char value, unsigned long addr) | ||
| 62 | { | ||
| 63 | struct m48t86_rtc_info *info = dev_get_drvdata(dev); | ||
| 64 | |||
| 65 | writeb(addr, info->index_reg); | ||
| 66 | writeb(value, info->data_reg); | ||
| 67 | } | ||
| 41 | 68 | ||
| 42 | static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | 69 | static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 43 | { | 70 | { |
| 44 | unsigned char reg; | 71 | unsigned char reg; |
| 45 | struct platform_device *pdev = to_platform_device(dev); | ||
| 46 | struct m48t86_ops *ops = dev_get_platdata(&pdev->dev); | ||
| 47 | 72 | ||
| 48 | reg = ops->readbyte(M48T86_REG_B); | 73 | reg = m48t86_readb(dev, M48T86_B); |
| 49 | 74 | ||
| 50 | if (reg & M48T86_REG_B_DM) { | 75 | if (reg & M48T86_B_DM) { |
| 51 | /* data (binary) mode */ | 76 | /* data (binary) mode */ |
| 52 | tm->tm_sec = ops->readbyte(M48T86_REG_SEC); | 77 | tm->tm_sec = m48t86_readb(dev, M48T86_SEC); |
| 53 | tm->tm_min = ops->readbyte(M48T86_REG_MIN); | 78 | tm->tm_min = m48t86_readb(dev, M48T86_MIN); |
| 54 | tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F; | 79 | tm->tm_hour = m48t86_readb(dev, M48T86_HOUR) & 0x3f; |
| 55 | tm->tm_mday = ops->readbyte(M48T86_REG_DOM); | 80 | tm->tm_mday = m48t86_readb(dev, M48T86_DOM); |
| 56 | /* tm_mon is 0-11 */ | 81 | /* tm_mon is 0-11 */ |
| 57 | tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1; | 82 | tm->tm_mon = m48t86_readb(dev, M48T86_MONTH) - 1; |
| 58 | tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100; | 83 | tm->tm_year = m48t86_readb(dev, M48T86_YEAR) + 100; |
| 59 | tm->tm_wday = ops->readbyte(M48T86_REG_DOW); | 84 | tm->tm_wday = m48t86_readb(dev, M48T86_DOW); |
| 60 | } else { | 85 | } else { |
| 61 | /* bcd mode */ | 86 | /* bcd mode */ |
| 62 | tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC)); | 87 | tm->tm_sec = bcd2bin(m48t86_readb(dev, M48T86_SEC)); |
| 63 | tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN)); | 88 | tm->tm_min = bcd2bin(m48t86_readb(dev, M48T86_MIN)); |
| 64 | tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F); | 89 | tm->tm_hour = bcd2bin(m48t86_readb(dev, M48T86_HOUR) & |
| 65 | tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM)); | 90 | 0x3f); |
| 91 | tm->tm_mday = bcd2bin(m48t86_readb(dev, M48T86_DOM)); | ||
| 66 | /* tm_mon is 0-11 */ | 92 | /* tm_mon is 0-11 */ |
| 67 | tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1; | 93 | tm->tm_mon = bcd2bin(m48t86_readb(dev, M48T86_MONTH)) - 1; |
| 68 | tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100; | 94 | tm->tm_year = bcd2bin(m48t86_readb(dev, M48T86_YEAR)) + 100; |
| 69 | tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW)); | 95 | tm->tm_wday = bcd2bin(m48t86_readb(dev, M48T86_DOW)); |
| 70 | } | 96 | } |
| 71 | 97 | ||
| 72 | /* correct the hour if the clock is in 12h mode */ | 98 | /* correct the hour if the clock is in 12h mode */ |
| 73 | if (!(reg & M48T86_REG_B_H24)) | 99 | if (!(reg & M48T86_B_H24)) |
| 74 | if (ops->readbyte(M48T86_REG_HOUR) & 0x80) | 100 | if (m48t86_readb(dev, M48T86_HOUR) & 0x80) |
| 75 | tm->tm_hour += 12; | 101 | tm->tm_hour += 12; |
| 76 | 102 | ||
| 77 | return rtc_valid_tm(tm); | 103 | return rtc_valid_tm(tm); |
| @@ -80,38 +106,36 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 80 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | 106 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) |
| 81 | { | 107 | { |
| 82 | unsigned char reg; | 108 | unsigned char reg; |
| 83 | struct platform_device *pdev = to_platform_device(dev); | ||
| 84 | struct m48t86_ops *ops = dev_get_platdata(&pdev->dev); | ||
| 85 | 109 | ||
| 86 | reg = ops->readbyte(M48T86_REG_B); | 110 | reg = m48t86_readb(dev, M48T86_B); |
| 87 | 111 | ||
| 88 | /* update flag and 24h mode */ | 112 | /* update flag and 24h mode */ |
| 89 | reg |= M48T86_REG_B_SET | M48T86_REG_B_H24; | 113 | reg |= M48T86_B_SET | M48T86_B_H24; |
| 90 | ops->writebyte(reg, M48T86_REG_B); | 114 | m48t86_writeb(dev, reg, M48T86_B); |
| 91 | 115 | ||
| 92 | if (reg & M48T86_REG_B_DM) { | 116 | if (reg & M48T86_B_DM) { |
| 93 | /* data (binary) mode */ | 117 | /* data (binary) mode */ |
| 94 | ops->writebyte(tm->tm_sec, M48T86_REG_SEC); | 118 | m48t86_writeb(dev, tm->tm_sec, M48T86_SEC); |
| 95 | ops->writebyte(tm->tm_min, M48T86_REG_MIN); | 119 | m48t86_writeb(dev, tm->tm_min, M48T86_MIN); |
| 96 | ops->writebyte(tm->tm_hour, M48T86_REG_HOUR); | 120 | m48t86_writeb(dev, tm->tm_hour, M48T86_HOUR); |
| 97 | ops->writebyte(tm->tm_mday, M48T86_REG_DOM); | 121 | m48t86_writeb(dev, tm->tm_mday, M48T86_DOM); |
| 98 | ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH); | 122 | m48t86_writeb(dev, tm->tm_mon + 1, M48T86_MONTH); |
| 99 | ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR); | 123 | m48t86_writeb(dev, tm->tm_year % 100, M48T86_YEAR); |
| 100 | ops->writebyte(tm->tm_wday, M48T86_REG_DOW); | 124 | m48t86_writeb(dev, tm->tm_wday, M48T86_DOW); |
| 101 | } else { | 125 | } else { |
| 102 | /* bcd mode */ | 126 | /* bcd mode */ |
| 103 | ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC); | 127 | m48t86_writeb(dev, bin2bcd(tm->tm_sec), M48T86_SEC); |
| 104 | ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN); | 128 | m48t86_writeb(dev, bin2bcd(tm->tm_min), M48T86_MIN); |
| 105 | ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR); | 129 | m48t86_writeb(dev, bin2bcd(tm->tm_hour), M48T86_HOUR); |
| 106 | ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM); | 130 | m48t86_writeb(dev, bin2bcd(tm->tm_mday), M48T86_DOM); |
| 107 | ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH); | 131 | m48t86_writeb(dev, bin2bcd(tm->tm_mon + 1), M48T86_MONTH); |
| 108 | ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR); | 132 | m48t86_writeb(dev, bin2bcd(tm->tm_year % 100), M48T86_YEAR); |
| 109 | ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW); | 133 | m48t86_writeb(dev, bin2bcd(tm->tm_wday), M48T86_DOW); |
| 110 | } | 134 | } |
| 111 | 135 | ||
| 112 | /* update ended */ | 136 | /* update ended */ |
| 113 | reg &= ~M48T86_REG_B_SET; | 137 | reg &= ~M48T86_B_SET; |
| 114 | ops->writebyte(reg, M48T86_REG_B); | 138 | m48t86_writeb(dev, reg, M48T86_B); |
| 115 | 139 | ||
| 116 | return 0; | 140 | return 0; |
| 117 | } | 141 | } |
| @@ -119,18 +143,16 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 119 | static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) | 143 | static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) |
| 120 | { | 144 | { |
| 121 | unsigned char reg; | 145 | unsigned char reg; |
| 122 | struct platform_device *pdev = to_platform_device(dev); | ||
| 123 | struct m48t86_ops *ops = dev_get_platdata(&pdev->dev); | ||
| 124 | 146 | ||
| 125 | reg = ops->readbyte(M48T86_REG_B); | 147 | reg = m48t86_readb(dev, M48T86_B); |
| 126 | 148 | ||
| 127 | seq_printf(seq, "mode\t\t: %s\n", | 149 | seq_printf(seq, "mode\t\t: %s\n", |
| 128 | (reg & M48T86_REG_B_DM) ? "binary" : "bcd"); | 150 | (reg & M48T86_B_DM) ? "binary" : "bcd"); |
| 129 | 151 | ||
| 130 | reg = ops->readbyte(M48T86_REG_D); | 152 | reg = m48t86_readb(dev, M48T86_D); |
| 131 | 153 | ||
| 132 | seq_printf(seq, "battery\t\t: %s\n", | 154 | seq_printf(seq, "battery\t\t: %s\n", |
| 133 | (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); | 155 | (reg & M48T86_D_VRT) ? "ok" : "exhausted"); |
| 134 | 156 | ||
| 135 | return 0; | 157 | return 0; |
| 136 | } | 158 | } |
| @@ -141,25 +163,116 @@ static const struct rtc_class_ops m48t86_rtc_ops = { | |||
| 141 | .proc = m48t86_rtc_proc, | 163 | .proc = m48t86_rtc_proc, |
| 142 | }; | 164 | }; |
| 143 | 165 | ||
| 144 | static int m48t86_rtc_probe(struct platform_device *dev) | 166 | static ssize_t m48t86_nvram_read(struct file *filp, struct kobject *kobj, |
| 167 | struct bin_attribute *attr, | ||
| 168 | char *buf, loff_t off, size_t count) | ||
| 169 | { | ||
| 170 | struct device *dev = kobj_to_dev(kobj); | ||
| 171 | unsigned int i; | ||
| 172 | |||
| 173 | for (i = 0; i < count; i++) | ||
| 174 | buf[i] = m48t86_readb(dev, M48T86_NVRAM(off + i)); | ||
| 175 | |||
| 176 | return count; | ||
| 177 | } | ||
| 178 | |||
| 179 | static ssize_t m48t86_nvram_write(struct file *filp, struct kobject *kobj, | ||
| 180 | struct bin_attribute *attr, | ||
| 181 | char *buf, loff_t off, size_t count) | ||
| 145 | { | 182 | { |
| 183 | struct device *dev = kobj_to_dev(kobj); | ||
| 184 | unsigned int i; | ||
| 185 | |||
| 186 | for (i = 0; i < count; i++) | ||
| 187 | m48t86_writeb(dev, buf[i], M48T86_NVRAM(off + i)); | ||
| 188 | |||
| 189 | return count; | ||
| 190 | } | ||
| 191 | |||
| 192 | static BIN_ATTR(nvram, 0644, m48t86_nvram_read, m48t86_nvram_write, | ||
| 193 | M48T86_NVRAM_LEN); | ||
| 194 | |||
| 195 | /* | ||
| 196 | * The RTC is an optional feature at purchase time on some Technologic Systems | ||
| 197 | * boards. Verify that it actually exists by checking if the last two bytes | ||
| 198 | * of the NVRAM can be changed. | ||
| 199 | * | ||
| 200 | * This is based on the method used in their rtc7800.c example. | ||
| 201 | */ | ||
| 202 | static bool m48t86_verify_chip(struct platform_device *pdev) | ||
| 203 | { | ||
| 204 | unsigned int offset0 = M48T86_NVRAM(M48T86_NVRAM_LEN - 2); | ||
| 205 | unsigned int offset1 = M48T86_NVRAM(M48T86_NVRAM_LEN - 1); | ||
| 206 | unsigned char tmp0, tmp1; | ||
| 207 | |||
| 208 | tmp0 = m48t86_readb(&pdev->dev, offset0); | ||
| 209 | tmp1 = m48t86_readb(&pdev->dev, offset1); | ||
| 210 | |||
| 211 | m48t86_writeb(&pdev->dev, 0x00, offset0); | ||
| 212 | m48t86_writeb(&pdev->dev, 0x55, offset1); | ||
| 213 | if (m48t86_readb(&pdev->dev, offset1) == 0x55) { | ||
| 214 | m48t86_writeb(&pdev->dev, 0xaa, offset1); | ||
| 215 | if (m48t86_readb(&pdev->dev, offset1) == 0xaa && | ||
| 216 | m48t86_readb(&pdev->dev, offset0) == 0x00) { | ||
| 217 | m48t86_writeb(&pdev->dev, tmp0, offset0); | ||
| 218 | m48t86_writeb(&pdev->dev, tmp1, offset1); | ||
| 219 | |||
| 220 | return true; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | return false; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int m48t86_rtc_probe(struct platform_device *pdev) | ||
| 227 | { | ||
| 228 | struct m48t86_rtc_info *info; | ||
| 229 | struct resource *res; | ||
| 146 | unsigned char reg; | 230 | unsigned char reg; |
| 147 | struct m48t86_ops *ops = dev_get_platdata(&dev->dev); | ||
| 148 | struct rtc_device *rtc; | ||
| 149 | 231 | ||
| 150 | rtc = devm_rtc_device_register(&dev->dev, "m48t86", | 232 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
| 151 | &m48t86_rtc_ops, THIS_MODULE); | 233 | if (!info) |
| 234 | return -ENOMEM; | ||
| 235 | |||
| 236 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 237 | if (!res) | ||
| 238 | return -ENODEV; | ||
| 239 | info->index_reg = devm_ioremap_resource(&pdev->dev, res); | ||
| 240 | if (IS_ERR(info->index_reg)) | ||
| 241 | return PTR_ERR(info->index_reg); | ||
| 242 | |||
| 243 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 244 | if (!res) | ||
| 245 | return -ENODEV; | ||
| 246 | info->data_reg = devm_ioremap_resource(&pdev->dev, res); | ||
| 247 | if (IS_ERR(info->data_reg)) | ||
| 248 | return PTR_ERR(info->data_reg); | ||
| 152 | 249 | ||
| 153 | if (IS_ERR(rtc)) | 250 | dev_set_drvdata(&pdev->dev, info); |
| 154 | return PTR_ERR(rtc); | 251 | |
| 252 | if (!m48t86_verify_chip(pdev)) { | ||
| 253 | dev_info(&pdev->dev, "RTC not present\n"); | ||
| 254 | return -ENODEV; | ||
| 255 | } | ||
| 155 | 256 | ||
| 156 | platform_set_drvdata(dev, rtc); | 257 | info->rtc = devm_rtc_device_register(&pdev->dev, "m48t86", |
| 258 | &m48t86_rtc_ops, THIS_MODULE); | ||
| 259 | if (IS_ERR(info->rtc)) | ||
| 260 | return PTR_ERR(info->rtc); | ||
| 157 | 261 | ||
| 158 | /* read battery status */ | 262 | /* read battery status */ |
| 159 | reg = ops->readbyte(M48T86_REG_D); | 263 | reg = m48t86_readb(&pdev->dev, M48T86_D); |
| 160 | dev_info(&dev->dev, "battery %s\n", | 264 | dev_info(&pdev->dev, "battery %s\n", |
| 161 | (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); | 265 | (reg & M48T86_D_VRT) ? "ok" : "exhausted"); |
| 162 | 266 | ||
| 267 | if (device_create_bin_file(&pdev->dev, &bin_attr_nvram)) | ||
| 268 | dev_err(&pdev->dev, "failed to create nvram sysfs entry\n"); | ||
| 269 | |||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | static int m48t86_rtc_remove(struct platform_device *pdev) | ||
| 274 | { | ||
| 275 | device_remove_bin_file(&pdev->dev, &bin_attr_nvram); | ||
| 163 | return 0; | 276 | return 0; |
| 164 | } | 277 | } |
| 165 | 278 | ||
| @@ -168,6 +281,7 @@ static struct platform_driver m48t86_rtc_platform_driver = { | |||
| 168 | .name = "rtc-m48t86", | 281 | .name = "rtc-m48t86", |
| 169 | }, | 282 | }, |
| 170 | .probe = m48t86_rtc_probe, | 283 | .probe = m48t86_rtc_probe, |
| 284 | .remove = m48t86_rtc_remove, | ||
| 171 | }; | 285 | }; |
| 172 | 286 | ||
| 173 | module_platform_driver(m48t86_rtc_platform_driver); | 287 | module_platform_driver(m48t86_rtc_platform_driver); |
diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index ce75e421ba00..77f21331ae21 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c | |||
| @@ -44,12 +44,22 @@ | |||
| 44 | #define MCP795_REG_DAY 0x04 | 44 | #define MCP795_REG_DAY 0x04 |
| 45 | #define MCP795_REG_MONTH 0x06 | 45 | #define MCP795_REG_MONTH 0x06 |
| 46 | #define MCP795_REG_CONTROL 0x08 | 46 | #define MCP795_REG_CONTROL 0x08 |
| 47 | #define MCP795_REG_ALM0_SECONDS 0x0C | ||
| 48 | #define MCP795_REG_ALM0_DAY 0x0F | ||
| 47 | 49 | ||
| 48 | #define MCP795_ST_BIT BIT(7) | 50 | #define MCP795_ST_BIT BIT(7) |
| 49 | #define MCP795_24_BIT BIT(6) | 51 | #define MCP795_24_BIT BIT(6) |
| 50 | #define MCP795_LP_BIT BIT(5) | 52 | #define MCP795_LP_BIT BIT(5) |
| 51 | #define MCP795_EXTOSC_BIT BIT(3) | 53 | #define MCP795_EXTOSC_BIT BIT(3) |
| 52 | #define MCP795_OSCON_BIT BIT(5) | 54 | #define MCP795_OSCON_BIT BIT(5) |
| 55 | #define MCP795_ALM0_BIT BIT(4) | ||
| 56 | #define MCP795_ALM1_BIT BIT(5) | ||
| 57 | #define MCP795_ALM0IF_BIT BIT(3) | ||
| 58 | #define MCP795_ALM0C0_BIT BIT(4) | ||
| 59 | #define MCP795_ALM0C1_BIT BIT(5) | ||
| 60 | #define MCP795_ALM0C2_BIT BIT(6) | ||
| 61 | |||
| 62 | #define SEC_PER_DAY (24 * 60 * 60) | ||
| 53 | 63 | ||
| 54 | static int mcp795_rtcc_read(struct device *dev, u8 addr, u8 *buf, u8 count) | 64 | static int mcp795_rtcc_read(struct device *dev, u8 addr, u8 *buf, u8 count) |
| 55 | { | 65 | { |
| @@ -150,6 +160,30 @@ static int mcp795_start_oscillator(struct device *dev, bool *extosc) | |||
| 150 | dev, MCP795_REG_SECONDS, MCP795_ST_BIT, MCP795_ST_BIT); | 160 | dev, MCP795_REG_SECONDS, MCP795_ST_BIT, MCP795_ST_BIT); |
| 151 | } | 161 | } |
| 152 | 162 | ||
| 163 | /* Enable or disable Alarm 0 in RTC */ | ||
| 164 | static int mcp795_update_alarm(struct device *dev, bool enable) | ||
| 165 | { | ||
| 166 | int ret; | ||
| 167 | |||
| 168 | dev_dbg(dev, "%s alarm\n", enable ? "Enable" : "Disable"); | ||
| 169 | |||
| 170 | if (enable) { | ||
| 171 | /* clear ALM0IF (Alarm 0 Interrupt Flag) bit */ | ||
| 172 | ret = mcp795_rtcc_set_bits(dev, MCP795_REG_ALM0_DAY, | ||
| 173 | MCP795_ALM0IF_BIT, 0); | ||
| 174 | if (ret) | ||
| 175 | return ret; | ||
| 176 | /* enable alarm 0 */ | ||
| 177 | ret = mcp795_rtcc_set_bits(dev, MCP795_REG_CONTROL, | ||
| 178 | MCP795_ALM0_BIT, MCP795_ALM0_BIT); | ||
| 179 | } else { | ||
| 180 | /* disable alarm 0 and alarm 1 */ | ||
| 181 | ret = mcp795_rtcc_set_bits(dev, MCP795_REG_CONTROL, | ||
| 182 | MCP795_ALM0_BIT | MCP795_ALM1_BIT, 0); | ||
| 183 | } | ||
| 184 | return ret; | ||
| 185 | } | ||
| 186 | |||
| 153 | static int mcp795_set_time(struct device *dev, struct rtc_time *tim) | 187 | static int mcp795_set_time(struct device *dev, struct rtc_time *tim) |
| 154 | { | 188 | { |
| 155 | int ret; | 189 | int ret; |
| @@ -170,6 +204,7 @@ static int mcp795_set_time(struct device *dev, struct rtc_time *tim) | |||
| 170 | data[0] = (data[0] & 0x80) | bin2bcd(tim->tm_sec); | 204 | data[0] = (data[0] & 0x80) | bin2bcd(tim->tm_sec); |
| 171 | data[1] = (data[1] & 0x80) | bin2bcd(tim->tm_min); | 205 | data[1] = (data[1] & 0x80) | bin2bcd(tim->tm_min); |
| 172 | data[2] = bin2bcd(tim->tm_hour); | 206 | data[2] = bin2bcd(tim->tm_hour); |
| 207 | data[3] = (data[3] & 0xF8) | bin2bcd(tim->tm_wday + 1); | ||
| 173 | data[4] = bin2bcd(tim->tm_mday); | 208 | data[4] = bin2bcd(tim->tm_mday); |
| 174 | data[5] = (data[5] & MCP795_LP_BIT) | bin2bcd(tim->tm_mon + 1); | 209 | data[5] = (data[5] & MCP795_LP_BIT) | bin2bcd(tim->tm_mon + 1); |
| 175 | 210 | ||
| @@ -198,9 +233,9 @@ static int mcp795_set_time(struct device *dev, struct rtc_time *tim) | |||
| 198 | if (ret) | 233 | if (ret) |
| 199 | return ret; | 234 | return ret; |
| 200 | 235 | ||
| 201 | dev_dbg(dev, "Set mcp795: %04d-%02d-%02d %02d:%02d:%02d\n", | 236 | dev_dbg(dev, "Set mcp795: %04d-%02d-%02d(%d) %02d:%02d:%02d\n", |
| 202 | tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, | 237 | tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, |
| 203 | tim->tm_hour, tim->tm_min, tim->tm_sec); | 238 | tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec); |
| 204 | 239 | ||
| 205 | return 0; | 240 | return 0; |
| 206 | } | 241 | } |
| @@ -218,20 +253,139 @@ static int mcp795_read_time(struct device *dev, struct rtc_time *tim) | |||
| 218 | tim->tm_sec = bcd2bin(data[0] & 0x7F); | 253 | tim->tm_sec = bcd2bin(data[0] & 0x7F); |
| 219 | tim->tm_min = bcd2bin(data[1] & 0x7F); | 254 | tim->tm_min = bcd2bin(data[1] & 0x7F); |
| 220 | tim->tm_hour = bcd2bin(data[2] & 0x3F); | 255 | tim->tm_hour = bcd2bin(data[2] & 0x3F); |
| 256 | tim->tm_wday = bcd2bin(data[3] & 0x07) - 1; | ||
| 221 | tim->tm_mday = bcd2bin(data[4] & 0x3F); | 257 | tim->tm_mday = bcd2bin(data[4] & 0x3F); |
| 222 | tim->tm_mon = bcd2bin(data[5] & 0x1F) - 1; | 258 | tim->tm_mon = bcd2bin(data[5] & 0x1F) - 1; |
| 223 | tim->tm_year = bcd2bin(data[6]) + 100; /* Assume we are in 20xx */ | 259 | tim->tm_year = bcd2bin(data[6]) + 100; /* Assume we are in 20xx */ |
| 224 | 260 | ||
| 225 | dev_dbg(dev, "Read from mcp795: %04d-%02d-%02d %02d:%02d:%02d\n", | 261 | dev_dbg(dev, "Read from mcp795: %04d-%02d-%02d(%d) %02d:%02d:%02d\n", |
| 226 | tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, | 262 | tim->tm_year + 1900, tim->tm_mon, tim->tm_mday, |
| 227 | tim->tm_hour, tim->tm_min, tim->tm_sec); | 263 | tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec); |
| 228 | 264 | ||
| 229 | return rtc_valid_tm(tim); | 265 | return rtc_valid_tm(tim); |
| 230 | } | 266 | } |
| 231 | 267 | ||
| 268 | static int mcp795_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
| 269 | { | ||
| 270 | struct rtc_time now_tm; | ||
| 271 | time64_t now; | ||
| 272 | time64_t later; | ||
| 273 | u8 tmp[6]; | ||
| 274 | int ret; | ||
| 275 | |||
| 276 | /* Read current time from RTC hardware */ | ||
| 277 | ret = mcp795_read_time(dev, &now_tm); | ||
| 278 | if (ret) | ||
| 279 | return ret; | ||
| 280 | /* Get the number of seconds since 1970 */ | ||
| 281 | now = rtc_tm_to_time64(&now_tm); | ||
| 282 | later = rtc_tm_to_time64(&alm->time); | ||
| 283 | if (later <= now) | ||
| 284 | return -EINVAL; | ||
| 285 | /* make sure alarm fires within the next one year */ | ||
| 286 | if ((later - now) >= | ||
| 287 | (SEC_PER_DAY * (365 + is_leap_year(alm->time.tm_year)))) | ||
| 288 | return -EDOM; | ||
| 289 | /* disable alarm */ | ||
| 290 | ret = mcp795_update_alarm(dev, false); | ||
| 291 | if (ret) | ||
| 292 | return ret; | ||
| 293 | /* Read registers, so we can leave configuration bits untouched */ | ||
| 294 | ret = mcp795_rtcc_read(dev, MCP795_REG_ALM0_SECONDS, tmp, sizeof(tmp)); | ||
| 295 | if (ret) | ||
| 296 | return ret; | ||
| 297 | |||
| 298 | alm->time.tm_year = -1; | ||
| 299 | alm->time.tm_isdst = -1; | ||
| 300 | alm->time.tm_yday = -1; | ||
| 301 | |||
| 302 | tmp[0] = (tmp[0] & 0x80) | bin2bcd(alm->time.tm_sec); | ||
| 303 | tmp[1] = (tmp[1] & 0x80) | bin2bcd(alm->time.tm_min); | ||
| 304 | tmp[2] = (tmp[2] & 0xE0) | bin2bcd(alm->time.tm_hour); | ||
| 305 | tmp[3] = (tmp[3] & 0x80) | bin2bcd(alm->time.tm_wday + 1); | ||
| 306 | /* set alarm match: seconds, minutes, hour, day, date and month */ | ||
| 307 | tmp[3] |= (MCP795_ALM0C2_BIT | MCP795_ALM0C1_BIT | MCP795_ALM0C0_BIT); | ||
| 308 | tmp[4] = (tmp[4] & 0xC0) | bin2bcd(alm->time.tm_mday); | ||
| 309 | tmp[5] = (tmp[5] & 0xE0) | bin2bcd(alm->time.tm_mon + 1); | ||
| 310 | |||
| 311 | ret = mcp795_rtcc_write(dev, MCP795_REG_ALM0_SECONDS, tmp, sizeof(tmp)); | ||
| 312 | if (ret) | ||
| 313 | return ret; | ||
| 314 | |||
| 315 | /* enable alarm if requested */ | ||
| 316 | if (alm->enabled) { | ||
| 317 | ret = mcp795_update_alarm(dev, true); | ||
| 318 | if (ret) | ||
| 319 | return ret; | ||
| 320 | dev_dbg(dev, "Alarm IRQ armed\n"); | ||
| 321 | } | ||
| 322 | dev_dbg(dev, "Set alarm: %02d-%02d(%d) %02d:%02d:%02d\n", | ||
| 323 | alm->time.tm_mon, alm->time.tm_mday, alm->time.tm_wday, | ||
| 324 | alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec); | ||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int mcp795_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
| 329 | { | ||
| 330 | u8 data[6]; | ||
| 331 | int ret; | ||
| 332 | |||
| 333 | ret = mcp795_rtcc_read( | ||
| 334 | dev, MCP795_REG_ALM0_SECONDS, data, sizeof(data)); | ||
| 335 | if (ret) | ||
| 336 | return ret; | ||
| 337 | |||
| 338 | alm->time.tm_sec = bcd2bin(data[0] & 0x7F); | ||
| 339 | alm->time.tm_min = bcd2bin(data[1] & 0x7F); | ||
| 340 | alm->time.tm_hour = bcd2bin(data[2] & 0x1F); | ||
| 341 | alm->time.tm_wday = bcd2bin(data[3] & 0x07) - 1; | ||
| 342 | alm->time.tm_mday = bcd2bin(data[4] & 0x3F); | ||
| 343 | alm->time.tm_mon = bcd2bin(data[5] & 0x1F) - 1; | ||
| 344 | alm->time.tm_year = -1; | ||
| 345 | alm->time.tm_isdst = -1; | ||
| 346 | alm->time.tm_yday = -1; | ||
| 347 | |||
| 348 | dev_dbg(dev, "Read alarm: %02d-%02d(%d) %02d:%02d:%02d\n", | ||
| 349 | alm->time.tm_mon, alm->time.tm_mday, alm->time.tm_wday, | ||
| 350 | alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec); | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int mcp795_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
| 355 | { | ||
| 356 | return mcp795_update_alarm(dev, !!enabled); | ||
| 357 | } | ||
| 358 | |||
| 359 | static irqreturn_t mcp795_irq(int irq, void *data) | ||
| 360 | { | ||
| 361 | struct spi_device *spi = data; | ||
| 362 | struct rtc_device *rtc = spi_get_drvdata(spi); | ||
| 363 | struct mutex *lock = &rtc->ops_lock; | ||
| 364 | int ret; | ||
| 365 | |||
| 366 | mutex_lock(lock); | ||
| 367 | |||
| 368 | /* Disable alarm. | ||
| 369 | * There is no need to clear ALM0IF (Alarm 0 Interrupt Flag) bit, | ||
| 370 | * because it is done every time when alarm is enabled. | ||
| 371 | */ | ||
| 372 | ret = mcp795_update_alarm(&spi->dev, false); | ||
| 373 | if (ret) | ||
| 374 | dev_err(&spi->dev, | ||
| 375 | "Failed to disable alarm in IRQ (ret=%d)\n", ret); | ||
| 376 | rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); | ||
| 377 | |||
| 378 | mutex_unlock(lock); | ||
| 379 | |||
| 380 | return IRQ_HANDLED; | ||
| 381 | } | ||
| 382 | |||
| 232 | static const struct rtc_class_ops mcp795_rtc_ops = { | 383 | static const struct rtc_class_ops mcp795_rtc_ops = { |
| 233 | .read_time = mcp795_read_time, | 384 | .read_time = mcp795_read_time, |
| 234 | .set_time = mcp795_set_time | 385 | .set_time = mcp795_set_time, |
| 386 | .read_alarm = mcp795_read_alarm, | ||
| 387 | .set_alarm = mcp795_set_alarm, | ||
| 388 | .alarm_irq_enable = mcp795_alarm_irq_enable | ||
| 235 | }; | 389 | }; |
| 236 | 390 | ||
| 237 | static int mcp795_probe(struct spi_device *spi) | 391 | static int mcp795_probe(struct spi_device *spi) |
| @@ -259,6 +413,23 @@ static int mcp795_probe(struct spi_device *spi) | |||
| 259 | 413 | ||
| 260 | spi_set_drvdata(spi, rtc); | 414 | spi_set_drvdata(spi, rtc); |
| 261 | 415 | ||
| 416 | if (spi->irq > 0) { | ||
| 417 | dev_dbg(&spi->dev, "Alarm support enabled\n"); | ||
| 418 | |||
| 419 | /* Clear any pending alarm (ALM0IF bit) before requesting | ||
| 420 | * the interrupt. | ||
| 421 | */ | ||
| 422 | mcp795_rtcc_set_bits(&spi->dev, MCP795_REG_ALM0_DAY, | ||
| 423 | MCP795_ALM0IF_BIT, 0); | ||
| 424 | ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, | ||
| 425 | mcp795_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 426 | dev_name(&rtc->dev), spi); | ||
| 427 | if (ret) | ||
| 428 | dev_err(&spi->dev, "Failed to request IRQ: %d: %d\n", | ||
| 429 | spi->irq, ret); | ||
| 430 | else | ||
| 431 | device_init_wakeup(&spi->dev, true); | ||
| 432 | } | ||
| 262 | return 0; | 433 | return 0; |
| 263 | } | 434 | } |
| 264 | 435 | ||
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 359876a88ac8..77319122642a 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
| @@ -353,7 +353,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | /* RTC layer */ | 355 | /* RTC layer */ |
| 356 | static struct rtc_class_ops mxc_rtc_ops = { | 356 | static const struct rtc_class_ops mxc_rtc_ops = { |
| 357 | .release = mxc_rtc_release, | 357 | .release = mxc_rtc_release, |
| 358 | .read_time = mxc_rtc_read_time, | 358 | .read_time = mxc_rtc_read_time, |
| 359 | .set_mmss64 = mxc_rtc_set_mmss, | 359 | .set_mmss64 = mxc_rtc_set_mmss, |
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 2bfdf638b673..f33447c5db85 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c | |||
| @@ -52,9 +52,20 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 52 | struct pcf2127 *pcf2127 = dev_get_drvdata(dev); | 52 | struct pcf2127 *pcf2127 = dev_get_drvdata(dev); |
| 53 | unsigned char buf[10]; | 53 | unsigned char buf[10]; |
| 54 | int ret; | 54 | int ret; |
| 55 | int i; | ||
| 55 | 56 | ||
| 56 | ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, buf, | 57 | for (i = 0; i <= PCF2127_REG_CTRL3; i++) { |
| 57 | sizeof(buf)); | 58 | ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1 + i, |
| 59 | (unsigned int *)(buf + i)); | ||
| 60 | if (ret) { | ||
| 61 | dev_err(dev, "%s: read error\n", __func__); | ||
| 62 | return ret; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_SC, | ||
| 67 | (buf + PCF2127_REG_SC), | ||
| 68 | ARRAY_SIZE(buf) - PCF2127_REG_SC); | ||
| 58 | if (ret) { | 69 | if (ret) { |
| 59 | dev_err(dev, "%s: read error\n", __func__); | 70 | dev_err(dev, "%s: read error\n", __func__); |
| 60 | return ret; | 71 | return ret; |
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 7163b91bb773..d08da371912c 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c | |||
| @@ -63,7 +63,6 @@ struct rx8010_data { | |||
| 63 | struct i2c_client *client; | 63 | struct i2c_client *client; |
| 64 | struct rtc_device *rtc; | 64 | struct rtc_device *rtc; |
| 65 | u8 ctrlreg; | 65 | u8 ctrlreg; |
| 66 | spinlock_t flags_lock; | ||
| 67 | }; | 66 | }; |
| 68 | 67 | ||
| 69 | static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) | 68 | static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) |
| @@ -72,12 +71,12 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) | |||
| 72 | struct rx8010_data *rx8010 = i2c_get_clientdata(client); | 71 | struct rx8010_data *rx8010 = i2c_get_clientdata(client); |
| 73 | int flagreg; | 72 | int flagreg; |
| 74 | 73 | ||
| 75 | spin_lock(&rx8010->flags_lock); | 74 | mutex_lock(&rx8010->rtc->ops_lock); |
| 76 | 75 | ||
| 77 | flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); | 76 | flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); |
| 78 | 77 | ||
| 79 | if (flagreg <= 0) { | 78 | if (flagreg <= 0) { |
| 80 | spin_unlock(&rx8010->flags_lock); | 79 | mutex_unlock(&rx8010->rtc->ops_lock); |
| 81 | return IRQ_NONE; | 80 | return IRQ_NONE; |
| 82 | } | 81 | } |
| 83 | 82 | ||
| @@ -101,7 +100,7 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) | |||
| 101 | 100 | ||
| 102 | i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg); | 101 | i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg); |
| 103 | 102 | ||
| 104 | spin_unlock(&rx8010->flags_lock); | 103 | mutex_unlock(&rx8010->rtc->ops_lock); |
| 105 | return IRQ_HANDLED; | 104 | return IRQ_HANDLED; |
| 106 | } | 105 | } |
| 107 | 106 | ||
| @@ -143,7 +142,6 @@ static int rx8010_set_time(struct device *dev, struct rtc_time *dt) | |||
| 143 | u8 date[7]; | 142 | u8 date[7]; |
| 144 | int ctrl, flagreg; | 143 | int ctrl, flagreg; |
| 145 | int ret; | 144 | int ret; |
| 146 | unsigned long irqflags; | ||
| 147 | 145 | ||
| 148 | if ((dt->tm_year < 100) || (dt->tm_year > 199)) | 146 | if ((dt->tm_year < 100) || (dt->tm_year > 199)) |
| 149 | return -EINVAL; | 147 | return -EINVAL; |
| @@ -181,11 +179,8 @@ static int rx8010_set_time(struct device *dev, struct rtc_time *dt) | |||
| 181 | if (ret < 0) | 179 | if (ret < 0) |
| 182 | return ret; | 180 | return ret; |
| 183 | 181 | ||
| 184 | spin_lock_irqsave(&rx8010->flags_lock, irqflags); | ||
| 185 | |||
| 186 | flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG); | 182 | flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG); |
| 187 | if (flagreg < 0) { | 183 | if (flagreg < 0) { |
| 188 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 189 | return flagreg; | 184 | return flagreg; |
| 190 | } | 185 | } |
| 191 | 186 | ||
| @@ -193,8 +188,6 @@ static int rx8010_set_time(struct device *dev, struct rtc_time *dt) | |||
| 193 | ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, | 188 | ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, |
| 194 | flagreg & ~RX8010_FLAG_VLF); | 189 | flagreg & ~RX8010_FLAG_VLF); |
| 195 | 190 | ||
| 196 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 197 | |||
| 198 | return 0; | 191 | return 0; |
| 199 | } | 192 | } |
| 200 | 193 | ||
| @@ -288,12 +281,9 @@ static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 288 | u8 alarmvals[3]; | 281 | u8 alarmvals[3]; |
| 289 | int extreg, flagreg; | 282 | int extreg, flagreg; |
| 290 | int err; | 283 | int err; |
| 291 | unsigned long irqflags; | ||
| 292 | 284 | ||
| 293 | spin_lock_irqsave(&rx8010->flags_lock, irqflags); | ||
| 294 | flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); | 285 | flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); |
| 295 | if (flagreg < 0) { | 286 | if (flagreg < 0) { |
| 296 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 297 | return flagreg; | 287 | return flagreg; |
| 298 | } | 288 | } |
| 299 | 289 | ||
| @@ -302,14 +292,12 @@ static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 302 | err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL, | 292 | err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL, |
| 303 | rx8010->ctrlreg); | 293 | rx8010->ctrlreg); |
| 304 | if (err < 0) { | 294 | if (err < 0) { |
| 305 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 306 | return err; | 295 | return err; |
| 307 | } | 296 | } |
| 308 | } | 297 | } |
| 309 | 298 | ||
| 310 | flagreg &= ~RX8010_FLAG_AF; | 299 | flagreg &= ~RX8010_FLAG_AF; |
| 311 | err = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, flagreg); | 300 | err = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, flagreg); |
| 312 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 313 | if (err < 0) | 301 | if (err < 0) |
| 314 | return err; | 302 | return err; |
| 315 | 303 | ||
| @@ -404,7 +392,6 @@ static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 404 | struct rx8010_data *rx8010 = dev_get_drvdata(dev); | 392 | struct rx8010_data *rx8010 = dev_get_drvdata(dev); |
| 405 | int ret, tmp; | 393 | int ret, tmp; |
| 406 | int flagreg; | 394 | int flagreg; |
| 407 | unsigned long irqflags; | ||
| 408 | 395 | ||
| 409 | switch (cmd) { | 396 | switch (cmd) { |
| 410 | case RTC_VL_READ: | 397 | case RTC_VL_READ: |
| @@ -419,16 +406,13 @@ static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 419 | return 0; | 406 | return 0; |
| 420 | 407 | ||
| 421 | case RTC_VL_CLR: | 408 | case RTC_VL_CLR: |
| 422 | spin_lock_irqsave(&rx8010->flags_lock, irqflags); | ||
| 423 | flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG); | 409 | flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG); |
| 424 | if (flagreg < 0) { | 410 | if (flagreg < 0) { |
| 425 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 426 | return flagreg; | 411 | return flagreg; |
| 427 | } | 412 | } |
| 428 | 413 | ||
| 429 | flagreg &= ~RX8010_FLAG_VLF; | 414 | flagreg &= ~RX8010_FLAG_VLF; |
| 430 | ret = i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg); | 415 | ret = i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg); |
| 431 | spin_unlock_irqrestore(&rx8010->flags_lock, irqflags); | ||
| 432 | if (ret < 0) | 416 | if (ret < 0) |
| 433 | return ret; | 417 | return ret; |
| 434 | 418 | ||
| @@ -466,8 +450,6 @@ static int rx8010_probe(struct i2c_client *client, | |||
| 466 | rx8010->client = client; | 450 | rx8010->client = client; |
| 467 | i2c_set_clientdata(client, rx8010); | 451 | i2c_set_clientdata(client, rx8010); |
| 468 | 452 | ||
| 469 | spin_lock_init(&rx8010->flags_lock); | ||
| 470 | |||
| 471 | err = rx8010_init_client(client); | 453 | err = rx8010_init_client(client); |
| 472 | if (err) | 454 | if (err) |
| 473 | return err; | 455 | return err; |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 17b6235d67a5..c626e43a9cbb 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
| @@ -535,7 +535,7 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
| 535 | return 0; | 535 | return 0; |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | static struct rtc_class_ops sh_rtc_ops = { | 538 | static const struct rtc_class_ops sh_rtc_ops = { |
| 539 | .read_time = sh_rtc_read_time, | 539 | .read_time = sh_rtc_read_time, |
| 540 | .set_time = sh_rtc_set_time, | 540 | .set_time = sh_rtc_set_time, |
| 541 | .read_alarm = sh_rtc_read_alarm, | 541 | .read_alarm = sh_rtc_read_alarm, |
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 0f11c2a228e3..d51b07d620f7 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c | |||
| @@ -184,6 +184,7 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 184 | rtc_tm_to_time(alrm_tm, &time); | 184 | rtc_tm_to_time(alrm_tm, &time); |
| 185 | 185 | ||
| 186 | regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); | 186 | regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); |
| 187 | rtc_write_sync_lp(data); | ||
| 187 | regmap_write(data->regmap, data->offset + SNVS_LPTAR, time); | 188 | regmap_write(data->regmap, data->offset + SNVS_LPTAR, time); |
| 188 | 189 | ||
| 189 | /* Clear alarm interrupt status bit */ | 190 | /* Clear alarm interrupt status bit */ |
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c new file mode 100644 index 000000000000..bd57eb1029e1 --- /dev/null +++ b/drivers/rtc/rtc-stm32.c | |||
| @@ -0,0 +1,725 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Amelie Delaunay 2016 | ||
| 3 | * Author: Amelie Delaunay <amelie.delaunay@st.com> | ||
| 4 | * License terms: GNU General Public License (GPL), version 2 | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/bcd.h> | ||
| 8 | #include <linux/clk.h> | ||
| 9 | #include <linux/iopoll.h> | ||
| 10 | #include <linux/ioport.h> | ||
| 11 | #include <linux/mfd/syscon.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of_device.h> | ||
| 14 | #include <linux/regmap.h> | ||
| 15 | #include <linux/rtc.h> | ||
| 16 | |||
| 17 | #define DRIVER_NAME "stm32_rtc" | ||
| 18 | |||
| 19 | /* STM32 RTC registers */ | ||
| 20 | #define STM32_RTC_TR 0x00 | ||
| 21 | #define STM32_RTC_DR 0x04 | ||
| 22 | #define STM32_RTC_CR 0x08 | ||
| 23 | #define STM32_RTC_ISR 0x0C | ||
| 24 | #define STM32_RTC_PRER 0x10 | ||
| 25 | #define STM32_RTC_ALRMAR 0x1C | ||
| 26 | #define STM32_RTC_WPR 0x24 | ||
| 27 | |||
| 28 | /* STM32_RTC_TR bit fields */ | ||
| 29 | #define STM32_RTC_TR_SEC_SHIFT 0 | ||
| 30 | #define STM32_RTC_TR_SEC GENMASK(6, 0) | ||
| 31 | #define STM32_RTC_TR_MIN_SHIFT 8 | ||
| 32 | #define STM32_RTC_TR_MIN GENMASK(14, 8) | ||
| 33 | #define STM32_RTC_TR_HOUR_SHIFT 16 | ||
| 34 | #define STM32_RTC_TR_HOUR GENMASK(21, 16) | ||
| 35 | |||
| 36 | /* STM32_RTC_DR bit fields */ | ||
| 37 | #define STM32_RTC_DR_DATE_SHIFT 0 | ||
| 38 | #define STM32_RTC_DR_DATE GENMASK(5, 0) | ||
| 39 | #define STM32_RTC_DR_MONTH_SHIFT 8 | ||
| 40 | #define STM32_RTC_DR_MONTH GENMASK(12, 8) | ||
| 41 | #define STM32_RTC_DR_WDAY_SHIFT 13 | ||
| 42 | #define STM32_RTC_DR_WDAY GENMASK(15, 13) | ||
| 43 | #define STM32_RTC_DR_YEAR_SHIFT 16 | ||
| 44 | #define STM32_RTC_DR_YEAR GENMASK(23, 16) | ||
| 45 | |||
| 46 | /* STM32_RTC_CR bit fields */ | ||
| 47 | #define STM32_RTC_CR_FMT BIT(6) | ||
| 48 | #define STM32_RTC_CR_ALRAE BIT(8) | ||
| 49 | #define STM32_RTC_CR_ALRAIE BIT(12) | ||
| 50 | |||
| 51 | /* STM32_RTC_ISR bit fields */ | ||
| 52 | #define STM32_RTC_ISR_ALRAWF BIT(0) | ||
| 53 | #define STM32_RTC_ISR_INITS BIT(4) | ||
| 54 | #define STM32_RTC_ISR_RSF BIT(5) | ||
| 55 | #define STM32_RTC_ISR_INITF BIT(6) | ||
| 56 | #define STM32_RTC_ISR_INIT BIT(7) | ||
| 57 | #define STM32_RTC_ISR_ALRAF BIT(8) | ||
| 58 | |||
| 59 | /* STM32_RTC_PRER bit fields */ | ||
| 60 | #define STM32_RTC_PRER_PRED_S_SHIFT 0 | ||
| 61 | #define STM32_RTC_PRER_PRED_S GENMASK(14, 0) | ||
| 62 | #define STM32_RTC_PRER_PRED_A_SHIFT 16 | ||
| 63 | #define STM32_RTC_PRER_PRED_A GENMASK(22, 16) | ||
| 64 | |||
| 65 | /* STM32_RTC_ALRMAR and STM32_RTC_ALRMBR bit fields */ | ||
| 66 | #define STM32_RTC_ALRMXR_SEC_SHIFT 0 | ||
| 67 | #define STM32_RTC_ALRMXR_SEC GENMASK(6, 0) | ||
| 68 | #define STM32_RTC_ALRMXR_SEC_MASK BIT(7) | ||
| 69 | #define STM32_RTC_ALRMXR_MIN_SHIFT 8 | ||
| 70 | #define STM32_RTC_ALRMXR_MIN GENMASK(14, 8) | ||
| 71 | #define STM32_RTC_ALRMXR_MIN_MASK BIT(15) | ||
| 72 | #define STM32_RTC_ALRMXR_HOUR_SHIFT 16 | ||
| 73 | #define STM32_RTC_ALRMXR_HOUR GENMASK(21, 16) | ||
| 74 | #define STM32_RTC_ALRMXR_PM BIT(22) | ||
| 75 | #define STM32_RTC_ALRMXR_HOUR_MASK BIT(23) | ||
| 76 | #define STM32_RTC_ALRMXR_DATE_SHIFT 24 | ||
| 77 | #define STM32_RTC_ALRMXR_DATE GENMASK(29, 24) | ||
| 78 | #define STM32_RTC_ALRMXR_WDSEL BIT(30) | ||
| 79 | #define STM32_RTC_ALRMXR_WDAY_SHIFT 24 | ||
| 80 | #define STM32_RTC_ALRMXR_WDAY GENMASK(27, 24) | ||
| 81 | #define STM32_RTC_ALRMXR_DATE_MASK BIT(31) | ||
| 82 | |||
| 83 | /* STM32_RTC_WPR key constants */ | ||
| 84 | #define RTC_WPR_1ST_KEY 0xCA | ||
| 85 | #define RTC_WPR_2ND_KEY 0x53 | ||
| 86 | #define RTC_WPR_WRONG_KEY 0xFF | ||
| 87 | |||
| 88 | /* | ||
| 89 | * RTC registers are protected against parasitic write access. | ||
| 90 | * PWR_CR_DBP bit must be set to enable write access to RTC registers. | ||
| 91 | */ | ||
| 92 | /* STM32_PWR_CR */ | ||
| 93 | #define PWR_CR 0x00 | ||
| 94 | /* STM32_PWR_CR bit field */ | ||
| 95 | #define PWR_CR_DBP BIT(8) | ||
| 96 | |||
| 97 | struct stm32_rtc { | ||
| 98 | struct rtc_device *rtc_dev; | ||
| 99 | void __iomem *base; | ||
| 100 | struct regmap *dbp; | ||
| 101 | struct clk *ck_rtc; | ||
| 102 | int irq_alarm; | ||
| 103 | }; | ||
| 104 | |||
| 105 | static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc) | ||
| 106 | { | ||
| 107 | writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + STM32_RTC_WPR); | ||
| 108 | writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + STM32_RTC_WPR); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc) | ||
| 112 | { | ||
| 113 | writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + STM32_RTC_WPR); | ||
| 114 | } | ||
| 115 | |||
| 116 | static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc) | ||
| 117 | { | ||
| 118 | unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR); | ||
| 119 | |||
| 120 | if (!(isr & STM32_RTC_ISR_INITF)) { | ||
| 121 | isr |= STM32_RTC_ISR_INIT; | ||
| 122 | writel_relaxed(isr, rtc->base + STM32_RTC_ISR); | ||
| 123 | |||
| 124 | /* | ||
| 125 | * It takes around 2 ck_rtc clock cycles to enter in | ||
| 126 | * initialization phase mode (and have INITF flag set). As | ||
| 127 | * slowest ck_rtc frequency may be 32kHz and highest should be | ||
| 128 | * 1MHz, we poll every 10 us with a timeout of 100ms. | ||
| 129 | */ | ||
| 130 | return readl_relaxed_poll_timeout_atomic( | ||
| 131 | rtc->base + STM32_RTC_ISR, | ||
| 132 | isr, (isr & STM32_RTC_ISR_INITF), | ||
| 133 | 10, 100000); | ||
| 134 | } | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc) | ||
| 140 | { | ||
| 141 | unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR); | ||
| 142 | |||
| 143 | isr &= ~STM32_RTC_ISR_INIT; | ||
| 144 | writel_relaxed(isr, rtc->base + STM32_RTC_ISR); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int stm32_rtc_wait_sync(struct stm32_rtc *rtc) | ||
| 148 | { | ||
| 149 | unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR); | ||
| 150 | |||
| 151 | isr &= ~STM32_RTC_ISR_RSF; | ||
| 152 | writel_relaxed(isr, rtc->base + STM32_RTC_ISR); | ||
| 153 | |||
| 154 | /* | ||
| 155 | * Wait for RSF to be set to ensure the calendar registers are | ||
| 156 | * synchronised, it takes around 2 ck_rtc clock cycles | ||
| 157 | */ | ||
| 158 | return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR, | ||
| 159 | isr, | ||
| 160 | (isr & STM32_RTC_ISR_RSF), | ||
| 161 | 10, 100000); | ||
| 162 | } | ||
| 163 | |||
| 164 | static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) | ||
| 165 | { | ||
| 166 | struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id; | ||
| 167 | unsigned int isr, cr; | ||
| 168 | |||
| 169 | mutex_lock(&rtc->rtc_dev->ops_lock); | ||
| 170 | |||
| 171 | isr = readl_relaxed(rtc->base + STM32_RTC_ISR); | ||
| 172 | cr = readl_relaxed(rtc->base + STM32_RTC_CR); | ||
| 173 | |||
| 174 | if ((isr & STM32_RTC_ISR_ALRAF) && | ||
| 175 | (cr & STM32_RTC_CR_ALRAIE)) { | ||
| 176 | /* Alarm A flag - Alarm interrupt */ | ||
| 177 | dev_dbg(&rtc->rtc_dev->dev, "Alarm occurred\n"); | ||
| 178 | |||
| 179 | /* Pass event to the kernel */ | ||
| 180 | rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
| 181 | |||
| 182 | /* Clear event flag, otherwise new events won't be received */ | ||
| 183 | writel_relaxed(isr & ~STM32_RTC_ISR_ALRAF, | ||
| 184 | rtc->base + STM32_RTC_ISR); | ||
| 185 | } | ||
| 186 | |||
| 187 | mutex_unlock(&rtc->rtc_dev->ops_lock); | ||
| 188 | |||
| 189 | return IRQ_HANDLED; | ||
| 190 | } | ||
| 191 | |||
| 192 | /* Convert rtc_time structure from bin to bcd format */ | ||
| 193 | static void tm2bcd(struct rtc_time *tm) | ||
| 194 | { | ||
| 195 | tm->tm_sec = bin2bcd(tm->tm_sec); | ||
| 196 | tm->tm_min = bin2bcd(tm->tm_min); | ||
| 197 | tm->tm_hour = bin2bcd(tm->tm_hour); | ||
| 198 | |||
| 199 | tm->tm_mday = bin2bcd(tm->tm_mday); | ||
| 200 | tm->tm_mon = bin2bcd(tm->tm_mon + 1); | ||
| 201 | tm->tm_year = bin2bcd(tm->tm_year - 100); | ||
| 202 | /* | ||
| 203 | * Number of days since Sunday | ||
| 204 | * - on kernel side, 0=Sunday...6=Saturday | ||
| 205 | * - on rtc side, 0=invalid,1=Monday...7=Sunday | ||
| 206 | */ | ||
| 207 | tm->tm_wday = (!tm->tm_wday) ? 7 : tm->tm_wday; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* Convert rtc_time structure from bcd to bin format */ | ||
| 211 | static void bcd2tm(struct rtc_time *tm) | ||
| 212 | { | ||
| 213 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
| 214 | tm->tm_min = bcd2bin(tm->tm_min); | ||
| 215 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
| 216 | |||
| 217 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
| 218 | tm->tm_mon = bcd2bin(tm->tm_mon) - 1; | ||
| 219 | tm->tm_year = bcd2bin(tm->tm_year) + 100; | ||
| 220 | /* | ||
| 221 | * Number of days since Sunday | ||
| 222 | * - on kernel side, 0=Sunday...6=Saturday | ||
| 223 | * - on rtc side, 0=invalid,1=Monday...7=Sunday | ||
| 224 | */ | ||
| 225 | tm->tm_wday %= 7; | ||
| 226 | } | ||
| 227 | |||
| 228 | static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 229 | { | ||
| 230 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 231 | unsigned int tr, dr; | ||
| 232 | |||
| 233 | /* Time and Date in BCD format */ | ||
| 234 | tr = readl_relaxed(rtc->base + STM32_RTC_TR); | ||
| 235 | dr = readl_relaxed(rtc->base + STM32_RTC_DR); | ||
| 236 | |||
| 237 | tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT; | ||
| 238 | tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT; | ||
| 239 | tm->tm_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT; | ||
| 240 | |||
| 241 | tm->tm_mday = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT; | ||
| 242 | tm->tm_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT; | ||
| 243 | tm->tm_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT; | ||
| 244 | tm->tm_wday = (dr & STM32_RTC_DR_WDAY) >> STM32_RTC_DR_WDAY_SHIFT; | ||
| 245 | |||
| 246 | /* We don't report tm_yday and tm_isdst */ | ||
| 247 | |||
| 248 | bcd2tm(tm); | ||
| 249 | |||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 254 | { | ||
| 255 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 256 | unsigned int tr, dr; | ||
| 257 | int ret = 0; | ||
| 258 | |||
| 259 | tm2bcd(tm); | ||
| 260 | |||
| 261 | /* Time in BCD format */ | ||
| 262 | tr = ((tm->tm_sec << STM32_RTC_TR_SEC_SHIFT) & STM32_RTC_TR_SEC) | | ||
| 263 | ((tm->tm_min << STM32_RTC_TR_MIN_SHIFT) & STM32_RTC_TR_MIN) | | ||
| 264 | ((tm->tm_hour << STM32_RTC_TR_HOUR_SHIFT) & STM32_RTC_TR_HOUR); | ||
| 265 | |||
| 266 | /* Date in BCD format */ | ||
| 267 | dr = ((tm->tm_mday << STM32_RTC_DR_DATE_SHIFT) & STM32_RTC_DR_DATE) | | ||
| 268 | ((tm->tm_mon << STM32_RTC_DR_MONTH_SHIFT) & STM32_RTC_DR_MONTH) | | ||
| 269 | ((tm->tm_year << STM32_RTC_DR_YEAR_SHIFT) & STM32_RTC_DR_YEAR) | | ||
| 270 | ((tm->tm_wday << STM32_RTC_DR_WDAY_SHIFT) & STM32_RTC_DR_WDAY); | ||
| 271 | |||
| 272 | stm32_rtc_wpr_unlock(rtc); | ||
| 273 | |||
| 274 | ret = stm32_rtc_enter_init_mode(rtc); | ||
| 275 | if (ret) { | ||
| 276 | dev_err(dev, "Can't enter in init mode. Set time aborted.\n"); | ||
| 277 | goto end; | ||
| 278 | } | ||
| 279 | |||
| 280 | writel_relaxed(tr, rtc->base + STM32_RTC_TR); | ||
| 281 | writel_relaxed(dr, rtc->base + STM32_RTC_DR); | ||
| 282 | |||
| 283 | stm32_rtc_exit_init_mode(rtc); | ||
| 284 | |||
| 285 | ret = stm32_rtc_wait_sync(rtc); | ||
| 286 | end: | ||
| 287 | stm32_rtc_wpr_lock(rtc); | ||
| 288 | |||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 293 | { | ||
| 294 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 295 | struct rtc_time *tm = &alrm->time; | ||
| 296 | unsigned int alrmar, cr, isr; | ||
| 297 | |||
| 298 | alrmar = readl_relaxed(rtc->base + STM32_RTC_ALRMAR); | ||
| 299 | cr = readl_relaxed(rtc->base + STM32_RTC_CR); | ||
| 300 | isr = readl_relaxed(rtc->base + STM32_RTC_ISR); | ||
| 301 | |||
| 302 | if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) { | ||
| 303 | /* | ||
| 304 | * Date/day doesn't matter in Alarm comparison so alarm | ||
| 305 | * triggers every day | ||
| 306 | */ | ||
| 307 | tm->tm_mday = -1; | ||
| 308 | tm->tm_wday = -1; | ||
| 309 | } else { | ||
| 310 | if (alrmar & STM32_RTC_ALRMXR_WDSEL) { | ||
| 311 | /* Alarm is set to a day of week */ | ||
| 312 | tm->tm_mday = -1; | ||
| 313 | tm->tm_wday = (alrmar & STM32_RTC_ALRMXR_WDAY) >> | ||
| 314 | STM32_RTC_ALRMXR_WDAY_SHIFT; | ||
| 315 | tm->tm_wday %= 7; | ||
| 316 | } else { | ||
| 317 | /* Alarm is set to a day of month */ | ||
| 318 | tm->tm_wday = -1; | ||
| 319 | tm->tm_mday = (alrmar & STM32_RTC_ALRMXR_DATE) >> | ||
| 320 | STM32_RTC_ALRMXR_DATE_SHIFT; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | if (alrmar & STM32_RTC_ALRMXR_HOUR_MASK) { | ||
| 325 | /* Hours don't matter in Alarm comparison */ | ||
| 326 | tm->tm_hour = -1; | ||
| 327 | } else { | ||
| 328 | tm->tm_hour = (alrmar & STM32_RTC_ALRMXR_HOUR) >> | ||
| 329 | STM32_RTC_ALRMXR_HOUR_SHIFT; | ||
| 330 | if (alrmar & STM32_RTC_ALRMXR_PM) | ||
| 331 | tm->tm_hour += 12; | ||
| 332 | } | ||
| 333 | |||
| 334 | if (alrmar & STM32_RTC_ALRMXR_MIN_MASK) { | ||
| 335 | /* Minutes don't matter in Alarm comparison */ | ||
| 336 | tm->tm_min = -1; | ||
| 337 | } else { | ||
| 338 | tm->tm_min = (alrmar & STM32_RTC_ALRMXR_MIN) >> | ||
| 339 | STM32_RTC_ALRMXR_MIN_SHIFT; | ||
| 340 | } | ||
| 341 | |||
| 342 | if (alrmar & STM32_RTC_ALRMXR_SEC_MASK) { | ||
| 343 | /* Seconds don't matter in Alarm comparison */ | ||
| 344 | tm->tm_sec = -1; | ||
| 345 | } else { | ||
| 346 | tm->tm_sec = (alrmar & STM32_RTC_ALRMXR_SEC) >> | ||
| 347 | STM32_RTC_ALRMXR_SEC_SHIFT; | ||
| 348 | } | ||
| 349 | |||
| 350 | bcd2tm(tm); | ||
| 351 | |||
| 352 | alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0; | ||
| 353 | alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0; | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
| 359 | { | ||
| 360 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 361 | unsigned int isr, cr; | ||
| 362 | |||
| 363 | cr = readl_relaxed(rtc->base + STM32_RTC_CR); | ||
| 364 | |||
| 365 | stm32_rtc_wpr_unlock(rtc); | ||
| 366 | |||
| 367 | /* We expose Alarm A to the kernel */ | ||
| 368 | if (enabled) | ||
| 369 | cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE); | ||
| 370 | else | ||
| 371 | cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE); | ||
| 372 | writel_relaxed(cr, rtc->base + STM32_RTC_CR); | ||
| 373 | |||
| 374 | /* Clear event flag, otherwise new events won't be received */ | ||
| 375 | isr = readl_relaxed(rtc->base + STM32_RTC_ISR); | ||
| 376 | isr &= ~STM32_RTC_ISR_ALRAF; | ||
| 377 | writel_relaxed(isr, rtc->base + STM32_RTC_ISR); | ||
| 378 | |||
| 379 | stm32_rtc_wpr_lock(rtc); | ||
| 380 | |||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm) | ||
| 385 | { | ||
| 386 | int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec; | ||
| 387 | unsigned int dr = readl_relaxed(rtc->base + STM32_RTC_DR); | ||
| 388 | unsigned int tr = readl_relaxed(rtc->base + STM32_RTC_TR); | ||
| 389 | |||
| 390 | cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT; | ||
| 391 | cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT; | ||
| 392 | cur_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT; | ||
| 393 | cur_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT; | ||
| 394 | cur_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT; | ||
| 395 | cur_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT; | ||
| 396 | |||
| 397 | /* | ||
| 398 | * Assuming current date is M-D-Y H:M:S. | ||
| 399 | * RTC alarm can't be set on a specific month and year. | ||
| 400 | * So the valid alarm range is: | ||
| 401 | * M-D-Y H:M:S < alarm <= (M+1)-D-Y H:M:S | ||
| 402 | * with a specific case for December... | ||
| 403 | */ | ||
| 404 | if ((((tm->tm_year > cur_year) && | ||
| 405 | (tm->tm_mon == 0x1) && (cur_mon == 0x12)) || | ||
| 406 | ((tm->tm_year == cur_year) && | ||
| 407 | (tm->tm_mon <= cur_mon + 1))) && | ||
| 408 | ((tm->tm_mday > cur_day) || | ||
| 409 | ((tm->tm_mday == cur_day) && | ||
| 410 | ((tm->tm_hour > cur_hour) || | ||
| 411 | ((tm->tm_hour == cur_hour) && (tm->tm_min > cur_min)) || | ||
| 412 | ((tm->tm_hour == cur_hour) && (tm->tm_min == cur_min) && | ||
| 413 | (tm->tm_sec >= cur_sec)))))) | ||
| 414 | return 0; | ||
| 415 | |||
| 416 | return -EINVAL; | ||
| 417 | } | ||
| 418 | |||
| 419 | static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 420 | { | ||
| 421 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 422 | struct rtc_time *tm = &alrm->time; | ||
| 423 | unsigned int cr, isr, alrmar; | ||
| 424 | int ret = 0; | ||
| 425 | |||
| 426 | tm2bcd(tm); | ||
| 427 | |||
| 428 | /* | ||
| 429 | * RTC alarm can't be set on a specific date, unless this date is | ||
| 430 | * up to the same day of month next month. | ||
| 431 | */ | ||
| 432 | if (stm32_rtc_valid_alrm(rtc, tm) < 0) { | ||
| 433 | dev_err(dev, "Alarm can be set only on upcoming month.\n"); | ||
| 434 | return -EINVAL; | ||
| 435 | } | ||
| 436 | |||
| 437 | alrmar = 0; | ||
| 438 | /* tm_year and tm_mon are not used because not supported by RTC */ | ||
| 439 | alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) & | ||
| 440 | STM32_RTC_ALRMXR_DATE; | ||
| 441 | /* 24-hour format */ | ||
| 442 | alrmar &= ~STM32_RTC_ALRMXR_PM; | ||
| 443 | alrmar |= (tm->tm_hour << STM32_RTC_ALRMXR_HOUR_SHIFT) & | ||
| 444 | STM32_RTC_ALRMXR_HOUR; | ||
| 445 | alrmar |= (tm->tm_min << STM32_RTC_ALRMXR_MIN_SHIFT) & | ||
| 446 | STM32_RTC_ALRMXR_MIN; | ||
| 447 | alrmar |= (tm->tm_sec << STM32_RTC_ALRMXR_SEC_SHIFT) & | ||
| 448 | STM32_RTC_ALRMXR_SEC; | ||
| 449 | |||
| 450 | stm32_rtc_wpr_unlock(rtc); | ||
| 451 | |||
| 452 | /* Disable Alarm */ | ||
| 453 | cr = readl_relaxed(rtc->base + STM32_RTC_CR); | ||
| 454 | cr &= ~STM32_RTC_CR_ALRAE; | ||
| 455 | writel_relaxed(cr, rtc->base + STM32_RTC_CR); | ||
| 456 | |||
| 457 | /* | ||
| 458 | * Poll Alarm write flag to be sure that Alarm update is allowed: it | ||
| 459 | * takes around 2 ck_rtc clock cycles | ||
| 460 | */ | ||
| 461 | ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR, | ||
| 462 | isr, | ||
| 463 | (isr & STM32_RTC_ISR_ALRAWF), | ||
| 464 | 10, 100000); | ||
| 465 | |||
| 466 | if (ret) { | ||
| 467 | dev_err(dev, "Alarm update not allowed\n"); | ||
| 468 | goto end; | ||
| 469 | } | ||
| 470 | |||
| 471 | /* Write to Alarm register */ | ||
| 472 | writel_relaxed(alrmar, rtc->base + STM32_RTC_ALRMAR); | ||
| 473 | |||
| 474 | if (alrm->enabled) | ||
| 475 | stm32_rtc_alarm_irq_enable(dev, 1); | ||
| 476 | else | ||
| 477 | stm32_rtc_alarm_irq_enable(dev, 0); | ||
| 478 | |||
| 479 | end: | ||
| 480 | stm32_rtc_wpr_lock(rtc); | ||
| 481 | |||
| 482 | return ret; | ||
| 483 | } | ||
| 484 | |||
| 485 | static const struct rtc_class_ops stm32_rtc_ops = { | ||
| 486 | .read_time = stm32_rtc_read_time, | ||
| 487 | .set_time = stm32_rtc_set_time, | ||
| 488 | .read_alarm = stm32_rtc_read_alarm, | ||
| 489 | .set_alarm = stm32_rtc_set_alarm, | ||
| 490 | .alarm_irq_enable = stm32_rtc_alarm_irq_enable, | ||
| 491 | }; | ||
| 492 | |||
| 493 | static const struct of_device_id stm32_rtc_of_match[] = { | ||
| 494 | { .compatible = "st,stm32-rtc" }, | ||
| 495 | {} | ||
| 496 | }; | ||
| 497 | MODULE_DEVICE_TABLE(of, stm32_rtc_of_match); | ||
| 498 | |||
| 499 | static int stm32_rtc_init(struct platform_device *pdev, | ||
| 500 | struct stm32_rtc *rtc) | ||
| 501 | { | ||
| 502 | unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr; | ||
| 503 | unsigned int rate; | ||
| 504 | int ret = 0; | ||
| 505 | |||
| 506 | rate = clk_get_rate(rtc->ck_rtc); | ||
| 507 | |||
| 508 | /* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */ | ||
| 509 | pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT; | ||
| 510 | pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT; | ||
| 511 | |||
| 512 | for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) { | ||
| 513 | pred_s = (rate / (pred_a + 1)) - 1; | ||
| 514 | |||
| 515 | if (((pred_s + 1) * (pred_a + 1)) == rate) | ||
| 516 | break; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* | ||
| 520 | * Can't find a 1Hz, so give priority to RTC power consumption | ||
| 521 | * by choosing the higher possible value for prediv_a | ||
| 522 | */ | ||
| 523 | if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) { | ||
| 524 | pred_a = pred_a_max; | ||
| 525 | pred_s = (rate / (pred_a + 1)) - 1; | ||
| 526 | |||
| 527 | dev_warn(&pdev->dev, "ck_rtc is %s\n", | ||
| 528 | (rate < ((pred_a + 1) * (pred_s + 1))) ? | ||
| 529 | "fast" : "slow"); | ||
| 530 | } | ||
| 531 | |||
| 532 | stm32_rtc_wpr_unlock(rtc); | ||
| 533 | |||
| 534 | ret = stm32_rtc_enter_init_mode(rtc); | ||
| 535 | if (ret) { | ||
| 536 | dev_err(&pdev->dev, | ||
| 537 | "Can't enter in init mode. Prescaler config failed.\n"); | ||
| 538 | goto end; | ||
| 539 | } | ||
| 540 | |||
| 541 | prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S; | ||
| 542 | writel_relaxed(prer, rtc->base + STM32_RTC_PRER); | ||
| 543 | prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A; | ||
| 544 | writel_relaxed(prer, rtc->base + STM32_RTC_PRER); | ||
| 545 | |||
| 546 | /* Force 24h time format */ | ||
| 547 | cr = readl_relaxed(rtc->base + STM32_RTC_CR); | ||
| 548 | cr &= ~STM32_RTC_CR_FMT; | ||
| 549 | writel_relaxed(cr, rtc->base + STM32_RTC_CR); | ||
| 550 | |||
| 551 | stm32_rtc_exit_init_mode(rtc); | ||
| 552 | |||
| 553 | ret = stm32_rtc_wait_sync(rtc); | ||
| 554 | end: | ||
| 555 | stm32_rtc_wpr_lock(rtc); | ||
| 556 | |||
| 557 | return ret; | ||
| 558 | } | ||
| 559 | |||
| 560 | static int stm32_rtc_probe(struct platform_device *pdev) | ||
| 561 | { | ||
| 562 | struct stm32_rtc *rtc; | ||
| 563 | struct resource *res; | ||
| 564 | int ret; | ||
| 565 | |||
| 566 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
| 567 | if (!rtc) | ||
| 568 | return -ENOMEM; | ||
| 569 | |||
| 570 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 571 | rtc->base = devm_ioremap_resource(&pdev->dev, res); | ||
| 572 | if (IS_ERR(rtc->base)) | ||
| 573 | return PTR_ERR(rtc->base); | ||
| 574 | |||
| 575 | rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
| 576 | "st,syscfg"); | ||
| 577 | if (IS_ERR(rtc->dbp)) { | ||
| 578 | dev_err(&pdev->dev, "no st,syscfg\n"); | ||
| 579 | return PTR_ERR(rtc->dbp); | ||
| 580 | } | ||
| 581 | |||
| 582 | rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL); | ||
| 583 | if (IS_ERR(rtc->ck_rtc)) { | ||
| 584 | dev_err(&pdev->dev, "no ck_rtc clock"); | ||
| 585 | return PTR_ERR(rtc->ck_rtc); | ||
| 586 | } | ||
| 587 | |||
| 588 | ret = clk_prepare_enable(rtc->ck_rtc); | ||
| 589 | if (ret) | ||
| 590 | return ret; | ||
| 591 | |||
| 592 | regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP); | ||
| 593 | |||
| 594 | /* | ||
| 595 | * After a system reset, RTC_ISR.INITS flag can be read to check if | ||
| 596 | * the calendar has been initalized or not. INITS flag is reset by a | ||
| 597 | * power-on reset (no vbat, no power-supply). It is not reset if | ||
| 598 | * ck_rtc parent clock has changed (so RTC prescalers need to be | ||
| 599 | * changed). That's why we cannot rely on this flag to know if RTC | ||
| 600 | * init has to be done. | ||
| 601 | */ | ||
| 602 | ret = stm32_rtc_init(pdev, rtc); | ||
| 603 | if (ret) | ||
| 604 | goto err; | ||
| 605 | |||
| 606 | rtc->irq_alarm = platform_get_irq(pdev, 0); | ||
| 607 | if (rtc->irq_alarm <= 0) { | ||
| 608 | dev_err(&pdev->dev, "no alarm irq\n"); | ||
| 609 | ret = rtc->irq_alarm; | ||
| 610 | goto err; | ||
| 611 | } | ||
| 612 | |||
| 613 | platform_set_drvdata(pdev, rtc); | ||
| 614 | |||
| 615 | ret = device_init_wakeup(&pdev->dev, true); | ||
| 616 | if (ret) | ||
| 617 | dev_warn(&pdev->dev, | ||
| 618 | "alarm won't be able to wake up the system"); | ||
| 619 | |||
| 620 | rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, | ||
| 621 | &stm32_rtc_ops, THIS_MODULE); | ||
| 622 | if (IS_ERR(rtc->rtc_dev)) { | ||
| 623 | ret = PTR_ERR(rtc->rtc_dev); | ||
| 624 | dev_err(&pdev->dev, "rtc device registration failed, err=%d\n", | ||
| 625 | ret); | ||
| 626 | goto err; | ||
| 627 | } | ||
| 628 | |||
| 629 | /* Handle RTC alarm interrupts */ | ||
| 630 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL, | ||
| 631 | stm32_rtc_alarm_irq, | ||
| 632 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
| 633 | pdev->name, rtc); | ||
| 634 | if (ret) { | ||
| 635 | dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n", | ||
| 636 | rtc->irq_alarm); | ||
| 637 | goto err; | ||
| 638 | } | ||
| 639 | |||
| 640 | /* | ||
| 641 | * If INITS flag is reset (calendar year field set to 0x00), calendar | ||
| 642 | * must be initialized | ||
| 643 | */ | ||
| 644 | if (!(readl_relaxed(rtc->base + STM32_RTC_ISR) & STM32_RTC_ISR_INITS)) | ||
| 645 | dev_warn(&pdev->dev, "Date/Time must be initialized\n"); | ||
| 646 | |||
| 647 | return 0; | ||
| 648 | err: | ||
| 649 | clk_disable_unprepare(rtc->ck_rtc); | ||
| 650 | |||
| 651 | regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0); | ||
| 652 | |||
| 653 | device_init_wakeup(&pdev->dev, false); | ||
| 654 | |||
| 655 | return ret; | ||
| 656 | } | ||
| 657 | |||
| 658 | static int stm32_rtc_remove(struct platform_device *pdev) | ||
| 659 | { | ||
| 660 | struct stm32_rtc *rtc = platform_get_drvdata(pdev); | ||
| 661 | unsigned int cr; | ||
| 662 | |||
| 663 | /* Disable interrupts */ | ||
| 664 | stm32_rtc_wpr_unlock(rtc); | ||
| 665 | cr = readl_relaxed(rtc->base + STM32_RTC_CR); | ||
| 666 | cr &= ~STM32_RTC_CR_ALRAIE; | ||
| 667 | writel_relaxed(cr, rtc->base + STM32_RTC_CR); | ||
| 668 | stm32_rtc_wpr_lock(rtc); | ||
| 669 | |||
| 670 | clk_disable_unprepare(rtc->ck_rtc); | ||
| 671 | |||
| 672 | /* Enable backup domain write protection */ | ||
| 673 | regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0); | ||
| 674 | |||
| 675 | device_init_wakeup(&pdev->dev, false); | ||
| 676 | |||
| 677 | return 0; | ||
| 678 | } | ||
| 679 | |||
| 680 | #ifdef CONFIG_PM_SLEEP | ||
| 681 | static int stm32_rtc_suspend(struct device *dev) | ||
| 682 | { | ||
| 683 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 684 | |||
| 685 | if (device_may_wakeup(dev)) | ||
| 686 | return enable_irq_wake(rtc->irq_alarm); | ||
| 687 | |||
| 688 | return 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | static int stm32_rtc_resume(struct device *dev) | ||
| 692 | { | ||
| 693 | struct stm32_rtc *rtc = dev_get_drvdata(dev); | ||
| 694 | int ret = 0; | ||
| 695 | |||
| 696 | ret = stm32_rtc_wait_sync(rtc); | ||
| 697 | if (ret < 0) | ||
| 698 | return ret; | ||
| 699 | |||
| 700 | if (device_may_wakeup(dev)) | ||
| 701 | return disable_irq_wake(rtc->irq_alarm); | ||
| 702 | |||
| 703 | return ret; | ||
| 704 | } | ||
| 705 | #endif | ||
| 706 | |||
| 707 | static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops, | ||
| 708 | stm32_rtc_suspend, stm32_rtc_resume); | ||
| 709 | |||
| 710 | static struct platform_driver stm32_rtc_driver = { | ||
| 711 | .probe = stm32_rtc_probe, | ||
| 712 | .remove = stm32_rtc_remove, | ||
| 713 | .driver = { | ||
| 714 | .name = DRIVER_NAME, | ||
| 715 | .pm = &stm32_rtc_pm_ops, | ||
| 716 | .of_match_table = stm32_rtc_of_match, | ||
| 717 | }, | ||
| 718 | }; | ||
| 719 | |||
| 720 | module_platform_driver(stm32_rtc_driver); | ||
| 721 | |||
| 722 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
| 723 | MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>"); | ||
| 724 | MODULE_DESCRIPTION("STMicroelectronics STM32 Real Time Clock driver"); | ||
| 725 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index c169a2cd4727..39cbc1238b92 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | * more details. | 20 | * more details. |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/clk.h> | ||
| 24 | #include <linux/clk-provider.h> | ||
| 23 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 24 | #include <linux/err.h> | 26 | #include <linux/err.h> |
| 25 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
| @@ -33,15 +35,20 @@ | |||
| 33 | #include <linux/of_device.h> | 35 | #include <linux/of_device.h> |
| 34 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
| 35 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
| 38 | #include <linux/slab.h> | ||
| 36 | #include <linux/types.h> | 39 | #include <linux/types.h> |
| 37 | 40 | ||
| 38 | /* Control register */ | 41 | /* Control register */ |
| 39 | #define SUN6I_LOSC_CTRL 0x0000 | 42 | #define SUN6I_LOSC_CTRL 0x0000 |
| 43 | #define SUN6I_LOSC_CTRL_KEY (0x16aa << 16) | ||
| 40 | #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) | 44 | #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) |
| 41 | #define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) | 45 | #define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) |
| 42 | #define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) | 46 | #define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) |
| 47 | #define SUN6I_LOSC_CTRL_EXT_OSC BIT(0) | ||
| 43 | #define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) | 48 | #define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) |
| 44 | 49 | ||
| 50 | #define SUN6I_LOSC_CLK_PRESCAL 0x0008 | ||
| 51 | |||
| 45 | /* RTC */ | 52 | /* RTC */ |
| 46 | #define SUN6I_RTC_YMD 0x0010 | 53 | #define SUN6I_RTC_YMD 0x0010 |
| 47 | #define SUN6I_RTC_HMS 0x0014 | 54 | #define SUN6I_RTC_HMS 0x0014 |
| @@ -114,13 +121,142 @@ struct sun6i_rtc_dev { | |||
| 114 | void __iomem *base; | 121 | void __iomem *base; |
| 115 | int irq; | 122 | int irq; |
| 116 | unsigned long alarm; | 123 | unsigned long alarm; |
| 124 | |||
| 125 | struct clk_hw hw; | ||
| 126 | struct clk_hw *int_osc; | ||
| 127 | struct clk *losc; | ||
| 128 | |||
| 129 | spinlock_t lock; | ||
| 130 | }; | ||
| 131 | |||
| 132 | static struct sun6i_rtc_dev *sun6i_rtc; | ||
| 133 | |||
| 134 | static 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 | |||
| 150 | static 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 | |||
| 157 | static 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 | |||
| 177 | static 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, | ||
| 117 | }; | 182 | }; |
| 118 | 183 | ||
| 184 | static 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 (IS_ERR(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 | /* Yes, I know, this is ugly. */ | ||
| 215 | sun6i_rtc = rtc; | ||
| 216 | |||
| 217 | /* Deal with old DTs */ | ||
| 218 | if (!of_get_property(node, "clocks", NULL)) | ||
| 219 | return; | ||
| 220 | |||
| 221 | rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL, | ||
| 222 | "rtc-int-osc", | ||
| 223 | NULL, 0, | ||
| 224 | 667000, | ||
| 225 | 300000000); | ||
| 226 | if (IS_ERR(rtc->int_osc)) { | ||
| 227 | pr_crit("Couldn't register the internal oscillator\n"); | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | |||
| 231 | parents[0] = clk_hw_get_name(rtc->int_osc); | ||
| 232 | parents[1] = of_clk_get_parent_name(node, 0); | ||
| 233 | |||
| 234 | rtc->hw.init = &init; | ||
| 235 | |||
| 236 | init.parent_names = parents; | ||
| 237 | init.num_parents = of_clk_get_parent_count(node) + 1; | ||
| 238 | of_property_read_string(node, "clock-output-names", &init.name); | ||
| 239 | |||
| 240 | rtc->losc = clk_register(NULL, &rtc->hw); | ||
| 241 | if (IS_ERR(rtc->losc)) { | ||
| 242 | pr_crit("Couldn't register the LOSC clock\n"); | ||
| 243 | return; | ||
| 244 | } | ||
| 245 | |||
| 246 | clk_data->num = 1; | ||
| 247 | clk_data->hws[0] = &rtc->hw; | ||
| 248 | of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); | ||
| 249 | } | ||
| 250 | CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc", | ||
| 251 | sun6i_rtc_clk_init); | ||
| 252 | |||
| 119 | static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) | 253 | static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) |
| 120 | { | 254 | { |
| 121 | struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; | 255 | struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; |
| 256 | irqreturn_t ret = IRQ_NONE; | ||
| 122 | u32 val; | 257 | u32 val; |
| 123 | 258 | ||
| 259 | spin_lock(&chip->lock); | ||
| 124 | val = readl(chip->base + SUN6I_ALRM_IRQ_STA); | 260 | val = readl(chip->base + SUN6I_ALRM_IRQ_STA); |
| 125 | 261 | ||
| 126 | if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { | 262 | if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { |
| @@ -129,10 +265,11 @@ static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) | |||
| 129 | 265 | ||
| 130 | rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); | 266 | rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); |
| 131 | 267 | ||
| 132 | return IRQ_HANDLED; | 268 | ret = IRQ_HANDLED; |
| 133 | } | 269 | } |
| 270 | spin_unlock(&chip->lock); | ||
| 134 | 271 | ||
| 135 | return IRQ_NONE; | 272 | return ret; |
| 136 | } | 273 | } |
| 137 | 274 | ||
| 138 | static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) | 275 | static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) |
| @@ -140,6 +277,7 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) | |||
| 140 | u32 alrm_val = 0; | 277 | u32 alrm_val = 0; |
| 141 | u32 alrm_irq_val = 0; | 278 | u32 alrm_irq_val = 0; |
| 142 | u32 alrm_wake_val = 0; | 279 | u32 alrm_wake_val = 0; |
| 280 | unsigned long flags; | ||
| 143 | 281 | ||
| 144 | if (to) { | 282 | if (to) { |
| 145 | alrm_val = SUN6I_ALRM_EN_CNT_EN; | 283 | alrm_val = SUN6I_ALRM_EN_CNT_EN; |
| @@ -150,9 +288,11 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) | |||
| 150 | chip->base + SUN6I_ALRM_IRQ_STA); | 288 | chip->base + SUN6I_ALRM_IRQ_STA); |
| 151 | } | 289 | } |
| 152 | 290 | ||
| 291 | spin_lock_irqsave(&chip->lock, flags); | ||
| 153 | writel(alrm_val, chip->base + SUN6I_ALRM_EN); | 292 | writel(alrm_val, chip->base + SUN6I_ALRM_EN); |
| 154 | writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); | 293 | writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); |
| 155 | writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); | 294 | writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); |
| 295 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 156 | } | 296 | } |
| 157 | 297 | ||
| 158 | static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | 298 | static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) |
| @@ -191,11 +331,15 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
| 191 | static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) | 331 | static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
| 192 | { | 332 | { |
| 193 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); | 333 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
| 334 | unsigned long flags; | ||
| 194 | u32 alrm_st; | 335 | u32 alrm_st; |
| 195 | u32 alrm_en; | 336 | u32 alrm_en; |
| 196 | 337 | ||
| 338 | spin_lock_irqsave(&chip->lock, flags); | ||
| 197 | alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); | 339 | alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); |
| 198 | alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); | 340 | alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); |
| 341 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 342 | |||
| 199 | wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); | 343 | wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); |
| 200 | wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); | 344 | wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); |
| 201 | rtc_time_to_tm(chip->alarm, &wkalrm->time); | 345 | rtc_time_to_tm(chip->alarm, &wkalrm->time); |
| @@ -349,22 +493,15 @@ static const struct rtc_class_ops sun6i_rtc_ops = { | |||
| 349 | 493 | ||
| 350 | static int sun6i_rtc_probe(struct platform_device *pdev) | 494 | static int sun6i_rtc_probe(struct platform_device *pdev) |
| 351 | { | 495 | { |
| 352 | struct sun6i_rtc_dev *chip; | 496 | struct sun6i_rtc_dev *chip = sun6i_rtc; |
| 353 | struct resource *res; | ||
| 354 | int ret; | 497 | int ret; |
| 355 | 498 | ||
| 356 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); | ||
| 357 | if (!chip) | 499 | if (!chip) |
| 358 | return -ENOMEM; | 500 | return -ENODEV; |
| 359 | 501 | ||
| 360 | platform_set_drvdata(pdev, chip); | 502 | platform_set_drvdata(pdev, chip); |
| 361 | chip->dev = &pdev->dev; | 503 | chip->dev = &pdev->dev; |
| 362 | 504 | ||
| 363 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 364 | chip->base = devm_ioremap_resource(&pdev->dev, res); | ||
| 365 | if (IS_ERR(chip->base)) | ||
| 366 | return PTR_ERR(chip->base); | ||
| 367 | |||
| 368 | chip->irq = platform_get_irq(pdev, 0); | 505 | chip->irq = platform_get_irq(pdev, 0); |
| 369 | if (chip->irq < 0) { | 506 | if (chip->irq < 0) { |
| 370 | dev_err(&pdev->dev, "No IRQ resource\n"); | 507 | dev_err(&pdev->dev, "No IRQ resource\n"); |
| @@ -404,8 +541,10 @@ static int sun6i_rtc_probe(struct platform_device *pdev) | |||
| 404 | /* disable alarm wakeup */ | 541 | /* disable alarm wakeup */ |
| 405 | writel(0, chip->base + SUN6I_ALARM_CONFIG); | 542 | writel(0, chip->base + SUN6I_ALARM_CONFIG); |
| 406 | 543 | ||
| 407 | chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, | 544 | clk_prepare_enable(chip->losc); |
| 408 | &sun6i_rtc_ops, THIS_MODULE); | 545 | |
| 546 | chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-sun6i", | ||
| 547 | &sun6i_rtc_ops, THIS_MODULE); | ||
| 409 | if (IS_ERR(chip->rtc)) { | 548 | if (IS_ERR(chip->rtc)) { |
| 410 | dev_err(&pdev->dev, "unable to register device\n"); | 549 | dev_err(&pdev->dev, "unable to register device\n"); |
| 411 | return PTR_ERR(chip->rtc); | 550 | return PTR_ERR(chip->rtc); |
| @@ -416,15 +555,6 @@ static int sun6i_rtc_probe(struct platform_device *pdev) | |||
| 416 | return 0; | 555 | return 0; |
| 417 | } | 556 | } |
| 418 | 557 | ||
| 419 | static int sun6i_rtc_remove(struct platform_device *pdev) | ||
| 420 | { | ||
| 421 | struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); | ||
| 422 | |||
| 423 | rtc_device_unregister(chip->rtc); | ||
| 424 | |||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static const struct of_device_id sun6i_rtc_dt_ids[] = { | 558 | static const struct of_device_id sun6i_rtc_dt_ids[] = { |
| 429 | { .compatible = "allwinner,sun6i-a31-rtc" }, | 559 | { .compatible = "allwinner,sun6i-a31-rtc" }, |
| 430 | { /* sentinel */ }, | 560 | { /* sentinel */ }, |
| @@ -433,15 +563,9 @@ MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); | |||
| 433 | 563 | ||
| 434 | static struct platform_driver sun6i_rtc_driver = { | 564 | static struct platform_driver sun6i_rtc_driver = { |
| 435 | .probe = sun6i_rtc_probe, | 565 | .probe = sun6i_rtc_probe, |
| 436 | .remove = sun6i_rtc_remove, | ||
| 437 | .driver = { | 566 | .driver = { |
| 438 | .name = "sun6i-rtc", | 567 | .name = "sun6i-rtc", |
| 439 | .of_match_table = sun6i_rtc_dt_ids, | 568 | .of_match_table = sun6i_rtc_dt_ids, |
| 440 | }, | 569 | }, |
| 441 | }; | 570 | }; |
| 442 | 571 | builtin_platform_driver(sun6i_rtc_driver); | |
| 443 | module_platform_driver(sun6i_rtc_driver); | ||
| 444 | |||
| 445 | MODULE_DESCRIPTION("sun6i RTC driver"); | ||
| 446 | MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); | ||
| 447 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 3853ba963bb5..d30d57b048d3 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c | |||
| @@ -17,16 +17,18 @@ | |||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | 17 | * with this program; if not, write to the Free Software Foundation, Inc., |
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | */ | 19 | */ |
| 20 | #include <linux/kernel.h> | 20 | |
| 21 | #include <linux/clk.h> | ||
| 22 | #include <linux/delay.h> | ||
| 21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/irq.h> | ||
| 25 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 26 | #include <linux/delay.h> | 25 | #include <linux/irq.h> |
| 27 | #include <linux/rtc.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
| 29 | #include <linux/pm.h> | 29 | #include <linux/pm.h> |
| 30 | #include <linux/rtc.h> | ||
| 31 | #include <linux/slab.h> | ||
| 30 | 32 | ||
| 31 | /* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */ | 33 | /* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */ |
| 32 | #define TEGRA_RTC_REG_BUSY 0x004 | 34 | #define TEGRA_RTC_REG_BUSY 0x004 |
| @@ -59,6 +61,7 @@ struct tegra_rtc_info { | |||
| 59 | struct platform_device *pdev; | 61 | struct platform_device *pdev; |
| 60 | struct rtc_device *rtc_dev; | 62 | struct rtc_device *rtc_dev; |
| 61 | void __iomem *rtc_base; /* NULL if not initialized. */ | 63 | void __iomem *rtc_base; /* NULL if not initialized. */ |
| 64 | struct clk *clk; | ||
| 62 | int tegra_rtc_irq; /* alarm and periodic irq */ | 65 | int tegra_rtc_irq; /* alarm and periodic irq */ |
| 63 | spinlock_t tegra_rtc_lock; | 66 | spinlock_t tegra_rtc_lock; |
| 64 | }; | 67 | }; |
| @@ -326,6 +329,14 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) | |||
| 326 | if (info->tegra_rtc_irq <= 0) | 329 | if (info->tegra_rtc_irq <= 0) |
| 327 | return -EBUSY; | 330 | return -EBUSY; |
| 328 | 331 | ||
| 332 | info->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 333 | if (IS_ERR(info->clk)) | ||
| 334 | return PTR_ERR(info->clk); | ||
| 335 | |||
| 336 | ret = clk_prepare_enable(info->clk); | ||
| 337 | if (ret < 0) | ||
| 338 | return ret; | ||
| 339 | |||
| 329 | /* set context info. */ | 340 | /* set context info. */ |
| 330 | info->pdev = pdev; | 341 | info->pdev = pdev; |
| 331 | spin_lock_init(&info->tegra_rtc_lock); | 342 | spin_lock_init(&info->tegra_rtc_lock); |
| @@ -346,7 +357,7 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) | |||
| 346 | ret = PTR_ERR(info->rtc_dev); | 357 | ret = PTR_ERR(info->rtc_dev); |
| 347 | dev_err(&pdev->dev, "Unable to register device (err=%d).\n", | 358 | dev_err(&pdev->dev, "Unable to register device (err=%d).\n", |
| 348 | ret); | 359 | ret); |
| 349 | return ret; | 360 | goto disable_clk; |
| 350 | } | 361 | } |
| 351 | 362 | ||
| 352 | ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, | 363 | ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, |
| @@ -356,12 +367,25 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) | |||
| 356 | dev_err(&pdev->dev, | 367 | dev_err(&pdev->dev, |
| 357 | "Unable to request interrupt for device (err=%d).\n", | 368 | "Unable to request interrupt for device (err=%d).\n", |
| 358 | ret); | 369 | ret); |
| 359 | return ret; | 370 | goto disable_clk; |
| 360 | } | 371 | } |
| 361 | 372 | ||
| 362 | dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); | 373 | dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); |
| 363 | 374 | ||
| 364 | return 0; | 375 | return 0; |
| 376 | |||
| 377 | disable_clk: | ||
| 378 | clk_disable_unprepare(info->clk); | ||
| 379 | return ret; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int tegra_rtc_remove(struct platform_device *pdev) | ||
| 383 | { | ||
| 384 | struct tegra_rtc_info *info = platform_get_drvdata(pdev); | ||
| 385 | |||
| 386 | clk_disable_unprepare(info->clk); | ||
| 387 | |||
| 388 | return 0; | ||
| 365 | } | 389 | } |
| 366 | 390 | ||
| 367 | #ifdef CONFIG_PM_SLEEP | 391 | #ifdef CONFIG_PM_SLEEP |
| @@ -413,6 +437,7 @@ static void tegra_rtc_shutdown(struct platform_device *pdev) | |||
| 413 | 437 | ||
| 414 | MODULE_ALIAS("platform:tegra_rtc"); | 438 | MODULE_ALIAS("platform:tegra_rtc"); |
| 415 | static struct platform_driver tegra_rtc_driver = { | 439 | static struct platform_driver tegra_rtc_driver = { |
| 440 | .remove = tegra_rtc_remove, | ||
| 416 | .shutdown = tegra_rtc_shutdown, | 441 | .shutdown = tegra_rtc_shutdown, |
| 417 | .driver = { | 442 | .driver = { |
| 418 | .name = "tegra_rtc", | 443 | .name = "tegra_rtc", |
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 5a3d53caa485..d0244d7979fc 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
| 22 | #include <linux/rtc.h> | 22 | #include <linux/rtc.h> |
| 23 | #include <linux/bcd.h> | 23 | #include <linux/bcd.h> |
| 24 | #include <linux/math64.h> | ||
| 24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 25 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
| 26 | #include <linux/mfd/tps65910.h> | 27 | #include <linux/mfd/tps65910.h> |
| @@ -33,7 +34,21 @@ struct tps65910_rtc { | |||
| 33 | /* Total number of RTC registers needed to set time*/ | 34 | /* Total number of RTC registers needed to set time*/ |
| 34 | #define NUM_TIME_REGS (TPS65910_YEARS - TPS65910_SECONDS + 1) | 35 | #define NUM_TIME_REGS (TPS65910_YEARS - TPS65910_SECONDS + 1) |
| 35 | 36 | ||
| 36 | static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | 37 | /* Total number of RTC registers needed to set compensation registers */ |
| 38 | #define NUM_COMP_REGS (TPS65910_RTC_COMP_MSB - TPS65910_RTC_COMP_LSB + 1) | ||
| 39 | |||
| 40 | /* Min and max values supported with 'offset' interface (swapped sign) */ | ||
| 41 | #define MIN_OFFSET (-277761) | ||
| 42 | #define MAX_OFFSET (277778) | ||
| 43 | |||
| 44 | /* Number of ticks per hour */ | ||
| 45 | #define TICKS_PER_HOUR (32768 * 3600) | ||
| 46 | |||
| 47 | /* Multiplier for ppb conversions */ | ||
| 48 | #define PPB_MULT (1000000000LL) | ||
| 49 | |||
| 50 | static int tps65910_rtc_alarm_irq_enable(struct device *dev, | ||
| 51 | unsigned int enabled) | ||
| 37 | { | 52 | { |
| 38 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | 53 | struct tps65910 *tps = dev_get_drvdata(dev->parent); |
| 39 | u8 val = 0; | 54 | u8 val = 0; |
| @@ -187,6 +202,133 @@ static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
| 187 | return ret; | 202 | return ret; |
| 188 | } | 203 | } |
| 189 | 204 | ||
| 205 | static int tps65910_rtc_set_calibration(struct device *dev, int calibration) | ||
| 206 | { | ||
| 207 | unsigned char comp_data[NUM_COMP_REGS]; | ||
| 208 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
| 209 | s16 value; | ||
| 210 | int ret; | ||
| 211 | |||
| 212 | /* | ||
| 213 | * TPS65910 uses two's complement 16 bit value for compensation for RTC | ||
| 214 | * crystal inaccuracies. One time every hour when seconds counter | ||
| 215 | * increments from 0 to 1 compensation value will be added to internal | ||
| 216 | * RTC counter value. | ||
| 217 | * | ||
| 218 | * Compensation value 0x7FFF is prohibited value. | ||
| 219 | * | ||
| 220 | * Valid range for compensation value: [-32768 .. 32766] | ||
| 221 | */ | ||
| 222 | if ((calibration < -32768) || (calibration > 32766)) { | ||
| 223 | dev_err(dev, "RTC calibration value out of range: %d\n", | ||
| 224 | calibration); | ||
| 225 | return -EINVAL; | ||
| 226 | } | ||
| 227 | |||
| 228 | value = (s16)calibration; | ||
| 229 | |||
| 230 | comp_data[0] = (u16)value & 0xFF; | ||
| 231 | comp_data[1] = ((u16)value >> 8) & 0xFF; | ||
| 232 | |||
| 233 | /* Update all the compensation registers in one shot */ | ||
| 234 | ret = regmap_bulk_write(tps->regmap, TPS65910_RTC_COMP_LSB, | ||
| 235 | comp_data, NUM_COMP_REGS); | ||
| 236 | if (ret < 0) { | ||
| 237 | dev_err(dev, "rtc_set_calibration error: %d\n", ret); | ||
| 238 | return ret; | ||
| 239 | } | ||
| 240 | |||
| 241 | /* Enable automatic compensation */ | ||
| 242 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, | ||
| 243 | TPS65910_RTC_CTRL_AUTO_COMP, TPS65910_RTC_CTRL_AUTO_COMP); | ||
| 244 | if (ret < 0) | ||
| 245 | dev_err(dev, "auto_comp enable failed with error: %d\n", ret); | ||
| 246 | |||
| 247 | return ret; | ||
| 248 | } | ||
| 249 | |||
| 250 | static int tps65910_rtc_get_calibration(struct device *dev, int *calibration) | ||
| 251 | { | ||
| 252 | unsigned char comp_data[NUM_COMP_REGS]; | ||
| 253 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
| 254 | unsigned int ctrl; | ||
| 255 | u16 value; | ||
| 256 | int ret; | ||
| 257 | |||
| 258 | ret = regmap_read(tps->regmap, TPS65910_RTC_CTRL, &ctrl); | ||
| 259 | if (ret < 0) | ||
| 260 | return ret; | ||
| 261 | |||
| 262 | /* If automatic compensation is not enabled report back zero */ | ||
| 263 | if (!(ctrl & TPS65910_RTC_CTRL_AUTO_COMP)) { | ||
| 264 | *calibration = 0; | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | ret = regmap_bulk_read(tps->regmap, TPS65910_RTC_COMP_LSB, comp_data, | ||
| 269 | NUM_COMP_REGS); | ||
| 270 | if (ret < 0) { | ||
| 271 | dev_err(dev, "rtc_get_calibration error: %d\n", ret); | ||
| 272 | return ret; | ||
| 273 | } | ||
| 274 | |||
| 275 | value = (u16)comp_data[0] | ((u16)comp_data[1] << 8); | ||
| 276 | |||
| 277 | *calibration = (s16)value; | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int tps65910_read_offset(struct device *dev, long *offset) | ||
| 283 | { | ||
| 284 | int calibration; | ||
| 285 | s64 tmp; | ||
| 286 | int ret; | ||
| 287 | |||
| 288 | ret = tps65910_rtc_get_calibration(dev, &calibration); | ||
| 289 | if (ret < 0) | ||
| 290 | return ret; | ||
| 291 | |||
| 292 | /* Convert from RTC calibration register format to ppb format */ | ||
| 293 | tmp = calibration * (s64)PPB_MULT; | ||
| 294 | if (tmp < 0) | ||
| 295 | tmp -= TICKS_PER_HOUR / 2LL; | ||
| 296 | else | ||
| 297 | tmp += TICKS_PER_HOUR / 2LL; | ||
| 298 | tmp = div_s64(tmp, TICKS_PER_HOUR); | ||
| 299 | |||
| 300 | /* Offset value operates in negative way, so swap sign */ | ||
| 301 | *offset = (long)-tmp; | ||
| 302 | |||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static int tps65910_set_offset(struct device *dev, long offset) | ||
| 307 | { | ||
| 308 | int calibration; | ||
| 309 | s64 tmp; | ||
| 310 | int ret; | ||
| 311 | |||
| 312 | /* Make sure offset value is within supported range */ | ||
| 313 | if (offset < MIN_OFFSET || offset > MAX_OFFSET) | ||
| 314 | return -ERANGE; | ||
| 315 | |||
| 316 | /* Convert from ppb format to RTC calibration register format */ | ||
| 317 | tmp = offset * (s64)TICKS_PER_HOUR; | ||
| 318 | if (tmp < 0) | ||
| 319 | tmp -= PPB_MULT / 2LL; | ||
| 320 | else | ||
| 321 | tmp += PPB_MULT / 2LL; | ||
| 322 | tmp = div_s64(tmp, PPB_MULT); | ||
| 323 | |||
| 324 | /* Offset value operates in negative way, so swap sign */ | ||
| 325 | calibration = (int)-tmp; | ||
| 326 | |||
| 327 | ret = tps65910_rtc_set_calibration(dev, calibration); | ||
| 328 | |||
| 329 | return ret; | ||
| 330 | } | ||
| 331 | |||
| 190 | static irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc) | 332 | static irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc) |
| 191 | { | 333 | { |
| 192 | struct device *dev = rtc; | 334 | struct device *dev = rtc; |
| @@ -219,6 +361,8 @@ static const struct rtc_class_ops tps65910_rtc_ops = { | |||
| 219 | .read_alarm = tps65910_rtc_read_alarm, | 361 | .read_alarm = tps65910_rtc_read_alarm, |
| 220 | .set_alarm = tps65910_rtc_set_alarm, | 362 | .set_alarm = tps65910_rtc_set_alarm, |
| 221 | .alarm_irq_enable = tps65910_rtc_alarm_irq_enable, | 363 | .alarm_irq_enable = tps65910_rtc_alarm_irq_enable, |
| 364 | .read_offset = tps65910_read_offset, | ||
| 365 | .set_offset = tps65910_set_offset, | ||
| 222 | }; | 366 | }; |
| 223 | 367 | ||
| 224 | static int tps65910_rtc_probe(struct platform_device *pdev) | 368 | static int tps65910_rtc_probe(struct platform_device *pdev) |
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 6483a6fdce59..ffb21e79204d 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h | |||
| @@ -134,6 +134,7 @@ | |||
| 134 | 134 | ||
| 135 | /* RTC_CTRL_REG bitfields */ | 135 | /* RTC_CTRL_REG bitfields */ |
| 136 | #define TPS65910_RTC_CTRL_STOP_RTC 0x01 /*0=stop, 1=run */ | 136 | #define TPS65910_RTC_CTRL_STOP_RTC 0x01 /*0=stop, 1=run */ |
| 137 | #define TPS65910_RTC_CTRL_AUTO_COMP 0x04 | ||
| 137 | #define TPS65910_RTC_CTRL_GET_TIME 0x40 | 138 | #define TPS65910_RTC_CTRL_GET_TIME 0x40 |
| 138 | 139 | ||
| 139 | /* RTC_STATUS_REG bitfields */ | 140 | /* RTC_STATUS_REG bitfields */ |
diff --git a/include/linux/platform_data/rtc-m48t86.h b/include/linux/platform_data/rtc-m48t86.h deleted file mode 100644 index 915d6b4f0f89..000000000000 --- a/include/linux/platform_data/rtc-m48t86.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * ST M48T86 / Dallas DS12887 RTC driver | ||
| 3 | * Copyright (c) 2006 Tower Technologies | ||
| 4 | * | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | struct m48t86_ops | ||
| 13 | { | ||
| 14 | void (*writebyte)(unsigned char value, unsigned long addr); | ||
| 15 | unsigned char (*readbyte)(unsigned long addr); | ||
| 16 | }; | ||
