Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/4 v3] pinctrl/abx500: add AB8500 pinctrl driver
From: Linus Walleij @ 2013-01-21 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

From: Patrice Chotard <patrice.chotard@st.com>

This adds a subdriver for the AB8500 pinctrl portions.

Reviewed-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Actually commit the changes dropping the _ranges_ infix.
ChangeLog v1->v2:
- Move definition of init functions over to this patch from
  the core patch so we don't have unimplemented functions defined
  in the kernel.
- Drop a few "_ranges_" substrings wher unappropriate.
---
 arch/arm/mach-ux500/Kconfig      |   1 +
 drivers/pinctrl/Kconfig          |   4 +
 drivers/pinctrl/Makefile         |   1 +
 drivers/pinctrl/pinctrl-ab8500.c | 485 +++++++++++++++++++++++++++++++++++++++
 drivers/pinctrl/pinctrl-abx500.c |   3 +
 drivers/pinctrl/pinctrl-abx500.h |  13 ++
 6 files changed, 507 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-ab8500.c

diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 2c090d7..31f1b5a 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -19,6 +19,7 @@ config UX500_SOC_DB8500
 	select CPU_FREQ_TABLE if CPU_FREQ
 	select MFD_DB8500_PRCMU
 	select PINCTRL_DB8500
+	select PINCTRL_AB8500
 	select REGULATOR
 	select REGULATOR_DB8500_PRCMU
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ba3038c..367556f 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -33,6 +33,10 @@ config PINCTRL_ABX500
 	help
 	  Select this to enable the ABx500 family IC GPIO driver
 
+config PINCTRL_AB8500
+	bool "AB8500 pin controller driver"
+	depends on PINCTRL_ABX500 && ARCH_U8500
+
 config PINCTRL_AT91
 	bool "AT91 pinctrl driver"
 	depends on OF
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index ead4fa7..aad5c93 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_PINCTRL)		+= devicetree.o
 endif
 obj-$(CONFIG_GENERIC_PINCONF)	+= pinconf-generic.o
 obj-$(CONFIG_PINCTRL_ABX500)	+= pinctrl-abx500.o
+obj-$(CONFIG_PINCTRL_AB8500)	+= pinctrl-ab8500.o
 obj-$(CONFIG_PINCTRL_AT91)	+= pinctrl-at91.o
 obj-$(CONFIG_PINCTRL_BCM2835)	+= pinctrl-bcm2835.o
 obj-$(CONFIG_PINCTRL_IMX)	+= pinctrl-imx.o
