serial: sh-sci: Drop the interface clock
As no platform defines an interface clock the SCI driver always falls back to a clock named "peripheral_clk". - On SH platforms that clock is the base clock for the SCI functional clock and has the same frequency, - On ARM platforms that clock doesn't exist, and clk_get() will return the default clock for the device. We can thus make the functional clock mandatory and drop the interface clock. EPROBE_DEFER is handled for clocks that may be referenced from DT (i.e. "fck", and the deprecated "sci_ick"). Cc: devicetree@vger.kernel.org Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Simon Horman <horms+renesas@verge.net.au> [geert: Handle EPROBE_DEFER, reformat description, break long comment line] Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Rob Herring <robh@kernel.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Geert Uytterhoeven

parent
8005c49d9a
commit
a9ec81f4ed
@@ -42,7 +42,7 @@ Required properties:
|
|||||||
|
|
||||||
- clocks: Must contain a phandle and clock-specifier pair for each entry
|
- clocks: Must contain a phandle and clock-specifier pair for each entry
|
||||||
in clock-names.
|
in clock-names.
|
||||||
- clock-names: Must contain "sci_ick" for the SCIx UART interface clock.
|
- clock-names: Must contain "fck" for the SCIx UART functional clock.
|
||||||
|
|
||||||
Note: Each enabled SCIx UART should have an alias correctly numbered in the
|
Note: Each enabled SCIx UART should have an alias correctly numbered in the
|
||||||
"aliases" node.
|
"aliases" node.
|
||||||
@@ -63,7 +63,7 @@ Example:
|
|||||||
interrupt-parent = <&gic>;
|
interrupt-parent = <&gic>;
|
||||||
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
|
clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
|
||||||
clock-names = "sci_ick";
|
clock-names = "fck";
|
||||||
dmas = <&dmac0 0x21>, <&dmac0 0x22>;
|
dmas = <&dmac0 0x21>, <&dmac0 0x22>;
|
||||||
dma-names = "tx", "rx";
|
dma-names = "tx", "rx";
|
||||||
};
|
};
|
||||||
|
@@ -92,8 +92,6 @@ struct sci_port {
|
|||||||
struct timer_list break_timer;
|
struct timer_list break_timer;
|
||||||
int break_flag;
|
int break_flag;
|
||||||
|
|
||||||
/* Interface clock */
|
|
||||||
struct clk *iclk;
|
|
||||||
/* Function clock */
|
/* Function clock */
|
||||||
struct clk *fclk;
|
struct clk *fclk;
|
||||||
|
|
||||||
@@ -457,9 +455,8 @@ static void sci_port_enable(struct sci_port *sci_port)
|
|||||||
|
|
||||||
pm_runtime_get_sync(sci_port->port.dev);
|
pm_runtime_get_sync(sci_port->port.dev);
|
||||||
|
|
||||||
clk_prepare_enable(sci_port->iclk);
|
|
||||||
sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
|
|
||||||
clk_prepare_enable(sci_port->fclk);
|
clk_prepare_enable(sci_port->fclk);
|
||||||
|
sci_port->port.uartclk = clk_get_rate(sci_port->fclk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sci_port_disable(struct sci_port *sci_port)
|
static void sci_port_disable(struct sci_port *sci_port)
|
||||||
@@ -476,7 +473,6 @@ static void sci_port_disable(struct sci_port *sci_port)
|
|||||||
sci_port->break_flag = 0;
|
sci_port->break_flag = 0;
|
||||||
|
|
||||||
clk_disable_unprepare(sci_port->fclk);
|
clk_disable_unprepare(sci_port->fclk);
|
||||||
clk_disable_unprepare(sci_port->iclk);
|
|
||||||
|
|
||||||
pm_runtime_put_sync(sci_port->port.dev);
|
pm_runtime_put_sync(sci_port->port.dev);
|
||||||
}
|
}
|
||||||
@@ -1622,7 +1618,7 @@ static int sci_notifier(struct notifier_block *self,
|
|||||||
struct uart_port *port = &sci_port->port;
|
struct uart_port *port = &sci_port->port;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
port->uartclk = clk_get_rate(sci_port->iclk);
|
port->uartclk = clk_get_rate(sci_port->fclk);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2241,6 +2237,42 @@ static struct uart_ops sci_uart_ops = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
|
||||||
|
{
|
||||||
|
/* Get the SCI functional clock. It's called "fck" on ARM. */
|
||||||
|
sci_port->fclk = clk_get(dev, "fck");
|
||||||
|
if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
if (!IS_ERR(sci_port->fclk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* But it used to be called "sci_ick", and we need to maintain DT
|
||||||
|
* backward compatibility.
|
||||||
|
*/
|
||||||
|
sci_port->fclk = clk_get(dev, "sci_ick");
|
||||||
|
if (PTR_ERR(sci_port->fclk) == -EPROBE_DEFER)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
if (!IS_ERR(sci_port->fclk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* SH has historically named the clock "sci_fck". */
|
||||||
|
sci_port->fclk = clk_get(dev, "sci_fck");
|
||||||
|
if (!IS_ERR(sci_port->fclk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not all SH platforms declare a clock lookup entry for SCI devices,
|
||||||
|
* in which case we need to get the global "peripheral_clk" clock.
|
||||||
|
*/
|
||||||
|
sci_port->fclk = clk_get(dev, "peripheral_clk");
|
||||||
|
if (!IS_ERR(sci_port->fclk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dev_err(dev, "failed to get functional clock\n");
|
||||||
|
return PTR_ERR(sci_port->fclk);
|
||||||
|
}
|
||||||
|
|
||||||
static int sci_init_single(struct platform_device *dev,
|
static int sci_init_single(struct platform_device *dev,
|
||||||
struct sci_port *sci_port, unsigned int index,
|
struct sci_port *sci_port, unsigned int index,
|
||||||
struct plat_sci_port *p, bool early)
|
struct plat_sci_port *p, bool early)
|
||||||
@@ -2333,22 +2365,9 @@ static int sci_init_single(struct platform_device *dev,
|
|||||||
sci_port->sampling_rate = p->sampling_rate;
|
sci_port->sampling_rate = p->sampling_rate;
|
||||||
|
|
||||||
if (!early) {
|
if (!early) {
|
||||||
sci_port->iclk = clk_get(&dev->dev, "sci_ick");
|
ret = sci_init_clocks(sci_port, &dev->dev);
|
||||||
if (IS_ERR(sci_port->iclk)) {
|
if (ret < 0)
|
||||||
sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
|
return ret;
|
||||||
if (IS_ERR(sci_port->iclk)) {
|
|
||||||
dev_err(&dev->dev, "can't get iclk\n");
|
|
||||||
return PTR_ERR(sci_port->iclk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The function clock is optional, ignore it if we can't
|
|
||||||
* find it.
|
|
||||||
*/
|
|
||||||
sci_port->fclk = clk_get(&dev->dev, "sci_fck");
|
|
||||||
if (IS_ERR(sci_port->fclk))
|
|
||||||
sci_port->fclk = NULL;
|
|
||||||
|
|
||||||
port->dev = &dev->dev;
|
port->dev = &dev->dev;
|
||||||
|
|
||||||
@@ -2405,7 +2424,6 @@ static int sci_init_single(struct platform_device *dev,
|
|||||||
|
|
||||||
static void sci_cleanup_single(struct sci_port *port)
|
static void sci_cleanup_single(struct sci_port *port)
|
||||||
{
|
{
|
||||||
clk_put(port->iclk);
|
|
||||||
clk_put(port->fclk);
|
clk_put(port->fclk);
|
||||||
|
|
||||||
pm_runtime_disable(port->port.dev);
|
pm_runtime_disable(port->port.dev);
|
||||||
|
Reference in New Issue
Block a user