[RFC 1/4] of: add of_dev_get_platdata()

2015-08-28 Thread Milo Kim
of_dev_get_platdata()
  - provides unified handling of getting device platform data
  - supports DT and non-DT(legacy) cases
if CONFIG_OF is not defined, then returns legacy function,
'dev_get_platdata()'.
  - removes duplicated code from each driver
  - keeps driver specific code simple in each driver

Parser function - of_parse_dt_fn()
  Caller(aka driver) gets allocated platform data and optional private
  data. Then, it will parse the DT and copy properties into allocated
  platform data and use the private data if needed.

Cc: Dmitry Torokhov dmitry.torok...@gmail.com
Cc: Felipe Balbi ba...@ti.com
Cc: Grant Likely grant.lik...@linaro.org
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Lee Jones lee.jo...@linaro.org
Cc: Rob Herring robh...@kernel.org
Cc: Samuel Ortiz sa...@linux.intel.com
Cc: Tony Lindgren t...@atomide.com
Cc: devicet...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/of/device.c   | 46 ++
 include/linux/of_device.h | 12 
 2 files changed, 58 insertions(+)

diff --git a/drivers/of/device.c b/drivers/of/device.c
index 8b91ea2..5793ba0 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -286,3 +286,49 @@ int of_device_uevent_modalias(struct device *dev, struct 
kobj_uevent_env *env)
 
return 0;
 }
+
+/**
+ * of_dev_get_platdata - get the platform data.
+ * @dev: device to get the platform data.
+ * @size: size of the platform data.
+ * @of_parse_dt_fn: device specific function to parse the device tree.
+ * @priv: driver private data to be passed to of_parse_dt_fn.
+ *
+ * This routine provides unified way of getting device platform data.
+ * If the platform data exists, just return it. It's exactly same as
+ * how to get device platform data by using dev_get_platdata().
+ * If the platform data is null, checks the device node. If the device tree is
+ * is supported, then allocates the device platform data and call back to
+ * driver specific 'of_parse_dt_fn'. The caller driver should handle data
+ * manipulation inside this function.
+ *
+ * of_parse_dt_fn() has three arguments. The first is device structure.
+ * The second is the pointer of allocated device platform data.
+ * The last one is private data pointer which is used in of_parse_dt_fn().
+ *
+ * Return value is a pointer of device platform data.
+ * Caller should check IS_ERR(pdata) and return PTR_ERR(pdata).
+ */
+void *of_dev_get_platdata(struct device *dev, size_t size,
+ of_parse_dt_t of_parse_dt_fn, void *priv)
+{
+   void *pdata = dev_get_platdata(dev);
+   int err;
+
+   if (pdata)
+   return pdata;
+
+   if (!dev_of_node(dev) || !of_parse_dt_fn)
+   return NULL;
+
+   pdata = devm_kzalloc(dev, size, GFP_KERNEL);
+   if (!pdata)
+   return ERR_PTR(-ENOMEM);
+
+   err = of_parse_dt_fn(dev, pdata, priv);
+   if (err)
+   return ERR_PTR(err);
+
+   return pdata;
+}
+EXPORT_SYMBOL_GPL(of_dev_get_platdata);
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index cc7dd687..b24b3d8 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -10,6 +10,9 @@
 
 struct device;
 
+/* Device specific DT parser function */
+typedef int (*of_parse_dt_t)(struct device *, void *, void *);
+
 #ifdef CONFIG_OF
 extern const struct of_device_id *of_match_device(
const struct of_device_id *matches, const struct device *dev);
@@ -56,6 +59,9 @@ static inline struct device_node *of_cpu_device_node_get(int 
cpu)
 }
 
 void of_dma_configure(struct device *dev, struct device_node *np);
+
+extern void *of_dev_get_platdata(struct device *dev, size_t size,
+of_parse_dt_t of_parse_dt_fn, void *priv);
 #else /* CONFIG_OF */
 
 static inline int of_driver_match_device(struct device *dev,
@@ -100,6 +106,12 @@ static inline struct device_node 
*of_cpu_device_node_get(int cpu)
 }
 static inline void of_dma_configure(struct device *dev, struct device_node *np)
 {}
+
+static inline void *of_dev_get_platdata(struct device *dev, size_t size,
+   of_parse_dt_t of_parse_dt_fn, void *priv)
+{
+   return dev_get_platdata(dev);
+}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 2/4] input: touchscree: mms114: use of_dev_get_platdata()

2015-08-28 Thread Milo Kim
Driver calls of_dev_get_platdata(). Error handler is added - IS_ERR() and
PTR_ERR() if an error is found.
Return type of mms114_parse_dt() is changed to integer. So return values
are modified.

Cc: Dmitry Torokhov dmitry.torok...@gmail.com
Cc: Felipe Balbi ba...@ti.com
Cc: Grant Likely grant.lik...@linaro.org
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Lee Jones lee.jo...@linaro.org
Cc: Rob Herring robh...@kernel.org
Cc: Samuel Ortiz sa...@linux.intel.com
Cc: Tony Lindgren t...@atomide.com
Cc: devicet...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/input/touchscreen/mms114.c | 34 ++
 1 file changed, 10 insertions(+), 24 deletions(-)

diff --git a/drivers/input/touchscreen/mms114.c 
b/drivers/input/touchscreen/mms114.c
index 67c0d31..555e326 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -10,6 +10,7 @@
 #include linux/module.h
 #include linux/delay.h
 #include linux/of.h
+#include linux/of_device.h
 #include linux/i2c.h
 #include linux/i2c/mms114.h
 #include linux/input/mt.h
@@ -376,29 +377,19 @@ static void mms114_input_close(struct input_dev *dev)
mms114_stop(data);
 }
 
-#ifdef CONFIG_OF
-static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+static int mms114_parse_dt(struct device *dev, void *data, void *priv)
 {
-   struct mms114_platform_data *pdata;
+   struct mms114_platform_data *pdata = data;
struct device_node *np = dev-of_node;
 
-   if (!np)
-   return NULL;
-
-   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-   if (!pdata) {
-   dev_err(dev, failed to allocate platform data\n);
-   return NULL;
-   }
-
if (of_property_read_u32(np, x-size, pdata-x_size)) {
dev_err(dev, failed to get x-size property\n);
-   return NULL;
+   return -EINVAL;
};
 
if (of_property_read_u32(np, y-size, pdata-y_size)) {
dev_err(dev, failed to get y-size property\n);
-   return NULL;
+   return -EINVAL;
};
 
of_property_read_u32(np, contact-threshold,
@@ -411,14 +402,8 @@ static struct mms114_platform_data *mms114_parse_dt(struct 
device *dev)
if (of_find_property(np, y-invert, NULL))
pdata-y_invert = true;
 
-   return pdata;
-}
-#else
-static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
-{
-   return NULL;
+   return 0;
 }
-#endif
 
 static int mms114_probe(struct i2c_client *client,
  const struct i2c_device_id *id)
@@ -428,9 +413,10 @@ static int mms114_probe(struct i2c_client *client,
struct input_dev *input_dev;
int error;
 
-   pdata = dev_get_platdata(client-dev);
-   if (!pdata)
-   pdata = mms114_parse_dt(client-dev);
+   pdata = of_dev_get_platdata(client-dev, sizeof(*pdata),
+   mms114_parse_dt, NULL);
+   if (IS_ERR(pdata))
+   return PTR_ERR(pdata);
 
if (!pdata) {
dev_err(client-dev, Need platform data\n);
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 4/4] usb: musb: use of_dev_get_platdata()

2015-08-28 Thread Milo Kim
'of_dev_get_platdata()' makes if-statements simple.

Cc: Dmitry Torokhov dmitry.torok...@gmail.com
Cc: Felipe Balbi ba...@ti.com
Cc: Grant Likely grant.lik...@linaro.org
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Lee Jones lee.jo...@linaro.org
Cc: Rob Herring robh...@kernel.org
Cc: Samuel Ortiz sa...@linux.intel.com
Cc: Tony Lindgren t...@atomide.com
Cc: devicet...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/usb/musb/ux500.c | 40 
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 39168fe..851cf4a 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -25,6 +25,7 @@
 #include linux/err.h
 #include linux/io.h
 #include linux/of.h
+#include linux/of_device.h
 #include linux/platform_device.h
 #include linux/usb/musb-ux500.h
 
@@ -200,21 +201,16 @@ static const struct musb_platform_ops ux500_ops = {
.set_vbus   = ux500_musb_set_vbus,
 };
 
-static struct musb_hdrc_platform_data *
-ux500_of_probe(struct platform_device *pdev, struct device_node *np)
+static int ux500_of_probe(struct device *dev, void *data, void *priv)
 {
-   struct musb_hdrc_platform_data *pdata;
+   struct musb_hdrc_platform_data *pdata = data;
const char *mode;
int strlen;
 
-   pdata = devm_kzalloc(pdev-dev, sizeof(*pdata), GFP_KERNEL);
-   if (!pdata)
-   return NULL;
-
-   mode = of_get_property(np, dr_mode, strlen);
+   mode = of_get_property(dev-of_node, dr_mode, strlen);
if (!mode) {
-   dev_err(pdev-dev, No 'dr_mode' property found\n);
-   return NULL;
+   dev_err(dev, No 'dr_mode' property found\n);
+   return -EINVAL;
}
 
if (strlen  0) {
@@ -226,31 +222,27 @@ ux500_of_probe(struct platform_device *pdev, struct 
device_node *np)
pdata-mode = MUSB_PERIPHERAL;
}
 
-   return pdata;
+   return 0;
 }
 
 static int ux500_probe(struct platform_device *pdev)
 {
struct resource musb_resources[2];
-   struct musb_hdrc_platform_data  *pdata = dev_get_platdata(pdev-dev);
-   struct device_node  *np = pdev-dev.of_node;
+   struct musb_hdrc_platform_data  *pdata;
struct platform_device  *musb;
struct ux500_glue   *glue;
struct clk  *clk;
int ret = -ENOMEM;
 
-   if (!pdata) {
-   if (np) {
-   pdata = ux500_of_probe(pdev, np);
-   if (!pdata)
-   goto err0;
+   pdata = of_dev_get_platdata(pdev-dev, sizeof(*pdata),
+   ux500_of_probe, NULL);
+   if (IS_ERR(pdata))
+   return PTR_ERR(pdata);
 
-   pdev-dev.platform_data = pdata;
-   } else {
-   dev_err(pdev-dev, no pdata or device tree found\n);
-   goto err0;
-   }
-   }
+   if (!pdata)
+   goto err0;
+
+   pdev-dev.platform_data = pdata;
 
glue = devm_kzalloc(pdev-dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 3/4] mfd: tps65910: use of_dev_get_platdata()

2015-08-28 Thread Milo Kim
Platform data allocation, CONFIG_OF and condition statements are supported
in of_dev_get_platdata().
This patch shows how to use private data in each parser function.
tps65910 calls of_dev_get_platdata() with driver private data, 'chip_id'.
This data is used in tps65910_parse_dt().

'of_pmic_plat_data' is unnecessary any more. IRQ number is updated after
parsing the DT.

Cc: Dmitry Torokhov dmitry.torok...@gmail.com
Cc: Felipe Balbi ba...@ti.com
Cc: Grant Likely grant.lik...@linaro.org
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Lee Jones lee.jo...@linaro.org
Cc: Rob Herring robh...@kernel.org
Cc: Samuel Ortiz sa...@linux.intel.com
Cc: Tony Lindgren t...@atomide.com
Cc: devicet...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/mfd/tps65910.c | 49 -
 1 file changed, 16 insertions(+), 33 deletions(-)

diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 7612d89..2a068d7 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -378,7 +378,6 @@ err_sleep_init:
return ret;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id tps65910_of_match[] = {
{ .compatible = ti,tps65910, .data = (void *)TPS65910},
{ .compatible = ti,tps65911, .data = (void *)TPS65911},
@@ -386,30 +385,23 @@ static const struct of_device_id tps65910_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tps65910_of_match);
 
-static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
-   unsigned long *chip_id)
+static int tps65910_parse_dt(struct device *dev, void *data, void *priv)
 {
-   struct device_node *np = client-dev.of_node;
-   struct tps65910_board *board_info;
+   struct device_node *np = dev-of_node;
+   struct tps65910_board *board_info = data;
+   unsigned long *chip_id = priv;
unsigned int prop;
const struct of_device_id *match;
int ret = 0;
 
-   match = of_match_device(tps65910_of_match, client-dev);
+   match = of_match_device(tps65910_of_match, dev);
if (!match) {
-   dev_err(client-dev, Failed to find matching dt id\n);
-   return NULL;
+   dev_err(dev, Failed to find matching dt id\n);
+   return -EINVAL;
}
 
*chip_id  = (unsigned long)match-data;
 
-   board_info = devm_kzalloc(client-dev, sizeof(*board_info),
-   GFP_KERNEL);
-   if (!board_info) {
-   dev_err(client-dev, Failed to allocate pdata\n);
-   return NULL;
-   }
-
ret = of_property_read_u32(np, ti,vmbch-threshold, prop);
if (!ret)
board_info-vmbch_threshold = prop;
@@ -421,21 +413,12 @@ static struct tps65910_board *tps65910_parse_dt(struct 
i2c_client *client,
prop = of_property_read_bool(np, ti,en-ck32k-xtal);
board_info-en_ck32k_xtal = prop;
 
-   board_info-irq = client-irq;
board_info-irq_base = -1;
board_info-pm_off = of_property_read_bool(np,
ti,system-power-controller);
 
-   return board_info;
-}
-#else
-static inline
-struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
-unsigned long *chip_id)
-{
-   return NULL;
+   return 0;
 }
-#endif
 
 static struct i2c_client *tps65910_i2c_client;
 static void tps65910_power_off(void)
@@ -457,21 +440,21 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
 {
struct tps65910 *tps65910;
struct tps65910_board *pmic_plat_data;
-   struct tps65910_board *of_pmic_plat_data = NULL;
struct tps65910_platform_data *init_data;
unsigned long chip_id = id-driver_data;
int ret = 0;
 
-   pmic_plat_data = dev_get_platdata(i2c-dev);
-
-   if (!pmic_plat_data  i2c-dev.of_node) {
-   pmic_plat_data = tps65910_parse_dt(i2c, chip_id);
-   of_pmic_plat_data = pmic_plat_data;
-   }
+   pmic_plat_data = of_dev_get_platdata(i2c-dev,
+sizeof(*pmic_plat_data),
+tps65910_parse_dt, chip_id);
+   if (IS_ERR(pmic_plat_data))
+   return PTR_ERR(pmic_plat_data);
 
if (!pmic_plat_data)
return -EINVAL;
 
+   pmic_plat_data-irq = i2c-irq;
+
init_data = devm_kzalloc(i2c-dev, sizeof(*init_data), GFP_KERNEL);
if (init_data == NULL)
return -ENOMEM;
@@ -480,7 +463,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
if (tps65910 == NULL)
return -ENOMEM;
 
-   tps65910-of_plat_data = of_pmic_plat_data;
+   tps65910-of_plat_data = pmic_plat_data;
i2c_set_clientdata(i2c, tps65910);
tps65910-dev = i2c-dev;
tps65910-i2c_client = i2c;
-- 
1.9.1

--
To unsubscribe from this list: send the line

[RFC 0/4] of: introduce of_dev_get_platdata()

2015-08-28 Thread Milo Kim
/pwm_bl.c
  drivers/video/backlight/sky81452-backlight.c
  drivers/video/backlight/tps65217_bl.c

This is the RFC, so I would like to get some feedback prior to patching all
drivers. Any comments are welcome.

Cc: Dmitry Torokhov dmitry.torok...@gmail.com
Cc: Felipe Balbi ba...@ti.com
Cc: Grant Likely grant.lik...@linaro.org
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Lee Jones lee.jo...@linaro.org
Cc: Rob Herring robh...@kernel.org
Cc: Samuel Ortiz sa...@linux.intel.com
Cc: Tony Lindgren t...@atomide.com
Cc: devicet...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Milo Kim (4):
  of: introduce of_dev_get_platdata()
  input: touchscree: mms114: use of_dev_get_platdata()
  mfd: tps65910: use of_dev_get_platdata()
  usb: musb: use of_dev_get_platdata()

 drivers/input/touchscreen/mms114.c | 34 --
 drivers/mfd/tps65910.c | 49 +-
 drivers/of/device.c| 46 +++
 drivers/usb/musb/ux500.c   | 40 +--
 include/linux/of_device.h  | 12 ++
 5 files changed, 100 insertions(+), 81 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] regulator:lp872x: handle error case

2015-08-24 Thread Milo Kim
If memory allocation gets failed on parsing the DT, then it returns error
'-ENOMEM' explicitly. Then, the driver exists from the _probe().

Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/regulator/lp872x.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 9142c1a..8702e73 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -849,7 +849,7 @@ static struct lp872x_platform_data
 
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
-   goto out;
+   return ERR_PTR(-ENOMEM);
 
of_property_read_u8(np, ti,general-config, pdata-general_config);
if (of_find_property(np, ti,update-config, NULL))
@@ -857,7 +857,7 @@ static struct lp872x_platform_data
 
pdata-dvs = devm_kzalloc(dev, sizeof(struct lp872x_dvs), GFP_KERNEL);
if (!pdata-dvs)
-   goto out;
+   return ERR_PTR(-ENOMEM);
 
pdata-dvs-gpio = of_get_named_gpio(np, ti,dvs-gpio, 0);
of_property_read_u8(np, ti,dvs-vsel, (u8 *)pdata-dvs-vsel);
@@ -910,11 +910,14 @@ static int lp872x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
[LP8725] = LP8725_NUM_REGULATORS,
};
 
-   if (cl-dev.of_node)
+   if (cl-dev.of_node) {
pdata = lp872x_populate_pdata_from_dt(cl-dev,
  (enum lp872x_id)id-driver_data);
-   else
+   if (IS_ERR(pdata))
+   return PTR_ERR(pdata);
+   } else {
pdata = dev_get_platdata(cl-dev);
+   }
 
lp = devm_kzalloc(cl-dev, sizeof(struct lp872x), GFP_KERNEL);
if (!lp)
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] regulator:lp872x: use the private data instead of updating I2C device platform data

2015-08-24 Thread Milo Kim
Currently, lp872x driver parses the DT and copies values into the
'cl-dev.platform_data' if 'of_node' exists.
This may have architectural issue. Platform data is configurable through
the DT or I2C board info inside the platform area.
However, lp872x driver changes this configuration when it is loaded.

The lp872x driver should get data from the platform side and use the private
data, 'lp872x-pdata' instead of changing the original platform data.

Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/regulator/lp872x.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 3de328a..9142c1a 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -903,6 +903,7 @@ static struct lp872x_platform_data
 static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
struct lp872x *lp;
+   struct lp872x_platform_data *pdata;
int ret;
const int lp872x_num_regulators[] = {
[LP8720] = LP8720_NUM_REGULATORS,
@@ -910,8 +911,10 @@ static int lp872x_probe(struct i2c_client *cl, const 
struct i2c_device_id *id)
};
 
if (cl-dev.of_node)
-   cl-dev.platform_data = lp872x_populate_pdata_from_dt(cl-dev,
+   pdata = lp872x_populate_pdata_from_dt(cl-dev,
  (enum lp872x_id)id-driver_data);
+   else
+   pdata = dev_get_platdata(cl-dev);
 
lp = devm_kzalloc(cl-dev, sizeof(struct lp872x), GFP_KERNEL);
if (!lp)
@@ -927,7 +930,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct 
i2c_device_id *id)
}
 
lp-dev = cl-dev;
-   lp-pdata = dev_get_platdata(cl-dev);
+   lp-pdata = pdata;
lp-chipid = id-driver_data;
i2c_set_clientdata(cl, lp);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] power:lp8727_charger: parsing child node after getting debounce-ms

2015-08-25 Thread Milo Kim
According to lp8727 bindings[*], charging parameter is optional.
So parsing can be skipped in case those properties are undefined.
However, 'debounce-ms' should be read prior to checking the properties.
Otherwise, 'debounce-ms' property will be ignored even it is configured
inside the DT.
So, counting child is processed after updating 'debounce-ms'.

[*] Documentation/devicetree/bindings/power_supply/lp8727_charger.txt

Cc: Dmitry Eremin-Solenikov dbarysh...@gmail.com
Cc: linux...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/power/lp8727_charger.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index 30dc265..042fb3da 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -515,16 +515,16 @@ static struct lp8727_platform_data 
*lp8727_parse_dt(struct device *dev)
struct lp8727_platform_data *pdata;
const char *type;
 
-   /* If charging parameter is not defined, just skip parsing the dt */
-   if (of_get_child_count(np) == 0)
-   return NULL;
-
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
 
of_property_read_u32(np, debounce-ms, pdata-debounce_msec);
 
+   /* If charging parameter is not defined, just skip parsing the dt */
+   if (of_get_child_count(np) == 0)
+   return pdata;
+
for_each_child_of_node(np, child) {
of_property_read_string(child, charger-type, type);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] power:lp8727_charger: use the private data instead of updating I2C device platform data

2015-08-25 Thread Milo Kim
Currently, lp8727 charger driver parses the DT and copies values into the
'cl-dev.platform_data' if 'of_node' exists.
This may have architectural issue. Platform data is configurable through
the DT or I2C board info inside the platform area.
However, lp8727 driver changes this configuration when it is loaded.

The driver should get data from the platform side and use the private
data, 'lp8727_chg-pdata' instead of changing the original platform data.

_probe() procedure is changed as follows.
  1. lp8727_parse_dt() returns the pointer of lp8727_platform_data.
 The driver uses this allocated platform data. So it should keep
 original platform data, 'dev-platform_data'.
  2. In _probe(), check the return value of lp8727_parse_dt().
 If an error is found, then exit as PTR_ERR(pdata).
  3. If 'of_node' is not found, then the driver just gets the platform data
 from the I2C device structure.
  4. Map the platform data to private data structure.

Cc: Dmitry Eremin-Solenikov dbarysh...@gmail.com
Cc: linux...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim milo@ti.com
---
 drivers/power/lp8727_charger.c | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index 7e741f1..30dc265 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -508,7 +508,7 @@ out:
return param;
 }
 
-static int lp8727_parse_dt(struct device *dev)
+static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
 {
struct device_node *np = dev-of_node;
struct device_node *child;
@@ -517,11 +517,11 @@ static int lp8727_parse_dt(struct device *dev)
 
/* If charging parameter is not defined, just skip parsing the dt */
if (of_get_child_count(np) == 0)
-   goto out;
+   return NULL;
 
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
of_property_read_u32(np, debounce-ms, pdata-debounce_msec);
 
@@ -535,29 +535,30 @@ static int lp8727_parse_dt(struct device *dev)
pdata-usb = lp8727_parse_charge_pdata(dev, child);
}
 
-   dev-platform_data = pdata;
-out:
-   return 0;
+   return pdata;
 }
 #else
-static int lp8727_parse_dt(struct device *dev)
+static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
 {
-   return 0;
+   return NULL;
 }
 #endif
 
 static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
struct lp8727_chg *pchg;
+   struct lp8727_platform_data *pdata;
int ret;
 
if (!i2c_check_functionality(cl-adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
 
if (cl-dev.of_node) {
-   ret = lp8727_parse_dt(cl-dev);
-   if (ret)
-   return ret;
+   pdata = lp8727_parse_dt(cl-dev);
+   if (IS_ERR(pdata))
+   return PTR_ERR(pdata);
+   } else {
+   pdata = dev_get_platdata(cl-dev);
}
 
pchg = devm_kzalloc(cl-dev, sizeof(*pchg), GFP_KERNEL);
@@ -566,7 +567,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct 
i2c_device_id *id)
 
pchg-client = cl;
pchg-dev = cl-dev;
-   pchg-pdata = cl-dev.platform_data;
+   pchg-pdata = pdata;
i2c_set_clientdata(cl, pchg);
 
mutex_init(pchg-xfer_lock);
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 07/19] irqchip: atmel-aic: make common IRQ domain translate function

2016-01-03 Thread Milo Kim
AIC5 and AIC have common translate interrupt specifiers.
HW IRQ number, interrupt type (flag) and interrupt priority.

For interrupt priority update, those systems look different handing.
AIC5 writes SSR (Source Select Register) first and read SMR (Source Mode
Register) to update interrupt priority.
On the other hand, AIC reads SMR and update the priority into same register.
New helper, 'aic_update_smr()' provides unified handling.

aic_is_ssr_used():
  Check whether IRQ chip uses SSR for IRQ selection or not.
  AIC5 uses this register. AIC does not have it.

aic_update_smr():
  AIC has separate register for mode selection, SMR.
  Offset value depends on IRQ source number. (SMR + hwirq * 4)
  On the other hands, AIC5 requires two register access, SSR and SMR.
  This helper selects the interrupt source on updating prority level or
  IRQ flag.

aic_irq_domain_xlate():
  Common domain translator handles interrupt specifiers as below.
  1. Get HW IRQ number, IRQ flag and priority from interrupt specifiers.
  2. If SSR is used, write hwirq into SSR for IRQ selection.
  3. Read value of SMR
  4. Update priority into SMR

  In case of AIC, total number of interrupts is 32. It means selected index
  is always zero in xlate(), so generic IRQ chip data can be retrieved from
  irq_get_domain_generic_chip(d, 0).

Then, both IRQ domains can use common operations, aic_irq_ops, so ops
argument in aic_common_of_init() can be removed.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 94 +-
 drivers/irqchip/irq-atmel-aic-common.h | 10 
 drivers/irqchip/irq-atmel-aic.c| 44 +---
 drivers/irqchip/irq-atmel-aic5.c   | 37 +
 4 files changed, 61 insertions(+), 124 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index f840165..94c9dad 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -129,6 +129,63 @@ static const struct aic_reg_offset aic5_regs = {
 
 static const struct aic_reg_offset *aic_reg_data;
 
+static inline bool aic_is_ssr_used(void)
+{
+   return aic_reg_data->ssr != AT91_INVALID_OFFSET;
+}
+
+static void aic_update_smr(struct irq_chip_generic *gc, int hwirq,
+  u32 mask, u32 val)
+{
+   int reg = aic_reg_data->smr;
+   u32 tmp = 0;
+
+   if (aic_is_ssr_used())
+   irq_reg_writel(gc, hwirq, aic_reg_data->ssr);
+   else
+   reg += hwirq * 4;
+
+   tmp = irq_reg_readl(gc, reg);
+   tmp &= mask;
+   tmp |= val;
+
+   irq_reg_writel(gc, tmp, reg);
+}
+
+static int aic_irq_domain_xlate(struct irq_domain *d, struct device_node *node,
+   const u32 *intspec, unsigned int intsize,
+   irq_hw_number_t *out_hwirq,
+   unsigned int *out_type)
+{
+   struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
+   bool condition = (intsize < 3) ||
+(intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) ||
+(intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY);
+
+   if (!gc || WARN_ON(condition))
+   return -EINVAL;
+
+   /*
+* intspec[0]: HW IRQ number
+* intspec[1]: IRQ flag
+* intspec[2]: IRQ priority
+*/
+
+   *out_hwirq = intspec[0];
+   *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+   irq_gc_lock(gc);
+   aic_update_smr(gc, *out_hwirq, ~AT91_AIC_PRIOR, intspec[2]);
+   irq_gc_unlock(gc);
+
+   return 0;
+}
+
+static const struct irq_domain_ops aic_irq_ops = {
+   .map= irq_map_generic_chip,
+   .xlate  = aic_irq_domain_xlate,
+};
+
 static void aic_common_shutdown(struct irq_data *d)
 {
struct irq_chip_type *ct = irq_data_get_chip_type(d);
@@ -171,38 +228,6 @@ int aic_common_set_type(struct irq_data *d, unsigned type, 
unsigned *val)
return 0;
 }
 
-int aic_common_set_priority(int priority, unsigned *val)
-{
-   if (priority < AT91_AIC_IRQ_MIN_PRIORITY ||
-   priority > AT91_AIC_IRQ_MAX_PRIORITY)
-   return -EINVAL;
-
-   *val &= ~AT91_AIC_PRIOR;
-   *val |= priority;
-
-   return 0;
-}
-
-int aic_common_irq_domain_xlate(struct irq_domain *d,
-   struct device_node *ctrlr,
-   const u32 *intspec,
-   unsigned int intsize,
-   

[PATCH 04/19] irqchip: atmel-aic: replace magic numbers with named constant

2016-01-03 Thread Milo Kim
One AIC IRQ chip can have 32 interrupt source.
To enhance code readability, magic number is replaced with named constant,
'AIC_IRQS_PER_CHIP'.

aic_hw_init() initializes vector registers up to total number of
AIC interrupts. This magic number is replaced with NR_AIC_IRQS.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 11 ++-
 drivers/irqchip/irq-atmel-aic-common.h |  1 +
 drivers/irqchip/irq-atmel-aic.c|  2 +-
 drivers/irqchip/irq-atmel-aic5.c   |  4 ++--
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index ef2c619..5effd52 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -135,7 +135,7 @@ static void __init aic_common_ext_irq_of_init(struct 
irq_domain *domain)
}
 
aic = gc->private;
-   aic->ext_irqs |= (1 << (hwirq % 32));
+   aic->ext_irqs |= (1 << (hwirq % AIC_IRQS_PER_CHIP));
}
 }
 
@@ -151,7 +151,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
int ret;
int i;
 
-   nchips = DIV_ROUND_UP(nirqs, 32);
+   nchips = DIV_ROUND_UP(nirqs, AIC_IRQS_PER_CHIP);
 
reg_base = of_iomap(node, 0);
if (!reg_base)
@@ -163,13 +163,14 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
goto err_iounmap;
}
 
-   domain = irq_domain_add_linear(node, nchips * 32, ops, aic);
+   domain = irq_domain_add_linear(node, nchips * AIC_IRQS_PER_CHIP, ops,
+  aic);
if (!domain) {
ret = -ENOMEM;
goto err_free_aic;
}
 