diff --git a/drivers/pinctrl/pinctrl-ab8500.c b/drivers/pinctrl/pinctrl-ab8500.c
new file mode 100644
index 0000000..6495390
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-ab8500.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson.
+ *
+ * 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/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include "pinctrl-abx500.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define ABX500_GPIO(offset)		(offset)
+
+#define AB8500_PIN_T10		ABX500_GPIO(1)
+#define AB8500_PIN_T9		ABX500_GPIO(2)
+#define AB8500_PIN_U9		ABX500_GPIO(3)
+#define AB8500_PIN_W2		ABX500_GPIO(4)
+/* hole */
+#define AB8500_PIN_Y18		ABX500_GPIO(6)
+#define AB8500_PIN_AA20		ABX500_GPIO(7)
+#define AB8500_PIN_W18		ABX500_GPIO(8)
+#define AB8500_PIN_AA19		ABX500_GPIO(9)
+#define AB8500_PIN_U17		ABX500_GPIO(10)
+#define AB8500_PIN_AA18		ABX500_GPIO(11)
+#define AB8500_PIN_U16		ABX500_GPIO(12)
+#define AB8500_PIN_W17		ABX500_GPIO(13)
+#define AB8500_PIN_F14		ABX500_GPIO(14)
+#define AB8500_PIN_B17		ABX500_GPIO(15)
+#define AB8500_PIN_F15		ABX500_GPIO(16)
+#define AB8500_PIN_P5		ABX500_GPIO(17)
+#define AB8500_PIN_R5		ABX500_GPIO(18)
+#define AB8500_PIN_U5		ABX500_GPIO(19)
+#define AB8500_PIN_T5		ABX500_GPIO(20)
+#define AB8500_PIN_H19		ABX500_GPIO(21)
+#define AB8500_PIN_G20		ABX500_GPIO(22)
+#define AB8500_PIN_G19		ABX500_GPIO(23)
+#define AB8500_PIN_T14		ABX500_GPIO(24)
+#define AB8500_PIN_R16		ABX500_GPIO(25)
+#define AB8500_PIN_M16		ABX500_GPIO(26)
+#define AB8500_PIN_J6		ABX500_GPIO(27)
+#define AB8500_PIN_K6		ABX500_GPIO(28)
+#define AB8500_PIN_G6		ABX500_GPIO(29)
+#define AB8500_PIN_H6		ABX500_GPIO(30)
+#define AB8500_PIN_F5		ABX500_GPIO(31)
+#define AB8500_PIN_G5		ABX500_GPIO(32)
+/* hole */
+#define AB8500_PIN_R17		ABX500_GPIO(34)
+#define AB8500_PIN_W15		ABX500_GPIO(35)
+#define AB8500_PIN_A17		ABX500_GPIO(36)
+#define AB8500_PIN_E15		ABX500_GPIO(37)
+#define AB8500_PIN_C17		ABX500_GPIO(38)
+#define AB8500_PIN_E16		ABX500_GPIO(39)
+#define AB8500_PIN_T19		ABX500_GPIO(40)
+#define AB8500_PIN_U19		ABX500_GPIO(41)
+#define AB8500_PIN_U2		ABX500_GPIO(42)
+
+/* indicates the highest GPIO number */
+#define AB8500_GPIO_MAX_NUMBER	42
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc ab8500_pins[] = {
+	PINCTRL_PIN(AB8500_PIN_T10, "GPIO1_T10"),
+	PINCTRL_PIN(AB8500_PIN_T9, "GPIO2_T9"),
+	PINCTRL_PIN(AB8500_PIN_U9, "GPIO3_U9"),
+	PINCTRL_PIN(AB8500_PIN_W2, "GPIO4_W2"),
+	/* hole */
+	PINCTRL_PIN(AB8500_PIN_Y18, "GPIO6_Y18"),
+	PINCTRL_PIN(AB8500_PIN_AA20, "GPIO7_AA20"),
+	PINCTRL_PIN(AB8500_PIN_W18, "GPIO8_W18"),
+	PINCTRL_PIN(AB8500_PIN_AA19, "GPIO9_AA19"),
+	PINCTRL_PIN(AB8500_PIN_U17, "GPIO10_U17"),
+	PINCTRL_PIN(AB8500_PIN_AA18, "GPIO11_AA18"),
+	PINCTRL_PIN(AB8500_PIN_U16, "GPIO12_U16"),
+	PINCTRL_PIN(AB8500_PIN_W17, "GPIO13_W17"),
+	PINCTRL_PIN(AB8500_PIN_F14, "GPIO14_F14"),
+	PINCTRL_PIN(AB8500_PIN_B17, "GPIO15_B17"),
+	PINCTRL_PIN(AB8500_PIN_F15, "GPIO16_F15"),
+	PINCTRL_PIN(AB8500_PIN_P5, "GPIO17_P5"),
+	PINCTRL_PIN(AB8500_PIN_R5, "GPIO18_R5"),
+	PINCTRL_PIN(AB8500_PIN_U5, "GPIO19_U5"),
+	PINCTRL_PIN(AB8500_PIN_T5, "GPIO20_T5"),
+	PINCTRL_PIN(AB8500_PIN_H19, "GPIO21_H19"),
+	PINCTRL_PIN(AB8500_PIN_G20, "GPIO22_G20"),
+	PINCTRL_PIN(AB8500_PIN_G19, "GPIO23_G19"),
+	PINCTRL_PIN(AB8500_PIN_T14, "GPIO24_T14"),
+	PINCTRL_PIN(AB8500_PIN_R16, "GPIO25_R16"),
+	PINCTRL_PIN(AB8500_PIN_M16, "GPIO26_M16"),
+	PINCTRL_PIN(AB8500_PIN_J6, "GPIO27_J6"),
+	PINCTRL_PIN(AB8500_PIN_K6, "GPIO28_K6"),
+	PINCTRL_PIN(AB8500_PIN_G6, "GPIO29_G6"),
+	PINCTRL_PIN(AB8500_PIN_H6, "GPIO30_H6"),
+	PINCTRL_PIN(AB8500_PIN_F5, "GPIO31_F5"),
+	PINCTRL_PIN(AB8500_PIN_G5, "GPIO32_G5"),
+	/* hole */
+	PINCTRL_PIN(AB8500_PIN_R17, "GPIO34_R17"),
+	PINCTRL_PIN(AB8500_PIN_W15, "GPIO35_W15"),
+	PINCTRL_PIN(AB8500_PIN_A17, "GPIO36_A17"),
+	PINCTRL_PIN(AB8500_PIN_E15, "GPIO37_E15"),
+	PINCTRL_PIN(AB8500_PIN_C17, "GPIO38_C17"),
+	PINCTRL_PIN(AB8500_PIN_E16, "GPIO39_E16"),
+	PINCTRL_PIN(AB8500_PIN_T19, "GPIO40_T19"),
+	PINCTRL_PIN(AB8500_PIN_U19, "GPIO41_U19"),
+	PINCTRL_PIN(AB8500_PIN_U2, "GPIO42_U2"),
+};
+
+/*
+ * Maps local GPIO offsets to local pin numbers
+ */
+static const struct abx500_pinrange ab8500_pinranges[] = {
+	ABX500_PINRANGE(1, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(6, 4, ABX500_ALT_A),
+	ABX500_PINRANGE(10, 4, ABX500_DEFAULT),
+	ABX500_PINRANGE(14, 12, ABX500_ALT_A),
+	ABX500_PINRANGE(26, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(27, 6, ABX500_ALT_A),
+	ABX500_PINRANGE(34, 1, ABX500_ALT_A),
+	ABX500_PINRANGE(35, 1, ABX500_DEFAULT),
+	ABX500_PINRANGE(36, 7, ABX500_ALT_A),
+};
+
+/*
+ * Read the pin group names like this:
+ * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function
+ *
+ * The groups are arranged as sets per altfunction column, so we can
+ * mux in one group at a time by selecting the same altfunction for them
+ * all. When functions require pins on different altfunctions, you need
+ * to combine several groups.
+ */
+
+/* default column */
+static const unsigned sysclkreq2_d_1_pins[] = { AB8500_PIN_T10 };
+static const unsigned sysclkreq3_d_1_pins[] = { AB8500_PIN_T9 };
+static const unsigned sysclkreq4_d_1_pins[] = { AB8500_PIN_U9 };
+static const unsigned sysclkreq6_d_1_pins[] = { AB8500_PIN_W2 };
+static const unsigned ycbcr0123_d_1_pins[] = { AB8500_PIN_Y18, AB8500_PIN_AA20,
+					AB8500_PIN_W18, AB8500_PIN_AA19};
+static const unsigned gpio10_d_1_pins[] = { AB8500_PIN_U17 };
+static const unsigned gpio11_d_1_pins[] = { AB8500_PIN_AA18 };
+static const unsigned gpio12_d_1_pins[] = { AB8500_PIN_U16 };
+static const unsigned gpio13_d_1_pins[] = { AB8500_PIN_W17 };
+static const unsigned pwmout1_d_1_pins[] = { AB8500_PIN_F14 };
+static const unsigned pwmout2_d_1_pins[] = { AB8500_PIN_B17 };
+static const unsigned pwmout3_d_1_pins[] = { AB8500_PIN_F15 };
+
+/* audio data interface 1*/
+static const unsigned adi1_d_1_pins[] = { AB8500_PIN_P5, AB8500_PIN_R5,
+					AB8500_PIN_U5, AB8500_PIN_T5 };
+/* USBUICC */
+static const unsigned usbuicc_d_1_pins[] = { AB8500_PIN_H19, AB8500_PIN_G20,
+					AB8500_PIN_G19 };
+static const unsigned sysclkreq7_d_1_pins[] = { AB8500_PIN_T14 };
+static const unsigned sysclkreq8_d_1_pins[] = { AB8500_PIN_R16 };
+static const unsigned gpio26_d_1_pins[] = { AB8500_PIN_M16 };
+/* Digital microphone 1 and 2 */
+static const unsigned dmic12_d_1_pins[] = { AB8500_PIN_J6, AB8500_PIN_K6 };
+/* Digital microphone 3 and 4 */
+static const unsigned dmic34_d_1_pins[] = { AB8500_PIN_G6, AB8500_PIN_H6 };
+/* Digital microphone 5 and 6 */
+static const unsigned dmic56_d_1_pins[] = { AB8500_PIN_F5, AB8500_PIN_G5 };
+static const unsigned extcpena_d_1_pins[] = { AB8500_PIN_R17 };
+static const unsigned gpio35_d_1_pins[] = { AB8500_PIN_W15 };
+/* APE SPI */
+static const unsigned apespi_d_1_pins[] = { AB8500_PIN_A17, AB8500_PIN_E15,
+					AB8500_PIN_C17, AB8500_PIN_E16};
+/* modem SDA/SCL */
+static const unsigned modsclsda_d_1_pins[] = { AB8500_PIN_T19, AB8500_PIN_U19 };
+static const unsigned sysclkreq5_d_1_pins[] = { AB8500_PIN_U2 };
+
+/* Altfunction A column */
+static const unsigned gpio1_a_1_pins[] = { AB8500_PIN_T10 };
+static const unsigned gpio2_a_1_pins[] = { AB8500_PIN_T9 };
+static const unsigned gpio3_a_1_pins[] = { AB8500_PIN_U9 };
+static const unsigned gpio4_a_1_pins[] = { AB8500_PIN_W2 };
+static const unsigned gpio6_a_1_pins[] = { AB8500_PIN_Y18 };
+static const unsigned gpio7_a_1_pins[] = { AB8500_PIN_AA20 };
+static const unsigned gpio8_a_1_pins[] = { AB8500_PIN_W18 };
+static const unsigned gpio9_a_1_pins[] = { AB8500_PIN_AA19 };
+/* YCbCr4 YCbCr5 YCbCr6 YCbCr7*/
+static const unsigned ycbcr4567_a_1_pins[] = { AB8500_PIN_U17, AB8500_PIN_AA18,
+					AB8500_PIN_U16, AB8500_PIN_W17};
+static const unsigned gpio14_a_1_pins[] = { AB8500_PIN_F14 };
+static const unsigned gpio15_a_1_pins[] = { AB8500_PIN_B17 };
+static const unsigned gpio16_a_1_pins[] = { AB8500_PIN_F15 };
+static const unsigned gpio17_a_1_pins[] = { AB8500_PIN_P5 };
+static const unsigned gpio18_a_1_pins[] = { AB8500_PIN_R5 };
+static const unsigned gpio19_a_1_pins[] = { AB8500_PIN_U5 };
+static const unsigned gpio20_a_1_pins[] = { AB8500_PIN_T5 };
+static const unsigned gpio21_a_1_pins[] = { AB8500_PIN_H19 };
+static const unsigned gpio22_a_1_pins[] = { AB8500_PIN_G20 };
+static const unsigned gpio23_a_1_pins[] = { AB8500_PIN_G19 };
+static const unsigned gpio24_a_1_pins[] = { AB8500_PIN_T14 };
+static const unsigned gpio25_a_1_pins[] = { AB8500_PIN_R16 };
+static const unsigned gpio27_a_1_pins[] = { AB8500_PIN_J6 };
+static const unsigned gpio28_a_1_pins[] = { AB8500_PIN_K6 };
+static const unsigned gpio29_a_1_pins[] = { AB8500_PIN_G6 };
+static const unsigned gpio30_a_1_pins[] = { AB8500_PIN_H6 };
+static const unsigned gpio31_a_1_pins[] = { AB8500_PIN_F5 };
+static const unsigned gpio32_a_1_pins[] = { AB8500_PIN_G5 };
+static const unsigned gpio34_a_1_pins[] = { AB8500_PIN_R17 };
+static const unsigned gpio36_a_1_pins[] = { AB8500_PIN_A17 };
+static const unsigned gpio37_a_1_pins[] = { AB8500_PIN_E15 };
+static const unsigned gpio38_a_1_pins[] = { AB8500_PIN_C17 };
+static const unsigned gpio39_a_1_pins[] = { AB8500_PIN_E16 };
+static const unsigned gpio40_a_1_pins[] = { AB8500_PIN_T19 };
+static const unsigned gpio41_a_1_pins[] = { AB8500_PIN_U19 };
+static const unsigned gpio42_a_1_pins[] = { AB8500_PIN_U2 };
+
+/* Altfunction B colum */
+static const unsigned hiqclkena_b_1_pins[] = { AB8500_PIN_U17 };
+static const unsigned usbuiccpd_b_1_pins[] = { AB8500_PIN_AA18 };
+static const unsigned i2ctrig1_b_1_pins[] = { AB8500_PIN_U16 };
+static const unsigned i2ctrig2_b_1_pins[] = { AB8500_PIN_W17 };
+
+/* Altfunction C column */
+static const unsigned usbvdat_c_1_pins[] = { AB8500_PIN_W17 };
+
+
+#define AB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct abx500_pingroup ab8500_groups[] = {
+	/* default column */
+	AB8500_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(ycbcr0123_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio12_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(adi1_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio26_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(gpio35_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(apespi_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT),
+	AB8500_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT),
+	/* Altfunction A column */
+	AB8500_PIN_GROUP(gpio1_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio2_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio3_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio4_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio6_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio7_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio8_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio9_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(ycbcr4567_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio14_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio15_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio16_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio17_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio18_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio19_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio20_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio21_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio22_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio23_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio24_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio25_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio27_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio28_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio29_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio30_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio31_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio32_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio34_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio36_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio37_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio38_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio39_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio40_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio41_a_1, ABX500_ALT_A),
+	AB8500_PIN_GROUP(gpio42_a_1, ABX500_ALT_A),
+	/* Altfunction B column */
+	AB8500_PIN_GROUP(hiqclkena_b_1, ABX500_ALT_B),
+	AB8500_PIN_GROUP(usbuiccpd_b_1, ABX500_ALT_B),
+	AB8500_PIN_GROUP(i2ctrig1_b_1, ABX500_ALT_B),
+	AB8500_PIN_GROUP(i2ctrig2_b_1, ABX500_ALT_B),
+	/* Altfunction C column */
+	AB8500_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define AB8500_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+AB8500_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1",
+		"sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1",
+		"sysclkreq7_d_1", "sysclkreq8_d_1");
+AB8500_FUNC_GROUPS(ycbcr, "ycbcr0123_d_1", "ycbcr4567_a_1");
+AB8500_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1",
+		"gpio6_a_1", "gpio7_a_1", "gpio8_a_1", "gpio9_a_1",
+		"gpio10_d_1", "gpio11_d_1", "gpio12_d_1", "gpio13_d_1",
+		"gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1",
+		"gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio21_a_1",
+		"gpio22_a_1", "gpio23_a_1", "gpio24_a_1", "gpio25_a_1",
+		"gpio26_d_1", "gpio27_a_1", "gpio28_a_1", "gpio29_a_1",
+		"gpio30_a_1", "gpio31_a_1", "gpio32_a_1", "gpio34_a_1",
+		"gpio35_d_1", "gpio36_a_1", "gpio37_a_1", "gpio38_a_1",
+		"gpio39_a_1", "gpio40_a_1", "gpio41_a_1", "gpio42_a_1");
+AB8500_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1");
+AB8500_FUNC_GROUPS(adi1, "adi1_d_1");
+AB8500_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_b_1");
+AB8500_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1");
+AB8500_FUNC_GROUPS(extcpena, "extcpena_d_1");
+AB8500_FUNC_GROUPS(apespi, "apespi_d_1");
+AB8500_FUNC_GROUPS(modsclsda, "modsclsda_d_1");
+AB8500_FUNC_GROUPS(hiqclkena, "hiqclkena_b_1");
+AB8500_FUNC_GROUPS(i2ctrig, "i2ctrig1_b_1", "i2ctrig2_b_1");
+AB8500_FUNC_GROUPS(usbvdat, "usbvdat_c_1");
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct abx500_function ab8500_functions[] = {
+	FUNCTION(sysclkreq),
+	FUNCTION(ycbcr),
+	FUNCTION(gpio),
+	FUNCTION(pwmout),
+	FUNCTION(adi1),
+	FUNCTION(usbuicc),
+	FUNCTION(dmic),
+	FUNCTION(extcpena),
+	FUNCTION(apespi),
+	FUNCTION(modsclsda),
+	FUNCTION(hiqclkena),
+	FUNCTION(i2ctrig),
+	FUNCTION(usbvdat),
+};
+
+/*
+ * this table translates what's is in the AB8500 specification regarding the
+ * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C).
+ * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1,
+ * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val),
+ *
+ * example :
+ *
+ *	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 0, 1 ,2),
+ *	means that pin AB8500_PIN_W17 (pin 13) supports 4 mux (default/ALT_A,
+ *	ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to
+ *	select the mux.  ALTA, ALTB and ALTC val indicates values to write in
+ *	ALTERNATFUNC register. We need to specifies these values as SOC
+ *	designers didn't apply the same logic on how to select mux in the
+ *	ABx500 family.
+ *
+ *	As this pins supports at least ALT_B mux, default mux is
+ *	selected by writing 1 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3
+ *	default	|       1       |          0          |          0
+ *	alt_A	|       0       |          0          |          0
+ *	alt_B	|       0       |          0          |          1
+ *	alt_C	|       0       |          1          |          0
+ *
+ *	ALTERNATE_FUNCTIONS(8,      7, UNUSED, UNUSED),
+ *	means that pin AB8500_PIN_W18 (pin 8) supports 2 mux, so only GPIOSEL
+ *	register is used to select the mux. As this pins doesn't support at
+ *	least ALT_B mux, default mux is by writing 0 in GPIOSEL bit :
+ *
+ *		| GPIOSEL bit=7 | alternatfunc bit2=  | alternatfunc bit1=
+ *	default	|       0       |          0          |          0
+ *	alt_A	|       1       |          0          |          0
+ */
+
+struct alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
+	ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
+	ALTERNATE_FUNCTIONS(1,	    0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(2,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(3,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/
+	ALTERNATE_FUNCTIONS(4,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/
+	/* bit 4 reserved */
+	ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */
+	ALTERNATE_FUNCTIONS(6,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO6, altA controlled by bit 5*/
+	ALTERNATE_FUNCTIONS(7,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO7, altA controlled by bit 6*/
+	ALTERNATE_FUNCTIONS(8,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO8, altA controlled by bit 7*/
+
+	ALTERNATE_FUNCTIONS(9,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO9, altA controlled by bit 0*/
+	ALTERNATE_FUNCTIONS(10,     1,      0, UNUSED, 0, 1, 0), /* GPIO10, altA and altB controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(11,     2,      1, UNUSED, 0, 1, 0), /* GPIO11, altA and altB controlled by bit 1 */
+	ALTERNATE_FUNCTIONS(12,     3,      2, UNUSED, 0, 1, 0), /* GPIO12, altA and altB controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(13,     4,      3,      4, 0, 1, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
+	ALTERNATE_FUNCTIONS(14,     5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(15,     6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(16,     7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */
+	/*
+	 * pins 17 to 20 are special case, only bit 0 is used to select
+	 * alternate function for these 4 pins.
+	 * bits 1 to 3 are reserved
+	 */
+	ALTERNATE_FUNCTIONS(17,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(18,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(19,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(20,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(21,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(22,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(23,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(24,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */
+
+	ALTERNATE_FUNCTIONS(25,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */
+	/* pin 26 special case, no alternate function, bit 1 reserved */
+	ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO26 */
+	ALTERNATE_FUNCTIONS(27,      2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */
+	ALTERNATE_FUNCTIONS(28,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(29,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(30,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(31,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(32,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */
+
+	ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */
+	ALTERNATE_FUNCTIONS(34,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */
+	/* pin 35 special case, no alternate function, bit 2 reserved */
+	ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO35 */
+	ALTERNATE_FUNCTIONS(36,      3, UNUSED, UNUSED, 0, 0, 0), /* GPIO36, altA controlled by bit 3 */
+	ALTERNATE_FUNCTIONS(37,      4, UNUSED, UNUSED, 0, 0, 0), /* GPIO37, altA controlled by bit 4 */
+	ALTERNATE_FUNCTIONS(38,      5, UNUSED, UNUSED, 0, 0, 0), /* GPIO38, altA controlled by bit 5 */
+	ALTERNATE_FUNCTIONS(39,      6, UNUSED, UNUSED, 0, 0, 0), /* GPIO39, altA controlled by bit 6 */
+	ALTERNATE_FUNCTIONS(40,      7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */
+
+	ALTERNATE_FUNCTIONS(41,      0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */
+	ALTERNATE_FUNCTIONS(42,      1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */
+};
+
+/*
+ * Only some GPIOs are interrupt capable, and they are
+ * organized in discontiguous clusters:
+ *
+ *	GPIO6 to GPIO13
+ *	GPIO24 and GPIO25
+ *	GPIO36 to GPIO41
+ */
+struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
+	GPIO_IRQ_CLUSTER(5, 12, 0), /* GPIO numbers start from 1 */
+	GPIO_IRQ_CLUSTER(23, 24, 0),
+	GPIO_IRQ_CLUSTER(35, 40, 0),
+};
+
+static struct abx500_pinctrl_soc_data ab8500_soc = {
+	.gpio_ranges = ab8500_pinranges,
+	.gpio_num_ranges = ARRAY_SIZE(ab8500_pinranges),
+	.pins = ab8500_pins,
+	.npins = ARRAY_SIZE(ab8500_pins),
+	.functions = ab8500_functions,
+	.nfunctions = ARRAY_SIZE(ab8500_functions),
+	.groups = ab8500_groups,
+	.ngroups = ARRAY_SIZE(ab8500_groups),
+	.alternate_functions = ab8500_alternate_functions,
+	.gpio_irq_cluster = ab8500_gpio_irq_cluster,
+	.ngpio_irq_cluster = ARRAY_SIZE(ab8500_gpio_irq_cluster),
+	.irq_gpio_rising_offset = AB8500_INT_GPIO6R,
+	.irq_gpio_falling_offset = AB8500_INT_GPIO6F,
+	.irq_gpio_factor = 1,
+};
+
+void __devinit
+abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
+{
+	*soc = &ab8500_soc;
+}
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c
index 26abfd8..13ae68f 100644
--- a/drivers/pinctrl/pinctrl-abx500.c
+++ b/drivers/pinctrl/pinctrl-abx500.c
@@ -1116,6 +1116,9 @@ static int __devinit abx500_gpio_probe(struct platform_device *pdev)
 
 	/* Poke in other ASIC variants here */
 	switch (platid->driver_data) {
+	case PINCTRL_AB8500:
+		abx500_pinctrl_ab8500_init(&pct->soc);
+		break;
 	default:
 		dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n",
 				(int) platid->driver_data);
diff --git a/drivers/pinctrl/pinctrl-abx500.h b/drivers/pinctrl/pinctrl-abx500.h
index 436ace3..a6c9332 100644
--- a/drivers/pinctrl/pinctrl-abx500.h
+++ b/drivers/pinctrl/pinctrl-abx500.h
@@ -177,4 +177,17 @@ struct abx500_pinctrl_soc_data {
 	int irq_gpio_factor;
 };
 
+#ifdef CONFIG_PINCTRL_AB8500
+
+void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
 #endif /* PINCTRL_PINCTRL_ABx500_H */
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v2 4/4] drivers: usb: start using the control module driver
From: Kishon Vijay Abraham I @ 2013-01-21 14:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358777308-2409-1-git-send-email-kishon@ti.com>

Start using the control module driver for powering on the PHY and for
writing to the mailbox instead of writing to the control module
registers on their own.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/devicetree/bindings/usb/omap-usb.txt |    4 ++
 Documentation/devicetree/bindings/usb/usb-phy.txt  |    7 +--
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |   13 ----
 drivers/usb/musb/Kconfig                           |    1 +
 drivers/usb/musb/omap2430.c                        |   64 +++++++-------------
 drivers/usb/musb/omap2430.h                        |    9 ---
 drivers/usb/phy/Kconfig                            |    1 +
 drivers/usb/phy/omap-usb2.c                        |   38 +++---------
 include/linux/usb/omap_usb.h                       |    4 +-
 9 files changed, 40 insertions(+), 101 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index ead6ba9..8bedbba 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -3,6 +3,9 @@ OMAP GLUE AND OTHER OMAP SPECIFIC COMPONENTS
 OMAP MUSB GLUE
  - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
  - ti,hwmods : must be "usb_otg_hs"
+ - ti,has_mailbox : to specify that omap uses an external mailbox
+   (in control module) to communicate with the musb core during device connect
+   and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
  - num_eps : Specifies the number of endpoints. This is also a
@@ -24,6 +27,7 @@ SOC specific device node entry
 usb_otg_hs: usb_otg_hs at 4a0ab000 {
 	compatible = "ti,omap4-musb";
 	ti,hwmods = "usb_otg_hs";
+	ti,has_mailbox;
 	multipoint = <1>;
 	num_eps = <16>;
 	ram_bits = <12>;
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
index 2466b6f..48761a2 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -4,9 +4,7 @@ OMAP USB2 PHY
 
 Required properties:
  - compatible: Should be "ti,omap-usb2"
- - reg : Address and length of the register set for the device. Also
-add the address of control module dev conf register until a driver for
-control module is added
+ - reg : Address and length of the register set for the device.
 
 Optional properties:
  - ctrl_module : phandle of the control module used by PHY driver to power on
@@ -16,7 +14,6 @@ This is usually a subnode of ocp2scp to which it is connected.
 
 usb2phy at 4a0ad080 {
 	compatible = "ti,omap-usb2";
-	reg = <0x4a0ad080 0x58>,
-	      <0x4a002300 0x4>;
+	reg = <0x4a0ad080 0x58>;
 	ctrl_module = <&omap_control_usb>;
 };
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 129d508..103f4ba 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2698,13 +2698,6 @@ static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
 		.end		= 0x4a0ae000,
 		.flags		= IORESOURCE_MEM,
 	},
-	{
-		/* XXX: Remove this once control module driver is in place */
-		.name		= "ctrl_dev",
-		.start		= 0x4a002300,
-		.end		= 0x4a002303,
-		.flags		= IORESOURCE_MEM,
-	},
 	{ }
 };
 
@@ -6152,12 +6145,6 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
 		.pa_end		= 0x4a0ab7ff,
 		.flags		= ADDR_TYPE_RT
 	},
-	{
-		/* XXX: Remove this once control module driver is in place */
-		.pa_start	= 0x4a00233c,
-		.pa_end		= 0x4a00233f,
-		.flags		= ADDR_TYPE_RT
-	},
 	{ }
 };
 
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 23a0b7f..de6e5ce 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -11,6 +11,7 @@ config USB_MUSB_HDRC
 	select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
 	select TWL4030_USB if MACH_OMAP_3430SDP
 	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
+	select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
 	select USB_OTG_UTILS
 	help
 	  Say Y here if your system has a dual role high speed USB
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index da00af4..bf6cfe0 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -37,6 +37,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/usb/musb-omap.h>
+#include <linux/usb/omap_control_usb.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -46,7 +47,7 @@ struct omap2430_glue {
 	struct platform_device	*musb;
 	enum omap_musb_vbus_id_status status;
 	struct work_struct	omap_musb_mailbox_work;
-	u32 __iomem		*control_otghs;
+	struct device		*control_otghs;
 };
 #define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
@@ -54,26 +55,6 @@ struct omap2430_glue		*_glue;
 
 static struct timer_list musb_idle_timer;
 
-/**
- * omap4_usb_phy_mailbox - write to usb otg mailbox
- * @glue: struct omap2430_glue *
- * @val: the value to be written to the mailbox
- *
- * On detection of a device (ID pin is grounded), this API should be called
- * to set AVALID, VBUSVALID and ID pin is grounded.
- *
- * When OMAP is connected to a host (OMAP in device mode), this API
- * is called to set AVALID, VBUSVALID and ID pin in high impedance.
- *
- * XXX: This function will be removed once we have a seperate driver for
- * control module
- */
-static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
-{
-	if (glue->control_otghs)
-		writel(val, glue->control_otghs);
-}
-
 static void musb_do_idle(unsigned long _musb)
 {
 	struct musb	*musb = (void *)_musb;
@@ -269,7 +250,6 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox);
 
 static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
-	u32 val;
 	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
@@ -285,8 +265,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 		musb->xceiv->last_event = USB_EVENT_ID;
 		if (musb->gadget_driver) {
 			pm_runtime_get_sync(dev);
-			val = AVALID | VBUSVALID;
-			omap4_usb_phy_mailbox(glue, val);
+			omap_control_usb_set_mode(glue->control_otghs,
+				USB_MODE_HOST);
 			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
@@ -299,8 +279,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 		musb->xceiv->last_event = USB_EVENT_VBUS;
 		if (musb->gadget_driver)
 			pm_runtime_get_sync(dev);
-		val = IDDIG | AVALID | VBUSVALID;
-		omap4_usb_phy_mailbox(glue, val);
+		omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
 		break;
 
 	case OMAP_MUSB_ID_FLOAT:
@@ -317,8 +296,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 			if (musb->xceiv->otg->set_vbus)
 				otg_set_vbus(musb->xceiv->otg, 0);
 		}
-		val = SESSEND | IDDIG;
-		omap4_usb_phy_mailbox(glue, val);
+		omap_control_usb_set_mode(glue->control_otghs,
+			USB_MODE_DISCONNECT);
 		break;
 	default:
 		dev_dbg(dev, "ID float\n");
@@ -415,7 +394,6 @@ err1:
 static void omap2430_musb_enable(struct musb *musb)
 {
 	u8		devctl;
-	u32		val;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
@@ -425,8 +403,7 @@ static void omap2430_musb_enable(struct musb *musb)
 	switch (glue->status) {
 
 	case OMAP_MUSB_ID_GROUND:
-		val = AVALID | VBUSVALID;
-		omap4_usb_phy_mailbox(glue, val);
+		omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
 		if (data->interface_type != MUSB_INTERFACE_UTMI)
 			break;
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -445,8 +422,7 @@ static void omap2430_musb_enable(struct musb *musb)
 		break;
 
 	case OMAP_MUSB_VBUS_VALID:
-		val = IDDIG | AVALID | VBUSVALID;
-		omap4_usb_phy_mailbox(glue, val);
+		omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
 		break;
 
 	default:
@@ -456,14 +432,12 @@ static void omap2430_musb_enable(struct musb *musb)
 
 static void omap2430_musb_disable(struct musb *musb)
 {
-	u32 val;
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
-	if (glue->status != OMAP_MUSB_UNKNOWN) {
-		val = SESSEND | IDDIG;
-		omap4_usb_phy_mailbox(glue, val);
-	}
+	if (glue->status != OMAP_MUSB_UNKNOWN)
+		omap_control_usb_set_mode(glue->control_otghs,
+			USB_MODE_DISCONNECT);
 }
 
 static int omap2430_musb_exit(struct musb *musb)
@@ -523,9 +497,6 @@ static int omap2430_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 
-	glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
-	if (glue->control_otghs == NULL)
-		dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
 
 	if (np) {
 		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -558,11 +529,22 @@ static int omap2430_probe(struct platform_device *pdev)
 		of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
 		of_property_read_u32(np, "power", (u32 *)&pdata->power);
 		config->multipoint = of_property_read_bool(np, "multipoint");
+		pdata->has_mailbox = of_property_read_bool(np,
+		    "ti,has_mailbox");
 
 		pdata->board_data	= data;
 		pdata->config		= config;
 	}
 
+	if (pdata->has_mailbox) {
+		glue->control_otghs = omap_get_control_dev();
+		if (IS_ERR(glue->control_otghs)) {
+			dev_vdbg(&pdev->dev, "Failed to get control device\n");
+			return -ENODEV;
+		}
+	} else {
+		glue->control_otghs = ERR_PTR(-ENODEV);
+	}
 	pdata->platform_ops		= &omap2430_ops;
 
 	platform_set_drvdata(pdev, glue);
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index 8ef6566..1b5e83a 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -49,13 +49,4 @@
 #define OTG_FORCESTDBY		0x414
 #	define	ENABLEFORCE		(1 << 0)
 
-/*
- * Control Module bit definitions
- * XXX: Will be removed once we have a driver for control module.
- */
-#define	AVALID				BIT(0)
-#define	BVALID				BIT(1)
-#define	VBUSVALID			BIT(2)
-#define	SESSEND				BIT(3)
-#define	IDDIG				BIT(4)
 #endif	/* __MUSB_OMAP243X_H__ */
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 20479e8..cd1af7d 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -8,6 +8,7 @@ config OMAP_USB2
 	tristate "OMAP USB2 PHY Driver"
 	depends on ARCH_OMAP2PLUS
 	select USB_OTG_UTILS
+	select OMAP_CONTROL_USB
 	help
 	  Enable this to support the transceiver that is part of SOC. This
 	  driver takes care of all the PHY functionality apart from comparator.
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
index 26ae8f4..4b59b39 100644
--- a/drivers/usb/phy/omap-usb2.c
+++ b/drivers/usb/phy/omap-usb2.c
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
+#include <linux/usb/omap_control_usb.h>
 
 /**
  * omap_usb2_set_comparator - links the comparator present in the sytem with
@@ -52,29 +53,6 @@ int omap_usb2_set_comparator(struct phy_companion *comparator)
 }
 EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
 
-/**
- * omap_usb_phy_power - power on/off the phy using control module reg
- * @phy: struct omap_usb *
- * @on: 0 or 1, based on powering on or off the PHY
- *
- * XXX: Remove this function once control module driver gets merged
- */
-static void omap_usb_phy_power(struct omap_usb *phy, int on)
-{
-	u32 val;
-
-	if (on) {
-		val = readl(phy->control_dev);
-		if (val & PHY_PD) {
-			writel(~PHY_PD, phy->control_dev);
-			/* XXX: add proper documentation for this delay */
-			mdelay(200);
-		}
-	} else {
-		writel(PHY_PD, phy->control_dev);
-	}
-}
-
 static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
 {
 	struct omap_usb *phy = phy_to_omapusb(otg->phy);
@@ -124,7 +102,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
 	struct omap_usb *phy = phy_to_omapusb(x);
 
 	if (suspend && !phy->is_suspended) {
-		omap_usb_phy_power(phy, 0);
+		omap_control_usb_phy_power(phy->control_dev, 0);
 		pm_runtime_put_sync(phy->dev);
 		phy->is_suspended = 1;
 	} else if (!suspend && phy->is_suspended) {
@@ -134,7 +112,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
 									ret);
 			return ret;
 		}
-		omap_usb_phy_power(phy, 1);
+		omap_control_usb_phy_power(phy->control_dev, 1);
 		phy->is_suspended = 0;
 	}
 
@@ -168,14 +146,14 @@ static int omap_usb2_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 
-	phy->control_dev = devm_request_and_ioremap(&pdev->dev, res);
-	if (phy->control_dev == NULL) {
-		dev_err(&pdev->dev, "Failed to obtain io memory\n");
-		return -ENXIO;
+	phy->control_dev = omap_get_control_dev();
+	if (IS_ERR(phy->control_dev)) {
+		dev_dbg(&pdev->dev, "Failed to get control device\n");
+		return -ENODEV;
 	}
 
 	phy->is_suspended	= 1;
-	omap_usb_phy_power(phy, 0);
+	omap_control_usb_phy_power(phy->control_dev, 0);
 
 	otg->set_host		= omap_usb_set_host;
 	otg->set_peripheral	= omap_usb_set_peripheral;
diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
index 0ea17f8..3db9b53 100644
--- a/include/linux/usb/omap_usb.h
+++ b/include/linux/usb/omap_usb.h
@@ -25,13 +25,11 @@ struct omap_usb {
 	struct usb_phy		phy;
 	struct phy_companion	*comparator;
 	struct device		*dev;
-	u32 __iomem		*control_dev;
+	struct device		*control_dev;
 	struct clk		*wkupclk;
 	u8			is_suspended:1;
 };
 
-#define	PHY_PD	0x1
-
 #define	phy_to_omapusb(x)	container_of((x), struct omap_usb, phy)
 
 #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 3/4] ARM: OMAP2: MUSB: Specify omap4 has mailbox
From: Kishon Vijay Abraham I @ 2013-01-21 14:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358777308-2409-1-git-send-email-kishon@ti.com>

Added has_mailbox to the musb platform data to specify that omap uses
an external mailbox (in control module) to communicate with the musb
core during device connect and disconnect.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/usb-musb.c |    3 +++
 include/linux/usb/musb.h       |    2 ++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 7b33b37..9d27e3f 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -85,6 +85,9 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	musb_plat.mode = board_data->mode;
 	musb_plat.extvbus = board_data->extvbus;
 
+	if (cpu_is_omap44xx())
+		musb_plat.has_mailbox = true;
+
 	if (soc_is_am35xx()) {
 		oh_name = "am35x_otg_hs";
 		name = "musb-am35x";
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index eb50525..053c268 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -99,6 +99,8 @@ struct musb_hdrc_platform_data {
 	/* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
 	u8		mode;
 
+	u8		has_mailbox:1;
+
 	/* for clk_get() */
 	const char	*clock;
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 2/4] ARM: OMAP: devices: create device for usb part of control module
From: Kishon Vijay Abraham I @ 2013-01-21 14:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358777308-2409-1-git-send-email-kishon@ti.com>

A seperate driver has been added to handle the usb part of control
module. A device for the above driver is created here, using the register
address information to be used by the driver for powering on the PHY and
for writing to the mailbox.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/devices.c |   45 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5e304d0..edc5ec2 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -20,6 +20,7 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
 #include <linux/platform_data/omap_ocp2scp.h>
+#include <linux/usb/omap_control_usb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -254,6 +255,49 @@ static inline void omap_init_camera(void)
 #endif
 }
 
+#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
+static struct omap_control_usb_platform_data omap4_control_usb_pdata = {
+	.has_mailbox = true,
+};
+
+struct resource omap4_control_usb_res[] = {
+	{
+		.name	= "control_dev_conf",
+		.start	= 0x4a002300,
+		.end	= 0x4a002303,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "otghs_control",
+		.start	= 0x4a00233c,
+		.end	= 0x4a00233f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device omap4_control_usb = {
+	.name		= "omap-control-usb",
+	.id		= -1,
+	.dev = {
+		.platform_data = &omap4_control_usb_pdata,
+	},
+	.num_resources = 2,
+	.resource = omap4_control_usb_res,
+};
+
+static inline void __init omap_init_control_usb(void)
+{
+	if (!cpu_is_omap44xx())
+		return;
+
+	if (platform_device_register(&omap4_control_usb))
+		pr_err("Error registering omap_control_usb device\n");
+}
+
+#else
+static inline void omap_init_control_usb(void) { }
+#endif /* CONFIG_OMAP_CONTROL_USB */
+
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 			*sdp4430_keypad_data, struct omap_board_data *bdata)
 {
@@ -721,6 +765,7 @@ static int __init omap2_init_devices(void)
 	omap_init_mbox();
 	/* If dtb is there, the devices will be created dynamically */
 	if (!of_have_populated_dt()) {
+		omap_init_control_usb();
 		omap_init_dmic();
 		omap_init_mcpdm();
 		omap_init_mcspi();
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 1/4] drivers: usb: phy: add a new driver for usb part of control module
From: Kishon Vijay Abraham I @ 2013-01-21 14:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358777308-2409-1-git-send-email-kishon@ti.com>

Added a new driver for the usb part of control module. This has an API
to power on the USB2 phy and an API to write to the mailbox depending on
whether MUSB has to act in host mode or in device mode.

Writing to control module registers for doing the above task which was
previously done in omap glue and in omap-usb2 phy will be removed.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/devicetree/bindings/usb/omap-usb.txt |   26 ++-
 Documentation/devicetree/bindings/usb/usb-phy.txt  |    5 +
 drivers/usb/phy/Kconfig                            |    9 +
 drivers/usb/phy/Makefile                           |    1 +
 drivers/usb/phy/omap-control-usb.c                 |  238 ++++++++++++++++++++
 include/linux/usb/omap_control_usb.h               |   71 ++++++
 6 files changed, 349 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/phy/omap-control-usb.c
 create mode 100644 include/linux/usb/omap_control_usb.h

diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 29a043e..ead6ba9 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -1,4 +1,4 @@
-OMAP GLUE
+OMAP GLUE AND OTHER OMAP SPECIFIC COMPONENTS
 
 OMAP MUSB GLUE
  - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
@@ -16,6 +16,10 @@ OMAP MUSB GLUE
  - power : Should be "50". This signifies the controller can supply upto
    100mA when operating in host mode.
 
+Optional properties:
+ - ctrl_module : phandle of the control module this glue uses to write to
+   mailbox
+
 SOC specific device node entry
 usb_otg_hs: usb_otg_hs at 4a0ab000 {
 	compatible = "ti,omap4-musb";
@@ -23,6 +27,7 @@ usb_otg_hs: usb_otg_hs at 4a0ab000 {
 	multipoint = <1>;
 	num_eps = <16>;
 	ram_bits = <12>;
+	ctrl_module = <&omap_control_usb>;
 };
 
 Board specific device node entry
@@ -31,3 +36,22 @@ Board specific device node entry
 	mode = <3>;
 	power = <50>;
 };
+
+OMAP CONTROL USB
+
+Required properties:
+ - compatible: Should be "ti,omap-control-usb"
+ - reg : Address and length of the register set for the device. It contains
+   the address of "control_dev_conf" and "otghs_control".
+ - reg-names: The names of the register addresses corresponding to the registers
+   filled in "reg".
+ - ti,has_mailbox: This is used to specify if the platform has mailbox in
+   control module.
+
+omap_control_usb: omap-control-usb at 4a002300 {
+	compatible = "ti,omap-control-usb";
+	reg = <0x4a002300 0x4>,
+	      <0x4a00233c 0x4>;
+	reg-names = "control_dev_conf", "otghs_control";
+	ti,has_mailbox;
+};
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
index 80d4148..2466b6f 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -8,10 +8,15 @@ Required properties:
 add the address of control module dev conf register until a driver for
 control module is added
 
+Optional properties:
+ - ctrl_module : phandle of the control module used by PHY driver to power on
+   the PHY.
+
 This is usually a subnode of ocp2scp to which it is connected.
 
 usb2phy at 4a0ad080 {
 	compatible = "ti,omap-usb2";
 	reg = <0x4a0ad080 0x58>,
 	      <0x4a002300 0x4>;
+	ctrl_module = <&omap_control_usb>;
 };
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 36a85b6..20479e8 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -14,6 +14,15 @@ config OMAP_USB2
 	  The USB OTG controller communicates with the comparator using this
 	  driver.
 
+config OMAP_CONTROL_USB
+	tristate "OMAP CONTROL USB Driver"
+	depends on ARCH_OMAP2PLUS
+	help
+	  Enable this to add support for the USB part present in the control
+	  module. This driver has API to power on the PHY and to write to the
+	  mailbox. The mailbox is present only in omap4 and the register to
+	  power on the PHY is present in omap4 and omap5.
+
 config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
 	depends on USB || USB_GADGET
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index ec304f6..ee97767 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -5,6 +5,7 @@
 ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.o
+obj-$(CONFIG_OMAP_CONTROL_USB)		+= omap-control-usb.o
 obj-$(CONFIG_USB_ISP1301)		+= isp1301.o
 obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/omap-control-usb.c
new file mode 100644
index 0000000..e8fd85c
--- /dev/null
+++ b/drivers/usb/phy/omap-control-usb.c
@@ -0,0 +1,238 @@
+/*
+ * omap-control-usb.c - The USB part of control module.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * 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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/usb/omap_control_usb.h>
+
+static struct omap_control_usb *control_usb;
+
+/**
+ * omap_get_control_dev - returns the device pointer for this control device
+ *
+ * This API should be called to get the device pointer for this control
+ * module device. This device pointer should be used for called other
+ * exported API's in this driver.
+ *
+ * To be used by PHY driver and glue driver.
+ */
+struct device *omap_get_control_dev(void)
+{
+	if (!control_usb)
+		return ERR_PTR(-ENODEV);
+
+	return control_usb->dev;
+}
+EXPORT_SYMBOL_GPL(omap_get_control_dev);
+
+/**
+ * omap_control_usb_phy_power - power on/off the phy using control module reg
+ * @dev: the control module device
+ * @on: 0 or 1, based on powering on or off the PHY
+ */
+void omap_control_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	val = readl(control_usb->dev_conf);
+
+	if (on)
+		val &= ~OMAP_CTRL_DEV_PHY_PD;
+	else
+		val |= OMAP_CTRL_DEV_PHY_PD;
+
+	writel(val, control_usb->dev_conf);
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
+
+/**
+ * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
+ * @ctrl_usb: struct omap_control_usb *
+ *
+ * Writes to the mailbox register to notify the usb core that a usb
+ * device has been connected.
+ */
+static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb)
+{
+	u32 val;
+
+	val = readl(ctrl_usb->otghs_control);
+	val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
+	val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
+	writel(val, ctrl_usb->otghs_control);
+}
+
+/**
+ * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
+ * impedance
+ * @ctrl_usb: struct omap_control_usb *
+ *
+ * Writes to the mailbox register to notify the usb core that it has been
+ * connected to a usb host.
+ */
+static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb)
+{
+	u32 val;
+
+	val = readl(ctrl_usb->otghs_control);
+	val &= ~OMAP_CTRL_DEV_SESSEND;
+	val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
+		OMAP_CTRL_DEV_VBUSVALID;
+	writel(val, ctrl_usb->otghs_control);
+}
+
+/**
+ * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
+ * impedance
+ * @ctrl_usb: struct omap_control_usb *
+ *
+ * Writes to the mailbox register to notify the usb core it's now in
+ * disconnected state.
+ */
+static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb)
+{
+	u32 val;
+
+	val = readl(ctrl_usb->otghs_control);
+	val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
+	val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
+	writel(val, ctrl_usb->otghs_control);
+}
+
+/**
+ * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
+ * or device mode or to denote disconnected state
+ * @dev: the control module device
+ * @mode: The mode to which usb should be configured
+ *
+ * This is an API to write to the mailbox register to notify the usb core that
+ * a usb device has been connected.
+ */
+void omap_control_usb_set_mode(struct device *dev,
+	enum omap_control_usb_mode mode)
+{
+	struct omap_control_usb	*ctrl_usb;
+
+	if (IS_ERR(dev))
+		return;
+
+	ctrl_usb = dev_get_drvdata(dev);
+
+	switch (mode) {
+	case USB_MODE_HOST:
+		omap_control_usb_host_mode(ctrl_usb);
+		break;
+	case USB_MODE_DEVICE:
+		omap_control_usb_device_mode(ctrl_usb);
+		break;
+	case USB_MODE_DISCONNECT:
+		omap_control_usb_set_sessionend(ctrl_usb);
+		break;
+	default:
+		dev_vdbg(dev, "invalid omap control usb mode\n");
+	}
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
+
+static int omap_control_usb_probe(struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct device_node *np = pdev->dev.of_node;
+	struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
+
+	control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
+		GFP_KERNEL);
+	if (!control_usb) {
+		dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+		return -ENOMEM;
+	}
+
+	if (np) {
+		control_usb->has_mailbox = of_property_read_bool(np,
+			"ti,has_mailbox");
+	} else if (pdata) {
+		control_usb->has_mailbox = pdata->has_mailbox;
+	} else {
+		dev_err(&pdev->dev, "no pdata present\n");
+		return -EINVAL;
+	}
+
+	control_usb->dev	= &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+		"control_dev_conf");
+	control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
+	if (control_usb->dev_conf == NULL) {
+		dev_err(&pdev->dev, "Failed to obtain io memory\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	if (control_usb->has_mailbox) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"otghs_control");
+		control_usb->otghs_control = devm_request_and_ioremap(
+			&pdev->dev, res);
+		if (control_usb->otghs_control == NULL) {
+			dev_err(&pdev->dev, "Failed to obtain io memory\n");
+			return -EADDRNOTAVAIL;
+		}
+	}
+
+	dev_set_drvdata(control_usb->dev, control_usb);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_control_usb_id_table[] = {
+	{ .compatible = "ti,omap-control-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+#endif
+
+static struct platform_driver omap_control_usb_driver = {
+	.probe		= omap_control_usb_probe,
+	.driver		= {
+		.name	= "omap-control-usb",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_control_usb_id_table),
+	},
+};
+
+static int __init omap_control_usb_init(void)
+{
+	return platform_driver_register(&omap_control_usb_driver);
+}
+subsys_initcall(omap_control_usb_init);
+
+static void __exit omap_control_usb_exit(void)
+{
+	platform_driver_unregister(&omap_control_usb_driver);
+}
+module_exit(omap_control_usb_exit);
+
+MODULE_ALIAS("platform: omap_control_usb");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP Control Module USB Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/usb/omap_control_usb.h
new file mode 100644
index 0000000..941a43b
--- /dev/null
+++ b/include/linux/usb/omap_control_usb.h
@@ -0,0 +1,71 @@
+/*
+ * omap_control_usb.h - Header file for the USB part of control module.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * 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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __OMAP_CONTROL_USB_H__
+#define __OMAP_CONTROL_USB_H__
+
+struct omap_control_usb {
+	struct device *dev;
+
+	u32 __iomem *dev_conf;
+	u32 __iomem *otghs_control;
+
+	u8 has_mailbox:1;
+};
+
+struct omap_control_usb_platform_data {
+	u8 has_mailbox:1;
+};
+
+enum omap_control_usb_mode {
+	USB_MODE_UNDEFINED = 0,
+	USB_MODE_HOST,
+	USB_MODE_DEVICE,
+	USB_MODE_DISCONNECT,
+};
+
+#define	OMAP_CTRL_DEV_PHY_PD		BIT(0)
+
+#define	OMAP_CTRL_DEV_AVALID		BIT(0)
+#define	OMAP_CTRL_DEV_BVALID		BIT(1)
+#define	OMAP_CTRL_DEV_VBUSVALID		BIT(2)
+#define	OMAP_CTRL_DEV_SESSEND		BIT(3)
+#define	OMAP_CTRL_DEV_IDDIG		BIT(4)
+
+#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
+extern struct device *omap_get_control_dev(void);
+extern void omap_control_usb_phy_power(struct device *dev, int on);
+extern void omap_control_usb_set_mode(struct device *dev,
+	enum omap_control_usb_mode mode);
+#else
+static inline struct device *omap_get_control_dev()
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline void omap_control_usb_phy_power(struct device *dev, int on)
+{
+}
+
+static inline void omap_control_usb_set_mode(struct device *dev,
+	enum omap_control_usb_mode mode)
+{
+}
+#endif
+
+#endif	/* __OMAP_CONTROL_USB_H__ */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 0/4] usb: musb: add driver for control module
From: Kishon Vijay Abraham I @ 2013-01-21 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

Added a new driver for the usb part of control module. This has an API
to power on the USB2 phy and an API to write to the mailbox depending on
whether MUSB has to act in host mode or in device mode.

Writing to control module registers for doing the above task which was
previously done in omap glue and in omap-usb2 phy is removed.

Changes from v1:
* renamed get_omap_control_dev to omap_get_control_dev

* created and exported a single API (omap_control_usb_set_mode) to change
  the usb mode

* Before writing to the otghs_control regster, the value from
  otghs_control regster is read and only the appropriate bits are set.

* In omap_init_control_usb, the indentation is now reduced as per Felipe's
  suggestion.

Changes from RFC:
* Used "#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)" instead of 
  "#if (defined(CONFIG_OMAP_CONTROL_USB) || \
				defined(CONFIG_OMAP_CONTROL_USB_MODULE))"

* return "-EADDRNOTAVAIL" if devm_request_and_ioremap fails.

* Removed the dt data from this patch series (I'll send that as a separate
series).

* added "ctrl_module" binding to usb otg glue and usb phy in the Documentaion.
  This binding is not planned to be used until an actual requirement for
  it arises.

This series was developed on
git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git xceiv

Did basic enumeration testing in omap4 panda and omap3 beagle.

Kishon Vijay Abraham I (4):
  drivers: usb: phy: add a new driver for usb part of control module
  ARM: OMAP: devices: create device for usb part of control module
  ARM: OMAP2: MUSB: Specify omap4 has mailbox
  drivers: usb: start using the control module driver

 Documentation/devicetree/bindings/usb/omap-usb.txt |   30 ++-
 Documentation/devicetree/bindings/usb/usb-phy.txt  |   12 +-
 arch/arm/mach-omap2/devices.c                      |   45 ++++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |   13 --
 arch/arm/mach-omap2/usb-musb.c                     |    3 +
 drivers/usb/musb/Kconfig                           |    1 +
 drivers/usb/musb/omap2430.c                        |   64 ++----
 drivers/usb/musb/omap2430.h                        |    9 -
 drivers/usb/phy/Kconfig                            |   10 +
 drivers/usb/phy/Makefile                           |    1 +
 drivers/usb/phy/omap-control-usb.c                 |  238 ++++++++++++++++++++
 drivers/usb/phy/omap-usb2.c                        |   38 +---
 include/linux/usb/musb.h                           |    2 +
 include/linux/usb/omap_control_usb.h               |   71 ++++++
 include/linux/usb/omap_usb.h                       |    4 +-
 15 files changed, 439 insertions(+), 102 deletions(-)
 create mode 100644 drivers/usb/phy/omap-control-usb.c
 create mode 100644 include/linux/usb/omap_control_usb.h

-- 
1.7.9.5

^ permalink raw reply

* [PATCH 1/8] mmc: mmci: Move ios_handler functionality into the driver
From: Lee Jones @ 2013-01-21 14:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1355404930-5691-2-git-send-email-lee.jones@linaro.org>

On Thu, 13 Dec 2012, Lee Jones wrote:

> There are currently two instances of the ios_handler being used.
> Both of which mearly toy with some regulator settings. Now there
> is a GPIO regulator API, we can use that instead, and lessen the
> per platform burden. By doing this, we also become more Device
> Tree compatible.
> 
> Cc: Chris Ball <cjb@laptop.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Acked-by: Ulf Hansson <ulf.hansson@stericsson.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>

Any more news on this one?

>  drivers/mmc/host/mmci.c |   22 ++++++++++++++++++++++
>  drivers/mmc/host/mmci.h |    1 +
>  2 files changed, 23 insertions(+)
> 
> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> index edc3e9b..d45c931 100644
> --- a/drivers/mmc/host/mmci.c
> +++ b/drivers/mmc/host/mmci.c
> @@ -1091,6 +1091,16 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	case MMC_POWER_OFF:
>  		if (host->vcc)
>  			ret = mmc_regulator_set_ocr(mmc, host->vcc, 0);
> +
> +		if (host->vqmmc) {
> +			if (regulator_is_enabled(host->vqmmc)) {
> +				ret = regulator_disable(host->vqmmc);
> +				if (ret < 0)
> +					dev_warn(mmc_dev(mmc),
> +						 "unable to disable vmmc-ios\n");
> +			}
> +		}
> +
>  		break;
>  	case MMC_POWER_UP:
>  		if (host->vcc) {
> @@ -1115,6 +1125,14 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  
>  		break;
>  	case MMC_POWER_ON:
> +		if (host->vqmmc)
> +			if (!regulator_is_enabled(host->vqmmc)) {
> +				ret = regulator_enable(host->vqmmc);
> +				if (ret < 0)
> +					dev_warn(mmc_dev(mmc),
> +						 "unable to enable vmmc-ios\n");
> +			}
> +
>  		pwr |= MCI_PWR_ON;
>  		break;
>  	}
> @@ -1379,6 +1397,10 @@ static int __devinit mmci_probe(struct amba_device *dev,
>  				 "(using regulator instead)\n");
>  		}
>  	}
> +
> +	host->vqmmc = regulator_get(&dev->dev, "vqmmc");
> +	if (IS_ERR(host->vqmmc))
> +		host->vqmmc = NULL;
>  #endif
>  	/* Fall back to platform data if no regulator is found */
>  	if (host->vcc == NULL)
> diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
> index d437ccf..b87d9e2 100644
> --- a/drivers/mmc/host/mmci.h
> +++ b/drivers/mmc/host/mmci.h
> @@ -194,6 +194,7 @@ struct mmci_host {
>  	struct sg_mapping_iter	sg_miter;
>  	unsigned int		size;
>  	struct regulator	*vcc;
> +	struct regulator	*vqmmc;
>  
>  #ifdef CONFIG_DMA_ENGINE
>  	/* DMA stuff */

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH 1/4] ARM: cache-l2x0: Manage the errata at run time
From: Will Deacon @ 2013-01-21 14:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130121131451.GA29855@bnru10>

On Mon, Jan 21, 2013 at 01:14:53PM +0000, srinidhi kasagar wrote:
> Make it possible to manage the errata by its own by using the
> l2x0 ID register. This relieves the platforms from choosing the
> Errata's at compile time
> 
> Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
> ---
>  arch/arm/include/asm/hardware/cache-l2x0.h |    2 +
>  arch/arm/mm/cache-l2x0.c                   |   77 +++++++++++++++-------------
>  2 files changed, 43 insertions(+), 36 deletions(-)
> 
> diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
> index 3b2c40b..d5994ac 100644
> --- a/arch/arm/include/asm/hardware/cache-l2x0.h
> +++ b/arch/arm/include/asm/hardware/cache-l2x0.h
> @@ -117,6 +117,8 @@ static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)
>  }
>  #endif
>  
> +asmlinkage u32 l2x0_get_rtl_release(void);
> +
>  struct l2x0_regs {
>  	unsigned long phy_base;
>  	unsigned long aux_ctrl;
> diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
> index c2f3739..49058ac 100644
> --- a/arch/arm/mm/cache-l2x0.c
> +++ b/arch/arm/mm/cache-l2x0.c
> @@ -49,6 +49,16 @@ struct l2x0_of_data {
>  
>  static bool of_init = false;
>  
> +/*
> + * Identify ther RTL releases of l2x0 - This might help in applying
> + * the l2x0 errata's dynamically rather compile time options
> + */
> +asmlinkage u32 l2x0_get_rtl_release(void)
> +{
> +	return readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
> +			L2X0_CACHE_ID_RTL_MASK;
> +}

You're calling this function all over the place, including from the flush
code. Can you read the RTL release during probe and stash it somewhere
instead please?

Will

^ permalink raw reply

* [PATCH 1/1] ARM: ux500: Disable Power Supply and Battery Management by default
From: Lee Jones @ 2013-01-21 14:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYydqJ+BVsh7P411zCod+83f2pVV5tPsKfoWPYUnOVpDQ@mail.gmail.com>

> > The AB8500 Battery Management collection of drivers are more than a
> > little bit broken. There is lots of work still on-going in that area
> > and it's improving day by day; however, it's not ready to be enabled
> > by default just yet.
> >
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> 
> Is this going for fixes (v3.8?)
> 
> For v3.9 I think you've submitted a whole lot of patches
> actually fixing it up?

I did submit a bunch of fixes, but more are required.

> Anyway: Acked-by: Linus Walleij <linus.walleij@linaro.org>
> since you certainly know the status of this driver better than
> me.

Thanks.

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH] ARM: plat-samsung: using vsnprintf instead of vsprintf for the limit buffer length 256
From: Ben Dooks @ 2013-01-21 13:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50FD178E.9090105@asianux.com>

On Mon, Jan 21, 2013 at 06:25:18PM +0800, Chen Gang wrote:
> 
>   the buff size is 256, so need use vsnprintf instead of vsprintf.
> 
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> ---
>  arch/arm/plat-samsung/pm.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
> index 1507028..8d07b45 100644
> --- a/arch/arm/plat-samsung/pm.c
> +++ b/arch/arm/plat-samsung/pm.c
> @@ -51,7 +51,7 @@ void s3c_pm_dbg(const char *fmt, ...)
>  	char buff[256];
>  
>  	va_start(va, fmt);
> -	vsprintf(buff, fmt, va);
> +	vsnprintf(buff, 256, fmt, va);

How about: vsnprintf(buff, sizeof(buff), fmt, va);

It means we do not end up assuming the size of 'buff' and will be correct
if the code is changed to declare 'buff' to be a different size.

-- 
Ben Dooks, ben at fluff.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.

^ permalink raw reply

* [PATCH v6 14/15] KVM: ARM: Power State Coordination Interface implementation
From: Gleb Natapov @ 2013-01-21 13:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANM98q+z2tj72qFtjDF1ZpKMGs876=hRLpKTEwYKnpCMzdpErg@mail.gmail.com>

On Sun, Jan 20, 2013 at 06:35:51PM -0500, Christoffer Dall wrote:
> On Thu, Jan 17, 2013 at 10:55 AM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> > On 16/01/13 17:59, Christoffer Dall wrote:
> >> From: Marc Zyngier <marc.zyngier@arm.com>
> >>
> >> Implement the PSCI specification (ARM DEN 0022A) to control
> >> virtual CPUs being "powered" on or off.
> >>
> >> PSCI/KVM is detected using the KVM_CAP_ARM_PSCI capability.
> >>
> >> A virtual CPU can now be initialized in a "powered off" state,
> >> using the KVM_ARM_VCPU_POWER_OFF feature flag.
> >>
> >> The guest can use either SMC or HVC to execute a PSCI function.
> >>
> >> Reviewed-by: Will Deacon <will.deacon@arm.com>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
> >
> > A few bits went wrong when you reworked this patch. See below.
> >
> >> ---
> >>  Documentation/virtual/kvm/api.txt  |    4 +
> >>  arch/arm/include/asm/kvm_emulate.h |    5 ++
> >>  arch/arm/include/asm/kvm_host.h    |    5 +-
> >>  arch/arm/include/asm/kvm_psci.h    |   23 ++++++++
> >>  arch/arm/include/uapi/asm/kvm.h    |   16 +++++
> >>  arch/arm/kvm/Makefile              |    2 -
> >>  arch/arm/kvm/arm.c                 |   28 +++++++++-
> >>  arch/arm/kvm/psci.c                |  105 ++++++++++++++++++++++++++++++++++++
> >>  include/uapi/linux/kvm.h           |    1
> >>  9 files changed, 184 insertions(+), 5 deletions(-)
> >>  create mode 100644 arch/arm/include/asm/kvm_psci.h
> >>  create mode 100644 arch/arm/kvm/psci.c
> >>
> >> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >> index 38066a7a..c25439a 100644
> >> --- a/Documentation/virtual/kvm/api.txt
> >> +++ b/Documentation/virtual/kvm/api.txt
> >> @@ -2185,6 +2185,10 @@ return ENOEXEC for that vcpu.
> >>  Note that because some registers reflect machine topology, all vcpus
> >>  should be created before this ioctl is invoked.
> >>
> >> +Possible features:
> >> +     - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
> >> +       Depends on KVM_CAP_ARM_PSCI.
> >> +
> >>
> >>  4.78 KVM_GET_REG_LIST
> >>
> >> diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
> >> index 4c1a073..ba07de9 100644
> >> --- a/arch/arm/include/asm/kvm_emulate.h
> >> +++ b/arch/arm/include/asm/kvm_emulate.h
> >> @@ -32,6 +32,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu);
> >>  void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
> >>  void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
> >>
> >> +static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
> >> +{
> >> +     return 1;
> >> +}
> >> +
> >>  static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
> >>  {
> >>       return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
> >> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >> index e65fc96..c9ba918 100644
> >> --- a/arch/arm/include/asm/kvm_host.h
> >> +++ b/arch/arm/include/asm/kvm_host.h
> >> @@ -30,7 +30,7 @@
> >>  #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
> >>  #define KVM_HAVE_ONE_REG
> >>
> >> -#define KVM_VCPU_MAX_FEATURES 0
> >> +#define KVM_VCPU_MAX_FEATURES 1
> >>
> >>  /* We don't currently support large pages. */
> >>  #define KVM_HPAGE_GFN_SHIFT(x)       0
> >> @@ -100,6 +100,9 @@ struct kvm_vcpu_arch {
> >>       int last_pcpu;
> >>       cpumask_t require_dcache_flush;
> >>
> >> +     /* Don't run the guest: see copy_current_insn() */
> >
> > Now that you made this field PSCI-specific, how about rewording the comment?
> >
> 
> yeah, that would work. And actually it's kind of broken, because if we
> sent a paused VCPU a signal and that VCPU is never woken up using the
> PSCI call we'll busy spin in the kernel, which is sad :(
> 
> This should eventually be moved to the vcpu requests infrastructure,
> but I'll send some preparatory patches to the kvm first, so let's fix
> it in the right way later on (requires reworking the run loop quite a
> bit), and for now simply fix the pause clause, see patch below.
> 
> >> +     bool pause;
> >> +
> >>       /* IO related fields */
> >>       struct kvm_decode mmio_decode;
> >>
> >> diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
> >> new file mode 100644
> >> index 0000000..9a83d98
> >> --- /dev/null
> >> +++ b/arch/arm/include/asm/kvm_psci.h
> >> @@ -0,0 +1,23 @@
> >> +/*
> >> + * Copyright (C) 2012 - ARM Ltd
> >> + * Author: Marc Zyngier <marc.zyngier@arm.com>
> >> + *
> >> + * 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.
> >> + *
> >> + * 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.
> >> + *
> >> + * You should have received a copy of the GNU General Public License
> >> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >> + */
> >> +
> >> +#ifndef __ARM_KVM_PSCI_H__
> >> +#define __ARM_KVM_PSCI_H__
> >> +
> >> +bool kvm_psci_call(struct kvm_vcpu *vcpu);
> >> +
> >> +#endif /* __ARM_KVM_PSCI_H__ */
> >> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> >> index bbb6b23..3303ff5 100644
> >> --- a/arch/arm/include/uapi/asm/kvm.h
> >> +++ b/arch/arm/include/uapi/asm/kvm.h
> >> @@ -65,6 +65,8 @@ struct kvm_regs {
> >>  #define KVM_ARM_TARGET_CORTEX_A15    0
> >>  #define KVM_ARM_NUM_TARGETS          1
> >>
> >> +#define KVM_ARM_VCPU_POWER_OFF               0 /* CPU is started in OFF state */
> >> +
> >>  struct kvm_vcpu_init {
> >>       __u32 target;
> >>       __u32 features[7];
> >> @@ -145,4 +147,18 @@ struct kvm_arch_memory_slot {
> >>  /* Highest supported SPI, from VGIC_NR_IRQS */
> >>  #define KVM_ARM_IRQ_GIC_MAX          127
> >>
> >> +/* PSCI interface */
> >> +#define KVM_PSCI_FN_BASE             0x95c1ba5e
> >> +#define KVM_PSCI_FN(n)                       (KVM_PSCI_FN_BASE + (n))
> >> +
> >> +#define KVM_PSCI_FN_CPU_SUSPEND              KVM_PSCI_FN(0)
> >> +#define KVM_PSCI_FN_CPU_OFF          KVM_PSCI_FN(1)
> >> +#define KVM_PSCI_FN_CPU_ON           KVM_PSCI_FN(2)
> >> +#define KVM_PSCI_FN_MIGRATE          KVM_PSCI_FN(3)
> >> +
> >> +#define KVM_PSCI_RET_SUCCESS         0
> >> +#define KVM_PSCI_RET_NI                      ((unsigned long)-1)
> >> +#define KVM_PSCI_RET_INVAL           ((unsigned long)-2)
> >> +#define KVM_PSCI_RET_DENIED          ((unsigned long)-3)
> >> +
> >>  #endif /* __ARM_KVM_H__ */
> >> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> >> index 1e45cd9..ea27987 100644
> >> --- a/arch/arm/kvm/Makefile
> >> +++ b/arch/arm/kvm/Makefile
> >> @@ -18,4 +18,4 @@ kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
> >>
> >>  obj-y += kvm-arm.o init.o interrupts.o
> >>  obj-y += arm.o guest.o mmu.o emulate.o reset.o
> >> -obj-y += coproc.o coproc_a15.o mmio.o
> >> +obj-y += coproc.o coproc_a15.o mmio.o psci.o
> >> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> >> index 3168b9d..6ff5337 100644
> >> --- a/arch/arm/kvm/arm.c
> >> +++ b/arch/arm/kvm/arm.c
> >> @@ -43,6 +43,7 @@
> >>  #include <asm/kvm_mmu.h>
> >>  #include <asm/kvm_emulate.h>
> >>  #include <asm/kvm_coproc.h>
> >> +#include <asm/kvm_psci.h>
> >>  #include <asm/opcodes.h>
> >>
> >>  #ifdef REQUIRES_VIRT
> >> @@ -160,6 +161,7 @@ int kvm_dev_ioctl_check_extension(long ext)
> >>       case KVM_CAP_SYNC_MMU:
> >>       case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
> >>       case KVM_CAP_ONE_REG:
> >> +     case KVM_CAP_ARM_PSCI:
> >>               r = 1;
> >>               break;
> >>       case KVM_CAP_COALESCED_MMIO:
> >> @@ -443,13 +445,17 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
> >>       trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
> >>                     vcpu->arch.hsr & HSR_HVC_IMM_MASK);
> >>
> >> +     if (kvm_psci_call(vcpu))
> >> +             return 1;
> >> +
> >>       return 1;
> >
> > No undef injection if there is no PSCI match?
> >
> >>  }
> >>
> >>  static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
> >>  {
> >> -     /* We don't support SMC; don't do that. */
> >> -     kvm_debug("smc: at %08x", *vcpu_pc(vcpu));
> >> +     if (!kvm_psci_call(vcpu))
> >
> > Looks like you got the return value backward here.
> >
> 
> yeah, I missed that call completely.
> 
> >> +             return 1;
> >> +
> >>       kvm_inject_undefined(vcpu);
> >>       return 1;
> >>  }
> >
> Thanks, see this patch:
> 
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index 751aa86..d1736a5 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -113,7 +113,7 @@ struct kvm_vcpu_arch {
>  	int last_pcpu;
>  	cpumask_t require_dcache_flush;
> 
> -	/* Don't run the guest: see copy_current_insn() */
> +	/* Don't run the guest on this vcpu */
>  	bool pause;
> 
>  	/* IO related fields */
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index a67392a..2819575 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -502,7 +502,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu,
> struct kvm_run *run)
> 
>  static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  {
> -	if (!kvm_psci_call(vcpu))
> +	if (kvm_psci_call(vcpu))
>  		return 1;
> 
>  	kvm_inject_undefined(vcpu);
> @@ -667,6 +667,13 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
> 
> +static void vcpu_pause(struct kvm_vcpu *vcpu)
> +{
> +	wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
> +
> +	wait_event_interruptible(*wq, !vcpu->arch.pause);
> +}
> +
>  /**
>   * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
>   * @vcpu:	The VCPU pointer
> @@ -710,6 +717,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu,
> struct kvm_run *run)
> 
>  		update_vttbr(vcpu->kvm);
> 
> +		if (vcpu->arch.pause)
> +			vcpu_pause(vcpu);
> +
If you check vcpu->arch.pause in kvm_arch_vcpu_runnable() you can use
kvm_vcpu_block() here.

>  		kvm_vgic_flush_hwstate(vcpu);
>  		kvm_timer_flush_hwstate(vcpu);
> 
> @@ -737,13 +747,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu
> *vcpu, struct kvm_run *run)
>  		kvm_guest_enter();
>  		vcpu->mode = IN_GUEST_MODE;
> 
> -		smp_mb(); /* set mode before reading vcpu->arch.pause */
> -		if (unlikely(vcpu->arch.pause)) {
> -			/* This means ignore, try again. */
> -			ret = ARM_EXCEPTION_IRQ;
> -		} else {
> -			ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
> -		}
> +		ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
> 
>  		vcpu->mode = OUTSIDE_GUEST_MODE;
>  		vcpu->arch.last_pcpu = smp_processor_id();
> diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
> index 6be3687..d833604 100644
> --- a/arch/arm/kvm/psci.c
> +++ b/arch/arm/kvm/psci.c
> @@ -28,11 +28,7 @@
> 
>  static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
>  {
> -	wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
> -
>  	vcpu->arch.pause = true;
> -
> -	wait_event_interruptible(*wq, !vcpu->arch.pause);
>  }
> 
>  static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
> -- 
> 1.7.9.5
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
			Gleb.

^ permalink raw reply

* [PATCH 1/1] ARM: ux500: Disable Power Supply and Battery Management by default
From: Linus Walleij @ 2013-01-21 13:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358175470-5041-1-git-send-email-lee.jones@linaro.org>

On Mon, Jan 14, 2013 at 3:57 PM, Lee Jones <lee.jones@linaro.org> wrote:

> The AB8500 Battery Management collection of drivers are more than a
> little bit broken. There is lots of work still on-going in that area
> and it's improving day by day; however, it's not ready to be enabled
> by default just yet.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>

Is this going for fixes (v3.8?)

For v3.9 I think you've submitted a whole lot of patches
actually fixing it up?

Anyway: Acked-by: Linus Walleij <linus.walleij@linaro.org>
since you certainly know the status of this driver better than
me.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v4 3/7] ARM: Exynos: add device tree support for MCT controller driver
From: Mark Rutland @ 2013-01-21 13:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-4-git-send-email-thomas.abraham@linaro.org>

On Mon, Jan 21, 2013 at 10:02:18AM +0000, Thomas Abraham wrote:
> Allow the MCT controller base address and interrupts to be obtained from
> device tree and remove unused static definitions of these. The non-dt support
> for Exynos5250 is removed but retained for Exynos4210 based platforms.
> 
> Cc: Changhwan Youn <chaos.youn@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  .../bindings/timer/samsung,exynos4210-mct.txt      |   68 ++++++++++++++++++++
>  arch/arm/mach-exynos/include/mach/irqs.h           |    6 --
>  arch/arm/mach-exynos/mct.c                         |   49 +++++++++++----
>  3 files changed, 105 insertions(+), 18 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
> 
> diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
> new file mode 100644
> index 0000000..cb47bfb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
> @@ -0,0 +1,68 @@
> +Samsung's Multi Core Timer (MCT)
> +
> +The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
> +global timer and CPU local timers. The global timer is a 64-bit free running
> +up-counter and can generate 4 interrupts when the counter reaches one of the
> +four preset counter values. The CPU local timers are 32-bit free running
> +down-counters and generate an interrupt when the counter expires. There is
> +one CPU local timer instantiated in MCT for every CPU in the system.
> +
> +Required properties:
> +
> +- compatible: should be "samsung,exynos4210-mct".
> +  (a) "samsung,exynos4210-mct", for mct compatible with Exynos4210 mct.
> +  (b) "samsung,exynos4412-mct", for mct compatible with Exynos4412 mct.
> +
> +- reg: base address of the mct controller and length of the address space
> +  it occupies.
> +
> +- interrupts: the list of interrupts generated by the controller. The following
> +  should be the order of the interrupts specified. The local timer interrupts
> +  should be specified after the four global timer interrupts have been
> +  specified.
> +
> +	0: Global Timer Interrupt 0
> +	1: Global Timer Interrupt 1
> +	2: Global Timer Interrupt 2
> +	3: Global Timer Interrupt 3
> +	4: Local Timer Interrupt 0
> +	5: Local Timer Interrupt 1
> +	6: ..
> +	7: ..
> +	i: Local Timer Interrupt n
> +
> +Example 1: In this example, the system uses only the first global timer
> +	   interrupt generated by MCT and the remaining three global timer
> +	   interrupts are unused. Two local timer interrupts have been
> +	   specified.
> +
> +	mct at 10050000 {
> +		compatible = "samsung,exynos4210-mct";
> +		reg = <0x10050000 0x800>;
> +		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
> +			     <0 42 0>, <0 48 0>;

Rather than padding the interrupts list with nonexistent interrupts, could you
not use something like a #global-interrupts property?

That way you don't have to list fake interrupts, you know exactly how many
global interrupts to expect (so you can sanity-check the list without any
special knowledge of the interrupt controller), and it's easier to support
future revisions which could have more interrupts, in a backwards-compatible
fashion.

> +	};
> +
> +Example 2: In this example, the MCT global and local timer interrupts are
> +	   connected to two seperate interrupt controllers. Hence, an
> +	   interrupt-map is created to map the interrupts to the respective
> +	   interrupt controllers.
> +
> +	mct at 101C0000 {
> +		compatible = "samsung,exynos4210-mct";
> +		reg = <0x101C0000 0x800>;
> +		interrupt-controller;
> +		#interrups-cells = <2>;
> +		interrupt-parent = <&mct_map>;
> +		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
> +			     <4 0>, <5 0>;
> +
> +		mct_map: mct-map {
> +			#interrupt-cells = <2>;
> +			#address-cells = <0>;
> +			#size-cells = <0>;
> +			interrupt-map = <0x0 0 &combiner 23 3>,
> +					<0x4 0 &gic 0 120 0>,
> +					<0x5 0 &gic 0 121 0>;
> +		};
> +	};


[...]

Thanks,
Mark.

^ permalink raw reply

* [RFC PATCH 6/6] USB: MUSB: OMAP: get PHY by phandle for dt boot
From: kishon @ 2013-01-21 13:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50FD4034.5040402@ti.com>

Hi,

On Monday 21 January 2013 06:48 PM, Roger Quadros wrote:
> On 01/16/2013 05:01 PM, Kishon Vijay Abraham I wrote:
>> The OMAP glue has been modified to get PHY by phandle for dt boot.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> ---
>>   drivers/usb/musb/omap2430.c |    7 ++++++-
>>   1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
>> index 3628a50..08709cf 100644
>> --- a/drivers/usb/musb/omap2430.c
>> +++ b/drivers/usb/musb/omap2430.c
>> @@ -346,7 +346,12 @@ static int omap2430_musb_init(struct musb *musb)
>>   	 * up through ULPI.  TWL4030-family PMICs include one,
>>   	 * which needs a driver, drivers aren't always needed.
>>   	 */
>> -	musb->xceiv = devm_usb_get_phy(dev, 0);
>> +	if (dev->parent->of_node)
>> +		musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
>> +		    "usb_phy", 0);
>
> Why dev->parent and not just dev?

Right now MUSB core is not converted to dt and hence we don't have 
separate dt node for MUSB core.
So the PHY information is added to the glue dt data.

Thanks
Kishon

^ permalink raw reply

* IMX not ready for multiplatform?
From: Russell King - ARM Linux @ 2013-01-21 13:38 UTC (permalink / raw)
  To: linux-arm-kernel

drivers/usb/gadget/imx_udc.c:39:27: fatal error: mach/hardware.h: No such file or directory
drivers/usb/gadget/fsl_mxc_udc.c:21:27: fatal error: mach/hardware.h: No such file or directory

is rather suggestive in my OMAP4 randconfig build.

Might like to have this fixed before the next merge window, so we don't
cause regressions.

^ permalink raw reply

* [PATCH 1/1] ARM: ux500: Turn on the 'heartbeat' LED trigger
From: Lee Jones @ 2013-01-21 13:35 UTC (permalink / raw)
  To: linux-arm-kernel

The heartbeat LED trigger provides an excellent debugging tool
when hacking on development boards. Here we enable it on all
u8500 based platforms. This will pulse the User LED on the
Snowball low-cost development board only.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/configs/u8500_defconfig |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 029961d..16368ef 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -91,6 +91,8 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_LM3530=y
 CONFIG_LEDS_LP5521=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AB8500=y
 CONFIG_RTC_DRV_PL031=y
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/1] ARM: ux500: Enable Snowball's GPIO controlled Ethernet regulator in DT
From: Lee Jones @ 2013-01-21 13:35 UTC (permalink / raw)
  To: linux-arm-kernel

The Snowball Board's Ethernet chip is configured in a slightly
non-standard way. Its SoC has an address space usually reserved
for a NOR-flash device. However, on the Snowball, that external
bus is populated by the SMSC9115 Ethernet chip. So, to power on
the Ethernet chip, we have to enable the GPIO controlled
regulator which usually controls the NOR-flash. In this patch
we inform the Snowball's Device Tree which GPIO is used to
operate it.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/boot/dts/snowball.dts |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index 27f31a5..4733a96 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -134,6 +134,7 @@
 				reg = <0 0x10000>;
 				interrupts = <12 0x1>;
 				interrupt-parent = <&gpio4>;
+
 				vdd33a-supply = <&en_3v3_reg>;
 				vddvario-supply = <&db8500_vape_reg>;
 
@@ -153,6 +154,7 @@
 			bus-width = <4>;
 			mmc-cap-mmc-highspeed;
 			vmmc-supply = <&ab8500_ldo_aux3_reg>;
+			vqmmc-supply = <&vmmci>;
 
 			cd-gpios  = <&gpio6 26 0x4>; // 218
 			cd-inverted;
@@ -346,5 +348,12 @@
 				};
 			};
 		};
+
+		vmmci: regulator-gpio {
+			gpios = <&gpio7 4 0x4>;        // 228
+			enable-gpio = <&gpio6 25 0x4>; // 217
+
+			status = "okay";
+		};
 	};
 };
-- 
1.7.9.5

^ permalink raw reply related

* [RFC PATCH 5/6] usb: otg: add device tree support to otg library
From: kishon @ 2013-01-21 13:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50FD40D1.8020405@ti.com>

On Monday 21 January 2013 06:51 PM, Roger Quadros wrote:
> On 01/16/2013 05:01 PM, Kishon Vijay Abraham I wrote:
>> Added an API devm_usb_get_phy_by_phandle(), to get usb phy by passing a
>> device node phandle value. This function will return a pointer to
>> the phy on success, -EPROBE_DEFER if there is a device_node for the phandle,
>> but the phy has not been added, or a ERR_PTR() otherwise.
>>
>> Cc: Marc Kleine-Budde <mkl@pengutronix.de>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> ---
>>   drivers/usb/otg/otg.c   |   77 +++++++++++++++++++++++++++++++++++++++++++++++
>>   include/linux/usb/phy.h |    8 +++++
>>   2 files changed, 85 insertions(+)
>>
>> diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
>> index dbf2043..e9799bb 100644
>> --- a/drivers/usb/otg/otg.c
>> +++ b/drivers/usb/otg/otg.c
>> @@ -13,7 +13,9 @@
>>   #include <linux/export.h>
>>   #include <linux/err.h>
>>   #include <linux/device.h>
>> +#include <linux/module.h>
>>   #include <linux/slab.h>
>> +#include <linux/of.h>
>>
>>   #include <linux/usb/otg.h>
>>
>> @@ -34,6 +36,20 @@ static struct usb_phy *__usb_find_phy(struct device *dev, u8 index)
>>   	return ERR_PTR(-ENODEV);
>>   }
>>
>> +static struct usb_phy *__of_usb_find_phy(struct device_node *node)
>> +{
>> +	struct usb_phy  *phy;
>> +
>> +	list_for_each_entry(phy, &phy_list, head) {
>> +		if (node != phy->dev->of_node)
>> +			continue;
>> +
>> +		return phy;
>> +	}
>> +
>> +	return ERR_PTR(-ENODEV);
>> +}
>> +
>>   static void devm_usb_phy_release(struct device *dev, void *res)
>>   {
>>   	struct usb_phy *phy = *(struct usb_phy **)res;
>> @@ -109,6 +125,67 @@ err0:
>>   }
>>   EXPORT_SYMBOL(usb_get_phy);
>>
>> + /**
>> + * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
>> + * @dev - device that requests this phy
>> + * @phandle - name of the property holding the phy phandle value
>> + * @index - the index of the phy
>> + *
>> + * Returns the phy driver associated with the given phandle value,
>> + * after getting a refcount to it, -ENODEV if there is no such phy or
>> + * -EPROBE_DEFER if there is a phandle to the phy, but the device is
>> + * not yet loaded. While at that, it also associates the device with
>> + * the phy using devres. On driver detach, release function is invoked
>> + * on the devres data, then, devres data is freed.
>> + *
>> + * For use by USB host and peripheral drivers.
>> + */
>> +struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
>> +	const char *phandle, u8 index)
>> +{
>> +	struct usb_phy	*phy = NULL, **ptr;
>> +	unsigned long	flags;
>> +	struct device_node *node;
>> +
>> +	if (!dev->of_node) {
>> +		dev_dbg(dev, "device does not have a device node entry\n");
>> +		return ERR_PTR(-EINVAL);
>> +	}
>> +
>> +	node = of_parse_phandle(dev->of_node, phandle, index);
>> +	if (!node) {
>> +		dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
>> +			dev->of_node->full_name);
>> +		return ERR_PTR(-ENODEV);
>> +	}
>> +
>> +	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
>> +	if (!ptr) {
>> +		dev_dbg(dev, "failed to allocate memory for devres\n");
>> +		return ERR_PTR(-ENOMEM);
>> +	}
>
> I fail to understand why you need ptr at all and why do devres_alloc()
> for it.

Thats how we create a "managed device resource". You can have a look at 
Documentation/driver-model/devres.txt and drivers/base/devres.c.

I'm not sure if that is what you are looking for :-P

Thanks
Kishon

^ permalink raw reply

* [PATCH] ARM: board-zoom: Do not request LCD panel enable GPIO from twl4030
From: Peter Ujfalusi @ 2013-01-21 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

The pin in question is muxed between GPIO7 and PWM1. For backlight control
there is a custom code in board-zoom-display to control the backlight.
No need to request the GPIO7 - which was failing since the way it is
requested no longer valid: twl's gpio range is allocated dynamically.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
Hi Tony,

This patch is generated on top of my previous series for audio/pwm support:
http://www.spinics.net/lists/linux-omap/msg85085.html

Regards,
Peter

 arch/arm/mach-omap2/board-zoom-peripherals.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index f4ea926..0745bd9 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -38,8 +38,6 @@
 #define OMAP_ZOOM_TSC2004_IRQ_GPIO	(153)
 #define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
 
-#define LCD_PANEL_ENABLE_GPIO		(7 + OMAP_MAX_GPIO_LINES)
-
 /* Zoom2 has Qwerty keyboard*/
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_E),
@@ -243,23 +241,15 @@ static struct omap_tw4030_pdata omap_twl4030_audio_data = {
 static int zoom_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	int ret;
-
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
-	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
-			       "lcd enable");
-	if (ret)
-		pr_err("Failed to get LCD_PANEL_ENABLE_GPIO (gpio%d).\n",
-				LCD_PANEL_ENABLE_GPIO);
-
 	/* Audio setup */
 	omap_twl4030_audio_data.jack_detect = gpio + 2;
 	omap_twl4030_audio_init("Zoom2", &omap_twl4030_audio_data);
 
-	return ret;
+	return 0;
 }
 
 static struct twl4030_gpio_platform_data zoom_gpio_data = {
-- 
1.8.1.1

^ permalink raw reply related

* [RFC PATCH 5/6] usb: otg: add device tree support to otg library
From: Roger Quadros @ 2013-01-21 13:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358348462-27693-6-git-send-email-kishon@ti.com>

On 01/16/2013 05:01 PM, Kishon Vijay Abraham I wrote:
> Added an API devm_usb_get_phy_by_phandle(), to get usb phy by passing a
> device node phandle value. This function will return a pointer to
> the phy on success, -EPROBE_DEFER if there is a device_node for the phandle,
> but the phy has not been added, or a ERR_PTR() otherwise.
> 
> Cc: Marc Kleine-Budde <mkl@pengutronix.de>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/usb/otg/otg.c   |   77 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/usb/phy.h |    8 +++++
>  2 files changed, 85 insertions(+)
> 
> diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
> index dbf2043..e9799bb 100644
> --- a/drivers/usb/otg/otg.c
> +++ b/drivers/usb/otg/otg.c
> @@ -13,7 +13,9 @@
>  #include <linux/export.h>
>  #include <linux/err.h>
>  #include <linux/device.h>
> +#include <linux/module.h>
>  #include <linux/slab.h>
> +#include <linux/of.h>
>  
>  #include <linux/usb/otg.h>
>  
> @@ -34,6 +36,20 @@ static struct usb_phy *__usb_find_phy(struct device *dev, u8 index)
>  	return ERR_PTR(-ENODEV);
>  }
>  
> +static struct usb_phy *__of_usb_find_phy(struct device_node *node)
> +{
> +	struct usb_phy  *phy;
> +
> +	list_for_each_entry(phy, &phy_list, head) {
> +		if (node != phy->dev->of_node)
> +			continue;
> +
> +		return phy;
> +	}
> +
> +	return ERR_PTR(-ENODEV);
> +}
> +
>  static void devm_usb_phy_release(struct device *dev, void *res)
>  {
>  	struct usb_phy *phy = *(struct usb_phy **)res;
> @@ -109,6 +125,67 @@ err0:
>  }
>  EXPORT_SYMBOL(usb_get_phy);
>  
> + /**
> + * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
> + * @dev - device that requests this phy
> + * @phandle - name of the property holding the phy phandle value
> + * @index - the index of the phy
> + *
> + * Returns the phy driver associated with the given phandle value,
> + * after getting a refcount to it, -ENODEV if there is no such phy or
> + * -EPROBE_DEFER if there is a phandle to the phy, but the device is
> + * not yet loaded. While at that, it also associates the device with
> + * the phy using devres. On driver detach, release function is invoked
> + * on the devres data, then, devres data is freed.
> + *
> + * For use by USB host and peripheral drivers.
> + */
> +struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
> +	const char *phandle, u8 index)
> +{
> +	struct usb_phy	*phy = NULL, **ptr;
> +	unsigned long	flags;
> +	struct device_node *node;
> +
> +	if (!dev->of_node) {
> +		dev_dbg(dev, "device does not have a device node entry\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	node = of_parse_phandle(dev->of_node, phandle, index);
> +	if (!node) {
> +		dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
> +			dev->of_node->full_name);
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
> +	if (!ptr) {
> +		dev_dbg(dev, "failed to allocate memory for devres\n");
> +		return ERR_PTR(-ENOMEM);
> +	}

I fail to understand why you need ptr at all and why do devres_alloc()
for it.

> +
> +	spin_lock_irqsave(&phy_lock, flags);
> +
> +	phy = __of_usb_find_phy(node);
> +	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
> +		phy = ERR_PTR(-EPROBE_DEFER);
> +		devres_free(ptr);
> +		goto err0;
> +	}
> +
> +	*ptr = phy;
> +	devres_add(dev, ptr);
> +
> +	get_device(phy->dev);
> +
> +err0:
> +	spin_unlock_irqrestore(&phy_lock, flags);
> +
> +	return phy;
> +}
> +EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
> +

--
cheers,
-roger

^ permalink raw reply

* [RFC PATCH 6/6] USB: MUSB: OMAP: get PHY by phandle for dt boot
From: Roger Quadros @ 2013-01-21 13:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358348462-27693-7-git-send-email-kishon@ti.com>

On 01/16/2013 05:01 PM, Kishon Vijay Abraham I wrote:
> The OMAP glue has been modified to get PHY by phandle for dt boot.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/usb/musb/omap2430.c |    7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
> index 3628a50..08709cf 100644
> --- a/drivers/usb/musb/omap2430.c
> +++ b/drivers/usb/musb/omap2430.c
> @@ -346,7 +346,12 @@ static int omap2430_musb_init(struct musb *musb)
>  	 * up through ULPI.  TWL4030-family PMICs include one,
>  	 * which needs a driver, drivers aren't always needed.
>  	 */
> -	musb->xceiv = devm_usb_get_phy(dev, 0);
> +	if (dev->parent->of_node)
> +		musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
> +		    "usb_phy", 0);

Why dev->parent and not just dev?

> +	else
> +		musb->xceiv = devm_usb_get_phy(dev, 0);
> +
>  	if (IS_ERR_OR_NULL(musb->xceiv)) {
>  		pr_err("HS USB OTG: no transceiver configured\n");
>  		return -ENODEV;
> 

--
cheers,
-roger

^ permalink raw reply

* [PATCH 4/4] ARM: apply the l2x0 Errata 769419 at run time
From: srinidhi kasagar @ 2013-01-21 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
---
 arch/arm/kernel/process.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index c6dec5f..c94d84f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -39,6 +39,7 @@
 #include <asm/thread_notify.h>
 #include <asm/stacktrace.h>
 #include <asm/mach/time.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
@@ -201,9 +202,11 @@ void cpu_idle(void)
 			 * to ensure we don't miss a wakeup call.
 			 */
 			local_irq_disable();
-#ifdef CONFIG_PL310_ERRATA_769419
-			wmb();
-#endif
+
+			/* Check for PL310 ERRATA 769419 */
+			if (l2x0_get_rtl_release() == L2X0_CACHE_ID_RTL_R3P0)
+				wmb();
+
 			if (hlt_counter) {
 				local_irq_enable();
 				cpu_relax();
-- 
1.7.2.dirty

^ permalink raw reply related

* [PATCH 3/4] ARM: mach-omap2: apply the errata at run time rather
From: srinidhi kasagar @ 2013-01-21 13:16 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
---
 arch/arm/mach-omap2/sleep44xx.S |   25 +++++++++++++++++++++----
 1 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index 88ff83a..071ca1f 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -157,11 +157,19 @@ skip_scu_gp_set:
 	ldrne	r0, [r8, #L2X0_SAVE_OFFSET1]	@ memory.
 	cmp	r0, #3
 	bne	do_WFI
-#ifdef CONFIG_PL310_ERRATA_727915
+	/* Check for PL310_ERRATA_727915 */
+	bl	l2x0_get_rtl_release
+	cmp	r0, #0x4
+	beq	dosmc
+	cmp	r0, #0x5
+	beq	dosmc
+	b	nosmc
+dosmc:
 	mov	r0, #0x03
 	mov	r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
 	DO_SMC
-#endif
+
+nosmc:
 	bl	omap4_get_l2cache_base
 	mov	r2, r0
 	ldr	r0, =0xffff
@@ -171,11 +179,20 @@ wait:
 	ldr	r1, =0xffff
 	ands	r0, r0, r1
 	bne	wait
-#ifdef CONFIG_PL310_ERRATA_727915
+
+	/* Check for PL310_ERRATA_727915 */
+	bl	l2x0_get_rtl_release
+	cmp	r0, #0x4
+	beq	dosmc2
+	cmp	r0, #0x5
+	beq	dosmc2
+	b	nosmc2
+dosmc2:
 	mov	r0, #0x00
 	mov	r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
 	DO_SMC
-#endif
+
+nosmc2:
 l2x_sync:
 	bl	omap4_get_l2cache_base
 	mov	r2, r0
-- 
1.7.2.dirty

^ permalink raw reply related

* [PATCH 2/4] ARM: make the platforms not to select the l2x0 erratas
From: srinidhi kasagar @ 2013-01-21 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

Make the platforms not to choose the Errata's explicitly

Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
---
 arch/arm/mach-omap2/Kconfig    |    2 --
 arch/arm/mach-tegra/Kconfig    |    3 ---
 arch/arm/mach-ux500/Kconfig    |    1 -
 arch/arm/mach-vexpress/Kconfig |    1 -
 4 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 41b581f..7612c07 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -67,8 +67,6 @@ config ARCH_OMAP4
 	select HAVE_SMP
 	select LOCAL_TIMERS if SMP
 	select OMAP_INTERCONNECT
-	select PL310_ERRATA_588369
-	select PL310_ERRATA_727915
 	select PM_OPP if PM
 	select PM_RUNTIME if CPU_IDLE
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index b442f15..f6214f5 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -15,8 +15,6 @@ config ARCH_TEGRA_2x_SOC
 	select CPU_V7
 	select PINCTRL
 	select PINCTRL_TEGRA20
-	select PL310_ERRATA_727915 if CACHE_L2X0
-	select PL310_ERRATA_769419 if CACHE_L2X0
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ULPI if USB
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
@@ -36,7 +34,6 @@ config ARCH_TEGRA_3x_SOC
 	select CPU_V7
 	select PINCTRL
 	select PINCTRL_TEGRA30
-	select PL310_ERRATA_769419 if CACHE_L2X0
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ULPI if USB
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 5dea906..db13db5 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -11,7 +11,6 @@ config UX500_SOC_COMMON
 	select COMMON_CLK
 	select PINCTRL
 	select PINCTRL_NOMADIK
-	select PL310_ERRATA_753970 if CACHE_PL310
 
 config UX500_SOC_DB8500
 	bool
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 52d315b..c658c40 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -42,7 +42,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
 	bool "Enable A5 and A9 only errata work-arounds"
 	default y
 	select ARM_ERRATA_720789
-	select PL310_ERRATA_753970 if CACHE_PL310
 	help
 	  Provides common dependencies for Versatile Express platforms
 	  based on Cortex-A5 and Cortex-A9 processors. In order to
-- 
1.7.2.dirty

^ permalink raw reply related

* [PATCH 1/4] ARM: cache-l2x0: Manage the errata at run time
From: srinidhi kasagar @ 2013-01-21 13:14 UTC (permalink / raw)
  To: linux-arm-kernel

Make it possible to manage the errata by its own by using the
l2x0 ID register. This relieves the platforms from choosing the
Errata's at compile time

Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
---
 arch/arm/include/asm/hardware/cache-l2x0.h |    2 +
 arch/arm/mm/cache-l2x0.c                   |   77 +++++++++++++++-------------
 2 files changed, 43 insertions(+), 36 deletions(-)

diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 3b2c40b..d5994ac 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -117,6 +117,8 @@ static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)
 }
 #endif
 
+asmlinkage u32 l2x0_get_rtl_release(void);
+
 struct l2x0_regs {
 	unsigned long phy_base;
 	unsigned long aux_ctrl;
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index c2f3739..49058ac 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -49,6 +49,16 @@ struct l2x0_of_data {
 
 static bool of_init = false;
 
+/*
+ * Identify ther RTL releases of l2x0 - This might help in applying
+ * the l2x0 errata's dynamically rather compile time options
+ */
+asmlinkage u32 l2x0_get_rtl_release(void)
+{
+	return readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+			L2X0_CACHE_ID_RTL_MASK;
+}
+
 static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
 {
 	/* wait for cache operation by line or way to complete */
@@ -87,46 +97,41 @@ static inline void l2x0_inv_line(unsigned long addr)
 	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
 }
 
-#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
-static inline void debug_writel(unsigned long val)
+static void debug_writel(unsigned long val)
 {
-	if (outer_cache.set_debug)
-		outer_cache.set_debug(val);
+	u32 l2x0_revision = l2x0_get_rtl_release();
+
+	if (l2x0_revision == L2X0_CACHE_ID_RTL_R3P0 ||
+		l2x0_revision == L2X0_CACHE_ID_RTL_R2P0 ||
+		l2x0_revision == L2X0_CACHE_ID_RTL_R1P0 ||
+		l2x0_revision == L2X0_CACHE_ID_RTL_R0P0)
+			if (outer_cache.set_debug)
+				outer_cache.set_debug(val);
 }
 
 static void pl310_set_debug(unsigned long val)
 {
 	writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
 }
-#else
-/* Optimised out for non-errata case */
-static inline void debug_writel(unsigned long val)
-{
-}
-
-#define pl310_set_debug	NULL
-#endif
-
-#ifdef CONFIG_PL310_ERRATA_588369
-static inline void l2x0_flush_line(unsigned long addr)
-{
-	void __iomem *base = l2x0_base;
-
-	/* Clean by PA followed by Invalidate by PA */
-	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
-	writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
-	cache_wait(base + L2X0_INV_LINE_PA, 1);
-	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
-}
-#else
 
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
-	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
-	writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA);
+	u32 l2x0_revision = l2x0_get_rtl_release();
+
+	if (l2x0_revision == L2X0_CACHE_ID_RTL_R0P0 ||
+		l2x0_revision == L2X0_CACHE_ID_RTL_R1P0)
+	{
+		/* Clean by PA followed by Invalidate by PA */
+		cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
+		writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
+		cache_wait(base + L2X0_INV_LINE_PA, 1);
+		writel_relaxed(addr, base + L2X0_INV_LINE_PA);
+	} else {
+		cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+		writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA);
+	}
 }
-#endif
 
 static void l2x0_cache_sync(void)
 {
@@ -328,6 +333,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 	int ways;
 	int way_size_shift = L2X0_WAY_SIZE_SHIFT;
 	const char *type;
+	u32 l2x0_revision = l2x0_get_rtl_release();
 
 	l2x0_base = base;
 	if (cache_id_part_number_from_dt)
@@ -348,10 +354,11 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 		else
 			ways = 8;
 		type = "L310";
-#ifdef CONFIG_PL310_ERRATA_753970
-		/* Unmapped register. */
-		sync_reg_offset = L2X0_DUMMY_REG;
-#endif
+
+		if (l2x0_revision == L2X0_CACHE_ID_RTL_R3P0)
+			/* Unmapped register. */
+			sync_reg_offset = L2X0_DUMMY_REG;
+
 		if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0)
 			outer_cache.set_debug = pl310_set_debug;
 		break;
@@ -594,8 +601,7 @@ static void __init pl310_of_setup(const struct device_node *np,
 
 static void __init pl310_save(void)
 {
-	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
-		L2X0_CACHE_ID_RTL_MASK;
+	u32 l2x0_revision = l2x0_get_rtl_release();
 
 	l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
 		L2X0_TAG_LATENCY_CTRL);
@@ -657,8 +663,7 @@ static void pl310_resume(void)
 		writel_relaxed(l2x0_saved_regs.filter_start,
 			l2x0_base + L2X0_ADDR_FILTER_START);
 
-		l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
-			L2X0_CACHE_ID_RTL_MASK;
+		l2x0_revision = l2x0_get_rtl_release();
 
 		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
 			writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
-- 
1.7.2.dirty

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox