Re: [PATCH v4 02/31] serial: mpc512x: cleanup clock API use

2013-08-21 Thread Anatolij Gustschin
On Tue,  6 Aug 2013 22:43:42 +0200
Gerhard Sittig  wrote:

> cleanup the clock API use of the UART driver which is shared among the
> MPC512x and the MPC5200 platforms
> - get, prepare, and enable the MCLK during port allocation; disable,
>   unprepare and put the MCLK upon port release; hold a reference to the
>   clock over the period of use; check for and propagate enable errors
> - fix a buffer overflow for clock names with two digit PSC index numbers
> - stick with the PPC_CLOCK 'psc%d_mclk' name for clock lookup, only
>   switch to a fixed string later after device tree based clock lookup
>   will have become available
> 
> to achieve support for MPC512x which is neutral to MPC5200, the
> modification was done as follows
> - introduce "clock alloc" and "clock release" routines in addition to
>   the previous "clock enable/disable" routine in the psc_ops struct
> - make the clock allocation a part of the port request (resource
>   allocation), and make clock release a part of the port release, such
>   that essential resources get allocated early
> - just enable/disable the clock from within the .clock() callback
>   without any allocation or preparation as the former implementation
>   did, since this routine is called from within the startup and shutdown
>   callbacks
> - all of the above remains a NOP for the MPC5200 platform (no callbacks
>   are provided on that platform)
> - implementation note: the clock gets enabled upon allocation already
>   just in case the clock is not only required for bitrate generation but
>   for register access as well
> 
> Signed-off-by: Gerhard Sittig 
> ---
>  drivers/tty/serial/mpc52xx_uart.c |   98 
> ++---
>  1 file changed, 81 insertions(+), 17 deletions(-)

applied, thanks!

Anatolij
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH v4 02/31] serial: mpc512x: cleanup clock API use

2013-08-12 Thread Greg Kroah-Hartman
On Tue, Aug 06, 2013 at 10:43:42PM +0200, Gerhard Sittig wrote:
> cleanup the clock API use of the UART driver which is shared among the
> MPC512x and the MPC5200 platforms
> - get, prepare, and enable the MCLK during port allocation; disable,
>   unprepare and put the MCLK upon port release; hold a reference to the
>   clock over the period of use; check for and propagate enable errors
> - fix a buffer overflow for clock names with two digit PSC index numbers
> - stick with the PPC_CLOCK 'psc%d_mclk' name for clock lookup, only
>   switch to a fixed string later after device tree based clock lookup
>   will have become available
> 
> to achieve support for MPC512x which is neutral to MPC5200, the
> modification was done as follows
> - introduce "clock alloc" and "clock release" routines in addition to
>   the previous "clock enable/disable" routine in the psc_ops struct
> - make the clock allocation a part of the port request (resource
>   allocation), and make clock release a part of the port release, such
>   that essential resources get allocated early
> - just enable/disable the clock from within the .clock() callback
>   without any allocation or preparation as the former implementation
>   did, since this routine is called from within the startup and shutdown
>   callbacks
> - all of the above remains a NOP for the MPC5200 platform (no callbacks
>   are provided on that platform)
> - implementation note: the clock gets enabled upon allocation already
>   just in case the clock is not only required for bitrate generation but
>   for register access as well
> 
> Signed-off-by: Gerhard Sittig 

Acked-by: Greg Kroah-Hartman 

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v4 02/31] serial: mpc512x: cleanup clock API use

2013-08-06 Thread Gerhard Sittig
cleanup the clock API use of the UART driver which is shared among the
MPC512x and the MPC5200 platforms
- get, prepare, and enable the MCLK during port allocation; disable,
  unprepare and put the MCLK upon port release; hold a reference to the
  clock over the period of use; check for and propagate enable errors
- fix a buffer overflow for clock names with two digit PSC index numbers
- stick with the PPC_CLOCK 'psc%d_mclk' name for clock lookup, only
  switch to a fixed string later after device tree based clock lookup
  will have become available