-   ret = irq_alloc_domain_generic_chips(domain, 32, 1, name,
+   ret = irq_alloc_domain_generic_chips(domain, AIC_IRQS_PER_CHIP, 1, name,
 handle_fasteoi_irq,
 IRQ_NOREQUEST | IRQ_NOPROBE |
 IRQ_NOAUTOEN, 0, 0);
@@ -177,7 +178,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
goto err_domain_remove;
 
for (i = 0; i < nchips; i++) {
-   gc = irq_get_domain_generic_chip(domain, i * 32);
+   gc = irq_get_domain_generic_chip(domain, i * AIC_IRQS_PER_CHIP);
 
gc->reg_base = reg_base;
 
diff --git a/drivers/irqchip/irq-atmel-aic-common.h 
b/drivers/irqchip/irq-atmel-aic-common.h
index c178557..4c0b471 100644
--- a/drivers/irqchip/irq-atmel-aic-common.h
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -16,6 +16,7 @@
 #ifndef __IRQ_ATMEL_AIC_COMMON_H
 #define __IRQ_ATMEL_AIC_COMMON_H
 
+#define AIC_IRQS_PER_CHIP  32
 
 int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val);
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 6fcd680..c499949 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -164,7 +164,7 @@ static void __init aic_hw_init(struct irq_domain *domain)
irq_reg_writel(gc, 0x, AT91_AIC_IDCR);
irq_reg_writel(gc, 0x, AT91_AIC_ICCR);
 
-   for (i = 0; i < 32; i++)
+   for (i = 0; i < NR_AIC_IRQS; i++)
irq_reg_writel(gc, i, AT91_AIC_SVR(i));
 }
 
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index 8b8f5e2..f5848c8 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -306,9 +306,9 @@ static int __init aic5_of_init(struct device_node *node,
return PTR_ERR(domain);
 
aic5_domain = domain;
-   nchips = aic5_domain->revmap_size / 32;
+   nchips = aic5_domain->revmap_size / AIC_IRQS_PER_CHIP;
for (i = 0; i < nchips; i++) {
-   gc = irq_get_domain_generic_chip(domain, i * 32);
+   gc = irq_get_domain_generic_chip(domain, i * AIC_IRQS_PER_CHIP);
 
gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
gc->chip_types[0].chip.irq_mask = aic5_mask;
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 06/19] irqchip: atmel-aic: introduce register data structure

2016-01-03 Thread Milo Kim
Structure, 'aic_reg_offset' describes for device specific register offset.
Each offset is used for IRQ chip operation. AIC and AIC5 have different
register values, but the structure can be shared.

Please note that this is not complete patch, it's a preceding step for
making unified AIC driver.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 91 ++
 1 file changed, 91 insertions(+)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 5effd52..f840165 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -24,6 +24,32 @@
 
 #include "irq-atmel-aic-common.h"
 
+#define AT91_AIC_SMR_BASE  0
+#define AT91_AIC_SVR_BASE  0x80
+#define AT91_AIC_IVR   0x100
+#define AT91_AIC_ISR   0x108
+#define AT91_AIC_IECR  0x120
+#define AT91_AIC_IDCR  0x124
+#define AT91_AIC_ICCR  0x128
+#define AT91_AIC_ISCR  0x12c
+#define AT91_AIC_EOICR 0x130
+#define AT91_AIC_SPU   0x134
+#define AT91_AIC_DCR   0x138
+#define AT91_INVALID_OFFSET(-1)
+
+#define AT91_AIC5_SSR  0x0
+#define AT91_AIC5_SMR  0x4
+#define AT91_AIC5_SVR  0x8
+#define AT91_AIC5_IVR  0x10
+#define AT91_AIC5_ISR  0x18
+#define AT91_AIC5_EOICR0x38
+#define AT91_AIC5_SPU  0x3c
+#define AT91_AIC5_IECR 0x40
+#define AT91_AIC5_IDCR 0x44
+#define AT91_AIC5_ICCR 0x48
+#define AT91_AIC5_ISCR 0x4c
+#define AT91_AIC5_DCR  0x6c
+
 #define AT91_AIC_PRIOR GENMASK(2, 0)
 #define AT91_AIC_IRQ_MIN_PRIORITY  0
 #define AT91_AIC_IRQ_MAX_PRIORITY  7
@@ -38,6 +64,71 @@ struct aic_chip_data {
u32 ext_irqs;
 };
 
+/**
+ * struct aic_reg_offset
+ *
+ * @eoi:   End of interrupt command register
+ * @smr:   Source mode register
+ * @ssr:   Source select register
+ * @iscr:  Interrupt set command register
+ * @idcr:  Interrupt disable command register
+ * @iccr:  Interrupt clear command register
+ * @iecr:  Interrupt enable command register
+ * @spu:   Spurious interrupt vector register
+ * @dcr:   Debug control register
+ * @svr:   Source vector register
+ * @ivr:   Interrupt vector register
+ * @isr:   Interrupt status register
+ *
+ * Each value means register offset.
+ */
+struct aic_reg_offset {
+   int eoi;
+   int smr;
+   int ssr;
+   int iscr;
+   int idcr;
+   int iccr;
+   int iecr;
+   int spu;
+   int dcr;
+   int svr;
+   int ivr;
+   int isr;
+};
+
+static const struct aic_reg_offset aic_regs = {
+   .eoi= AT91_AIC_EOICR,
+   .smr= AT91_AIC_SMR_BASE,
+   .ssr= AT91_INVALID_OFFSET,  /* No SSR exists */
+   .iscr   = AT91_AIC_ISCR,
+   .idcr   = AT91_AIC_IDCR,
+   .iccr   = AT91_AIC_ICCR,
+   .iecr   = AT91_AIC_IECR,
+   .spu= AT91_AIC_SPU,
+   .dcr= AT91_AIC_DCR,
+   .svr= AT91_AIC_SVR_BASE,
+   .ivr= AT91_AIC_IVR,
+   .isr= AT91_AIC_ISR,
+};
+
+static const struct aic_reg_offset aic5_regs = {
+   .eoi= AT91_AIC5_EOICR,
+   .smr= AT91_AIC5_SMR,
+   .ssr= AT91_AIC5_SSR,
+   .iscr   = AT91_AIC5_ISCR,
+   .idcr   = AT91_AIC5_IDCR,
+   .iccr   = AT91_AIC5_ICCR,
+   .iecr   = AT91_AIC5_IECR,
+   .spu= AT91_AIC5_SPU,
+   .dcr= AT91_AIC5_DCR,
+   .svr= AT91_AIC5_SVR,
+   .ivr= AT91_AIC5_IVR,
+   .isr= AT91_AIC5_ISR,
+};
+
+static const struct aic_reg_offset *aic_reg_data;
+
 static void aic_common_shutdown(struct irq_data *d)
 {
struct irq_chip_type *ct = irq_data_get_chip_type(d);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/19] irqchip: atmel-aic: add common retrigger function

2016-01-03 Thread Milo Kim
AIC has one register access to retrigger an interrupt.
AIC5 requires two register accesses - SSR and ISCR.
This patch unifies interrupt retrigger operation.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 21 +
 drivers/irqchip/irq-atmel-aic.c| 13 -
 drivers/irqchip/irq-atmel-aic5.c   | 15 ---
 3 files changed, 21 insertions(+), 28 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 533b3e9..ec93725 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -243,6 +243,26 @@ static void aic_unmask(struct irq_data *d)
irq_gc_unlock(bgc);
 }
 
+static int aic_retrigger(struct irq_data *d)
+{
+   struct irq_domain *domain = d->domain;
+   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
+
+   /* Set interrupt */
+   irq_gc_lock(bgc);
+
+   if (aic_is_ssr_used()) {
+   irq_reg_writel(bgc, d->hwirq, aic_reg_data->ssr);
+   irq_reg_writel(bgc, 1, aic_reg_data->iscr);
+   } else {
+   irq_reg_writel(bgc, d->mask, aic_reg_data->iscr);
+   }
+
+   irq_gc_unlock(bgc);
+
+   return 0;
+}
+
 int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
@@ -355,6 +375,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
gc->chip_types[0].chip.irq_mask = aic_mask;
gc->chip_types[0].chip.irq_unmask = aic_unmask;
+   gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
gc->private = [i];
}
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index df12249d..c218716 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -74,18 +74,6 @@ aic_handle(struct pt_regs *regs)
handle_domain_irq(aic_domain, irqnr, regs);
 }
 
-static int aic_retrigger(struct irq_data *d)
-{
-   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-
-   /* Enable interrupt on AIC5 */
-   irq_gc_lock(gc);
-   irq_reg_writel(gc, d->mask, AT91_AIC_ISCR);
-   irq_gc_unlock(gc);
-
-   return 0;
-}
-
 static int aic_set_type(struct irq_data *d, unsigned type)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
@@ -185,7 +173,6 @@ static int __init aic_of_init(struct device_node *node,
gc = irq_get_domain_generic_chip(domain, 0);
 
gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
-   gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
gc->chip_types[0].chip.irq_set_type = aic_set_type;
gc->chip_types[0].chip.irq_suspend = aic_suspend;
gc->chip_types[0].chip.irq_resume = aic_resume;
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index e610780..49d40b4 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -83,20 +83,6 @@ aic5_handle(struct pt_regs *regs)
handle_domain_irq(aic5_domain, irqnr, regs);
 }
 
-static int aic5_retrigger(struct irq_data *d)
-{
-   struct irq_domain *domain = d->domain;
-   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
-
-   /* Enable interrupt on AIC5 */
-   irq_gc_lock(bgc);
-   irq_reg_writel(bgc, d->hwirq, AT91_AIC5_SSR);
-   irq_reg_writel(bgc, 1, AT91_AIC5_ISCR);
-   irq_gc_unlock(bgc);
-
-   return 0;
-}
-
 static int aic5_set_type(struct irq_data *d, unsigned type)
 {
struct irq_domain *domain = d->domain;
@@ -239,7 +225,6 @@ static int __init aic5_of_init(struct device_node *node,
gc = irq_get_domain_generic_chip(domain, i * AIC_IRQS_PER_CHIP);
 
gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
-   gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
gc->chip_types[0].chip.irq_set_type = aic5_set_type;
gc->chip_types[0].chip.irq_suspend = aic5_suspend;
gc->chip_types[0].chip.irq_resume = aic5_resume;
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 01/19] irqchip: atmel-aic: fix wrong bit operation for IRQ priority

2016-01-03 Thread Milo Kim
Atmel AIC has common structure for SMR (Source Mode Register).

  bit[6:5] Interrupt source type
  bit[2:0] Priority level
  Other bits are unused.

To update new priority value, bit[2:0] should be cleared first and then
new priority level can be written. However, aic_common_set_priority()
helper clears source type bits instead of priority bits.
This patch fixes wrong mask bit operation.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index b12a5d5..37199b9 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -86,7 +86,7 @@ int aic_common_set_priority(int priority, unsigned *val)
priority > AT91_AIC_IRQ_MAX_PRIORITY)
return -EINVAL;
 
-   *val &= AT91_AIC_PRIOR;
+   *val &= ~AT91_AIC_PRIOR;
*val |= priority;
 
return 0;
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 13/19] irqchip: atmel-aic: clean up irq_chip_generic

2016-01-03 Thread Milo Kim
Now, aic_common_of_init() handles all IRQ chip operations.
Remove unused code for getting irq_chip_generic data.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic.c  | 3 ---
 drivers/irqchip/irq-atmel-aic5.c | 8 
 2 files changed, 11 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index bab93a0..721ecb6 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -107,7 +107,6 @@ static void __init aic_hw_init(struct irq_domain *domain)
 static int __init aic_of_init(struct device_node *node,
  struct device_node *parent)
 {
-   struct irq_chip_generic *gc;
struct irq_domain *domain;
 
if (aic_domain)
@@ -118,8 +117,6 @@ static int __init aic_of_init(struct device_node *node,
return PTR_ERR(domain);
 
aic_domain = domain;
-   gc = irq_get_domain_generic_chip(domain, 0);
-
aic_hw_init(domain);
set_handle_irq(aic_handle);
 
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index b314aa4..ff487089 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -118,10 +118,7 @@ static int __init aic5_of_init(struct device_node *node,
   struct device_node *parent,
   int nirqs)
 {
-   struct irq_chip_generic *gc;
struct irq_domain *domain;
-   int nchips;
-   int i;
 
if (nirqs > NR_AIC5_IRQS)
return -EINVAL;
@@ -134,11 +131,6 @@ static int __init aic5_of_init(struct device_node *node,
return PTR_ERR(domain);
 
aic5_domain = domain;
-   nchips = aic5_domain->revmap_size / AIC_IRQS_PER_CHIP;
-   for (i = 0; i < nchips; i++) {
-   gc = irq_get_domain_generic_chip(domain, i * AIC_IRQS_PER_CHIP);
-   }
-
aic5_hw_init(domain);
set_handle_irq(aic5_handle);
 
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 18/19] irqchip: atmel-aic: use unified AIC driver

2016-01-03 Thread Milo Kim
AIC and AIC5 use same driver file, so IRQ chip specific driver files can
be deleted.
aic_common_ext_irq_of_init() is renamed as aic_ext_irq_of_init().
Fix checkpatch warning.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/Makefile   |  4 +--
 drivers/irqchip/irq-atmel-aic-common.c | 10 +++---
 drivers/irqchip/irq-atmel-aic.c| 54 
 drivers/irqchip/irq-atmel-aic5.c   | 64 --
 4 files changed, 7 insertions(+), 125 deletions(-)
 delete mode 100644 drivers/irqchip/irq-atmel-aic.c
 delete mode 100644 drivers/irqchip/irq-atmel-aic5.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 83d1fce..6e4 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -28,8 +28,8 @@ obj-$(CONFIG_ARM_GIC_V3_ITS)  += irq-gic-v3-its.o 
irq-gic-v3-its-pci-msi.o irq-g
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
 obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
 obj-$(CONFIG_ARM_VIC)  += irq-vic.o
-obj-$(CONFIG_ATMEL_AIC_IRQ)+= irq-atmel-aic-common.o 
irq-atmel-aic.o
-obj-$(CONFIG_ATMEL_AIC5_IRQ)   += irq-atmel-aic-common.o irq-atmel-aic5.o
+obj-$(CONFIG_ATMEL_AIC_IRQ)+= irq-atmel-aic-common.o
+obj-$(CONFIG_ATMEL_AIC5_IRQ)   += irq-atmel-aic-common.o
 obj-$(CONFIG_I8259)+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)   += irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o
diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index cd89d635..1d3978e 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -1,6 +1,5 @@
 /*
- * Atmel AT91 common AIC (Advanced Interrupt Controller) code shared by
- * irq-atmel-aic and irq-atmel-aic5 drivers
+ * Atmel AIC (Advanced Interrupt Controller) Driver
  *
  *  Copyright (C) 2004 SAN People
  *  Copyright (C) 2004 ATMEL
@@ -413,7 +412,8 @@ static void aic_pm_shutdown(struct irq_data *d)
if (aic_is_ssr_used()) {
irq_gc_lock(bgc);
for (i = 0; i < AIC_IRQS_PER_CHIP; i++) {
-   irq_reg_writel(bgc, i + gc->irq_base, 
aic_reg_data->ssr);
+   irq_reg_writel(bgc, i + gc->irq_base,
+  aic_reg_data->ssr);
irq_reg_writel(bgc, 1, aic_reg_data->idcr);
irq_reg_writel(bgc, 1, aic_reg_data->iccr);
}
@@ -455,7 +455,7 @@ static int __init aic_get_num_chips(struct device_node 
*node)
return DIV_ROUND_UP(nirqs, AIC_IRQS_PER_CHIP);
 }
 
-static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
+static void __init aic_ext_irq_of_init(struct irq_domain *domain)
 {
struct device_node *node = irq_domain_get_of_node(domain);
struct irq_chip_generic *gc;
@@ -587,7 +587,7 @@ static int __init aic_of_init(struct device_node *node,
}
 
aic_domain = domain;
-   aic_common_ext_irq_of_init(domain);
+   aic_ext_irq_of_init(domain);
aic_hw_init(domain);
set_handle_irq(aic_handle);
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
deleted file mode 100644
index 335a94e..000
--- a/drivers/irqchip/irq-atmel-aic.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Atmel AT91 AIC (Advanced Interrupt Controller) driver
- *
- *  Copyright (C) 2004 SAN People
- *  Copyright (C) 2004 ATMEL
- *  Copyright (C) Rick Bronson
- *  Copyright (C) 2014 Free Electrons
- *
- *  Author: Boris BREZILLON <boris.brezil...@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-/* Number of irq lines managed by AIC */
-#define NR_AIC_IRQS32
-
-#define AT91_AIC_SMR(n)((n) * 4)
-
-#define AT91_AIC_SVR(n)(0x80 + ((n) * 4))
-#define AT91_AIC_IVR   0x100
-#define AT91_AIC_FVR   0x104
-#define AT91_AIC_ISR   0x108
-
-#define AT91_AIC_IPR   0x10c
-#define AT91_AIC_IMR   0x110
-#define AT91_AIC_CISR  0x114
-
-#define AT91_A

[PATCH 19/19] irqchip: atmel-aic: rename AIC driver and fix Kconfig

2016-01-03 Thread Milo Kim
'irq-aic' is consolidated interrupt driver for Atmel SoCs.

Rename the driver file:
  irq-atmel-aic-common.c -> irq-aic.c

Kconfig:
  ATMEL_AIC5_IRQ is removed

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 arch/arm/mach-at91/Kconfig |   2 +-
 drivers/irqchip/Kconfig|   7 -
 drivers/irqchip/Makefile   |   3 +-
 drivers/irqchip/irq-aic.c  | 609 +
 drivers/irqchip/irq-atmel-aic-common.c | 609 -
 5 files changed, 611 insertions(+), 619 deletions(-)
 create mode 100644 drivers/irqchip/irq-aic.c
 delete mode 100644 drivers/irqchip/irq-atmel-aic-common.c

diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 23be2e4..315195c 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -122,7 +122,7 @@ config SOC_SAM_V7
 
 config SOC_SAMA5
bool
-   select ATMEL_AIC5_IRQ
+   select ATMEL_AIC_IRQ
select ATMEL_SDRAMC
select MEMORY
select SOC_SAM_V7
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index b5f5133..b926f79 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -67,13 +67,6 @@ config ATMEL_AIC_IRQ
select MULTI_IRQ_HANDLER
select SPARSE_IRQ
 
-config ATMEL_AIC5_IRQ
-   bool
-   select GENERIC_IRQ_CHIP
-   select IRQ_DOMAIN
-   select MULTI_IRQ_HANDLER
-   select SPARSE_IRQ
-
 config I8259
bool
select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 6e4..8d6494f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -28,8 +28,7 @@ obj-$(CONFIG_ARM_GIC_V3_ITS)  += irq-gic-v3-its.o 
irq-gic-v3-its-pci-msi.o irq-g
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
 obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
 obj-$(CONFIG_ARM_VIC)  += irq-vic.o
-obj-$(CONFIG_ATMEL_AIC_IRQ)+= irq-atmel-aic-common.o
-obj-$(CONFIG_ATMEL_AIC5_IRQ)   += irq-atmel-aic-common.o
+obj-$(CONFIG_ATMEL_AIC_IRQ)+= irq-aic.o
 obj-$(CONFIG_I8259)+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)   += irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o
diff --git a/drivers/irqchip/irq-aic.c b/drivers/irqchip/irq-aic.c
new file mode 100644
index 000..1d3978e
--- /dev/null
+++ b/drivers/irqchip/irq-aic.c
@@ -0,0 +1,609 @@
+/*
+ * Atmel AIC (Advanced Interrupt Controller) Driver
+ *
+ *  Copyright (C) 2004 SAN People
+ *  Copyright (C) 2004 ATMEL
+ *  Copyright (C) Rick Bronson
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezil...@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define AIC_IRQS_PER_CHIP  32
+#define NR_AT91RM9200_IRQS 32
+#define NR_SAMA5D2_IRQS77
+#define NR_SAMA5D3_IRQS48
+#define NR_SAMA5D4_IRQS68
+
+#define AT91_AIC_SMR_BASE  0
+#define AT91_AIC_SVR_BASE  0x80
+#define AT91_AIC_IVR   0x100
+#define AT91_AIC_ISR   0x108
+#define AT91_AIC_IECR  0x120
+#define AT91_AIC_IDCR  0x124
+#define AT91_AIC_ICCR  0x128
+#define AT91_AIC_ISCR  0x12c
+#define AT91_AIC_EOICR 0x130
+#define AT91_AIC_SPU   0x134
+#define AT91_AIC_DCR   0x138
+#define AT91_INVALID_OFFSET(-1)
+
+#define AT91_AIC5_SSR  0x0
+#define AT91_AIC5_SMR  0x4
+#define AT91_AIC5_SVR  0x8
+#define AT91_AIC5_IVR  0x10
+#define AT91_AIC5_ISR  0x18
+#define AT91_AIC5_EOICR0x38
+#define AT91_AIC5_SPU  0x3c
+#define AT91_AIC5_IECR 0x40
+#define AT91_AIC5_IDCR 0x44
+#define AT91_AIC5_ICCR 0x48
+#define AT91_AIC5_ISCR 0x4c
+#define AT91_AIC5_DCR  0x6c
+
+#define AT91_AIC_PRIOR GENMASK(2, 0)
+#define AT91_AIC_IRQ_MIN_PRIORITY  0
+#define AT91_AIC_IRQ_MAX_PRIORITY 

[PATCH 08/19] irqchip: atmel-aic: add common mask and unmask functions

2016-01-03 Thread Milo Kim
AIC has one register access to enable/disable an interrupt.
AIC5 requires two register accesses - SSR and IECR/IDCR.
This patch unifies interrupt mask and unmask operations.

Mask and unmask operations are moved into aic_common_of_init().
AIC5 can have multiple IRQ chips, mask/unmask should be assigned per chip.
In case of AIC, it's also good because AIC has one IRQ chip.
So looping count is just one time to configure mask/unmask functions.

struct irq_domain *__init aic_common_of_init(struct device_node *node,
 const char *name, int nirqs)
{
...

for (i = 0; i < nchips; i++) {
gc = irq_get_domain_generic_chip(domain, i * AIC_IRQS_PER_CHIP);

...
gc->chip_types[0].chip.irq_mask = aic_mask;
gc->chip_types[0].chip.irq_unmask = aic_unmask;
gc->private = [i];
}
}

In AIC, register configuration for enabling and disabling IRQ can be
replaced with irq_mask and irq_unmask. This is for using unified mask and
unmask functions (aic_mask and aic_unmask).

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 52 ++
 drivers/irqchip/irq-atmel-aic.c|  4 ---
 drivers/irqchip/irq-atmel-aic5.c   | 36 ---
 3 files changed, 52 insertions(+), 40 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 94c9dad..533b3e9 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -193,6 +193,56 @@ static void aic_common_shutdown(struct irq_data *d)
ct->chip.irq_mask(d);
 }
 
+static void aic_mask(struct irq_data *d)
+{
+   struct irq_domain *domain = d->domain;
+   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
+   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+   u32 mask = d->mask;
+
+   /*
+* Disable interrupt. We always take the lock of the
+* first irq chip as all chips share the same registers.
+*/
+   irq_gc_lock(bgc);
+
+   if (aic_is_ssr_used()) {
+   irq_reg_writel(gc, d->hwirq, aic_reg_data->ssr);
+   irq_reg_writel(gc, 1, aic_reg_data->idcr);
+   } else {
+   irq_reg_writel(gc, mask, aic_reg_data->idcr);
+   }
+
+   gc->mask_cache &= ~mask;
+
+   irq_gc_unlock(bgc);
+}
+
+static void aic_unmask(struct irq_data *d)
+{
+   struct irq_domain *domain = d->domain;
+   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
+   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+   u32 mask = d->mask;
+
+   /*
+* Enable interrupt. We always take the lock of the
+* first irq chip as all chips share the same registers.
+*/
+   irq_gc_lock(bgc);
+
+   if (aic_is_ssr_used()) {
+   irq_reg_writel(gc, d->hwirq, aic_reg_data->ssr);
+   irq_reg_writel(gc, 1, aic_reg_data->iecr);
+   } else {
+   irq_reg_writel(gc, mask, aic_reg_data->iecr);
+   }
+
+   gc->mask_cache |= mask;
+
+   irq_gc_unlock(bgc);
+}
+
 int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
@@ -303,6 +353,8 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
+   gc->chip_types[0].chip.irq_mask = aic_mask;
+   gc->chip_types[0].chip.irq_unmask = aic_unmask;
gc->private = [i];
}
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 46ce3ca..df12249d 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -185,10 +185,6 @@ static int __init aic_of_init(struct device_node *node,
gc = irq_get_domain_generic_chip(domain, 0);
 
gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
-   gc->chip_types[0].regs.enable = AT91_AIC_IECR;
-   gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
-   gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
-   gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_en

[PATCH 10/19] irqchip: atmel-aic: add common set_type function

2016-01-03 Thread Milo Kim
set_type() operation updates IRQ flag for selected IRQ.
By using aic_update_smr(), this operation can be unified.

Common set_type() handles interrupt type as below.
  1. Set register value corresponding to IRQ type.
  2. If SSR is used, write hwirq into SSR for IRQ selection
  3. Read value of SMR
  4. Update IRQ type into SMR

aic_update_smr() handles step 2, 3 and 4.

Please note that there are two helpers for getting IRQ chip generic data.
One is irq_data_get_irq_chip_data(d) named 'gc'.
The other is irq_get_domain_generic_chip(domain, 0) called 'bgc'.
'gc' is used for getting external IRQ configuration which is specified in
chip private data, 'aic'. Low level IRQ/falling IRQ detection is only
valid for external interrupts. So 'aic->ext_irqs' should be checked.
'bgc' is used for general operations like lock/unlocking IRQ data and
accessing AIC/AIC5 registers.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 20 
 drivers/irqchip/irq-atmel-aic-common.h |  2 --
 drivers/irqchip/irq-atmel-aic.c| 17 -
 drivers/irqchip/irq-atmel-aic5.c   | 19 ---
 4 files changed, 12 insertions(+), 46 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index ec93725..4c404f9 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -263,37 +263,40 @@ static int aic_retrigger(struct irq_data *d)
return 0;
 }
 
-int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
+static int aic_set_type(struct irq_data *d, unsigned int type)
 {
+   struct irq_domain *domain = d->domain;
+   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct aic_chip_data *aic = gc->private;
-   unsigned aic_type;
+   u32 val;
 
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
-   aic_type = AT91_AIC_SRCTYPE_HIGH;
+   val = AT91_AIC_SRCTYPE_HIGH;
break;
case IRQ_TYPE_EDGE_RISING:
-   aic_type = AT91_AIC_SRCTYPE_RISING;
+   val = AT91_AIC_SRCTYPE_RISING;
break;
case IRQ_TYPE_LEVEL_LOW:
if (!(d->mask & aic->ext_irqs))
return -EINVAL;
 
-   aic_type = AT91_AIC_SRCTYPE_LOW;
+   val = AT91_AIC_SRCTYPE_LOW;
break;
case IRQ_TYPE_EDGE_FALLING:
if (!(d->mask & aic->ext_irqs))
return -EINVAL;
 
-   aic_type = AT91_AIC_SRCTYPE_FALLING;
+   val = AT91_AIC_SRCTYPE_FALLING;
break;
default:
return -EINVAL;
}
 
-   *val &= ~AT91_AIC_SRCTYPE;
-   *val |= aic_type;
+   irq_gc_lock(bgc);
+   aic_update_smr(bgc, d->hwirq, ~AT91_AIC_SRCTYPE, val);
+   irq_gc_unlock(bgc);
 
return 0;
 }
@@ -376,6 +379,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
gc->chip_types[0].chip.irq_mask = aic_mask;
gc->chip_types[0].chip.irq_unmask = aic_unmask;
gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
+   gc->chip_types[0].chip.irq_set_type = aic_set_type;
gc->private = [i];
}
 
diff --git a/drivers/irqchip/irq-atmel-aic-common.h 
b/drivers/irqchip/irq-atmel-aic-common.h
index e068349..bf721b8 100644
--- a/drivers/irqchip/irq-atmel-aic-common.h
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -18,8 +18,6 @@
 
 #define AIC_IRQS_PER_CHIP  32
 
-int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val);
-
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
 const char *name, int nirqs);
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index c218716..9166733 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -74,22 +74,6 @@ aic_handle(struct pt_regs *regs)
handle_domain_irq(aic_domain, irqnr, regs);
 }
 
-static int aic_set_type(struct irq_data *d, unsigned type)
-{
-   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-   unsigned int smr;
-   int ret;
-
-   smr = irq_reg_readl(gc, AT91_AIC_SMR(d->hwirq));
-   ret = aic_common_set_type(d, type, )

[PATCH 03/19] irqchip: atmel-aic: clean up RTT interrupt code

2016-01-03 Thread Milo Kim
Atmel AIC disables RTT(Real Time Timer) interrupt on initialization.
Alarm interrupt(ALMIEN) and RTT increment interrupt(RTTINCIEN) are used.
However, the controller doesn't need to do it.

* RTT driver disables interrupts on _probe().
  ALMIEN and RTTINCIEN bits in RTT_MR are cleared to disable RTT
  interrupts.
  (drivers/rtc/rtc-at91sam9.c)
  /* disable all interrupts (same as on shutdown path) */
  mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
  rtt_writel(rtc, MR, mr);

* All RTT interrupts are disabled by default.
  Reset value of ALMIEN and RTTINCIEN bits are 0.
  Please note that all devices have same RTT registers.
  AT91RM9G45
  AT91SAM9RL
  AT91SAM9260
  AT91SAM9261
  AT91SAM9263
  AT91SAM9G20

So, aic_common_rtt_irq_fixup() helper can be removed.
And aic_common_irq_fixup() also can be removed because no driver
calls it any more.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 45 --
 drivers/irqchip/irq-atmel-aic-common.h |  4 ---
 drivers/irqchip/irq-atmel-aic.c| 22 -
 3 files changed, 71 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index f8261be..ef2c619 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -139,51 +139,6 @@ static void __init aic_common_ext_irq_of_init(struct 
irq_domain *domain)
}
 }
 
