[RFC 1/4] of: add of_dev_get_platdata()
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()
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()
'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()
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()
/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
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
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
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
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
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
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
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
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
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
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
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
'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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
* 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
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
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
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
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
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
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
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
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'
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
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
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
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
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
* 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
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'
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
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
* 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
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
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
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
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
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
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'
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
* 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
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
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
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
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
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
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
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