This series adds support obtain clk frequency of functional clk via
clocks phandle instead of hard coding it in DT as part of
clock-frequency DT parameter. This eliminates need to calculate
frequency offline and populate it.
Vignesh R (3):
serial: 8250_omap: Drop check for of_node
dt-bindings: serial: omap_serial: add clocks entry
serial: 8250_omap: Use clk_get_rate() to obtain fclk frequency
.../bindings/serial/omap_serial.txt | 2 +
drivers/tty/serial/8250/8250_omap.c | 75 ++++++++++---------
2 files changed, 42 insertions(+), 35 deletions(-)
--
2.20.1
Document clocks property used to pass phandle to functional clk.
Signed-off-by: Vignesh R <[email protected]>
---
Documentation/devicetree/bindings/serial/omap_serial.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/serial/omap_serial.txt b/Documentation/devicetree/bindings/serial/omap_serial.txt
index c35d5ece1156..0a9b5444f4e6 100644
--- a/Documentation/devicetree/bindings/serial/omap_serial.txt
+++ b/Documentation/devicetree/bindings/serial/omap_serial.txt
@@ -22,6 +22,8 @@ Optional properties:
- dma-names : "rx" for receive channel, "tx" for transmit channel.
- rs485-rts-delay, rs485-rx-during-tx, linux,rs485-enabled-at-boot-time: see rs485.txt
- rs485-rts-active-high: drive RTS high when sending (default is low).
+- clocks: phandle to the functional clock as per
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
Example:
--
2.20.1
8250_omap driver uses clock-frequency DT property to obtain functional
clk frequency. This is not ideal as users need to calculate functional
clk frequency offline and populate it in DT.
Therefore add support to obtain functional clock frequency using clk
APIs when clock-frequency DT property is not defined.
Suggested-by: Lokesh Vutla <[email protected]>
Signed-off-by: Vignesh R <[email protected]>
---
drivers/tty/serial/8250/8250_omap.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index a74126569785..0a8316632d75 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -12,6 +12,7 @@
#define SUPPORT_SYSRQ
#endif
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -1203,7 +1204,18 @@ static int omap8250_probe(struct platform_device *pdev)
}
up.port.line = ret;
- of_property_read_u32(np, "clock-frequency", &up.port.uartclk);
+ if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) {
+ struct clk *clk;
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ } else {
+ up.port.uartclk = clk_get_rate(clk);
+ }
+ }
+
priv->wakeirq = irq_of_parse_and_map(np, 1);
id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
--
2.20.1
8250_omap is DT only driver so dev->of_node always exists. Drop check
for existence of valid dev->of_node to simplify omap8250_probe().
Signed-off-by: Vignesh R <[email protected]>
---
drivers/tty/serial/8250/8250_omap.c | 63 +++++++++++++----------------
1 file changed, 28 insertions(+), 35 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index ad7ba7d0f28d..a74126569785 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1134,10 +1134,12 @@ static int omap8250_probe(struct platform_device *pdev)
{
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ struct device_node *np = pdev->dev.of_node;
struct omap8250_priv *priv;
struct uart_8250_port up;
int ret;
void __iomem *membase;
+ const struct of_device_id *id;
if (!regs || !irq) {
dev_err(&pdev->dev, "missing registers or irq\n");
@@ -1194,27 +1196,20 @@ static int omap8250_probe(struct platform_device *pdev)
up.port.unthrottle = omap_8250_unthrottle;
up.port.rs485_config = omap_8250_rs485_config;
- if (pdev->dev.of_node) {
- const struct of_device_id *id;
-
- ret = of_alias_get_id(pdev->dev.of_node, "serial");
-
- of_property_read_u32(pdev->dev.of_node, "clock-frequency",
- &up.port.uartclk);
- priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
-
- id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
- if (id && id->data)
- priv->habit |= *(u8 *)id->data;
- } else {
- ret = pdev->id;
- }
+ ret = of_alias_get_id(np, "serial");
if (ret < 0) {
- dev_err(&pdev->dev, "failed to get alias/pdev id\n");
+ dev_err(&pdev->dev, "failed to get alias\n");
return ret;
}
up.port.line = ret;
+ of_property_read_u32(np, "clock-frequency", &up.port.uartclk);
+ priv->wakeirq = irq_of_parse_and_map(np, 1);
+
+ id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
+ if (id && id->data)
+ priv->habit |= *(u8 *)id->data;
+
if (!up.port.uartclk) {
up.port.uartclk = DEFAULT_CLK_SPEED;
dev_warn(&pdev->dev,
@@ -1242,25 +1237,23 @@ static int omap8250_probe(struct platform_device *pdev)
omap_serial_fill_features_erratas(&up, priv);
up.port.handle_irq = omap8250_no_handle_irq;
#ifdef CONFIG_SERIAL_8250_DMA
- if (pdev->dev.of_node) {
- /*
- * Oh DMA support. If there are no DMA properties in the DT then
- * we will fall back to a generic DMA channel which does not
- * really work here. To ensure that we do not get a generic DMA
- * channel assigned, we have the the_no_dma_filter_fn() here.
- * To avoid "failed to request DMA" messages we check for DMA
- * properties in DT.
- */
- ret = of_property_count_strings(pdev->dev.of_node, "dma-names");
- if (ret == 2) {
- up.dma = &priv->omap8250_dma;
- priv->omap8250_dma.fn = the_no_dma_filter_fn;
- priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
- priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
- priv->omap8250_dma.rx_size = RX_TRIGGER;
- priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
- priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
- }
+ /*
+ * Oh DMA support. If there are no DMA properties in the DT then
+ * we will fall back to a generic DMA channel which does not
+ * really work here. To ensure that we do not get a generic DMA
+ * channel assigned, we have the the_no_dma_filter_fn() here.
+ * To avoid "failed to request DMA" messages we check for DMA
+ * properties in DT.
+ */
+ ret = of_property_count_strings(np, "dma-names");
+ if (ret == 2) {
+ up.dma = &priv->omap8250_dma;
+ priv->omap8250_dma.fn = the_no_dma_filter_fn;
+ priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
+ priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
+ priv->omap8250_dma.rx_size = RX_TRIGGER;
+ priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER;
+ priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER;
}
#endif
ret = serial8250_register_8250_port(&up);
--
2.20.1
* Vignesh R <[email protected]> [190109 09:11]:
> 8250_omap is DT only driver so dev->of_node always exists. Drop check
> for existence of valid dev->of_node to simplify omap8250_probe().
That part seems safe to me now.
> --- a/drivers/tty/serial/8250/8250_omap.c
> +++ b/drivers/tty/serial/8250/8250_omap.c
...
> - const struct of_device_id *id;
> -
> - ret = of_alias_get_id(pdev->dev.of_node, "serial");
> -
> - of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> - &up.port.uartclk);
> - priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
> -
> - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
> - if (id && id->data)
> - priv->habit |= *(u8 *)id->data;
But this part it seems we still need to keep around
as we still have lots of clock-frequency references
in the *.dtsi files. Or am I missing something?
Regards
Tony
On 10-Jan-19 5:37 PM, Sebastian Reichel wrote:
> Hi,
>
> On Wed, Jan 09, 2019 at 01:44:03PM -0800, Tony Lindgren wrote:
>> * Vignesh R <[email protected]> [190109 09:11]:
>>> 8250_omap is DT only driver so dev->of_node always exists. Drop check
>>> for existence of valid dev->of_node to simplify omap8250_probe().
>>
>> That part seems safe to me now.
>>
>>> --- a/drivers/tty/serial/8250/8250_omap.c
>>> +++ b/drivers/tty/serial/8250/8250_omap.c
>> ...
>>> - const struct of_device_id *id;
>>> -
>>> - ret = of_alias_get_id(pdev->dev.of_node, "serial");
>>> -
>>> - of_property_read_u32(pdev->dev.of_node, "clock-frequency",
>>> - &up.port.uartclk);
>>> - priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
>>> -
>>> - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
>>> - if (id && id->data)
>>> - priv->habit |= *(u8 *)id->data;
>>
>> But this part it seems we still need to keep around
>> as we still have lots of clock-frequency references
>> in the *.dtsi files. Or am I missing something?
>
> It's re-added a couple of lines later. Only the indent was removed.
>
That's right. You beat me to it. Thanks :)
Regards
Vignesh
Hi,
On Wed, Jan 09, 2019 at 01:44:03PM -0800, Tony Lindgren wrote:
> * Vignesh R <[email protected]> [190109 09:11]:
> > 8250_omap is DT only driver so dev->of_node always exists. Drop check
> > for existence of valid dev->of_node to simplify omap8250_probe().
>
> That part seems safe to me now.
>
> > --- a/drivers/tty/serial/8250/8250_omap.c
> > +++ b/drivers/tty/serial/8250/8250_omap.c
> ...
> > - const struct of_device_id *id;
> > -
> > - ret = of_alias_get_id(pdev->dev.of_node, "serial");
> > -
> > - of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> > - &up.port.uartclk);
> > - priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
> > -
> > - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
> > - if (id && id->data)
> > - priv->habit |= *(u8 *)id->data;
>
> But this part it seems we still need to keep around
> as we still have lots of clock-frequency references
> in the *.dtsi files. Or am I missing something?
It's re-added a couple of lines later. Only the indent was removed.
-- Sebastian
* Vignesh R <[email protected]> [190110 13:24]:
>
> On 10-Jan-19 5:37 PM, Sebastian Reichel wrote:
> > Hi,
> >
> > On Wed, Jan 09, 2019 at 01:44:03PM -0800, Tony Lindgren wrote:
> >> * Vignesh R <[email protected]> [190109 09:11]:
> >>> 8250_omap is DT only driver so dev->of_node always exists. Drop check
> >>> for existence of valid dev->of_node to simplify omap8250_probe().
> >>
> >> That part seems safe to me now.
> >>
> >>> --- a/drivers/tty/serial/8250/8250_omap.c
> >>> +++ b/drivers/tty/serial/8250/8250_omap.c
> >> ...
> >>> - const struct of_device_id *id;
> >>> -
> >>> - ret = of_alias_get_id(pdev->dev.of_node, "serial");
> >>> -
> >>> - of_property_read_u32(pdev->dev.of_node, "clock-frequency",
> >>> - &up.port.uartclk);
> >>> - priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
> >>> -
> >>> - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
> >>> - if (id && id->data)
> >>> - priv->habit |= *(u8 *)id->data;
> >>
> >> But this part it seems we still need to keep around
> >> as we still have lots of clock-frequency references
> >> in the *.dtsi files. Or am I missing something?
> >
> > It's re-added a couple of lines later. Only the indent was removed.
> >
>
> That's right. You beat me to it. Thanks :)
Oh right, sorry I missed that :)
Regards,
Tony
On Wed, 9 Jan 2019 14:42:05 +0530, Vignesh R wrote:
> Document clocks property used to pass phandle to functional clk.
>
> Signed-off-by: Vignesh R <[email protected]>
> ---
> Documentation/devicetree/bindings/serial/omap_serial.txt | 2 ++
> 1 file changed, 2 insertions(+)
>
Reviewed-by: Rob Herring <[email protected]>