-#define AT91_RTT_MR0x00/* Real-time Mode 
Register */
-#define AT91_RTT_ALMIEN(1 << 16)   /* Alarm 
Interrupt Enable */
-#define AT91_RTT_RTTINCIEN (1 << 17)   /* Real Time Timer 
Increment Interrupt Enable */
-
-void __init aic_common_rtt_irq_fixup(struct device_node *root)
-{
-   struct device_node *np;
-   void __iomem *regs;
-
-   /*
-* The at91sam9263 SoC has 2 instances of the RTT block, hence we
-* iterate over the DT to find each occurrence.
-*/
-   for_each_compatible_node(np, NULL, "atmel,at91sam9260-rtt") {
-   regs = of_iomap(np, 0);
-   if (!regs)
-   continue;
-
-   writel(readl(regs + AT91_RTT_MR) &
-  ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN),
-  regs + AT91_RTT_MR);
-
-   iounmap(regs);
-   }
-}
-
-void __init aic_common_irq_fixup(const struct of_device_id *matches)
-{
-   struct device_node *root = of_find_node_by_path("/");
-   const struct of_device_id *match;
-
-   if (!root)
-   return;
-
-   match = of_match_node(matches, root);
-   of_node_put(root);
-
-   if (match) {
-   void (*fixup)(struct device_node *) = match->data;
-   fixup(root);
-   }
-
-   of_node_put(root);
-}
-
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
 const struct irq_domain_ops *ops,
 const char *name, int nirqs)
diff --git a/drivers/irqchip/irq-atmel-aic-common.h 
b/drivers/irqchip/irq-atmel-aic-common.h
index 9027f15..c178557 100644
--- a/drivers/irqchip/irq-atmel-aic-common.h
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -32,8 +32,4 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
 const struct irq_domain_ops *ops,
 const char *name, int nirqs);
 
-void __init aic_common_rtt_irq_fixup(struct device_node *root);
-
-void __init aic_common_irq_fixup(const struct of_device_id *matches);
-
 #endif /* __IRQ_ATMEL_AIC_COMMON_H */
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 4c60224..6fcd680 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -209,26 +209,6 @@ static const struct irq_domain_ops aic_irq_ops = {
.xlate  = aic_irq_domain_xlate,
 };
 
-static void __init at91sam9260_aic_irq_fixup(struct device_node *root)
-{
-   aic_common_rtt_irq_fixup(root);
-}
-
-static void __init at91sam9g45_aic_irq_fixup(struct device_node *root)
-{
-   aic_common_rtt_irq_fixup(root);
-}
-
-static const struct of_device_id aic_irq_fixups[] __initconst = {
-   { .compatible = "atmel,at91sam9g45", .data = at91sam9g45_aic_irq_fixup 
},
-   { .compatible = "atmel,at91sam9rl", .data = at91sam9g45_aic_irq_fixup },
-   { .com

[PATCH 17/19] irqchip: atmel-aic: use unified IRQ chip initialization function

2016-01-03 Thread Milo Kim
Now, AIC and AIC5 have common IRQ chip initialization function.
All IRQ chips are declared in common part.
Return type is changed from irq_domain pointer to integer.
IRQ domain name is fixed as 'atmel-aic'.
Delete irq-atmel-aic-common.h because it is not used any more.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 29 +
 drivers/irqchip/irq-atmel-aic-common.h | 22 --
 drivers/irqchip/irq-atmel-aic.c| 15 ---
 drivers/irqchip/irq-atmel-aic5.c   | 18 --
 4 files changed, 17 insertions(+), 67 deletions(-)
 delete mode 100644 drivers/irqchip/irq-atmel-aic-common.h

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index deec551..cd89d635 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -15,10 +15,14 @@
  */
 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -26,8 +30,6 @@
 #include 
 #include 
 
-#include "irq-atmel-aic-common.h"
-
 #define AIC_IRQS_PER_CHIP  32
 #define NR_AT91RM9200_IRQS 32
 #define NR_SAMA5D2_IRQS77
@@ -519,8 +521,8 @@ static void __init aic_hw_init(struct irq_domain *domain)
}
 }
 
-struct irq_domain *__init aic_common_of_init(struct device_node *node,
-const char *name)
+static int __init aic_of_init(struct device_node *node,
+ struct device_node *parent)
 {
struct irq_chip_generic *gc;
struct irq_domain *domain;
@@ -531,15 +533,15 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
int i;
 
if (aic_domain)
-   return ERR_PTR(-EEXIST);
+   return -EEXIST;
 
nchips = aic_get_num_chips(node);
if (nchips < 0)
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
 
reg_base = of_iomap(node, 0);
if (!reg_base)
-   return ERR_PTR(-ENOMEM);
+   return -ENOMEM;
 
aic = kcalloc(nchips, sizeof(*aic), GFP_KERNEL);
if (!aic) {
@@ -554,8 +556,8 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
goto err_free_aic;
}
 
-   ret = irq_alloc_domain_generic_chips(domain, AIC_IRQS_PER_CHIP, 1, name,
-handle_fasteoi_irq,
+   ret = irq_alloc_domain_generic_chips(domain, AIC_IRQS_PER_CHIP, 1,
+"atmel-aic", handle_fasteoi_irq,
 IRQ_NOREQUEST | IRQ_NOPROBE |
 IRQ_NOAUTOEN, 0, 0);
if (ret)
@@ -589,7 +591,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
aic_hw_init(domain);
set_handle_irq(aic_handle);
 
-   return domain;
+   return 0;
 
 err_domain_remove:
irq_domain_remove(domain);
@@ -599,6 +601,9 @@ err_free_aic:
 
 err_iounmap:
iounmap(reg_base);
-
-   return ERR_PTR(ret);
+   return ret;
 }
+IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init);
+IRQCHIP_DECLARE(sama5d2_aic5, "atmel,sama5d2-aic", aic_of_init);
+IRQCHIP_DECLARE(sama5d3_aic5, "atmel,sama5d3-aic", aic_of_init);
+IRQCHIP_DECLARE(sama5d4_aic5, "atmel,sama5d4-aic", aic_of_init);
diff --git a/drivers/irqchip/irq-atmel-aic-common.h 
b/drivers/irqchip/irq-atmel-aic-common.h
deleted file mode 100644
index 4170133..000
--- a/drivers/irqchip/irq-atmel-aic-common.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Atmel AT91 common AIC (Advanced Interrupt Controller) header file
- *
- *  Copyright (C) 2004 SAN People
- *  Copyright (C) 2004 ATMEL
- *  Copyright (C) Rick Bronson
- *  Copyright (C) 2014 Free Electrons
- *
- *  Author: Boris BREZILLON <boris.brezil...@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __IRQ_ATMEL_AIC_COMMON_H
-#define __IRQ_ATMEL_AIC_COMMON_H
-
-struct irq_domain *__init aic_common_of_init(struct device_node *node,
-const char *name);
-
-#endif /* __IRQ_ATMEL_AIC_COMMON_H */
diff --git a/drivers/irqc

[PATCH 16/19] irqchip: atmel-aic: get total number of IRQs from device node

2016-01-03 Thread Milo Kim
aic_common_of_init() needs an argument for number of interrupts.
Argument, 'nirqs' can be ignored if device compatible string is used.
This patch provides unified way to get total number of interrupts.
Chip specific register data is assigned as well.

Use single constant total AIC IRQ number, 'NR_AT91RM9200_IRQS'.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 38 ++
 drivers/irqchip/irq-atmel-aic-common.h |  4 +---
 drivers/irqchip/irq-atmel-aic.c|  2 +-
 drivers/irqchip/irq-atmel-aic5.c   | 37 +
 4 files changed, 41 insertions(+), 40 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 3d8cc8d..deec551 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -28,7 +28,11 @@
 
 #include "irq-atmel-aic-common.h"
 
-#define NR_AIC_IRQS32
+#define AIC_IRQS_PER_CHIP  32
+#define NR_AT91RM9200_IRQS 32
+#define NR_SAMA5D2_IRQS77
+#define NR_SAMA5D3_IRQS48
+#define NR_SAMA5D4_IRQS68
 
 #define AT91_AIC_SMR_BASE  0
 #define AT91_AIC_SVR_BASE  0x80
@@ -425,6 +429,30 @@ static void aic_pm_shutdown(struct irq_data *d)
 #define aic_pm_shutdownNULL
 #endif /* CONFIG_PM */
 
+static int __init aic_get_num_chips(struct device_node *node)
+{
+   int nirqs;
+
+   /* Get total number of IRQs and configure register data */
+   if (of_device_is_compatible(node, "atmel,at91rm9200-aic")) {
+   nirqs = NR_AT91RM9200_IRQS;
+   aic_reg_data = _regs;
+   } else if (of_device_is_compatible(node, "atmel,sama5d2-aic")) {
+   nirqs = NR_SAMA5D2_IRQS;
+   aic_reg_data = _regs;
+   } else if (of_device_is_compatible(node, "atmel,sama5d3-aic")) {
+   nirqs = NR_SAMA5D3_IRQS;
+   aic_reg_data = _regs;
+   } else if (of_device_is_compatible(node, "atmel,sama5d4-aic")) {
+   nirqs = NR_SAMA5D4_IRQS;
+   aic_reg_data = _regs;
+   } else {
+   return -EINVAL;
+   }
+
+   return DIV_ROUND_UP(nirqs, AIC_IRQS_PER_CHIP);
+}
+
 static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
 {
struct device_node *node = irq_domain_get_of_node(domain);
@@ -486,13 +514,13 @@ static void __init aic_hw_init(struct irq_domain *domain)
irq_reg_writel(gc, 0x, aic_reg_data->idcr);
irq_reg_writel(gc, 0x, aic_reg_data->iccr);
 
-   for (i = 0; i < NR_AIC_IRQS; i++)
+   for (i = 0; i < NR_AT91RM9200_IRQS; i++)
irq_reg_writel(gc, i, aic_reg_data->svr + (i * 4));
}
 }
 
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
-const char *name, int nirqs)
+const char *name)
 {
struct irq_chip_generic *gc;
struct irq_domain *domain;
@@ -505,7 +533,9 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
if (aic_domain)
return ERR_PTR(-EEXIST);
 
-   nchips = DIV_ROUND_UP(nirqs, AIC_IRQS_PER_CHIP);
+   nchips = aic_get_num_chips(node);
+   if (nchips < 0)
+   return ERR_PTR(-EINVAL);
 
reg_base = of_iomap(node, 0);
if (!reg_base)
diff --git a/drivers/irqchip/irq-atmel-aic-common.h 
b/drivers/irqchip/irq-atmel-aic-common.h
index bf721b8..4170133 100644
--- a/drivers/irqchip/irq-atmel-aic-common.h
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -16,9 +16,7 @@
 #ifndef __IRQ_ATMEL_AIC_COMMON_H
 #define __IRQ_ATMEL_AIC_COMMON_H
 
-#define AIC_IRQS_PER_CHIP  32
-
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
-const char *name, int nirqs);
+const char *name);
 
 #endif /* __IRQ_ATMEL_AIC_COMMON_H */
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 44cedce..980197f 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -60,7 +60,7 @@ static int __init aic_of_init(struct device_node *node,
 {
struct irq_domain *domain;
 
-   domain = aic_common_of_init(node, "atmel-aic&q

[PATCH 15/19] irqchip: atmel-aic: add common interrupt handler

2016-01-03 Thread Milo Kim
AIC and AIC5 have same interrupt handling process.
  1. Read IVR (Interrupt Vector Register) to get a HW IRQ number.
  2. Read ISR (Interrupt Status Register) to get current IRQ source number.
  3. Indicate the interrupt handling is complete if no interrupt condition.
 Otherwise, handle current interrupt.

With aic_reg_data configuration, two handlers can be combined.
And irq_domain also can be moved to common part.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 24 
 drivers/irqchip/irq-atmel-aic.c| 25 -
 drivers/irqchip/irq-atmel-aic5.c   | 24 
 3 files changed, 24 insertions(+), 49 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 67f9204..3d8cc8d 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -17,11 +17,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+#include 
+
 #include "irq-atmel-aic-common.h"
 
 #define NR_AIC_IRQS32
@@ -129,8 +133,23 @@ static const struct aic_reg_offset aic5_regs = {
.isr= AT91_AIC5_ISR,
 };
 
+static struct irq_domain *aic_domain;
 static const struct aic_reg_offset *aic_reg_data;
 
+static asmlinkage void __exception_irq_entry
+aic_handle(struct pt_regs *regs)
+{
+   struct irq_chip_generic *gc = irq_get_domain_generic_chip(aic_domain,
+ 0);
+   u32 hwirq = irq_reg_readl(gc, aic_reg_data->ivr);
+   u32 status = irq_reg_readl(gc, aic_reg_data->isr);
+
+   if (!status)
+   irq_reg_writel(gc, 0, aic_reg_data->eoi);
+   else
+   handle_domain_irq(aic_domain, hwirq, regs);
+}
+
 static inline bool aic_is_ssr_used(void)
 {
return aic_reg_data->ssr != AT91_INVALID_OFFSET;
@@ -483,6 +502,9 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
int ret;
int i;
 
+   if (aic_domain)
+   return ERR_PTR(-EEXIST);
+
nchips = DIV_ROUND_UP(nirqs, AIC_IRQS_PER_CHIP);
 
reg_base = of_iomap(node, 0);
@@ -532,8 +554,10 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
gc->private = [i];
}
 
+   aic_domain = domain;
aic_common_ext_irq_of_init(domain);
aic_hw_init(domain);
+   set_handle_irq(aic_handle);
 
return domain;
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index ef2cfb8..44cedce 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -55,40 +55,15 @@
 #define AT91_AIC_SPU   0x134
 #define AT91_AIC_DCR   0x138
 
-static struct irq_domain *aic_domain;
-
-static asmlinkage void __exception_irq_entry
-aic_handle(struct pt_regs *regs)
-{
-   struct irq_domain_chip_generic *dgc = aic_domain->gc;
-   struct irq_chip_generic *gc = dgc->gc[0];
-   u32 irqnr;
-   u32 irqstat;
-
-   irqnr = irq_reg_readl(gc, AT91_AIC_IVR);
-   irqstat = irq_reg_readl(gc, AT91_AIC_ISR);
-
-   if (!irqstat)
-   irq_reg_writel(gc, 0, AT91_AIC_EOICR);
-   else
-   handle_domain_irq(aic_domain, irqnr, regs);
-}
-
 static int __init aic_of_init(struct device_node *node,
  struct device_node *parent)
 {
struct irq_domain *domain;
 
-   if (aic_domain)
-   return -EEXIST;
-
domain = aic_common_of_init(node, "atmel-aic", NR_AIC_IRQS);
if (IS_ERR(domain))
return PTR_ERR(domain);
 
-   aic_domain = domain;
-   set_handle_irq(aic_handle);
-
return 0;
 }
 IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init);
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index 4551bf6..d09cefe 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -65,24 +65,6 @@
 #define AT91_AIC5_FFDR 0x54
 #define AT91_AIC5_FFSR 0x58
 
-static struct irq_domain *aic5_domain;
-
-static asmlinkage void __exception_irq_entry
-aic5_handle(struct pt_regs *regs)
-{
-   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(aic5_domain, 
0);
-   u32 irqnr;
-   u32 irqstat;
-
-   irqnr = irq_reg_readl(bgc, AT91_AIC5_IVR);
-   irqs

[PATCH 14/19] irqchip: atmel-aic: add common HW init function

2016-01-03 Thread Milo Kim
AIC and AIC5 have common interrupt initialization process.
With aic_reg_data configuration, chip specific init functions can be
combined into one function, aic_common_hw_init().

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 42 ++
 drivers/irqchip/irq-atmel-aic.c| 31 -
 drivers/irqchip/irq-atmel-aic5.c   | 32 --
 3 files changed, 42 insertions(+), 63 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 777cf33..67f9204 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -24,6 +24,8 @@
 
 #include "irq-atmel-aic-common.h"
 
+#define NR_AIC_IRQS32
+
 #define AT91_AIC_SMR_BASE  0
 #define AT91_AIC_SVR_BASE  0x80
 #define AT91_AIC_IVR   0x100
@@ -431,6 +433,45 @@ static void __init aic_common_ext_irq_of_init(struct 
irq_domain *domain)
}
 }
 
+static void __init aic_hw_init(struct irq_domain *domain)
+{
+   struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+   int i;
+
+   /*
+* Perform 8 End Of Interrupt Command to make sure AIC
+* will not Lock out nIRQ
+*/
+   for (i = 0; i < 8; i++)
+   irq_reg_writel(gc, 0, aic_reg_data->eoi);
+
+   /*
+* Spurious Interrupt ID in Spurious Vector Register.
+* When there is no current interrupt, the IRQ Vector Register
+* reads the value stored in AIC_SPU
+*/
+   irq_reg_writel(gc, 0x, aic_reg_data->spu);
+
+   /* No debugging in AIC: Debug (Protect) Control Register */
+   irq_reg_writel(gc, 0, aic_reg_data->dcr);
+
+   /* Disable and clear all interrupts initially */
+   if (aic_is_ssr_used()) {
+   for (i = 0; i < domain->revmap_size; i++) {
+   irq_reg_writel(gc, i, aic_reg_data->ssr);
+   irq_reg_writel(gc, i, aic_reg_data->svr);
+   irq_reg_writel(gc, 1, aic_reg_data->idcr);
+   irq_reg_writel(gc, 1, aic_reg_data->iccr);
+   }
+   } else {
+   irq_reg_writel(gc, 0x, aic_reg_data->idcr);
+   irq_reg_writel(gc, 0x, aic_reg_data->iccr);
+
+   for (i = 0; i < NR_AIC_IRQS; i++)
+   irq_reg_writel(gc, i, aic_reg_data->svr + (i * 4));
+   }
+}
+
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
 const char *name, int nirqs)
 {
@@ -492,6 +533,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
}
 
aic_common_ext_irq_of_init(domain);
+   aic_hw_init(domain);
 
return domain;
 
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 721ecb6..ef2cfb8 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -74,36 +74,6 @@ aic_handle(struct pt_regs *regs)
handle_domain_irq(aic_domain, irqnr, regs);
 }
 
-static void __init aic_hw_init(struct irq_domain *domain)
-{
-   struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
-   int i;
-
-   /*
-* Perform 8 End Of Interrupt Command to make sure AIC
-* will not Lock out nIRQ
-*/
-   for (i = 0; i < 8; i++)
-   irq_reg_writel(gc, 0, AT91_AIC_EOICR);
-
-   /*
-* Spurious Interrupt ID in Spurious Vector Register.
-* When there is no current interrupt, the IRQ Vector Register
-* reads the value stored in AIC_SPU
-*/
-   irq_reg_writel(gc, 0x, AT91_AIC_SPU);
-
-   /* No debugging in AIC: Debug (Protect) Control Register */
-   irq_reg_writel(gc, 0, AT91_AIC_DCR);
-
-   /* Disable and clear all interrupts initially */
-   irq_reg_writel(gc, 0x, AT91_AIC_IDCR);
-   irq_reg_writel(gc, 0x, AT91_AIC_ICCR);
-
-   for (i = 0; i < NR_AIC_IRQS; i++)
-   irq_reg_writel(gc, i, AT91_AIC_SVR(i));
-}
-
 static int __init aic_of_init(struct device_node *node,
  struct device_node *parent)
 {
@@ -117,7 +87,6 @@ static int __init aic_of_init(struct device_node *node,
return PTR_ERR(domain);
 
aic_domain = domain;
-   aic_hw_init(domain);
set_handle_irq(

[PATCH 11/19] irqchip: atmel-aic: add common PM IRQ chip operation

2016-01-03 Thread Milo Kim
To control IDCR, IECR and ICCR, AIC5 selects the number by checking
each mask bit. AIC provides simple register access.
This patch unifies suspend/resume/pm_shutdown operation.

aic_common_shutdown() is renamed as aic_irq_shutdown() to differentiate it
from aic_pm_shutdowm().

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 113 -
 drivers/irqchip/irq-atmel-aic.c|  39 
 drivers/irqchip/irq-atmel-aic5.c   |  71 -
 3 files changed, 110 insertions(+), 113 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 4c404f9..3a723f4 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -186,7 +186,7 @@ static const struct irq_domain_ops aic_irq_ops = {
.xlate  = aic_irq_domain_xlate,
 };
 
-static void aic_common_shutdown(struct irq_data *d)
+static void aic_irq_shutdown(struct irq_data *d)
 {
struct irq_chip_type *ct = irq_data_get_chip_type(d);
 
@@ -301,6 +301,109 @@ static int aic_set_type(struct irq_data *d, unsigned int 
type)
return 0;
 }
 
+#ifdef CONFIG_PM
+
+enum aic_pm_mode {
+   AIC_PM_SUSPEND,
+   AIC_PM_RESUME,
+};
+
+static void aic_pm_ctrl_ssr(struct irq_data *d, enum aic_pm_mode mode)
+{
+   struct irq_domain *domain = d->domain;
+   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
+   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+   u32 mask;
+   u32 which;
+   int i;
+
+   if (mode == AIC_PM_SUSPEND)
+   which = gc->wake_active;
+   else
+   which = gc->mask_cache;
+
+   irq_gc_lock(bgc);
+
+   for (i = 0; i < AIC_IRQS_PER_CHIP; i++) {
+   mask = 1 << i;
+   if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+   continue;
+
+   irq_reg_writel(bgc, i + gc->irq_base, aic_reg_data->ssr);
+
+   if (mask & which)
+   irq_reg_writel(bgc, 1, aic_reg_data->iecr);
+   else
+   irq_reg_writel(bgc, 1, aic_reg_data->idcr);
+   }
+
+   irq_gc_unlock(bgc);
+}
+
+static void aic_pm_ctrl(struct irq_data *d, enum aic_pm_mode mode)
+{
+   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+   u32 mask_idcr;
+   u32 mask_iecr;
+
+   if (mode == AIC_PM_SUSPEND) {
+   mask_idcr = gc->mask_cache;
+   mask_iecr = gc->wake_active;
+   } else {
+   mask_idcr = gc->wake_active;
+   mask_iecr = gc->mask_cache;
+   }
+
+   irq_gc_lock(gc);
+   irq_reg_writel(gc, mask_idcr, aic_reg_data->idcr);
+   irq_reg_writel(gc, mask_iecr, aic_reg_data->iecr);
+   irq_gc_unlock(gc);
+}
+
+static void aic_suspend(struct irq_data *d)
+{
+   if (aic_is_ssr_used())
+   aic_pm_ctrl_ssr(d, AIC_PM_SUSPEND);
+   else
+   aic_pm_ctrl(d, AIC_PM_SUSPEND);
+}
+
+static void aic_resume(struct irq_data *d)
+{
+   if (aic_is_ssr_used())
+   aic_pm_ctrl_ssr(d, AIC_PM_RESUME);
+   else
+   aic_pm_ctrl(d, AIC_PM_RESUME);
+}
+
+static void aic_pm_shutdown(struct irq_data *d)
+{
+   struct irq_domain *domain = d->domain;
+   struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
+   struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+   int i;
+
+   if (aic_is_ssr_used()) {
+   irq_gc_lock(bgc);
+   for (i = 0; i < AIC_IRQS_PER_CHIP; i++) {
+   irq_reg_writel(bgc, i + gc->irq_base, 
aic_reg_data->ssr);
+   irq_reg_writel(bgc, 1, aic_reg_data->idcr);
+   irq_reg_writel(bgc, 1, aic_reg_data->iccr);
+   }
+   irq_gc_unlock(bgc);
+   } else {
+   irq_gc_lock(gc);
+   irq_reg_writel(gc, 0x, aic_reg_data->idcr);
+   irq_reg_writel(gc, 0x, aic_reg_data->iccr);
+   irq_gc_unlock(gc);
+   }
+}
+#else
+#define aic_suspendNULL
+#define aic_resume NULL
+#define aic_pm_shutdownNULL
+#endif /* CONFIG_PM */
+
 static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
 {
struct device_node *node = irq_domain_get_of_node(domain);
@@ -369,17 +472,21 @@ struct irq_d

[PATCH 00/19] irqchip: atmel-aic: make unified AIC driver

2016-01-03 Thread Milo Kim
This patch-set provides unified Atmel AIC (Advanced Interrupt Controller)
driver. Currently, there are two AIC drivers, AIC and AIC5.
Each driver consists of chip specific part (irq-atmel-aic.o or
irq-atmel-aic5.o) and shared code (irq-atmel-aic-common.o).
But consolidated AIC driver is just one file driver which supports both
IRQ chip systems.

How to handle two IRQ chips in one driver
-
  Structure aic_reg_offset is used for device configuration.
  AIC5 IRQ chip uses SSR (Source Select Register) to select IRQ number.
  On the other hand, AIC IRQ chip has simple register access.
  To support both IRQ chips, aic_is_ssr_used() helper is used.

Patches
---
  1 ~  5: fix IRQ priority issue, clean up RTC/RTT fixup code and etc.
  6 ~ 19: create unified IRQ chip operation with aic_reg_offset data.

Target boards
-
  Tested with two boards.
  * Arietta G25 (SoC: AT91SAM9G25)
  * Xplained board (SoC: SAMA5D3)

Number of driver files
--
  AIC:  3 (irq-atmel-aic.c, irq-atmel-aic-common.c and h)
  AIC5: 3 (irq-atmel-aic5.c, irq-atmel-aic-common.c and h)
  Consolidated AIC: 1 (irq-aic.c)

Code size
-
  AIC (irq-atmel-aic.o and irq-atmel-aic-common.o)
text   data bss dec hex filename
5137196   4533714d9 drivers/irqchip/built-in.o

  AIC5 (irq-atmel-aic5.o and irq-atmel-aic-common.o)
text   data bss dec hex filename
5548196   457481674 drivers/irqchip/built-in.o

  Consolidated AIC (irq-aic.o)
text   data bss dec hex filename
4841196   8504513b5 drivers/irqchip/built-in.o

Lines of code
-
  AIC:  597
  AIC5: 688
  Consolidated AIC: 609

Milo Kim (19):
  irqchip: atmel-aic: fix wrong bit operation for IRQ priority
  irqchip: atmel-aic: clean up RTC interrupt code
  irqchip: atmel-aic: clean up RTT interrupt code
  irqchip: atmel-aic: replace magic numbers with named constant
  irqchip: atmel-aic: use simple constant to get number of interrupts
per chip
  irqchip: atmel-aic: introduce register data structure
  irqchip: atmel-aic: make common IRQ domain translate function
  irqchip: atmel-aic: add common mask and unmask functions
  irqchip: atmel-aic: add common retrigger function
  irqchip: atmel-aic: add common set_type function
  irqchip: atmel-aic: add common PM IRQ chip operation
  irqchip: atmel-aic: use EOI register data in aic_reg_data
  irqchip: atmel-aic: clean up irq_chip_generic
  irqchip: atmel-aic: add common HW init function
  irqchip: atmel-aic: add common interrupt handler
  irqchip: atmel-aic: get total number of IRQs from device node
  irqchip: atmel-aic: use unified IRQ chip initialization function
  irqchip: atmel-aic: use unified AIC driver
  irqchip: atmel-aic: rename AIC driver and fix Kconfig

 arch/arm/mach-at91/Kconfig |   2 +-
 drivers/irqchip/Kconfig|   7 -
 drivers/irqchip/Makefile   |   3 +-
 drivers/irqchip/irq-aic.c  | 609 +
 drivers/irqchip/irq-atmel-aic-common.c | 280 ---
 drivers/irqchip/irq-atmel-aic-common.h |  41 ---
 drivers/irqchip/irq-atmel-aic.c| 276 ---
 drivers/irqchip/irq-atmel-aic5.c   | 367 
 8 files changed, 611 insertions(+), 974 deletions(-)
 create mode 100644 drivers/irqchip/irq-aic.c
 delete mode 100644 drivers/irqchip/irq-atmel-aic-common.c
 delete mode 100644 drivers/irqchip/irq-atmel-aic-common.h
 delete mode 100644 drivers/irqchip/irq-atmel-aic.c
 delete mode 100644 drivers/irqchip/irq-atmel-aic5.c

-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 02/19] irqchip: atmel-aic: clean up RTC interrupt code

2016-01-03 Thread Milo Kim
Atmel AIC disables RTC interrupt on initialization. However, the controller
doesn't need to do it. There are two reasons.

* RTC driver disables interrupts on _probe()
  RTC_IDR is set to 0x1f which means all RTC interrupts are disabled.
  (drivers/rtc/rtc-at91rm9200.c)
  at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
AT91_RTC_SECEV | AT91_RTC_TIMEV |
AT91_RTC_CALEV);

* All RTC interrupts are disabled by default.
  If we try to read RTC_IMR(interrup mask status), then read value is 0
  by default. It means all RTC interrupts are disabled by default.
  We can also check the default status in the datasheet. Please note that
  all devices have same RTC registers.
  AT91RM9200
  AT91SAM9N12
  AT91SAM9X5
  AT91SAM9G45
  AT91SAM9RL
  SAMA5D3
  SAMA5D4

So, aic_common_rtc_irq_fixup() helper can be removed.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 28 
 drivers/irqchip/irq-atmel-aic-common.h |  2 --
 drivers/irqchip/irq-atmel-aic.c|  9 -
 drivers/irqchip/irq-atmel-aic5.c   | 13 -
 4 files changed, 52 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 37199b9..f8261be 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -139,34 +139,6 @@ static void __init aic_common_ext_irq_of_init(struct 
irq_domain *domain)
}
 }
 
-#define AT91_RTC_IDR   0x24
-#define AT91_RTC_IMR   0x28
-#define AT91_RTC_IRQ_MASK  0x1f
-
-void __init aic_common_rtc_irq_fixup(struct device_node *root)
-{
-   struct device_node *np;
-   void __iomem *regs;
-
-   np = of_find_compatible_node(root, NULL, "atmel,at91rm9200-rtc");
-   if (!np)
-   np = of_find_compatible_node(root, NULL,
-"atmel,at91sam9x5-rtc");
-
-   if (!np)
-   return;
-
-   regs = of_iomap(np, 0);
-   of_node_put(np);
-
-   if (!regs)
-   return;
-
-   writel(AT91_RTC_IRQ_MASK, regs + AT91_RTC_IDR);
-
-   iounmap(regs);
-}
-
 #define AT91_RTT_MR0x00/* Real-time Mode 
Register */
 #define AT91_RTT_ALMIEN(1 << 16)   /* Alarm 
Interrupt Enable */
 #define AT91_RTT_RTTINCIEN (1 << 17)   /* Real Time Timer 
Increment Interrupt Enable */
diff --git a/drivers/irqchip/irq-atmel-aic-common.h 
b/drivers/irqchip/irq-atmel-aic-common.h
index 603f0a9..9027f15 100644
--- a/drivers/irqchip/irq-atmel-aic-common.h
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -32,8 +32,6 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
 const struct irq_domain_ops *ops,
 const char *name, int nirqs);
 