to achieve support for MPC512x which is neutral to MPC5200, the
modification was done as follows
- introduce "clock alloc" and "clock release" routines in addition to
  the previous "clock enable/disable" routine in the psc_ops struct
- make the clock allocation a part of the port request (resource
  allocation), and make clock release a part of the port release, such
  that essential resources get allocated early
- just enable/disable the clock from within the .clock() callback
  without any allocation or preparation as the former implementation
  did, since this routine is called from within the startup and shutdown
  callbacks
- all of the above remains a NOP for the MPC5200 platform (no callbacks
  are provided on that platform)
- implementation note: the clock gets enabled upon allocation already
  just in case the clock is not only required for bitrate generation but
  for register access as well

Signed-off-by: Gerhard Sittig 
---
 drivers/tty/serial/mpc52xx_uart.c |   98 ++---
 1 file changed, 81 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c 
b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..5be1df3 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -107,6 +107,8 @@ struct psc_ops {
unsigned int(*set_baudrate)(struct uart_port *port,
struct ktermios *new,
struct ktermios *old);
+   int (*clock_alloc)(struct uart_port *port);
+   void(*clock_relse)(struct uart_port *port);
int (*clock)(struct uart_port *port, int enable);
int (*fifoc_init)(void);
void(*fifoc_uninit)(void);
@@ -616,31 +618,73 @@ static irqreturn_t mpc512x_psc_handle_irq(struct 
uart_port *port)
return IRQ_NONE;
 }
 
-static int mpc512x_psc_clock(struct uart_port *port, int enable)
+static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM];
+
+/* called from within the .request_port() callback (allocation) */
+static int mpc512x_psc_alloc_clock(struct uart_port *port)
 {
-   struct clk *psc_clk;
int psc_num;
-   char clk_name[10];
+   char clk_name[16];
+   struct clk *clk;
+   int err;
+
+   psc_num = (port->mapbase & 0xf00) >> 8;
+   snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+   clk = devm_clk_get(port->dev, clk_name);
+   if (IS_ERR(clk)) {
+   dev_err(port->dev, "Failed to get MCLK!\n");
+   return PTR_ERR(clk);
+   }
+   err = clk_prepare_enable(clk);
+   if (err) {
+   dev_err(port->dev, "Failed to enable MCLK!\n");
+   return err;
+   }
+   psc_mclk_clk[psc_num] = clk;
+   return 0;
+}
+
+/* called from within the .release_port() callback (release) */
+static void mpc512x_psc_relse_clock(struct uart_port *port)
+{
+   int psc_num;
+   struct clk *clk;
+
+   psc_num = (port->mapbase & 0xf00) >> 8;
+   clk = psc_mclk_clk[psc_num];
+   if (clk) {
+   clk_disable_unprepare(clk);
+   psc_mclk_clk[psc_num] = NULL;
+   }
+}
+
+/* implementation of the .clock() callback (enable/disable) */
+static int mpc512x_psc_endis_clock(struct uart_port *port, int enable)
+{
+   int psc_num;
+   struct clk *psc_clk;
+   int ret;
 
if (uart_console(port))
return 0;
 
psc_num = (port->mapbase & 0xf00) >> 8;
-   snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-   psc_clk = clk_get(port->dev, clk_name);
-   if (IS_ERR(psc_clk)) {
+   psc_clk = psc_mclk_clk[psc_num];
+   if (!psc_clk) {
dev_err(port->dev, "Failed to get PSC clock entry!\n");
return -ENODEV;
}
 
-   dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis");
-
-   if (enable)
-   clk_enable(psc_clk);
-   else
+   dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis");
+   if (enable) {
+   ret = clk_enable(psc_clk);
+   if (ret)
+   dev_err(port->dev, "Failed to enable MCLK!\n");
+   return ret;
+   } else {
clk_disable(psc_clk);
-
-   return 0;
+   return 0;
+   }
 }
 
 static void mpc512x_psc_get_irq(struct uart_port *por