* [PATCH v2 02/10] mfd: ac100: Add device tree bindings for X-Powers AC100 codec/RTC combo IC
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
@ 2016-06-15 10:27 ` Chen-Yu Tsai
[not found] ` <1465986467-14802-3-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2016-06-15 10:27 ` [PATCH v2 03/10] mfd: ac100: Add driver for X-Powers AC100 audio codec / RTC " Chen-Yu Tsai
` (7 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Documentation/devicetree/bindings/mfd/ac100.txt | 42 +++++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/ac100.txt
diff --git a/Documentation/devicetree/bindings/mfd/ac100.txt b/Documentation/devicetree/bindings/mfd/ac100.txt
new file mode 100644
index 000000000000..fbab623e6fba
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ac100.txt
@@ -0,0 +1,42 @@
+X-Powers AC100 Codec/RTC IC device tree bindings
+
+AC100 is a audio codec and RTC subsystem combo IC. The 2 parts are
+separated, including power supplies and interrupt lines, but share
+a common register address space and host interface.
+
+Required properties:
+- compatible: "x-powers,ac100"
+- reg: The I2C slave address or RSB hardware address for the chip
+- sub-nodes:
+ - codec
+ - compatible: "x-powers,ac100-codec"
+ - interrupt-parent: The parent interrupt controller
+ - interrupts: SoC NMI / GPIO interrupt connected to the IRQ_AUDIO pin
+ - rtc
+ - compatible: "x-powers,ac100-rtc"
+ - interrupt-parent: The parent interrupt controller
+ - interrupts: SoC NMI / GPIO interrupt connected to the IRQ_RTC pin
+ - #clock-cells: shall be 1
+ - clock-output-names: "cko1_rtc", "cko2_rtc", "cko3_rtc"
+ - see clock/clock-bindings.txt for common clock bindings
+
+Example:
+
+ac100: codec@e89 {
+ compatible = "x-powers,ac100";
+ reg = <0xe89>;
+
+ ac100_codec {
+ compatible = "x-powers,ac100-codec";
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ ac100_rtc {
+ compatible = "x-powers,ac100-rtc";
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "cko1_rtc", "cko2_rtc", "cko3_rtc";
+ };
+};
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 03/10] mfd: ac100: Add driver for X-Powers AC100 audio codec / RTC combo IC
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2016-06-15 10:27 ` [PATCH v2 02/10] mfd: ac100: Add device tree bindings for X-Powers AC100 codec/RTC combo IC Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
[not found] ` <1465986467-14802-4-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2016-06-15 10:27 ` [PATCH v2 04/10] rtc: ac100: Add RTC driver for X-Powers AC100 Chen-Yu Tsai
` (6 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
The AC100 is a multifunction device with an audio codec subsystem and
an RTC subsystem. These two subsystems share a common register space
and host interface.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
drivers/mfd/Kconfig | 10 +++
drivers/mfd/Makefile | 2 +
drivers/mfd/ac100.c | 135 +++++++++++++++++++++++++++++++++++
include/linux/mfd/ac100.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 323 insertions(+)
create mode 100644 drivers/mfd/ac100.c
create mode 100644 include/linux/mfd/ac100.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1bcf601de5bc..bd83849a0c8d 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -101,6 +101,16 @@ config MFD_BCM590XX
help
Support for the BCM590xx PMUs from Broadcom
+config MFD_AC100
+ tristate "X-Powers AC100"
+ select MFD_CORE
+ depends on SUNXI_RSB
+ help
+ If you say Y here you get support for the X-Powers AC100 audio codec
+ IC.
+ This driver include only the core APIs. You have to select individual
+ components like codecs or RTC under the corresponding menus.
+
config MFD_AXP20X
tristate
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 42a66e19e191..60f9a6b0557c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -113,6 +113,8 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-irq.o
obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
+
+obj-$(CONFIG_MFD_AC100) += ac100.o
obj-$(CONFIG_MFD_AXP20X) += axp20x.o
obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o
obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o
diff --git a/drivers/mfd/ac100.c b/drivers/mfd/ac100.c
new file mode 100644
index 000000000000..15d24fa77771
--- /dev/null
+++ b/drivers/mfd/ac100.c
@@ -0,0 +1,135 @@
+/*
+ * ac100.c - MFD core driver for X-Powers' AC100 Audio Codec IC
+ *
+ * The AC100 is a highly integrated audio codec and RTC subsystem designed
+ * for mobile applications. It has 3 I2S/PCM interfaces, a 2 channel DAC,
+ * a 2 channel ADC with 5 inputs and a builtin mixer. The RTC subsystem has
+ * 3 clock outputs.
+ *
+ * The audio codec and RTC parts are completely separate, sharing only the
+ * host interface for access to its registers.
+ *
+ * Author: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ac100.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/sunxi-rsb.h>
+
+static const struct regmap_range ac100_writeable_ranges[] = {
+ regmap_reg_range(AC100_CHIP_AUDIO_RST, AC100_I2S_SR_CTRL),
+ regmap_reg_range(AC100_I2S1_CLK_CTRL, AC100_I2S1_MXR_GAIN),
+ regmap_reg_range(AC100_I2S2_CLK_CTRL, AC100_I2S2_MXR_GAIN),
+ regmap_reg_range(AC100_I2S3_CLK_CTRL, AC100_I2S3_SIG_PATH_CTRL),
+ regmap_reg_range(AC100_ADC_DIG_CTRL, AC100_ADC_VOL_CTRL),
+ regmap_reg_range(AC100_HMIC_CTRL1, AC100_HMIC_STATUS),
+ regmap_reg_range(AC100_DAC_DIG_CTRL, AC100_DAC_MXR_GAIN),
+ regmap_reg_range(AC100_ADC_APC_CTRL, AC100_LINEOUT_CTRL),
+ regmap_reg_range(AC100_ADC_DAP_L_CTRL, AC100_ADC_DAP_OPT),
+ regmap_reg_range(AC100_DAC_DAP_CTRL, AC100_DAC_DAP_OPT),
+ regmap_reg_range(AC100_ADC_DAP_ENA, AC100_DAC_DAP_ENA),
+ regmap_reg_range(AC100_SRC1_CTRL1, AC100_SRC1_CTRL2),
+ regmap_reg_range(AC100_SRC2_CTRL1, AC100_SRC2_CTRL2),
+ regmap_reg_range(AC100_CLK32K_ANALOG_CTRL, AC100_CLK32K_OUT_CTRL3),
+ regmap_reg_range(AC100_RTC_RST, AC100_RTC_UPD),
+ regmap_reg_range(AC100_ALM_INT_ENA, AC100_ALM_INT_STA),
+ regmap_reg_range(AC100_ALM_SEC, AC100_RTC_GP(15)),
+};
+
+static const struct regmap_range ac100_volatile_ranges[] = {
+ regmap_reg_range(AC100_CHIP_AUDIO_RST, AC100_PLL_CTRL2),
+ regmap_reg_range(AC100_HMIC_STATUS, AC100_HMIC_STATUS),
+ regmap_reg_range(AC100_ADC_DAP_L_STA, AC100_ADC_DAP_L_STA),
+ regmap_reg_range(AC100_SRC1_CTRL1, AC100_SRC1_CTRL1),
+ regmap_reg_range(AC100_SRC1_CTRL3, AC100_SRC2_CTRL1),
+ regmap_reg_range(AC100_SRC2_CTRL3, AC100_SRC2_CTRL4),
+ regmap_reg_range(AC100_RTC_RST, AC100_RTC_RST),
+ regmap_reg_range(AC100_RTC_SEC, AC100_ALM_INT_STA),
+ regmap_reg_range(AC100_ALM_SEC, AC100_ALM_UPD),
+};
+
+static const struct regmap_access_table ac100_writeable_table = {
+ .yes_ranges = ac100_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ac100_writeable_ranges),
+};
+
+static const struct regmap_access_table ac100_volatile_table = {
+ .yes_ranges = ac100_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ac100_volatile_ranges),
+};
+
+static const struct regmap_config ac100_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .wr_table = &ac100_writeable_table,
+ .volatile_table = &ac100_volatile_table,
+ .max_register = AC100_RTC_GP(15),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static struct mfd_cell ac100_cells[] = {
+ {
+ .name = "ac100-codec",
+ .of_compatible = "x-powers,ac100-codec",
+ }, {
+ .name = "ac100-rtc",
+ .of_compatible = "x-powers,ac100-rtc",
+ },
+};
+
+static int ac100_rsb_probe(struct sunxi_rsb_device *rdev)
+{
+ struct ac100_dev *ac100;
+ int ret;
+
+ ac100 = devm_kzalloc(&rdev->dev, sizeof(*ac100), GFP_KERNEL);
+ if (!ac100)
+ return -ENOMEM;
+
+ ac100->dev = &rdev->dev;
+ sunxi_rsb_device_set_drvdata(rdev, ac100);
+
+ ac100->regmap = devm_regmap_init_sunxi_rsb(rdev, &ac100_regmap_config);
+ if (IS_ERR(ac100->regmap)) {
+ ret = PTR_ERR(ac100->regmap);
+ dev_err(ac100->dev, "regmap init failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_mfd_add_devices(ac100->dev, PLATFORM_DEVID_NONE, ac100_cells,
+ ARRAY_SIZE(ac100_cells), NULL, 0, NULL);
+ if (ret) {
+ dev_err(ac100->dev, "failed to add MFD devices: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ac100_of_match[] = {
+ { .compatible = "x-powers,ac100" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ac100_of_match);
+
+static struct sunxi_rsb_driver ac100_rsb_driver = {
+ .driver = {
+ .name = "ac100",
+ .of_match_table = of_match_ptr(ac100_of_match),
+ },
+ .probe = ac100_rsb_probe,
+};
+module_sunxi_rsb_driver(ac100_rsb_driver);
+
+MODULE_DESCRIPTION("Audio codec MFD core driver for AC100");
+MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/ac100.h b/include/linux/mfd/ac100.h
new file mode 100644
index 000000000000..460b4fd03df1
--- /dev/null
+++ b/include/linux/mfd/ac100.h
@@ -0,0 +1,176 @@
+/*
+ * Functions and registers to access AC100 codec / RTC combo IC.
+ *
+ * Copyright (C) 2013, Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MFD_AC100_H
+#define __LINUX_MFD_AC100_H
+
+#include <linux/regmap.h>
+
+struct ac100_dev {
+ struct device *dev;
+ struct regmap *regmap;
+};
+
+/* Audio codec related registers */
+#define AC100_CHIP_AUDIO_RST 0x00
+#define AC100_PLL_CTRL1 0x01
+#define AC100_PLL_CTRL2 0x02
+#define AC100_SYSCLK_CTRL 0x03
+#define AC100_MOD_CLK_ENA 0x04
+#define AC100_MOD_RST_CTRL 0x05
+#define AC100_I2S_SR_CTRL 0x06
+
+/* I2S1 interface */
+#define AC100_I2S1_CLK_CTRL 0x10
+#define AC100_I2S1_SND_OUT_CTRL 0x11
+#define AC100_I2S1_SND_IN_CTRL 0x12
+#define AC100_I2S1_MXR_SRC 0x13
+#define AC100_I2S1_VOL_CTRL1 0x14
+#define AC100_I2S1_VOL_CTRL2 0x15
+#define AC100_I2S1_VOL_CTRL3 0x16
+#define AC100_I2S1_VOL_CTRL4 0x17
+#define AC100_I2S1_MXR_GAIN 0x18
+
+/* I2S2 interface */
+#define AC100_I2S2_CLK_CTRL 0x20
+#define AC100_I2S2_SND_OUT_CTRL 0x21
+#define AC100_I2S2_SND_IN_CTRL 0x22
+#define AC100_I2S2_MXR_SRC 0x23
+#define AC100_I2S2_VOL_CTRL1 0x24
+#define AC100_I2S2_VOL_CTRL2 0x25
+#define AC100_I2S2_VOL_CTRL3 0x26
+#define AC100_I2S2_VOL_CTRL4 0x27
+#define AC100_I2S2_MXR_GAIN 0x28
+
+/* I2S3 interface */
+#define AC100_I2S3_CLK_CTRL 0x30
+#define AC100_I2S3_SND_OUT_CTRL 0x31
+#define AC100_I2S3_SND_IN_CTRL 0x32
+#define AC100_I2S3_SIG_PATH_CTRL 0x33
+
+/* ADC digital controls */
+#define AC100_ADC_DIG_CTRL 0x40
+#define AC100_ADC_VOL_CTRL 0x41
+
+/* HMIC plug sensing / key detection */
+#define AC100_HMIC_CTRL1 0x44
+#define AC100_HMIC_CTRL2 0x45
+#define AC100_HMIC_STATUS 0x46
+
+/* DAC digital controls */
+#define AC100_DAC_DIG_CTRL 0x48
+#define AC100_DAC_VOL_CTRL 0x49
+#define AC100_DAC_MXR_SRC 0x4c
+#define AC100_DAC_MXR_GAIN 0x4d
+
+/* Analog controls */
+#define AC100_ADC_APC_CTRL 0x50
+#define AC100_ADC_SRC 0x51
+#define AC100_ADC_SRC_BST_CTRL 0x52
+#define AC100_OUT_MXR_DAC_A_CTRL 0x53
+#define AC100_OUT_MXR_SRC 0x54
+#define AC100_OUT_MXR_SRC_BST 0x55
+#define AC100_HPOUT_CTRL 0x56
+#define AC100_ERPOUT_CTRL 0x57
+#define AC100_SPKOUT_CTRL 0x58
+#define AC100_LINEOUT_CTRL 0x59
+
+/* ADC digital audio processing (high pass filter & auto gain control */
+#define AC100_ADC_DAP_L_STA 0x80
+#define AC100_ADC_DAP_R_STA 0x81
+#define AC100_ADC_DAP_L_CTRL 0x82
+#define AC100_ADC_DAP_R_CTRL 0x83
+#define AC100_ADC_DAP_L_T_L 0x84 /* Left Target Level */
+#define AC100_ADC_DAP_R_T_L 0x85 /* Right Target Level */
+#define AC100_ADC_DAP_L_H_A_C 0x86 /* Left High Avg. Coef */
+#define AC100_ADC_DAP_L_L_A_C 0x87 /* Left Low Avg. Coef */
+#define AC100_ADC_DAP_R_H_A_C 0x88 /* Right High Avg. Coef */
+#define AC100_ADC_DAP_R_L_A_C 0x89 /* Right Low Avg. Coef */
+#define AC100_ADC_DAP_L_D_T 0x8a /* Left Decay Time */
+#define AC100_ADC_DAP_L_A_T 0x8b /* Left Attack Time */
+#define AC100_ADC_DAP_R_D_T 0x8c /* Right Decay Time */
+#define AC100_ADC_DAP_R_A_T 0x8d /* Right Attack Time */
+#define AC100_ADC_DAP_N_TH 0x8e /* Noise Threshold */
+#define AC100_ADC_DAP_L_H_N_A_C 0x8f /* Left High Noise Avg. Coef */
+#define AC100_ADC_DAP_L_L_N_A_C 0x90 /* Left Low Noise Avg. Coef */
+#define AC100_ADC_DAP_R_H_N_A_C 0x91 /* Right High Noise Avg. Coef */
+#define AC100_ADC_DAP_R_L_N_A_C 0x92 /* Right Low Noise Avg. Coef */
+#define AC100_ADC_DAP_H_HPF_C 0x93 /* High High-Pass-Filter Coef */
+#define AC100_ADC_DAP_L_HPF_C 0x94 /* Low High-Pass-Filter Coef */
+#define AC100_ADC_DAP_OPT 0x95 /* AGC Optimum */
+
+/* DAC digital audio processing (high pass filter & dynamic range control) */
+#define AC100_DAC_DAP_CTRL 0xa0
+#define AC100_DAC_DAP_H_HPF_C 0xa1 /* High High-Pass-Filter Coef */
+#define AC100_DAC_DAP_L_HPF_C 0xa2 /* Low High-Pass-Filter Coef */
+#define AC100_DAC_DAP_L_H_E_A_C 0xa3 /* Left High Energy Avg Coef */
+#define AC100_DAC_DAP_L_L_E_A_C 0xa4 /* Left Low Energy Avg Coef */
+#define AC100_DAC_DAP_R_H_E_A_C 0xa5 /* Right High Energy Avg Coef */
+#define AC100_DAC_DAP_R_L_E_A_C 0xa6 /* Right Low Energy Avg Coef */
+#define AC100_DAC_DAP_H_G_D_T_C 0xa7 /* High Gain Delay Time Coef */
+#define AC100_DAC_DAP_L_G_D_T_C 0xa8 /* Low Gain Delay Time Coef */
+#define AC100_DAC_DAP_H_G_A_T_C 0xa9 /* High Gain Attack Time Coef */
+#define AC100_DAC_DAP_L_G_A_T_C 0xaa /* Low Gain Attack Time Coef */
+#define AC100_DAC_DAP_H_E_TH 0xab /* High Energy Threshold */
+#define AC100_DAC_DAP_L_E_TH 0xac /* Low Energy Threshold */
+#define AC100_DAC_DAP_H_G_K 0xad /* High Gain K parameter */
+#define AC100_DAC_DAP_L_G_K 0xae /* Low Gain K parameter */
+#define AC100_DAC_DAP_H_G_OFF 0xaf /* High Gain offset */
+#define AC100_DAC_DAP_L_G_OFF 0xb0 /* Low Gain offset */
+#define AC100_DAC_DAP_OPT 0xb1 /* DRC optimum */
+
+/* Digital audio processing enable */
+#define AC100_ADC_DAP_ENA 0xb4
+#define AC100_DAC_DAP_ENA 0xb5
+
+/* SRC control */
+#define AC100_SRC1_CTRL1 0xb8
+#define AC100_SRC1_CTRL2 0xb9
+#define AC100_SRC1_CTRL3 0xba
+#define AC100_SRC1_CTRL4 0xbb
+#define AC100_SRC2_CTRL1 0xbc
+#define AC100_SRC2_CTRL2 0xbd
+#define AC100_SRC2_CTRL3 0xbe
+#define AC100_SRC2_CTRL4 0xbf
+
+/* RTC clk control */
+#define AC100_CLK32K_ANALOG_CTRL 0xc0
+#define AC100_CLK32K_OUT_CTRL1 0xc1
+#define AC100_CLK32K_OUT_CTRL2 0xc2
+#define AC100_CLK32K_OUT_CTRL3 0xc3
+
+/* RTC module */
+#define AC100_RTC_RST 0xc6
+#define AC100_RTC_CTRL 0xc7
+#define AC100_RTC_SEC 0xc8 /* second */
+#define AC100_RTC_MIN 0xc9 /* minute */
+#define AC100_RTC_HOU 0xca /* hour */
+#define AC100_RTC_WEE 0xcb /* weekday */
+#define AC100_RTC_DAY 0xcc /* day */
+#define AC100_RTC_MON 0xcd /* month */
+#define AC100_RTC_YEA 0xce /* year */
+#define AC100_RTC_UPD 0xcf /* update trigger */
+
+/* RTC alarm */
+#define AC100_ALM_INT_ENA 0xd0
+#define AC100_ALM_INT_STA 0xd1
+#define AC100_ALM_SEC 0xd8
+#define AC100_ALM_MIN 0xd9
+#define AC100_ALM_HOU 0xda
+#define AC100_ALM_WEE 0xdb
+#define AC100_ALM_DAY 0xdc
+#define AC100_ALM_MON 0xdd
+#define AC100_ALM_YEA 0xde
+#define AC100_ALM_UPD 0xdf
+
+/* RTC general purpose register 0 ~ 15 */
+#define AC100_RTC_GP(x) (0xe0 + (x))
+
+#endif /* __LINUX_MFD_AC100_H */
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 04/10] rtc: ac100: Add RTC driver for X-Powers AC100
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2016-06-15 10:27 ` [PATCH v2 02/10] mfd: ac100: Add device tree bindings for X-Powers AC100 codec/RTC combo IC Chen-Yu Tsai
2016-06-15 10:27 ` [PATCH v2 03/10] mfd: ac100: Add driver for X-Powers AC100 audio codec / RTC " Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
2016-06-15 10:27 ` [PATCH v2 05/10] rtc: ac100: Add clk output support Chen-Yu Tsai
` (5 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
X-Powers AC100 is a codec / RTC combo chip. This driver supports
the RTC sub-device.
The RTC block also has clock outputs and non-volatile storage.
Non-volatile storage wthin the RTC hardware is not supported.
Clock output support is added in the next patch.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
drivers/rtc/Kconfig | 10 ++
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-ac100.c | 367 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 378 insertions(+)
create mode 100644 drivers/rtc/rtc-ac100.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 18639e0cb6e2..b9d7cbb6bd76 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -183,6 +183,16 @@ config RTC_DRV_ABX80X
This driver can also be built as a module. If so, the module
will be called rtc-abx80x.
+config RTC_DRV_AC100
+ tristate "X-Powers AC100"
+ depends on MFD_AC100
+ help
+ If you say yes here you get support for the real-time clock found
+ in X-Powers AC100 family peripheral ICs.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ac100.
+
config RTC_DRV_AS3722
tristate "ams AS3722 RTC driver"
depends on MFD_AS3722
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ea2833723fa9..b07c28779573 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o
obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o
+obj-$(CONFIG_RTC_DRV_AC100) += rtc-ac100.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
new file mode 100644
index 000000000000..360346792ca5
--- /dev/null
+++ b/drivers/rtc/rtc-ac100.c
@@ -0,0 +1,367 @@
+/*
+ * RTC Driver for X-Powers AC100
+ *
+ * Copyright (c) 2015, Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/bcd.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/ac100.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+
+/* Control register */
+#define AC100_RTC_CTRL_24HOUR BIT(0)
+
+/* RTC */
+#define AC100_RTC_SEC_MASK GENMASK(6, 0)
+#define AC100_RTC_MIN_MASK GENMASK(6, 0)
+#define AC100_RTC_HOU_MASK GENMASK(5, 0)
+#define AC100_RTC_WEE_MASK GENMASK(3, 0)
+#define AC100_RTC_DAY_MASK GENMASK(5, 0)
+#define AC100_RTC_MON_MASK GENMASK(4, 0)
+#define AC100_RTC_YEA_MASK GENMASK(7, 0)
+#define AC100_RTC_YEA_LEAP BIT(15)
+#define AC100_RTC_UPD_TRIGGER BIT(15)
+
+/* Alarm (wall clock) */
+#define AC100_ALM_INT_ENABLE BIT(0)
+
+#define AC100_ALM_SEC_MASK GENMASK(5, 0)
+#define AC100_ALM_MIN_MASK GENMASK(5, 0)
+#define AC100_ALM_HOU_MASK GENMASK(4, 0)
+#define AC100_ALM_WEE_MASK GENMASK(3, 0)
+#define AC100_ALM_DAY_MASK GENMASK(5, 0)
+#define AC100_ALM_MON_MASK GENMASK(4, 0)
+#define AC100_ALM_YEA_MASK GENMASK(7, 0)
+#define AC100_ALM_ENABLE_FLAG BIT(15)
+#define AC100_ALM_UPD_TRIGGER BIT(15)
+
+/*
+ * The year parameter passed to the driver is usually an offset relative to
+ * the year 1900. This macro is used to convert this offset to another one
+ * relative to the minimum year allowed by the hardware.
+ *
+ * The year range is 1970 - 2069. This range is selected to match Allwinner's
+ * driver.
+ */
+#define AC100_YEAR_MIN 1970
+#define AC100_YEAR_MAX 2069
+#define AC100_YEAR_OFF (AC100_YEAR_MIN - 1900)
+
+struct ac100_rtc_dev {
+ struct rtc_device *rtc;
+ struct device *dev;
+ struct regmap *regmap;
+ struct mutex mutex;
+ int irq;
+ unsigned long alarm;
+};
+
+static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
+{
+ struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
+ struct regmap *regmap = chip->regmap;
+ u16 reg[7];
+ int ret;
+
+ ret = regmap_bulk_read(regmap, AC100_RTC_SEC, reg, 7);
+ if (ret)
+ return ret;
+
+ rtc_tm->tm_sec = bcd2bin(reg[0] & AC100_RTC_SEC_MASK);
+ rtc_tm->tm_min = bcd2bin(reg[1] & AC100_RTC_MIN_MASK);
+ rtc_tm->tm_hour = bcd2bin(reg[2] & AC100_RTC_HOU_MASK);
+ rtc_tm->tm_wday = bcd2bin(reg[3] & AC100_RTC_WEE_MASK);
+ rtc_tm->tm_mday = bcd2bin(reg[4] & AC100_RTC_DAY_MASK);
+ rtc_tm->tm_mon = bcd2bin(reg[5] & AC100_RTC_MON_MASK);
+ rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK);
+
+ rtc_tm->tm_mon -= 1;
+
+ /*
+ * switch from (data_year->min)-relative offset to
+ * a (1900)-relative one
+ */
+ rtc_tm->tm_year += AC100_YEAR_OFF;
+
+ return rtc_valid_tm(rtc_tm);
+}
+
+static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
+{
+ struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
+ struct regmap *regmap = chip->regmap;
+ int year;
+ u16 reg[8];
+
+ /* our RTC has a limited year range... */
+ year = rtc_tm->tm_year + 1900;
+ if (year < AC100_YEAR_MIN || year > AC100_YEAR_MAX) {
+ dev_err(dev, "rtc only supports year in range %d - %d\n",
+ AC100_YEAR_MIN, AC100_YEAR_MAX);
+ return -EINVAL;
+ }
+
+ /* correct offsets */
+ rtc_tm->tm_year -= AC100_YEAR_OFF;
+ rtc_tm->tm_mon += 1;
+
+ /* convert to BCD */
+ reg[0] = bin2bcd(rtc_tm->tm_sec) & AC100_RTC_SEC_MASK;
+ reg[1] = bin2bcd(rtc_tm->tm_min) & AC100_RTC_MIN_MASK;
+ reg[2] = bin2bcd(rtc_tm->tm_hour) & AC100_RTC_HOU_MASK;
+ reg[3] = bin2bcd(rtc_tm->tm_wday) & AC100_RTC_WEE_MASK;
+ reg[4] = bin2bcd(rtc_tm->tm_mday) & AC100_RTC_DAY_MASK;
+ reg[5] = bin2bcd(rtc_tm->tm_mon) & AC100_RTC_MON_MASK;
+ reg[6] = bin2bcd(rtc_tm->tm_year) & AC100_RTC_YEA_MASK;
+ /* trigger write */
+ reg[7] = AC100_RTC_UPD_TRIGGER;
+
+ /* Is it a leap year? */
+ if (is_leap_year(year))
+ reg[6] |= AC100_RTC_YEA_LEAP;
+
+ return regmap_bulk_write(regmap, AC100_RTC_SEC, reg, 8);
+}
+
+static int _ac100_rtc_alarm_irq_enable(struct ac100_rtc_dev *chip,
+ unsigned int en)
+{
+ struct regmap *regmap = chip->regmap;
+ unsigned int val;
+
+ val = en ? AC100_ALM_INT_ENABLE : 0;
+
+ return regmap_write(regmap, AC100_ALM_INT_ENA, val);
+}
+
+static int ac100_rtc_alarm_irq_enable(struct device *dev, unsigned int en)
+{
+ struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
+ int ret;
+
+ mutex_lock(&chip->mutex);
+ ret = _ac100_rtc_alarm_irq_enable(chip, en);
+ mutex_unlock(&chip->mutex);
+
+ return ret;
+}
+
+static int ac100_rtc_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
+ struct regmap *regmap = chip->regmap;
+ struct rtc_time *alrm_tm = &alrm->time;
+ u16 reg[7];
+ unsigned int val;
+ int ret;
+
+ mutex_lock(&chip->mutex);
+
+ ret = regmap_read(regmap, AC100_ALM_INT_ENA, &val);
+ if (ret)
+ goto out;
+
+ alrm->enabled = !!(val & AC100_ALM_INT_ENABLE);
+
+ ret = regmap_bulk_read(regmap, AC100_ALM_SEC, reg, 7);
+ if (ret)
+ goto out;
+
+ alrm_tm->tm_sec = bcd2bin(reg[0] & AC100_ALM_SEC_MASK);
+ alrm_tm->tm_min = bcd2bin(reg[1] & AC100_ALM_MIN_MASK);
+ alrm_tm->tm_hour = bcd2bin(reg[2] & AC100_ALM_HOU_MASK);
+ alrm_tm->tm_wday = bcd2bin(reg[3] & AC100_ALM_WEE_MASK);
+ alrm_tm->tm_mday = bcd2bin(reg[4] & AC100_ALM_DAY_MASK);
+ alrm_tm->tm_mon = bcd2bin(reg[5] & AC100_ALM_MON_MASK);
+ alrm_tm->tm_year = bcd2bin(reg[6] & AC100_ALM_YEA_MASK);
+
+ alrm_tm->tm_mon -= 1;
+
+ /*
+ * switch from (data_year->min)-relative offset to
+ * a (1900)-relative one
+ */
+ alrm_tm->tm_year += AC100_YEAR_OFF;
+
+out:
+ mutex_unlock(&chip->mutex);
+ return ret;
+}
+
+static int ac100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
+ struct regmap *regmap = chip->regmap;
+ struct rtc_time *alrm_tm = &alrm->time;
+ u16 reg[8];
+ int year;
+ int ret;
+
+ /* our alarm has a limited year range... */
+ year = alrm_tm->tm_year + 1900;
+ if (year < AC100_YEAR_MIN || year > AC100_YEAR_MAX) {
+ dev_err(dev, "alarm only supports year in range %d - %d\n",
+ AC100_YEAR_MIN, AC100_YEAR_MAX);
+ return -EINVAL;
+ }
+
+ /* correct offsets */
+ alrm_tm->tm_year -= AC100_YEAR_OFF;
+ alrm_tm->tm_mon += 1;
+
+ /* convert to BCD */
+ reg[0] = (bin2bcd(alrm_tm->tm_sec) & AC100_RTC_SEC_MASK) |
+ AC100_ALM_ENABLE_FLAG;
+ reg[1] = (bin2bcd(alrm_tm->tm_min) & AC100_RTC_MIN_MASK) |
+ AC100_ALM_ENABLE_FLAG;
+ reg[2] = (bin2bcd(alrm_tm->tm_hour) & AC100_RTC_HOU_MASK) |
+ AC100_ALM_ENABLE_FLAG;
+ /* Do not enable weekday alarm */
+ reg[3] = bin2bcd(alrm_tm->tm_wday) & AC100_RTC_WEE_MASK;
+ reg[4] = (bin2bcd(alrm_tm->tm_mday) & AC100_RTC_DAY_MASK) |
+ AC100_ALM_ENABLE_FLAG;
+ reg[5] = (bin2bcd(alrm_tm->tm_mon) & AC100_RTC_MON_MASK) |
+ AC100_ALM_ENABLE_FLAG;
+ reg[6] = (bin2bcd(alrm_tm->tm_year) & AC100_RTC_YEA_MASK) |
+ AC100_ALM_ENABLE_FLAG;
+ /* trigger write */
+ reg[7] = AC100_RTC_UPD_TRIGGER;
+
+ mutex_lock(&chip->mutex);
+
+ ret = regmap_bulk_write(regmap, AC100_RTC_SEC, reg, 8);
+ if (ret)
+ goto out;
+
+ ret = _ac100_rtc_alarm_irq_enable(chip, alrm->enabled);
+
+out:
+ mutex_unlock(&chip->mutex);
+ return ret;
+}
+
+static irqreturn_t ac100_rtc_irq(int irq, void *data)
+{
+ struct ac100_rtc_dev *chip = data;
+ struct regmap *regmap = chip->regmap;
+ unsigned int val = 0;
+ int ret;
+
+ mutex_lock(&chip->mutex);
+
+ /* read status */
+ ret = regmap_read(regmap, AC100_ALM_INT_STA, &val);
+ if (ret)
+ goto out;
+
+ if (val & AC100_ALM_INT_ENABLE) {
+ /* signal rtc framework */
+ rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
+
+ /* clear status */
+ ret = regmap_write(regmap, AC100_ALM_INT_STA, val);
+ if (ret)
+ goto out;
+
+ /* disable interrupt */
+ ret = _ac100_rtc_alarm_irq_enable(chip, 0);
+ if (ret)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&chip->mutex);
+ return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops ac100_rtc_ops = {
+ .read_time = ac100_rtc_get_time,
+ .set_time = ac100_rtc_set_time,
+ .read_alarm = ac100_rtc_get_alarm,
+ .set_alarm = ac100_rtc_set_alarm,
+ .alarm_irq_enable = ac100_rtc_alarm_irq_enable,
+};
+
+static int ac100_rtc_probe(struct platform_device *pdev)
+{
+ struct ac100_dev *ac100 = dev_get_drvdata(pdev->dev.parent);
+ struct ac100_rtc_dev *chip;
+ int ret;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ platform_set_drvdata(pdev, chip);
+ chip->dev = &pdev->dev;
+ chip->regmap = ac100->regmap;
+ mutex_init(&chip->mutex);
+
+ chip->irq = of_irq_get(pdev->dev.of_node, 0);
+ if (chip->irq < 0) {
+ dev_err(&pdev->dev, "No IRQ resource\n");
+ return chip->irq;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, chip->irq, NULL,
+ ac100_rtc_irq,
+ IRQF_SHARED | IRQF_ONESHOT,
+ dev_name(&pdev->dev), chip);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not request IRQ\n");
+ return ret;
+ }
+
+ /* always use 24 hour mode */
+ regmap_write_bits(chip->regmap, AC100_RTC_CTRL, AC100_RTC_CTRL_24HOUR,
+ AC100_RTC_CTRL_24HOUR);
+
+ /* disable counter alarm interrupt */
+ regmap_write(chip->regmap, AC100_ALM_INT_ENA, 0);
+
+ /* clear counter alarm pending interrupts */
+ regmap_write(chip->regmap, AC100_ALM_INT_STA, AC100_ALM_INT_ENABLE);
+
+ chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-ac100",
+ &ac100_rtc_ops, THIS_MODULE);
+ if (IS_ERR(chip->rtc)) {
+ dev_err(&pdev->dev, "unable to register device\n");
+ return PTR_ERR(chip->rtc);
+ }
+
+ /* We do not support user interrupts */
+ chip->rtc->uie_unsupported = 1;
+
+ dev_info(&pdev->dev, "RTC enabled\n");
+
+ return 0;
+}
+
+static struct platform_driver ac100_rtc_driver = {
+ .probe = ac100_rtc_probe,
+ .driver = {
+ .name = "ac100-rtc",
+ },
+};
+module_platform_driver(ac100_rtc_driver);
+
+MODULE_DESCRIPTION("X-Powers AC100 RTC driver");
+MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>");
+MODULE_LICENSE("GPL");
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 05/10] rtc: ac100: Add clk output support
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (2 preceding siblings ...)
2016-06-15 10:27 ` [PATCH v2 04/10] rtc: ac100: Add RTC driver for X-Powers AC100 Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
2016-06-15 10:27 ` [PATCH v2 06/10] ARM: dts: sun9i: a80-optimus: Add device node for AC100 Chen-Yu Tsai
` (4 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
The AC100's RTC side has 3 clock outputs on external pins, which can
provide a clock signal to the SoC or other modules, such as WiFi or
GSM modules.
Support this with a custom clk driver integrated with the rtc driver.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
drivers/rtc/rtc-ac100.c | 319 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 319 insertions(+)
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index 360346792ca5..89b63b4bb88f 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -15,6 +15,7 @@
*/
#include <linux/bcd.h>
+#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -31,6 +32,15 @@
/* Control register */
#define AC100_RTC_CTRL_24HOUR BIT(0)
+/* Clock output register bits */
+#define AC100_CLK32K_PRE_DIV_SHIFT 5
+#define AC100_CLK32K_PRE_DIV_WIDTH 3
+#define AC100_CLK32K_MUX_SHIFT 4
+#define AC100_CLK32K_MUX_WIDTH 1
+#define AC100_CLK32K_DIV_SHIFT 1
+#define AC100_CLK32K_DIV_WIDTH 3
+#define AC100_CLK32K_EN BIT(0)
+
/* RTC */
#define AC100_RTC_SEC_MASK GENMASK(6, 0)
#define AC100_RTC_MIN_MASK GENMASK(6, 0)
@@ -67,6 +77,26 @@
#define AC100_YEAR_MAX 2069
#define AC100_YEAR_OFF (AC100_YEAR_MIN - 1900)
+struct ac100_clk32k {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u8 offset;
+};
+
+#define to_ac100_clk32k(_hw) container_of(_hw, struct ac100_clk32k, hw)
+
+#define AC100_RTC_32K_NAME "ac100-rtc-32k"
+#define AC100_RTC_32K_RATE 32768
+#define AC100_ADDA_4M_NAME "ac100-adda-4M"
+#define AC100_ADDA_4M_RATE 4000000
+#define AC100_CLK32K_NUM 3
+
+static const char * const ac100_clk32k_names[] = {
+ "ac100-clk32k-ap",
+ "ac100-clk32k-bb",
+ "ac100-clk32k-md",
+};
+
struct ac100_rtc_dev {
struct rtc_device *rtc;
struct device *dev;
@@ -74,8 +104,283 @@ struct ac100_rtc_dev {
struct mutex mutex;
int irq;
unsigned long alarm;
+
+ struct clk_hw *rtc_32k_clk;
+ struct clk_hw *adda_4M_clk;
+ struct ac100_clk32k clks[AC100_CLK32K_NUM];
+ struct clk_hw_onecell_data *clk_data;
+};
+
+/**
+ * Clock controls for 3 clock output pins
+ */
+
+static const struct clk_div_table ac100_clk32k_prediv[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 8 },
+ { .val = 4, .div = 16 },
+ { .val = 5, .div = 32 },
+ { .val = 6, .div = 64 },
+ { .val = 7, .div = 122 },
+ { },
+};
+
+/* Abuse the fact that one parent is 32768 Hz, and the other is 4 MHz */
+static unsigned long ac100_clk32k_recalc_rate(struct clk_hw *hw,
+ unsigned long prate)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+ unsigned int reg, div;
+
+ regmap_read(clk->regmap, clk->offset, ®);
+
+ /* Handle pre-divider first */
+ if (prate != AC100_RTC_32K_RATE) {
+ div = (reg >> AC100_CLK32K_PRE_DIV_SHIFT) &
+ ((1 << AC100_CLK32K_PRE_DIV_WIDTH) - 1);
+ prate = divider_recalc_rate(hw, prate, div,
+ ac100_clk32k_prediv, 0);
+ }
+
+ div = (reg >> AC100_CLK32K_DIV_SHIFT) &
+ (BIT(AC100_CLK32K_DIV_WIDTH) - 1);
+ return divider_recalc_rate(hw, prate, div, NULL,
+ CLK_DIVIDER_POWER_OF_TWO);
+}
+
+static long ac100_clk32k_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate)
+{
+ unsigned long best_rate = 0, tmp_rate, tmp_prate;
+ int i;
+
+ if (prate == AC100_RTC_32K_RATE)
+ return divider_round_rate(hw, rate, &prate, NULL,
+ AC100_CLK32K_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+
+ for (i = 0; ac100_clk32k_prediv[i].div; i++) {
+ tmp_prate = DIV_ROUND_UP(prate, ac100_clk32k_prediv[i].val);
+ tmp_rate = divider_round_rate(hw, rate, &tmp_prate, NULL,
+ AC100_CLK32K_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+
+ if (tmp_rate > rate)
+ continue;
+ if (rate - tmp_rate < best_rate - tmp_rate)
+ best_rate = tmp_rate;
+ }
+
+ return best_rate;
+}
+
+static int ac100_clk32k_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_hw *best_parent;
+ unsigned long best = 0;
+ int i, num_parents = clk_hw_get_num_parents(hw);
+
+ for (i = 0; i < num_parents; i++) {
+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
+ unsigned long tmp, prate = clk_hw_get_rate(parent);
+
+ tmp = ac100_clk32k_round_rate(hw, req->rate, prate);
+
+ if (tmp > req->rate)
+ continue;
+ if (req->rate - tmp < req->rate - best) {
+ best = tmp;
+ best_parent = parent;
+ }
+ }
+
+ if (!best)
+ return -EINVAL;
+
+ req->best_parent_hw = best_parent;
+ req->best_parent_rate = best;
+ req->rate = best;
+
+ return 0;
+}
+
+static int ac100_clk32k_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+ int div = 0, pre_div = 0;
+
+ do {
+ div = divider_get_val(rate * ac100_clk32k_prediv[pre_div].div,
+ prate, NULL, AC100_CLK32K_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+ if (div >= 0)
+ break;
+ } while (prate == AC100_ADDA_4M_RATE &&
+ ac100_clk32k_prediv[++pre_div].div);
+
+ if (div < 0)
+ return div;
+
+ pre_div = ac100_clk32k_prediv[pre_div].val;
+
+ regmap_update_bits(clk->regmap, clk->offset,
+ ((1 << AC100_CLK32K_DIV_WIDTH) - 1) << AC100_CLK32K_DIV_SHIFT |
+ ((1 << AC100_CLK32K_PRE_DIV_WIDTH) - 1) << AC100_CLK32K_PRE_DIV_SHIFT,
+ (div - 1) << AC100_CLK32K_DIV_SHIFT |
+ (pre_div - 1) << AC100_CLK32K_PRE_DIV_SHIFT);
+
+ return 0;
+}
+
+static int ac100_clk32k_prepare(struct clk_hw *hw)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+
+ return regmap_update_bits(clk->regmap, clk->offset, AC100_CLK32K_EN,
+ AC100_CLK32K_EN);
+}
+
+static void ac100_clk32k_unprepare(struct clk_hw *hw)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+
+ regmap_update_bits(clk->regmap, clk->offset, AC100_CLK32K_EN, 0);
+}
+
+static int ac100_clk32k_is_prepared(struct clk_hw *hw)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+ unsigned int reg;
+
+ regmap_read(clk->regmap, clk->offset, ®);
+
+ return reg & AC100_CLK32K_EN;
+}
+
+static u8 ac100_clk32k_get_parent(struct clk_hw *hw)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+ unsigned int reg;
+
+ regmap_read(clk->regmap, clk->offset, ®);
+
+ return (reg >> AC100_CLK32K_MUX_SHIFT) & 0x1;
+}
+
+static int ac100_clk32k_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct ac100_clk32k *clk = to_ac100_clk32k(hw);
+
+ return regmap_update_bits(clk->regmap, clk->offset,
+ BIT(AC100_CLK32K_MUX_SHIFT),
+ index ? BIT(AC100_CLK32K_MUX_SHIFT) : 0);
+}
+
+static const struct clk_ops ac100_clk32k_ops = {
+ .prepare = ac100_clk32k_prepare,
+ .unprepare = ac100_clk32k_unprepare,
+ .is_prepared = ac100_clk32k_is_prepared,
+ .recalc_rate = ac100_clk32k_recalc_rate,
+ .determine_rate = ac100_clk32k_determine_rate,
+ .get_parent = ac100_clk32k_get_parent,
+ .set_parent = ac100_clk32k_set_parent,
+ .set_rate = ac100_clk32k_set_rate,
};
+static int ac100_rtc_register_clks(struct ac100_rtc_dev *chip)
+{
+ struct device_node *np = chip->dev->of_node;
+ const char *parents[2] = {AC100_RTC_32K_NAME, AC100_ADDA_4M_NAME};
+ int i, ret;
+
+ chip->clk_data = devm_kzalloc(chip->dev, sizeof(*chip->clk_data) +
+ sizeof(*chip->clk_data->hws) *
+ AC100_CLK32K_NUM,
+ GFP_KERNEL);
+ if (!chip->clk_data)
+ return -ENOMEM;
+
+ chip->rtc_32k_clk = clk_hw_register_fixed_rate(chip->dev,
+ AC100_RTC_32K_NAME,
+ NULL, 0,
+ AC100_RTC_32K_RATE);
+ if (IS_ERR(chip->rtc_32k_clk)) {
+ ret = PTR_ERR(chip->rtc_32k_clk);
+ dev_err(chip->dev, "Failed to register RTC-32k clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * The ADDA 4 MHz clock is from the codec side of the AC100,
+ * which is likely a different power domain. However, boards
+ * always have both sides powered on, so it is impossible to
+ * test this.
+ */
+ chip->adda_4M_clk = clk_hw_register_fixed_rate(chip->dev,
+ AC100_ADDA_4M_NAME,
+ NULL, 0,
+ AC100_ADDA_4M_RATE);
+ if (IS_ERR(chip->adda_4M_clk)) {
+ ret = PTR_ERR(chip->adda_4M_clk);
+ dev_err(chip->dev, "Failed to register ADDA-4M clock: %d\n",
+ ret);
+ goto err_unregister_rtc_32k;
+ }
+
+ for (i = 0; i < AC100_CLK32K_NUM; i++) {
+ struct ac100_clk32k *clk = &chip->clks[i];
+ struct clk_init_data init = {
+ .name = ac100_clk32k_names[i],
+ .ops = &ac100_clk32k_ops,
+ .parent_names = parents,
+ .num_parents = ARRAY_SIZE(parents),
+ .flags = 0,
+ };
+
+ clk->regmap = chip->regmap;
+ clk->offset = AC100_CLK32K_OUT_CTRL1 + i;
+ clk->hw.init = &init;
+
+ ret = devm_clk_hw_register(chip->dev, &clk->hw);
+ if (ret) {
+ dev_err(chip->dev, "Failed to register clk '%s': %d\n",
+ init.name, ret);
+ goto err_unregister_adda_4M;
+ }
+
+ chip->clk_data->hws[i] = &clk->hw;
+ }
+
+ chip->clk_data->num = i;
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, chip->clk_data);
+ if (ret)
+ goto err_unregister_adda_4M;
+
+ return 0;
+
+err_unregister_adda_4M:
+ clk_unregister_fixed_rate(chip->adda_4M_clk->clk);
+err_unregister_rtc_32k:
+ clk_unregister_fixed_rate(chip->rtc_32k_clk->clk);
+
+ return ret;
+}
+
+static void ac100_rtc_unregister_clks(struct ac100_rtc_dev *chip)
+{
+ of_clk_del_provider(chip->dev->of_node);
+ clk_unregister_fixed_rate(chip->adda_4M_clk->clk);
+ clk_unregister_fixed_rate(chip->rtc_32k_clk->clk);
+}
+
+/**
+ * RTC related bits
+ */
static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
{
struct ac100_rtc_dev *chip = dev_get_drvdata(dev);
@@ -349,13 +654,27 @@ static int ac100_rtc_probe(struct platform_device *pdev)
/* We do not support user interrupts */
chip->rtc->uie_unsupported = 1;
+ ret = ac100_rtc_register_clks(chip);
+ if (ret)
+ return ret;
+
dev_info(&pdev->dev, "RTC enabled\n");
return 0;
}
+static int ac100_rtc_remove(struct platform_device *pdev)
+{
+ struct ac100_rtc_dev *chip = platform_get_drvdata(pdev);
+
+ ac100_rtc_unregister_clks(chip);
+
+ return 0;
+}
+
static struct platform_driver ac100_rtc_driver = {
.probe = ac100_rtc_probe,
+ .remove = ac100_rtc_remove,
.driver = {
.name = "ac100-rtc",
},
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 06/10] ARM: dts: sun9i: a80-optimus: Add device node for AC100
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (3 preceding siblings ...)
2016-06-15 10:27 ` [PATCH v2 05/10] rtc: ac100: Add clk output support Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
2016-06-15 10:27 ` [PATCH v2 07/10] ARM: dts: sun9i: cubieboard4: " Chen-Yu Tsai
` (3 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/arm/boot/dts/sun9i-a80-optimus.dts | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
index 78fddd9152a5..24ef8e65a975 100644
--- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -322,6 +322,27 @@
};
};
};
+
+ ac100: codec@e89 {
+ compatible = "x-powers,ac100";
+ reg = <0xe89>;
+
+ ac100_codec: codec {
+ compatible = "x-powers,ac100-codec";
+ interrupt-parent = <&r_pio>;
+ interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PL9 */
+ };
+
+ ac100_rtc: rtc {
+ compatible = "x-powers,ac100-rtc";
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "cko1_rtc",
+ "cko2_rtc",
+ "cko3_rtc";
+ };
+ };
};
#include "axp809.dtsi"
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 07/10] ARM: dts: sun9i: cubieboard4: Add device node for AC100
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (4 preceding siblings ...)
2016-06-15 10:27 ` [PATCH v2 06/10] ARM: dts: sun9i: a80-optimus: Add device node for AC100 Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
2016-06-15 10:27 ` [PATCH v2 08/10] ARM: dts: sun9i: cubieboard4: Order nodes by alphabetical order Chen-Yu Tsai
` (2 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
index db770d06c31e..a92eeea1b222 100644
--- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -250,6 +250,27 @@
};
};
};
+
+ ac100: codec@e89 {
+ compatible = "x-powers,ac100";
+ reg = <0xe89>;
+
+ ac100_codec: codec {
+ compatible = "x-powers,ac100-codec";
+ interrupt-parent = <&r_pio>;
+ interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>; /* PL9 */
+ };
+
+ ac100_rtc: rtc {
+ compatible = "x-powers,ac100-rtc";
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "cko1_rtc",
+ "cko2_rtc",
+ "cko3_rtc";
+ };
+ };
};
#include "axp809.dtsi"
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 08/10] ARM: dts: sun9i: cubieboard4: Order nodes by alphabetical order
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (5 preceding siblings ...)
2016-06-15 10:27 ` [PATCH v2 07/10] ARM: dts: sun9i: cubieboard4: " Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
[not found] ` <1465986467-14802-9-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2016-06-15 10:27 ` [PATCH v2 09/10] ARM: dts: sun9i: a80-optimus: " Chen-Yu Tsai
2016-06-15 10:27 ` [PATCH v2 10/10] ARM: dts: sun9i: Switch to the AC100 RTC clock outputs for osc32k Chen-Yu Tsai
8 siblings, 1 reply; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Move the &pio node below the mmc nodes for proper ordering by name.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 32 ++++++++++++++---------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
index a92eeea1b222..65f4f32f89ad 100644
--- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -78,22 +78,6 @@
};
};
-&pio {
- led_pins_cubieboard4: led-pins@0 {
- allwinner,pins = "PH6", "PH17";
- allwinner,function = "gpio_out";
- allwinner,drive = <SUN4I_PINCTRL_10_MA>;
- allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
- };
-
- mmc0_cd_pin_cubieboard4: mmc0_cd_pin@0 {
- allwinner,pins = "PH18";
- allwinner,function = "gpio_in";
- allwinner,drive = <SUN4I_PINCTRL_10_MA>;
- allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
- };
-};
-
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin_cubieboard4>;
@@ -119,6 +103,22 @@
allwinner,drive = <SUN4I_PINCTRL_40_MA>;
};
+&pio {
+ led_pins_cubieboard4: led-pins@0 {
+ allwinner,pins = "PH6", "PH17";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ mmc0_cd_pin_cubieboard4: mmc0_cd_pin@0 {
+ allwinner,pins = "PH18";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+ };
+};
+
&r_ir {
status = "okay";
};
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 09/10] ARM: dts: sun9i: a80-optimus: Order nodes by alphabetical order
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (6 preceding siblings ...)
2016-06-15 10:27 ` [PATCH v2 08/10] ARM: dts: sun9i: cubieboard4: Order nodes by alphabetical order Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
[not found] ` <1465986467-14802-10-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2016-06-15 10:27 ` [PATCH v2 10/10] ARM: dts: sun9i: Switch to the AC100 RTC clock outputs for osc32k Chen-Yu Tsai
8 siblings, 1 reply; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
Move the mmc nodes above the ohci nodes for proper ordering by name.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/arm/boot/dts/sun9i-a80-optimus.dts | 50 ++++++++++++++++-----------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
index 24ef8e65a975..3b013dc5fef1 100644
--- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -119,6 +119,31 @@
status = "okay";
};
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin_optimus>;
+ vmmc-supply = <®_dcdc1>;
+ bus-width = <4>;
+ cd-gpios = <&pio 7 18 GPIO_ACTIVE_HIGH>; /* PH8 */
+ cd-inverted;
+ status = "okay";
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <®_dcdc1>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
+
+&mmc2_8bit_pins {
+ /* Increase drive strength for DDR modes */
+ allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+};
+
&ohci0 {
status = "okay";
};
@@ -157,31 +182,6 @@
};
};
-&mmc0 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin_optimus>;
- vmmc-supply = <®_dcdc1>;
- bus-width = <4>;
- cd-gpios = <&pio 7 18 GPIO_ACTIVE_HIGH>; /* PH8 */
- cd-inverted;
- status = "okay";
-};
-
-&mmc2 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc2_8bit_pins>;
- vmmc-supply = <®_dcdc1>;
- bus-width = <8>;
- non-removable;
- cap-mmc-hw-reset;
- status = "okay";
-};
-
-&mmc2_8bit_pins {
- /* Increase drive strength for DDR modes */
- allwinner,drive = <SUN4I_PINCTRL_40_MA>;
-};
-
&r_ir {
status = "okay";
};
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 10/10] ARM: dts: sun9i: Switch to the AC100 RTC clock outputs for osc32k
[not found] ` <1465986467-14802-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (7 preceding siblings ...)
2016-06-15 10:27 ` [PATCH v2 09/10] ARM: dts: sun9i: a80-optimus: " Chen-Yu Tsai
@ 2016-06-15 10:27 ` Chen-Yu Tsai
8 siblings, 0 replies; 19+ messages in thread
From: Chen-Yu Tsai @ 2016-06-15 10:27 UTC (permalink / raw)
To: Mark Brown, Lee Jones, Alessandro Zummo, Alexandre Belloni,
Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-clk-u79uwXL29TY76Z2rM5mHXA
The 32.768 kHz clock inside the A80 SoC is fed from an external source,
typically the AC100 RTC module.
Make the osc32k placeholder a fixed-factor clock so board dts files can
specify its source.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 5 +++++
arch/arm/boot/dts/sun9i-a80-optimus.dts | 5 +++++
arch/arm/boot/dts/sun9i-a80.dtsi | 9 +++------
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
index 65f4f32f89ad..b6299a9c14e3 100644
--- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -103,6 +103,11 @@
allwinner,drive = <SUN4I_PINCTRL_40_MA>;
};
+&osc32k {
+ /* osc32k input is from AC100 */
+ clocks = <&ac100_rtc 0>;
+};
+
&pio {
led_pins_cubieboard4: led-pins@0 {
allwinner,pins = "PH6", "PH17";
diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
index 3b013dc5fef1..2f079cbd2025 100644
--- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -152,6 +152,11 @@
status = "okay";
};
+&osc32k {
+ /* osc32k input is from AC100 */
+ clocks = <&ac100_rtc 0>;
+};
+
&pio {
led_pins_optimus: led-pins@0 {
allwinner,pins = "PH0", "PH1";
diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi
index f68b3242b33a..dd11115ec087 100644
--- a/arch/arm/boot/dts/sun9i-a80.dtsi
+++ b/arch/arm/boot/dts/sun9i-a80.dtsi
@@ -148,15 +148,12 @@
/*
* The 32k clock is from an external source, normally the
- * AC100 codec/RTC chip. This clock is by default enabled
- * and clocked at 32768 Hz, from the oscillator connected
- * to the AC100. It is configurable, but no such driver or
- * bindings exist yet.
+ * AC100 codec/RTC chip. This serves as a placeholder for
+ * board dts files to specify the source.
*/
osc32k: osc32k_clk {
#clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <32768>;
+ compatible = "fixed-factor-clock";
clock-output-names = "osc32k";
};
--
2.8.1
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply related [flat|nested] 19+ messages in thread