-void __init aic_common_rtc_irq_fixup(struct device_node *root);
-
 void __init aic_common_rtt_irq_fixup(struct device_node *root);
 
 void __init aic_common_irq_fixup(const struct of_device_id *matches);
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 8a0c7f2..4c60224 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -209,11 +209,6 @@ static const struct irq_domain_ops aic_irq_ops = {
.xlate  = aic_irq_domain_xlate,
 };
 
-static void __init at91rm9200_aic_irq_fixup(struct device_node *root)
-{
-   aic_common_rtc_irq_fixup(root);
-}
-
 static void __init at91sam9260_aic_irq_fixup(struct device_node *root)
 {
aic_common_rtt_irq_fixup(root);
@@ -221,16 +216,12 @@ static void __init at91sam9260_aic_irq_fixup(struct 
device_node *root)
 
 static void __init at91sam9g45_aic_irq_fixup(struct device_node *root)
 {
-   aic_common_rtc_irq_fixup(root);
aic_common_rtt_irq_fixup(root);
 }
 
 static const struct of_device_id aic_irq_fixups[] __initconst = {
-   { .compatible = "atmel,at91rm9200", .data = at91rm9200_aic_irq_fixup },
{ .compatible = "atmel,at91sam9g45", .data = at91sam9g45_aic_irq_fixup 
},
-   { .compatible = "atmel,at91sam9n12", .data = at91rm9200_aic_irq_fixup },
{ .compatible = "atmel,at91sam9rl", .data = at91sam9g45_aic_irq_fixup },
-   { .compatible = "atmel,at91sam9x5", .data = at91rm9200_aic_irq_fixup },
{ .compatible = "atmel,at91sam9260", .data = at91sam9260_aic_irq_fix

[PATCH 05/19] irqchip: atmel-aic: use simple constant to get number of interrupts per chip

2016-01-03 Thread Milo Kim
Number of interrupts per each chip is determined when IRQ controller
allocates IRQ chip by calling irq_alloc_domain_generic_chips().
This number is fixed by atmel-aic-common part. The value is 32.
So each AIC driver can use this value directly in IRQ chip operation.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic.c  | 2 +-
 drivers/irqchip/irq-atmel-aic5.c | 9 +++--
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index c499949..f2c0fd9 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -188,7 +188,7 @@ static int aic_irq_domain_xlate(struct irq_domain *d,
if (ret)
return ret;
 
-   idx = intspec[0] / dgc->irqs_per_chip;
+   idx = intspec[0] / AIC_IRQS_PER_CHIP;
if (idx >= dgc->num_chips)
return -EINVAL;
 
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index f5848c8..50d540b 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -153,14 +153,13 @@ static int aic5_set_type(struct irq_data *d, unsigned 
type)
 static void aic5_suspend(struct irq_data *d)
 {
struct irq_domain *domain = d->domain;
-   struct irq_domain_chip_generic *dgc = domain->gc;
struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
int i;
u32 mask;
 
irq_gc_lock(bgc);
-   for (i = 0; i < dgc->irqs_per_chip; i++) {
+   for (i = 0; i < AIC_IRQS_PER_CHIP; i++) {
mask = 1 << i;
if ((mask & gc->mask_cache) == (mask & gc->wake_active))
continue;
@@ -177,14 +176,13 @@ static void aic5_suspend(struct irq_data *d)
 static void aic5_resume(struct irq_data *d)
 {
struct irq_domain *domain = d->domain;
-   struct irq_domain_chip_generic *dgc = domain->gc;
struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
int i;
u32 mask;
 
irq_gc_lock(bgc);
-   for (i = 0; i < dgc->irqs_per_chip; i++) {
+   for (i = 0; i < AIC_IRQS_PER_CHIP; i++) {
mask = 1 << i;
if ((mask & gc->mask_cache) == (mask & gc->wake_active))
continue;
@@ -201,13 +199,12 @@ static void aic5_resume(struct irq_data *d)
 static void aic5_pm_shutdown(struct irq_data *d)
 {
struct irq_domain *domain = d->domain;
-   struct irq_domain_chip_generic *dgc = domain->gc;
struct irq_chip_generic *bgc = irq_get_domain_generic_chip(domain, 0);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
int i;
 
irq_gc_lock(bgc);
-   for (i = 0; i < dgc->irqs_per_chip; i++) {
+   for (i = 0; i < AIC_IRQS_PER_CHIP; i++) {
irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR);
irq_reg_writel(bgc, 1, AT91_AIC5_IDCR);
irq_reg_writel(bgc, 1, AT91_AIC5_ICCR);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 12/19] irqchip: atmel-aic: use EOI register data in aic_reg_data

2016-01-03 Thread Milo Kim
Structure 'aic_reg_data' has EOI data, chip type data can be moved to
common part.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-atmel-aic-common.c | 1 +
 drivers/irqchip/irq-atmel-aic.c| 2 --
 drivers/irqchip/irq-atmel-aic5.c   | 2 --
 3 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 3a723f4..777cf33 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -476,6 +476,7 @@ struct irq_domain *__init aic_common_of_init(struct 
device_node *node,
gc->wake_enabled = ~0;
 
gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
+   gc->chip_types[0].regs.eoi = aic_reg_data->eoi;
gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
gc->chip_types[0].chip.irq_shutdown = aic_irq_shutdown;
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
index 5f943b5..bab93a0 100644
--- a/drivers/irqchip/irq-atmel-aic.c
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -120,8 +120,6 @@ static int __init aic_of_init(struct device_node *node,
aic_domain = domain;
gc = irq_get_domain_generic_chip(domain, 0);
 
-   gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
-
aic_hw_init(domain);
set_handle_irq(aic_handle);
 
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
index ec89178..b314aa4 100644
--- a/drivers/irqchip/irq-atmel-aic5.c
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -137,8 +137,6 @@ static int __init aic5_of_init(struct device_node *node,
nchips = aic5_domain->revmap_size / AIC_IRQS_PER_CHIP;
for (i = 0; i < nchips; i++) {
gc = irq_get_domain_generic_chip(domain, i * AIC_IRQS_PER_CHIP);
-
-   gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
}
 
aic5_hw_init(domain);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 06/19] irqchip: atmel-aic: introduce register data structure

2016-01-06 Thread Milo Kim

On 01/04/2016 05:53 PM, Boris Brezillon wrote:

On Mon, 4 Jan 2016 13:28:30 +0900
Milo Kim <milo@ti.com> wrote:


Structure, 'aic_reg_offset' describes for device specific register offset.
Each offset is used for IRQ chip operation. AIC and AIC5 have different
register values, but the structure can be shared.

Please note that this is not complete patch, it's a preceding step for
making unified AIC driver.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Boris BREZILLON <boris.brezil...@free-electrons.com>
Cc: Ludovic Desroches <ludovic.desroc...@atmel.com>
Cc: Nicolas Ferre <nicolas.fe...@atmel.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
  drivers/irqchip/irq-atmel-aic-common.c | 91 ++
  1 file changed, 91 insertions(+)

diff --git a/drivers/irqchip/irq-atmel-aic-common.c 
b/drivers/irqchip/irq-atmel-aic-common.c
index 5effd52..f840165 100644
--- a/drivers/irqchip/irq-atmel-aic-common.c
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -24,6 +24,32 @@

  #include "irq-atmel-aic-common.h"

+#define AT91_AIC_SMR_BASE  0
+#define AT91_AIC_SVR_BASE  0x80
+#define AT91_AIC_IVR   0x100
+#define AT91_AIC_ISR   0x108
+#define AT91_AIC_IECR  0x120
+#define AT91_AIC_IDCR  0x124
+#define AT91_AIC_ICCR  0x128
+#define AT91_AIC_ISCR  0x12c
+#define AT91_AIC_EOICR 0x130
+#define AT91_AIC_SPU   0x134
+#define AT91_AIC_DCR   0x138
+#define AT91_INVALID_OFFSET(-1)
+
+#define AT91_AIC5_SSR  0x0
+#define AT91_AIC5_SMR  0x4
+#define AT91_AIC5_SVR  0x8
+#define AT91_AIC5_IVR  0x10
+#define AT91_AIC5_ISR  0x18
+#define AT91_AIC5_EOICR0x38
+#define AT91_AIC5_SPU  0x3c
+#define AT91_AIC5_IECR 0x40
+#define AT91_AIC5_IDCR 0x44
+#define AT91_AIC5_ICCR 0x48
+#define AT91_AIC5_ISCR 0x4c
+#define AT91_AIC5_DCR  0x6c
+
  #define AT91_AIC_PRIORGENMASK(2, 0)
  #define AT91_AIC_IRQ_MIN_PRIORITY 0
  #define AT91_AIC_IRQ_MAX_PRIORITY 7
@@ -38,6 +64,71 @@ struct aic_chip_data {
u32 ext_irqs;
  };

+/**
+ * struct aic_reg_offset
+ *
+ * @eoi:   End of interrupt command register
+ * @smr:   Source mode register
+ * @ssr:   Source select register
+ * @iscr:  Interrupt set command register
+ * @idcr:  Interrupt disable command register
+ * @iccr:  Interrupt clear command register
+ * @iecr:  Interrupt enable command register
+ * @spu:   Spurious interrupt vector register
+ * @dcr:   Debug control register
+ * @svr:   Source vector register
+ * @ivr:   Interrupt vector register
+ * @isr:   Interrupt status register
+ *
+ * Each value means register offset.
+ */
+struct aic_reg_offset {
+   int eoi;
+   int smr;
+   int ssr;
+   int iscr;
+   int idcr;
+   int iccr;
+   int iecr;
+   int spu;
+   int dcr;
+   int svr;
+   int ivr;
+   int isr;
+};
+
+static const struct aic_reg_offset aic_regs = {
+   .eoi= AT91_AIC_EOICR,
+   .smr= AT91_AIC_SMR_BASE,
+   .ssr= AT91_INVALID_OFFSET,  /* No SSR exists */
+   .iscr   = AT91_AIC_ISCR,
+   .idcr   = AT91_AIC_IDCR,
+   .iccr   = AT91_AIC_ICCR,
+   .iecr   = AT91_AIC_IECR,
+   .spu= AT91_AIC_SPU,
+   .dcr= AT91_AIC_DCR,
+   .svr= AT91_AIC_SVR_BASE,
+   .ivr= AT91_AIC_IVR,
+   .isr= AT91_AIC_ISR,
+};
+
+static const struct aic_reg_offset aic5_regs = {
+   .eoi= AT91_AIC5_EOICR,
+   .smr= AT91_AIC5_SMR,
+   .ssr= AT91_AIC5_SSR,
+   .iscr   = AT91_AIC5_ISCR,
+   .idcr   = AT91_AIC5_IDCR,
+   .iccr   = AT91_AIC5_ICCR,
+   .iecr   = AT91_AIC5_IECR,
+   .spu= AT91_AIC5_SPU,
+   .dcr= AT91_AIC5_DCR,
+   .svr= AT91_AIC5_SVR,
+   .ivr= AT91_AIC5_IVR,
+   .isr= AT91_AIC5_ISR,
+};
+
+static const struct aic_reg_offset *aic_reg_data;
+


Can we avoid adding this global variable: this information can probably
be added to the aic_chip_data struct.


Chip private data, 'aic_chip_data' is allocated per each chip. If we 
move aic_reg_data into aic_chip_data, then this data will be allocated 
in each IRQ chip data as well. Then, AIC5 will allocate several register 
data. (nchips >= 2 in AIC5)


aic = kcalloc(nchips, sizeof(*aic), GFP_KERNEL);
if (!aic) {
ret = -ENOMEM;
goto err_iounmap;
}

No need to use multiple regist

Re: [PATCH 00/19] irqchip: atmel-aic: make unified AIC driver

2016-01-05 Thread Milo Kim

Hi Boris,

Thanks a lot for your comments.

On 01/04/2016 06:02 PM, Boris Brezillon wrote:

Hi Milo,

On Mon, 4 Jan 2016 13:28:24 +0900
Milo Kim <milo@ti.com> wrote:


This patch-set provides unified Atmel AIC (Advanced Interrupt Controller)
driver. Currently, there are two AIC drivers, AIC and AIC5.
Each driver consists of chip specific part (irq-atmel-aic.o or
irq-atmel-aic5.o) and shared code (irq-atmel-aic-common.o).
But consolidated AIC driver is just one file driver which supports both
IRQ chip systems.


Sorry, but what's the real motivation behind this rework?


During my driver development on Atmel boards, I just found major 
difference between two IRQ chips is how to select HW IRQ number. Other 
parts could be merged into single driver like OMAP.






How to handle two IRQ chips in one driver
-
   Structure aic_reg_offset is used for device configuration.
   AIC5 IRQ chip uses SSR (Source Select Register) to select IRQ number.
   On the other hand, AIC IRQ chip has simple register access.
   To support both IRQ chips, aic_is_ssr_used() helper is used.

Patches
---
   1 ~  5: fix IRQ priority issue, clean up RTC/RTT fixup code and etc.


As explained in my review, those irq fixup are essential, and cannot
remove them.


My apologies for this regression. I should check your log carefully. 
Thanks for pointing this out.
I'm just thinking about boot code modification for this. How about 
supporting RTC/RTT fixup code in at91bootstrap?





   6 ~ 19: create unified IRQ chip operation with aic_reg_offset data.


I started to review those patches, but honestly I don't see the point of
this rework, since you're trying to merge drivers for 2 IPs that are
completely different from a functional POV (except for a few tiny things
like priority or irq type definition).

Before reviewing the remaining patches, I'd like to know more about your
real motivations for pushing those changes?


Yeap, thanks for your time. My idea is simple.

"Different IRQ chip operation can be consolidated if simple data 
structure is used."


If AIC and AIC5 must be separate, then I'll try to rework 
irq-atmel-common part.






Target boards
-
   Tested with two boards.
   * Arietta G25 (SoC: AT91SAM9G25)
   * Xplained board (SoC: SAMA5D3)

Number of driver files
--
   AIC:  3 (irq-atmel-aic.c, irq-atmel-aic-common.c and h)
   AIC5: 3 (irq-atmel-aic5.c, irq-atmel-aic-common.c and h)
   Consolidated AIC: 1 (irq-aic.c)

Code size
-
   AIC (irq-atmel-aic.o and irq-atmel-aic-common.o)
 text  data bss dec hex filename
 5137   196   4533714d9 drivers/irqchip/built-in.o

   AIC5 (irq-atmel-aic5.o and irq-atmel-aic-common.o)
 text  data bss dec hex filename
 5548   196   457481674 drivers/irqchip/built-in.o

   Consolidated AIC (irq-aic.o)
 text  data bss dec hex filename
 4841   196   8504513b5 drivers/irqchip/built-in.o

Lines of code
-
   AIC:  597
   AIC5: 688
   Consolidated AIC: 609



Please, redo the same thing, but after keeping the IRQ fixup stuff, and
I'm pretty sure the text section of the AIC/AIC5 and the consolidated
version will be much closer.


Let me check it later if I could have a chance to create the 2nd patch ;)

Best regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 00/19] irqchip: atmel-aic: make unified AIC driver

2016-01-05 Thread Milo Kim

Hi Nicolas,

On 01/04/2016 06:37 PM, Nicolas Ferre wrote:

Le 04/01/2016 10:02, Boris Brezillon a écrit :

Hi Milo,

On Mon, 4 Jan 2016 13:28:24 +0900
Milo Kim <milo@ti.com> wrote:


This patch-set provides unified Atmel AIC (Advanced Interrupt Controller)
driver. Currently, there are two AIC drivers, AIC and AIC5.
Each driver consists of chip specific part (irq-atmel-aic.o or
irq-atmel-aic5.o) and shared code (irq-atmel-aic-common.o).
But consolidated AIC driver is just one file driver which supports both
IRQ chip systems.


Sorry, but what's the real motivation behind this rework?


I was about to ask the same question.

I'm really sorry that you spent so much time and effort for something
that I'm absolutely against: reworking stable code that had been
maturing for years and that is now nicely stable... for no obvious reason...


That's fine. It's not a problem. I enjoyed the time :)
I was also concerning about a regression. Let me try to rework common 
part then.




So unless there is a very strong benefit, it's a pretty firm NACK for
this series. We will certainly take some time to review the bits that
can be taken further to enhance our current drivers.


Sure, I totally agree.



I also advice you to talk to us before starting such a big project and
you'll notice that we are open to changes and have many aspect that you
can work on with AT91.


I'll keep in mind. Thanks for your advice.

Best regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 0/9] Support TI LMU devices

2016-01-05 Thread Milo Kim

Hi Lee,

On 11/26/2015 03:56 PM, Milo Kim wrote:

TI Lighting Management Unit drivers support lighting devices below.

  Enable pin  Backlight  HW fault monitoring  LEDs   Regulators
  --  -  ---    
LM3532   o   o   xx x
LM3631   o   o   xx5 regulators
LM3632   o   o   xx3 regulators
LM3633   o   o   oo x
LM3695   o   o   xx x
LM3697   o   o   ox x

This patch-set consists of several parts below.

   DT bindings: Binding information for each module
   LMU MFD: Device registration and HW enable pin control
   LMU fault monitor  : HW fault monitoring for open and short circuit
   LMU backlight  : Consolidated LMU backlight driver
   LM3633 LED : LED subsystem and dimming pattern generation
supported
   LM363X regulator   : LM3631 and LM3632 regulator driver for the
display bias

Updates from v1
---
   * DT bindings
 mfd   : Describe complete DT properties.
 backlight : Move backlight properties into leds/backlight/.
 Use common LED properties like 'led-sources' and 'label'.
 hwmon : LMU fault monitoring driver is not HWMON any more.
 So related properties are moved into 'ti-lmu' binding.
 leds  : Use LED common properties like 'led-sources' and 'label'.

   * MFD
 Remove LMU helpers for I2C register access. Each driver uses regmap
 helpers instead.

   * LMU fault monitoring driver
 In v1, it was HWMON driver but HWMON subsystem maintainer suggested
 moving it into MFD because it has no sensor data like temperature or
 voltage. Device attributes were replaced with debugfs files because
 monitoring should be processed for debug purpose only.

   * Backlight
 Six separate driver code was consolidated.
 Driver control code is implemented in 'ti-lmu-backlight-core.c'.
 Device specific data is defined in 'ti-lmu-backlight-data.c'.
 194 lines are saved in v2. The text segment is decreased by removing
 duplicate instructions.

 Lines of code:
   v1: 1420 (8 files)
   v2: 1226 (3 files)

 Size:
   v1:
   text  data  bss  filename
  12202   720   40  drivers/video/backlight/built-in.o
   v2:
   text  data  bss  filename
   6883   712   41  drivers/video/backlight/built-in.o

   * LED
 Use single device attribute for LED dimming operation.
 Max brightness is determined by DT property, 'led-max-microamp'.
 Remove brightness workqueue.

   * Regulator
 Use 'of_match' in regulator_desc instead of calling of_regulator_match.
 Remove unnecessary OF device ID because MFD core registers a platform
 device based on the compatible string.

Milo Kim (9):
   Documentation: dt-bindings: mfd: add TI LMU device binding information
   Documentation: dt-bindings: leds: backlight: add TI LMU backlight
 binding information
   Documentation: dt-bindings: leds: add LM3633 LED binding information
   Documentation: dt-bindings: regulator: add LM363x regulator binding
 information
   mfd: add TI LMU driver
   mfd: add TI LMU hardware fault monitoring driver
   backlight: add TI LMU backlight driver


For patch 5,6 and 7,
I'd like to get some feedback. Thanks!


   leds: add LM3633 driver
   regulator: add LM363X driver

  .../ABI/testing/debugfs-ti-lmu-fault-monitor   |  32 +
  Documentation/ABI/testing/sysfs-class-led-lm3633   |  97 +++
  .../bindings/leds/backlight/ti-lmu-backlight.txt   |  65 ++
  .../devicetree/bindings/leds/leds-lm3633.txt   |  24 +
  Documentation/devicetree/bindings/mfd/ti-lmu.txt   | 243 ++
  .../bindings/regulator/lm363x-regulator.txt|  34 +
  drivers/leds/Kconfig   |  10 +
  drivers/leds/Makefile  |   1 +
  drivers/leds/leds-lm3633.c | 840 +
  drivers/mfd/Kconfig|  22 +
  drivers/mfd/Makefile   |   3 +
  drivers/mfd/ti-lmu-fault-monitor.c | 405 ++
  drivers/mfd/ti-lmu.c   | 259 +++
  drivers/regulator/Kconfig  |   9 +
  drivers/regulator/Makefile |   1 +
  drivers/regulator/lm363x-regulator.c   | 309 
  drivers/video/backlight/Kconfig|   7 +
  drivers/video/backlight/Makefile   |   3 +
  drivers/video/backlight/ti-lmu-backlight-core.c| 649 
  drivers/video/backlight/ti-lmu-backlight-data.c| 287 +++
  include/linux/mfd/ti-lmu-backlight.h   | 290 +++
  include

Re: [PATCH 4/6] regulator: lp872x: Add enable GPIO pin support

2015-12-29 Thread Milo Kim

Hi Paul,

On 29/12/15 20:13, Paul Kocialkowski wrote:

Hi Milo,

Le mardi 29 décembre 2015 à 09:45 +0900, Milo Kim a écrit :

Hi Paul,

On 29/12/15 07:49, Paul Kocialkowski wrote:

Hi Milo, thanks for the review,

Le lundi 28 décembre 2015 à 09:56 +0900, Milo Kim a écrit :

Hi Paul,

On 23/12/15 20:56, Mark Brown wrote:

On Wed, Dec 23, 2015 at 11:58:37AM +0100, Paul Kocialkowski wrote:


+   gpio = lp->pdata->enable_gpio;
+   if (!gpio_is_valid(gpio))
+   return 0;
+
+   /* Always set enable GPIO high. */
+   ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X 
EN");
+   if (ret) {
+   dev_err(lp->dev, "gpio request err: %d\n", ret);
+   return ret;
+   }


This isn't really adding support for the enable GPIO as the changelog
suggests, it's requesting but not managing the GPIO.  Since there is
core support for manging enable GPIOs this seems especially silly,
please tell the core about the GPIO and then it will work at runtime
too.



With reference to my previous mail, external GPIOs for LDO3 and BUCK2 in
LP8725 can be specified through regulator_config.ena_gpio. BUCK2 only
can be controlled by external pin when CONFIG pin is grounded.

Please see the description at page 5 of the datasheet.

http://www.ti.com/lit/ds/symlink/lp8725.pdf


After reading the datasheets thoroughly, it seems to me that for the
lp8720, the EN pin is used to enable the regulators output, which is a
good fit for the core regulator GPIO framework, as there is no reason to
keep it on when no regulator is in use. The serial interface is already
available when EN=0 and regulators can be configured in that state. The
lp8725 seems seems to behave the same when CONFIG=0 (the datasheet
clearly states: "CONFIG=0: EN=1 turns on outputs or standby mode if
EN=0"). On the other hand, it is indeed used as a power-on pin when
CONFIG=1.


I think it's different use case. LP8720/5 are designed for system PMU,
so some regulators are enabled by default after the device is on. EN pin
is used for turning on/off the chip. This pin does not control regulator
outputs directly. It's separate functional block in the silicon.


Well, I really don't understand why the EN pin would turn on/off the
chip. All it does it enable the regulators outputs (by entering IDLE
mode), the serial block is already available in STANDBY state.

If we want some regulators enabled at boot, the best thing to do seems
to be to request the GPIO with the GPIOF_INIT_HIGH flag, as done in e.g.
the max8952 regulator driver:

if (pdata->reg_data->constraints.boot_on)
config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;


According to MAX8952 datasheet, output regulator is enabled/disabled 
using EN pin, so ena_gpio is used correctly.
However, LP8720/5 regulators are enabled/disabled through I2C command. 
Only few regulators of LP8725 can be on/off by separate external pins. 
(B2_EN and LDO3_EN)
Please note that EN pin in LP8720/5 is not the control pin for 
enabling/disabling regulators.


Best regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] regulator: lp8788: constify regulator_ops structures

2015-12-20 Thread Milo Kim

On 20/12/15 00:43, Julia Lawall wrote:

The regulator_ops structures are never modified, so declare them as const.

Done with the help of Coccinelle.

Signed-off-by: Julia Lawall <julia.law...@lip6.fr>


Acked-by: Milo Kim <milo@ti.com>



---
  drivers/regulator/lp8788-buck.c |4 ++--
  drivers/regulator/lp8788-ldo.c  |4 ++--
  2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index a97bed9..ec46290 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -344,7 +344,7 @@ static unsigned int lp8788_buck_get_mode(struct 
regulator_dev *rdev)
REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
  }

-static struct regulator_ops lp8788_buck12_ops = {
+static const struct regulator_ops lp8788_buck12_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp8788_buck12_set_voltage_sel,
@@ -357,7 +357,7 @@ static struct regulator_ops lp8788_buck12_ops = {
.get_mode = lp8788_buck_get_mode,
  };

-static struct regulator_ops lp8788_buck34_ops = {
+static const struct regulator_ops lp8788_buck34_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 30e28b1..cbfd358 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -170,7 +170,7 @@ static int lp8788_ldo_enable_time(struct regulator_dev 
*rdev)
return ENABLE_TIME_USEC * val;
  }

-static struct regulator_ops lp8788_ldo_voltage_table_ops = {
+static const struct regulator_ops lp8788_ldo_voltage_table_ops = {
.list_voltage = regulator_list_voltage_table,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -180,7 +180,7 @@ static struct regulator_ops lp8788_ldo_voltage_table_ops = {
.enable_time = lp8788_ldo_enable_time,
  };

-static struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
+static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] irqchip: omap-intc: Remove duplicate setup for IRQ chip type handler

2015-12-21 Thread Milo Kim
Some OMAP interrupt controllers use generic level detection, so
handle_level_irq() is used as the chip type handler.
Allocated IRQ chip type handler doesn't need to set it again because
irq_alloc_domain_generic_chips() has already registered it.

Tested with BeagleBoneBlack Rev C.

Cc: Tony Lindgren <t...@atomide.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Jason Cooper <ja...@lakedaemon.net>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: linux-o...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/irqchip/irq-omap-intc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c
index 8587d0f..ed25175 100644
--- a/drivers/irqchip/irq-omap-intc.c
+++ b/drivers/irqchip/irq-omap-intc.c
@@ -207,7 +207,6 @@ static int __init omap_alloc_gc_of(struct irq_domain *d, 
void __iomem *base)
ct = gc->chip_types;
 
ct->type = IRQ_TYPE_LEVEL_MASK;
-   ct->handler = handle_level_irq;
 
ct->chip.irq_ack = omap_mask_ack_irq;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/6] regulator: lp872x: Add enable GPIO pin support

2015-12-27 Thread Milo Kim

Hi Paul,

On 23/12/15 20:56, Mark Brown wrote:

On Wed, Dec 23, 2015 at 11:58:37AM +0100, Paul Kocialkowski wrote:


+   gpio = lp->pdata->enable_gpio;
+   if (!gpio_is_valid(gpio))
+   return 0;
+
+   /* Always set enable GPIO high. */
+   ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X 
EN");
+   if (ret) {
+   dev_err(lp->dev, "gpio request err: %d\n", ret);
+   return ret;
+   }


This isn't really adding support for the enable GPIO as the changelog
suggests, it's requesting but not managing the GPIO.  Since there is
core support for manging enable GPIOs this seems especially silly,
please tell the core about the GPIO and then it will work at runtime
too.



With reference to my previous mail, external GPIOs for LDO3 and BUCK2 in 
LP8725 can be specified through regulator_config.ena_gpio. BUCK2 only 
can be controlled by external pin when CONFIG pin is grounded.


Please see the description at page 5 of the datasheet.

http://www.ti.com/lit/ds/symlink/lp8725.pdf

Best regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/6] regulator: lp872x: Add missing of_match in regulators descriptions

2015-12-27 Thread Milo Kim


On 23/12/15 19:58, Paul Kocialkowski wrote:

In order to select the regulators via of_find_regulator_by_node (and thus use
them in devicetree), defining of_match for each regulator is required.

Signed-off-by: Paul Kocialkowski <cont...@paulk.fr>


Acked-by: Milo Kim <milo@ti.com>


---
  drivers/regulator/lp872x.c | 15 +++
  1 file changed, 15 insertions(+)

diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index e5af072..9412353 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -520,6 +520,7 @@ static struct regulator_ops lp8725_buck_ops = {
  static struct regulator_desc lp8720_regulator_desc[] = {
{
.name = "ldo1",
+   .of_match = of_match_ptr("ldo1"),
.id = LP8720_ID_LDO1,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -533,6 +534,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
{
.name = "ldo2",
+   .of_match = of_match_ptr("ldo2"),
.id = LP8720_ID_LDO2,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -546,6 +548,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
{
.name = "ldo3",
+   .of_match = of_match_ptr("ldo3"),
.id = LP8720_ID_LDO3,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -559,6 +562,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
{
.name = "ldo4",
+   .of_match = of_match_ptr("ldo4"),
.id = LP8720_ID_LDO4,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
@@ -572,6 +576,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
{
.name = "ldo5",
+   .of_match = of_match_ptr("ldo5"),
.id = LP8720_ID_LDO5,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -585,6 +590,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
{
.name = "buck",
+   .of_match = of_match_ptr("buck"),
.id = LP8720_ID_BUCK,
.ops = _buck_ops,
.n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
@@ -599,6 +605,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
  static struct regulator_desc lp8725_regulator_desc[] = {
{
.name = "ldo1",
+   .of_match = of_match_ptr("ldo1"),
.id = LP8725_ID_LDO1,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -612,6 +619,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
{
.name = "ldo2",
+   .of_match = of_match_ptr("ldo2"),
.id = LP8725_ID_LDO2,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -625,6 +633,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
{
.name = "ldo3",
+   .of_match = of_match_ptr("ldo3"),
.id = LP8725_ID_LDO3,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -638,6 +647,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
{
.name = "ldo4",
+   .of_match = of_match_ptr("ldo4"),
.id = LP8725_ID_LDO4,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -651,6 +661,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
{
.name = "ldo5",
+   .of_match = of_match_ptr("ldo5"),
.id = LP8725_ID_LDO5,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
@@ -664,6 +675,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
{
.name = "lilo1",
+   .of_match = of_match_ptr("lilo1"),
.id = LP8725_ID_LILO1,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
@@ -677,6 +689,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
{
.name = "lilo2",
+   .of_match = of_match_ptr("lilo2"),
.id = LP8725_ID_LILO2,
.ops = _ldo_ops,
.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
@@ -690,6 +703,7 @@ static struct regulator_desc lp8

Re: [PATCH 2/6] regulator: lp872x: Get rid of duplicate reference to DVS GPIO

2015-12-27 Thread Milo Kim

On 23/12/15 19:58, Paul Kocialkowski wrote:

The lp872x structure holds a reference to the DVS GPIO, but it is never actually
used anywhere, since a first reference exists from the lp872x_dvs structure.

Signed-off-by: Paul Kocialkowski <cont...@paulk.fr>


Acked-by: Milo Kim <milo@ti.com>


---
  drivers/regulator/lp872x.c | 2 --
  1 file changed, 2 deletions(-)

diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 9412353..19d7584 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -108,7 +108,6 @@ struct lp872x {
struct lp872x_platform_data *pdata;
int num_regulators;
enum lp872x_dvs_state dvs_pin;
-   int dvs_gpio;
  };

  /* LP8720/LP8725 shared voltage table for LDOs */
@@ -752,7 +751,6 @@ static int lp872x_init_dvs(struct lp872x *lp)
}

lp->dvs_pin = pinstate;
-   lp->dvs_gpio = gpio;

return 0;



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/6] regulator: lp872x: Add enable GPIO pin support

2015-12-27 Thread Milo Kim

Hi Paul,

Thanks for the patches. Please see my comments below.

On 23/12/15 19:58, Paul Kocialkowski wrote:

LP872x regulators are made active via the EN pin, which might be hooked to a
GPIO. This adds support for driving the GPIO high when the driver is in use.


EN pin is used for enabling HW logic like I2C block. It's not regulator 
enable pin. Please check the block diagram in the datasheet.


All regulators of LP8720 and LP8725 are controlled through I2C 
registers. Additionally, LP8725 provides external pin control for LDO3 
and BUCK2. In this case, you can use 'regulator_config.ena_gpio' when a 
regulator is registered.




Signed-off-by: Paul Kocialkowski 
---
  .../devicetree/bindings/regulator/lp872x.txt   |  1 +
  drivers/regulator/lp872x.c | 33 --
  include/linux/regulator/lp872x.h   |  2 ++
  3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/lp872x.txt 
b/Documentation/devicetree/bindings/regulator/lp872x.txt
index 7818318..0559c25 100644
--- a/Documentation/devicetree/bindings/regulator/lp872x.txt
+++ b/Documentation/devicetree/bindings/regulator/lp872x.txt
@@ -28,6 +28,7 @@ Optional properties:
- ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x 
devices.
- ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2.
- ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH.
+  - ti,enable-gpio: GPIO specifier for EN pin control of LP872x devices.


Please use general property, "enable-gpios" instead of "ti,enable-gpio".



Sub nodes for regulator_init_data
  LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck)
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 21c49d8..c8855f3 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -726,6 +726,27 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
  };

+static int lp872x_init_enable(struct lp872x *lp)


lp872x_enable_hw() would be better.


+{
+   int ret, gpio;
+
+   if (!lp->pdata)
+   return -EINVAL;
+
+   gpio = lp->pdata->enable_gpio;
+   if (!gpio_is_valid(gpio))
+   return 0;
+
+   /* Always set enable GPIO high. */
+   ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X 
EN");
+   if (ret) {
+   dev_err(lp->dev, "gpio request err: %d\n", ret);
+   return ret;
+   }


LP8720 device needs max 200usec for startup time.
LP8725 also requires enable time about 30ms.
Please use usleep_range() after EN pin control.


+
+   return 0;
+}
+
  static int lp872x_init_dvs(struct lp872x *lp)
  {
int ret, gpio;
@@ -763,14 +784,18 @@ static int lp872x_config(struct lp872x *lp)
int ret;

if (!pdata || !pdata->update_config)
-   goto init_dvs;
+   goto init_dvs_enable;

ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
if (ret)
return ret;

-init_dvs:
-   return lp872x_init_dvs(lp);
+init_dvs_enable:
+   ret = lp872x_init_dvs(lp);
+   if (ret)
+   return ret;
+
+   return lp872x_init_enable(lp);
  }


Logic should be enabled prior to DVS configuration. And please call 
lp872x_enable_hw() in _probe().




  static struct regulator_init_data
@@ -875,6 +900,8 @@ static struct lp872x_platform_data
of_property_read_u8(np, "ti,dvs-state", _state);
pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW;

+   pdata->enable_gpio = of_get_named_gpio(np, "ti,enable-gpio", 0);
+


Please replace "ti,enable-gpio" with "enable-gpios".

Best regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/6] regulator: lp872x: Add enable GPIO pin support

2015-12-28 Thread Milo Kim

Hi Paul,

On 29/12/15 07:49, Paul Kocialkowski wrote:

Hi Milo, thanks for the review,

Le lundi 28 décembre 2015 à 09:56 +0900, Milo Kim a écrit :

Hi Paul,

On 23/12/15 20:56, Mark Brown wrote:

On Wed, Dec 23, 2015 at 11:58:37AM +0100, Paul Kocialkowski wrote:


+   gpio = lp->pdata->enable_gpio;
+   if (!gpio_is_valid(gpio))
+   return 0;
+
+   /* Always set enable GPIO high. */
+   ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X 
EN");
+   if (ret) {
+   dev_err(lp->dev, "gpio request err: %d\n", ret);
+   return ret;
+   }


This isn't really adding support for the enable GPIO as the changelog
suggests, it's requesting but not managing the GPIO.  Since there is
core support for manging enable GPIOs this seems especially silly,
please tell the core about the GPIO and then it will work at runtime
too.



With reference to my previous mail, external GPIOs for LDO3 and BUCK2 in
LP8725 can be specified through regulator_config.ena_gpio. BUCK2 only
can be controlled by external pin when CONFIG pin is grounded.

Please see the description at page 5 of the datasheet.

http://www.ti.com/lit/ds/symlink/lp8725.pdf


After reading the datasheets thoroughly, it seems to me that for the
lp8720, the EN pin is used to enable the regulators output, which is a
good fit for the core regulator GPIO framework, as there is no reason to
keep it on when no regulator is in use. The serial interface is already
available when EN=0 and regulators can be configured in that state. The
lp8725 seems seems to behave the same when CONFIG=0 (the datasheet
clearly states: "CONFIG=0: EN=1 turns on outputs or standby mode if
EN=0"). On the other hand, it is indeed used as a power-on pin when
CONFIG=1.


I think it's different use case. LP8720/5 are designed for system PMU, 
so some regulators are enabled by default after the device is on. EN pin 
is used for turning on/off the chip. This pin does not control regulator 
outputs directly. It's separate functional block in the silicon.


On the other hand, 'ena_gpio' is used for each regulator control itself.
For example, WM8994 has two LDOs which are controlled by external pins. 
LDOs are enabled/disabled through LDO1ENA and LDO2ENA pins. In this 
case, 'ena_gpio' is used.


http://www.cirrus.com/en/pubs/proDatasheet/WM8994_v4.4.pdf
(please refer to page 224 and 225)

Best regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 6/9] mfd: add TI LMU hardware fault monitoring driver

2015-11-25 Thread Milo Kim
LM3633 and LM3697 are TI LMU MFD device.
Those devices have hardware monitoring feature which detects open or
short circuit case.

Debugfs
---
  Two files are created.
open_fault:  check light output channel is open or not.
short_fault: check light output channel is shorted or not.

  The driver checks the status of backlight output channels.
  LM3633 and LM3697 have same sequence to check channels, so common
  functions are used.
  ABI/testing document is also included.

Operations
--
  Two devices have common control flow but register addresses are different.
  The structure, 'ti_lmu_reg' is used for register configuration.

Event notifier
--
  After fault monitoring is done, LMU device is reset. So backlight and
  LED device should be reinitialized. It notifies an event as soon as
  the monitoring is done. Then, LM3633 and LM3697 backlight and LED drivers
  handle this event.

Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 .../ABI/testing/debugfs-ti-lmu-fault-monitor   |  32 ++
 drivers/mfd/Kconfig|  10 +
 drivers/mfd/Makefile   |   1 +
 drivers/mfd/ti-lmu-fault-monitor.c | 405 +
 4 files changed, 448 insertions(+)
 create mode 100644 Documentation/ABI/testing/debugfs-ti-lmu-fault-monitor
 create mode 100644 drivers/mfd/ti-lmu-fault-monitor.c

diff --git a/Documentation/ABI/testing/debugfs-ti-lmu-fault-monitor 
b/Documentation/ABI/testing/debugfs-ti-lmu-fault-monitor
new file mode 100644
index 000..7e39e4a
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-ti-lmu-fault-monitor
@@ -0,0 +1,32 @@
+TI LMU (Lighting Management Unit) Fault Monitoring via the debugfs
+
+LM3633 and LM3697 support hardware fault monitoring which detects
+open or short circuit case.
+
+What:  /sys/kernel/debug/ti-lmu-fault-monitor/open_fault
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   read only
+Check whether light channel works or open circuit is detected.
+
+   Example:
+   cat /sys/kernel/debug/ti-lmu-fault-monitor/open_fault
+
+   Channel 0 works
+   Channel 1 works
+   Channel 2 is open
+
+What:  /sys/kernel/debug/ti-lmu-fault-monitor/short_fault
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   read only
+Check whether light channel works or short circuit is detected.
+
+   Example:
+   cat /sys/kernel/debug/ti-lmu-fault-monitor/short_fault
+
+   Channel 0 is shorted
+   Channel 1 works
+   Channel 2 works
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index a6aab27..e08acba 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1061,6 +1061,16 @@ config MFD_TI_LMU
  It consists of backlight, LED and regulator driver.
  It provides consistent device controls for lighting functions.
 
+config MFD_TI_LMU_FAULT_MONITOR
+   tristate "TI LMU Hardware Fault Monitoring Driver"
+   depends on MFD_TI_LMU && DEBUG_FS
+   help
+ Say Y here to include support for open and short circuit fault
+ detection of TI LMU devices.
+
+ This driver can also be built as a module. If so the module
+ will be called ti-lmu-fault-monitor.
+
 config MFD_OMAP_USB_HOST
bool "TI OMAP USBHS core and TLL driver"
depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 10e4bc2..5ddb4e6 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -112,6 +112,7 @@ obj-$(CONFIG_MFD_LP3943)+= lp3943.o
 obj-$(CONFIG_MFD_LP8788)   += lp8788.o lp8788-irq.o
 
 obj-$(CONFIG_MFD_TI_LMU)   += ti-lmu.o
+obj-$(CONFIG_MFD_TI_LMU_FAULT_MONITOR) += ti-lmu-fault-monitor.o
 
 da9055-objs:= da9055-core.o da9055-i2c.o
 obj-$(CONFIG_MFD_DA9055)   += da9055.o
diff --git a/drivers/mfd/ti-lmu-fault-monitor.c 
b/drivers/mfd/ti-lmu-fault-monitor.c
new file mode 100644
index 000..ba65c93
--- /dev/null
+++ b/drivers/mfd/ti-lmu-fault-monitor.c
@@ -0,0 +1,405 @@
+/*
+ * TI LMU (Lighting Management Unit) Hardware Fault Monitoring Driver
+ *
+ * Copyright 2015 Texas Instruments
+ *
+ * Author: Milo Kim <milo@ti.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.
+ */
+
+#include 
+#include 
+#include 
+#include 

[PATCH v2 8/9] leds: add LM3633 driver

2015-11-25 Thread Milo Kim
LM3633 LED driver supports generic LED functions and pattern generation.
Pattern is generated through the sysfs. ABI documentation is also added.

Device creation from device tree

  LED channel name, LED string usage and max current settings are
  configured inside the DT.

LED dimming pattern generation
--
  LM3633 supports programmable dimming pattern generator.
  To enable it, eight attributes are used. Sysfs ABI describes it.
  - Time domain
: 'pattern_time_delay', 'pattern_time_rise', 'pattern_time_high',
  'pattern_time_fall' and 'pattern_time_low'.
  - Level domain
: 'pattern_brightness_low' and 'pattern_brightness_high'.
  - Start or stop
: 'run_pattern'

LMU fault monitor event handling

  As soon as LMU fault monitoring is done, LMU device is reset. So LED
  device should be reinitialized. lm3633_led_fault_monitor_notifier() is
  used for this purpose.

Data structure
--
  ti_lmu_led: LED output channel data.
  ti_lmu_led_chip:LED device data. One LED device can have multiple
  LED channel data.

Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: linux-l...@vger.kernel.org 
Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Mark Brown <broo...@kernel.org>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 Documentation/ABI/testing/sysfs-class-led-lm3633 |  97 +++
 drivers/leds/Kconfig |  10 +
 drivers/leds/Makefile|   1 +
 drivers/leds/leds-lm3633.c   | 840 +++
 4 files changed, 948 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-lm3633
 create mode 100644 drivers/leds/leds-lm3633.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-lm3633 
b/Documentation/ABI/testing/sysfs-class-led-lm3633
new file mode 100644
index 000..46217d4
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-lm3633
@@ -0,0 +1,97 @@
+LM3633 LED driver generates programmable pattern via the sysfs.
+
+LED Pattern Generator Structure
+
+(3)
+  (a) --->  ___
+   /   \
+  (2) / \ (4)
+  (b) > _/   \_  ...
+   (1)   (5)
+
+ |<-   period   -> |
+
+What:  /sys/class/leds//pattern_time_delay
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern startup delay. Please refer to (1).
+Range is from 0 to 9700. Unit is millisecond.
+
+What:  /sys/class/leds//pattern_time_rise
+Date:      Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern rising dimming time. Please refer to (2).
+Range is from 0 to 16000. Unit is millisecond.
+
+What:  /sys/class/leds//pattern_time_high
+Date:      Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern high level time. Please refer to (3).
+It means how much time stays at high level.
+Range is from 0 to 9700. Unit is millisecond.
+
+What:  /sys/class/leds//pattern_time_fall
+Date:      Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern falling dimming time. Please refer to (4).
+Range is from 0 to 16000. Unit is millisecond.
+
+What:  /sys/class/leds//pattern_time_low
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern low level time. Please refer to (5).
+It means how much time stays at low level.
+Range is from 0 to 9700. Unit is millisecond.
+
+What:  /sys/class/leds//pattern_brightness_high
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern brightness value at high level.
+Please refer to (a). Range is from 0 to max brightness value.
+
+What:  /sys/class/leds//pattern_brightness_low
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <milo@ti.com>
+Description:   write only
+Set pattern brightness value at low level.
+Please refer to (b). Range is from 0 to max brightness value.
+
+What:  /sys/class/leds//run_pattern
+Date:  Dec 2015
+KernelVersion: 4.5
+Contact:   Milo Kim <

[PATCH v2 3/9] Documentation: dt-bindings: leds: add LM3633 LED binding information

2015-11-25 Thread Milo Kim
LM3633 LED device is one of TI LMU device list.

Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 .../devicetree/bindings/leds/leds-lm3633.txt   | 24 ++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-lm3633.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-lm3633.txt 
b/Documentation/devicetree/bindings/leds/leds-lm3633.txt
new file mode 100644
index 000..a553894
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lm3633.txt
@@ -0,0 +1,24 @@
+TI LMU LM3633 LED device tree bindings
+
+Required properties:
+  - compatible: "ti,lm3633-leds"
+
+Child nodes:
+  Each node matches with LED control bank.
+  Please refer to the datasheet [1].
+
+  Required properties of a child node:
+  - led-sources: List of enabled channels from 0 to 5.
+ Please refer to LED binding [2].
+
+  Optional properties of a child node:
+  - label: LED channel identification. Please refer to LED binding [2].
+  - led-max-microamp: Max current setting. Type is .
+  Unit is microampere. Range is from 5000 to 3.
+  Step is 1000. Please refer to LED binding [2].
+
+Example: Please refer to ti-lmu dt-bindings [3].
+
+[1] http://www.ti.com/product/LM3633/datasheet
+[2] ../leds/common.txt
+[2] ../mfd/ti-lmu.txt
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 9/9] regulator: add LM363X driver

2015-11-25 Thread Milo Kim
LM363X regulator driver supports LM3631 and LM3632.
LM3631 has 5 regulators. LM3632 provides 3 regulators.
One boost output and LDOs are used for the display module.
Boost voltage is configurable but always on.
Supported operations for LDOs are enabled/disabled and voltage change.

Two LDOs of LM3632 can be controlled by external pins.
Those are configured through the DT properties.

Cc: Mark Brown <broo...@kernel.org>
Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/regulator/Kconfig|   9 +
 drivers/regulator/Makefile   |   1 +
 drivers/regulator/lm363x-regulator.c | 309 +++
 3 files changed, 319 insertions(+)
 create mode 100644 drivers/regulator/lm363x-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 3e028d9..971ebfa 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -274,6 +274,15 @@ config REGULATOR_ISL6271A
help
  This driver supports ISL6271A voltage regulator chip.
 
+config REGULATOR_LM363X
+   tristate "TI LM363X voltage regulators"
+   depends on MFD_TI_LMU
+   help
+ This driver supports LM3631 and LM3632 voltage regulators for
+ the LCD bias.
+ One boost output voltage is configurable and always on.
+ Other LDOs are used for the display module.
+
 config REGULATOR_LP3971
tristate "National Semiconductors LP3971 PMIC regulator driver"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 5a963d9..21a3e67 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
+obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
 obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
diff --git a/drivers/regulator/lm363x-regulator.c 
b/drivers/regulator/lm363x-regulator.c
new file mode 100644
index 000..e1b683e
--- /dev/null
+++ b/drivers/regulator/lm363x-regulator.c
@@ -0,0 +1,309 @@
+/*
+ * TI LM363X Regulator Driver
+ *
+ * Copyright 2015 Texas Instruments
+ *
+ * Author: Milo Kim <milo@ti.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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* LM3631 */
+#define LM3631_BOOST_VSEL_MAX  0x25
+#define LM3631_LDO_VSEL_MAX0x28
+#define LM3631_CONT_VSEL_MAX   0x03
+#define LM3631_VBOOST_MIN  450
+#define LM3631_VCONT_MIN   180
+#define LM3631_VLDO_MIN400
+#define ENABLE_TIME_USEC   1000
+
+/* LM3632 */
+#define LM3632_BOOST_VSEL_MAX  0x26
+#define LM3632_LDO_VSEL_MAX0x29
+#define LM3632_VBOOST_MIN  450
+#define LM3632_VLDO_MIN400
+
+/* Common */
+#define LM363X_STEP_50mV   5
+#define LM363X_STEP_500mV  50
+
+struct lm363x_regulator {
+   struct regmap *regmap;
+   struct regulator_dev *regulator;
+};
+
+const int ldo_cont_enable_time[] = {
+   0, 2000, 5000, 1, 2, 5, 10, 20,
+};
+
+static int lm363x_regulator_enable_time(struct regulator_dev *rdev)
+{
+   struct lm363x_regulator *lm363x_regulator = rdev_get_drvdata(rdev);
+   enum lm363x_regulator_id id = rdev_get_id(rdev);
+   u8 val, addr, mask;
+
+   switch (id) {
+   case LM3631_LDO_CONT:
+   addr = LM3631_REG_ENTIME_VCONT;
+   mask = LM3631_ENTIME_CONT_MASK;
+   break;
+   case LM3631_LDO_OREF:
+   addr = LM3631_REG_ENTIME_VOREF;
+   mask = LM3631_ENTIME_MASK;
+   break;
+   case LM3631_LDO_POS:
+   addr = LM3631_REG_ENTIME_VPOS;
+   mask = LM3631_ENTIME_MASK;
+   break;
+   case LM3631_LDO_NEG:
+   addr = LM3631_REG_ENTIME_VNEG;
+   mask = LM3631_ENTIME_MASK;
+   break;
+   default:
+   return 0;
+   }
+
+   if (regmap_read(lm363x_regulator->regmap, addr, (unsigned int *)))
+   return -EINVAL;
+
+   val = (val & mask) >> LM3631_ENTIME_SHIFT;
+
+   if (id == LM3631_LDO_CONT)
+   return ldo_cont_enable_

[PATCH v2 0/9] Support TI LMU devices

2015-11-25 Thread Milo Kim
TI Lighting Management Unit drivers support lighting devices below.

 Enable pin  Backlight  HW fault monitoring  LEDs   Regulators
 --  -  ---    
LM3532   o   o   xx x
LM3631   o   o   xx5 regulators
LM3632   o   o   xx3 regulators
LM3633   o   o   oo x
LM3695   o   o   xx x
LM3697   o   o   ox x

This patch-set consists of several parts below.

  DT bindings: Binding information for each module
  LMU MFD: Device registration and HW enable pin control
  LMU fault monitor  : HW fault monitoring for open and short circuit
  LMU backlight  : Consolidated LMU backlight driver
  LM3633 LED : LED subsystem and dimming pattern generation
   supported
  LM363X regulator   : LM3631 and LM3632 regulator driver for the
   display bias

Updates from v1
---
  * DT bindings
mfd   : Describe complete DT properties.
backlight : Move backlight properties into leds/backlight/.
Use common LED properties like 'led-sources' and 'label'.
hwmon : LMU fault monitoring driver is not HWMON any more.
So related properties are moved into 'ti-lmu' binding.
leds  : Use LED common properties like 'led-sources' and 'label'.

  * MFD
Remove LMU helpers for I2C register access. Each driver uses regmap
helpers instead.

  * LMU fault monitoring driver
In v1, it was HWMON driver but HWMON subsystem maintainer suggested
moving it into MFD because it has no sensor data like temperature or
voltage. Device attributes were replaced with debugfs files because
monitoring should be processed for debug purpose only.

  * Backlight
Six separate driver code was consolidated.
Driver control code is implemented in 'ti-lmu-backlight-core.c'.
Device specific data is defined in 'ti-lmu-backlight-data.c'.
194 lines are saved in v2. The text segment is decreased by removing
duplicate instructions.

Lines of code:
  v1: 1420 (8 files)
  v2: 1226 (3 files)

Size:
  v1:
  text  data  bss  filename
 12202   720   40  drivers/video/backlight/built-in.o
  v2:
  text  data  bss  filename
  6883   712   41  drivers/video/backlight/built-in.o

  * LED
Use single device attribute for LED dimming operation.
Max brightness is determined by DT property, 'led-max-microamp'.
Remove brightness workqueue.

  * Regulator
Use 'of_match' in regulator_desc instead of calling of_regulator_match.
Remove unnecessary OF device ID because MFD core registers a platform
device based on the compatible string.

Milo Kim (9):
  Documentation: dt-bindings: mfd: add TI LMU device binding information
  Documentation: dt-bindings: leds: backlight: add TI LMU backlight
binding information
  Documentation: dt-bindings: leds: add LM3633 LED binding information
  Documentation: dt-bindings: regulator: add LM363x regulator binding
information
  mfd: add TI LMU driver
  mfd: add TI LMU hardware fault monitoring driver
  backlight: add TI LMU backlight driver
  leds: add LM3633 driver
  regulator: add LM363X driver

 .../ABI/testing/debugfs-ti-lmu-fault-monitor   |  32 +
 Documentation/ABI/testing/sysfs-class-led-lm3633   |  97 +++
 .../bindings/leds/backlight/ti-lmu-backlight.txt   |  65 ++
 .../devicetree/bindings/leds/leds-lm3633.txt   |  24 +
 Documentation/devicetree/bindings/mfd/ti-lmu.txt   | 243 ++
 .../bindings/regulator/lm363x-regulator.txt|  34 +
 drivers/leds/Kconfig   |  10 +
 drivers/leds/Makefile  |   1 +
 drivers/leds/leds-lm3633.c | 840 +
 drivers/mfd/Kconfig|  22 +
 drivers/mfd/Makefile   |   3 +
 drivers/mfd/ti-lmu-fault-monitor.c | 405 ++
 drivers/mfd/ti-lmu.c   | 259 +++
 drivers/regulator/Kconfig  |   9 +
 drivers/regulator/Makefile |   1 +
 drivers/regulator/lm363x-regulator.c   | 309 
 drivers/video/backlight/Kconfig|   7 +
 drivers/video/backlight/Makefile   |   3 +
 drivers/video/backlight/ti-lmu-backlight-core.c| 649 
 drivers/video/backlight/ti-lmu-backlight-data.c| 287 +++
 include/linux/mfd/ti-lmu-backlight.h   | 290 +++
 include/linux/mfd/ti-lmu-register.h| 280 +++
 include/linux/mfd/ti-lmu.h |  87 +++
 23 files changed, 3957 insertions(+)
 create mode 100644 Documentation/ABI

[PATCH v2 1/9] Documentation: dt-bindings: mfd: add TI LMU device binding information

2015-11-25 Thread Milo Kim
This patch describes overall binding for TI LMU MFD devices.

Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 Documentation/devicetree/bindings/mfd/ti-lmu.txt | 243 +++
 1 file changed, 243 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/ti-lmu.txt

diff --git a/Documentation/devicetree/bindings/mfd/ti-lmu.txt 
b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
new file mode 100644
index 000..c885cf8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
@@ -0,0 +1,243 @@
+TI LMU (Lighting Management Unit) device tree bindings
+
+TI LMU driver supports lighting devices below.
+
+   Name  Child nodes
+  --  -
+  LM3532   Backlight
+  LM3631   Backlight and regulator
+  LM3632   Backlight and regulator
+  LM3633   Backlight, LED and fault monitor
+  LM3695   Backlight
+  LM3697   Backlight and fault monitor
+
+Required properties:
+  - compatible: Should be one of:
+"ti,lm3532"
+"ti,lm3631"
+"ti,lm3632"
+"ti,lm3633"
+"ti,lm3695"
+"ti,lm3697"
+  - reg: I2C slave address.
+ 0x11 for LM3632
+ 0x29 for LM3631
+ 0x36 for LM3633, LM3697
+ 0x38 for LM3532
+ 0x63 for LM3695
+
+Optional property:
+  - enable-gpios: A GPIO specifier for hardware enable pin.
+
+Required node:
+  - backlight: All LMU devices have backlight child nodes.
+   For the properties, please refer to [1].
+
+Optional nodes:
+  - fault-monitor: Hardware fault monitoring driver for LM3633 and LM3697.
+Required properties:
+  - compatible: Should be one of:
+"ti,lm3633-fault-monitor"
+"ti,lm3697-fault-monitor"
+  - leds: LED properties for LM3633. Please refer to [2].
+  - regulators: Regulator properties for LM3631 and LM3632.
+Please refer to [3].
+
+[1] ../leds/backlight/ti-lmu-backlight.txt
+[2] ../leds/leds-lm3633.txt
+[3] ../regulator/lm363x-regulator.txt
+
+lm3532@38 {
+   compatible = "ti,lm3532";
+   reg = <0x38>;
+
+   enable-gpios = < 2 GPIO_ACTIVE_HIGH>;
+
+   backlight {
+   compatible = "ti,lm3532-backlight";
+
+   lcd {
+   led-sources = <0 1 2>;
+   ramp-up-msec = <30>;
+   ramp-down-msec = <0>;
+   };
+   };
+};
+
+lm3631@29 {
+   compatible = "ti,lm3631";
+   reg = <0x29>;
+
+   regulators {
+   compatible = "ti,lm363x-regulator";
+
+   vboost {
+   regulator-name = "lcd_boost";
+   regulator-min-microvolt = <450>;
+   regulator-max-microvolt = <635>;
+   regulator-always-on;
+   };
+
+   vcont {
+   regulator-name = "lcd_vcont";
+   regulator-min-microvolt = <180>;
+   regulator-max-microvolt = <330>;
+   };
+
+   voref {
+   regulator-name = "lcd_voref";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   };
+
+   vpos {
+   regulator-name = "lcd_vpos";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   regulator-boot-on;
+   };
+
+   vneg {
+   regulator-name = "lcd_vneg";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   regulator-boot-on;
+   };
+   };
+
+   backlight {
+   compatible = "ti,lm3631-backlight";
+
+   lcd_bl {
+   led-sources = <0 1>;
+   ramp-up-msec = <300>;
+   };
+   };
+};
+
+lm3632@11 {
+   compatible = "ti,lm3632";
+   reg = <0x11>;
+
+   enable-gpios = < 2 GPIO_ACTIVE_HIGH>; /* PC2 */
+
+   regulators {
+   compatible = "ti,lm363x-regulator";
+
+   ti,lcm-en1-gpio = < 0 GPIO_ACTIVE_HIGH>; /* PC0 */

[PATCH v2 5/9] mfd: add TI LMU driver

2015-11-25 Thread Milo Kim
TI LMU (Lighting Management Unit) driver supports lighting devices below.

  LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.

LMU devices have common features.
  - I2C interface for accessing device registers
  - Hardware enable pin control
  - Backlight brightness control
  - Notifier for hardware fault monitoring
  - Regulators for LCD display bias

It contains fault monitor, backlight, LED and regulator driver.

LMU fault monitor
-
  LM3633 and LM3697 provide hardware monitoring feature.
  It enables open or short circuit detection.
  After monitoring is done, each device should be re-initialized.
  Notifier is used for this case.
  Please refer to separate patch for 'ti-lmu-fault-monitor'.

Backlight
-
  It's handled by TI LMU backlight consolidated driver and
  chip dependent data. Please refer to separate patches for
  'ti-lmu-backlight'.

LED indicator
-
  LM3633 has 6 indicator LEDs. Programmable dimming pattern is also
  supported. Please refer to separate patch for 'leds-lm3633'.

Regulator
-
  LM3631 has 5 regulators for the display bias.
  LM3632 supports 3 regulators. One consolidated driver enables it.
  Please refer to separate patch for 'lm363x-regulator'.

Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/mfd/Kconfig |  12 ++
 drivers/mfd/Makefile|   2 +
 drivers/mfd/ti-lmu.c| 259 +
 include/linux/mfd/ti-lmu-register.h | 280 
 include/linux/mfd/ti-lmu.h  |  87 +++
 5 files changed, 640 insertions(+)
 create mode 100644 drivers/mfd/ti-lmu.c
 create mode 100644 include/linux/mfd/ti-lmu-register.h
 create mode 100644 include/linux/mfd/ti-lmu.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4d92df6..a6aab27 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1049,6 +1049,18 @@ config MFD_LP8788
  TI LP8788 PMU supports regulators, battery charger, RTC,
  ADC, backlight driver and current sinks.
 
+config MFD_TI_LMU
+   tristate "TI Lighting Management Unit driver"
+   depends on I2C
+   select MFD_CORE
+   select REGMAP_I2C
+   help
+ Say yes here to enable support for TI LMU chips.
+
+ TI LMU MFD supports LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.
+ It consists of backlight, LED and regulator driver.
+ It provides consistent device controls for lighting functions.
+
 config MFD_OMAP_USB_HOST
bool "TI OMAP USBHS core and TLL driver"
depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a8b76b8..10e4bc2 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -111,6 +111,8 @@ obj-$(CONFIG_MFD_AXP20X)+= axp20x.o
 obj-$(CONFIG_MFD_LP3943)   += lp3943.o
 obj-$(CONFIG_MFD_LP8788)   += lp8788.o lp8788-irq.o
 
+obj-$(CONFIG_MFD_TI_LMU)   += ti-lmu.o
+
 da9055-objs:= da9055-core.o da9055-i2c.o
 obj-$(CONFIG_MFD_DA9055)   += da9055.o
 obj-$(CONFIG_MFD_DA9062)   += da9062-core.o
diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c
new file mode 100644
index 000..aeb1e7d
--- /dev/null
+++ b/drivers/mfd/ti-lmu.c
@@ -0,0 +1,259 @@
+/*
+ * TI LMU (Lighting Management Unit) Core Driver
+ *
+ * Copyright 2015 Texas Instruments
+ *
+ * Author: Milo Kim <milo@ti.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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ti_lmu_data {
+   struct mfd_cell *cells;
+   int num_cells;
+   unsigned int max_register;
+};
+
+static int ti_lmu_enable_hw(struct ti_lmu *lmu, enum ti_lmu_id id)
+{
+   int ret;
+
+   if (gpio_is_valid(lmu->en_gpio)) {
+   ret = devm_gpio_request_one(lmu->dev, lmu->en_gpio,
+   GPIOF_OUT_INIT_HIGH, "lmu_hwen");
+   if (ret) {
+   dev_err(lmu->dev, "Can not request enable GPIO: %d\n",
+   ret);
+   return ret;
+   }
+   }
+
+   /* Delay about 1ms after HW enable pin control */
+   usleep_range(1000, 1500);
+
+   /* LM3631 has additional power up sequence - enable LCD_EN bit. */
+   if (id == LM3631) {
+   return regmap_update_bits(lmu-&

[PATCH v2 4/9] Documentation: dt-bindings: regulator: add LM363x regulator binding information

2015-11-25 Thread Milo Kim
This binding describes LM3631 and LM3632 regulator properties.

Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 .../bindings/regulator/lm363x-regulator.txt| 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/regulator/lm363x-regulator.txt

diff --git a/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt 
b/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
new file mode 100644
index 000..8f14df9
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
@@ -0,0 +1,34 @@
+TI LMU LM363x regulator device tree bindings
+
+LM363x regulator driver supports LM3631 and LM3632.
+LM3631 has five regulators and LM3632 supports three regulators.
+
+Required property:
+  - compatible: "ti,lm363x-regulator"
+
+Optional properties:
+  LM3632 has external enable pins for two LDOs.
+  - ti,lcm-en1-gpio: A GPIO specifier for Vpos control pin.
+  - ti,lcm-en2-gpio: A GPIO specifier for Vneg control pin.
+
+Child nodes:
+  LM3631
+  - vboost
+  - vcont
+  - voref
+  - vpos
+  - vneg
+
+  LM3632
+  - vboost
+  - vpos
+  - vneg
+
+  Optional properties of a child node:
+  Each sub-node should contain the constraints and initialization.
+  Please refer to [1].
+
+Examples: Please refer to ti-lmu dt-bindings [2].
+
+[1] ../regulator/regulator.txt
+[2] ../mfd/ti-lmu.txt
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 7/9] backlight: add TI LMU backlight driver

2015-11-25 Thread Milo Kim
This is consolidated driver which supports backlight devices below.
  LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.

Structure
-
  It consists of two parts - core and data.

  Core part supports features below.
- Backlight subsystem control
- Channel configuration from DT properties
- Light dimming effect control: ramp up and down.
- LMU fault monitor notifier handling
- PWM brightness control

  Data part describes device specific data.
- Register value configuration for each LMU device
  : initialization, channel configuration, control mode, enable and
brightness.
- PWM action configuration
- Light dimming effect table
- Option for LMU fault monitor support

Macros for register data

  All LMU devices have 8-bit based registers. LMU_BL_REG() creates 24-bit
  register value in data part. It consists of address, mask and value.
  On the other hand, register value should be parsed when the driver
  reads/writes data from/to I2C registers. Driver uses LMU_BL_GET_ADDR(),
  LMU_BL_GET_MASK() and LMU_BL_GET_VAL() for this purpose.

Data structure
--
  ti_lmu_bl: Backlight output channel data
  ti_lmu_bl_chip:Backlight device data. One device can have multiple
 backlight channel data.
  ti_lmu_bl_reg: Backlight device register data
  ti_lmu_bl_cfg: Backlight configuration data for each LMU device

Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/video/backlight/Kconfig |   7 +
 drivers/video/backlight/Makefile|   3 +
 drivers/video/backlight/ti-lmu-backlight-core.c | 649 
 drivers/video/backlight/ti-lmu-backlight-data.c | 287 +++
 include/linux/mfd/ti-lmu-backlight.h| 290 +++
 5 files changed, 1236 insertions(+)
 create mode 100644 drivers/video/backlight/ti-lmu-backlight-core.c
 create mode 100644 drivers/video/backlight/ti-lmu-backlight-data.c
 create mode 100644 include/linux/mfd/ti-lmu-backlight.h

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 5ffa4b4..451d043 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -427,6 +427,13 @@ config BACKLIGHT_SKY81452
  To compile this driver as a module, choose M here: the module will
  be called sky81452-backlight
 
+config BACKLIGHT_TI_LMU
+   tristate "Backlight driver for TI LMU"
+   depends on BACKLIGHT_CLASS_DEVICE && MFD_TI_LMU
+   help
+ Say Y to enable the backlight driver for TI LMU devices.
+ This supports LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.
+
 config BACKLIGHT_TPS65217
tristate "TPS65217 Backlight"
depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 16ec534..0f74ce7 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -52,6 +52,9 @@ obj-$(CONFIG_BACKLIGHT_PM8941_WLED)   += pm8941-wled.o
 obj-$(CONFIG_BACKLIGHT_PWM)+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_SKY81452)   += sky81452-backlight.o
+ti-lmu-backlight-objs  := ti-lmu-backlight-core.o \
+  ti-lmu-backlight-data.o
+obj-$(CONFIG_BACKLIGHT_TI_LMU) += ti-lmu-backlight.o
 obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217)   += tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
diff --git a/drivers/video/backlight/ti-lmu-backlight-core.c 
b/drivers/video/backlight/ti-lmu-backlight-core.c
new file mode 100644
index 000..838e2c2
--- /dev/null
+++ b/drivers/video/backlight/ti-lmu-backlight-core.c
@@ -0,0 +1,649 @@
+/*
+ * TI LMU (Lighting Management Unit) Backlight Driver
+ *
+ * Copyright 2015 Texas Instruments
+ *
+ * Author: Milo Kim <milo@ti.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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NUM_DUAL_CHANNEL   2
+#define LMU_BACKLIGHT_DUAL_CHANNEL_USED(BIT(0) | BIT(1))
+#define LMU_BACKLIGHT_11BIT_LSB_MASK   (BIT(0) | BIT(1) | BIT(2))
+#define LMU_BACKLIGHT_11BIT_MSB_SHIFT  3
+#define DEFAULT_PWM_NAME   "lmu-backligh

[PATCH v2 2/9] Documentation: dt-bindings: leds: backlight: add TI LMU backlight binding information

2015-11-25 Thread Milo Kim
LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697 use common dt-bindings
for describing backlight device.

Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: Lee Jones <lee.jo...@linaro.org> 
Cc: Jacek Anaszewski <j.anaszew...@samsung.com>
Cc: Mark Brown <broo...@kernel.org>
Cc: linux-l...@vger.kernel.org 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <milo@ti.com>
---
 .../bindings/leds/backlight/ti-lmu-backlight.txt   | 65 ++
 1 file changed, 65 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt

diff --git 
a/Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt 
b/Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt
new file mode 100644
index 000..c2c35b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt
@@ -0,0 +1,65 @@
+TI LMU backlight device tree bindings
+
+Required property:
+  - compatible: Should be one of:
+"ti,lm3532-backlight"
+"ti,lm3631-backlight"
+"ti,lm3632-backlight"
+"ti,lm3633-backlight"
+"ti,lm3695-backlight"
+"ti,lm3697-backlight"
+
+Optional properties:
+  There are two backlight control mode. One is I2C, the other is PWM mode.
+  Following properties are only specified in PWM mode.
+  Please note that LMU backlight device can have only one PWM channel.
+
+  - pwms: OF device-tree PWM specification.
+  - pwm-names: a list of names for the PWM devices specified in the "pwms"
+   property.
+
+  For the PWM user nodes, please refer to [1].
+
+Child nodes:
+  LMU backlight is represented as sub-nodes of the TI LMU device [2].
+  So, LMU backlight should have more than one backlight child node.
+  Each node exactly matches with backlight control bank configuration.
+  Maximum numbers of child nodes depend on the device.
+  1 = LM3631, LM3632, LM3695
+  2 = LM3633, LM3697
+  3 = LM3532
+
+  Required property of a child node:
+  - led-sources: List of enabled channels from 0 to 2.
+ Please refer to LED binding [3].
+ For output channels, please refer to the datasheets [4].
+
+  Optional properties of a child node:
+  - label: Backlight channel identification.
+   Please refer to LED binding [3].
+  - default-brightness-level: Backlight initial brightness value.
+  Type is . It is set as soon as backlight
+  device is created.
+  0 ~ 2047 = LM3631, LM3632, LM3633, LM3695 and
+ LM3697
+  0 ~ 255  = LM3532
+  - ramp-up-msec, ramp-down-msec: Light dimming effect properties.
+  Type is . Unit is millisecond.
+  0 ~ 65 msec= LM3532
+  0 ~ 4000 msec  = LM3631
+  0 ~ 16000 msec = LM3633 and LM3697
+  - pwm-period: PWM period. Only valid in PWM brightness mode.
+Type is . If this property is missing, then control
+mode is set to I2C by default.
+
+Examples: Please refer to ti-lmu dt-bindings. [2].
+
+[1] ../pwm/pwm.txt
+[2] ../mfd/ti-lmu.txt
+[3] ../leds/common.txt
+[4] LM3532: http://www.ti.com/product/LM3532/datasheet
+LM3631: http://www.ti.com/product/LM3631/datasheet
+LM3632: http://www.ti.com/product/LM3632A/datasheet
+LM3633: http://www.ti.com/product/LM3633/datasheet
+LM3695: Datasheet is not opened yet, but only two strings are used.
+LM3697: http://www.ti.com/product/LM3697/datasheet
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] leds: turn off the LED and wait for completion on unregistering LED class device

2015-11-20 Thread Milo Kim
Workqueue, 'set_brightness_work' is used for scheduling brightness control.
This workqueue is canceled when the LED class device is unregistered.
Currently, LED subsystem handles like below.

  cancel_work_sync(_cdev->set_brightness_work)
  led_set_brightness(led_cdev, LED_OFF)

However, this could be a problem.
Workqueue is going to be canceled but LED device needs to be off.
The worst case is null pointer access due to scheduling a workqueue.

LED module is loaded.
  LED driver private data is allocated by using devm_zalloc().

LED module is unloaded.
  led_classdev_unregister() is called.
cancel_work_sync()
  led_set_brightness(led_cdev, LED_OFF)
schedule_work() if LED driver uses brightness_set_blocking()
In the meantime, driver private data will be freed.

..scheduling..

brightness_set_blocking() callback is invoked.
  For the brightness control, LED driver tries to access private
  data but resource is removed!

To avoid this problem, LED subsystem should turn off the brightness first
and wait for completion.

  led_set_brightness(led_cdev, LED_OFF)
  flush_work(_cdev->set_brightness_work)

It guarantees that LED driver turns off the brightness prior to
resource management.

Cc: linux-l...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org 
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/leds/led-class.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index d946991..14139c3 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -245,12 +245,13 @@ void led_classdev_unregister(struct led_classdev 
*led_cdev)
up_write(_cdev->trigger_lock);
 #endif
 
-   cancel_work_sync(_cdev->set_brightness_work);
-
/* Stop blinking */
led_stop_software_blink(led_cdev);
+
led_set_brightness(led_cdev, LED_OFF);
 
+   flush_work(_cdev->set_brightness_work);
+
device_unregister(led_cdev->dev);
 
down_write(_list_lock);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] Documentation: dt-bindings: mfd: add TI LMU device binding information

2017-02-27 Thread Milo Kim
This patch describes overall binding for TI LMU MFD devices.

Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Rob Herring <robh...@kernel.org>
Signed-off-by: Milo Kim <milo@ti.com>
---
 Documentation/devicetree/bindings/mfd/ti-lmu.txt | 243 +++
 1 file changed, 243 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/ti-lmu.txt

diff --git a/Documentation/devicetree/bindings/mfd/ti-lmu.txt 
b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
new file mode 100644
index ..c885cf89b8ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
@@ -0,0 +1,243 @@
+TI LMU (Lighting Management Unit) device tree bindings
+
+TI LMU driver supports lighting devices below.
+
+   Name  Child nodes
+  --  -
+  LM3532   Backlight
+  LM3631   Backlight and regulator
+  LM3632   Backlight and regulator
+  LM3633   Backlight, LED and fault monitor
+  LM3695   Backlight
+  LM3697   Backlight and fault monitor
+
+Required properties:
+  - compatible: Should be one of:
+"ti,lm3532"
+"ti,lm3631"
+"ti,lm3632"
+"ti,lm3633"
+"ti,lm3695"
+"ti,lm3697"
+  - reg: I2C slave address.
+ 0x11 for LM3632
+ 0x29 for LM3631
+ 0x36 for LM3633, LM3697
+ 0x38 for LM3532
+ 0x63 for LM3695
+
+Optional property:
+  - enable-gpios: A GPIO specifier for hardware enable pin.
+
+Required node:
+  - backlight: All LMU devices have backlight child nodes.
+   For the properties, please refer to [1].
+
+Optional nodes:
+  - fault-monitor: Hardware fault monitoring driver for LM3633 and LM3697.
+Required properties:
+  - compatible: Should be one of:
+"ti,lm3633-fault-monitor"
+"ti,lm3697-fault-monitor"
+  - leds: LED properties for LM3633. Please refer to [2].
+  - regulators: Regulator properties for LM3631 and LM3632.
+Please refer to [3].
+
+[1] ../leds/backlight/ti-lmu-backlight.txt
+[2] ../leds/leds-lm3633.txt
+[3] ../regulator/lm363x-regulator.txt
+
+lm3532@38 {
+   compatible = "ti,lm3532";
+   reg = <0x38>;
+
+   enable-gpios = < 2 GPIO_ACTIVE_HIGH>;
+
+   backlight {
+   compatible = "ti,lm3532-backlight";
+
+   lcd {
+   led-sources = <0 1 2>;
+   ramp-up-msec = <30>;
+   ramp-down-msec = <0>;
+   };
+   };
+};
+
+lm3631@29 {
+   compatible = "ti,lm3631";
+   reg = <0x29>;
+
+   regulators {
+   compatible = "ti,lm363x-regulator";
+
+   vboost {
+   regulator-name = "lcd_boost";
+   regulator-min-microvolt = <450>;
+   regulator-max-microvolt = <635>;
+   regulator-always-on;
+   };
+
+   vcont {
+   regulator-name = "lcd_vcont";
+   regulator-min-microvolt = <180>;
+   regulator-max-microvolt = <330>;
+   };
+
+   voref {
+   regulator-name = "lcd_voref";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   };
+
+   vpos {
+   regulator-name = "lcd_vpos";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   regulator-boot-on;
+   };
+
+   vneg {
+   regulator-name = "lcd_vneg";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   regulator-boot-on;
+   };
+   };
+
+   backlight {
+   compatible = "ti,lm3631-backlight";
+
+   lcd_bl {
+   led-sources = <0 1>;
+   ramp-up-msec = <300>;
+   };
+   };
+};
+
+lm3632@11 {
+   compatible = "ti,lm3632";
+   reg = <0x11>;
+
+   enable-gpios = < 2 GPIO_ACTIVE_HIGH>; /* PC2 */
+
+   regulators {
+   compatible = "ti,lm363x-regulator";
+
+   ti,lcm-en1-gpio = < 0 GPIO_ACTIVE_HIGH>; /* PC0 */
+   ti,lcm-en2-gpio = < 1 GPIO_ACTIVE_HIGH>; /* PC1 */
+
+   vboost {
+   regulator-name = "lcd_boost";
+   

[PATCH 2/2] mfd: add TI LMU driver

2017-02-27 Thread Milo Kim
TI LMU (Lighting Management Unit) driver supports lighting devices below.

  LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.

LMU devices have common features.
  - I2C interface for accessing device registers
  - Hardware enable pin control
  - Backlight brightness control
  - Notifier for hardware fault monitoring
  - Regulators for LCD display bias

It contains fault monitor, backlight, LED and regulator driver.

LMU fault monitor
-
  LM3633 and LM3697 provide hardware monitoring feature.
  It enables open or short circuit detection.
  After monitoring is done, each device should be re-initialized.
  Notifier is used for this case.
  Separate patch for 'ti-lmu-fault-monitor' will be sent later.

Backlight
-
  It's handled by TI LMU backlight consolidated driver and
  chip dependent data. Separate patchset will be sent later.

LED indicator
-
  LM3633 has 6 indicator LEDs. Programmable dimming pattern is also
  supported. Separate patch for 'leds-lm3633' will be sent later.

Regulator
-
  LM3631 has 5 regulators for the display bias.
  LM3632 supports 3 regulators. One consolidated driver enables it.
  The lm363x regulator driver is already upstreamed.

Acked-by: Lee Jones <lee.jo...@linaro.org>
Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/mfd/Kconfig |  12 ++
 drivers/mfd/Makefile|   2 +
 drivers/mfd/ti-lmu.c| 259 +
 include/linux/mfd/ti-lmu-register.h | 280 
 include/linux/mfd/ti-lmu.h  |  87 +++
 5 files changed, 640 insertions(+)
 create mode 100644 drivers/mfd/ti-lmu.c
 create mode 100644 include/linux/mfd/ti-lmu-register.h
 create mode 100644 include/linux/mfd/ti-lmu.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 55ecdfb74d31..75e749c1ff1a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1164,6 +1164,18 @@ config MFD_LP8788
  TI LP8788 PMU supports regulators, battery charger, RTC,
  ADC, backlight driver and current sinks.
 
+config MFD_TI_LMU
+   tristate "TI Lighting Management Unit driver"
+   depends on I2C
+   select MFD_CORE
+   select REGMAP_I2C
+   help
+ Say yes here to enable support for TI LMU chips.
+
+ TI LMU MFD supports LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.
+ It consists of backlight, LED and regulator driver.
+ It provides consistent device controls for lighting functions.
+
 config MFD_OMAP_USB_HOST
bool "TI OMAP USBHS core and TLL driver"
depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 31ce07611a6f..dac78a0f23a7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -125,6 +125,8 @@ obj-$(CONFIG_MFD_AXP20X_RSB)+= axp20x-rsb.o
 obj-$(CONFIG_MFD_LP3943)   += lp3943.o
 obj-$(CONFIG_MFD_LP8788)   += lp8788.o lp8788-irq.o
 
+obj-$(CONFIG_MFD_TI_LMU)   += ti-lmu.o
+
 da9055-objs:= da9055-core.o da9055-i2c.o
 obj-$(CONFIG_MFD_DA9055)   += da9055.o
 obj-$(CONFIG_MFD_DA9062)   += da9062-core.o
diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c
new file mode 100644
index ..cfb411cde51c
--- /dev/null
+++ b/drivers/mfd/ti-lmu.c
@@ -0,0 +1,259 @@
+/*
+ * TI LMU (Lighting Management Unit) Core Driver
+ *
+ * Copyright 2017 Texas Instruments
+ *
+ * Author: Milo Kim <milo@ti.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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ti_lmu_data {
+   struct mfd_cell *cells;
+   int num_cells;
+   unsigned int max_register;
+};
+
+static int ti_lmu_enable_hw(struct ti_lmu *lmu, enum ti_lmu_id id)
+{
+   int ret;
+
+   if (gpio_is_valid(lmu->en_gpio)) {
+   ret = devm_gpio_request_one(lmu->dev, lmu->en_gpio,
+   GPIOF_OUT_INIT_HIGH, "lmu_hwen");
+   if (ret) {
+   dev_err(lmu->dev, "Can not request enable GPIO: %d\n",
+   ret);
+   return ret;
+   }
+   }
+
+   /* Delay about 1ms after HW enable pin control */
+   usleep_range(1000, 1500);
+
+   /* LM3631 has additional power up sequence - enable LCD_EN bit. */
+   if (id == LM3631) {
+   return regmap_update_bits(lmu->regmap, LM3631_REG_DEVCTRL,
+ LM3631_LCD_EN_MASK,
+ LM3631_LCD_EN_MASK);
+   }
+
+   return 0;
+}
+
+static void ti_lmu

[PATCH v3 0/2] Support TI LMU devices

2017-02-27 Thread Milo Kim
Back from 2015! TI LMU core driver got acked but few more efforts
were required like backlight, LEDs and others.
Recently, Tony Lindgren has been working on porting mainline Linux on 
Droid 4 xt894. One of LMU devices - LM3532 is used for LCD backlight on 
that device. I hope this patch-set would be helpful.

TI Lighting Management Unit drivers support lighting devices below.

 Enable pin  Backlight  HW fault monitoring  LEDs   Regulators
 --  -  ---    
LM3532   o   o   xx x
LM3631   o   o   xx5 regulators
LM3632   o   o   xx3 regulators
LM3633   o   o   oo x
LM3695   o   o   xx x
LM3697   o   o   ox x

This patch-set includes only MFD part. Other subsystem drivers will be sent
separately.

  ti-lmu-backlight: Backlight subsystem
  ti-lmu-fault-monitor: Misc driver
  leds-lm3633: LED subsystem

Updates from v2:
  Submit acked patches to get merged quickly.

Milo Kim (2):
  Documentation: dt-bindings: mfd: add TI LMU device binding information
  mfd: add TI LMU driver

 Documentation/devicetree/bindings/mfd/ti-lmu.txt | 243 
 drivers/mfd/Kconfig  |  12 +
 drivers/mfd/Makefile |   2 +
 drivers/mfd/ti-lmu.c | 259 +
 include/linux/mfd/ti-lmu-register.h  | 280 +++
 include/linux/mfd/ti-lmu.h   |  87 +++
 6 files changed, 883 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/ti-lmu.txt
 create mode 100644 drivers/mfd/ti-lmu.c
 create mode 100644 include/linux/mfd/ti-lmu-register.h
 create mode 100644 include/linux/mfd/ti-lmu.h

-- 
2.11.0



[PATCH 1/2] Documentation: dt-bindings: Use generic property for hardware enable pins

2017-02-28 Thread Milo Kim
With index usages, device specific properties can be replaced with generic
one. Vpos is index 0 and Vneg is index 1.
DT examples are added as well.

Signed-off-by: Milo Kim <milo@ti.com>
---
 .../bindings/regulator/lm363x-regulator.txt| 78 +-
 1 file changed, 76 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt 
b/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
index 8f14df9d1205..cc5a6151d85f 100644
--- a/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
@@ -8,8 +8,8 @@ Required property:
 
 Optional properties:
   LM3632 has external enable pins for two LDOs.
-  - ti,lcm-en1-gpio: A GPIO specifier for Vpos control pin.
-  - ti,lcm-en2-gpio: A GPIO specifier for Vneg control pin.
+  - enable-gpios: Two GPIO specifiers for Vpos and Vneg control pins.
+  The first entry is Vpos, the second is Vneg enable pin.
 
 Child nodes:
   LM3631
@@ -30,5 +30,79 @@ Child nodes:
 
 Examples: Please refer to ti-lmu dt-bindings [2].
 
+lm3631@29 {
+   compatible = "ti,lm3631";
+   reg = <0x29>;
+
+   regulators {
+   compatible = "ti,lm363x-regulator";
+
+   vboost {
+   regulator-name = "lcd_boost";
+   regulator-min-microvolt = <450>;
+   regulator-max-microvolt = <635>;
+   regulator-always-on;
+   };
+
+   vcont {
+   regulator-name = "lcd_vcont";
+   regulator-min-microvolt = <180>;
+   regulator-max-microvolt = <330>;
+   };
+
+   voref {
+   regulator-name = "lcd_voref";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   };
+
+   vpos {
+   regulator-name = "lcd_vpos";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   regulator-boot-on;
+   };
+
+   vneg {
+   regulator-name = "lcd_vneg";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   regulator-boot-on;
+   };
+   };
+};
+
+lm3632@11 {
+   compatible = "ti,lm3632";
+   reg = <0x11>;
+
+   regulators {
+   compatible = "ti,lm363x-regulator";
+
+   /* GPIO1_16 for Vpos, GPIO1_28 is for Vneg */
+   enable-gpios = < 16 GPIO_ACTIVE_HIGH>,
+   < 28 GPIO_ACTIVE_HIGH>;
+
+   vboost {
+   regulator-name = "lcd_boost";
+   regulator-min-microvolt = <450>;
+   regulator-max-microvolt = <640>;
+   regulator-always-on;
+   };
+
+   vpos {
+   regulator-name = "lcd_vpos";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   };
+
+   vneg {
+   regulator-name = "lcd_vneg";
+   regulator-min-microvolt = <400>;
+   regulator-max-microvolt = <600>;
+   };
+   };
+};
+
 [1] ../regulator/regulator.txt
 [2] ../mfd/ti-lmu.txt
-- 
2.11.0



[PATCH 2/2] regulator: lm363x: Use generic DT property name for external control pins

2017-02-28 Thread Milo Kim
Vpos and Vneg LDOs can be enabled or disabled by external GPIOs.
Use general DT property 'enable-gpios' for this usage.
Two enable pins are differentiable by selecting the index number.

Signed-off-by: Milo Kim <milo@ti.com>
---
 drivers/regulator/lm363x-regulator.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/lm363x-regulator.c 
b/drivers/regulator/lm363x-regulator.c
index f53e63301a20..ce5f7d9ad475 100644
--- a/drivers/regulator/lm363x-regulator.c
+++ b/drivers/regulator/lm363x-regulator.c
@@ -227,9 +227,9 @@ static int lm363x_regulator_of_get_enable_gpio(struct 
device_node *np, int id)
 */
switch (id) {
case LM3632_LDO_POS:
-   return of_get_named_gpio(np, "ti,lcm-en1-gpio", 0);
+   return of_get_named_gpio(np, "enable-gpios", 0);
case LM3632_LDO_NEG:
-   return of_get_named_gpio(np, "ti,lcm-en2-gpio", 0);
+   return of_get_named_gpio(np, "enable-gpios", 1);
default:
return -EINVAL;
}
-- 
2.11.0



[PATCH 1/2] pwm: sun4i: Add Allwinner H3 support

2016-08-25 Thread Milo Kim
According to the latest datasheet (v1.2), H3 has single PWM channel.
H3 PWM controller has same register layout as sun4i driver, so it works 
by adding H3 specific data.
And the second PWM channel is not supported, so the pinctrl function is removed.

Datasheet:
  http://linux-sunxi.org/File:Allwinner_H3_Datasheet_V1.2.pdf

Test environment:
  Tested on Nano Pi M1 board, but PA5 pin is assigned for UART0.
  So the debug console should be changed to other port like UART1.

  Ex)
aliases {
serial0 = 
};

 {
pinctrl-names = "default";
pinctrl-0 = <_pins_a>;
status = "okay";
};

Cc: Chen-Yu Tsai <w...@csie.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: Thierry Reding <thierry.red...@gmail.com>
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 Documentation/devicetree/bindings/pwm/pwm-sun4i.txt |  1 +
 arch/arm/boot/dts/sun8i-h3.dtsi | 15 +++
 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c|  1 -
 drivers/pwm/pwm-sun4i.c |  9 +
 4 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt 
b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
index cf6068b..f1cbeef 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
@@ -6,6 +6,7 @@ Required properties:
 - "allwinner,sun5i-a10s-pwm"
 - "allwinner,sun5i-a13-pwm"
 - "allwinner,sun7i-a20-pwm"
+- "allwinner,sun8i-h3-pwm"
   - reg: physical base address and length of the controller's registers
   - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
 the cells format.
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index b44bc48..3a965fb 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -512,6 +512,13 @@
allwinner,pull = ;
};
 
+   pwm0_pin_a: pwm0@0 {
+   allwinner,pins = "PA5";
+   allwinner,function = "pwm0";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+
uart0_pins_a: uart0@0 {
allwinner,pins = "PA4", "PA5";
allwinner,function = "uart0";
@@ -585,6 +592,14 @@
interrupts = ;
};
 
+   pwm: pwm@01c21400 {
+   compatible = "allwinner,sun8i-h3-pwm";
+   reg = <0x01c21400 0x8>;
+   clocks = <>;
+   #pwm-cells = <3>;
+   status = "disabled";
+   };
+
uart0: serial@01c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c 
b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
index 11760bb..087f231 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
@@ -60,7 +60,6 @@ static const struct sunxi_desc_pin sun8i_h3_pins[] = {
  SUNXI_FUNCTION(0x0, "gpio_in"),
  SUNXI_FUNCTION(0x1, "gpio_out"),
  SUNXI_FUNCTION(0x2, "sim"),   /* PWREN */
- SUNXI_FUNCTION(0x3, "pwm1"),
  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),  /* PA_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
  SUNXI_FUNCTION(0x0, "gpio_in"),
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 03a99a5..b0803f6 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -284,6 +284,12 @@ static const struct sun4i_pwm_data sun4i_pwm_data_a20 = {
.npwm = 2,
 };
 
+static const struct sun4i_pwm_data sun4i_pwm_data_h3 = {
+   .has_prescaler_bypass = true,
+   .has_rdy = true,
+   .npwm = 1,
+};
+
 static const struct of_device_id sun4i_pwm_dt_ids[] = {
{
.compatible = "allwinner,sun4i-a10-pwm",
@@ -298,6 +304,9 @@ static const struct of_device_id sun4i_pwm_dt_ids[] = {
.compatible = "allwinner,sun7i-a20-pwm",
.data = _pwm_data_a20,
}, {
+   .compatible = "allwinner,sun8i-h3-pwm",
+   .data = _pwm_data_h3,
+   }, {
/* sentinel */
},
 };
-- 
1.9.1



[PATCH 2/2] ARM: dts: sun8i-h3: Add UART1 pinctrl

2016-08-25 Thread Milo Kim
In H3, PA5 can be used as PWM and UART0. If the PWM is used, the console
UART should be moved to other port.
This patch enables UART1 pinctrl to support this case.

PA5: PWM
PG6, PG7: debug console

Cc: Chen-Yu Tsai <w...@csie.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Rob Herring <robh...@kernel.org>
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 3a965fb..fdb6801 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -526,6 +526,13 @@
allwinner,pull = ;
};
 
+   uart1_pins_a: uart1@0 {
+   allwinner,pins = "PG6", "PG7";
+   allwinner,function = "uart1";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+
mmc0_pins_a: mmc0@0 {
allwinner,pins = "PF0", "PF1", "PF2", "PF3",
 "PF4", "PF5";
-- 
1.9.1



Re: [PATCH v2 1/4] ARM: dts: sun8i: Add PWM pin in H3

2016-09-01 Thread Milo Kim

On 09/01/2016 01:20 AM, Maxime Ripard wrote:

Hi Milo,

On Wed, Aug 31, 2016 at 05:25:17PM +0900, Milo Kim wrote:

H3 PA5 pin is assigned for single PWM channel.

Cc: Rob Herring <robh...@kernel.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Chen-Yu Tsai <w...@csie.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index fdf9fdb..05d0c4b 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -360,6 +360,13 @@
allwinner,pull = ;
};

+   pwm0_pin_a: pwm0@0 {
+   allwinner,pins = "PA5";
+   allwinner,function = "pwm0";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+


Is it used on any boards?

If not, we have the policy of not merging the pinctrl nodes that are
not used by anyone to avoid bloating the DT for no particular reason.


Yes, I have. It's Nano Pi M1 which was derived from Orange Pi PC.
The board DTS is ready to be sent out, but I'm not sure which is better.

a) Send new board DTS file in other patch thread

[PATCH v3 0/4] Add PWM feature in Allwinner H3
[PATCH v3 1/4] ARM: dts: sun8i: Add PWM pin in H3
..
[PATCH v3 4/4] pwm: sunxi: Add H3 support

[PATCH] ARM: dts: sun8i: Add Nano Pi M1 support

Or

b) Include the DTS in next patch-set v3
[PATCH v3 0/4] Add PWM feature in Allwinner H3
[PATCH v3 1/4] ARM: dts: sun8i: Add PWM pin in H3
[PATCH v3 2/4] ARM: dts: sun8i: Add PWM controller node in H3
[PATCH v3 3/4] ARM: dts: sun8i: Add Nano Pi M1 support
...

I'd like to have your opinion.

Best regards,
Milo


Re: [PATCH v2 1/4] ARM: dts: sun8i: Add PWM pin in H3

2016-09-01 Thread Milo Kim

On 08/31/2016 05:33 PM, Chen-Yu Tsai wrote:

+   pwm0_pin_a: pwm0@0 {

This is the only possible configuration. You can drop the _a suffix
from the label, and @0 from the node name.


OK, thanks for your review.

Best regards,
Milo


Re: [PATCH v3 1/5] ARM: dts: exynos: Enable HDMI for Arndale Octa board

2016-08-31 Thread Milo Kim

Hi Krzysztof,

On 08/25/2016 04:05 AM, Krzysztof Kozlowski wrote:

First of all - it looks like these DTS patches do not depend on DRM
part, do they?


I just sent the v4 patch for DTS. DRM patch-set was sent separately. 
Thanks for your advise.


Best regards,
Milo


[PATCH v2 0/4] Add PWM feature in Allwinner H3

2016-08-31 Thread Milo Kim
According to the latest datasheet, H3 has single PWM channel.
H3 PWM controller has same register layout as sun4i driver, so it works 
by adding H3 specific data.
And the second PWM channel is not supported, so the pinctrl function is removed.

Datasheet:
  http://linux-sunxi.org/File:Allwinner_H3_Datasheet_V1.2.pdf

Test environment:
  Tested on Nano Pi M1 board, but PA5 pin is assigned for UART0.
  So the debug console should be changed to other port like UART1.

  Ex)
aliases {
serial0 = 
};

 {
pinctrl-names = "default";
pinctrl-0 = <_pins_a>;
status = "okay";
};

v2:
  Split v1 patch-set into several patches

Milo Kim (4):
  ARM: dts: sun8i: Add PWM pin in H3
  ARM: dts: sun8i: Add PWM controller node in H3
  pinctrl: sunxi: Remove unsupported PWM channel pinmux in H3
  pwm: sunxi: Add H3 support

 Documentation/devicetree/bindings/pwm/pwm-sun4i.txt |  1 +
 arch/arm/boot/dts/sun8i-h3.dtsi | 15 +++
 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c|  1 -
 drivers/pwm/pwm-sun4i.c |  9 +
 4 files changed, 25 insertions(+), 1 deletion(-)

-- 
2.9.3



[PATCH v2 1/4] ARM: dts: sun8i: Add PWM pin in H3

2016-08-31 Thread Milo Kim
H3 PA5 pin is assigned for single PWM channel.

Cc: Rob Herring <robh...@kernel.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Chen-Yu Tsai <w...@csie.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index fdf9fdb..05d0c4b 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -360,6 +360,13 @@
allwinner,pull = ;
};
 
+   pwm0_pin_a: pwm0@0 {
+   allwinner,pins = "PA5";
+   allwinner,function = "pwm0";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+
uart0_pins_a: uart0@0 {
allwinner,pins = "PA4", "PA5";
allwinner,function = "uart0";
-- 
2.9.3



[PATCH v2 3/4] pinctrl: sunxi: Remove unsupported PWM channel pinmux in H3

2016-08-31 Thread Milo Kim
H3 has single PWM channel. The second PWM channel is not supported,
so the pinctrl function should be removed.

Cc: Linus Walleij <linus.wall...@linaro.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Chen-Yu Tsai <w...@csie.org>
Cc: Icenowy Zheng <icen...@aosc.xyz>
Cc: Jens Kuske <jensku...@gmail.com>
Cc: Krzysztof Adamski <k...@japko.eu>
Cc: linux-g...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c 
b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
index 26a2ad3..518a92d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
@@ -60,7 +60,6 @@ static const struct sunxi_desc_pin sun8i_h3_pins[] = {
  SUNXI_FUNCTION(0x0, "gpio_in"),
  SUNXI_FUNCTION(0x1, "gpio_out"),
  SUNXI_FUNCTION(0x2, "sim"),   /* PWREN */
- SUNXI_FUNCTION(0x3, "pwm1"),
  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),  /* PA_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
  SUNXI_FUNCTION(0x0, "gpio_in"),
-- 
2.9.3



[PATCH v4 2/3] gpu: drm: exynos_hdmi: Move PHY logic into single function

2016-08-31 Thread Milo Kim
Paring DT properties and getting PHY IO (memory mapped or I2C) in one
function.

Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 63 +++-
 1 file changed, 33 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 1440dfd..42b0b98 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1790,16 +1790,44 @@ static int hdmi_get_ddc_adapter(struct hdmi_context 
*hdata)
return 0;
 }
 
-static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
+static int hdmi_get_phy_io(struct hdmi_context *hdata)
 {
const char *compatible_str = "samsung,exynos4212-hdmiphy";
+   struct device_node *np;
+   int ret = 0;
+
+   np = of_find_compatible_node(NULL, NULL, compatible_str);
+   if (!np) {
+   np = of_parse_phandle(hdata->dev->of_node, "phy", 0);
+   if (!np) {
+   DRM_ERROR("Failed to find hdmiphy node in device 
tree\n");
+   return -ENODEV;
+   }
+   }
+
+   if (hdata->drv_data->is_apb_phy) {
+   hdata->regs_hdmiphy = of_iomap(np, 0);
+   if (!hdata->regs_hdmiphy) {
+   DRM_ERROR("failed to ioremap hdmi phy\n");
+   ret = -ENOMEM;
+   goto out;
+   }
+   } else {
+   hdata->hdmiphy_port = of_find_i2c_device_by_node(np);
+   if (!hdata->hdmiphy_port) {
+   DRM_INFO("Failed to get hdmi phy i2c client\n");
+   ret = -EPROBE_DEFER;
+   goto out;
+   }
+   }
 
-   return of_find_compatible_node(NULL, NULL, compatible_str);
+out:
+   of_node_put(np);
+   return ret;
 }
 
 static int hdmi_probe(struct platform_device *pdev)
 {
-   struct device_node *phy_node;
struct device *dev = >dev;
struct hdmi_context *hdata;
struct resource *res;
@@ -1833,34 +1861,9 @@ static int hdmi_probe(struct platform_device *pdev)
if (ret)
return ret;
 
-   phy_node = hdmi_legacy_phy_dt_binding(dev);
-   if (phy_node)
-   goto out_get_phy_port;
-
-   phy_node = of_parse_phandle(dev->of_node, "phy", 0);
-   if (!phy_node) {
-   DRM_ERROR("Failed to find hdmiphy node in device tree\n");
-   ret = -ENODEV;
+   ret = hdmi_get_phy_io(hdata);
+   if (ret)
goto err_ddc;
-   }
-   of_node_put(dev->of_node);
-
-out_get_phy_port:
-   if (hdata->drv_data->is_apb_phy) {
-   hdata->regs_hdmiphy = of_iomap(phy_node, 0);
-   if (!hdata->regs_hdmiphy) {
-   DRM_ERROR("failed to ioremap hdmi phy\n");
-   ret = -ENOMEM;
-   goto err_ddc;
-   }
-   } else {
-   hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
-   if (!hdata->hdmiphy_port) {
-   DRM_ERROR("Failed to get hdmi phy i2c client\n");
-   ret = -EPROBE_DEFER;
-   goto err_ddc;
-   }
-   }
 
INIT_DELAYED_WORK(>hotplug_work, hdmi_hotplug_work_func);
 
-- 
2.9.3



[PATCH v4] ARM: dts: exynos: Enable HDMI for Arndale Octa board

2016-08-31 Thread Milo Kim
* GPIO for HDMI hot plug detect
  GPX3_7 is used. The HPD awareness is done when the GPIO is active high.

* Enable HDMI block in Exynos5420
  HDMI VDD and PLL consume 1.0V LDO6 (PVDD_ANAIP_1V0) and HDMI oscillator
  requires 1.8V LDO7 (PVDD_ANAIP_1V8).

* Support HDMI display data channel
  I2C #2 is assigned for the HDMI DDC. It enables the EDID access.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/exynos5420-arndale-octa.dts | 13 +
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts 
b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 39a3b81..d2ad48e 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -70,6 +70,15 @@
status = "disabled";
 };
 
+ {
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
+   vdd_osc-supply = <_reg>;
+   vdd_pll-supply = <_reg>;
+   vdd-supply = <_reg>;
+   ddc = <_2>;
+   status = "okay";
+};
+
 _4 {
status = "okay";
 
@@ -347,6 +356,10 @@
};
 };
 
+_2 {
+   status = "okay";
+};
+
 _0 {
status = "okay";
broken-cd;
-- 
2.9.3



[PATCH v4 3/3] gpu: drm: exynos_hdmi: Remove duplicate initialization of regulator bulk consumer

2016-08-31 Thread Milo Kim
The helper, devm_regulator_bulk_get() initializes the consumer as NULL,
so this code can be ignored.

Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 42b0b98..e8fb6ef 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1669,10 +1669,9 @@ static int hdmi_resources_init(struct hdmi_context 
*hdata)
if (ret)
return ret;
 
-   for (i = 0; i < ARRAY_SIZE(supply); ++i) {
+   for (i = 0; i < ARRAY_SIZE(supply); ++i)
hdata->regul_bulk[i].supply = supply[i];
-   hdata->regul_bulk[i].consumer = NULL;
-   }
+
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), 
hdata->regul_bulk);
if (ret) {
if (ret != -EPROBE_DEFER)
-- 
2.9.3



[PATCH v4 1/3] gpu: drm: exynos_hdmi: Move DDC logic into single function

2016-08-31 Thread Milo Kim
Paring DT properties and getting the I2C adapter in one function.

Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: dri-de...@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 46 
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2275efe..1440dfd 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1760,16 +1760,34 @@ static const struct component_ops hdmi_component_ops = {
.unbind = hdmi_unbind,
 };
 
-static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
+static int hdmi_get_ddc_adapter(struct hdmi_context *hdata)
 {
const char *compatible_str = "samsung,exynos4210-hdmiddc";
struct device_node *np;
+   struct i2c_adapter *adpt;
 
np = of_find_compatible_node(NULL, NULL, compatible_str);
if (np)
-   return of_get_next_parent(np);
+   np = of_get_next_parent(np);
+   else
+   np = of_parse_phandle(hdata->dev->of_node, "ddc", 0);
+
+   if (!np) {
+   DRM_ERROR("Failed to find ddc node in device tree\n");
+   return -ENODEV;
+   }
+
+   adpt = of_find_i2c_adapter_by_node(np);
+   of_node_put(np);
 
-   return NULL;
+   if (!adpt) {
+   DRM_INFO("Failed to get ddc i2c adapter by node\n");
+   return -EPROBE_DEFER;
+   }
+
+   hdata->ddc_adpt = adpt;
+
+   return 0;
 }
 
 static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
@@ -1781,7 +1799,7 @@ static struct device_node 
*hdmi_legacy_phy_dt_binding(struct device *dev)
 
 static int hdmi_probe(struct platform_device *pdev)
 {
-   struct device_node *ddc_node, *phy_node;
+   struct device_node *phy_node;
struct device *dev = >dev;
struct hdmi_context *hdata;
struct resource *res;
@@ -1811,23 +1829,9 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}
 
-   ddc_node = hdmi_legacy_ddc_dt_binding(dev);
-   if (ddc_node)
-   goto out_get_ddc_adpt;
-
-   ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
-   if (!ddc_node) {
-   DRM_ERROR("Failed to find ddc node in device tree\n");
-   return -ENODEV;
-   }
-   of_node_put(dev->of_node);
-
-out_get_ddc_adpt:
-   hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
-   if (!hdata->ddc_adpt) {
-   DRM_ERROR("Failed to get ddc i2c adapter by node\n");
-   return -EPROBE_DEFER;
-   }
+   ret = hdmi_get_ddc_adapter(hdata);
+   if (ret)
+   return ret;
 
phy_node = hdmi_legacy_phy_dt_binding(dev);
if (phy_node)
-- 
2.9.3



[PATCH v4 0/3] gpu: drm: exynos_hdmi: Code refactoring on hdmi ddc and phy

2016-08-31 Thread Milo Kim
v4:
  Only DRM patchset is sent, DTS patch was sent separately.

Milo Kim (3):
  gpu: drm: exynos_hdmi: Move DDC logic into single function
  gpu: drm: exynos_hdmi: Move PHY logic into single function
  gpu: drm: exynos_hdmi: Remove duplicate initialization of regulator
bulk consumer

 drivers/gpu/drm/exynos/exynos_hdmi.c | 112 ++-
 1 file changed, 59 insertions(+), 53 deletions(-)

-- 
2.9.3



[PATCH v2 4/4] pwm: sunxi: Add H3 support

2016-08-31 Thread Milo Kim
H3 PWM controller has same register layout as sun4i driver, so it works
by adding H3 specific data.

Cc: Thierry Reding <thierry.red...@gmail.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Alexandre Belloni <alexandre.bell...@free-electrons.com>
Cc: Chen-Yu Tsai <w...@csie.org>
Cc: linux-...@vger.kernel.org
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 Documentation/devicetree/bindings/pwm/pwm-sun4i.txt | 1 +
 drivers/pwm/pwm-sun4i.c | 9 +
 2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt 
b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
index cf6068b..f1cbeef 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-sun4i.txt
@@ -6,6 +6,7 @@ Required properties:
 - "allwinner,sun5i-a10s-pwm"
 - "allwinner,sun5i-a13-pwm"
 - "allwinner,sun7i-a20-pwm"
+- "allwinner,sun8i-h3-pwm"
   - reg: physical base address and length of the controller's registers
   - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
 the cells format.
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 03a99a5..b0803f6 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -284,6 +284,12 @@ static const struct sun4i_pwm_data sun4i_pwm_data_a20 = {
.npwm = 2,
 };
 
+static const struct sun4i_pwm_data sun4i_pwm_data_h3 = {
+   .has_prescaler_bypass = true,
+   .has_rdy = true,
+   .npwm = 1,
+};
+
 static const struct of_device_id sun4i_pwm_dt_ids[] = {
{
.compatible = "allwinner,sun4i-a10-pwm",
@@ -298,6 +304,9 @@ static const struct of_device_id sun4i_pwm_dt_ids[] = {
.compatible = "allwinner,sun7i-a20-pwm",
.data = _pwm_data_a20,
}, {
+   .compatible = "allwinner,sun8i-h3-pwm",
+   .data = _pwm_data_h3,
+   }, {
/* sentinel */
},
 };
-- 
2.9.3



[PATCH v2 2/4] ARM: dts: sun8i: Add PWM controller node in H3

2016-08-31 Thread Milo Kim
Cc: Rob Herring <robh...@kernel.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Chen-Yu Tsai <w...@csie.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 05d0c4b..860e355 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -396,6 +396,14 @@
interrupts = ;
};
 
+   pwm: pwm@01c21400 {
+   compatible = "allwinner,sun8i-h3-pwm";
+   reg = <0x01c21400 0x8>;
+   clocks = <>;
+   #pwm-cells = <3>;
+   status = "disabled";
+   };
+
uart0: serial@01c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
-- 
2.9.3



Re: [PATCH 2/2] ARM: dts: sun8i-h3: Add UART1 pinctrl

2016-08-31 Thread Milo Kim

Hi Maxime,

On 08/26/2016 04:10 PM, Maxime Ripard wrote:

Hi Milo,

On Thu, Aug 25, 2016 at 03:44:54PM +0900, Milo Kim wrote:

In H3, PA5 can be used as PWM and UART0. If the PWM is used, the console
UART should be moved to other port.
This patch enables UART1 pinctrl to support this case.

PA5: PWM
PG6, PG7: debug console

Cc: Chen-Yu Tsai <w...@csie.org>
Cc: Maxime Ripard <maxime.rip...@free-electrons.com>
Cc: Rob Herring <robh...@kernel.org>
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 3a965fb..fdb6801 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -526,6 +526,13 @@
allwinner,pull = ;
};

+   uart1_pins_a: uart1@0 {
+   allwinner,pins = "PG6", "PG7";
+   allwinner,function = "uart1";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+


Our policy is that we don't introduce new pinctrl nodes that are not
used by any board to avoid bloating the DT too much with unused nodes.

If you have a board using it, please submit that change as well.


UART1 was already added in sun8i-h3.dtsi, so I drop this change in v2.

Commit-ID: 966c11a3b5e4

Best regards,
Milo


Re: [PATCH 2/2] ARM: dts: sun8i-h3: Add UART1 pinctrl

2016-08-26 Thread Milo Kim

On 08/26/2016 04:10 PM, Maxime Ripard wrote:

+   uart1_pins_a: uart1@0 {
> +  allwinner,pins = "PG6", "PG7";
> +  allwinner,function = "uart1";
> +  allwinner,drive = ;
> +  allwinner,pull = ;
> +  };
> +

Our policy is that we don't introduce new pinctrl nodes that are not
used by any board to avoid bloating the DT too much with unused nodes.

If you have a board using it, please submit that change as well.


OK, I agree.

However, this pinmux is only useful in case PA5 is assigned for PWM.
PA5 is commonly used for UART0_RX, so I'd like to add UART1 node into 
*.dts and disable it (status = "disabled"). Does it make sense?


Best regards,
Milo


[PATCH v2 4/4] gpu: drm: exynos_hdmi: Use consolidated function on binding PHY DT property

2016-08-23 Thread Milo Kim
Handle legacy and raw 'phy' parsing in single function.
And it also removes goto condition.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 6a636f2..bb2d6d4 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1778,11 +1778,22 @@ static struct device_node *hdmi_ddc_dt_binding(struct 
device *dev)
return np;
 }
 
-static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
+static struct device_node *hdmi_phy_dt_binding(struct device *dev)
 {
const char *compatible_str = "samsung,exynos4212-hdmiphy";
+   struct device_node *np;
+
+   np = of_find_compatible_node(NULL, NULL, compatible_str);
+   if (np)
+   return np;
+
+   np = of_parse_phandle(dev->of_node, "phy", 0);
+   if (!np)
+   return NULL;
+
+   of_node_put(dev->of_node);
 
-   return of_find_compatible_node(NULL, NULL, compatible_str);
+   return np;
 }
 
 static int hdmi_probe(struct platform_device *pdev)
@@ -1829,19 +1840,13 @@ static int hdmi_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
 
-   phy_node = hdmi_legacy_phy_dt_binding(dev);
-   if (phy_node)
-   goto out_get_phy_port;
-
-   phy_node = of_parse_phandle(dev->of_node, "phy", 0);
+   phy_node = hdmi_phy_dt_binding(dev);
if (!phy_node) {
DRM_ERROR("Failed to find hdmiphy node in device tree\n");
ret = -ENODEV;
goto err_ddc;
}
-   of_node_put(dev->of_node);
 
-out_get_phy_port:
if (hdata->drv_data->is_apb_phy) {
hdata->regs_hdmiphy = of_iomap(phy_node, 0);
if (!hdata->regs_hdmiphy) {
-- 
1.9.1



[PATCH v2 2/4] ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'

2016-08-23 Thread Milo Kim
This patch enables getting a HPD GPIO descriptor quickly.
The exynos-hdmi driver uses "hpd" for HDMI hot plug detection.

static int hdmi_resources_init(struct hdmi_context *hdata)
{
...
hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
...
}

This calls 'of_find_gpio()' and it generates the GPIO consumer ID by referring
GPIO suffix. So 'hpd-gpios' is preferred on getting a GPIO descriptor.

However, if the device tree uses 'hpd-gpio', then the exynos-hdmi driver
always retries to get a GPIO descriptor because the first GPIO suffix is not
'gpio' but 'gpios'. So you always see the debug message below.

of_get_named_gpiod_flags: can't parse 'hpd-gpios' property of node 
'/soc/hdmi@1453[0]'

Use the preferred property, 'hpd-gpios' instead of 'hpd-gpio'.

Acked-by: Rob Herring <r...@kernel.org>
Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt | 4 ++--
 arch/arm/boot/dts/exynos4210-universal_c210.dts  | 2 +-
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi  | 2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts | 2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts| 2 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi| 2 +-
 arch/arm/boot/dts/exynos5250-spring.dts  | 2 +-
 arch/arm/boot/dts/exynos5420-peach-pit.dts   | 2 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts| 2 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi   | 2 +-
 arch/arm/boot/dts/exynos5800-peach-pi.dts| 2 +-
 11 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt 
b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
index a2ec4c1..6394ea9 100644
--- a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
@@ -9,7 +9,7 @@ Required properties:
 - reg: physical base address of the hdmi and length of memory mapped
region.
 - interrupts: interrupt number to the cpu.
-- hpd-gpio: following information about the hotplug gpio pin.
+- hpd-gpios: following information about the hotplug gpio pin.
a) phandle of the gpio controller node.
b) pin number within the gpio controller.
c) optional flags and pull up/down.
@@ -56,7 +56,7 @@ Example:
compatible = "samsung,exynos4212-hdmi";
reg = <0x1453 0x10>;
interrupts = <0 95 0>;
-   hpd-gpio = < 7 1>;
+   hpd-gpios = < 7 1>;
ddc = <_ddc_node>;
phy = <_phy_node>;
samsung,syscon-phandle = <_system_controller>;
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts 
b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index 9a75e3e..cf95202 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -269,7 +269,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_HIGH>;
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <_hpd>;
hdmi-en-supply = <_en>;
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi 
b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 58ad48e7..be644fe 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -227,7 +227,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_HIGH>;
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <_hpd>;
vdd-supply = <_reg>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts 
b/arch/arm/boot/dts/exynos5250-arndale.dts
index ea70603..3d981f3 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -152,7 +152,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_LOW>;
+   hpd-gpios = < 7 GPIO_ACTIVE_LOW>;
vdd_osc-supply = <_reg>;
vdd_pll-supply = <_reg>;
vdd-supply = <_reg>;
diff --git a/ar

[PATCH v2 0/4] ARM: dts: exynos: Enable HDMI in Arndale Octa board

2016-08-23 Thread Milo Kim
This patch-set enables HDMI in Arndale Octa board and fixes HPD DT property.
It also includes code refactoring on ddc and phy.

v2:
  Include DRM and Exynos maintainers and resend the patch-set.
  Add Rob's ack for the patch,
[PATCH 2/4] ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'

Milo Kim (4):
  ARM: dts: exynos: Enable HDMI for Arndale Octa board
  ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'
  gpu: drm: exynos_hdmi: Use consolidated function on binding DDC DT
property
  gpu: drm: exynos_hdmi: Use consolidated function on binding PHY DT
property

 .../bindings/display/exynos/exynos_hdmi.txt|  4 +--
 arch/arm/boot/dts/exynos4210-universal_c210.dts|  2 +-
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi|  2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts   |  2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts  |  2 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi  |  2 +-
 arch/arm/boot/dts/exynos5250-spring.dts|  2 +-
 arch/arm/boot/dts/exynos5420-arndale-octa.dts  | 17 +
 arch/arm/boot/dts/exynos5420-peach-pit.dts |  2 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts  |  2 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  2 +-
 arch/arm/boot/dts/exynos5800-peach-pi.dts  |  2 +-
 drivers/gpu/drm/exynos/exynos_hdmi.c   | 41 --
 13 files changed, 52 insertions(+), 30 deletions(-)

-- 
1.9.1



Re: [PATCH 0/4] ARM: dts: exynos: Enable HDMI in Arndale Octa board

2016-08-23 Thread Milo Kim

On 08/24/2016 04:55 AM, Krzysztof Kozlowski wrote:

I saw DTS patches on linux-samsung-soc patchwork but still I would
appreciate if you send them to appropriate maintainers pointed by
get_maintainers.pl script. DTS stuff goes through samsung-soc tree.


Thanks for your tip. I've just sent out the v2.

Best regards,
Milo


Re: [PATCH v2 1/4] ARM: dts: exynos: Enable HDMI for Arndale Octa board

2016-08-24 Thread Milo Kim

Hi Andrzej,

On 08/24/2016 02:28 PM, Andrzej Hajda wrote:

Please use ddc property in hdmi node, instead of this legacy binding.
See exynos4210-universal_c210.dts or exynos4412-odroid-common.dtsi for
reference.


Cool! I prefer this simple property. Thanks for the review.

Best regards,
Milo


Re: [PATCH v2 3/4] gpu: drm: exynos_hdmi: Use consolidated function on binding DDC DT property

2016-08-24 Thread Milo Kim

Hi Andrzej,

On 08/24/2016 02:55 PM, Andrzej Hajda wrote:

This is mistake introduced  by other patch, of_node_put should be called on
np, after calling of_find_i2c_adapter_by_node. You can fix it in your
patch as well.
I think you can move of_find_i2c_adapter_by_node also to this function and
rename it to sth like hdmi_get_ddc_adapter, this way you will enclose
whole logic
of getting resource into one function.


Agree, let me prepare next patch-set. Thanks!

Best regards,
Milo


[PATCH v2 1/4] ARM: dts: exynos: Enable HDMI for Arndale Octa board

2016-08-23 Thread Milo Kim
* Support HDMI display data channel
  I2C #2 is assigned for the HDMI DDC. It enables the EDID access.

* GPIO for HDMI hot plug detect
  GPX3_7 is used. The HPD awareness is done when the GPIO is active high and
  single ended.

* Enable HDMI block in Exynos5420
  HDMI PLL consumes 1.0V LDO6 (PVDD_ANAIP_1V0) and HDMI oscillator requires
  1.8V LDO7 (PVDD_ANAIP_1V8).

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/exynos5420-arndale-octa.dts | 17 +
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts 
b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 39a3b81..df362a2 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -70,6 +70,23 @@
status = "disabled";
 };
 
+_2 {
+   samsung,i2c-slave-addr = <0x50>;
+   status = "okay";
+
+   hdmiddc@50 {
+   compatible = "samsung,exynos4210-hdmiddc";
+   reg = <0x50>;
+   };
+};
+
+ {
+   hpd-gpios = < 7 GPIO_OPEN_SOURCE>;
+   vdd_osc-supply = <_reg>;
+   vdd_pll-supply = <_reg>;
+   status = "okay";
+};
+
 _4 {
status = "okay";
 
-- 
1.9.1



[PATCH v2 3/4] gpu: drm: exynos_hdmi: Use consolidated function on binding DDC DT property

2016-08-23 Thread Milo Kim
Handle legacy and raw 'ddc' parsing in single function.
And it also removes goto condition.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2275efe..6a636f2 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1760,7 +1760,7 @@ static const struct component_ops hdmi_component_ops = {
.unbind = hdmi_unbind,
 };
 
-static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
+static struct device_node *hdmi_ddc_dt_binding(struct device *dev)
 {
const char *compatible_str = "samsung,exynos4210-hdmiddc";
struct device_node *np;
@@ -1769,7 +1769,13 @@ static struct device_node 
*hdmi_legacy_ddc_dt_binding(struct device *dev)
if (np)
return of_get_next_parent(np);
 
-   return NULL;
+   np = of_parse_phandle(dev->of_node, "ddc", 0);
+   if (!np)
+   return NULL;
+
+   of_node_put(dev->of_node);
+
+   return np;
 }
 
 static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
@@ -1811,18 +1817,12 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}
 
-   ddc_node = hdmi_legacy_ddc_dt_binding(dev);
-   if (ddc_node)
-   goto out_get_ddc_adpt;
-
-   ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
+   ddc_node = hdmi_ddc_dt_binding(dev);
if (!ddc_node) {
DRM_ERROR("Failed to find ddc node in device tree\n");
return -ENODEV;
}
-   of_node_put(dev->of_node);
 
-out_get_ddc_adpt:
hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
if (!hdata->ddc_adpt) {
DRM_ERROR("Failed to get ddc i2c adapter by node\n");
-- 
1.9.1



[PATCH 2/4] ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'

2016-08-23 Thread Milo Kim
This patch enables getting a HPD GPIO descriptor quickly.
The exynos-hdmi driver uses "hpd" for HDMI hot plug detection.

static int hdmi_resources_init(struct hdmi_context *hdata)
{
...
hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
...
}

This calls 'of_find_gpio()' and it generates the GPIO consumer ID by referring
GPIO suffix. So 'hpd-gpios' is preferred on getting a GPIO descriptor.

However, if the device tree uses 'hpd-gpio', then the exynos-hdmi driver
always retries to get a GPIO descriptor because the first GPIO suffix is not
'gpio' but 'gpios'. So you always see the debug message below.

of_get_named_gpiod_flags: can't parse 'hpd-gpios' property of node 
'/soc/hdmi@1453[0]'

Use the preferred property, 'hpd-gpios' instead of 'hpd-gpio'.

Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt | 4 ++--
 arch/arm/boot/dts/exynos4210-universal_c210.dts  | 2 +-
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi  | 2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts | 2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts| 2 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi| 2 +-
 arch/arm/boot/dts/exynos5250-spring.dts  | 2 +-
 arch/arm/boot/dts/exynos5420-peach-pit.dts   | 2 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts| 2 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi   | 2 +-
 arch/arm/boot/dts/exynos5800-peach-pi.dts| 2 +-
 11 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt 
b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
index a2ec4c1..6394ea9 100644
--- a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
@@ -9,7 +9,7 @@ Required properties:
 - reg: physical base address of the hdmi and length of memory mapped
region.
 - interrupts: interrupt number to the cpu.
-- hpd-gpio: following information about the hotplug gpio pin.
+- hpd-gpios: following information about the hotplug gpio pin.
a) phandle of the gpio controller node.
b) pin number within the gpio controller.
c) optional flags and pull up/down.
@@ -56,7 +56,7 @@ Example:
compatible = "samsung,exynos4212-hdmi";
reg = <0x1453 0x10>;
interrupts = <0 95 0>;
-   hpd-gpio = < 7 1>;
+   hpd-gpios = < 7 1>;
ddc = <_ddc_node>;
phy = <_phy_node>;
samsung,syscon-phandle = <_system_controller>;
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts 
b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index 9a75e3e..cf95202 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -269,7 +269,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_HIGH>;
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <_hpd>;
hdmi-en-supply = <_en>;
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi 
b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 58ad48e7..be644fe 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -227,7 +227,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_HIGH>;
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <_hpd>;
vdd-supply = <_reg>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts 
b/arch/arm/boot/dts/exynos5250-arndale.dts
index ea70603..3d981f3 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -152,7 +152,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_LOW>;
+   hpd-gpios = < 7 GPIO_ACTIVE_LOW>;
vdd_osc-supply = <_reg>;
vdd_pll-supply = <_reg>;
vdd-supply = <_reg>;
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts 
b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 381af13..7f27263 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smd

[PATCH 4/4] gpu: drm: exynos_hdmi: Use consolidated function on binding PHY DT property

2016-08-23 Thread Milo Kim
Handle legacy and raw 'phy' parsing in single function.
And it also removes goto condition.

Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 6a636f2..bb2d6d4 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1778,11 +1778,22 @@ static struct device_node *hdmi_ddc_dt_binding(struct 
device *dev)
return np;
 }
 
-static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
+static struct device_node *hdmi_phy_dt_binding(struct device *dev)
 {
const char *compatible_str = "samsung,exynos4212-hdmiphy";
+   struct device_node *np;
+
+   np = of_find_compatible_node(NULL, NULL, compatible_str);
+   if (np)
+   return np;
+
+   np = of_parse_phandle(dev->of_node, "phy", 0);
+   if (!np)
+   return NULL;
+
+   of_node_put(dev->of_node);
 
-   return of_find_compatible_node(NULL, NULL, compatible_str);
+   return np;
 }
 
 static int hdmi_probe(struct platform_device *pdev)
@@ -1829,19 +1840,13 @@ static int hdmi_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
 
-   phy_node = hdmi_legacy_phy_dt_binding(dev);
-   if (phy_node)
-   goto out_get_phy_port;
-
-   phy_node = of_parse_phandle(dev->of_node, "phy", 0);
+   phy_node = hdmi_phy_dt_binding(dev);
if (!phy_node) {
DRM_ERROR("Failed to find hdmiphy node in device tree\n");
ret = -ENODEV;
goto err_ddc;
}
-   of_node_put(dev->of_node);
 
-out_get_phy_port:
if (hdata->drv_data->is_apb_phy) {
hdata->regs_hdmiphy = of_iomap(phy_node, 0);
if (!hdata->regs_hdmiphy) {
-- 
1.9.1



[PATCH 1/4] ARM: dts: exynos: Enable HDMI for Arndale Octa board

2016-08-23 Thread Milo Kim
* Support HDMI display data channel
  I2C #2 is assigned for the HDMI DDC. It enables the EDID access.

* GPIO for HDMI hot plug detect
  GPX3_7 is used. The HPD awareness is done when the GPIO is active high and
  single ended.

* Enable HDMI block in Exynos5420
  HDMI PLL consumes 1.0V LDO6 (PVDD_ANAIP_1V0) and HDMI oscillator requires
  1.8V LDO7 (PVDD_ANAIP_1V8).

Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/exynos5420-arndale-octa.dts | 17 +
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts 
b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 39a3b81..df362a2 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -70,6 +70,23 @@
status = "disabled";
 };
 
+_2 {
+   samsung,i2c-slave-addr = <0x50>;
+   status = "okay";
+
+   hdmiddc@50 {
+   compatible = "samsung,exynos4210-hdmiddc";
+   reg = <0x50>;
+   };
+};
+
+ {
+   hpd-gpios = < 7 GPIO_OPEN_SOURCE>;
+   vdd_osc-supply = <_reg>;
+   vdd_pll-supply = <_reg>;
+   status = "okay";
+};
+
 _4 {
status = "okay";
 
-- 
1.9.1



[PATCH 0/4] ARM: dts: exynos: Enable HDMI in Arndale Octa board

2016-08-23 Thread Milo Kim
This patch-set enables HDMI in Arndale Octa board and fixes HPD DT property.
It also includes code refactoring on ddc and phy.

Milo Kim (4):
  ARM: dts: exynos: Enable HDMI for Arndale Octa board
  ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'
  gpu: drm: exynos_hdmi: Use consolidated function on binding DDC DT
property
  gpu: drm: exynos_hdmi: Use consolidated function on binding PHY DT
property

 .../bindings/display/exynos/exynos_hdmi.txt|  4 +--
 arch/arm/boot/dts/exynos4210-universal_c210.dts|  2 +-
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi|  2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts   |  2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts  |  2 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi  |  2 +-
 arch/arm/boot/dts/exynos5250-spring.dts|  2 +-
 arch/arm/boot/dts/exynos5420-arndale-octa.dts  | 17 +
 arch/arm/boot/dts/exynos5420-peach-pit.dts |  2 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts  |  2 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  2 +-
 arch/arm/boot/dts/exynos5800-peach-pi.dts  |  2 +-
 drivers/gpu/drm/exynos/exynos_hdmi.c   | 41 --
 13 files changed, 52 insertions(+), 30 deletions(-)

-- 
1.9.1



[PATCH 3/4] gpu: drm: exynos_hdmi: Use consolidated function on binding DDC DT property

2016-08-23 Thread Milo Kim
Handle legacy and raw 'ddc' parsing in single function.
And it also removes goto condition.

Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2275efe..6a636f2 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1760,7 +1760,7 @@ static const struct component_ops hdmi_component_ops = {
.unbind = hdmi_unbind,
 };
 
-static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
+static struct device_node *hdmi_ddc_dt_binding(struct device *dev)
 {
const char *compatible_str = "samsung,exynos4210-hdmiddc";
struct device_node *np;
@@ -1769,7 +1769,13 @@ static struct device_node 
*hdmi_legacy_ddc_dt_binding(struct device *dev)
if (np)
return of_get_next_parent(np);
 
-   return NULL;
+   np = of_parse_phandle(dev->of_node, "ddc", 0);
+   if (!np)
+   return NULL;
+
+   of_node_put(dev->of_node);
+
+   return np;
 }
 
 static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
@@ -1811,18 +1817,12 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}
 
-   ddc_node = hdmi_legacy_ddc_dt_binding(dev);
-   if (ddc_node)
-   goto out_get_ddc_adpt;
-
-   ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
+   ddc_node = hdmi_ddc_dt_binding(dev);
if (!ddc_node) {
DRM_ERROR("Failed to find ddc node in device tree\n");
return -ENODEV;
}
-   of_node_put(dev->of_node);
 
-out_get_ddc_adpt:
hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
if (!hdata->ddc_adpt) {
DRM_ERROR("Failed to get ddc i2c adapter by node\n");
-- 
1.9.1



Re: [PATCH 1/2] pwm: sun4i: Add Allwinner H3 support

2016-08-26 Thread Milo Kim

Hi Maxime,

On 08/26/2016 05:51 AM, Maxime Ripard wrote:

Remember to use get_maintainers to send your patches, you missed a few
mailing lists (linux-arm-kernel, for example), developpers (Alexandre
Belloni, the original author of the driver) and maintainers (Linus
Walleij for the pinctrl changes).


Thanks for this tip and your review regarding splitting pinctrl patch. 
Let me prepare the 2nd patch-set.


Best regards,
Milo


[PATCH v3 5/5] gpu: drm: exynos_hdmi: Remove duplicate initialization of regulator bulk consumer

2016-08-24 Thread Milo Kim
The helper, devm_regulator_bulk_get() initializes the consumer as NULL,
so this code can be ignored.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 249cb23..4e17877f 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1669,10 +1669,9 @@ static int hdmi_resources_init(struct hdmi_context 
*hdata)
if (ret)
return ret;
 
-   for (i = 0; i < ARRAY_SIZE(supply); ++i) {
+   for (i = 0; i < ARRAY_SIZE(supply); ++i)
hdata->regul_bulk[i].supply = supply[i];
-   hdata->regul_bulk[i].consumer = NULL;
-   }
+
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), 
hdata->regul_bulk);
if (ret) {
if (ret != -EPROBE_DEFER)
-- 
1.9.1



[PATCH v3 4/5] gpu: drm: exynos_hdmi: Move PHY logic into single function

2016-08-24 Thread Milo Kim
Paring DT properties and getting PHY IO (memory mapped or I2C) in one function.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 63 +++-
 1 file changed, 33 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 8d99b5d..249cb23 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1790,16 +1790,44 @@ static int hdmi_get_ddc_adapter(struct hdmi_context 
*hdata)
return 0;
 }
 
-static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
+static int hdmi_get_phy_io(struct hdmi_context *hdata)
 {
const char *compatible_str = "samsung,exynos4212-hdmiphy";
+   struct device_node *np;
+   int ret = 0;
+
+   np = of_find_compatible_node(NULL, NULL, compatible_str);
+   if (!np) {
+   np = of_parse_phandle(hdata->dev->of_node, "phy", 0);
+   if (!np) {
+   DRM_ERROR("Failed to find hdmiphy node in device 
tree\n");
+   return -ENODEV;
+   }
+   }
+
+   if (hdata->drv_data->is_apb_phy) {
+   hdata->regs_hdmiphy = of_iomap(np, 0);
+   if (!hdata->regs_hdmiphy) {
+   DRM_ERROR("failed to ioremap hdmi phy\n");
+   ret = -ENOMEM;
+   goto out;
+   }
+   } else {
+   hdata->hdmiphy_port = of_find_i2c_device_by_node(np);
+   if (!hdata->hdmiphy_port) {
+   DRM_ERROR("Failed to get hdmi phy i2c client\n");
+   ret = -EPROBE_DEFER;
+   goto out;
+   }
+   }
 
-   return of_find_compatible_node(NULL, NULL, compatible_str);
+out:
+   of_node_put(np);
+   return ret;
 }
 
 static int hdmi_probe(struct platform_device *pdev)
 {
-   struct device_node *phy_node;
struct device *dev = >dev;
struct hdmi_context *hdata;
struct resource *res;
@@ -1833,34 +1861,9 @@ static int hdmi_probe(struct platform_device *pdev)
if (ret)
return ret;
 
-   phy_node = hdmi_legacy_phy_dt_binding(dev);
-   if (phy_node)
-   goto out_get_phy_port;
-
-   phy_node = of_parse_phandle(dev->of_node, "phy", 0);
-   if (!phy_node) {
-   DRM_ERROR("Failed to find hdmiphy node in device tree\n");
-   ret = -ENODEV;
+   ret = hdmi_get_phy_io(hdata);
+   if (ret)
goto err_ddc;
-   }
-   of_node_put(dev->of_node);
-
-out_get_phy_port:
-   if (hdata->drv_data->is_apb_phy) {
-   hdata->regs_hdmiphy = of_iomap(phy_node, 0);
-   if (!hdata->regs_hdmiphy) {
-   DRM_ERROR("failed to ioremap hdmi phy\n");
-   ret = -ENOMEM;
-   goto err_ddc;
-   }
-   } else {
-   hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
-   if (!hdata->hdmiphy_port) {
-   DRM_ERROR("Failed to get hdmi phy i2c client\n");
-   ret = -EPROBE_DEFER;
-   goto err_ddc;
-   }
-   }
 
INIT_DELAYED_WORK(>hotplug_work, hdmi_hotplug_work_func);
 
-- 
1.9.1



[PATCH v3 3/5] gpu: drm: exynos_hdmi: Move DDC logic into single function

2016-08-24 Thread Milo Kim
Paring DT properties and getting the I2C adapter in one function.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: David Airlie <airl...@linux.ie>
Cc: Inki Dae <inki@samsung.com>
Cc: Joonyoung Shim <jy0922.s...@samsung.com>
Cc: Seung-Woo Kim <sw0312@samsung.com>
Cc: Kyungmin Park <kyungmin.p...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 46 
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2275efe..8d99b5d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1760,16 +1760,34 @@ static const struct component_ops hdmi_component_ops = {
.unbind = hdmi_unbind,
 };
 
-static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
+static int hdmi_get_ddc_adapter(struct hdmi_context *hdata)
 {
const char *compatible_str = "samsung,exynos4210-hdmiddc";
struct device_node *np;
+   struct i2c_adapter *adpt;
 
np = of_find_compatible_node(NULL, NULL, compatible_str);
if (np)
-   return of_get_next_parent(np);
+   np = of_get_next_parent(np);
+   else
+   np = of_parse_phandle(hdata->dev->of_node, "ddc", 0);
+
+   if (!np) {
+   DRM_ERROR("Failed to find ddc node in device tree\n");
+   return -ENODEV;
+   }
 
-   return NULL;
+   adpt = of_find_i2c_adapter_by_node(np);
+   if (!adpt) {
+   DRM_ERROR("Failed to get ddc i2c adapter by node\n");
+   of_node_put(np);
+   return -EPROBE_DEFER;
+   }
+
+   hdata->ddc_adpt = adpt;
+   of_node_put(np);
+
+   return 0;
 }
 
 static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
@@ -1781,7 +1799,7 @@ static struct device_node 
*hdmi_legacy_phy_dt_binding(struct device *dev)
 
 static int hdmi_probe(struct platform_device *pdev)
 {
-   struct device_node *ddc_node, *phy_node;
+   struct device_node *phy_node;
struct device *dev = >dev;
struct hdmi_context *hdata;
struct resource *res;
@@ -1811,23 +1829,9 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}
 
-   ddc_node = hdmi_legacy_ddc_dt_binding(dev);
-   if (ddc_node)
-   goto out_get_ddc_adpt;
-
-   ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
-   if (!ddc_node) {
-   DRM_ERROR("Failed to find ddc node in device tree\n");
-   return -ENODEV;
-   }
-   of_node_put(dev->of_node);
-
-out_get_ddc_adpt:
-   hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
-   if (!hdata->ddc_adpt) {
-   DRM_ERROR("Failed to get ddc i2c adapter by node\n");
-   return -EPROBE_DEFER;
-   }
+   ret = hdmi_get_ddc_adapter(hdata);
+   if (ret)
+   return ret;
 
phy_node = hdmi_legacy_phy_dt_binding(dev);
if (phy_node)
-- 
1.9.1



[PATCH v3 2/5] ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'

2016-08-24 Thread Milo Kim
This patch enables getting a HPD GPIO descriptor quickly.
The exynos-hdmi driver uses "hpd" for HDMI hot plug detection.

static int hdmi_resources_init(struct hdmi_context *hdata)
{
...
hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
...
}

This calls 'of_find_gpio()' and it generates the GPIO consumer ID by referring
GPIO suffix. So 'hpd-gpios' is preferred on getting a GPIO descriptor.

However, if the device tree uses 'hpd-gpio', then the exynos-hdmi driver
always retries to get a GPIO descriptor because the first GPIO suffix is not
'gpio' but 'gpios'. So you always see the debug message below.

of_get_named_gpiod_flags: can't parse 'hpd-gpios' property of node 
'/soc/hdmi@1453[0]'

Use the preferred property, 'hpd-gpios' instead of 'hpd-gpio'.

Acked-by: Rob Herring <r...@kernel.org>
Reviewed-by: Andrzej Hajda <a.ha...@samsung.com>
Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt | 4 ++--
 arch/arm/boot/dts/exynos4210-universal_c210.dts  | 2 +-
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi  | 2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts | 2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts| 2 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi| 2 +-
 arch/arm/boot/dts/exynos5250-spring.dts  | 2 +-
 arch/arm/boot/dts/exynos5420-peach-pit.dts   | 2 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts| 2 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi   | 2 +-
 arch/arm/boot/dts/exynos5800-peach-pi.dts| 2 +-
 11 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt 
b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
index a2ec4c1..6394ea9 100644
--- a/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
@@ -9,7 +9,7 @@ Required properties:
 - reg: physical base address of the hdmi and length of memory mapped
region.
 - interrupts: interrupt number to the cpu.
-- hpd-gpio: following information about the hotplug gpio pin.
+- hpd-gpios: following information about the hotplug gpio pin.
a) phandle of the gpio controller node.
b) pin number within the gpio controller.
c) optional flags and pull up/down.
@@ -56,7 +56,7 @@ Example:
compatible = "samsung,exynos4212-hdmi";
reg = <0x1453 0x10>;
interrupts = <0 95 0>;
-   hpd-gpio = < 7 1>;
+   hpd-gpios = < 7 1>;
ddc = <_ddc_node>;
phy = <_phy_node>;
samsung,syscon-phandle = <_system_controller>;
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts 
b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index 9a75e3e..cf95202 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -269,7 +269,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_HIGH>;
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <_hpd>;
hdmi-en-supply = <_en>;
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi 
b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 58ad48e7..be644fe 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -227,7 +227,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_HIGH>;
+   hpd-gpios = < 7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <_hpd>;
vdd-supply = <_reg>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts 
b/arch/arm/boot/dts/exynos5250-arndale.dts
index ea70603..3d981f3 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -152,7 +152,7 @@
 };
 
  {
-   hpd-gpio = < 7 GPIO_ACTIVE_LOW>;
+   hpd-gpios = < 7 GPIO_ACTIVE_LOW>;
vdd_osc-supply = <_reg>;
vdd_pll-supply = <_reg>;
vdd-supply = <_reg>;
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts 
b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 381af13..7f27263 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -116,7 +116

[PATCH v3 1/5] ARM: dts: exynos: Enable HDMI for Arndale Octa board

2016-08-24 Thread Milo Kim
* GPIO for HDMI hot plug detect
  GPX3_7 is used. The HPD awareness is done when the GPIO is active high and
  single ended.

* Enable HDMI block in Exynos5420
  HDMI VDD and PLL consume 1.0V LDO6 (PVDD_ANAIP_1V0) and HDMI oscillator
  requires 1.8V LDO7 (PVDD_ANAIP_1V8).

* Support HDMI display data channel
  I2C #2 is assigned for the HDMI DDC. It enables the EDID access.

Cc: Kukjin Kim <kg...@kernel.org>
Cc: Krzysztof Kozlowski <k.kozlow...@samsung.com>
Cc: Rob Herring <robh...@kernel.org>
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/exynos5420-arndale-octa.dts | 13 +
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts 
b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 39a3b81..2fb5708 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -70,6 +70,19 @@
status = "disabled";
 };
 
+ {
+   hpd-gpios = < 7 GPIO_OPEN_SOURCE>;
+   vdd_osc-supply = <_reg>;
+   vdd_pll-supply = <_reg>;
+   vdd-supply = <_reg>;
+   ddc = <_2>;
+   status = "okay";
+};
+
+_2 {
+   status = "okay";
+};
+
 _4 {
status = "okay";
 
-- 
1.9.1



[PATCH v3 0/5] ARM: dts: exynos: Enable HDMI in Arndale Octa board

2016-08-24 Thread Milo Kim
This patch-set enables HDMI in Arndale Octa board and fixes HPD DT property.
It also includes code refactoring on ddc and phy.

v3:
  Add 'vdd-supply' property in dts.
  Use generic 'ddc' property instead of legacy property.
  Clean up DDC and PHY logic in _probe().
  Remove duplicate code of regulator consumer initialization.

v2:
  Include DRM and Exynos maintainers and resend the patch-set.
  Add Rob's ack for the patch,
[PATCH 2/4] ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'

Milo Kim (5):
  ARM: dts: exynos: Enable HDMI for Arndale Octa board
  ARM: dts: exynos: Use 'hpd-gpios' instead of 'hpd-gpio'
  gpu: drm: exynos_hdmi: Move DDC logic into single function
  gpu: drm: exynos_hdmi: Move PHY logic into single function
  gpu: drm: exynos_hdmi: Remove duplicate initialization of regulator
bulk consumer

 .../bindings/display/exynos/exynos_hdmi.txt|   4 +-
 arch/arm/boot/dts/exynos4210-universal_c210.dts|   2 +-
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi|   2 +-
 arch/arm/boot/dts/exynos5250-arndale.dts   |   2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts  |   2 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi  |   2 +-
 arch/arm/boot/dts/exynos5250-spring.dts|   2 +-
 arch/arm/boot/dts/exynos5420-arndale-octa.dts  |  13 +++
 arch/arm/boot/dts/exynos5420-peach-pit.dts |   2 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts  |   2 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |   2 +-
 arch/arm/boot/dts/exynos5800-peach-pi.dts  |   2 +-
 drivers/gpu/drm/exynos/exynos_hdmi.c   | 112 +++--
 13 files changed, 84 insertions(+), 65 deletions(-)

-- 
1.9.1



[PATCH 1/3] ARM: dts: sun8i: Add common dtsi file for NanoPi SBCs

2016-10-20 Thread Milo Kim
This patch provides a common file for NanoPi M1 and Neo SBC.

Those have common features below.
  * UART0
  * 2 LEDs
  * USB host (EHCI3, OHCI3) and PHY
  * MicroSD
  * GPIO key switch

Cc: James Pettigrew <ja...@innovum.com.au>
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi | 143 +
 1 file changed, 143 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi

diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi 
b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
new file mode 100644
index 000..e89ca6f
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 Milo Kim <woogyom@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include 
+#include 
+#include 
+
+/ {
+   aliases {
+   serial0 = 
+   };
+
+   chosen {
+   stdout-path = "serial0:115200n8";
+   };
+
+   leds {
+   compatible = "gpio-leds";
+   pinctrl-names = "default";
+   pinctrl-0 = <_npi>, <_r_npi>;
+
+   status {
+   label = "nanopi:blue:status";
+   gpios = < 0 10 GPIO_ACTIVE_HIGH>;
+   linux,default-trigger = "heartbeat";
+   };
+
+   pwr {
+   label = "nanopi:green:pwr";
+   gpios = <_pio 0 10 GPIO_ACTIVE_HIGH>;
+   default-state = "on";
+   };
+   };
+
+   r_gpio_keys {
+   compatible = "gpio-keys";
+   input-name = "k1";
+   pinctrl-names = "default";
+   pinctrl-0 = <_r_npi>;
+
+   k1@0 {
+   label = "k1";
+   linux,code = ;
+   gpios = <_pio 0 3 GPIO_ACTIVE_LOW>;
+   };
+   };
+};
+
+ {
+   status = "okay";
+};
+
+ {
+   bus-width = <4>;
+   cd-gpios = < 5 6 GPIO_ACTIVE_HIGH>;
+   cd-inverted;
+   pinctrl-names = "default";
+   pinctrl-0 = <_pins_a>, <_cd_pin>;
+   status = "okay";
+   vmmc-supply = <_vcc3v3>;
+};
+
+ {
+   status = "okay";
+};
+
+ {
+   leds_npi: led_pins@0 {
+   allwinner,pins = "PA10";
+   allwinner,function = "gpio_out";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+};
+
+_pio {
+   leds_r_npi: led_pins@0 {
+   allwinner,pins = "PL10";
+   allwinner,function = "gpio_out";
+   allwinner,drive = ;
+   allwinner,pull = ;
+   };
+
+   sw_r_npi: ke

[PATCH 0/3] ARM: dts: sun8i: Support NanoPi SBCs

2016-10-20 Thread Milo Kim
NanoPi M1 and NEO have common features, so duplicate properties can be 
moved into new dtsi file.

Milo Kim (3):
  ARM: dts: sun8i: Add common dtsi file for NanoPi SBCs
  ARM: dts: sun8i: Use the common file in NanoPi NEO SBC
  ARM: dts: sun8i: Add dts file for NanoPi M1 SBC

 arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts  |  64 +
 arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts |  79 +
 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi| 143 ++
 3 files changed, 208 insertions(+), 78 deletions(-)
 create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
 create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi

-- 
2.9.3



[PATCH 3/3] ARM: dts: sun8i: Add dts file for NanoPi M1 SBC

2016-10-20 Thread Milo Kim
NanoPi M1 is the Allwinner H3 based board.
This patch enables UART for debug console, LEDs, GPIO key switch, 3 USB
host ports, a micro SD slot and related power and pin controls.

Cc: James Pettigrew <ja...@innovum.com.au>
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 64 
 1 file changed, 64 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts

diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts 
b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
new file mode 100644
index 000..ec63d10
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Milo Kim <woogyom@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sun8i-h3-nanopi.dtsi"
+
+/ {
+   model = "FriendlyArm NanoPi M1";
+   compatible = "friendlyarm,nanopi-m1", "allwinner,sun8i-h3";
+};
+
+ {
+   status = "okay";
+};
+
+ {
+   status = "okay";
+};
+
+ {
+   status = "okay";
+};
+
+ {
+   status = "okay";
+};
-- 
2.9.3



[PATCH 2/3] ARM: dts: sun8i: Use the common file in NanoPi NEO SBC

2016-10-20 Thread Milo Kim
Cc: James Pettigrew <ja...@innovum.com.au>
Signed-off-by: Milo Kim <woogyom@gmail.com>
---
 arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 79 +--
 1 file changed, 1 insertion(+), 78 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts 
b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
index 3d64caf..8d2cc6e 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
@@ -40,86 +40,9 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/dts-v1/;
-#include "sun8i-h3.dtsi"
-#include "sunxi-common-regulators.dtsi"
-
-#include 
-#include 
+#include "sun8i-h3-nanopi.dtsi"
 
 / {
model = "FriendlyARM NanoPi NEO";
compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
-
-   aliases {
-   serial0 = 
-   };
-
-   chosen {
-   stdout-path = "serial0:115200n8";
-   };
-
-   leds {
-   compatible = "gpio-leds";
-   pinctrl-names = "default";
-   pinctrl-0 = <_opc>, <_r_opc>;
-
-   pwr {
-   label = "nanopi:green:pwr";
-   gpios = <_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
-   default-state = "on";
-   };
-
-   status {
-   label = "nanopi:blue:status";
-   gpios = < 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */
-   };
-   };
-};
-
- {
-   status = "okay";
-};
-
- {
-   pinctrl-names = "default";
-   pinctrl-0 = <_pins_a>, <_cd_pin>;
-   vmmc-supply = <_vcc3v3>;
-   bus-width = <4>;
-   cd-gpios = < 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
-   cd-inverted;
-   status = "okay";
-};
-
- {
-   status = "okay";
-};
-
- {
-   leds_opc: led-pins {
-   allwinner,pins = "PA10";
-   allwinner,function = "gpio_out";
-   allwinner,drive = ;
-   allwinner,pull = ;
-   };
-};
-
-_pio {
-   leds_r_opc: led-pins {
-   allwinner,pins = "PL10";
-   allwinner,function = "gpio_out";
-   allwinner,drive = ;
-   allwinner,pull = ;
-   };
-};
-
- {
-   pinctrl-names = "default";
-   pinctrl-0 = <_pins_a>;
-   status = "okay";
-};
-
- {
-   /* USB VBUS is always on */
-   status = "okay";
 };
-- 
2.9.3



Re: [PATCH 1/3] ARM: dts: sun8i: Add common dtsi file for NanoPi SBCs

2016-10-21 Thread Milo Kim

On 10/21/2016 01:04 AM, Maxime Ripard wrote:

+ * Copyright (C) 2016 Milo Kim <woogyom@gmail.com>

This looks like a copy of James' DT. Keeping him as the copyright
holder seems like the right thing to do.


Oh... thanks for catching this. Sorry to James.

Best regards,
Milo


Re: [PATCH 2/3] spi: sun6i: Support Allwinner H3 SPI controller

2016-10-21 Thread Milo Kim

On 10/21/2016 12:53 AM, Chen-Yu Tsai wrote:

Use of_device_get_match_data, then you don't even have to move sun6i_spi_match
above this function.


Oh, good. Thanks for introducing this helper.

Best regards,
Milo


<    1   2   3   4   5   6   7   >