All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/24] add COMMON_CLK support for PowerPC MPC512x
@ 2013-07-15 18:47 ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this series introduces support for the common clock framework (CCF,
COMMON_CLK Kconfig option) in the PowerPC based MPC512x platform, a
resulting debugfs clk_summary is at the end of the message after the
stats

although the series does touch several subsystems -- serial, spi, net
(can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of the
patches are strictly clock related, changes outside of the clock driver
in the mpc512x platform are rather small and local to probe and setup

the distribution was chosen such to not spam too many lists, yet reach
all the relevant maintainers (there appears to be no clk related list,
it's assumed that the clk API is ARM centric, which is why I send the
PowerPC related changes to the ARM list as well), but I'd be happy to
add more participants if necessary

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications --
splitting the series and taking the parts through several trees might
reorder the set (make drivers fail to see the device tree specs) or
would create unnecessary dependencies which need to get tracked upon
merges and might defer propagation (unless I missed something)

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #413: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 836 lines checked


Gerhard Sittig (24):
  spi: mpc512x: prepare clocks before enabling them
  serial: mpc512x: prepare clocks before enabling them
  mtd: mpc5121_nfc: prepare clocks before enabling them
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: make mpc512x code use common clock
  spi: mpc512x: OF clock lookup, use the 'mclk' name
  powerpc/mpc512x: improve DIU related clock setup
  serial: mpc512x: OF clock lookup, use the 'mclk' name
  clk: mpc512x: remove now obsolete clkdev registration
  serial: mpc512x: setup the PSC FIFO clock as well
  i2c: mpc: OF clock lookup for MPC512x
  USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  fs_enet: OF clock lookup (non-fatal), prepare and enable
  [media] fsl-viu: OF clock lookup, prepare before enable
  powerpc/fsl-pci: OF clock lookup, prepare before enable
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove MPC512x non-COMMON_CLK code path

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  762 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   15 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |    9 +
 drivers/media/platform/fsl-viu.c                   |   12 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |    4 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  234 +++---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +-
 drivers/spi/spi-mpc512x-psc.c                      |    6 +-
 drivers/tty/serial/mpc52xx_uart.c                  |   59 +-
 drivers/usb/host/fsl-mph-dr-of.c                   |   24 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 26 files changed, 1299 insertions(+), 1015 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


$ uname -srm
Linux 3.11.0-rc1-00024-g25dc674 ppc
$ cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      9           9            320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 2           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 2           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             0           0            320000000
             psc7-en0           0           0            320000000
                psc7_mclk_div   0           0            80000000
                   psc7_mclk_out 0           0            80000000
                      psc7_mclk 0           0            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 1           1            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 00/24] add COMMON_CLK support for PowerPC MPC512x
@ 2013-07-15 18:47 ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

this series introduces support for the common clock framework (CCF,
COMMON_CLK Kconfig option) in the PowerPC based MPC512x platform, a
resulting debugfs clk_summary is at the end of the message after the
stats

although the series does touch several subsystems -- serial, spi, net
(can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of the
patches are strictly clock related, changes outside of the clock driver
in the mpc512x platform are rather small and local to probe and setup

the distribution was chosen such to not spam too many lists, yet reach
all the relevant maintainers (there appears to be no clk related list,
it's assumed that the clk API is ARM centric, which is why I send the
PowerPC related changes to the ARM list as well), but I'd be happy to
add more participants if necessary

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications --
splitting the series and taking the parts through several trees might
reorder the set (make drivers fail to see the device tree specs) or
would create unnecessary dependencies which need to get tracked upon
merges and might defer propagation (unless I missed something)

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #413: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 836 lines checked


Gerhard Sittig (24):
  spi: mpc512x: prepare clocks before enabling them
  serial: mpc512x: prepare clocks before enabling them
  mtd: mpc5121_nfc: prepare clocks before enabling them
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: make mpc512x code use common clock
  spi: mpc512x: OF clock lookup, use the 'mclk' name
  powerpc/mpc512x: improve DIU related clock setup
  serial: mpc512x: OF clock lookup, use the 'mclk' name
  clk: mpc512x: remove now obsolete clkdev registration
  serial: mpc512x: setup the PSC FIFO clock as well
  i2c: mpc: OF clock lookup for MPC512x
  USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  fs_enet: OF clock lookup (non-fatal), prepare and enable
  [media] fsl-viu: OF clock lookup, prepare before enable
  powerpc/fsl-pci: OF clock lookup, prepare before enable
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove MPC512x non-COMMON_CLK code path

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  762 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   15 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |    9 +
 drivers/media/platform/fsl-viu.c                   |   12 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |    4 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  234 +++---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +-
 drivers/spi/spi-mpc512x-psc.c                      |    6 +-
 drivers/tty/serial/mpc52xx_uart.c                  |   59 +-
 drivers/usb/host/fsl-mph-dr-of.c                   |   24 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 26 files changed, 1299 insertions(+), 1015 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


$ uname -srm
Linux 3.11.0-rc1-00024-g25dc674 ppc
$ cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      9           9            320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 2           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 2           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             0           0            320000000
             psc7-en0           0           0            320000000
                psc7_mclk_div   0           0            80000000
                   psc7_mclk_out 0           0            80000000
                      psc7_mclk 0           0            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 1           1            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

clocks need to get prepared before they can get enabled,
fix the MPC512x PSC SPI master's initialization

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/spi/spi-mpc512x-psc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..76b20ea 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	sprintf(name, "psc%d_mclk", master->bus_num);
 	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
+	clk_prepare_enable(spiclk);
 	mps->mclk = clk_get_rate(spiclk);
 	clk_put(spiclk);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

clocks need to get prepared before they can get enabled,
fix the MPC512x PSC SPI master's initialization

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..76b20ea 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	sprintf(name, "psc%d_mclk", master->bus_num);
 	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
+	clk_prepare_enable(spiclk);
 	mps->mclk = clk_get_rate(spiclk);
 	clk_put(spiclk);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

clocks need to get prepared before they can get enabled,
fix the MPC512x PSC SPI master's initialization

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..76b20ea 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	sprintf(name, "psc%d_mclk", master->bus_num);
 	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
+	clk_prepare_enable(spiclk);
 	mps->mclk = clk_get_rate(spiclk);
 	clk_put(spiclk);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 02/24] serial: mpc512x: prepare clocks before enabling them
  2013-07-15 18:47 ` Gerhard Sittig
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

clocks need to get prepared before they can get enabled, and after
disabling them they can get unprepared

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..53c1093 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -636,9 +636,9 @@ static int mpc512x_psc_clock(struct uart_port *port, int enable)
 	dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis");
 
 	if (enable)
-		clk_enable(psc_clk);
+		clk_prepare_enable(psc_clk);
 	else
-		clk_disable(psc_clk);
+		clk_disable_unprepare(psc_clk);
 
 	return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 02/24] serial: mpc512x: prepare clocks before enabling them
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

clocks need to get prepared before they can get enabled, and after
disabling them they can get unprepared

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..53c1093 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -636,9 +636,9 @@ static int mpc512x_psc_clock(struct uart_port *port, int enable)
 	dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis");
 
 	if (enable)
-		clk_enable(psc_clk);
+		clk_prepare_enable(psc_clk);
 	else
-		clk_disable(psc_clk);
+		clk_disable_unprepare(psc_clk);
 
 	return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

must prepare clocks before enabling them, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..eb7771d 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,7 +618,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
+		clk_disable_unprepare(prv->clk);
 		clk_put(prv->clk);
 	}
 
@@ -737,7 +737,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 		goto error;
 	}
 
-	clk_enable(prv->clk);
+	clk_prepare_enable(prv->clk);
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

must prepare clocks before enabling them, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..eb7771d 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,7 +618,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
+		clk_disable_unprepare(prv->clk);
 		clk_put(prv->clk);
 	}
 
@@ -737,7 +737,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 		goto error;
 	}
 
-	clk_enable(prv->clk);
+	clk_prepare_enable(prv->clk);
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

must prepare clocks before enabling them, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..eb7771d 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,7 +618,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
+		clk_disable_unprepare(prv->clk);
 		clk_put(prv->clk);
 	}
 
@@ -737,7 +737,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 		goto error;
 	}
 
-	clk_enable(prv->clk);
+	clk_prepare_enable(prv->clk);
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 06/24] dts: mpc512x: prepare for preprocessor support
  2013-07-15 18:47 ` Gerhard Sittig
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 06/24] dts: mpc512x: prepare for preprocessor support
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 07/24] dts: mpc512x: introduce dt-bindings/clock/ header
  2013-07-15 18:47 ` Gerhard Sittig
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 07/24] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 08/24] dts: mpc512x: add clock related device tree specs
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc@80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock@f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc@80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock@f00 {
+		clks: clock@f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 08/24] dts: mpc512x: add clock related device tree specs
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc@80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock@f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc@80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock@f00 {
+		clks: clock@f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 08/24] dts: mpc512x: add clock related device tree specs
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc at 80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock at f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc at 80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock at f00 {
+		clks: clock at f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  777 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 809 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..218f55b
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,777 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from OF specs, before this clkdev registration becomes
+	 * obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  777 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 809 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..218f55b
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,777 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from OF specs, before this clkdev registration becomes
+	 * obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  777 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 809 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..218f55b
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,777 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from OF specs, before this clkdev registration becomes
+	 * obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 10/24] dts: mpc512x: add clock specs for client lookups
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the client side of device tree based clock lookups:
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu,
viu, mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the
shared mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver; some drivers
still need to learn how to lookup OF clocks, other drivers will
transparently probe successfully on MPC512x as well (sdhc)

few 'clock-names' (nfc, viu) use strings that are encoded in their
respective drivers to keep up compatibility, an alternative approach
would be to register clkdev items in the platform's clock driver for
the migration period

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..983da9c 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram@30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "nfc_clk";	/* backwards compat */
 	};
 
 	localbus@80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc@1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c@1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol@1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display@2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can@2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu@2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "viu_clk";	/* backwards compat */
 		};
 
 		mdio@2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet@2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo@11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma@14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 10/24] dts: mpc512x: add clock specs for client lookups
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the client side of device tree based clock lookups:
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu,
viu, mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the
shared mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver; some drivers
still need to learn how to lookup OF clocks, other drivers will
transparently probe successfully on MPC512x as well (sdhc)

few 'clock-names' (nfc, viu) use strings that are encoded in their
respective drivers to keep up compatibility, an alternative approach
would be to register clkdev items in the platform's clock driver for
the migration period

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..983da9c 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram@30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "nfc_clk";	/* backwards compat */
 	};
 
 	localbus@80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc@1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c@1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol@1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display@2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can@2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu@2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "viu_clk";	/* backwards compat */
 		};
 
 		mdio@2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet@2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo@11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma@14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 10/24] dts: mpc512x: add clock specs for client lookups
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the client side of device tree based clock lookups:
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu,
viu, mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the
shared mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver; some drivers
still need to learn how to lookup OF clocks, other drivers will
transparently probe successfully on MPC512x as well (sdhc)

few 'clock-names' (nfc, viu) use strings that are encoded in their
respective drivers to keep up compatibility, an alternative approach
would be to register clkdev items in the platform's clock driver for
the migration period

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..983da9c 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram at 30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "nfc_clk";	/* backwards compat */
 	};
 
 	localbus at 80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can at 1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc at 1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c at 1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol at 1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display at 2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can at 2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can at 2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu at 2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "viu_clk";	/* backwards compat */
 		};
 
 		mdio at 2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet at 2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo at 11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma at 14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 11/24] net: can: mscan: add a comment on reg to idx mapping
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 11/24] net: can: mscan: add a comment on reg to idx mapping
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 11/24] net: can: mscan: add a comment on reg to idx mapping
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 12/24] net: can: mscan: make mpc512x code use common clock
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

extend the mscan(4) driver with alternative support for the COMMON_CLK
approach which is an option in the MPC512x platform, keep the existing
clock support implementation in place since the driver is shared with
other MPC5xxx SoCs which don't have common clock support

one byproduct of this change is that the CAN driver no longer needs to
access the SoC's clock control registers, which shall be the domain of
the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..dd26ab6 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+#else	/* COMMON_CLK */
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -238,6 +375,8 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 12/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

extend the mscan(4) driver with alternative support for the COMMON_CLK
approach which is an option in the MPC512x platform, keep the existing
clock support implementation in place since the driver is shared with
other MPC5xxx SoCs which don't have common clock support

one byproduct of this change is that the CAN driver no longer needs to
access the SoC's clock control registers, which shall be the domain of
the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..dd26ab6 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+#else	/* COMMON_CLK */
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -238,6 +375,8 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 12/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

extend the mscan(4) driver with alternative support for the COMMON_CLK
approach which is an option in the MPC512x platform, keep the existing
clock support implementation in place since the driver is shared with
other MPC5xxx SoCs which don't have common clock support

one byproduct of this change is that the CAN driver no longer needs to
access the SoC's clock control registers, which shall be the domain of
the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..dd26ab6 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+#else	/* COMMON_CLK */
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -238,6 +375,8 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 13/24] spi: mpc512x: OF clock lookup, use the 'mclk' name
  2013-07-15 18:47 ` Gerhard Sittig
@ 2013-07-15 18:47   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after PSC related clock specifiers were added to the device tree,
the former 'psc%d_mclk' isn't needed any longer to lookup clock items

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 76b20ea..3e30e52 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -388,13 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
 	struct clk *spiclk;
 	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
+	spiclk = clk_get(&master->dev, "mclk");
 	clk_prepare_enable(spiclk);
 	mps->mclk = clk_get_rate(spiclk);
 	clk_put(spiclk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 13/24] spi: mpc512x: OF clock lookup, use the 'mclk' name
@ 2013-07-15 18:47   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

after PSC related clock specifiers were added to the device tree,
the former 'psc%d_mclk' isn't needed any longer to lookup clock items

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 76b20ea..3e30e52 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -388,13 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
 	struct clk *spiclk;
 	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
+	spiclk = clk_get(&master->dev, "mclk");
 	clk_prepare_enable(spiclk);
 	mps->mclk = clk_get_rate(spiclk);
 	clk_put(spiclk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 14/24] powerpc/mpc512x: improve DIU related clock setup
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 18:47     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 218f55b..f31f895 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -705,7 +705,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 14/24] powerpc/mpc512x: improve DIU related clock setup
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 218f55b..f31f895 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -705,7 +705,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 14/24] powerpc/mpc512x: improve DIU related clock setup
@ 2013-07-15 18:47     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 218f55b..f31f895 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -705,7 +705,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-15 18:47     ` Gerhard Sittig
@ 2013-07-15 19:38       ` Sascha Hauer
  -1 siblings, 0 replies; 432+ messages in thread
From: Sascha Hauer @ 2013-07-15 19:38 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 6d55eb2..2c07061 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>  	struct clk_divider *divider = to_clk_divider(hw);
>  	unsigned int div, val;
>  
> -	val = readl(divider->reg) >> divider->shift;
> +	val = clk_readl(divider->reg) >> divider->shift;
>  	val &= div_mask(divider);

Would it be an option to use regmap for the generic dividers/muxes
instead? This should be suitable for ppc and also for people who want to
use the generic clocks on i2c devices.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-15 19:38       ` Sascha Hauer
  0 siblings, 0 replies; 432+ messages in thread
From: Sascha Hauer @ 2013-07-15 19:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 6d55eb2..2c07061 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>  	struct clk_divider *divider = to_clk_divider(hw);
>  	unsigned int div, val;
>  
> -	val = readl(divider->reg) >> divider->shift;
> +	val = clk_readl(divider->reg) >> divider->shift;
>  	val &= div_mask(divider);

Would it be an option to use regmap for the generic dividers/muxes
instead? This should be suitable for ppc and also for people who want to
use the generic clocks on i2c devices.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
  2013-07-15 18:47     ` Gerhard Sittig
  (?)
@ 2013-07-15 20:17         ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-15 20:17 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Greg Kroah-Hartman,
	Rob Herring, Marc Kleine-Budde, Wolfgang Grandegger,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 1065 bytes --]

On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> clocks need to get prepared before they can get enabled,
> fix the MPC512x PSC SPI master's initialization

> Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
> ---
>  drivers/spi/spi-mpc512x-psc.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
> index 29fce6a..76b20ea 100644
> --- a/drivers/spi/spi-mpc512x-psc.c
> +++ b/drivers/spi/spi-mpc512x-psc.c
> @@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
>  
>  	sprintf(name, "psc%d_mclk", master->bus_num);
>  	spiclk = clk_get(&master->dev, name);
> -	clk_enable(spiclk);
> +	clk_prepare_enable(spiclk);
>  	mps->mclk = clk_get_rate(spiclk);
>  	clk_put(spiclk);

This code is *clearly* buggy and should be fixed rather than papered
over.  Not only is there no matching put the driver is also dropping the
reference to the clock rather than holding on to it while it's in use.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-15 20:17         ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-15 20:17 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 1044 bytes --]

On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> clocks need to get prepared before they can get enabled,
> fix the MPC512x PSC SPI master's initialization

> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/spi/spi-mpc512x-psc.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
> index 29fce6a..76b20ea 100644
> --- a/drivers/spi/spi-mpc512x-psc.c
> +++ b/drivers/spi/spi-mpc512x-psc.c
> @@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
>  
>  	sprintf(name, "psc%d_mclk", master->bus_num);
>  	spiclk = clk_get(&master->dev, name);
> -	clk_enable(spiclk);
> +	clk_prepare_enable(spiclk);
>  	mps->mclk = clk_get_rate(spiclk);
>  	clk_put(spiclk);

This code is *clearly* buggy and should be fixed rather than papered
over.  Not only is there no matching put the driver is also dropping the
reference to the clock rather than holding on to it while it's in use.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-15 20:17         ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-15 20:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> clocks need to get prepared before they can get enabled,
> fix the MPC512x PSC SPI master's initialization

> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/spi/spi-mpc512x-psc.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
> index 29fce6a..76b20ea 100644
> --- a/drivers/spi/spi-mpc512x-psc.c
> +++ b/drivers/spi/spi-mpc512x-psc.c
> @@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
>  
>  	sprintf(name, "psc%d_mclk", master->bus_num);
>  	spiclk = clk_get(&master->dev, name);
> -	clk_enable(spiclk);
> +	clk_prepare_enable(spiclk);
>  	mps->mclk = clk_get_rate(spiclk);
>  	clk_put(spiclk);

This code is *clearly* buggy and should be fixed rather than papered
over.  Not only is there no matching put the driver is also dropping the
reference to the clock rather than holding on to it while it's in use.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130715/a9b4d8ae/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-15 21:46     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 21:46 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

with device tree based clock lookup, the MCLK name no longer
depends on the PSC index

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 53c1093..221fb89 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
 static int mpc512x_psc_clock(struct uart_port *port, int enable)
 {
 	struct clk *psc_clk;
-	int psc_num;
-	char clk_name[10];
 
 	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);
+	psc_clk = clk_get(port->dev, "mclk");
 	if (IS_ERR(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");
+	dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis");
 
 	if (enable)
 		clk_prepare_enable(psc_clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
@ 2013-07-15 21:46     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 21:46 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

with device tree based clock lookup, the MCLK name no longer
depends on the PSC index

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 53c1093..221fb89 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
 static int mpc512x_psc_clock(struct uart_port *port, int enable)
 {
 	struct clk *psc_clk;
-	int psc_num;
-	char clk_name[10];
 
 	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);
+	psc_clk = clk_get(port->dev, "mclk");
 	if (IS_ERR(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");
+	dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis");
 
 	if (enable)
 		clk_prepare_enable(psc_clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
@ 2013-07-15 21:46     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-15 21:46 UTC (permalink / raw)
  To: linux-arm-kernel

with device tree based clock lookup, the MCLK name no longer
depends on the PSC index

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 53c1093..221fb89 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
 static int mpc512x_psc_clock(struct uart_port *port, int enable)
 {
 	struct clk *psc_clk;
-	int psc_num;
-	char clk_name[10];
 
 	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);
+	psc_clk = clk_get(port->dev, "mclk");
 	if (IS_ERR(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");
+	dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis");
 
 	if (enable)
 		clk_prepare_enable(psc_clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
  2013-07-15 21:46     ` Gerhard Sittig
@ 2013-07-15 21:54       ` Sascha Hauer
  -1 siblings, 0 replies; 432+ messages in thread
From: Sascha Hauer @ 2013-07-15 21:54 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 11:46:01PM +0200, Gerhard Sittig wrote:
> with device tree based clock lookup, the MCLK name no longer
> depends on the PSC index
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/tty/serial/mpc52xx_uart.c |    8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> index 53c1093..221fb89 100644
> --- a/drivers/tty/serial/mpc52xx_uart.c
> +++ b/drivers/tty/serial/mpc52xx_uart.c
> @@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
>  static int mpc512x_psc_clock(struct uart_port *port, int enable)
>  {
>  	struct clk *psc_clk;
> -	int psc_num;
> -	char clk_name[10];
>  
>  	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);
> +	psc_clk = clk_get(port->dev, "mclk");

Same comment applies here as Mark made to the spi driver.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
@ 2013-07-15 21:54       ` Sascha Hauer
  0 siblings, 0 replies; 432+ messages in thread
From: Sascha Hauer @ 2013-07-15 21:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 11:46:01PM +0200, Gerhard Sittig wrote:
> with device tree based clock lookup, the MCLK name no longer
> depends on the PSC index
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/tty/serial/mpc52xx_uart.c |    8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> index 53c1093..221fb89 100644
> --- a/drivers/tty/serial/mpc52xx_uart.c
> +++ b/drivers/tty/serial/mpc52xx_uart.c
> @@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
>  static int mpc512x_psc_clock(struct uart_port *port, int enable)
>  {
>  	struct clk *psc_clk;
> -	int psc_num;
> -	char clk_name[10];
>  
>  	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);
> +	psc_clk = clk_get(port->dev, "mclk");

Same comment applies here as Mark made to the spi driver.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 16/24] clk: mpc512x: remove now obsolete clkdev registration
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  6:05     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the PSC drivers for UART and SPI mode got converted to device tree
based clock lookup, the former MCLK name which depends on the PSC index
isn't needed any longer -- remove the clk_register_clkdev() invocation

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index f31f895..31707b5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -529,16 +529,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from OF specs, before this clkdev registration becomes
-	 * obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 16/24] clk: mpc512x: remove now obsolete clkdev registration
@ 2013-07-16  6:05     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the PSC drivers for UART and SPI mode got converted to device tree
based clock lookup, the former MCLK name which depends on the PSC index
isn't needed any longer -- remove the clk_register_clkdev() invocation

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index f31f895..31707b5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -529,16 +529,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from OF specs, before this clkdev registration becomes
-	 * obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 16/24] clk: mpc512x: remove now obsolete clkdev registration
@ 2013-07-16  6:05     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

after the PSC drivers for UART and SPI mode got converted to device tree
based clock lookup, the former MCLK name which depends on the PSC index
isn't needed any longer -- remove the clk_register_clkdev() invocation

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index f31f895..31707b5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -529,16 +529,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from OF specs, before this clkdev registration becomes
-	 * obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 17/24] serial: mpc512x: setup the PSC FIFO clock as well
  2013-07-15 18:47 ` Gerhard Sittig
@ 2013-07-16  6:05   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare and enable the FIFO clock upon PSC FIFO initialization, disable
and unprepare the FIFO clock upon PSC FIFO uninitialization, remove the
pre-enable workaround from the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   47 +++++++++++++++++++++----
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 31707b5..2c6da07 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -690,8 +690,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 221fb89..e67d4c0 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -567,35 +567,70 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 static int __init mpc512x_psc_fifoc_init(void)
 {
 	struct device_node *np;
+	struct clk *clk;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
+	}
+
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		goto out_clk_put;
 	}
 
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	clk_put(clk);
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(clk);
+out_clk_put:
+	clk_put(clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return -ENODEV;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
+	struct device_node *np;
+	struct clk *clk;
+
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-psc-fifo");
+	if (np) {
+		clk = of_clk_get_by_name(np, "per");
+		if (!IS_ERR(clk)) {
+			clk_disable_unprepare(clk);
+			clk_put(clk);
+		}
+		of_node_put(np);
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 17/24] serial: mpc512x: setup the PSC FIFO clock as well
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

prepare and enable the FIFO clock upon PSC FIFO initialization, disable
and unprepare the FIFO clock upon PSC FIFO uninitialization, remove the
pre-enable workaround from the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   47 +++++++++++++++++++++----
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 31707b5..2c6da07 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -690,8 +690,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 221fb89..e67d4c0 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -567,35 +567,70 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 static int __init mpc512x_psc_fifoc_init(void)
 {
 	struct device_node *np;
+	struct clk *clk;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
+	}
+
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		goto out_clk_put;
 	}
 
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	clk_put(clk);
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(clk);
+out_clk_put:
+	clk_put(clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return -ENODEV;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
+	struct device_node *np;
+	struct clk *clk;
+
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-psc-fifo");
+	if (np) {
+		clk = of_clk_get_by_name(np, "per");
+		if (!IS_ERR(clk)) {
+			clk_disable_unprepare(clk);
+			clk_put(clk);
+		}
+		of_node_put(np);
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 18/24] i2c: mpc: OF clock lookup for MPC512x
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  6:05   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

make the MPC I2C driver prepare and enable the peripheral clock
('per' for register access) in the MPC512x setup routine,
make this clock setup non-fatal to allow for a migration period,
remove the pre-enabling hack in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/i2c/busses/i2c-mpc.c                  |    9 +++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 2c6da07..29c51a5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -693,7 +693,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..13d6822 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -264,11 +265,19 @@ static void mpc_i2c_setup_512x(struct device_node *node,
 					 struct mpc_i2c *i2c,
 					 u32 clock, u32 prescaler)
 {
+	struct clk *clk;
 	struct device_node *node_ctrl;
 	void __iomem *ctrl;
 	const u32 *pval;
 	u32 idx;
 
+	/* enable clock for the I2C peripheral (non fatal) */
+	clk = of_clk_get_by_name(node, "per");
+	if (!IS_ERR(clk)) {
+		clk_prepare_enable(clk);
+		clk_put(clk);
+	}
+
 	/* Enable I2C interrupts for mpc5121 */
 	node_ctrl = of_find_compatible_node(NULL, NULL,
 					    "fsl,mpc5121-i2c-ctrl");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the MPC I2C driver prepare and enable the peripheral clock
('per' for register access) in the MPC512x setup routine,
make this clock setup non-fatal to allow for a migration period,
remove the pre-enabling hack in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/i2c/busses/i2c-mpc.c                  |    9 +++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 2c6da07..29c51a5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -693,7 +693,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..13d6822 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -264,11 +265,19 @@ static void mpc_i2c_setup_512x(struct device_node *node,
 					 struct mpc_i2c *i2c,
 					 u32 clock, u32 prescaler)
 {
+	struct clk *clk;
 	struct device_node *node_ctrl;
 	void __iomem *ctrl;
 	const u32 *pval;
 	u32 idx;
 
+	/* enable clock for the I2C peripheral (non fatal) */
+	clk = of_clk_get_by_name(node, "per");
+	if (!IS_ERR(clk)) {
+		clk_prepare_enable(clk);
+		clk_put(clk);
+	}
+
 	/* Enable I2C interrupts for mpc5121 */
 	node_ctrl = of_find_compatible_node(NULL, NULL,
 					    "fsl,mpc5121-i2c-ctrl");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

make the MPC I2C driver prepare and enable the peripheral clock
('per' for register access) in the MPC512x setup routine,
make this clock setup non-fatal to allow for a migration period,
remove the pre-enabling hack in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/i2c/busses/i2c-mpc.c                  |    9 +++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 2c6da07..29c51a5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -693,7 +693,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..13d6822 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -264,11 +265,19 @@ static void mpc_i2c_setup_512x(struct device_node *node,
 					 struct mpc_i2c *i2c,
 					 u32 clock, u32 prescaler)
 {
+	struct clk *clk;
 	struct device_node *node_ctrl;
 	void __iomem *ctrl;
 	const u32 *pval;
 	u32 idx;
 
+	/* enable clock for the I2C peripheral (non fatal) */
+	clk = of_clk_get_by_name(node, "per");
+	if (!IS_ERR(clk)) {
+		clk_prepare_enable(clk);
+		clk_put(clk);
+	}
+
 	/* Enable I2C interrupts for mpc5121 */
 	node_ctrl = of_find_compatible_node(NULL, NULL,
 					    "fsl,mpc5121-i2c-ctrl");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  6:05   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup in the MPC512x initialization (lookup
'per' for register access), add error check in the clock setup, must
prepare clocks before they can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..eb564f3 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,25 +260,19 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
+	int err;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		clk_put(clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,7 +297,7 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
 		clk_put(pdata->clk);
 	}
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup in the MPC512x initialization (lookup
'per' for register access), add error check in the clock setup, must
prepare clocks before they can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..eb564f3 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,25 +260,19 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
+	int err;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		clk_put(clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,7 +297,7 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
 		clk_put(pdata->clk);
 	}
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup in the MPC512x initialization (lookup
'per' for register access), add error check in the clock setup, must
prepare clocks before they can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..eb564f3 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,25 +260,19 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
+	int err;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		clk_put(clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,7 +297,7 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
 		clk_put(pdata->clk);
 	}
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 20/24] fs_enet: OF clock lookup (non-fatal), prepare and enable
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  6:05   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup, remove
the pre-enable workaround in the MPC512x platform's clock driver

this change implements non-fatal clock lookup since not all platforms
provide device tree specs for clocks, but failure to enable a specified
clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c      |    1 -
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +++++++++++++++++++-
 include/linux/fs_enet_pd.h                         |    3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 29c51a5..31d0cf3 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..df92e12 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1020,6 +1020,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 		fpi->cp_command = *data;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found
+	 */
+	fpi->clk_per = clk_get(&ofdev->dev, "per");
+	if (IS_ERR(fpi->clk_per))
+		fpi->clk_per = NULL;
+	if (fpi->clk_per) {
+		int err;
+		err = clk_prepare_enable(fpi->clk_per);
+		if (err) {
+			ret = err;
+			goto out_clk_put;
+		}
+	}
+
 	fpi->rx_ring = 32;
 	fpi->tx_ring = 32;
 	fpi->rx_copybreak = 240;
@@ -1028,7 +1043,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
 	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
 						  NULL)))
-		goto out_free_fpi;
+		goto out_clk_dis;
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
 		phy_connection_type = of_get_property(ofdev->dev.of_node,
@@ -1108,6 +1123,12 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+out_clk_dis:
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
+out_clk_put:
+	if (fpi->clk_per)
+		clk_put(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1124,6 +1145,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		clk_put(fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 20/24] fs_enet: OF clock lookup (non-fatal), prepare and enable
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup, remove
the pre-enable workaround in the MPC512x platform's clock driver

this change implements non-fatal clock lookup since not all platforms
provide device tree specs for clocks, but failure to enable a specified
clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c      |    1 -
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +++++++++++++++++++-
 include/linux/fs_enet_pd.h                         |    3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 29c51a5..31d0cf3 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..df92e12 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1020,6 +1020,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 		fpi->cp_command = *data;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found
+	 */
+	fpi->clk_per = clk_get(&ofdev->dev, "per");
+	if (IS_ERR(fpi->clk_per))
+		fpi->clk_per = NULL;
+	if (fpi->clk_per) {
+		int err;
+		err = clk_prepare_enable(fpi->clk_per);
+		if (err) {
+			ret = err;
+			goto out_clk_put;
+		}
+	}
+
 	fpi->rx_ring = 32;
 	fpi->tx_ring = 32;
 	fpi->rx_copybreak = 240;
@@ -1028,7 +1043,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
 	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
 						  NULL)))
-		goto out_free_fpi;
+		goto out_clk_dis;
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
 		phy_connection_type = of_get_property(ofdev->dev.of_node,
@@ -1108,6 +1123,12 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+out_clk_dis:
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
+out_clk_put:
+	if (fpi->clk_per)
+		clk_put(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1124,6 +1145,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		clk_put(fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 20/24] fs_enet: OF clock lookup (non-fatal), prepare and enable
@ 2013-07-16  6:05   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup, remove
the pre-enable workaround in the MPC512x platform's clock driver

this change implements non-fatal clock lookup since not all platforms
provide device tree specs for clocks, but failure to enable a specified
clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c      |    1 -
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +++++++++++++++++++-
 include/linux/fs_enet_pd.h                         |    3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 29c51a5..31d0cf3 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..df92e12 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1020,6 +1020,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 		fpi->cp_command = *data;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found
+	 */
+	fpi->clk_per = clk_get(&ofdev->dev, "per");
+	if (IS_ERR(fpi->clk_per))
+		fpi->clk_per = NULL;
+	if (fpi->clk_per) {
+		int err;
+		err = clk_prepare_enable(fpi->clk_per);
+		if (err) {
+			ret = err;
+			goto out_clk_put;
+		}
+	}
+
 	fpi->rx_ring = 32;
 	fpi->tx_ring = 32;
 	fpi->rx_copybreak = 240;
@@ -1028,7 +1043,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
 	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
 						  NULL)))
-		goto out_free_fpi;
+		goto out_clk_dis;
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
 		phy_connection_type = of_get_property(ofdev->dev.of_node,
@@ -1108,6 +1123,12 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+out_clk_dis:
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
+out_clk_put:
+	if (fpi->clk_per)
+		clk_put(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1124,6 +1145,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		clk_put(fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 21/24] [media] fsl-viu: OF clock lookup, prepare before enable
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  8:45     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/media/platform/fsl-viu.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..b95aa43 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1582,8 +1582,11 @@ static int viu_of_probe(struct platform_device *op)
 		dev_err(&op->dev, "failed to find the clock module!\n");
 		ret = -ENODEV;
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
+	}
+	ret = clk_prepare_enable(viu_dev->clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		goto err_clk_put;
 	}
 
 	/* reset VIU module */
@@ -1602,7 +1605,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+err_clk_put:
 	clk_put(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
@@ -1626,7 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 
 	video_unregister_device(dev->vdev);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 21/24] [media] fsl-viu: OF clock lookup, prepare before enable
@ 2013-07-16  8:45     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..b95aa43 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1582,8 +1582,11 @@ static int viu_of_probe(struct platform_device *op)
 		dev_err(&op->dev, "failed to find the clock module!\n");
 		ret = -ENODEV;
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
+	}
+	ret = clk_prepare_enable(viu_dev->clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		goto err_clk_put;
 	}
 
 	/* reset VIU module */
@@ -1602,7 +1605,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+err_clk_put:
 	clk_put(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
@@ -1626,7 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 
 	video_unregister_device(dev->vdev);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 21/24] [media] fsl-viu: OF clock lookup, prepare before enable
@ 2013-07-16  8:45     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..b95aa43 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1582,8 +1582,11 @@ static int viu_of_probe(struct platform_device *op)
 		dev_err(&op->dev, "failed to find the clock module!\n");
 		ret = -ENODEV;
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
+	}
+	ret = clk_prepare_enable(viu_dev->clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		goto err_clk_put;
 	}
 
 	/* reset VIU module */
@@ -1602,7 +1605,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+err_clk_put:
 	clk_put(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
@@ -1626,7 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 
 	video_unregister_device(dev->vdev);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable
  2013-07-15 18:47 ` Gerhard Sittig
@ 2013-07-16  8:45   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, error check in the clock setup

this change implements non-fatal clock lookup for compatibility with
platforms that don't provide OF clock specs, but failure to enable a
specified clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..cb2ed92 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -741,6 +743,7 @@ err0:
 
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
+	struct clk *clk;
 	int ret;
 	int len;
 	struct pci_controller *hose;
@@ -758,6 +761,18 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	}
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
+	/* non-fatal OF clock lookup, but fatal when a clock
+	 * was specified yet could not get enabled */
+	clk = of_clk_get_by_name(dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		clk_put(clk);
+		if (ret) {
+			pr_err("Could not enable peripheral clock\n");
+			return ret;
+		}
+	}
+
 	/* Fetch host bridge registers address */
 	if (of_address_to_resource(dev, 0, &rsrc_reg)) {
 		printk(KERN_WARNING "Can't get pci register base!\n");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable
@ 2013-07-16  8:45   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup, must prepare clocks before enabling
them, error check in the clock setup

this change implements non-fatal clock lookup for compatibility with
platforms that don't provide OF clock specs, but failure to enable a
specified clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..cb2ed92 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -741,6 +743,7 @@ err0:
 
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
+	struct clk *clk;
 	int ret;
 	int len;
 	struct pci_controller *hose;
@@ -758,6 +761,18 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	}
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
+	/* non-fatal OF clock lookup, but fatal when a clock
+	 * was specified yet could not get enabled */
+	clk = of_clk_get_by_name(dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		clk_put(clk);
+		if (ret) {
+			pr_err("Could not enable peripheral clock\n");
+			return ret;
+		}
+	}
+
 	/* Fetch host bridge registers address */
 	if (of_address_to_resource(dev, 0, &rsrc_reg)) {
 		printk(KERN_WARNING "Can't get pci register base!\n");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  8:45     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-07-16  8:45     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-07-16  8:45     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-16  8:45   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

transition to the COMMON_CLK framework has completed for the MPC512x
platform, remove the now obsolete code path of the mpc5xxx mscan
driver which accessed clock control module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  136 -----------------------------------
 1 file changed, 136 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index dd26ab6..cf5e4cfc 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,9 +108,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -244,139 +241,6 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
-#else	/* COMMON_CLK */
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path
@ 2013-07-16  8:45   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

transition to the COMMON_CLK framework has completed for the MPC512x
platform, remove the now obsolete code path of the mpc5xxx mscan
driver which accessed clock control module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  136 -----------------------------------
 1 file changed, 136 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index dd26ab6..cf5e4cfc 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,9 +108,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -244,139 +241,6 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
-#else	/* COMMON_CLK */
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v1 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path
@ 2013-07-16  8:45   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-16  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

transition to the COMMON_CLK framework has completed for the MPC512x
platform, remove the now obsolete code path of the mpc5xxx mscan
driver which accessed clock control module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  136 -----------------------------------
 1 file changed, 136 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index dd26ab6..cf5e4cfc 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,9 +108,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -244,139 +241,6 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
-#else	/* COMMON_CLK */
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
  2013-07-15 20:17         ` Mark Brown
  (?)
@ 2013-07-17 11:22             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 11:22 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
	Marc Kleine-Budde,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> > clocks need to get prepared before they can get enabled,
> > fix the MPC512x PSC SPI master's initialization
> 
> > Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
> > ---
> >  drivers/spi/spi-mpc512x-psc.c |    2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
> > index 29fce6a..76b20ea 100644
> > --- a/drivers/spi/spi-mpc512x-psc.c
> > +++ b/drivers/spi/spi-mpc512x-psc.c
> > @@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
> >  
> >  	sprintf(name, "psc%d_mclk", master->bus_num);
> >  	spiclk = clk_get(&master->dev, name);
> > -	clk_enable(spiclk);
> > +	clk_prepare_enable(spiclk);
> >  	mps->mclk = clk_get_rate(spiclk);
> >  	clk_put(spiclk);
> 
> This code is *clearly* buggy and should be fixed rather than papered
> over.  Not only is there no matching put the driver is also dropping the
> reference to the clock rather than holding on to it while it's in use.

"This code" refers to the driver's original condition, right?  I
agree that the driver has been suffering from incomplete clock
handling since it was born three years ago.  And that this issue
shall get addressed.  The question is just whether it needs to be
part of this series which has a different focus.

What the above patch addresses is prevention of an immediate and
fatal breakage, when common clock gets used but clocks aren't
prepared before getting enabled.  So I consider it appropriate as
a step in preparation before introducing support for common clock
on the platform.  (It's funny that I had a comment in this spirit
in the commit message, but trimmed it to not be overly verbose.)

What the patch does not address is to fix any other deficiencies
in the driver which might have been lurking there for ages.  This
would be the scope of a different patch or series, as addressing
it here as well would mix orthogonal issues within one series,
and would complicate review and test (and would delay or even
potentially kill the introduction of desirable support for common
infrastructure just because other legacy non-fatal issues aren't
addressed as well in bypassing).

I will look into what I can do to address your concerns about
proper general clock handling in this specific driver.  But I'm
unable to do this for all other drivers as well which I happen to
pass by as I work on platform code (partially due to lack of
knowledge).  In any case I won't be able to test all of these
changes in all subsystems (mostly due to lack of hardware and
test setups).

So I suggest to leave these general cleanup activities for a
separate series.  The current series certainly improves general
platform code, transparently brings new drivers into successful
operation, and keeps the quality of existing code (doesn't break
anything, does even actively prevent breakage).  So it shall be
acceptable despite its not being perfect (like addressing each
and every other aspect which may arise elsewhere).  Where would I
stop then?

Sorry for the lengthy reply, but I guess it's about just one
general aspect which equally applies to other parts of the
series, not just the specific SPI driver which the feedback was
provided for.  And I do appreciate your looking at the
submission.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 11:22             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 11:22 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, linuxppc-dev, Rob Herring, Marc Kleine-Budde,
	linux-arm-kernel, Anatolij Gustschin, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> > clocks need to get prepared before they can get enabled,
> > fix the MPC512x PSC SPI master's initialization
> 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/spi/spi-mpc512x-psc.c |    2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
> > index 29fce6a..76b20ea 100644
> > --- a/drivers/spi/spi-mpc512x-psc.c
> > +++ b/drivers/spi/spi-mpc512x-psc.c
> > @@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
> >  
> >  	sprintf(name, "psc%d_mclk", master->bus_num);
> >  	spiclk = clk_get(&master->dev, name);
> > -	clk_enable(spiclk);
> > +	clk_prepare_enable(spiclk);
> >  	mps->mclk = clk_get_rate(spiclk);
> >  	clk_put(spiclk);
> 
> This code is *clearly* buggy and should be fixed rather than papered
> over.  Not only is there no matching put the driver is also dropping the
> reference to the clock rather than holding on to it while it's in use.

"This code" refers to the driver's original condition, right?  I
agree that the driver has been suffering from incomplete clock
handling since it was born three years ago.  And that this issue
shall get addressed.  The question is just whether it needs to be
part of this series which has a different focus.

What the above patch addresses is prevention of an immediate and
fatal breakage, when common clock gets used but clocks aren't
prepared before getting enabled.  So I consider it appropriate as
a step in preparation before introducing support for common clock
on the platform.  (It's funny that I had a comment in this spirit
in the commit message, but trimmed it to not be overly verbose.)

What the patch does not address is to fix any other deficiencies
in the driver which might have been lurking there for ages.  This
would be the scope of a different patch or series, as addressing
it here as well would mix orthogonal issues within one series,
and would complicate review and test (and would delay or even
potentially kill the introduction of desirable support for common
infrastructure just because other legacy non-fatal issues aren't
addressed as well in bypassing).

I will look into what I can do to address your concerns about
proper general clock handling in this specific driver.  But I'm
unable to do this for all other drivers as well which I happen to
pass by as I work on platform code (partially due to lack of
knowledge).  In any case I won't be able to test all of these
changes in all subsystems (mostly due to lack of hardware and
test setups).

So I suggest to leave these general cleanup activities for a
separate series.  The current series certainly improves general
platform code, transparently brings new drivers into successful
operation, and keeps the quality of existing code (doesn't break
anything, does even actively prevent breakage).  So it shall be
acceptable despite its not being perfect (like addressing each
and every other aspect which may arise elsewhere).  Where would I
stop then?

Sorry for the lengthy reply, but I guess it's about just one
general aspect which equally applies to other parts of the
series, not just the specific SPI driver which the feedback was
provided for.  And I do appreciate your looking at the
submission.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 11:22             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 11:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> > clocks need to get prepared before they can get enabled,
> > fix the MPC512x PSC SPI master's initialization
> 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/spi/spi-mpc512x-psc.c |    2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
> > index 29fce6a..76b20ea 100644
> > --- a/drivers/spi/spi-mpc512x-psc.c
> > +++ b/drivers/spi/spi-mpc512x-psc.c
> > @@ -395,7 +395,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
> >  
> >  	sprintf(name, "psc%d_mclk", master->bus_num);
> >  	spiclk = clk_get(&master->dev, name);
> > -	clk_enable(spiclk);
> > +	clk_prepare_enable(spiclk);
> >  	mps->mclk = clk_get_rate(spiclk);
> >  	clk_put(spiclk);
> 
> This code is *clearly* buggy and should be fixed rather than papered
> over.  Not only is there no matching put the driver is also dropping the
> reference to the clock rather than holding on to it while it's in use.

"This code" refers to the driver's original condition, right?  I
agree that the driver has been suffering from incomplete clock
handling since it was born three years ago.  And that this issue
shall get addressed.  The question is just whether it needs to be
part of this series which has a different focus.

What the above patch addresses is prevention of an immediate and
fatal breakage, when common clock gets used but clocks aren't
prepared before getting enabled.  So I consider it appropriate as
a step in preparation before introducing support for common clock
on the platform.  (It's funny that I had a comment in this spirit
in the commit message, but trimmed it to not be overly verbose.)

What the patch does not address is to fix any other deficiencies
in the driver which might have been lurking there for ages.  This
would be the scope of a different patch or series, as addressing
it here as well would mix orthogonal issues within one series,
and would complicate review and test (and would delay or even
potentially kill the introduction of desirable support for common
infrastructure just because other legacy non-fatal issues aren't
addressed as well in bypassing).

I will look into what I can do to address your concerns about
proper general clock handling in this specific driver.  But I'm
unable to do this for all other drivers as well which I happen to
pass by as I work on platform code (partially due to lack of
knowledge).  In any case I won't be able to test all of these
changes in all subsystems (mostly due to lack of hardware and
test setups).

So I suggest to leave these general cleanup activities for a
separate series.  The current series certainly improves general
platform code, transparently brings new drivers into successful
operation, and keeps the quality of existing code (doesn't break
anything, does even actively prevent breakage).  So it shall be
acceptable despite its not being perfect (like addressing each
and every other aspect which may arise elsewhere).  Where would I
stop then?

Sorry for the lengthy reply, but I guess it's about just one
general aspect which equally applies to other parts of the
series, not just the specific SPI driver which the feedback was
provided for.  And I do appreciate your looking at the
submission.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
  2013-07-15 21:54       ` Sascha Hauer
  (?)
@ 2013-07-17 11:27           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 11:27 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
	Mark Brown, Marc Kleine-Budde, Wolfgang Grandegger,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, David Woodhouse,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 23:54 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 11:46:01PM +0200, Gerhard Sittig wrote:
> > with device tree based clock lookup, the MCLK name no longer
> > depends on the PSC index
> > 
> > Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
> > ---
> >  drivers/tty/serial/mpc52xx_uart.c |    8 ++------
> >  1 file changed, 2 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> > index 53c1093..221fb89 100644
> > --- a/drivers/tty/serial/mpc52xx_uart.c
> > +++ b/drivers/tty/serial/mpc52xx_uart.c
> > @@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
> >  static int mpc512x_psc_clock(struct uart_port *port, int enable)
> >  {
> >  	struct clk *psc_clk;
> > -	int psc_num;
> > -	char clk_name[10];
> >  
> >  	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);
> > +	psc_clk = clk_get(port->dev, "mclk");
> 
> Same comment applies here as Mark made to the spi driver.

So I'd like to respond in the same way as I did for the SPI
driver. :)

The scope of this series is the introduction of support for the
common clock framework.  Addressing other (legacy non-fatal and
previously accepted) issues as they get identified in bypassing
would be the scope of a separate patch or series.

I'm not questioning the need to fix other additionally identified
issues.  I'm just asking whether they shall be in the scope of
this very series.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
@ 2013-07-17 11:27           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 11:27 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 23:54 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 11:46:01PM +0200, Gerhard Sittig wrote:
> > with device tree based clock lookup, the MCLK name no longer
> > depends on the PSC index
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/tty/serial/mpc52xx_uart.c |    8 ++------
> >  1 file changed, 2 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> > index 53c1093..221fb89 100644
> > --- a/drivers/tty/serial/mpc52xx_uart.c
> > +++ b/drivers/tty/serial/mpc52xx_uart.c
> > @@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
> >  static int mpc512x_psc_clock(struct uart_port *port, int enable)
> >  {
> >  	struct clk *psc_clk;
> > -	int psc_num;
> > -	char clk_name[10];
> >  
> >  	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);
> > +	psc_clk = clk_get(port->dev, "mclk");
> 
> Same comment applies here as Mark made to the spi driver.

So I'd like to respond in the same way as I did for the SPI
driver. :)

The scope of this series is the introduction of support for the
common clock framework.  Addressing other (legacy non-fatal and
previously accepted) issues as they get identified in bypassing
would be the scope of a separate patch or series.

I'm not questioning the need to fix other additionally identified
issues.  I'm just asking whether they shall be in the scope of
this very series.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name
@ 2013-07-17 11:27           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 11:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 23:54 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 11:46:01PM +0200, Gerhard Sittig wrote:
> > with device tree based clock lookup, the MCLK name no longer
> > depends on the PSC index
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/tty/serial/mpc52xx_uart.c |    8 ++------
> >  1 file changed, 2 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> > index 53c1093..221fb89 100644
> > --- a/drivers/tty/serial/mpc52xx_uart.c
> > +++ b/drivers/tty/serial/mpc52xx_uart.c
> > @@ -619,21 +619,17 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
> >  static int mpc512x_psc_clock(struct uart_port *port, int enable)
> >  {
> >  	struct clk *psc_clk;
> > -	int psc_num;
> > -	char clk_name[10];
> >  
> >  	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);
> > +	psc_clk = clk_get(port->dev, "mclk");
> 
> Same comment applies here as Mark made to the spi driver.

So I'd like to respond in the same way as I did for the SPI
driver. :)

The scope of this series is the introduction of support for the
common clock framework.  Addressing other (legacy non-fatal and
previously accepted) issues as they get identified in bypassing
would be the scope of a separate patch or series.

I'm not questioning the need to fix other additionally identified
issues.  I'm just asking whether they shall be in the scope of
this very series.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-15 19:38       ` Sascha Hauer
@ 2013-07-17 12:07         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 12:07 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 21:38 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 6d55eb2..2c07061 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> >  	struct clk_divider *divider = to_clk_divider(hw);
> >  	unsigned int div, val;
> >  
> > -	val = readl(divider->reg) >> divider->shift;
> > +	val = clk_readl(divider->reg) >> divider->shift;
> >  	val &= div_mask(divider);
> 
> Would it be an option to use regmap for the generic dividers/muxes
> instead? This should be suitable for ppc and also for people who want to
> use the generic clocks on i2c devices.

Does regmap assume that those registers form a (dense) array of
equal sized items?  Does it introduce unconditional indirection
and requirement for explicit setup beyond mere mapping?  What's
the overhead compared to the readl/inbe32 approach that's
currently resolved at compile time?

Neither of the above needs to be a blocker, just needs to be
acceptable after consideration.  So far nobody appears to have
felt pain with the LE32 register assumption.


BTW does the common clock support that I introduce for MPC512x
only cover those parts from crystal over internal busses to
internal peripherals (register files).

It does not include bitrate generation within the peripherals --
this appears to remain the domain of individual drivers, which
keep manipulating register fields to derive wire bitrates from
internal references.  Sharing drivers between platforms with and
without common clock support forbids the switch anyway, or both
CCF abstraction as well as local register manipulation need to
get implemented in parallel, as I did for the mscan(4) driver.

Some of these bitrate related registers aren't 32bit entities and
thus could not get managed by the common clock primitives in
their current form.  Some of the IP blocks may even spread
integer values across several non-adjacent bit fields for legacy
reasons, but I guess that these aren't in the scope of the shared
primitives either (and they may not be popular either).


While we are at improvements for the common clock primitives:

What I missed was support for fractional dividers, i.e. dividers
with a register bitfield backed divider part but a fixed factor
multiplier part.  Currently there's only dividers (bitfield
factor or bitfield with table lookup for the factor) and
fixed-factor (multiplier and divider, but both of them fixed and
not adjustable by register manipulation).  This was addressed by
"intermediate" clock items ("ungated", "x4")


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-17 12:07         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 21:38 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 6d55eb2..2c07061 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> >  	struct clk_divider *divider = to_clk_divider(hw);
> >  	unsigned int div, val;
> >  
> > -	val = readl(divider->reg) >> divider->shift;
> > +	val = clk_readl(divider->reg) >> divider->shift;
> >  	val &= div_mask(divider);
> 
> Would it be an option to use regmap for the generic dividers/muxes
> instead? This should be suitable for ppc and also for people who want to
> use the generic clocks on i2c devices.

Does regmap assume that those registers form a (dense) array of
equal sized items?  Does it introduce unconditional indirection
and requirement for explicit setup beyond mere mapping?  What's
the overhead compared to the readl/inbe32 approach that's
currently resolved at compile time?

Neither of the above needs to be a blocker, just needs to be
acceptable after consideration.  So far nobody appears to have
felt pain with the LE32 register assumption.


BTW does the common clock support that I introduce for MPC512x
only cover those parts from crystal over internal busses to
internal peripherals (register files).

It does not include bitrate generation within the peripherals --
this appears to remain the domain of individual drivers, which
keep manipulating register fields to derive wire bitrates from
internal references.  Sharing drivers between platforms with and
without common clock support forbids the switch anyway, or both
CCF abstraction as well as local register manipulation need to
get implemented in parallel, as I did for the mscan(4) driver.

Some of these bitrate related registers aren't 32bit entities and
thus could not get managed by the common clock primitives in
their current form.  Some of the IP blocks may even spread
integer values across several non-adjacent bit fields for legacy
reasons, but I guess that these aren't in the scope of the shared
primitives either (and they may not be popular either).


While we are at improvements for the common clock primitives:

What I missed was support for fractional dividers, i.e. dividers
with a register bitfield backed divider part but a fixed factor
multiplier part.  Currently there's only dividers (bitfield
factor or bitfield with table lookup for the factor) and
fixed-factor (multiplier and divider, but both of them fixed and
not adjustable by register manipulation).  This was addressed by
"intermediate" clock items ("ungated", "x4")


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
  2013-07-17 11:22             ` Gerhard Sittig
  (?)
@ 2013-07-17 12:07               ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-17 12:07 UTC (permalink / raw)
  To: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 1693 bytes --]

On Wed, Jul 17, 2013 at 01:22:29PM +0200, Gerhard Sittig wrote:
> On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> > On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:

> > >   sprintf(name, "psc%d_mclk", master->bus_num);
> > >  	spiclk = clk_get(&master->dev, name);
> > > -	clk_enable(spiclk);
> > > +	clk_prepare_enable(spiclk);
> > >  	mps->mclk = clk_get_rate(spiclk);
> > >  	clk_put(spiclk);

> > This code is *clearly* buggy and should be fixed rather than papered
> > over.  Not only is there no matching put the driver is also dropping the
> > reference to the clock rather than holding on to it while it's in use.

> "This code" refers to the driver's original condition, right?  I
> agree that the driver has been suffering from incomplete clock
> handling since it was born three years ago.  And that this issue
> shall get addressed.  The question is just whether it needs to be
> part of this series which has a different focus.

This is a pretty long e-mail.  It'd probably have taken less time to
fix the issues than to reply to the e-mail...  but anyway.

A big part of the issue with the state of the driver is that there's
obvious clock API abuse going on that isn't corrected here - the main
one is that the sprintf() for the clock name is a fairly clear warning
sign, the driver should be using a fixed value there.  This raises a
warning flag for me about the quality of the common clock API
implementation that's being sent and/or the potential for bugs to be
noticed with the common clock framework.  I'd not expect this code to
actually work, and looking at the rest of the series I don't see how it
does since I can't see what forces the name.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 150 bytes --]

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

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 12:07               ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-17 12:07 UTC (permalink / raw)
  To: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 1693 bytes --]

On Wed, Jul 17, 2013 at 01:22:29PM +0200, Gerhard Sittig wrote:
> On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> > On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:

> > >   sprintf(name, "psc%d_mclk", master->bus_num);
> > >  	spiclk = clk_get(&master->dev, name);
> > > -	clk_enable(spiclk);
> > > +	clk_prepare_enable(spiclk);
> > >  	mps->mclk = clk_get_rate(spiclk);
> > >  	clk_put(spiclk);

> > This code is *clearly* buggy and should be fixed rather than papered
> > over.  Not only is there no matching put the driver is also dropping the
> > reference to the clock rather than holding on to it while it's in use.

> "This code" refers to the driver's original condition, right?  I
> agree that the driver has been suffering from incomplete clock
> handling since it was born three years ago.  And that this issue
> shall get addressed.  The question is just whether it needs to be
> part of this series which has a different focus.

This is a pretty long e-mail.  It'd probably have taken less time to
fix the issues than to reply to the e-mail...  but anyway.

A big part of the issue with the state of the driver is that there's
obvious clock API abuse going on that isn't corrected here - the main
one is that the sprintf() for the clock name is a fairly clear warning
sign, the driver should be using a fixed value there.  This raises a
warning flag for me about the quality of the common clock API
implementation that's being sent and/or the potential for bugs to be
noticed with the common clock framework.  I'd not expect this code to
actually work, and looking at the rest of the series I don't see how it
does since I can't see what forces the name.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 12:07               ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-17 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 17, 2013 at 01:22:29PM +0200, Gerhard Sittig wrote:
> On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> > On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:

> > >   sprintf(name, "psc%d_mclk", master->bus_num);
> > >  	spiclk = clk_get(&master->dev, name);
> > > -	clk_enable(spiclk);
> > > +	clk_prepare_enable(spiclk);
> > >  	mps->mclk = clk_get_rate(spiclk);
> > >  	clk_put(spiclk);

> > This code is *clearly* buggy and should be fixed rather than papered
> > over.  Not only is there no matching put the driver is also dropping the
> > reference to the clock rather than holding on to it while it's in use.

> "This code" refers to the driver's original condition, right?  I
> agree that the driver has been suffering from incomplete clock
> handling since it was born three years ago.  And that this issue
> shall get addressed.  The question is just whether it needs to be
> part of this series which has a different focus.

This is a pretty long e-mail.  It'd probably have taken less time to
fix the issues than to reply to the e-mail...  but anyway.

A big part of the issue with the state of the driver is that there's
obvious clock API abuse going on that isn't corrected here - the main
one is that the sprintf() for the clock name is a fairly clear warning
sign, the driver should be using a fixed value there.  This raises a
warning flag for me about the quality of the common clock API
implementation that's being sent and/or the potential for bugs to be
noticed with the common clock framework.  I'd not expect this code to
actually work, and looking at the rest of the series I don't see how it
does since I can't see what forces the name.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130717/245057e2/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
  2013-07-17 12:07               ` Mark Brown
  (?)
@ 2013-07-17 14:26                   ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 14:26 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
	Marc Kleine-Budde,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

On Wed, Jul 17, 2013 at 13:07 +0100, Mark Brown wrote:
> 
> On Wed, Jul 17, 2013 at 01:22:29PM +0200, Gerhard Sittig wrote:
> > On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> > > On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> 
> > > >   sprintf(name, "psc%d_mclk", master->bus_num);
> > > >  	spiclk = clk_get(&master->dev, name);
> > > > -	clk_enable(spiclk);
> > > > +	clk_prepare_enable(spiclk);
> > > >  	mps->mclk = clk_get_rate(spiclk);
> > > >  	clk_put(spiclk);
> 
> > > This code is *clearly* buggy and should be fixed rather than papered
> > > over.  Not only is there no matching put the driver is also dropping the
> > > reference to the clock rather than holding on to it while it's in use.
> 
> > "This code" refers to the driver's original condition, right?  I
> > agree that the driver has been suffering from incomplete clock
> > handling since it was born three years ago.  And that this issue
> > shall get addressed.  The question is just whether it needs to be
> > part of this series which has a different focus.
> 
> This is a pretty long e-mail.  It'd probably have taken less time to
> fix the issues than to reply to the e-mail...  but anyway.

[ this is meta stuff, technical details are after the next quotation ]

Not quite.  Please consider that careful submission is as
expensive as thorough review is, and that a lot of work is done
before v1 gets submitted, which you may not always notice from
looking at a concentrated series that may no longer suggest how
much it took to get there (especially when prepared carefully).

As mentioned before I did not question the need to fix issues as
they get identified.  I just asked whether reworking the serial
driver is in the scope of this series which provides a different
clock driver implementation for the platform.  To me these two
things are orthogonal, while I did promise to see how I can
address your concerns.

Let's provide the technical information you need to judge the
quality of the submission and see why it shall be acceptable:


> A big part of the issue with the state of the driver is that there's
> obvious clock API abuse going on that isn't corrected here - the main
> one is that the sprintf() for the clock name is a fairly clear warning
> sign, the driver should be using a fixed value there.  This raises a
> warning flag for me about the quality of the common clock API
> implementation that's being sent and/or the potential for bugs to be
> noticed with the common clock framework.  I'd not expect this code to
> actually work, and looking at the rest of the series I don't see how it
> does since I can't see what forces the name.

Why the code does work:

OK, here is why the driver keeps its state throughout the set and
is operational as good or as bad as it was before:

The sprintf() in the SPI driver used to construct a name which
includes the PSC index.  This applies to the UART driver as well,
as they both use the PSC controller hardware to implement their
serial communication.

The corresponding clock name was found in the previous PPC_CLOCK
implementation since the clock driver provided those names which
include the PSC index (fixed strings in a table).

The initial COMMON_CLK implementation in part 09/24 registers
clkdev items for compatibility during migration.  The string
isn't greppable since it's constructed by the preprocessor in the
MCLK data setup, see the MCLK_SETUP_DATA_PSC() macro.

Part 13/24 adjusts the SPI driver to no longer construct a name,
but instead use a fixed string after OF based clock lookup became
available.  This shall meet your expectation and simplifies the
client side.  Part 15/24 does the same for the UART driver.

Part 16/24 removes the clkdev registration in the clock driver
after both the UART and SPI clients switched to OF clock lookups.

At this stage things are the way you would expect:  The client
uses a fixed string in the lookup, while lookup occurs via device
tree, and instances are supported without the clients'
constructing something based on a component index.

Remaining issues are not with the common clock support of the
platform, but in the serial driver and are identical to the
previous (actually: the initial) status.  While we agree on the
existance of the remaining issue and the desire to address it.
Just not on which context that fix shall be done in.


The series' status and perspective:

The UART and SPI drivers did work before, while it's true that
clock handling wasn't complete (in non-fatal ways).  This has
been the case in the past, and has been identified just now.

The serial drivers are kept operational during migration, and
still are operational after the series.  But now they use common
clock and OF lookups, which is an improvement for the platform in
my eyes.

It's true that the status of the serial driver isn't improved
with the series -- but it isn't degraded either, while
(additional) breakage actively gets prevented.

Now let me see how I can improve the SPI driver with regard to
overall clock handling and beyond mere operation by coincidence
in the absence of errors.  But please understand that I don't
want to stall the common clock support for a whole platform just
because some of the drivers it needs to touch to keep them
operational have other issues that weren't addressed yet, while
these issues aren't introduced with the series but preceed it.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 14:26                   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 14:26 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, linuxppc-dev, Rob Herring, Marc Kleine-Budde,
	linux-arm-kernel, Anatolij Gustschin, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

On Wed, Jul 17, 2013 at 13:07 +0100, Mark Brown wrote:
> 
> On Wed, Jul 17, 2013 at 01:22:29PM +0200, Gerhard Sittig wrote:
> > On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> > > On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> 
> > > >   sprintf(name, "psc%d_mclk", master->bus_num);
> > > >  	spiclk = clk_get(&master->dev, name);
> > > > -	clk_enable(spiclk);
> > > > +	clk_prepare_enable(spiclk);
> > > >  	mps->mclk = clk_get_rate(spiclk);
> > > >  	clk_put(spiclk);
> 
> > > This code is *clearly* buggy and should be fixed rather than papered
> > > over.  Not only is there no matching put the driver is also dropping the
> > > reference to the clock rather than holding on to it while it's in use.
> 
> > "This code" refers to the driver's original condition, right?  I
> > agree that the driver has been suffering from incomplete clock
> > handling since it was born three years ago.  And that this issue
> > shall get addressed.  The question is just whether it needs to be
> > part of this series which has a different focus.
> 
> This is a pretty long e-mail.  It'd probably have taken less time to
> fix the issues than to reply to the e-mail...  but anyway.

[ this is meta stuff, technical details are after the next quotation ]

Not quite.  Please consider that careful submission is as
expensive as thorough review is, and that a lot of work is done
before v1 gets submitted, which you may not always notice from
looking at a concentrated series that may no longer suggest how
much it took to get there (especially when prepared carefully).

As mentioned before I did not question the need to fix issues as
they get identified.  I just asked whether reworking the serial
driver is in the scope of this series which provides a different
clock driver implementation for the platform.  To me these two
things are orthogonal, while I did promise to see how I can
address your concerns.

Let's provide the technical information you need to judge the
quality of the submission and see why it shall be acceptable:


> A big part of the issue with the state of the driver is that there's
> obvious clock API abuse going on that isn't corrected here - the main
> one is that the sprintf() for the clock name is a fairly clear warning
> sign, the driver should be using a fixed value there.  This raises a
> warning flag for me about the quality of the common clock API
> implementation that's being sent and/or the potential for bugs to be
> noticed with the common clock framework.  I'd not expect this code to
> actually work, and looking at the rest of the series I don't see how it
> does since I can't see what forces the name.

Why the code does work:

OK, here is why the driver keeps its state throughout the set and
is operational as good or as bad as it was before:

The sprintf() in the SPI driver used to construct a name which
includes the PSC index.  This applies to the UART driver as well,
as they both use the PSC controller hardware to implement their
serial communication.

The corresponding clock name was found in the previous PPC_CLOCK
implementation since the clock driver provided those names which
include the PSC index (fixed strings in a table).

The initial COMMON_CLK implementation in part 09/24 registers
clkdev items for compatibility during migration.  The string
isn't greppable since it's constructed by the preprocessor in the
MCLK data setup, see the MCLK_SETUP_DATA_PSC() macro.

Part 13/24 adjusts the SPI driver to no longer construct a name,
but instead use a fixed string after OF based clock lookup became
available.  This shall meet your expectation and simplifies the
client side.  Part 15/24 does the same for the UART driver.

Part 16/24 removes the clkdev registration in the clock driver
after both the UART and SPI clients switched to OF clock lookups.

At this stage things are the way you would expect:  The client
uses a fixed string in the lookup, while lookup occurs via device
tree, and instances are supported without the clients'
constructing something based on a component index.

Remaining issues are not with the common clock support of the
platform, but in the serial driver and are identical to the
previous (actually: the initial) status.  While we agree on the
existance of the remaining issue and the desire to address it.
Just not on which context that fix shall be done in.


The series' status and perspective:

The UART and SPI drivers did work before, while it's true that
clock handling wasn't complete (in non-fatal ways).  This has
been the case in the past, and has been identified just now.

The serial drivers are kept operational during migration, and
still are operational after the series.  But now they use common
clock and OF lookups, which is an improvement for the platform in
my eyes.

It's true that the status of the serial driver isn't improved
with the series -- but it isn't degraded either, while
(additional) breakage actively gets prevented.

Now let me see how I can improve the SPI driver with regard to
overall clock handling and beyond mere operation by coincidence
in the absence of errors.  But please understand that I don't
want to stall the common clock support for a whole platform just
because some of the drivers it needs to touch to keep them
operational have other issues that weren't addressed yet, while
these issues aren't introduced with the series but preceed it.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 14:26                   ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-17 14:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 17, 2013 at 13:07 +0100, Mark Brown wrote:
> 
> On Wed, Jul 17, 2013 at 01:22:29PM +0200, Gerhard Sittig wrote:
> > On Mon, Jul 15, 2013 at 21:17 +0100, Mark Brown wrote:
> > > On Mon, Jul 15, 2013 at 08:47:30PM +0200, Gerhard Sittig wrote:
> 
> > > >   sprintf(name, "psc%d_mclk", master->bus_num);
> > > >  	spiclk = clk_get(&master->dev, name);
> > > > -	clk_enable(spiclk);
> > > > +	clk_prepare_enable(spiclk);
> > > >  	mps->mclk = clk_get_rate(spiclk);
> > > >  	clk_put(spiclk);
> 
> > > This code is *clearly* buggy and should be fixed rather than papered
> > > over.  Not only is there no matching put the driver is also dropping the
> > > reference to the clock rather than holding on to it while it's in use.
> 
> > "This code" refers to the driver's original condition, right?  I
> > agree that the driver has been suffering from incomplete clock
> > handling since it was born three years ago.  And that this issue
> > shall get addressed.  The question is just whether it needs to be
> > part of this series which has a different focus.
> 
> This is a pretty long e-mail.  It'd probably have taken less time to
> fix the issues than to reply to the e-mail...  but anyway.

[ this is meta stuff, technical details are after the next quotation ]

Not quite.  Please consider that careful submission is as
expensive as thorough review is, and that a lot of work is done
before v1 gets submitted, which you may not always notice from
looking at a concentrated series that may no longer suggest how
much it took to get there (especially when prepared carefully).

As mentioned before I did not question the need to fix issues as
they get identified.  I just asked whether reworking the serial
driver is in the scope of this series which provides a different
clock driver implementation for the platform.  To me these two
things are orthogonal, while I did promise to see how I can
address your concerns.

Let's provide the technical information you need to judge the
quality of the submission and see why it shall be acceptable:


> A big part of the issue with the state of the driver is that there's
> obvious clock API abuse going on that isn't corrected here - the main
> one is that the sprintf() for the clock name is a fairly clear warning
> sign, the driver should be using a fixed value there.  This raises a
> warning flag for me about the quality of the common clock API
> implementation that's being sent and/or the potential for bugs to be
> noticed with the common clock framework.  I'd not expect this code to
> actually work, and looking at the rest of the series I don't see how it
> does since I can't see what forces the name.

Why the code does work:

OK, here is why the driver keeps its state throughout the set and
is operational as good or as bad as it was before:

The sprintf() in the SPI driver used to construct a name which
includes the PSC index.  This applies to the UART driver as well,
as they both use the PSC controller hardware to implement their
serial communication.

The corresponding clock name was found in the previous PPC_CLOCK
implementation since the clock driver provided those names which
include the PSC index (fixed strings in a table).

The initial COMMON_CLK implementation in part 09/24 registers
clkdev items for compatibility during migration.  The string
isn't greppable since it's constructed by the preprocessor in the
MCLK data setup, see the MCLK_SETUP_DATA_PSC() macro.

Part 13/24 adjusts the SPI driver to no longer construct a name,
but instead use a fixed string after OF based clock lookup became
available.  This shall meet your expectation and simplifies the
client side.  Part 15/24 does the same for the UART driver.

Part 16/24 removes the clkdev registration in the clock driver
after both the UART and SPI clients switched to OF clock lookups.

At this stage things are the way you would expect:  The client
uses a fixed string in the lookup, while lookup occurs via device
tree, and instances are supported without the clients'
constructing something based on a component index.

Remaining issues are not with the common clock support of the
platform, but in the serial driver and are identical to the
previous (actually: the initial) status.  While we agree on the
existance of the remaining issue and the desire to address it.
Just not on which context that fix shall be done in.


The series' status and perspective:

The UART and SPI drivers did work before, while it's true that
clock handling wasn't complete (in non-fatal ways).  This has
been the case in the past, and has been identified just now.

The serial drivers are kept operational during migration, and
still are operational after the series.  But now they use common
clock and OF lookups, which is an improvement for the platform in
my eyes.

It's true that the status of the serial driver isn't improved
with the series -- but it isn't degraded either, while
(additional) breakage actively gets prevented.

Now let me see how I can improve the SPI driver with regard to
overall clock handling and beyond mere operation by coincidence
in the absence of errors.  But please understand that I don't
want to stall the common clock support for a whole platform just
because some of the drivers it needs to touch to keep them
operational have other issues that weren't addressed yet, while
these issues aren't introduced with the series but preceed it.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
  2013-07-17 14:26                   ` Gerhard Sittig
  (?)
@ 2013-07-17 16:53                       ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-17 16:53 UTC (permalink / raw)
  To: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Greg Kroah-Hartman,
	Rob Herring, Marc Kleine-Budde, Wolfgang Grandegger,
	Anatolij Gustschin, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 2415 bytes --]

On Wed, Jul 17, 2013 at 04:26:28PM +0200, Gerhard Sittig wrote:
> On Wed, Jul 17, 2013 at 13:07 +0100, Mark Brown wrote:

> > This is a pretty long e-mail.  It'd probably have taken less time to
> > fix the issues than to reply to the e-mail...  but anyway.

> Not quite.  Please consider that careful submission is as
> expensive as thorough review is, and that a lot of work is done
> before v1 gets submitted, which you may not always notice from
> looking at a concentrated series that may no longer suggest how
> much it took to get there (especially when prepared carefully).

This is rather undermined the more time and effort gets spent pushing
back against doing trival fixes, of course...  besides, the issues here
are all really simple to fix and test.  It's not a major or risky
rewrite of the driver or anything like that - most of this can be tested
by just probing the driver.

> As mentioned before I did not question the need to fix issues as
> they get identified.  I just asked whether reworking the serial

OK, so send patches then.

> The initial COMMON_CLK implementation in part 09/24 registers
> clkdev items for compatibility during migration.  The string
> isn't greppable since it's constructed by the preprocessor in the
> MCLK data setup, see the MCLK_SETUP_DATA_PSC() macro.

Ugh, right - it didn't show up in searches due to being hidden by the
macro.

> Now let me see how I can improve the SPI driver with regard to
> overall clock handling and beyond mere operation by coincidence
> in the absence of errors.  But please understand that I don't
> want to stall the common clock support for a whole platform just
> because some of the drivers it needs to touch to keep them
> operational have other issues that weren't addressed yet, while
> these issues aren't introduced with the series but preceed it.

Again, you're not being asked to implement substantial new functionality
here.  From my point of view I can't test this at all so I'm looking at
code that's obviously not good for the standard clock API and wondering
if it even works or how robust it's going to be going forward as the
common clock code changes which makes me relucatant to say it'll be OK.

The fact that you're switching over to use generic code is itself a
reason to make sure that the API usage is sane, dodgy API usage against
open coded clock implementations is less risky than against the common
code.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 16:53                       ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-17 16:53 UTC (permalink / raw)
  To: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 2415 bytes --]

On Wed, Jul 17, 2013 at 04:26:28PM +0200, Gerhard Sittig wrote:
> On Wed, Jul 17, 2013 at 13:07 +0100, Mark Brown wrote:

> > This is a pretty long e-mail.  It'd probably have taken less time to
> > fix the issues than to reply to the e-mail...  but anyway.

> Not quite.  Please consider that careful submission is as
> expensive as thorough review is, and that a lot of work is done
> before v1 gets submitted, which you may not always notice from
> looking at a concentrated series that may no longer suggest how
> much it took to get there (especially when prepared carefully).

This is rather undermined the more time and effort gets spent pushing
back against doing trival fixes, of course...  besides, the issues here
are all really simple to fix and test.  It's not a major or risky
rewrite of the driver or anything like that - most of this can be tested
by just probing the driver.

> As mentioned before I did not question the need to fix issues as
> they get identified.  I just asked whether reworking the serial

OK, so send patches then.

> The initial COMMON_CLK implementation in part 09/24 registers
> clkdev items for compatibility during migration.  The string
> isn't greppable since it's constructed by the preprocessor in the
> MCLK data setup, see the MCLK_SETUP_DATA_PSC() macro.

Ugh, right - it didn't show up in searches due to being hidden by the
macro.

> Now let me see how I can improve the SPI driver with regard to
> overall clock handling and beyond mere operation by coincidence
> in the absence of errors.  But please understand that I don't
> want to stall the common clock support for a whole platform just
> because some of the drivers it needs to touch to keep them
> operational have other issues that weren't addressed yet, while
> these issues aren't introduced with the series but preceed it.

Again, you're not being asked to implement substantial new functionality
here.  From my point of view I can't test this at all so I'm looking at
code that's obviously not good for the standard clock API and wondering
if it even works or how robust it's going to be going forward as the
common clock code changes which makes me relucatant to say it'll be OK.

The fact that you're switching over to use generic code is itself a
reason to make sure that the API usage is sane, dodgy API usage against
open coded clock implementations is less risky than against the common
code.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them
@ 2013-07-17 16:53                       ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-17 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 17, 2013 at 04:26:28PM +0200, Gerhard Sittig wrote:
> On Wed, Jul 17, 2013 at 13:07 +0100, Mark Brown wrote:

> > This is a pretty long e-mail.  It'd probably have taken less time to
> > fix the issues than to reply to the e-mail...  but anyway.

> Not quite.  Please consider that careful submission is as
> expensive as thorough review is, and that a lot of work is done
> before v1 gets submitted, which you may not always notice from
> looking at a concentrated series that may no longer suggest how
> much it took to get there (especially when prepared carefully).

This is rather undermined the more time and effort gets spent pushing
back against doing trival fixes, of course...  besides, the issues here
are all really simple to fix and test.  It's not a major or risky
rewrite of the driver or anything like that - most of this can be tested
by just probing the driver.

> As mentioned before I did not question the need to fix issues as
> they get identified.  I just asked whether reworking the serial

OK, so send patches then.

> The initial COMMON_CLK implementation in part 09/24 registers
> clkdev items for compatibility during migration.  The string
> isn't greppable since it's constructed by the preprocessor in the
> MCLK data setup, see the MCLK_SETUP_DATA_PSC() macro.

Ugh, right - it didn't show up in searches due to being hidden by the
macro.

> Now let me see how I can improve the SPI driver with regard to
> overall clock handling and beyond mere operation by coincidence
> in the absence of errors.  But please understand that I don't
> want to stall the common clock support for a whole platform just
> because some of the drivers it needs to touch to keep them
> operational have other issues that weren't addressed yet, while
> these issues aren't introduced with the series but preceed it.

Again, you're not being asked to implement substantial new functionality
here.  From my point of view I can't test this at all so I'm looking at
code that's obviously not good for the standard clock API and wondering
if it even works or how robust it's going to be going forward as the
common clock code changes which makes me relucatant to say it'll be OK.

The fact that you're switching over to use generic code is itself a
reason to make sure that the API usage is sane, dodgy API usage against
open coded clock implementations is less risky than against the common
code.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130717/df54aed2/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-15 19:38       ` Sascha Hauer
@ 2013-07-18  7:04         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18  7:04 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 15, 2013 at 21:38 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 6d55eb2..2c07061 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> >  	struct clk_divider *divider = to_clk_divider(hw);
> >  	unsigned int div, val;
> >  
> > -	val = readl(divider->reg) >> divider->shift;
> > +	val = clk_readl(divider->reg) >> divider->shift;
> >  	val &= div_mask(divider);
> 
> Would it be an option to use regmap for the generic dividers/muxes
> instead? This should be suitable for ppc and also for people who want to
> use the generic clocks on i2c devices.

Some other thought crossed my mind regarding access to clock
control registers that reside behind some communication channel
like I2C:

The common clock API assumes (it's part of the contract) that
there are potentially expensive operations like get, put, prepare
and unprepare, as well as swift and non-blocking operations like
enable and disable.

Would the regmap abstraction hide the potentially blocking nature
of a register access (I understand that you can implement "local"
as well as "remote" register sets by this mechanism)?  Or could
you still meet the assumptions or requirements of the common
clock API?

It might as well be the responsibility of the clock driver's
implementor to arrange for the availability of non-blocking
enable/disable operations, just as it is today.  Such that
expensive register access need not be forbidden in general.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18  7:04         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18  7:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 15, 2013 at 21:38 +0200, Sascha Hauer wrote:
> 
> On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 6d55eb2..2c07061 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> >  	struct clk_divider *divider = to_clk_divider(hw);
> >  	unsigned int div, val;
> >  
> > -	val = readl(divider->reg) >> divider->shift;
> > +	val = clk_readl(divider->reg) >> divider->shift;
> >  	val &= div_mask(divider);
> 
> Would it be an option to use regmap for the generic dividers/muxes
> instead? This should be suitable for ppc and also for people who want to
> use the generic clocks on i2c devices.

Some other thought crossed my mind regarding access to clock
control registers that reside behind some communication channel
like I2C:

The common clock API assumes (it's part of the contract) that
there are potentially expensive operations like get, put, prepare
and unprepare, as well as swift and non-blocking operations like
enable and disable.

Would the regmap abstraction hide the potentially blocking nature
of a register access (I understand that you can implement "local"
as well as "remote" register sets by this mechanism)?  Or could
you still meet the assumptions or requirements of the common
clock API?

It might as well be the responsibility of the clock driver's
implementor to arrange for the availability of non-blocking
enable/disable operations, just as it is today.  Such that
expensive register access need not be forbidden in general.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-18  7:04         ` Gerhard Sittig
@ 2013-07-18  8:06           ` Sascha Hauer
  -1 siblings, 0 replies; 432+ messages in thread
From: Sascha Hauer @ 2013-07-18  8:06 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss, Detlev Zundel,
	Wolfram Sang, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Marc Kleine-Budde, David Woodhouse, Wolfgang Grandegger,
	Mauro Carvalho Chehab

On Thu, Jul 18, 2013 at 09:04:02AM +0200, Gerhard Sittig wrote:
> On Mon, Jul 15, 2013 at 21:38 +0200, Sascha Hauer wrote:
> > 
> > On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> > > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > > index 6d55eb2..2c07061 100644
> > > --- a/drivers/clk/clk-divider.c
> > > +++ b/drivers/clk/clk-divider.c
> > > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> > >  	struct clk_divider *divider = to_clk_divider(hw);
> > >  	unsigned int div, val;
> > >  
> > > -	val = readl(divider->reg) >> divider->shift;
> > > +	val = clk_readl(divider->reg) >> divider->shift;
> > >  	val &= div_mask(divider);
> > 
> > Would it be an option to use regmap for the generic dividers/muxes
> > instead? This should be suitable for ppc and also for people who want to
> > use the generic clocks on i2c devices.
> 
> Some other thought crossed my mind regarding access to clock
> control registers that reside behind some communication channel
> like I2C:
> 
> The common clock API assumes (it's part of the contract) that
> there are potentially expensive operations like get, put, prepare
> and unprepare, as well as swift and non-blocking operations like
> enable and disable.
> 
> Would the regmap abstraction hide the potentially blocking nature
> of a register access (I understand that you can implement "local"
> as well as "remote" register sets by this mechanism)?  Or could
> you still meet the assumptions or requirements of the common
> clock API?
> 
> It might as well be the responsibility of the clock driver's
> implementor to arrange for the availability of non-blocking
> enable/disable operations, just as it is today.  Such that
> expensive register access need not be forbidden in general.

regmap for mmio uses a spinlock for read/modify/write operations, just
like you have to use a spinlock in the common clk dividers/gates. This
part wouldn't change with regmap.

For i2c connected clocks where a spinlock doesn't work due to the
nonatomic nature of i2c devices we would have to move the enable/disble
stuff to prepare/unprepare in the common gate code. This can be left
for someone who works on i2c clocks though.

I think regmap has the potential to solve a number of issues like the
hardcoded readl/writel in the common clock blocks, issues with i2c
clocks and your endianess issue. The biggest question probably is how
to get there without putting too much of a burden on you. It's probably
not an option to convert all users to regmap, so it seems additional
functions like clk_register_gate_regmap are better to handle.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18  8:06           ` Sascha Hauer
  0 siblings, 0 replies; 432+ messages in thread
From: Sascha Hauer @ 2013-07-18  8:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 18, 2013 at 09:04:02AM +0200, Gerhard Sittig wrote:
> On Mon, Jul 15, 2013 at 21:38 +0200, Sascha Hauer wrote:
> > 
> > On Mon, Jul 15, 2013 at 08:47:34PM +0200, Gerhard Sittig wrote:
> > > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > > index 6d55eb2..2c07061 100644
> > > --- a/drivers/clk/clk-divider.c
> > > +++ b/drivers/clk/clk-divider.c
> > > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> > >  	struct clk_divider *divider = to_clk_divider(hw);
> > >  	unsigned int div, val;
> > >  
> > > -	val = readl(divider->reg) >> divider->shift;
> > > +	val = clk_readl(divider->reg) >> divider->shift;
> > >  	val &= div_mask(divider);
> > 
> > Would it be an option to use regmap for the generic dividers/muxes
> > instead? This should be suitable for ppc and also for people who want to
> > use the generic clocks on i2c devices.
> 
> Some other thought crossed my mind regarding access to clock
> control registers that reside behind some communication channel
> like I2C:
> 
> The common clock API assumes (it's part of the contract) that
> there are potentially expensive operations like get, put, prepare
> and unprepare, as well as swift and non-blocking operations like
> enable and disable.
> 
> Would the regmap abstraction hide the potentially blocking nature
> of a register access (I understand that you can implement "local"
> as well as "remote" register sets by this mechanism)?  Or could
> you still meet the assumptions or requirements of the common
> clock API?
> 
> It might as well be the responsibility of the clock driver's
> implementor to arrange for the availability of non-blocking
> enable/disable operations, just as it is today.  Such that
> expensive register access need not be forbidden in general.

regmap for mmio uses a spinlock for read/modify/write operations, just
like you have to use a spinlock in the common clk dividers/gates. This
part wouldn't change with regmap.

For i2c connected clocks where a spinlock doesn't work due to the
nonatomic nature of i2c devices we would have to move the enable/disble
stuff to prepare/unprepare in the common gate code. This can be left
for someone who works on i2c clocks though.

I think regmap has the potential to solve a number of issues like the
hardcoded readl/writel in the common clock blocks, issues with i2c
clocks and your endianess issue. The biggest question probably is how
to get there without putting too much of a burden on you. It's probably
not an option to convert all users to regmap, so it seems additional
functions like clk_register_gate_regmap are better to handle.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-18  7:04         ` Gerhard Sittig
  (?)
@ 2013-07-18  9:17             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 432+ messages in thread
From: Russell King - ARM Linux @ 2013-07-18  9:17 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	Sascha Hauer, Rob Herring, David Woodhouse, Mark Brown,
	Marc Kleine-Budde,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Wolfgang Grandegger,
	Mauro Carvalho Chehab

On Thu, Jul 18, 2013 at 09:04:02AM +0200, Gerhard Sittig wrote:
> The common clock API assumes (it's part of the contract) that
> there are potentially expensive operations like get, put, prepare
> and unprepare, as well as swift and non-blocking operations like
> enable and disable.

Let's get something straight here, because what you've said above is
wrong.

1. clk_get() and clk_put() are NOT part of the common clock API.
   They're separate - they're part of the clk API, and the infrastructure
   behind that is clkdev, which is a separately owned thing (by me.)

2. The "contract" of the clk API is defined by the clk API, not by some
   random implementation like the common clock API.  The clk API is
   maintained by myself, and is described in include/linux/clk.h

3. clk_prepare() and clk_unprepare() are functions MUST only be called
   from contexts where sleeping is permitted.  These functions MAY sleep
   for whatever reason they require to, and as long as they require to.
   (This is the whole reason these two functions were created in the
   first place.)

4. clk_enable() and clk_disable() MAY be called from any context, but
   MUST never sleep.  If you need to talk over a non-atomic bus for these,
   then these functions should be no-ops, and the code which does that
   must be executed from the clk_prepare()/clk_unprepare() operations.

That is the "clk API" contract.  The CCF has no bearing on this; if it
disagrees, then the CCF is buggy and is non-conformant.

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18  9:17             ` Russell King - ARM Linux
  0 siblings, 0 replies; 432+ messages in thread
From: Russell King - ARM Linux @ 2013-07-18  9:17 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	Sascha Hauer, Rob Herring, David Woodhouse, Mark Brown,
	Marc Kleine-Budde, linux-arm-kernel, Anatolij Gustschin,
	linuxppc-dev, devicetree-discuss, Wolfgang Grandegger,
	Mauro Carvalho Chehab

On Thu, Jul 18, 2013 at 09:04:02AM +0200, Gerhard Sittig wrote:
> The common clock API assumes (it's part of the contract) that
> there are potentially expensive operations like get, put, prepare
> and unprepare, as well as swift and non-blocking operations like
> enable and disable.

Let's get something straight here, because what you've said above is
wrong.

1. clk_get() and clk_put() are NOT part of the common clock API.
   They're separate - they're part of the clk API, and the infrastructure
   behind that is clkdev, which is a separately owned thing (by me.)

2. The "contract" of the clk API is defined by the clk API, not by some
   random implementation like the common clock API.  The clk API is
   maintained by myself, and is described in include/linux/clk.h

3. clk_prepare() and clk_unprepare() are functions MUST only be called
   from contexts where sleeping is permitted.  These functions MAY sleep
   for whatever reason they require to, and as long as they require to.
   (This is the whole reason these two functions were created in the
   first place.)

4. clk_enable() and clk_disable() MAY be called from any context, but
   MUST never sleep.  If you need to talk over a non-atomic bus for these,
   then these functions should be no-ops, and the code which does that
   must be executed from the clk_prepare()/clk_unprepare() operations.

That is the "clk API" contract.  The CCF has no bearing on this; if it
disagrees, then the CCF is buggy and is non-conformant.

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18  9:17             ` Russell King - ARM Linux
  0 siblings, 0 replies; 432+ messages in thread
From: Russell King - ARM Linux @ 2013-07-18  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 18, 2013 at 09:04:02AM +0200, Gerhard Sittig wrote:
> The common clock API assumes (it's part of the contract) that
> there are potentially expensive operations like get, put, prepare
> and unprepare, as well as swift and non-blocking operations like
> enable and disable.

Let's get something straight here, because what you've said above is
wrong.

1. clk_get() and clk_put() are NOT part of the common clock API.
   They're separate - they're part of the clk API, and the infrastructure
   behind that is clkdev, which is a separately owned thing (by me.)

2. The "contract" of the clk API is defined by the clk API, not by some
   random implementation like the common clock API.  The clk API is
   maintained by myself, and is described in include/linux/clk.h

3. clk_prepare() and clk_unprepare() are functions MUST only be called
   from contexts where sleeping is permitted.  These functions MAY sleep
   for whatever reason they require to, and as long as they require to.
   (This is the whole reason these two functions were created in the
   first place.)

4. clk_enable() and clk_disable() MAY be called from any context, but
   MUST never sleep.  If you need to talk over a non-atomic bus for these,
   then these functions should be no-ops, and the code which does that
   must be executed from the clk_prepare()/clk_unprepare() operations.

That is the "clk API" contract.  The CCF has no bearing on this; if it
disagrees, then the CCF is buggy and is non-conformant.

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-18  8:06           ` Sascha Hauer
  (?)
@ 2013-07-18 10:08               ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-18 10:08 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, David Woodhouse,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 583 bytes --]

On Thu, Jul 18, 2013 at 10:06:57AM +0200, Sascha Hauer wrote:

> I think regmap has the potential to solve a number of issues like the
> hardcoded readl/writel in the common clock blocks, issues with i2c
> clocks and your endianess issue. The biggest question probably is how
> to get there without putting too much of a burden on you. It's probably
> not an option to convert all users to regmap, so it seems additional
> functions like clk_register_gate_regmap are better to handle.

That's basically what regulator does.  There's versions of the ops that
all the drivers can use.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18 10:08               ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-18 10:08 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 583 bytes --]

On Thu, Jul 18, 2013 at 10:06:57AM +0200, Sascha Hauer wrote:

> I think regmap has the potential to solve a number of issues like the
> hardcoded readl/writel in the common clock blocks, issues with i2c
> clocks and your endianess issue. The biggest question probably is how
> to get there without putting too much of a burden on you. It's probably
> not an option to convert all users to regmap, so it seems additional
> functions like clk_register_gate_regmap are better to handle.

That's basically what regulator does.  There's versions of the ops that
all the drivers can use.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18 10:08               ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-18 10:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 18, 2013 at 10:06:57AM +0200, Sascha Hauer wrote:

> I think regmap has the potential to solve a number of issues like the
> hardcoded readl/writel in the common clock blocks, issues with i2c
> clocks and your endianess issue. The biggest question probably is how
> to get there without putting too much of a burden on you. It's probably
> not an option to convert all users to regmap, so it seems additional
> functions like clk_register_gate_regmap are better to handle.

That's basically what regulator does.  There's versions of the ops that
all the drivers can use.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130718/43ffb513/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 00/24] add COMMON_CLK support for PowerPC MPC512x
  2013-07-15 18:47 ` Gerhard Sittig
  (?)
@ 2013-07-18 17:00     ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this series introduces support for the common clock framework (CCF,
COMMON_CLK Kconfig option) in the PowerPC based MPC512x platform

although the series does touch several subsystems -- serial, spi, net
(can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of the
patches are strictly clock related

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #413: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 836 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v2:
- cleanup of the UART and SPI clock handling before the introduction of
  common clock support for the platform, as incomplete clock handling
  becomes fatal or more dangerous later (which in turn changes the
  context of the "device tree lookup only" followup patch later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call


Gerhard Sittig (24):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  mtd: mpc5121_nfc: prepare clocks before enabling them
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  spi: mpc512x: remove now obsolete clock lookup name
  serial: mpc512x: remove now obsolete clock lookup name
  clk: mpc512x: remove now obsolete clkdev registration
  serial: mpc512x: setup the PSC FIFO clock as well
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: make mpc512x code use common clock
  powerpc/mpc512x: improve DIU related clock setup
  i2c: mpc: OF clock lookup for MPC512x
  USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  fs_enet: OF clock lookup (non-fatal), prepare and enable
  [media] fsl-viu: OF clock lookup, prepare before enable
  powerpc/fsl-pci: OF clock lookup, prepare before enable
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove MPC512x non-COMMON_CLK code path

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  761 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   15 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |    9 +
 drivers/media/platform/fsl-viu.c                   |   12 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |    4 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  234 +++---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +-
 drivers/spi/spi-mpc512x-psc.c                      |   45 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  137 +++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   24 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 26 files changed, 1392 insertions(+), 1038 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc1-00024-g96ff9fe ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      10          10           320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 2           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 2           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk_out 1           1            80000000
                      psc7_mclk 1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 00/24] add COMMON_CLK support for PowerPC MPC512x
@ 2013-07-18 17:00     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this series introduces support for the common clock framework (CCF,
COMMON_CLK Kconfig option) in the PowerPC based MPC512x platform

although the series does touch several subsystems -- serial, spi, net
(can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of the
patches are strictly clock related

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #413: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 836 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v2:
- cleanup of the UART and SPI clock handling before the introduction of
  common clock support for the platform, as incomplete clock handling
  becomes fatal or more dangerous later (which in turn changes the
  context of the "device tree lookup only" followup patch later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call


Gerhard Sittig (24):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  mtd: mpc5121_nfc: prepare clocks before enabling them
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  spi: mpc512x: remove now obsolete clock lookup name
  serial: mpc512x: remove now obsolete clock lookup name
  clk: mpc512x: remove now obsolete clkdev registration
  serial: mpc512x: setup the PSC FIFO clock as well
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: make mpc512x code use common clock
  powerpc/mpc512x: improve DIU related clock setup
  i2c: mpc: OF clock lookup for MPC512x
  USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  fs_enet: OF clock lookup (non-fatal), prepare and enable
  [media] fsl-viu: OF clock lookup, prepare before enable
  powerpc/fsl-pci: OF clock lookup, prepare before enable
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove MPC512x non-COMMON_CLK code path

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  761 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   15 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |    9 +
 drivers/media/platform/fsl-viu.c                   |   12 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |    4 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  234 +++---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +-
 drivers/spi/spi-mpc512x-psc.c                      |   45 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  137 +++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   24 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 26 files changed, 1392 insertions(+), 1038 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc1-00024-g96ff9fe ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      10          10           320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 2           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 2           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk_out 1           1            80000000
                      psc7_mclk 1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 00/24] add COMMON_CLK support for PowerPC MPC512x
@ 2013-07-18 17:00     ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

this series introduces support for the common clock framework (CCF,
COMMON_CLK Kconfig option) in the PowerPC based MPC512x platform

although the series does touch several subsystems -- serial, spi, net
(can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of the
patches are strictly clock related

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #413: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 836 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v2:
- cleanup of the UART and SPI clock handling before the introduction of
  common clock support for the platform, as incomplete clock handling
  becomes fatal or more dangerous later (which in turn changes the
  context of the "device tree lookup only" followup patch later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call


Gerhard Sittig (24):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  mtd: mpc5121_nfc: prepare clocks before enabling them
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  spi: mpc512x: remove now obsolete clock lookup name
  serial: mpc512x: remove now obsolete clock lookup name
  clk: mpc512x: remove now obsolete clkdev registration
  serial: mpc512x: setup the PSC FIFO clock as well
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: make mpc512x code use common clock
  powerpc/mpc512x: improve DIU related clock setup
  i2c: mpc: OF clock lookup for MPC512x
  USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  fs_enet: OF clock lookup (non-fatal), prepare and enable
  [media] fsl-viu: OF clock lookup, prepare before enable
  powerpc/fsl-pci: OF clock lookup, prepare before enable
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove MPC512x non-COMMON_CLK code path

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  761 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   15 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |    9 +
 drivers/media/platform/fsl-viu.c                   |   12 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |    4 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  234 +++---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +-
 drivers/spi/spi-mpc512x-psc.c                      |   45 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  137 +++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   24 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 26 files changed, 1392 insertions(+), 1038 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc1-00024-g96ff9fe ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      10          10           320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 2           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 2           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk_out 1           1            80000000
                      psc7_mclk 1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 01/24] spi: mpc512x: cleanup clock API use
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 17:00         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

the omission in the clock handling previously went unnoticed, but will
become fatal in the common clock scenario

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/spi/spi-mpc512x-psc.c |   49 ++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..7a32373 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,8 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +518,30 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	mps->clk_mclk = clk_get(dev, clk_name);
+	if (IS_ERR(mps->clk_mclk))
+		goto free_irq;
+	ret = clk_prepare_enable(mps->clk_mclk);
+	if (ret)
+		goto free_putclk;
+	mps->mclk_rate = clk_get_rate(mps->clk_mclk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_disclk;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_disclk;
 
 	return ret;
 
+free_disclk:
+	clk_disable_unprepare(mps->clk_mclk);
+free_putclk:
+	clk_put(mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,8 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
+	clk_put(mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 01/24] spi: mpc512x: cleanup clock API use
@ 2013-07-18 17:00         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

the omission in the clock handling previously went unnoticed, but will
become fatal in the common clock scenario

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   49 ++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..7a32373 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,8 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +518,30 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	mps->clk_mclk = clk_get(dev, clk_name);
+	if (IS_ERR(mps->clk_mclk))
+		goto free_irq;
+	ret = clk_prepare_enable(mps->clk_mclk);
+	if (ret)
+		goto free_putclk;
+	mps->mclk_rate = clk_get_rate(mps->clk_mclk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_disclk;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_disclk;
 
 	return ret;
 
+free_disclk:
+	clk_disable_unprepare(mps->clk_mclk);
+free_putclk:
+	clk_put(mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,8 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
+	clk_put(mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 01/24] spi: mpc512x: cleanup clock API use
@ 2013-07-18 17:00         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

the omission in the clock handling previously went unnoticed, but will
become fatal in the common clock scenario

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   49 ++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..7a32373 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,8 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +518,30 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	mps->clk_mclk = clk_get(dev, clk_name);
+	if (IS_ERR(mps->clk_mclk))
+		goto free_irq;
+	ret = clk_prepare_enable(mps->clk_mclk);
+	if (ret)
+		goto free_putclk;
+	mps->mclk_rate = clk_get_rate(mps->clk_mclk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_disclk;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_disclk;
 
 	return ret;
 
+free_disclk:
+	clk_disable_unprepare(mps->clk_mclk);
+free_putclk:
+	clk_put(mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,8 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
+	clk_put(mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 02/24] serial: mpc512x: cleanup clock API use
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 17:00         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

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

the omission in the clock handling previously went unnoticed, but will
become fatal in the common clock scenario

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 <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/tty/serial/mpc52xx_uart.c |  100 ++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..98a1f43 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,75 @@ 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 = 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");
+		clk_put(clk);
+		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);
+		clk_put(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 *port, struct device_node *np)
@@ -873,7 +919,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +954,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1216,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1243,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 02/24] serial: mpc512x: cleanup clock API use
@ 2013-07-18 17:00         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

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

the omission in the clock handling previously went unnoticed, but will
become fatal in the common clock scenario

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 <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |  100 ++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..98a1f43 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,75 @@ 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 = 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");
+		clk_put(clk);
+		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);
+		clk_put(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 *port, struct device_node *np)
@@ -873,7 +919,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +954,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1216,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1243,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 02/24] serial: mpc512x: cleanup clock API use
@ 2013-07-18 17:00         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

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

the omission in the clock handling previously went unnoticed, but will
become fatal in the common clock scenario

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 <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |  100 ++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..98a1f43 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,75 @@ 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 = 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");
+		clk_put(clk);
+		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);
+		clk_put(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 *port, struct device_node *np)
@@ -873,7 +919,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +954,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1216,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1243,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

must prepare clocks before enabling them, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..eb7771d 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,7 +618,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
+		clk_disable_unprepare(prv->clk);
 		clk_put(prv->clk);
 	}
 
@@ -737,7 +737,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 		goto error;
 	}
 
-	clk_enable(prv->clk);
+	clk_prepare_enable(prv->clk);
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

must prepare clocks before enabling them, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..eb7771d 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,7 +618,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
+		clk_disable_unprepare(prv->clk);
 		clk_put(prv->clk);
 	}
 
@@ -737,7 +737,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 		goto error;
 	}
 
-	clk_enable(prv->clk);
+	clk_prepare_enable(prv->clk);
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 05/24] clk: wrap I/O access for improved portability
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 06/24] dts: mpc512x: prepare for preprocessor support
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 06/24] dts: mpc512x: prepare for preprocessor support
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 07/24] dts: mpc512x: introduce dt-bindings/clock/ header
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 17:00         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 07/24] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-07-18 17:00         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 07/24] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-07-18 17:00         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 08/24] dts: mpc512x: add clock related device tree specs
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc@80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock@f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc@80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock@f00 {
+		clks: clock@f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 08/24] dts: mpc512x: add clock related device tree specs
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc at 80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock at f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc at 80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock at f00 {
+		clks: clock at f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

since not all drivers for peripherals were adjusted yet to properly
allocate and release their clock items, this platform clock driver
implementation pre-enables some of the clock items to not break
peripheral drivers during migration -- these clock pre-enable
workarounds will get removed as peripheral drivers get adjusted

to provide clock names which the serial communication drivers are using
and where the PSC index number is encoded into, clkdev registration is
done to not break these peripheral drivers -- this workaround will get
removed as these drivers get adjusted after device tree based clock
lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  778 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 810 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..6627957
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

since not all drivers for peripherals were adjusted yet to properly
allocate and release their clock items, this platform clock driver
implementation pre-enables some of the clock items to not break
peripheral drivers during migration -- these clock pre-enable
workarounds will get removed as peripheral drivers get adjusted

to provide clock names which the serial communication drivers are using
and where the PSC index number is encoded into, clkdev registration is
done to not break these peripheral drivers -- this workaround will get
removed as these drivers get adjusted after device tree based clock
lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  778 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 810 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..6627957
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 10/24] dts: mpc512x: add clock specs for client lookups
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the client side of device tree based clock lookups:
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu,
viu, mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the
shared mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver; some drivers
still need to learn how to lookup OF clocks, other drivers will
transparently probe successfully on MPC512x as well (sdhc)

few 'clock-names' (nfc, viu) use strings that are encoded in their
respective drivers to keep up compatibility, an alternative approach
would be to register clkdev items in the platform's clock driver for
the migration period

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..983da9c 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram@30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "nfc_clk";	/* backwards compat */
 	};
 
 	localbus@80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc@1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c@1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol@1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display@2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can@2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu@2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "viu_clk";	/* backwards compat */
 		};
 
 		mdio@2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet@2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo@11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma@14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 10/24] dts: mpc512x: add clock specs for client lookups
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the client side of device tree based clock lookups:
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu,
viu, mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the
shared mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver; some drivers
still need to learn how to lookup OF clocks, other drivers will
transparently probe successfully on MPC512x as well (sdhc)

few 'clock-names' (nfc, viu) use strings that are encoded in their
respective drivers to keep up compatibility, an alternative approach
would be to register clkdev items in the platform's clock driver for
the migration period

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..983da9c 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram@30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "nfc_clk";	/* backwards compat */
 	};
 
 	localbus@80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc@1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c@1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol@1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display@2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can@2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu@2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "viu_clk";	/* backwards compat */
 		};
 
 		mdio@2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet@2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo@11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma@14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 10/24] dts: mpc512x: add clock specs for client lookups
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the client side of device tree based clock lookups:
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu,
viu, mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the
shared mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver; some drivers
still need to learn how to lookup OF clocks, other drivers will
transparently probe successfully on MPC512x as well (sdhc)

few 'clock-names' (nfc, viu) use strings that are encoded in their
respective drivers to keep up compatibility, an alternative approach
would be to register clkdev items in the platform's clock driver for
the migration period

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..983da9c 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram at 30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "nfc_clk";	/* backwards compat */
 	};
 
 	localbus at 80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can at 1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc at 1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c at 1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol at 1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display at 2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can at 2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can at 2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu at 2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "viu_clk";	/* backwards compat */
 		};
 
 		mdio at 2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet at 2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo at 11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma at 14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 11/24] spi: mpc512x: remove now obsolete clock lookup name
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 7a32373..b04f094 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -474,8 +474,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -518,9 +516,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	mps->clk_mclk = clk_get(dev, clk_name);
+	mps->clk_mclk = clk_get(dev, "mclk");
 	if (IS_ERR(mps->clk_mclk))
 		goto free_irq;
 	ret = clk_prepare_enable(mps->clk_mclk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 11/24] spi: mpc512x: remove now obsolete clock lookup name
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 7a32373..b04f094 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -474,8 +474,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -518,9 +516,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	mps->clk_mclk = clk_get(dev, clk_name);
+	mps->clk_mclk = clk_get(dev, "mclk");
 	if (IS_ERR(mps->clk_mclk))
 		goto free_irq;
 	ret = clk_prepare_enable(mps->clk_mclk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 11/24] spi: mpc512x: remove now obsolete clock lookup name
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 7a32373..b04f094 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -474,8 +474,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -518,9 +516,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	mps->clk_mclk = clk_get(dev, clk_name);
+	mps->clk_mclk = clk_get(dev, "mclk");
 	if (IS_ERR(mps->clk_mclk))
 		goto free_irq;
 	ret = clk_prepare_enable(mps->clk_mclk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 12/24] serial: mpc512x: remove now obsolete clock lookup name
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 98a1f43..8643dcf 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -623,14 +623,11 @@ 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)
 {
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 	int err;
+	int psc_num;
 
-	psc_num = (port->mapbase & 0xf00) >> 8;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = clk_get(port->dev, clk_name);
+	clk = clk_get(port->dev, "mclk");
 	if (IS_ERR(clk)) {
 		dev_err(port->dev, "Failed to get MCLK!\n");
 		return PTR_ERR(clk);
@@ -641,6 +638,7 @@ static int mpc512x_psc_alloc_clock(struct uart_port *port)
 		clk_put(clk);
 		return err;
 	}
+	psc_num = (port->mapbase & 0xf00) >> 8;
 	psc_mclk_clk[psc_num] = clk;
 	return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 12/24] serial: mpc512x: remove now obsolete clock lookup name
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 98a1f43..8643dcf 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -623,14 +623,11 @@ 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)
 {
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 	int err;
+	int psc_num;
 
-	psc_num = (port->mapbase & 0xf00) >> 8;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = clk_get(port->dev, clk_name);
+	clk = clk_get(port->dev, "mclk");
 	if (IS_ERR(clk)) {
 		dev_err(port->dev, "Failed to get MCLK!\n");
 		return PTR_ERR(clk);
@@ -641,6 +638,7 @@ static int mpc512x_psc_alloc_clock(struct uart_port *port)
 		clk_put(clk);
 		return err;
 	}
+	psc_num = (port->mapbase & 0xf00) >> 8;
 	psc_mclk_clk[psc_num] = clk;
 	return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 13/24] clk: mpc512x: remove now obsolete clkdev registration
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the peripheral drivers for UART and SPI mode (both using the PSC
controller) got converted to device tree based clock lookups, the
platform clock driver need no longer provide the "psc%d_mclk" name which
depends on the PSC index number -- remove the clk_register_clkdev() call

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 6627957..b822469 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -529,17 +528,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from device tree specs, and device tree nodes need to
-	 * provide the clock specs, before this clkdev registration
-	 * becomes obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 13/24] clk: mpc512x: remove now obsolete clkdev registration
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

after the peripheral drivers for UART and SPI mode (both using the PSC
controller) got converted to device tree based clock lookups, the
platform clock driver need no longer provide the "psc%d_mclk" name which
depends on the PSC index number -- remove the clk_register_clkdev() call

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 6627957..b822469 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -529,17 +528,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from device tree specs, and device tree nodes need to
-	 * provide the clock specs, before this clkdev registration
-	 * becomes obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 14/24] serial: mpc512x: setup the PSC FIFO clock as well
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 17:00       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare and enable the FIFO clock upon PSC FIFO initialization,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   39 +++++++++++++++++++++----
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index b822469..99d197d 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -689,8 +689,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 8643dcf..3fdadf9 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -574,30 +575,56 @@ static int __init mpc512x_psc_fifoc_init(void)
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
+	}
+
+	psc_fifoc_clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(psc_fifoc_clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(psc_fifoc_clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		goto out_clk_put;
 	}
 
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+out_clk_put:
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return -ENODEV;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk && !IS_ERR(psc_fifoc_clk)) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 14/24] serial: mpc512x: setup the PSC FIFO clock as well
@ 2013-07-18 17:00       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

prepare and enable the FIFO clock upon PSC FIFO initialization,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   39 +++++++++++++++++++++----
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index b822469..99d197d 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -689,8 +689,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 8643dcf..3fdadf9 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -574,30 +575,56 @@ static int __init mpc512x_psc_fifoc_init(void)
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
+	}
+
+	psc_fifoc_clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(psc_fifoc_clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(psc_fifoc_clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		goto out_clk_put;
 	}
 
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+out_clk_put:
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return -ENODEV;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk && !IS_ERR(psc_fifoc_clk)) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-18  9:17             ` Russell King - ARM Linux
@ 2013-07-18 17:47               ` Nicolas Pitre
  -1 siblings, 0 replies; 432+ messages in thread
From: Nicolas Pitre @ 2013-07-18 17:47 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, devicetree-discuss,
	Greg Kroah-Hartman, Gerhard Sittig, linuxppc-dev, Rob Herring,
	Mark Brown, Marc Kleine-Budde, Wolfgang Grandegger,
	David Woodhouse, Sascha Hauer, linux-arm-kernel,
	Mauro Carvalho Chehab

On Thu, 18 Jul 2013, Russell King - ARM Linux wrote:

> 1. clk_get() and clk_put() are NOT part of the common clock API.
>    They're separate - they're part of the clk API, and the infrastructure
>    behind that is clkdev, which is a separately owned thing (by me.)
> 
> 2. The "contract" of the clk API is defined by the clk API, not by some
>    random implementation like the common clock API.  The clk API is
>    maintained by myself, and is described in include/linux/clk.h
> 
> 3. clk_prepare() and clk_unprepare() are functions MUST only be called
>    from contexts where sleeping is permitted.  These functions MAY sleep
>    for whatever reason they require to, and as long as they require to.
>    (This is the whole reason these two functions were created in the
>    first place.)
> 
> 4. clk_enable() and clk_disable() MAY be called from any context, but
>    MUST never sleep.  If you need to talk over a non-atomic bus for these,
>    then these functions should be no-ops, and the code which does that
>    must be executed from the clk_prepare()/clk_unprepare() operations.

Could the above be included in some form in Documentation/clk.txt (this 
is likely one of the first location people look for information) and 
elsewhere if appropriate please?

A *lot* of people are confused by the prepare-enable-disable-unprepare 
sequence and when I try to find some rational for the prepare/enable 
split I can only direct them to mail archive posts since this is nowhere 
to be found in the kernel.

The comments in include/linux/clk.h, while correct, are very terse and 
don't provide any insight to the reason why there is a split in the API.

The content of Documentation/clk.txt does refer to prepare and enable 
(and their counterparts) but again doesn't provide any clue about the 
reason for their existence.

Since there've been several good posts with usage example now buried 
into list archives, I think this would go a long way helping people get 
it right if those were part of the kernel documentation as well.


Nicolas

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-07-18 17:47               ` Nicolas Pitre
  0 siblings, 0 replies; 432+ messages in thread
From: Nicolas Pitre @ 2013-07-18 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 18 Jul 2013, Russell King - ARM Linux wrote:

> 1. clk_get() and clk_put() are NOT part of the common clock API.
>    They're separate - they're part of the clk API, and the infrastructure
>    behind that is clkdev, which is a separately owned thing (by me.)
> 
> 2. The "contract" of the clk API is defined by the clk API, not by some
>    random implementation like the common clock API.  The clk API is
>    maintained by myself, and is described in include/linux/clk.h
> 
> 3. clk_prepare() and clk_unprepare() are functions MUST only be called
>    from contexts where sleeping is permitted.  These functions MAY sleep
>    for whatever reason they require to, and as long as they require to.
>    (This is the whole reason these two functions were created in the
>    first place.)
> 
> 4. clk_enable() and clk_disable() MAY be called from any context, but
>    MUST never sleep.  If you need to talk over a non-atomic bus for these,
>    then these functions should be no-ops, and the code which does that
>    must be executed from the clk_prepare()/clk_unprepare() operations.

Could the above be included in some form in Documentation/clk.txt (this 
is likely one of the first location people look for information) and 
elsewhere if appropriate please?

A *lot* of people are confused by the prepare-enable-disable-unprepare 
sequence and when I try to find some rational for the prepare/enable 
split I can only direct them to mail archive posts since this is nowhere 
to be found in the kernel.

The comments in include/linux/clk.h, while correct, are very terse and 
don't provide any insight to the reason why there is a split in the API.

The content of Documentation/clk.txt does refer to prepare and enable 
(and their counterparts) but again doesn't provide any clue about the 
reason for their existence.

Since there've been several good posts with usage example now buried 
into list archives, I think this would go a long way helping people get 
it right if those were part of the kernel documentation as well.


Nicolas

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 15/24] net: can: mscan: add a comment on reg to idx mapping
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 15/24] net: can: mscan: add a comment on reg to idx mapping
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 15/24] net: can: mscan: add a comment on reg to idx mapping
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

extend the mscan(4) driver with alternative support for the COMMON_CLK
approach which is an option in the MPC512x platform, keep the existing
clock support implementation in place since the driver is shared with
other MPC5xxx SoCs which don't have common clock support

one byproduct of this change is that the CAN driver no longer needs to
access the SoC's clock control registers, which shall be the domain of
the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..dd26ab6 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+#else	/* COMMON_CLK */
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -238,6 +375,8 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

extend the mscan(4) driver with alternative support for the COMMON_CLK
approach which is an option in the MPC512x platform, keep the existing
clock support implementation in place since the driver is shared with
other MPC5xxx SoCs which don't have common clock support

one byproduct of this change is that the CAN driver no longer needs to
access the SoC's clock control registers, which shall be the domain of
the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..dd26ab6 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+#else	/* COMMON_CLK */
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -238,6 +375,8 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

extend the mscan(4) driver with alternative support for the COMMON_CLK
approach which is an option in the MPC512x platform, keep the existing
clock support implementation in place since the driver is shared with
other MPC5xxx SoCs which don't have common clock support

one byproduct of this change is that the CAN driver no longer needs to
access the SoC's clock control registers, which shall be the domain of
the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..dd26ab6 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		clk_prepare_enable(clk_can);
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+#else	/* COMMON_CLK */
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -238,6 +375,8 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 17/24] powerpc/mpc512x: improve DIU related clock setup
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 99d197d..b8963b7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 17/24] powerpc/mpc512x: improve DIU related clock setup
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 99d197d..b8963b7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 17/24] powerpc/mpc512x: improve DIU related clock setup
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 99d197d..b8963b7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

make the MPC I2C driver prepare and enable the peripheral clock
('per' for register access) in the MPC512x setup routine,
make this clock setup non-fatal to allow for a migration period,
remove the pre-enabling hack in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/i2c/busses/i2c-mpc.c                  |    9 +++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index b8963b7..49c52bc 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..13d6822 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -264,11 +265,19 @@ static void mpc_i2c_setup_512x(struct device_node *node,
 					 struct mpc_i2c *i2c,
 					 u32 clock, u32 prescaler)
 {
+	struct clk *clk;
 	struct device_node *node_ctrl;
 	void __iomem *ctrl;
 	const u32 *pval;
 	u32 idx;
 
+	/* enable clock for the I2C peripheral (non fatal) */
+	clk = of_clk_get_by_name(node, "per");
+	if (!IS_ERR(clk)) {
+		clk_prepare_enable(clk);
+		clk_put(clk);
+	}
+
 	/* Enable I2C interrupts for mpc5121 */
 	node_ctrl = of_find_compatible_node(NULL, NULL,
 					    "fsl,mpc5121-i2c-ctrl");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the MPC I2C driver prepare and enable the peripheral clock
('per' for register access) in the MPC512x setup routine,
make this clock setup non-fatal to allow for a migration period,
remove the pre-enabling hack in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/i2c/busses/i2c-mpc.c                  |    9 +++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index b8963b7..49c52bc 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..13d6822 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -264,11 +265,19 @@ static void mpc_i2c_setup_512x(struct device_node *node,
 					 struct mpc_i2c *i2c,
 					 u32 clock, u32 prescaler)
 {
+	struct clk *clk;
 	struct device_node *node_ctrl;
 	void __iomem *ctrl;
 	const u32 *pval;
 	u32 idx;
 
+	/* enable clock for the I2C peripheral (non fatal) */
+	clk = of_clk_get_by_name(node, "per");
+	if (!IS_ERR(clk)) {
+		clk_prepare_enable(clk);
+		clk_put(clk);
+	}
+
 	/* Enable I2C interrupts for mpc5121 */
 	node_ctrl = of_find_compatible_node(NULL, NULL,
 					    "fsl,mpc5121-i2c-ctrl");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

make the MPC I2C driver prepare and enable the peripheral clock
('per' for register access) in the MPC512x setup routine,
make this clock setup non-fatal to allow for a migration period,
remove the pre-enabling hack in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/i2c/busses/i2c-mpc.c                  |    9 +++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index b8963b7..49c52bc 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -692,7 +692,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..13d6822 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -264,11 +265,19 @@ static void mpc_i2c_setup_512x(struct device_node *node,
 					 struct mpc_i2c *i2c,
 					 u32 clock, u32 prescaler)
 {
+	struct clk *clk;
 	struct device_node *node_ctrl;
 	void __iomem *ctrl;
 	const u32 *pval;
 	u32 idx;
 
+	/* enable clock for the I2C peripheral (non fatal) */
+	clk = of_clk_get_by_name(node, "per");
+	if (!IS_ERR(clk)) {
+		clk_prepare_enable(clk);
+		clk_put(clk);
+	}
+
 	/* Enable I2C interrupts for mpc5121 */
 	node_ctrl = of_find_compatible_node(NULL, NULL,
 					    "fsl,mpc5121-i2c-ctrl");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 20:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup in the MPC512x initialization (lookup
'per' for register access), add error check in the clock setup, must
prepare clocks before they can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..eb564f3 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,25 +260,19 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
+	int err;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		clk_put(clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,7 +297,7 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
 		clk_put(pdata->clk);
 	}
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup in the MPC512x initialization (lookup
'per' for register access), add error check in the clock setup, must
prepare clocks before they can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..eb564f3 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,25 +260,19 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
+	int err;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		clk_put(clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,7 +297,7 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
 		clk_put(pdata->clk);
 	}
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 20/24] fs_enet: OF clock lookup (non-fatal), prepare and enable
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup, remove
the pre-enable workaround in the MPC512x platform's clock driver

this change implements non-fatal clock lookup since not all platforms
provide device tree specs for clocks, but failure to enable a specified
clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c      |    1 -
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +++++++++++++++++++-
 include/linux/fs_enet_pd.h                         |    3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 49c52bc..e9451a7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -691,7 +691,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..df92e12 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1020,6 +1020,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 		fpi->cp_command = *data;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found
+	 */
+	fpi->clk_per = clk_get(&ofdev->dev, "per");
+	if (IS_ERR(fpi->clk_per))
+		fpi->clk_per = NULL;
+	if (fpi->clk_per) {
+		int err;
+		err = clk_prepare_enable(fpi->clk_per);
+		if (err) {
+			ret = err;
+			goto out_clk_put;
+		}
+	}
+
 	fpi->rx_ring = 32;
 	fpi->tx_ring = 32;
 	fpi->rx_copybreak = 240;
@@ -1028,7 +1043,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
 	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
 						  NULL)))
-		goto out_free_fpi;
+		goto out_clk_dis;
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
 		phy_connection_type = of_get_property(ofdev->dev.of_node,
@@ -1108,6 +1123,12 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+out_clk_dis:
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
+out_clk_put:
+	if (fpi->clk_per)
+		clk_put(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1124,6 +1145,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		clk_put(fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 20/24] fs_enet: OF clock lookup (non-fatal), prepare and enable
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup, remove
the pre-enable workaround in the MPC512x platform's clock driver

this change implements non-fatal clock lookup since not all platforms
provide device tree specs for clocks, but failure to enable a specified
clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c      |    1 -
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +++++++++++++++++++-
 include/linux/fs_enet_pd.h                         |    3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 49c52bc..e9451a7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -691,7 +691,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..df92e12 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1020,6 +1020,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 		fpi->cp_command = *data;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found
+	 */
+	fpi->clk_per = clk_get(&ofdev->dev, "per");
+	if (IS_ERR(fpi->clk_per))
+		fpi->clk_per = NULL;
+	if (fpi->clk_per) {
+		int err;
+		err = clk_prepare_enable(fpi->clk_per);
+		if (err) {
+			ret = err;
+			goto out_clk_put;
+		}
+	}
+
 	fpi->rx_ring = 32;
 	fpi->tx_ring = 32;
 	fpi->rx_copybreak = 240;
@@ -1028,7 +1043,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
 	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
 						  NULL)))
-		goto out_free_fpi;
+		goto out_clk_dis;
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
 		phy_connection_type = of_get_property(ofdev->dev.of_node,
@@ -1108,6 +1123,12 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+out_clk_dis:
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
+out_clk_put:
+	if (fpi->clk_per)
+		clk_put(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1124,6 +1145,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		clk_put(fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 20/24] fs_enet: OF clock lookup (non-fatal), prepare and enable
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup, remove
the pre-enable workaround in the MPC512x platform's clock driver

this change implements non-fatal clock lookup since not all platforms
provide device tree specs for clocks, but failure to enable a specified
clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c      |    1 -
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   27 +++++++++++++++++++-
 include/linux/fs_enet_pd.h                         |    3 +++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 49c52bc..e9451a7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -691,7 +691,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..df92e12 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1020,6 +1020,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 		fpi->cp_command = *data;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found
+	 */
+	fpi->clk_per = clk_get(&ofdev->dev, "per");
+	if (IS_ERR(fpi->clk_per))
+		fpi->clk_per = NULL;
+	if (fpi->clk_per) {
+		int err;
+		err = clk_prepare_enable(fpi->clk_per);
+		if (err) {
+			ret = err;
+			goto out_clk_put;
+		}
+	}
+
 	fpi->rx_ring = 32;
 	fpi->tx_ring = 32;
 	fpi->rx_copybreak = 240;
@@ -1028,7 +1043,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
 	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
 						  NULL)))
-		goto out_free_fpi;
+		goto out_clk_dis;
 
 	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
 		phy_connection_type = of_get_property(ofdev->dev.of_node,
@@ -1108,6 +1123,12 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+out_clk_dis:
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
+out_clk_put:
+	if (fpi->clk_per)
+		clk_put(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1124,6 +1145,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		clk_put(fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 21/24] [media] fsl-viu: OF clock lookup, prepare before enable
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..b95aa43 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1582,8 +1582,11 @@ static int viu_of_probe(struct platform_device *op)
 		dev_err(&op->dev, "failed to find the clock module!\n");
 		ret = -ENODEV;
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
+	}
+	ret = clk_prepare_enable(viu_dev->clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		goto err_clk_put;
 	}
 
 	/* reset VIU module */
@@ -1602,7 +1605,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+err_clk_put:
 	clk_put(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
@@ -1626,7 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 
 	video_unregister_device(dev->vdev);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 21/24] [media] fsl-viu: OF clock lookup, prepare before enable
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..b95aa43 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1582,8 +1582,11 @@ static int viu_of_probe(struct platform_device *op)
 		dev_err(&op->dev, "failed to find the clock module!\n");
 		ret = -ENODEV;
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
+	}
+	ret = clk_prepare_enable(viu_dev->clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		goto err_clk_put;
 	}
 
 	/* reset VIU module */
@@ -1602,7 +1605,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+err_clk_put:
 	clk_put(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
@@ -1626,7 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 
 	video_unregister_device(dev->vdev);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 21/24] [media] fsl-viu: OF clock lookup, prepare before enable
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup, must prepare clocks before enabling
them, unprepare after disable, error check in the clock setup

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..b95aa43 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1582,8 +1582,11 @@ static int viu_of_probe(struct platform_device *op)
 		dev_err(&op->dev, "failed to find the clock module!\n");
 		ret = -ENODEV;
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
+	}
+	ret = clk_prepare_enable(viu_dev->clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		goto err_clk_put;
 	}
 
 	/* reset VIU module */
@@ -1602,7 +1605,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+err_clk_put:
 	clk_put(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
@@ -1626,7 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 
 	video_unregister_device(dev->vdev);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, error check in the clock setup

this change implements non-fatal clock lookup for compatibility with
platforms that don't provide OF clock specs, but failure to enable a
specified clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/sysdev/fsl_pci.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..cb2ed92 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -741,6 +743,7 @@ err0:
 
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
+	struct clk *clk;
 	int ret;
 	int len;
 	struct pci_controller *hose;
@@ -758,6 +761,18 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	}
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
+	/* non-fatal OF clock lookup, but fatal when a clock
+	 * was specified yet could not get enabled */
+	clk = of_clk_get_by_name(dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		clk_put(clk);
+		if (ret) {
+			pr_err("Could not enable peripheral clock\n");
+			return ret;
+		}
+	}
+
 	/* Fetch host bridge registers address */
 	if (of_address_to_resource(dev, 0, &rsrc_reg)) {
 		printk(KERN_WARNING "Can't get pci register base!\n");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

device tree based clock lookup, must prepare clocks before enabling
them, error check in the clock setup

this change implements non-fatal clock lookup for compatibility with
platforms that don't provide OF clock specs, but failure to enable a
specified clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..cb2ed92 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -741,6 +743,7 @@ err0:
 
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
+	struct clk *clk;
 	int ret;
 	int len;
 	struct pci_controller *hose;
@@ -758,6 +761,18 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	}
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
+	/* non-fatal OF clock lookup, but fatal when a clock
+	 * was specified yet could not get enabled */
+	clk = of_clk_get_by_name(dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		clk_put(clk);
+		if (ret) {
+			pr_err("Could not enable peripheral clock\n");
+			return ret;
+		}
+	}
+
 	/* Fetch host bridge registers address */
 	if (of_address_to_resource(dev, 0, &rsrc_reg)) {
 		printk(KERN_WARNING "Can't get pci register base!\n");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

device tree based clock lookup, must prepare clocks before enabling
them, error check in the clock setup

this change implements non-fatal clock lookup for compatibility with
platforms that don't provide OF clock specs, but failure to enable a
specified clock is considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..cb2ed92 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -741,6 +743,7 @@ err0:
 
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
+	struct clk *clk;
 	int ret;
 	int len;
 	struct pci_controller *hose;
@@ -758,6 +761,18 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	}
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
+	/* non-fatal OF clock lookup, but fatal when a clock
+	 * was specified yet could not get enabled */
+	clk = of_clk_get_by_name(dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		clk_put(clk);
+		if (ret) {
+			pr_err("Could not enable peripheral clock\n");
+			return ret;
+		}
+	}
+
 	/* Fetch host bridge registers address */
 	if (of_address_to_resource(dev, 0, &rsrc_reg)) {
 		printk(KERN_WARNING "Can't get pci register base!\n");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  2013-07-18 17:00     ` Gerhard Sittig
  (?)
@ 2013-07-18 20:20         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-07-18 20:20         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-18 20:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

transition to the COMMON_CLK framework has completed for the MPC512x
platform, remove the now obsolete code path of the mpc5xxx mscan
driver which accessed clock control module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  136 -----------------------------------
 1 file changed, 136 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index dd26ab6..cf5e4cfc 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,9 +108,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -244,139 +241,6 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
-#else	/* COMMON_CLK */
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path
@ 2013-07-18 20:20       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-18 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

transition to the COMMON_CLK framework has completed for the MPC512x
platform, remove the now obsolete code path of the mpc5xxx mscan
driver which accessed clock control module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  136 -----------------------------------
 1 file changed, 136 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index dd26ab6..cf5e4cfc 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -108,9 +108,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -244,139 +241,6 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
-#else	/* COMMON_CLK */
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
  2013-07-18 20:20       ` Gerhard Sittig
@ 2013-07-18 20:33         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 432+ messages in thread
From: Russell King - ARM Linux @ 2013-07-18 20:33 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Thu, Jul 18, 2013 at 10:20:52PM +0200, Gerhard Sittig wrote:
> +	/* enable clock for the I2C peripheral (non fatal) */
> +	clk = of_clk_get_by_name(node, "per");
> +	if (!IS_ERR(clk)) {
> +		clk_prepare_enable(clk);
> +		clk_put(clk);
> +	}
> +

This kind of hacked up approach to the clk API is exactly the thing I
really don't like seeing.  I don't know what it is... is the clk API
somehow difficult to use or what's the problem with doing stuff correctly?

1. Get the clock in your probe function.
2. Prepare it at the appropriate time.
3. Enable it appropriately.  (or if you want to combine 2 and 3, use
   clk_prepare_enable().)
4. Ensure that enables/disables and prepares/unprepares are appropriately
   balanced.
5. 'put' the clock in your remove function.

Certainly do not get-enable-put a clock.  You're supposed to hold on to
the clock all the time that you're actually using it.

Final point - if you want to make it non-fatal, don't play games like:

	clk = clk_get(whatever);
	if (IS_ERR(clk))
		clk = NULL;

	...
	if (clk)
		clk_prepare(clk);

Do this instead:

	clk = clk_get(whatever);
	...

	if (!IS_ERR(clk))
		clk_prepare(clk);
etc.

(And on this subject, I'm considering whether to make a change to the
clk API where clk_prepare() and clk_enable() return zero when passed
an error pointer - this means drivers with optional clocks don't have
to burden themselves with these kinds of checks.)

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-18 20:33         ` Russell King - ARM Linux
  0 siblings, 0 replies; 432+ messages in thread
From: Russell King - ARM Linux @ 2013-07-18 20:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 18, 2013 at 10:20:52PM +0200, Gerhard Sittig wrote:
> +	/* enable clock for the I2C peripheral (non fatal) */
> +	clk = of_clk_get_by_name(node, "per");
> +	if (!IS_ERR(clk)) {
> +		clk_prepare_enable(clk);
> +		clk_put(clk);
> +	}
> +

This kind of hacked up approach to the clk API is exactly the thing I
really don't like seeing.  I don't know what it is... is the clk API
somehow difficult to use or what's the problem with doing stuff correctly?

1. Get the clock in your probe function.
2. Prepare it at the appropriate time.
3. Enable it appropriately.  (or if you want to combine 2 and 3, use
   clk_prepare_enable().)
4. Ensure that enables/disables and prepares/unprepares are appropriately
   balanced.
5. 'put' the clock in your remove function.

Certainly do not get-enable-put a clock.  You're supposed to hold on to
the clock all the time that you're actually using it.

Final point - if you want to make it non-fatal, don't play games like:

	clk = clk_get(whatever);
	if (IS_ERR(clk))
		clk = NULL;

	...
	if (clk)
		clk_prepare(clk);

Do this instead:

	clk = clk_get(whatever);
	...

	if (!IS_ERR(clk))
		clk_prepare(clk);
etc.

(And on this subject, I'm considering whether to make a change to the
clk API where clk_prepare() and clk_enable() return zero when passed
an error pointer - this means drivers with optional clocks don't have
to burden themselves with these kinds of checks.)

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 01/24] spi: mpc512x: cleanup clock API use
  2013-07-18 17:00         ` Gerhard Sittig
  (?)
@ 2013-07-18 20:49             ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-18 20:49 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Greg Kroah-Hartman,
	Rob Herring, Marc Kleine-Budde, Wolfgang Grandegger,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 289 bytes --]

On Thu, Jul 18, 2013 at 07:00:32PM +0200, Gerhard Sittig wrote:

> +	psc_num = master->bus_num;
> +	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
> +	mps->clk_mclk = clk_get(dev, clk_name);
> +	if (IS_ERR(mps->clk_mclk))
> +		goto free_irq;

Should be using devm_clk_get().

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 01/24] spi: mpc512x: cleanup clock API use
@ 2013-07-18 20:49             ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-18 20:49 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 289 bytes --]

On Thu, Jul 18, 2013 at 07:00:32PM +0200, Gerhard Sittig wrote:

> +	psc_num = master->bus_num;
> +	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
> +	mps->clk_mclk = clk_get(dev, clk_name);
> +	if (IS_ERR(mps->clk_mclk))
> +		goto free_irq;

Should be using devm_clk_get().

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 01/24] spi: mpc512x: cleanup clock API use
@ 2013-07-18 20:49             ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-18 20:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 18, 2013 at 07:00:32PM +0200, Gerhard Sittig wrote:

> +	psc_num = master->bus_num;
> +	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
> +	mps->clk_mclk = clk_get(dev, clk_name);
> +	if (IS_ERR(mps->clk_mclk))
> +		goto free_irq;

Should be using devm_clk_get().
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130718/5428dd8f/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
  2013-07-18 20:20         ` Gerhard Sittig
  (?)
@ 2013-07-19  7:34           ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-19  7:34 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Pantelis Antoniou, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 5265 bytes --]

On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
> extend the mscan(4) driver with alternative support for the COMMON_CLK
> approach which is an option in the MPC512x platform, keep the existing
> clock support implementation in place since the driver is shared with
> other MPC5xxx SoCs which don't have common clock support
> 
> one byproduct of this change is that the CAN driver no longer needs to
> access the SoC's clock control registers, which shall be the domain of
> the platform's clock driver
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index bc422ba..dd26ab6 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>  #endif /* CONFIG_PPC_MPC52xx */
>  
>  #ifdef CONFIG_PPC_MPC512x
> +
> +#if IS_ENABLED(CONFIG_COMMON_CLK)
> +
> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> +				 const char *clock_source, int *mscan_clksrc)
> +{
> +	struct device_node *np;
> +	u32 clockdiv;
> +	enum {
> +		CLK_FROM_AUTO,
> +		CLK_FROM_IPS,
> +		CLK_FROM_SYS,
> +		CLK_FROM_REF,
> +	} clk_from;
> +	struct clk *clk_in, *clk_can;
> +	unsigned long freq_calc;
> +
> +	/* the caller passed in the clock source spec that was read from
> +	 * the device tree, get the optional clock divider as well
> +	 */
> +	np = ofdev->dev.of_node;
> +	clockdiv = 1;
> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> +		clock_source ? clock_source : "<NULL>", clockdiv);
> +
> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> +	 * get set, and the 'ips' clock is the input to the MSCAN
> +	 * component
> +	 *
> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> +	 * bit needs to get cleared, an optional clock-divider may have
> +	 * been specified (the default value is 1), the appropriate
> +	 * MSCAN related MCLK is the input to the MSCAN component
> +	 *
> +	 * in the absence of a clock-source spec, first an optimal clock
> +	 * gets determined based on the 'sys' clock, if that fails the
> +	 * 'ref' clock is used
> +	 */
> +	clk_from = CLK_FROM_AUTO;
> +	if (clock_source) {
> +		/* interpret the device tree's spec for the clock source */
> +		if (!strcmp(clock_source, "ip"))
> +			clk_from = CLK_FROM_IPS;
> +		else if (!strcmp(clock_source, "sys"))
> +			clk_from = CLK_FROM_SYS;
> +		else if (!strcmp(clock_source, "ref"))
> +			clk_from = CLK_FROM_REF;
> +		else
> +			goto err_invalid;
> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, try the 'sys' clock; round to the
> +		 * next MHz and see if we can get a multiple of 16MHz
> +		 */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> +		clk_in = clk_get(&ofdev->dev, "sys");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc +=  499999;
> +		freq_calc /= 1000000;
> +		freq_calc *= 1000000;
> +		if ((freq_calc % 16000000) == 0) {
> +			clk_from = CLK_FROM_SYS;
> +			clockdiv = freq_calc / 16000000;
> +			dev_dbg(&ofdev->dev,
> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> +				freq_calc, clockdiv, freq_calc / clockdiv);
> +		}
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, use the 'ref' clock */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> +		clk_in = clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_from = CLK_FROM_REF;
> +		freq_calc = clk_get_rate(clk_in);
> +		dev_dbg(&ofdev->dev,
> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> +			freq_calc, freq_calc);
> +	}
> +
> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> +	 * setup the MCLK mux source and rate if applicable, apply the
> +	 * optionally specified or derived above divider, and determine
> +	 * the actual resulting clock rate to return to the caller
> +	 */
> +	switch (clk_from) {
> +	case CLK_FROM_IPS:
> +		clk_can = clk_get(&ofdev->dev, "ips");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		clk_prepare_enable(clk_can);

Where is the corresponding clk_disable_unprepare()?a

> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	case CLK_FROM_SYS:
> +	case CLK_FROM_REF:
> +		clk_can = clk_get(&ofdev->dev, "mclk");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		clk_prepare_enable(clk_can);

dito

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-19  7:34           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-19  7:34 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 5265 bytes --]

On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
> extend the mscan(4) driver with alternative support for the COMMON_CLK
> approach which is an option in the MPC512x platform, keep the existing
> clock support implementation in place since the driver is shared with
> other MPC5xxx SoCs which don't have common clock support
> 
> one byproduct of this change is that the CAN driver no longer needs to
> access the SoC's clock control registers, which shall be the domain of
> the platform's clock driver
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index bc422ba..dd26ab6 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>  #endif /* CONFIG_PPC_MPC52xx */
>  
>  #ifdef CONFIG_PPC_MPC512x
> +
> +#if IS_ENABLED(CONFIG_COMMON_CLK)
> +
> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> +				 const char *clock_source, int *mscan_clksrc)
> +{
> +	struct device_node *np;
> +	u32 clockdiv;
> +	enum {
> +		CLK_FROM_AUTO,
> +		CLK_FROM_IPS,
> +		CLK_FROM_SYS,
> +		CLK_FROM_REF,
> +	} clk_from;
> +	struct clk *clk_in, *clk_can;
> +	unsigned long freq_calc;
> +
> +	/* the caller passed in the clock source spec that was read from
> +	 * the device tree, get the optional clock divider as well
> +	 */
> +	np = ofdev->dev.of_node;
> +	clockdiv = 1;
> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> +		clock_source ? clock_source : "<NULL>", clockdiv);
> +
> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> +	 * get set, and the 'ips' clock is the input to the MSCAN
> +	 * component
> +	 *
> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> +	 * bit needs to get cleared, an optional clock-divider may have
> +	 * been specified (the default value is 1), the appropriate
> +	 * MSCAN related MCLK is the input to the MSCAN component
> +	 *
> +	 * in the absence of a clock-source spec, first an optimal clock
> +	 * gets determined based on the 'sys' clock, if that fails the
> +	 * 'ref' clock is used
> +	 */
> +	clk_from = CLK_FROM_AUTO;
> +	if (clock_source) {
> +		/* interpret the device tree's spec for the clock source */
> +		if (!strcmp(clock_source, "ip"))
> +			clk_from = CLK_FROM_IPS;
> +		else if (!strcmp(clock_source, "sys"))
> +			clk_from = CLK_FROM_SYS;
> +		else if (!strcmp(clock_source, "ref"))
> +			clk_from = CLK_FROM_REF;
> +		else
> +			goto err_invalid;
> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, try the 'sys' clock; round to the
> +		 * next MHz and see if we can get a multiple of 16MHz
> +		 */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> +		clk_in = clk_get(&ofdev->dev, "sys");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc +=  499999;
> +		freq_calc /= 1000000;
> +		freq_calc *= 1000000;
> +		if ((freq_calc % 16000000) == 0) {
> +			clk_from = CLK_FROM_SYS;
> +			clockdiv = freq_calc / 16000000;
> +			dev_dbg(&ofdev->dev,
> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> +				freq_calc, clockdiv, freq_calc / clockdiv);
> +		}
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, use the 'ref' clock */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> +		clk_in = clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_from = CLK_FROM_REF;
> +		freq_calc = clk_get_rate(clk_in);
> +		dev_dbg(&ofdev->dev,
> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> +			freq_calc, freq_calc);
> +	}
> +
> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> +	 * setup the MCLK mux source and rate if applicable, apply the
> +	 * optionally specified or derived above divider, and determine
> +	 * the actual resulting clock rate to return to the caller
> +	 */
> +	switch (clk_from) {
> +	case CLK_FROM_IPS:
> +		clk_can = clk_get(&ofdev->dev, "ips");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		clk_prepare_enable(clk_can);

Where is the corresponding clk_disable_unprepare()?a

> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	case CLK_FROM_SYS:
> +	case CLK_FROM_REF:
> +		clk_can = clk_get(&ofdev->dev, "mclk");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		clk_prepare_enable(clk_can);

dito

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-19  7:34           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-19  7:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
> extend the mscan(4) driver with alternative support for the COMMON_CLK
> approach which is an option in the MPC512x platform, keep the existing
> clock support implementation in place since the driver is shared with
> other MPC5xxx SoCs which don't have common clock support
> 
> one byproduct of this change is that the CAN driver no longer needs to
> access the SoC's clock control registers, which shall be the domain of
> the platform's clock driver
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index bc422ba..dd26ab6 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>  #endif /* CONFIG_PPC_MPC52xx */
>  
>  #ifdef CONFIG_PPC_MPC512x
> +
> +#if IS_ENABLED(CONFIG_COMMON_CLK)
> +
> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> +				 const char *clock_source, int *mscan_clksrc)
> +{
> +	struct device_node *np;
> +	u32 clockdiv;
> +	enum {
> +		CLK_FROM_AUTO,
> +		CLK_FROM_IPS,
> +		CLK_FROM_SYS,
> +		CLK_FROM_REF,
> +	} clk_from;
> +	struct clk *clk_in, *clk_can;
> +	unsigned long freq_calc;
> +
> +	/* the caller passed in the clock source spec that was read from
> +	 * the device tree, get the optional clock divider as well
> +	 */
> +	np = ofdev->dev.of_node;
> +	clockdiv = 1;
> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> +		clock_source ? clock_source : "<NULL>", clockdiv);
> +
> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> +	 * get set, and the 'ips' clock is the input to the MSCAN
> +	 * component
> +	 *
> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> +	 * bit needs to get cleared, an optional clock-divider may have
> +	 * been specified (the default value is 1), the appropriate
> +	 * MSCAN related MCLK is the input to the MSCAN component
> +	 *
> +	 * in the absence of a clock-source spec, first an optimal clock
> +	 * gets determined based on the 'sys' clock, if that fails the
> +	 * 'ref' clock is used
> +	 */
> +	clk_from = CLK_FROM_AUTO;
> +	if (clock_source) {
> +		/* interpret the device tree's spec for the clock source */
> +		if (!strcmp(clock_source, "ip"))
> +			clk_from = CLK_FROM_IPS;
> +		else if (!strcmp(clock_source, "sys"))
> +			clk_from = CLK_FROM_SYS;
> +		else if (!strcmp(clock_source, "ref"))
> +			clk_from = CLK_FROM_REF;
> +		else
> +			goto err_invalid;
> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, try the 'sys' clock; round to the
> +		 * next MHz and see if we can get a multiple of 16MHz
> +		 */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> +		clk_in = clk_get(&ofdev->dev, "sys");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc +=  499999;
> +		freq_calc /= 1000000;
> +		freq_calc *= 1000000;
> +		if ((freq_calc % 16000000) == 0) {
> +			clk_from = CLK_FROM_SYS;
> +			clockdiv = freq_calc / 16000000;
> +			dev_dbg(&ofdev->dev,
> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> +				freq_calc, clockdiv, freq_calc / clockdiv);
> +		}
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, use the 'ref' clock */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> +		clk_in = clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_from = CLK_FROM_REF;
> +		freq_calc = clk_get_rate(clk_in);
> +		dev_dbg(&ofdev->dev,
> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> +			freq_calc, freq_calc);
> +	}
> +
> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> +	 * setup the MCLK mux source and rate if applicable, apply the
> +	 * optionally specified or derived above divider, and determine
> +	 * the actual resulting clock rate to return to the caller
> +	 */
> +	switch (clk_from) {
> +	case CLK_FROM_IPS:
> +		clk_can = clk_get(&ofdev->dev, "ips");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		clk_prepare_enable(clk_can);

Where is the corresponding clk_disable_unprepare()?a

> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	case CLK_FROM_SYS:
> +	case CLK_FROM_REF:
> +		clk_can = clk_get(&ofdev->dev, "mclk");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		clk_prepare_enable(clk_can);

dito

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130719/2115e02f/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
  2013-07-18 20:33         ` Russell King - ARM Linux
  (?)
@ 2013-07-19  8:42             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-19  8:42 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
	Mark Brown, Marc Kleine-Budde, Wolfgang Grandegger,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, David Woodhouse,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab

On Thu, Jul 18, 2013 at 21:33 +0100, Russell King - ARM Linux wrote:
> 
> On Thu, Jul 18, 2013 at 10:20:52PM +0200, Gerhard Sittig wrote:
> > +	/* enable clock for the I2C peripheral (non fatal) */
> > +	clk = of_clk_get_by_name(node, "per");
> > +	if (!IS_ERR(clk)) {
> > +		clk_prepare_enable(clk);
> > +		clk_put(clk);
> > +	}
> > +
> 
> This kind of hacked up approach to the clk API is exactly the thing I
> really don't like seeing.  I don't know what it is... is the clk API
> somehow difficult to use or what's the problem with doing stuff correctly?
> 
> 1. Get the clock in your probe function.
> 2. Prepare it at the appropriate time.
> 3. Enable it appropriately.  (or if you want to combine 2 and 3, use
>    clk_prepare_enable().)
> 4. Ensure that enables/disables and prepares/unprepares are appropriately
>    balanced.
> 5. 'put' the clock in your remove function.
> 
> Certainly do not get-enable-put a clock.  You're supposed to hold on to
> the clock all the time that you're actually using it.

Russel, thank you for the feedback!  I agree that your outline of
steps to take is simple and should not be a problem to do.

I noticed that I kept looking at the wrong spot in the driver,
hooked up to some setup routine which lacks a counter part.  You
made me re-visit the drivers and find better locations to hook up
to (probe and remove).  Part of my sloppiness with immediate put
after enable was caused by put being a NOP at the moment, and the
assumption that clocks without references but in the enabled
state won't go away.  But I saw your recent message as well about
how clocks shall get reference counted and keep their provider's
module loaded.

I've queued an update to the I2C, ethernet, and PCI drivers,
which addresses your concerns.  I2C and ethernet clock handling
will become correctly balanced, while PCI won't since the
existing driver already lacks a remove() routine.  These changes
will be part of v3 of the series.

Mark, Greg, v2 of the series already addresses the above concerns
for the serial communication with the PSC hardware (UART and
SPI).  See how 01/24 and 02/24 became much more complex than in
v1, yet should result in appropriate clock handling in these
drivers.

In the very minute I wanted to send out v3, I received feedback
on the CAN driver manipulation from Marc.  Apparently it suffers
from the same problem (my blindness to locate the best spot for
resource release), but CAN shall be the last driver in the series
which is not acceptable yet.


> Final point - if you want to make it non-fatal, don't play games like:
> 
> 	clk = clk_get(whatever);
> 	if (IS_ERR(clk))
> 		clk = NULL;
> 
> 	...
> 	if (clk)
> 		clk_prepare(clk);
> 
> Do this instead:
> 
> 	clk = clk_get(whatever);
> 	...
> 
> 	if (!IS_ERR(clk))
> 		clk_prepare(clk);
> etc.

You saw this in the ethernet driver, right?  This "interesting"
style of "normalization to NULL" in the setup path was meant to
simplify the cleanup path, but that point has become obsolete by
now.  Your example doesn't reflect that 'clk' was a more complex
to access member in the driver's private data.

It seems that doing the setup in steps with a local variable, to
only store the reference when all steps were successful, cleans
up the release code paths.

Immediately putting the clock and not having stored the reference
when enable failed is one more instruction before jumping to the
bailout label, but eliminates the pain of tracking get and enable
separately, and needing two labels for disable and put (you
cannot disable a clock that wasn't enabled).

As mentioned, both the I2C driver you responded to as well as the
ethernet driver you reference here got adjusted.  v3 will get
sent when I could address the remaining CAN driver issue.


> (And on this subject, I'm considering whether to make a change to the
> clk API where clk_prepare() and clk_enable() return zero when passed
> an error pointer - this means drivers with optional clocks don't have
> to burden themselves with these kinds of checks.)


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-19  8:42             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-19  8:42 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Thu, Jul 18, 2013 at 21:33 +0100, Russell King - ARM Linux wrote:
> 
> On Thu, Jul 18, 2013 at 10:20:52PM +0200, Gerhard Sittig wrote:
> > +	/* enable clock for the I2C peripheral (non fatal) */
> > +	clk = of_clk_get_by_name(node, "per");
> > +	if (!IS_ERR(clk)) {
> > +		clk_prepare_enable(clk);
> > +		clk_put(clk);
> > +	}
> > +
> 
> This kind of hacked up approach to the clk API is exactly the thing I
> really don't like seeing.  I don't know what it is... is the clk API
> somehow difficult to use or what's the problem with doing stuff correctly?
> 
> 1. Get the clock in your probe function.
> 2. Prepare it at the appropriate time.
> 3. Enable it appropriately.  (or if you want to combine 2 and 3, use
>    clk_prepare_enable().)
> 4. Ensure that enables/disables and prepares/unprepares are appropriately
>    balanced.
> 5. 'put' the clock in your remove function.
> 
> Certainly do not get-enable-put a clock.  You're supposed to hold on to
> the clock all the time that you're actually using it.

Russel, thank you for the feedback!  I agree that your outline of
steps to take is simple and should not be a problem to do.

I noticed that I kept looking at the wrong spot in the driver,
hooked up to some setup routine which lacks a counter part.  You
made me re-visit the drivers and find better locations to hook up
to (probe and remove).  Part of my sloppiness with immediate put
after enable was caused by put being a NOP at the moment, and the
assumption that clocks without references but in the enabled
state won't go away.  But I saw your recent message as well about
how clocks shall get reference counted and keep their provider's
module loaded.

I've queued an update to the I2C, ethernet, and PCI drivers,
which addresses your concerns.  I2C and ethernet clock handling
will become correctly balanced, while PCI won't since the
existing driver already lacks a remove() routine.  These changes
will be part of v3 of the series.

Mark, Greg, v2 of the series already addresses the above concerns
for the serial communication with the PSC hardware (UART and
SPI).  See how 01/24 and 02/24 became much more complex than in
v1, yet should result in appropriate clock handling in these
drivers.

In the very minute I wanted to send out v3, I received feedback
on the CAN driver manipulation from Marc.  Apparently it suffers
from the same problem (my blindness to locate the best spot for
resource release), but CAN shall be the last driver in the series
which is not acceptable yet.


> Final point - if you want to make it non-fatal, don't play games like:
> 
> 	clk = clk_get(whatever);
> 	if (IS_ERR(clk))
> 		clk = NULL;
> 
> 	...
> 	if (clk)
> 		clk_prepare(clk);
> 
> Do this instead:
> 
> 	clk = clk_get(whatever);
> 	...
> 
> 	if (!IS_ERR(clk))
> 		clk_prepare(clk);
> etc.

You saw this in the ethernet driver, right?  This "interesting"
style of "normalization to NULL" in the setup path was meant to
simplify the cleanup path, but that point has become obsolete by
now.  Your example doesn't reflect that 'clk' was a more complex
to access member in the driver's private data.

It seems that doing the setup in steps with a local variable, to
only store the reference when all steps were successful, cleans
up the release code paths.

Immediately putting the clock and not having stored the reference
when enable failed is one more instruction before jumping to the
bailout label, but eliminates the pain of tracking get and enable
separately, and needing two labels for disable and put (you
cannot disable a clock that wasn't enabled).

As mentioned, both the I2C driver you responded to as well as the
ethernet driver you reference here got adjusted.  v3 will get
sent when I could address the remaining CAN driver issue.


> (And on this subject, I'm considering whether to make a change to the
> clk API where clk_prepare() and clk_enable() return zero when passed
> an error pointer - this means drivers with optional clocks don't have
> to burden themselves with these kinds of checks.)


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x
@ 2013-07-19  8:42             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-19  8:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 18, 2013 at 21:33 +0100, Russell King - ARM Linux wrote:
> 
> On Thu, Jul 18, 2013 at 10:20:52PM +0200, Gerhard Sittig wrote:
> > +	/* enable clock for the I2C peripheral (non fatal) */
> > +	clk = of_clk_get_by_name(node, "per");
> > +	if (!IS_ERR(clk)) {
> > +		clk_prepare_enable(clk);
> > +		clk_put(clk);
> > +	}
> > +
> 
> This kind of hacked up approach to the clk API is exactly the thing I
> really don't like seeing.  I don't know what it is... is the clk API
> somehow difficult to use or what's the problem with doing stuff correctly?
> 
> 1. Get the clock in your probe function.
> 2. Prepare it at the appropriate time.
> 3. Enable it appropriately.  (or if you want to combine 2 and 3, use
>    clk_prepare_enable().)
> 4. Ensure that enables/disables and prepares/unprepares are appropriately
>    balanced.
> 5. 'put' the clock in your remove function.
> 
> Certainly do not get-enable-put a clock.  You're supposed to hold on to
> the clock all the time that you're actually using it.

Russel, thank you for the feedback!  I agree that your outline of
steps to take is simple and should not be a problem to do.

I noticed that I kept looking at the wrong spot in the driver,
hooked up to some setup routine which lacks a counter part.  You
made me re-visit the drivers and find better locations to hook up
to (probe and remove).  Part of my sloppiness with immediate put
after enable was caused by put being a NOP at the moment, and the
assumption that clocks without references but in the enabled
state won't go away.  But I saw your recent message as well about
how clocks shall get reference counted and keep their provider's
module loaded.

I've queued an update to the I2C, ethernet, and PCI drivers,
which addresses your concerns.  I2C and ethernet clock handling
will become correctly balanced, while PCI won't since the
existing driver already lacks a remove() routine.  These changes
will be part of v3 of the series.

Mark, Greg, v2 of the series already addresses the above concerns
for the serial communication with the PSC hardware (UART and
SPI).  See how 01/24 and 02/24 became much more complex than in
v1, yet should result in appropriate clock handling in these
drivers.

In the very minute I wanted to send out v3, I received feedback
on the CAN driver manipulation from Marc.  Apparently it suffers
from the same problem (my blindness to locate the best spot for
resource release), but CAN shall be the last driver in the series
which is not acceptable yet.


> Final point - if you want to make it non-fatal, don't play games like:
> 
> 	clk = clk_get(whatever);
> 	if (IS_ERR(clk))
> 		clk = NULL;
> 
> 	...
> 	if (clk)
> 		clk_prepare(clk);
> 
> Do this instead:
> 
> 	clk = clk_get(whatever);
> 	...
> 
> 	if (!IS_ERR(clk))
> 		clk_prepare(clk);
> etc.

You saw this in the ethernet driver, right?  This "interesting"
style of "normalization to NULL" in the setup path was meant to
simplify the cleanup path, but that point has become obsolete by
now.  Your example doesn't reflect that 'clk' was a more complex
to access member in the driver's private data.

It seems that doing the setup in steps with a local variable, to
only store the reference when all steps were successful, cleans
up the release code paths.

Immediately putting the clock and not having stored the reference
when enable failed is one more instruction before jumping to the
bailout label, but eliminates the pain of tracking get and enable
separately, and needing two labels for disable and put (you
cannot disable a clock that wasn't enabled).

As mentioned, both the I2C driver you responded to as well as the
ethernet driver you reference here got adjusted.  v3 will get
sent when I could address the remaining CAN driver issue.


> (And on this subject, I'm considering whether to make a change to the
> clk API where clk_prepare() and clk_enable() return zero when passed
> an error pointer - this means drivers with optional clocks don't have
> to burden themselves with these kinds of checks.)


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
  2013-07-19  7:34           ` Marc Kleine-Budde
  (?)
@ 2013-07-19  9:41               ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-19  9:41 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Greg Kroah-Hartman,
	Rob Herring, Mark Brown, Wolfgang Grandegger,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Mauro Carvalho Chehab

On Fri, Jul 19, 2013 at 09:34 +0200, Marc Kleine-Budde wrote:
> 
> On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
> > extend the mscan(4) driver with alternative support for the COMMON_CLK
> > approach which is an option in the MPC512x platform, keep the existing
> > clock support implementation in place since the driver is shared with
> > other MPC5xxx SoCs which don't have common clock support
> > 
> > one byproduct of this change is that the CAN driver no longer needs to
> > access the SoC's clock control registers, which shall be the domain of
> > the platform's clock driver
> > 
> > Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
> > ---
> >  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 139 insertions(+)
> > 
> > diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> > index bc422ba..dd26ab6 100644
> > --- a/drivers/net/can/mscan/mpc5xxx_can.c
> > +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> > @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
> >  #endif /* CONFIG_PPC_MPC52xx */
> >  
> >  #ifdef CONFIG_PPC_MPC512x
> > +
> > +#if IS_ENABLED(CONFIG_COMMON_CLK)
> > +
> > +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> > +				 const char *clock_source, int *mscan_clksrc)
> > +{
> > +	struct device_node *np;
> > +	u32 clockdiv;
> > +	enum {
> > +		CLK_FROM_AUTO,
> > +		CLK_FROM_IPS,
> > +		CLK_FROM_SYS,
> > +		CLK_FROM_REF,
> > +	} clk_from;
> > +	struct clk *clk_in, *clk_can;
> > +	unsigned long freq_calc;
> > +
> > +	/* the caller passed in the clock source spec that was read from
> > +	 * the device tree, get the optional clock divider as well
> > +	 */
> > +	np = ofdev->dev.of_node;
> > +	clockdiv = 1;
> > +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> > +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> > +		clock_source ? clock_source : "<NULL>", clockdiv);
> > +
> > +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> > +	 * get set, and the 'ips' clock is the input to the MSCAN
> > +	 * component
> > +	 *
> > +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> > +	 * bit needs to get cleared, an optional clock-divider may have
> > +	 * been specified (the default value is 1), the appropriate
> > +	 * MSCAN related MCLK is the input to the MSCAN component
> > +	 *
> > +	 * in the absence of a clock-source spec, first an optimal clock
> > +	 * gets determined based on the 'sys' clock, if that fails the
> > +	 * 'ref' clock is used
> > +	 */
> > +	clk_from = CLK_FROM_AUTO;
> > +	if (clock_source) {
> > +		/* interpret the device tree's spec for the clock source */
> > +		if (!strcmp(clock_source, "ip"))
> > +			clk_from = CLK_FROM_IPS;
> > +		else if (!strcmp(clock_source, "sys"))
> > +			clk_from = CLK_FROM_SYS;
> > +		else if (!strcmp(clock_source, "ref"))
> > +			clk_from = CLK_FROM_REF;
> > +		else
> > +			goto err_invalid;
> > +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, try the 'sys' clock; round to the
> > +		 * next MHz and see if we can get a multiple of 16MHz
> > +		 */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> > +		clk_in = clk_get(&ofdev->dev, "sys");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc +=  499999;
> > +		freq_calc /= 1000000;
> > +		freq_calc *= 1000000;
> > +		if ((freq_calc % 16000000) == 0) {
> > +			clk_from = CLK_FROM_SYS;
> > +			clockdiv = freq_calc / 16000000;
> > +			dev_dbg(&ofdev->dev,
> > +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> > +				freq_calc, clockdiv, freq_calc / clockdiv);
> > +		}
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, use the 'ref' clock */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> > +		clk_in = clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_from = CLK_FROM_REF;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		dev_dbg(&ofdev->dev,
> > +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> > +			freq_calc, freq_calc);
> > +	}
> > +
> > +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> > +	 * setup the MCLK mux source and rate if applicable, apply the
> > +	 * optionally specified or derived above divider, and determine
> > +	 * the actual resulting clock rate to return to the caller
> > +	 */
> > +	switch (clk_from) {
> > +	case CLK_FROM_IPS:
> > +		clk_can = clk_get(&ofdev->dev, "ips");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		clk_prepare_enable(clk_can);
> 
> Where is the corresponding clk_disable_unprepare()?a

It's missing, as I could not find the counterpart of the
.get_clock() callback where the get and prepare/enable was added
to.  And it appears that neither are enable errors checked for.
This patch clearly needs an update as well, but already should be
the last part of the series in a currently inacceptable state.

This .get_clock() routine is supposed to determine the clock
source, setup the desired rate and return the actual rate.  The
callback's API is rather limited in that it does communicate
clock rate values, but cannot access a location to store handles
to.

Are the introduction of a .put_clock() callback and passing the
'priv' handle to both get and put routines acceptable?  As this
would hook up clock handling to probe() and remove() just as
memory mapping gets approached.

Below is a patch on top of the CAN related patch in v2 of the
series.  If this approach is acceptable (maybe modulo how the
"unused" warnings get silenced), I'll fold it into the
introduction of common clock support in the mscan(4) driver.

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index cf5e4cfc..16ca712 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -39,7 +39,9 @@
 struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
-			 int *mscan_clksrc);
+			 int *mscan_clksrc, struct mscan_priv *priv);
+	void (*put_clock)(struct platform_device *ofdev,
+			  struct mscan_priv *priv);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -49,7 +51,8 @@ static struct of_device_id mpc52xx_cdm_ids[] = {
 };
 
 static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	unsigned int pvr;
 	struct mpc52xx_cdm  __iomem *cdm;
@@ -101,15 +104,24 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 }
 #else /* !CONFIG_PPC_MPC52xx */
 static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	return 0;
 }
 #endif /* CONFIG_PPC_MPC52xx */
+static void mpc52xx_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	/* EMPTY */
+	(void)ofdev;
+	(void)priv;
+}
 
 #ifdef CONFIG_PPC_MPC512x
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_source, int *mscan_clksrc)
+				 const char *clock_source, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	struct device_node *np;
 	u32 clockdiv;
@@ -200,7 +212,9 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		clk_can = clk_get(&ofdev->dev, "ips");
 		if (IS_ERR(clk_can))
 			goto err_notavail;
-		clk_prepare_enable(clk_can);
+		if (clk_prepare_enable(clk_can))
+			goto err_notavail;
+		priv->clk_can = clk_can;
 		freq_calc = clk_get_rate(clk_can);
 		*mscan_clksrc = MSCAN_CLKSRC_IPS;
 		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
@@ -211,7 +225,9 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		clk_can = clk_get(&ofdev->dev, "mclk");
 		if (IS_ERR(clk_can))
 			goto err_notavail;
-		clk_prepare_enable(clk_can);
+		if (clk_prepare_enable(clk_can))
+			goto err_notavail;
+		priv->clk_can = clk_can;
 		if (clk_from == CLK_FROM_SYS)
 			clk_in = clk_get(&ofdev->dev, "sys");
 		if (clk_from == CLK_FROM_REF)
@@ -241,12 +257,31 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	(void)ofdev;
+	if (priv->clk_can) {
+		clk_disable_unprepare(priv->clk_can);
+		clk_put(priv->clk_can);
+	}
+}
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	return 0;
 }
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	(void)ofdev;
+	(void)priv;
+	/* EMPTY */
+}
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -293,7 +328,7 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	BUG_ON(!data);
 	priv->type = data->type;
 	priv->can.clock.freq = data->get_clock(ofdev, clock_name,
-					       &mscan_clksrc);
+					       &mscan_clksrc, priv);
 	if (!priv->can.clock.freq) {
 		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
 		goto exit_free_mscan;
@@ -327,10 +362,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data)
+		data->put_clock(ofdev, priv);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
@@ -383,11 +425,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	.put_clock = mpc52xx_can_put_clock,
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..f32e190 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,7 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_can;	/* clock for registers or bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;

> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> > +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	case CLK_FROM_SYS:
> > +	case CLK_FROM_REF:
> > +		clk_can = clk_get(&ofdev->dev, "mclk");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		clk_prepare_enable(clk_can);
> 
> dito

yes, both problems of not checking for errors and dropping the
reference, will address this as well


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office-ynQEQJNshbs@public.gmane.org

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-19  9:41               ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-19  9:41 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

On Fri, Jul 19, 2013 at 09:34 +0200, Marc Kleine-Budde wrote:
> 
> On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
> > extend the mscan(4) driver with alternative support for the COMMON_CLK
> > approach which is an option in the MPC512x platform, keep the existing
> > clock support implementation in place since the driver is shared with
> > other MPC5xxx SoCs which don't have common clock support
> > 
> > one byproduct of this change is that the CAN driver no longer needs to
> > access the SoC's clock control registers, which shall be the domain of
> > the platform's clock driver
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 139 insertions(+)
> > 
> > diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> > index bc422ba..dd26ab6 100644
> > --- a/drivers/net/can/mscan/mpc5xxx_can.c
> > +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> > @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
> >  #endif /* CONFIG_PPC_MPC52xx */
> >  
> >  #ifdef CONFIG_PPC_MPC512x
> > +
> > +#if IS_ENABLED(CONFIG_COMMON_CLK)
> > +
> > +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> > +				 const char *clock_source, int *mscan_clksrc)
> > +{
> > +	struct device_node *np;
> > +	u32 clockdiv;
> > +	enum {
> > +		CLK_FROM_AUTO,
> > +		CLK_FROM_IPS,
> > +		CLK_FROM_SYS,
> > +		CLK_FROM_REF,
> > +	} clk_from;
> > +	struct clk *clk_in, *clk_can;
> > +	unsigned long freq_calc;
> > +
> > +	/* the caller passed in the clock source spec that was read from
> > +	 * the device tree, get the optional clock divider as well
> > +	 */
> > +	np = ofdev->dev.of_node;
> > +	clockdiv = 1;
> > +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> > +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> > +		clock_source ? clock_source : "<NULL>", clockdiv);
> > +
> > +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> > +	 * get set, and the 'ips' clock is the input to the MSCAN
> > +	 * component
> > +	 *
> > +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> > +	 * bit needs to get cleared, an optional clock-divider may have
> > +	 * been specified (the default value is 1), the appropriate
> > +	 * MSCAN related MCLK is the input to the MSCAN component
> > +	 *
> > +	 * in the absence of a clock-source spec, first an optimal clock
> > +	 * gets determined based on the 'sys' clock, if that fails the
> > +	 * 'ref' clock is used
> > +	 */
> > +	clk_from = CLK_FROM_AUTO;
> > +	if (clock_source) {
> > +		/* interpret the device tree's spec for the clock source */
> > +		if (!strcmp(clock_source, "ip"))
> > +			clk_from = CLK_FROM_IPS;
> > +		else if (!strcmp(clock_source, "sys"))
> > +			clk_from = CLK_FROM_SYS;
> > +		else if (!strcmp(clock_source, "ref"))
> > +			clk_from = CLK_FROM_REF;
> > +		else
> > +			goto err_invalid;
> > +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, try the 'sys' clock; round to the
> > +		 * next MHz and see if we can get a multiple of 16MHz
> > +		 */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> > +		clk_in = clk_get(&ofdev->dev, "sys");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc +=  499999;
> > +		freq_calc /= 1000000;
> > +		freq_calc *= 1000000;
> > +		if ((freq_calc % 16000000) == 0) {
> > +			clk_from = CLK_FROM_SYS;
> > +			clockdiv = freq_calc / 16000000;
> > +			dev_dbg(&ofdev->dev,
> > +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> > +				freq_calc, clockdiv, freq_calc / clockdiv);
> > +		}
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, use the 'ref' clock */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> > +		clk_in = clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_from = CLK_FROM_REF;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		dev_dbg(&ofdev->dev,
> > +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> > +			freq_calc, freq_calc);
> > +	}
> > +
> > +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> > +	 * setup the MCLK mux source and rate if applicable, apply the
> > +	 * optionally specified or derived above divider, and determine
> > +	 * the actual resulting clock rate to return to the caller
> > +	 */
> > +	switch (clk_from) {
> > +	case CLK_FROM_IPS:
> > +		clk_can = clk_get(&ofdev->dev, "ips");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		clk_prepare_enable(clk_can);
> 
> Where is the corresponding clk_disable_unprepare()?a

It's missing, as I could not find the counterpart of the
.get_clock() callback where the get and prepare/enable was added
to.  And it appears that neither are enable errors checked for.
This patch clearly needs an update as well, but already should be
the last part of the series in a currently inacceptable state.

This .get_clock() routine is supposed to determine the clock
source, setup the desired rate and return the actual rate.  The
callback's API is rather limited in that it does communicate
clock rate values, but cannot access a location to store handles
to.

Are the introduction of a .put_clock() callback and passing the
'priv' handle to both get and put routines acceptable?  As this
would hook up clock handling to probe() and remove() just as
memory mapping gets approached.

Below is a patch on top of the CAN related patch in v2 of the
series.  If this approach is acceptable (maybe modulo how the
"unused" warnings get silenced), I'll fold it into the
introduction of common clock support in the mscan(4) driver.

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index cf5e4cfc..16ca712 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -39,7 +39,9 @@
 struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
-			 int *mscan_clksrc);
+			 int *mscan_clksrc, struct mscan_priv *priv);
+	void (*put_clock)(struct platform_device *ofdev,
+			  struct mscan_priv *priv);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -49,7 +51,8 @@ static struct of_device_id mpc52xx_cdm_ids[] = {
 };
 
 static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	unsigned int pvr;
 	struct mpc52xx_cdm  __iomem *cdm;
@@ -101,15 +104,24 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 }
 #else /* !CONFIG_PPC_MPC52xx */
 static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	return 0;
 }
 #endif /* CONFIG_PPC_MPC52xx */
+static void mpc52xx_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	/* EMPTY */
+	(void)ofdev;
+	(void)priv;
+}
 
 #ifdef CONFIG_PPC_MPC512x
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_source, int *mscan_clksrc)
+				 const char *clock_source, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	struct device_node *np;
 	u32 clockdiv;
@@ -200,7 +212,9 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		clk_can = clk_get(&ofdev->dev, "ips");
 		if (IS_ERR(clk_can))
 			goto err_notavail;
-		clk_prepare_enable(clk_can);
+		if (clk_prepare_enable(clk_can))
+			goto err_notavail;
+		priv->clk_can = clk_can;
 		freq_calc = clk_get_rate(clk_can);
 		*mscan_clksrc = MSCAN_CLKSRC_IPS;
 		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
@@ -211,7 +225,9 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		clk_can = clk_get(&ofdev->dev, "mclk");
 		if (IS_ERR(clk_can))
 			goto err_notavail;
-		clk_prepare_enable(clk_can);
+		if (clk_prepare_enable(clk_can))
+			goto err_notavail;
+		priv->clk_can = clk_can;
 		if (clk_from == CLK_FROM_SYS)
 			clk_in = clk_get(&ofdev->dev, "sys");
 		if (clk_from == CLK_FROM_REF)
@@ -241,12 +257,31 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	(void)ofdev;
+	if (priv->clk_can) {
+		clk_disable_unprepare(priv->clk_can);
+		clk_put(priv->clk_can);
+	}
+}
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	return 0;
 }
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	(void)ofdev;
+	(void)priv;
+	/* EMPTY */
+}
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -293,7 +328,7 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	BUG_ON(!data);
 	priv->type = data->type;
 	priv->can.clock.freq = data->get_clock(ofdev, clock_name,
-					       &mscan_clksrc);
+					       &mscan_clksrc, priv);
 	if (!priv->can.clock.freq) {
 		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
 		goto exit_free_mscan;
@@ -327,10 +362,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data)
+		data->put_clock(ofdev, priv);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
@@ -383,11 +425,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	.put_clock = mpc52xx_can_put_clock,
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..f32e190 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,7 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_can;	/* clock for registers or bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;

> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> > +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	case CLK_FROM_SYS:
> > +	case CLK_FROM_REF:
> > +		clk_can = clk_get(&ofdev->dev, "mclk");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		clk_prepare_enable(clk_can);
> 
> dito

yes, both problems of not checking for errors and dropping the
reference, will address this as well


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-19  9:41               ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-19  9:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 19, 2013 at 09:34 +0200, Marc Kleine-Budde wrote:
> 
> On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
> > extend the mscan(4) driver with alternative support for the COMMON_CLK
> > approach which is an option in the MPC512x platform, keep the existing
> > clock support implementation in place since the driver is shared with
> > other MPC5xxx SoCs which don't have common clock support
> > 
> > one byproduct of this change is that the CAN driver no longer needs to
> > access the SoC's clock control registers, which shall be the domain of
> > the platform's clock driver
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 139 insertions(+)
> > 
> > diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> > index bc422ba..dd26ab6 100644
> > --- a/drivers/net/can/mscan/mpc5xxx_can.c
> > +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> > @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
> >  #endif /* CONFIG_PPC_MPC52xx */
> >  
> >  #ifdef CONFIG_PPC_MPC512x
> > +
> > +#if IS_ENABLED(CONFIG_COMMON_CLK)
> > +
> > +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> > +				 const char *clock_source, int *mscan_clksrc)
> > +{
> > +	struct device_node *np;
> > +	u32 clockdiv;
> > +	enum {
> > +		CLK_FROM_AUTO,
> > +		CLK_FROM_IPS,
> > +		CLK_FROM_SYS,
> > +		CLK_FROM_REF,
> > +	} clk_from;
> > +	struct clk *clk_in, *clk_can;
> > +	unsigned long freq_calc;
> > +
> > +	/* the caller passed in the clock source spec that was read from
> > +	 * the device tree, get the optional clock divider as well
> > +	 */
> > +	np = ofdev->dev.of_node;
> > +	clockdiv = 1;
> > +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> > +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> > +		clock_source ? clock_source : "<NULL>", clockdiv);
> > +
> > +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> > +	 * get set, and the 'ips' clock is the input to the MSCAN
> > +	 * component
> > +	 *
> > +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> > +	 * bit needs to get cleared, an optional clock-divider may have
> > +	 * been specified (the default value is 1), the appropriate
> > +	 * MSCAN related MCLK is the input to the MSCAN component
> > +	 *
> > +	 * in the absence of a clock-source spec, first an optimal clock
> > +	 * gets determined based on the 'sys' clock, if that fails the
> > +	 * 'ref' clock is used
> > +	 */
> > +	clk_from = CLK_FROM_AUTO;
> > +	if (clock_source) {
> > +		/* interpret the device tree's spec for the clock source */
> > +		if (!strcmp(clock_source, "ip"))
> > +			clk_from = CLK_FROM_IPS;
> > +		else if (!strcmp(clock_source, "sys"))
> > +			clk_from = CLK_FROM_SYS;
> > +		else if (!strcmp(clock_source, "ref"))
> > +			clk_from = CLK_FROM_REF;
> > +		else
> > +			goto err_invalid;
> > +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, try the 'sys' clock; round to the
> > +		 * next MHz and see if we can get a multiple of 16MHz
> > +		 */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> > +		clk_in = clk_get(&ofdev->dev, "sys");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc +=  499999;
> > +		freq_calc /= 1000000;
> > +		freq_calc *= 1000000;
> > +		if ((freq_calc % 16000000) == 0) {
> > +			clk_from = CLK_FROM_SYS;
> > +			clockdiv = freq_calc / 16000000;
> > +			dev_dbg(&ofdev->dev,
> > +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> > +				freq_calc, clockdiv, freq_calc / clockdiv);
> > +		}
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, use the 'ref' clock */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> > +		clk_in = clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_from = CLK_FROM_REF;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		dev_dbg(&ofdev->dev,
> > +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> > +			freq_calc, freq_calc);
> > +	}
> > +
> > +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> > +	 * setup the MCLK mux source and rate if applicable, apply the
> > +	 * optionally specified or derived above divider, and determine
> > +	 * the actual resulting clock rate to return to the caller
> > +	 */
> > +	switch (clk_from) {
> > +	case CLK_FROM_IPS:
> > +		clk_can = clk_get(&ofdev->dev, "ips");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		clk_prepare_enable(clk_can);
> 
> Where is the corresponding clk_disable_unprepare()?a

It's missing, as I could not find the counterpart of the
.get_clock() callback where the get and prepare/enable was added
to.  And it appears that neither are enable errors checked for.
This patch clearly needs an update as well, but already should be
the last part of the series in a currently inacceptable state.

This .get_clock() routine is supposed to determine the clock
source, setup the desired rate and return the actual rate.  The
callback's API is rather limited in that it does communicate
clock rate values, but cannot access a location to store handles
to.

Are the introduction of a .put_clock() callback and passing the
'priv' handle to both get and put routines acceptable?  As this
would hook up clock handling to probe() and remove() just as
memory mapping gets approached.

Below is a patch on top of the CAN related patch in v2 of the
series.  If this approach is acceptable (maybe modulo how the
"unused" warnings get silenced), I'll fold it into the
introduction of common clock support in the mscan(4) driver.

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index cf5e4cfc..16ca712 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -39,7 +39,9 @@
 struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
-			 int *mscan_clksrc);
+			 int *mscan_clksrc, struct mscan_priv *priv);
+	void (*put_clock)(struct platform_device *ofdev,
+			  struct mscan_priv *priv);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -49,7 +51,8 @@ static struct of_device_id mpc52xx_cdm_ids[] = {
 };
 
 static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	unsigned int pvr;
 	struct mpc52xx_cdm  __iomem *cdm;
@@ -101,15 +104,24 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 }
 #else /* !CONFIG_PPC_MPC52xx */
 static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	return 0;
 }
 #endif /* CONFIG_PPC_MPC52xx */
+static void mpc52xx_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	/* EMPTY */
+	(void)ofdev;
+	(void)priv;
+}
 
 #ifdef CONFIG_PPC_MPC512x
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_source, int *mscan_clksrc)
+				 const char *clock_source, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	struct device_node *np;
 	u32 clockdiv;
@@ -200,7 +212,9 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		clk_can = clk_get(&ofdev->dev, "ips");
 		if (IS_ERR(clk_can))
 			goto err_notavail;
-		clk_prepare_enable(clk_can);
+		if (clk_prepare_enable(clk_can))
+			goto err_notavail;
+		priv->clk_can = clk_can;
 		freq_calc = clk_get_rate(clk_can);
 		*mscan_clksrc = MSCAN_CLKSRC_IPS;
 		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
@@ -211,7 +225,9 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		clk_can = clk_get(&ofdev->dev, "mclk");
 		if (IS_ERR(clk_can))
 			goto err_notavail;
-		clk_prepare_enable(clk_can);
+		if (clk_prepare_enable(clk_can))
+			goto err_notavail;
+		priv->clk_can = clk_can;
 		if (clk_from == CLK_FROM_SYS)
 			clk_in = clk_get(&ofdev->dev, "sys");
 		if (clk_from == CLK_FROM_REF)
@@ -241,12 +257,31 @@ err_notavail:
 	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
 	return 0;
 }
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	(void)ofdev;
+	if (priv->clk_can) {
+		clk_disable_unprepare(priv->clk_can);
+		clk_put(priv->clk_can);
+	}
+}
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
+				 const char *clock_name, int *mscan_clksrc,
+				 struct mscan_priv *priv)
 {
 	return 0;
 }
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev,
+				  struct mscan_priv *priv)
+{
+	(void)ofdev;
+	(void)priv;
+	/* EMPTY */
+}
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -293,7 +328,7 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	BUG_ON(!data);
 	priv->type = data->type;
 	priv->can.clock.freq = data->get_clock(ofdev, clock_name,
-					       &mscan_clksrc);
+					       &mscan_clksrc, priv);
 	if (!priv->can.clock.freq) {
 		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
 		goto exit_free_mscan;
@@ -327,10 +362,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data)
+		data->put_clock(ofdev, priv);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
@@ -383,11 +425,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	.put_clock = mpc52xx_can_put_clock,
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..f32e190 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,7 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_can;	/* clock for registers or bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;

> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> > +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	case CLK_FROM_SYS:
> > +	case CLK_FROM_REF:
> > +		clk_can = clk_get(&ofdev->dev, "mclk");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		clk_prepare_enable(clk_can);
> 
> dito

yes, both problems of not checking for errors and dropping the
reference, will address this as well


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
  2013-07-19  9:41               ` Gerhard Sittig
  (?)
@ 2013-07-19 10:46                   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-19 10:46 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Anatolij Gustschin,
	Mike Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Wolfram Sang,
	Mauro Carvalho Chehab, David Woodhouse, Wolfgang Grandegger,
	Pantelis Antoniou, Mark Brown, Greg Kroah-Hartman, Rob Herring,
	Detlev Zundel


[-- Attachment #1.1: Type: text/plain, Size: 7064 bytes --]

On 07/19/2013 11:41 AM, Gerhard Sittig wrote:
> On Fri, Jul 19, 2013 at 09:34 +0200, Marc Kleine-Budde wrote:
>>
>> On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
>>> extend the mscan(4) driver with alternative support for the COMMON_CLK
>>> approach which is an option in the MPC512x platform, keep the existing
>>> clock support implementation in place since the driver is shared with
>>> other MPC5xxx SoCs which don't have common clock support
>>>
>>> one byproduct of this change is that the CAN driver no longer needs to
>>> access the SoC's clock control registers, which shall be the domain of
>>> the platform's clock driver
>>>
>>> Signed-off-by: Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>
>>> ---
>>>  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
>>>  1 file changed, 139 insertions(+)
>>>
>>> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
>>> index bc422ba..dd26ab6 100644
>>> --- a/drivers/net/can/mscan/mpc5xxx_can.c
>>> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
>>> @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>>>  #endif /* CONFIG_PPC_MPC52xx */
>>>  
>>>  #ifdef CONFIG_PPC_MPC512x
>>> +
>>> +#if IS_ENABLED(CONFIG_COMMON_CLK)
>>> +
>>> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>>> +				 const char *clock_source, int *mscan_clksrc)
>>> +{
>>> +	struct device_node *np;
>>> +	u32 clockdiv;
>>> +	enum {
>>> +		CLK_FROM_AUTO,
>>> +		CLK_FROM_IPS,
>>> +		CLK_FROM_SYS,
>>> +		CLK_FROM_REF,
>>> +	} clk_from;
>>> +	struct clk *clk_in, *clk_can;
>>> +	unsigned long freq_calc;
>>> +
>>> +	/* the caller passed in the clock source spec that was read from
>>> +	 * the device tree, get the optional clock divider as well
>>> +	 */
>>> +	np = ofdev->dev.of_node;
>>> +	clockdiv = 1;
>>> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
>>> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
>>> +		clock_source ? clock_source : "<NULL>", clockdiv);
>>> +
>>> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
>>> +	 * get set, and the 'ips' clock is the input to the MSCAN
>>> +	 * component
>>> +	 *
>>> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
>>> +	 * bit needs to get cleared, an optional clock-divider may have
>>> +	 * been specified (the default value is 1), the appropriate
>>> +	 * MSCAN related MCLK is the input to the MSCAN component
>>> +	 *
>>> +	 * in the absence of a clock-source spec, first an optimal clock
>>> +	 * gets determined based on the 'sys' clock, if that fails the
>>> +	 * 'ref' clock is used
>>> +	 */
>>> +	clk_from = CLK_FROM_AUTO;
>>> +	if (clock_source) {
>>> +		/* interpret the device tree's spec for the clock source */
>>> +		if (!strcmp(clock_source, "ip"))
>>> +			clk_from = CLK_FROM_IPS;
>>> +		else if (!strcmp(clock_source, "sys"))
>>> +			clk_from = CLK_FROM_SYS;
>>> +		else if (!strcmp(clock_source, "ref"))
>>> +			clk_from = CLK_FROM_REF;
>>> +		else
>>> +			goto err_invalid;
>>> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
>>> +	}
>>> +	if (clk_from == CLK_FROM_AUTO) {
>>> +		/* no spec so far, try the 'sys' clock; round to the
>>> +		 * next MHz and see if we can get a multiple of 16MHz
>>> +		 */
>>> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
>>> +		clk_in = clk_get(&ofdev->dev, "sys");
>>> +		if (IS_ERR(clk_in))
>>> +			goto err_notavail;
>>> +		freq_calc = clk_get_rate(clk_in);
>>> +		freq_calc +=  499999;
>>> +		freq_calc /= 1000000;
>>> +		freq_calc *= 1000000;
>>> +		if ((freq_calc % 16000000) == 0) {
>>> +			clk_from = CLK_FROM_SYS;
>>> +			clockdiv = freq_calc / 16000000;
>>> +			dev_dbg(&ofdev->dev,
>>> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
>>> +				freq_calc, clockdiv, freq_calc / clockdiv);
>>> +		}
>>> +	}
>>> +	if (clk_from == CLK_FROM_AUTO) {
>>> +		/* no spec so far, use the 'ref' clock */
>>> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
>>> +		clk_in = clk_get(&ofdev->dev, "ref");
>>> +		if (IS_ERR(clk_in))
>>> +			goto err_notavail;
>>> +		clk_from = CLK_FROM_REF;
>>> +		freq_calc = clk_get_rate(clk_in);
>>> +		dev_dbg(&ofdev->dev,
>>> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
>>> +			freq_calc, freq_calc);
>>> +	}
>>> +
>>> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
>>> +	 * setup the MCLK mux source and rate if applicable, apply the
>>> +	 * optionally specified or derived above divider, and determine
>>> +	 * the actual resulting clock rate to return to the caller
>>> +	 */
>>> +	switch (clk_from) {
>>> +	case CLK_FROM_IPS:
>>> +		clk_can = clk_get(&ofdev->dev, "ips");
>>> +		if (IS_ERR(clk_can))
>>> +			goto err_notavail;
>>> +		clk_prepare_enable(clk_can);
>>
>> Where is the corresponding clk_disable_unprepare()?a
> 
> It's missing, as I could not find the counterpart of the
> .get_clock() callback where the get and prepare/enable was added
> to.  And it appears that neither are enable errors checked for.
> This patch clearly needs an update as well, but already should be
> the last part of the series in a currently inacceptable state.
> 
> This .get_clock() routine is supposed to determine the clock
> source, setup the desired rate and return the actual rate.  The
> callback's API is rather limited in that it does communicate
> clock rate values, but cannot access a location to store handles
> to.

I think the API is sufficient, the ofdev links via drv data to the
netdev
(http://lxr.free-electrons.com/source/drivers/net/can/mscan/mpc5xxx_can.c#L305)
and you get from the netdev to the mscan_priv
(http://lxr.free-electrons.com/source/drivers/net/can/mscan/mpc5xxx_can.c#L281).

BTW: You should prepare_enable the clock in the ndo_open() callback,
i.e. mscan_open() and disable_unprepare in mscan_close(). Doing this you
maximize the power saving effect by not powering the mscan IP core if
the CAN device is not up.

> Are the introduction of a .put_clock() callback and passing the
> 'priv' handle to both get and put routines acceptable?  As this
> would hook up clock handling to probe() and remove() just as
> memory mapping gets approached.

I think an additional priv parameter is not needed. get_ and put_clock()
in probe() and remove() is good, but put the
prepare_enable()/disable_unprepare() in open()/close().

> Below is a patch on top of the CAN related patch in v2 of the
> series.  If this approach is acceptable (maybe modulo how the
> "unused" warnings get silenced), I'll fold it into the
> introduction of common clock support in the mscan(4) driver.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-19 10:46                   ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-19 10:46 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss, Wolfram Sang,
	Mauro Carvalho Chehab, David Woodhouse, Wolfgang Grandegger,
	Pantelis Antoniou, Mark Brown, Greg Kroah-Hartman, Rob Herring,
	Detlev Zundel

[-- Attachment #1: Type: text/plain, Size: 7043 bytes --]

On 07/19/2013 11:41 AM, Gerhard Sittig wrote:
> On Fri, Jul 19, 2013 at 09:34 +0200, Marc Kleine-Budde wrote:
>>
>> On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
>>> extend the mscan(4) driver with alternative support for the COMMON_CLK
>>> approach which is an option in the MPC512x platform, keep the existing
>>> clock support implementation in place since the driver is shared with
>>> other MPC5xxx SoCs which don't have common clock support
>>>
>>> one byproduct of this change is that the CAN driver no longer needs to
>>> access the SoC's clock control registers, which shall be the domain of
>>> the platform's clock driver
>>>
>>> Signed-off-by: Gerhard Sittig <gsi@denx.de>
>>> ---
>>>  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
>>>  1 file changed, 139 insertions(+)
>>>
>>> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
>>> index bc422ba..dd26ab6 100644
>>> --- a/drivers/net/can/mscan/mpc5xxx_can.c
>>> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
>>> @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>>>  #endif /* CONFIG_PPC_MPC52xx */
>>>  
>>>  #ifdef CONFIG_PPC_MPC512x
>>> +
>>> +#if IS_ENABLED(CONFIG_COMMON_CLK)
>>> +
>>> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>>> +				 const char *clock_source, int *mscan_clksrc)
>>> +{
>>> +	struct device_node *np;
>>> +	u32 clockdiv;
>>> +	enum {
>>> +		CLK_FROM_AUTO,
>>> +		CLK_FROM_IPS,
>>> +		CLK_FROM_SYS,
>>> +		CLK_FROM_REF,
>>> +	} clk_from;
>>> +	struct clk *clk_in, *clk_can;
>>> +	unsigned long freq_calc;
>>> +
>>> +	/* the caller passed in the clock source spec that was read from
>>> +	 * the device tree, get the optional clock divider as well
>>> +	 */
>>> +	np = ofdev->dev.of_node;
>>> +	clockdiv = 1;
>>> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
>>> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
>>> +		clock_source ? clock_source : "<NULL>", clockdiv);
>>> +
>>> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
>>> +	 * get set, and the 'ips' clock is the input to the MSCAN
>>> +	 * component
>>> +	 *
>>> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
>>> +	 * bit needs to get cleared, an optional clock-divider may have
>>> +	 * been specified (the default value is 1), the appropriate
>>> +	 * MSCAN related MCLK is the input to the MSCAN component
>>> +	 *
>>> +	 * in the absence of a clock-source spec, first an optimal clock
>>> +	 * gets determined based on the 'sys' clock, if that fails the
>>> +	 * 'ref' clock is used
>>> +	 */
>>> +	clk_from = CLK_FROM_AUTO;
>>> +	if (clock_source) {
>>> +		/* interpret the device tree's spec for the clock source */
>>> +		if (!strcmp(clock_source, "ip"))
>>> +			clk_from = CLK_FROM_IPS;
>>> +		else if (!strcmp(clock_source, "sys"))
>>> +			clk_from = CLK_FROM_SYS;
>>> +		else if (!strcmp(clock_source, "ref"))
>>> +			clk_from = CLK_FROM_REF;
>>> +		else
>>> +			goto err_invalid;
>>> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
>>> +	}
>>> +	if (clk_from == CLK_FROM_AUTO) {
>>> +		/* no spec so far, try the 'sys' clock; round to the
>>> +		 * next MHz and see if we can get a multiple of 16MHz
>>> +		 */
>>> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
>>> +		clk_in = clk_get(&ofdev->dev, "sys");
>>> +		if (IS_ERR(clk_in))
>>> +			goto err_notavail;
>>> +		freq_calc = clk_get_rate(clk_in);
>>> +		freq_calc +=  499999;
>>> +		freq_calc /= 1000000;
>>> +		freq_calc *= 1000000;
>>> +		if ((freq_calc % 16000000) == 0) {
>>> +			clk_from = CLK_FROM_SYS;
>>> +			clockdiv = freq_calc / 16000000;
>>> +			dev_dbg(&ofdev->dev,
>>> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
>>> +				freq_calc, clockdiv, freq_calc / clockdiv);
>>> +		}
>>> +	}
>>> +	if (clk_from == CLK_FROM_AUTO) {
>>> +		/* no spec so far, use the 'ref' clock */
>>> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
>>> +		clk_in = clk_get(&ofdev->dev, "ref");
>>> +		if (IS_ERR(clk_in))
>>> +			goto err_notavail;
>>> +		clk_from = CLK_FROM_REF;
>>> +		freq_calc = clk_get_rate(clk_in);
>>> +		dev_dbg(&ofdev->dev,
>>> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
>>> +			freq_calc, freq_calc);
>>> +	}
>>> +
>>> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
>>> +	 * setup the MCLK mux source and rate if applicable, apply the
>>> +	 * optionally specified or derived above divider, and determine
>>> +	 * the actual resulting clock rate to return to the caller
>>> +	 */
>>> +	switch (clk_from) {
>>> +	case CLK_FROM_IPS:
>>> +		clk_can = clk_get(&ofdev->dev, "ips");
>>> +		if (IS_ERR(clk_can))
>>> +			goto err_notavail;
>>> +		clk_prepare_enable(clk_can);
>>
>> Where is the corresponding clk_disable_unprepare()?a
> 
> It's missing, as I could not find the counterpart of the
> .get_clock() callback where the get and prepare/enable was added
> to.  And it appears that neither are enable errors checked for.
> This patch clearly needs an update as well, but already should be
> the last part of the series in a currently inacceptable state.
> 
> This .get_clock() routine is supposed to determine the clock
> source, setup the desired rate and return the actual rate.  The
> callback's API is rather limited in that it does communicate
> clock rate values, but cannot access a location to store handles
> to.

I think the API is sufficient, the ofdev links via drv data to the
netdev
(http://lxr.free-electrons.com/source/drivers/net/can/mscan/mpc5xxx_can.c#L305)
and you get from the netdev to the mscan_priv
(http://lxr.free-electrons.com/source/drivers/net/can/mscan/mpc5xxx_can.c#L281).

BTW: You should prepare_enable the clock in the ndo_open() callback,
i.e. mscan_open() and disable_unprepare in mscan_close(). Doing this you
maximize the power saving effect by not powering the mscan IP core if
the CAN device is not up.

> Are the introduction of a .put_clock() callback and passing the
> 'priv' handle to both get and put routines acceptable?  As this
> would hook up clock handling to probe() and remove() just as
> memory mapping gets approached.

I think an additional priv parameter is not needed. get_ and put_clock()
in probe() and remove() is good, but put the
prepare_enable()/disable_unprepare() in open()/close().

> Below is a patch on top of the CAN related patch in v2 of the
> series.  If this approach is acceptable (maybe modulo how the
> "unused" warnings get silenced), I'll fold it into the
> introduction of common clock support in the mscan(4) driver.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock
@ 2013-07-19 10:46                   ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-19 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/19/2013 11:41 AM, Gerhard Sittig wrote:
> On Fri, Jul 19, 2013 at 09:34 +0200, Marc Kleine-Budde wrote:
>>
>> On 07/18/2013 10:20 PM, Gerhard Sittig wrote:
>>> extend the mscan(4) driver with alternative support for the COMMON_CLK
>>> approach which is an option in the MPC512x platform, keep the existing
>>> clock support implementation in place since the driver is shared with
>>> other MPC5xxx SoCs which don't have common clock support
>>>
>>> one byproduct of this change is that the CAN driver no longer needs to
>>> access the SoC's clock control registers, which shall be the domain of
>>> the platform's clock driver
>>>
>>> Signed-off-by: Gerhard Sittig <gsi@denx.de>
>>> ---
>>>  drivers/net/can/mscan/mpc5xxx_can.c |  139 +++++++++++++++++++++++++++++++++++
>>>  1 file changed, 139 insertions(+)
>>>
>>> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
>>> index bc422ba..dd26ab6 100644
>>> --- a/drivers/net/can/mscan/mpc5xxx_can.c
>>> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
>>> @@ -108,6 +108,143 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>>>  #endif /* CONFIG_PPC_MPC52xx */
>>>  
>>>  #ifdef CONFIG_PPC_MPC512x
>>> +
>>> +#if IS_ENABLED(CONFIG_COMMON_CLK)
>>> +
>>> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>>> +				 const char *clock_source, int *mscan_clksrc)
>>> +{
>>> +	struct device_node *np;
>>> +	u32 clockdiv;
>>> +	enum {
>>> +		CLK_FROM_AUTO,
>>> +		CLK_FROM_IPS,
>>> +		CLK_FROM_SYS,
>>> +		CLK_FROM_REF,
>>> +	} clk_from;
>>> +	struct clk *clk_in, *clk_can;
>>> +	unsigned long freq_calc;
>>> +
>>> +	/* the caller passed in the clock source spec that was read from
>>> +	 * the device tree, get the optional clock divider as well
>>> +	 */
>>> +	np = ofdev->dev.of_node;
>>> +	clockdiv = 1;
>>> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
>>> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
>>> +		clock_source ? clock_source : "<NULL>", clockdiv);
>>> +
>>> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
>>> +	 * get set, and the 'ips' clock is the input to the MSCAN
>>> +	 * component
>>> +	 *
>>> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
>>> +	 * bit needs to get cleared, an optional clock-divider may have
>>> +	 * been specified (the default value is 1), the appropriate
>>> +	 * MSCAN related MCLK is the input to the MSCAN component
>>> +	 *
>>> +	 * in the absence of a clock-source spec, first an optimal clock
>>> +	 * gets determined based on the 'sys' clock, if that fails the
>>> +	 * 'ref' clock is used
>>> +	 */
>>> +	clk_from = CLK_FROM_AUTO;
>>> +	if (clock_source) {
>>> +		/* interpret the device tree's spec for the clock source */
>>> +		if (!strcmp(clock_source, "ip"))
>>> +			clk_from = CLK_FROM_IPS;
>>> +		else if (!strcmp(clock_source, "sys"))
>>> +			clk_from = CLK_FROM_SYS;
>>> +		else if (!strcmp(clock_source, "ref"))
>>> +			clk_from = CLK_FROM_REF;
>>> +		else
>>> +			goto err_invalid;
>>> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
>>> +	}
>>> +	if (clk_from == CLK_FROM_AUTO) {
>>> +		/* no spec so far, try the 'sys' clock; round to the
>>> +		 * next MHz and see if we can get a multiple of 16MHz
>>> +		 */
>>> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
>>> +		clk_in = clk_get(&ofdev->dev, "sys");
>>> +		if (IS_ERR(clk_in))
>>> +			goto err_notavail;
>>> +		freq_calc = clk_get_rate(clk_in);
>>> +		freq_calc +=  499999;
>>> +		freq_calc /= 1000000;
>>> +		freq_calc *= 1000000;
>>> +		if ((freq_calc % 16000000) == 0) {
>>> +			clk_from = CLK_FROM_SYS;
>>> +			clockdiv = freq_calc / 16000000;
>>> +			dev_dbg(&ofdev->dev,
>>> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
>>> +				freq_calc, clockdiv, freq_calc / clockdiv);
>>> +		}
>>> +	}
>>> +	if (clk_from == CLK_FROM_AUTO) {
>>> +		/* no spec so far, use the 'ref' clock */
>>> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
>>> +		clk_in = clk_get(&ofdev->dev, "ref");
>>> +		if (IS_ERR(clk_in))
>>> +			goto err_notavail;
>>> +		clk_from = CLK_FROM_REF;
>>> +		freq_calc = clk_get_rate(clk_in);
>>> +		dev_dbg(&ofdev->dev,
>>> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
>>> +			freq_calc, freq_calc);
>>> +	}
>>> +
>>> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
>>> +	 * setup the MCLK mux source and rate if applicable, apply the
>>> +	 * optionally specified or derived above divider, and determine
>>> +	 * the actual resulting clock rate to return to the caller
>>> +	 */
>>> +	switch (clk_from) {
>>> +	case CLK_FROM_IPS:
>>> +		clk_can = clk_get(&ofdev->dev, "ips");
>>> +		if (IS_ERR(clk_can))
>>> +			goto err_notavail;
>>> +		clk_prepare_enable(clk_can);
>>
>> Where is the corresponding clk_disable_unprepare()?a
> 
> It's missing, as I could not find the counterpart of the
> .get_clock() callback where the get and prepare/enable was added
> to.  And it appears that neither are enable errors checked for.
> This patch clearly needs an update as well, but already should be
> the last part of the series in a currently inacceptable state.
> 
> This .get_clock() routine is supposed to determine the clock
> source, setup the desired rate and return the actual rate.  The
> callback's API is rather limited in that it does communicate
> clock rate values, but cannot access a location to store handles
> to.

I think the API is sufficient, the ofdev links via drv data to the
netdev
(http://lxr.free-electrons.com/source/drivers/net/can/mscan/mpc5xxx_can.c#L305)
and you get from the netdev to the mscan_priv
(http://lxr.free-electrons.com/source/drivers/net/can/mscan/mpc5xxx_can.c#L281).

BTW: You should prepare_enable the clock in the ndo_open() callback,
i.e. mscan_open() and disable_unprepare in mscan_close(). Doing this you
maximize the power saving effect by not powering the mscan IP core if
the CAN device is not up.

> Are the introduction of a .put_clock() callback and passing the
> 'priv' handle to both get and put routines acceptable?  As this
> would hook up clock handling to probe() and remove() just as
> memory mapping gets approached.

I think an additional priv parameter is not needed. get_ and put_clock()
in probe() and remove() is good, but put the
prepare_enable()/disable_unprepare() in open()/close().

> Below is a patch on top of the CAN related patch in v2 of the
> series.  If this approach is acceptable (maybe modulo how the
> "unused" warnings get silenced), I'll fold it into the
> introduction of common clock support in the mscan(4) driver.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130719/a63fef52/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-07-18 17:00     ` Gerhard Sittig
@ 2013-07-22 12:14       ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this series
- fixes several drivers that are used in the MPC512x platform (UART,
  SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
  handle clocks (appropriately acquire and setup them, hold references
  during use, release clocks after use)
- introduces support for the common clock framework (CCF, COMMON_CLK
  Kconfig option) in the PowerPC based MPC512x platform, which brings
  device tree based clock lookup as well

although the series does touch several subsystems -- tty (serial), spi,
net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
the patches are strictly clock related

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #436: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 845 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v3:
- rebase the series against v3.11-rc2
- re-ordered the series to first address all general clock handling
  concerns in existing drivers, before introducing common clock support
  in the platform's clock driver
- slightly rework the SPI (01/31), UART (02/31), and PSC FIFO (23/31)
  clock handling in comparison to v2 which introduced those fixes
  (devm_{get,put}_clk() calls, fewer goto labels in error paths)
- fix and improve clock handling (balance allocation and release of
  clocks, check for errors during setup) in all of the other drivers
  which this series has touched before in naive ways: USB (03/31), NAND
  flash (04/31), video capture (05/31), I2C (06/31), ethernet (08/31),
  PCI (09/31), CAN (11/31)
- silence a build warning in the ethernet driver (07/31)
- eliminate all PPC_CLOCK references, use 'per' clock names for NAND
  flash (25/31) and VIU (26/31) as well
- unbreak CAN operation for the period between introducing common clock
  support in the platform's clock driver and introducing common clock
  support in the CAN peripheral driver as well as providing clock specs
  in the device tree (provide clkdev aliases for SYS and REF)
- improve common clock support for CAN (devm_{get,put}_clk() calls,
  check enable() errors, keep a reference to used clocks, disable and
  put clocks after use)
- reworded several commit messages to better reflect the kind of change
  and because fixes were applied before adding common infrastructure
  support
- point to individual numbered patches of the series in the list of
  changes for v2 as well

changes in v2:
- cleanup of the UART (02/24) and SPI (01/24) clock handling before the
  introduction of common clock support for the platform, as incomplete
  clock handling becomes fatal or more dangerous later (which in turn
  changes the context of the "device tree lookup only" followup patch
  later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced, which have become 11-14/24 now)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration (09/24)
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine (14/24)
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call (13/24)


Gerhard Sittig (31):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  USB: fsl-mph-dr-of: cleanup clock API use
  mtd: mpc5121_nfc: cleanup clock API use
  [media] fsl-viu: cleanup clock API use
  i2c: mpc: cleanup clock API use
  fs_enet: silence a build warning (unused variable)
  fs_enet: cleanup clock API use
  powerpc/fsl-pci: improve clock API use
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: improve clock API use
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  clk: mpc512x: don't pre-enable FEC and I2C clocks
  spi: mpc512x: remove now obsolete clock lookup name
  serial: mpc512x: remove now obsolete clock lookup name
  clk: mpc512x: remove clkdev registration (uart, spi)
  serial: mpc512x: setup the PSC FIFO clock as well
  USB: fsl-mph-dr-of: remove now obsolete clock lookup name
  mtd: mpc5121_nfc: remove now obsolete clock lookup name
  [media] fsl-viu: remove now obsolete clock lookup name
  net: can: mscan: add common clock support for  mpc512x
  powerpc/mpc512x: improve DIU related clock setup
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove non-common_clock code for MPC512x
  clk: mpc512x: remove clkdev registration (sys/ref, header)

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  761 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   23 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |   28 +
 drivers/media/platform/fsl-viu.c                   |   26 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |   20 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  271 ++++---
 drivers/net/can/mscan/mscan.c                      |    9 +
 drivers/net/can/mscan/mscan.h                      |    2 +
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   26 +-
 drivers/spi/spi-mpc512x-psc.c                      |   48 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  144 +++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   26 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 28 files changed, 1493 insertions(+), 1053 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc2-00031-ge72cd55 ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      10          10           320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 1           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 1           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk_out 1           1            80000000
                      psc7_mclk 1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-07-22 12:14       ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

this series
- fixes several drivers that are used in the MPC512x platform (UART,
  SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
  handle clocks (appropriately acquire and setup them, hold references
  during use, release clocks after use)
- introduces support for the common clock framework (CCF, COMMON_CLK
  Kconfig option) in the PowerPC based MPC512x platform, which brings
  device tree based clock lookup as well

although the series does touch several subsystems -- tty (serial), spi,
net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
the patches are strictly clock related

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #436: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:335:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 845 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v3:
- rebase the series against v3.11-rc2
- re-ordered the series to first address all general clock handling
  concerns in existing drivers, before introducing common clock support
  in the platform's clock driver
- slightly rework the SPI (01/31), UART (02/31), and PSC FIFO (23/31)
  clock handling in comparison to v2 which introduced those fixes
  (devm_{get,put}_clk() calls, fewer goto labels in error paths)
- fix and improve clock handling (balance allocation and release of
  clocks, check for errors during setup) in all of the other drivers
  which this series has touched before in naive ways: USB (03/31), NAND
  flash (04/31), video capture (05/31), I2C (06/31), ethernet (08/31),
  PCI (09/31), CAN (11/31)
- silence a build warning in the ethernet driver (07/31)
- eliminate all PPC_CLOCK references, use 'per' clock names for NAND
  flash (25/31) and VIU (26/31) as well
- unbreak CAN operation for the period between introducing common clock
  support in the platform's clock driver and introducing common clock
  support in the CAN peripheral driver as well as providing clock specs
  in the device tree (provide clkdev aliases for SYS and REF)
- improve common clock support for CAN (devm_{get,put}_clk() calls,
  check enable() errors, keep a reference to used clocks, disable and
  put clocks after use)
- reworded several commit messages to better reflect the kind of change
  and because fixes were applied before adding common infrastructure
  support
- point to individual numbered patches of the series in the list of
  changes for v2 as well

changes in v2:
- cleanup of the UART (02/24) and SPI (01/24) clock handling before the
  introduction of common clock support for the platform, as incomplete
  clock handling becomes fatal or more dangerous later (which in turn
  changes the context of the "device tree lookup only" followup patch
  later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced, which have become 11-14/24 now)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration (09/24)
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine (14/24)
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call (13/24)


Gerhard Sittig (31):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  USB: fsl-mph-dr-of: cleanup clock API use
  mtd: mpc5121_nfc: cleanup clock API use
  [media] fsl-viu: cleanup clock API use
  i2c: mpc: cleanup clock API use
  fs_enet: silence a build warning (unused variable)
  fs_enet: cleanup clock API use
  powerpc/fsl-pci: improve clock API use
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: improve clock API use
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  clk: mpc512x: don't pre-enable FEC and I2C clocks
  spi: mpc512x: remove now obsolete clock lookup name
  serial: mpc512x: remove now obsolete clock lookup name
  clk: mpc512x: remove clkdev registration (uart, spi)
  serial: mpc512x: setup the PSC FIFO clock as well
  USB: fsl-mph-dr-of: remove now obsolete clock lookup name
  mtd: mpc5121_nfc: remove now obsolete clock lookup name
  [media] fsl-viu: remove now obsolete clock lookup name
  net: can: mscan: add common clock support for  mpc512x
  powerpc/mpc512x: improve DIU related clock setup
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove non-common_clock code for MPC512x
  clk: mpc512x: remove clkdev registration (sys/ref, header)

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |   94 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  761 ++++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 -------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   23 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |   28 +
 drivers/media/platform/fsl-viu.c                   |   26 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |   20 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  271 ++++---
 drivers/net/can/mscan/mscan.c                      |    9 +
 drivers/net/can/mscan/mscan.h                      |    2 +
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   26 +-
 drivers/spi/spi-mpc512x-psc.c                      |   48 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  144 +++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   26 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   59 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 28 files changed, 1493 insertions(+), 1053 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc2-00031-ge72cd55 ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      10          10           320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk_out 0           0            80000000
                      spdif_mclk 0           0            80000000
          mscan3-mux0           1           1            320000000
             mscan3-en0         1           1            320000000
                mscan3_mclk_div 1           1            80000000
                   mscan3_mclk_out 1           1            80000000
                      mscan3_mclk 1           1            80000000
          mscan2-mux0           1           1            320000000
             mscan2-en0         1           1            320000000
                mscan2_mclk_div 1           1            80000000
                   mscan2_mclk_out 1           1            80000000
                      mscan2_mclk 1           1            80000000
          mscan1-mux0           1           1            320000000
             mscan1-en0         1           1            320000000
                mscan1_mclk_div 1           1            16000000
                   mscan1_mclk_out 1           1            16000000
                      mscan1_mclk 1           2            16000000
          mscan0-mux0           1           1            320000000
             mscan0-en0         1           1            320000000
                mscan0_mclk_div 1           1            16000000
                   mscan0_mclk_out 1           1            16000000
                      mscan0_mclk 1           2            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk_out 0           0            80000000
                      psc11_mclk 0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk_out 0           0            80000000
                      psc10_mclk 0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk_out 0           0            80000000
                      psc9_mclk 0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk_out 0           0            80000000
                      psc8_mclk 0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk_out 1           1            80000000
                      psc7_mclk 1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk_out 0           0            80000000
                      psc6_mclk 0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk_out 1           1            80000000
                      psc5_mclk 1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk_out 1           1            80000000
                      psc4_mclk 1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk_out 1           1            80000000
                      psc3_mclk 2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk_out 0           0            80000000
                      psc2_mclk 0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk_out 0           0            80000000
                      psc1_mclk 0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk_out 0           0            80000000
                      psc0_mclk 0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                7           7            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   52 +++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..823e5e0 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
+	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +519,32 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	clk = devm_clk_get(dev, clk_name);
+	if (IS_ERR(clk))
+		goto free_irq;
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		devm_clk_put(dev, clk);
+		goto free_irq;
+	}
+	mps->clk_mclk = clk;
+	mps->mclk_rate = clk_get_rate(clk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	return ret;
 
+free_clock:
+	clk_disable_unprepare(mps->clk_mclk);
+	devm_clk_put(dev, mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +561,8 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
+	devm_clk_put(dev, mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   52 +++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..823e5e0 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
+	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +519,32 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	clk = devm_clk_get(dev, clk_name);
+	if (IS_ERR(clk))
+		goto free_irq;
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		devm_clk_put(dev, clk);
+		goto free_irq;
+	}
+	mps->clk_mclk = clk;
+	mps->mclk_rate = clk_get_rate(clk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	return ret;
 
+free_clock:
+	clk_disable_unprepare(mps->clk_mclk);
+	devm_clk_put(dev, mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +561,8 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
+	devm_clk_put(dev, mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 02/31] serial: mpc512x: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

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 <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |  100 ++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..8f16ed9 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,75 @@ 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");
+		devm_clk_put(port->dev, clk);
+		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);
+		devm_clk_put(port->dev, 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 *port, struct device_node *np)
@@ -873,7 +919,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +954,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1216,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1243,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 02/31] serial: mpc512x: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

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 <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |  100 ++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index e1280a2..8f16ed9 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,75 @@ 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");
+		devm_clk_put(port->dev, clk);
+		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);
+		devm_clk_put(port->dev, 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 *port, struct device_node *np)
@@ -873,7 +919,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +954,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1216,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1243,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 03/31] USB: fsl-mph-dr-of: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

error check in the clock setup, must prepare clocks before they
can get enabled, unprepare after disable, use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..5e51384 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,6 +260,7 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
+	int err;
 	char clk_name[10];
 	int base, clk_num;
 
@@ -272,13 +273,17 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 		return -ENODEV;
 
 	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, clk_name);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		devm_clk_put(&pdev->dev, clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,8 +308,8 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
-		clk_put(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
+		devm_clk_put(&pdev->dev, pdata->clk);
 	}
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 03/31] USB: fsl-mph-dr-of: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

error check in the clock setup, must prepare clocks before they
can get enabled, unprepare after disable, use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..5e51384 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,6 +260,7 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
+	int err;
 	char clk_name[10];
 	int base, clk_num;
 
@@ -272,13 +273,17 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 		return -ENODEV;
 
 	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, clk_name);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		devm_clk_put(&pdev->dev, clk);
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -303,8 +308,8 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 	pdata->regs = NULL;
 
 	if (pdata->clk) {
-		clk_disable(pdata->clk);
-		clk_put(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
+		devm_clk_put(&pdev->dev, pdata->clk);
 	}
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 04/31] mtd: mpc5121_nfc: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare before enable isn't optional, do check for and propagate clock
setup errors, adjust error code paths to correctly balance get/put and
prepare/unprepare and enable/disable, use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |   20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..9c0b8fe 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,8 +618,8 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
-		clk_put(prv->clk);
+		clk_disable_unprepare(prv->clk);
+		devm_clk_put(dev, prv->clk);
 	}
 
 	if (prv->csreg)
@@ -629,6 +629,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
+	struct clk *clk;
 	struct device *dev = &op->dev;
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
@@ -730,14 +731,19 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	prv->clk = clk_get(dev, "nfc_clk");
-	if (IS_ERR(prv->clk)) {
+	clk = devm_clk_get(dev, "nfc_clk");
+	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
-		retval = PTR_ERR(prv->clk);
+		retval = PTR_ERR(clk);
 		goto error;
 	}
-
-	clk_enable(prv->clk);
+	retval = clk_prepare_enable(clk);
+	if (retval) {
+		dev_err(dev, "Unable to enable NFC clock!\n");
+		devm_clk_put(dev, clk);
+		goto error;
+	}
+	prv->clk = clk;
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 04/31] mtd: mpc5121_nfc: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

prepare before enable isn't optional, do check for and propagate clock
setup errors, adjust error code paths to correctly balance get/put and
prepare/unprepare and enable/disable, use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |   20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..9c0b8fe 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -618,8 +618,8 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
 	if (prv->clk) {
-		clk_disable(prv->clk);
-		clk_put(prv->clk);
+		clk_disable_unprepare(prv->clk);
+		devm_clk_put(dev, prv->clk);
 	}
 
 	if (prv->csreg)
@@ -629,6 +629,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
+	struct clk *clk;
 	struct device *dev = &op->dev;
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
@@ -730,14 +731,19 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	prv->clk = clk_get(dev, "nfc_clk");
-	if (IS_ERR(prv->clk)) {
+	clk = devm_clk_get(dev, "nfc_clk");
+	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
-		retval = PTR_ERR(prv->clk);
+		retval = PTR_ERR(clk);
 		goto error;
 	}
-
-	clk_enable(prv->clk);
+	retval = clk_prepare_enable(clk);
+	if (retval) {
+		dev_err(dev, "Unable to enable NFC clock!\n");
+		devm_clk_put(dev, clk);
+		goto error;
+	}
+	prv->clk = clk;
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 05/31] [media] fsl-viu: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
  (?)
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

prepare clocks before enabling them, check for and propagate enable
errors, balance get/put and prepare/unprepare and enable/disable,
use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..48fced4 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1485,6 +1485,7 @@ static int viu_of_probe(struct platform_device *op)
 	struct viu_reg __iomem *viu_regs;
 	struct i2c_adapter *ad;
 	int ret, viu_irq;
+	struct clk *clk;
 
 	ret = of_address_to_resource(op->dev.of_node, 0, &r);
 	if (ret) {
@@ -1577,14 +1578,19 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	viu_dev->clk = clk_get(&op->dev, "viu_clk");
-	if (IS_ERR(viu_dev->clk)) {
-		dev_err(&op->dev, "failed to find the clock module!\n");
-		ret = -ENODEV;
+	clk = devm_clk_get(&op->dev, "viu_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&op->dev, "failed to lookup the clock!\n");
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		devm_clk_put(&op->dev, clk);
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
 	}
+	viu_dev->clk = clk;
 
 	/* reset VIU module */
 	viu_reset(viu_dev->vr);
@@ -1602,8 +1608,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
-	clk_put(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+	devm_clk_put(&op->dev, viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
 err_vdev:
@@ -1626,8 +1632,8 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
+	clk_disable_unprepare(dev->clk);
+	devm_clk_put(&op->dev, dev->clk);
 
 	video_unregister_device(dev->vdev);
 	i2c_put_adapter(client->adapter);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 05/31] [media] fsl-viu: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare clocks before enabling them, check for and propagate enable
errors, balance get/put and prepare/unprepare and enable/disable,
use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..48fced4 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1485,6 +1485,7 @@ static int viu_of_probe(struct platform_device *op)
 	struct viu_reg __iomem *viu_regs;
 	struct i2c_adapter *ad;
 	int ret, viu_irq;
+	struct clk *clk;
 
 	ret = of_address_to_resource(op->dev.of_node, 0, &r);
 	if (ret) {
@@ -1577,14 +1578,19 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	viu_dev->clk = clk_get(&op->dev, "viu_clk");
-	if (IS_ERR(viu_dev->clk)) {
-		dev_err(&op->dev, "failed to find the clock module!\n");
-		ret = -ENODEV;
+	clk = devm_clk_get(&op->dev, "viu_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&op->dev, "failed to lookup the clock!\n");
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		devm_clk_put(&op->dev, clk);
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
 	}
+	viu_dev->clk = clk;
 
 	/* reset VIU module */
 	viu_reset(viu_dev->vr);
@@ -1602,8 +1608,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
-	clk_put(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+	devm_clk_put(&op->dev, viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
 err_vdev:
@@ -1626,8 +1632,8 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
+	clk_disable_unprepare(dev->clk);
+	devm_clk_put(&op->dev, dev->clk);
 
 	video_unregister_device(dev->vdev);
 	i2c_put_adapter(client->adapter);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 05/31] [media] fsl-viu: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

prepare clocks before enabling them, check for and propagate enable
errors, balance get/put and prepare/unprepare and enable/disable,
use devm_{get,put}_clk()

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..48fced4 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1485,6 +1485,7 @@ static int viu_of_probe(struct platform_device *op)
 	struct viu_reg __iomem *viu_regs;
 	struct i2c_adapter *ad;
 	int ret, viu_irq;
+	struct clk *clk;
 
 	ret = of_address_to_resource(op->dev.of_node, 0, &r);
 	if (ret) {
@@ -1577,14 +1578,19 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	viu_dev->clk = clk_get(&op->dev, "viu_clk");
-	if (IS_ERR(viu_dev->clk)) {
-		dev_err(&op->dev, "failed to find the clock module!\n");
-		ret = -ENODEV;
+	clk = devm_clk_get(&op->dev, "viu_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&op->dev, "failed to lookup the clock!\n");
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
+		devm_clk_put(&op->dev, clk);
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
 	}
+	viu_dev->clk = clk;
 
 	/* reset VIU module */
 	viu_reset(viu_dev->vr);
@@ -1602,8 +1608,8 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
-	clk_put(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
+	devm_clk_put(&op->dev, viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
 err_vdev:
@@ -1626,8 +1632,8 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
+	clk_disable_unprepare(dev->clk);
+	devm_clk_put(&op->dev, dev->clk);
 
 	video_unregister_device(dev->vdev);
 	i2c_put_adapter(client->adapter);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 06/31] i2c: mpc: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the MPC I2C driver get, prepare and enable the peripheral clock
('per' for access to the peripheral's registers) during probe;
disable, unprepare and put the clock upon remove(); hold a reference
to the clock over the period of use

clock lookup is non-fatal in this implementation as not all platforms
may provide clock specs in their device tree, but enable errors for
specified clocks are considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/i2c/busses/i2c-mpc.c |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..9e837be 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -67,6 +68,7 @@ struct mpc_i2c {
 #ifdef CONFIG_PM
 	u8 fdr, dfsrr;
 #endif
+	struct clk *clk_per;
 };
 
 struct mpc_i2c_divider {
@@ -623,6 +625,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
+	struct clk *clk;
+	int err;
 
 	match = of_match_device(mpc_i2c_of_match, &op->dev);
 	if (!match)
@@ -653,6 +657,21 @@ static int fsl_i2c_probe(struct platform_device *op)
 		}
 	}
 
+	/*
+	 * enable clock for the I2C peripheral (non fatal),
+	 * keep a reference upon successful allocation
+	 */
+	clk = devm_clk_get(&op->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			dev_err(&op->dev, "failed to enable clock\n");
+			devm_clk_put(&op->dev, clk);
+		} else {
+			i2c->clk_per = clk;
+		}
+	}
+
 	if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) {
 		clock = MPC_I2C_CLOCK_PRESERVE;
 	} else {
@@ -696,6 +715,10 @@ static int fsl_i2c_probe(struct platform_device *op)
 	return result;
 
  fail_add:
+	if (i2c->clk_per) {
+		clk_disable_unprepare(i2c->clk_per);
+		devm_clk_put(&op->dev, i2c->clk_per);
+	}
 	free_irq(i2c->irq, i2c);
  fail_request:
 	irq_dispose_mapping(i2c->irq);
@@ -711,6 +734,11 @@ static int fsl_i2c_remove(struct platform_device *op)
 
 	i2c_del_adapter(&i2c->adap);
 
+	if (i2c->clk_per) {
+		clk_disable_unprepare(i2c->clk_per);
+		devm_clk_put(&op->dev, i2c->clk_per);
+	}
+
 	if (i2c->irq)
 		free_irq(i2c->irq, i2c);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 06/31] i2c: mpc: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

make the MPC I2C driver get, prepare and enable the peripheral clock
('per' for access to the peripheral's registers) during probe;
disable, unprepare and put the clock upon remove(); hold a reference
to the clock over the period of use

clock lookup is non-fatal in this implementation as not all platforms
may provide clock specs in their device tree, but enable errors for
specified clocks are considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/i2c/busses/i2c-mpc.c |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..9e837be 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -67,6 +68,7 @@ struct mpc_i2c {
 #ifdef CONFIG_PM
 	u8 fdr, dfsrr;
 #endif
+	struct clk *clk_per;
 };
 
 struct mpc_i2c_divider {
@@ -623,6 +625,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
+	struct clk *clk;
+	int err;
 
 	match = of_match_device(mpc_i2c_of_match, &op->dev);
 	if (!match)
@@ -653,6 +657,21 @@ static int fsl_i2c_probe(struct platform_device *op)
 		}
 	}
 
+	/*
+	 * enable clock for the I2C peripheral (non fatal),
+	 * keep a reference upon successful allocation
+	 */
+	clk = devm_clk_get(&op->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			dev_err(&op->dev, "failed to enable clock\n");
+			devm_clk_put(&op->dev, clk);
+		} else {
+			i2c->clk_per = clk;
+		}
+	}
+
 	if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) {
 		clock = MPC_I2C_CLOCK_PRESERVE;
 	} else {
@@ -696,6 +715,10 @@ static int fsl_i2c_probe(struct platform_device *op)
 	return result;
 
  fail_add:
+	if (i2c->clk_per) {
+		clk_disable_unprepare(i2c->clk_per);
+		devm_clk_put(&op->dev, i2c->clk_per);
+	}
 	free_irq(i2c->irq, i2c);
  fail_request:
 	irq_dispose_mapping(i2c->irq);
@@ -711,6 +734,11 @@ static int fsl_i2c_remove(struct platform_device *op)
 
 	i2c_del_adapter(&i2c->adap);
 
+	if (i2c->clk_per) {
+		clk_disable_unprepare(i2c->clk_per);
+		devm_clk_put(&op->dev, i2c->clk_per);
+	}
+
 	if (i2c->irq)
 		free_irq(i2c->irq, i2c);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 07/31] fs_enet: silence a build warning (unused variable)
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab


Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..c04eb3a 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -583,7 +583,6 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
 					       struct sk_buff *skb)
 {
 	struct sk_buff *new_skb;
-	struct fs_enet_private *fep = netdev_priv(dev);
 
 	/* Alloc new skb */
 	new_skb = netdev_alloc_skb(dev, skb->len + 4);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 07/31] fs_enet: silence a build warning (unused variable)
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel


Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..c04eb3a 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -583,7 +583,6 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
 					       struct sk_buff *skb)
 {
 	struct sk_buff *new_skb;
-	struct fs_enet_private *fep = netdev_priv(dev);
 
 	/* Alloc new skb */
 	new_skb = netdev_alloc_skb(dev, skb->len + 4);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 08/31] fs_enet: cleanup clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the Freescale ethernet driver get, prepare and enable the FEC clock
during probe(); disable, unprepare and put the clock upon remove(); hold
a reference to the clock over the period of use; use devm_{get,put}_clk()

clock lookup is non-fatal as not all platforms provide clock specs in
their device tree; failure to enable specified clocks is fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   25 ++++++++++++++++++++
 include/linux/fs_enet_pd.h                         |    3 +++
 2 files changed, 28 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index c04eb3a..1f58f57 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -999,6 +999,8 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	struct fs_enet_private *fep;
 	struct fs_platform_info *fpi;
 	const u32 *data;
+	struct clk *clk;
+	int err;
 	const u8 *mac_addr;
 	const char *phy_connection_type;
 	int privsize, len, ret = -ENODEV;
@@ -1036,6 +1038,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 			fpi->use_rmii = 1;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found,
+	 * keep a reference to the clock upon successful acquisition
+	 */
+	clk = devm_clk_get(&ofdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			devm_clk_put(&ofdev->dev, clk);
+			ret = err;
+			goto out_free_fpi;
+		}
+		fpi->clk_per = clk;
+	}
+
 	privsize = sizeof(*fep) +
 	           sizeof(struct sk_buff **) *
 	           (fpi->rx_ring + fpi->tx_ring);
@@ -1107,6 +1124,10 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+	if (fpi->clk_per) {
+		clk_disable_unprepare(fpi->clk_per);
+		devm_clk_put(&ofdev->dev, fpi->clk_per);
+	}
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1123,6 +1144,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		devm_clk_put(&ofdev->dev, fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 08/31] fs_enet: cleanup clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

make the Freescale ethernet driver get, prepare and enable the FEC clock
during probe(); disable, unprepare and put the clock upon remove(); hold
a reference to the clock over the period of use; use devm_{get,put}_clk()

clock lookup is non-fatal as not all platforms provide clock specs in
their device tree; failure to enable specified clocks is fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   25 ++++++++++++++++++++
 include/linux/fs_enet_pd.h                         |    3 +++
 2 files changed, 28 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index c04eb3a..1f58f57 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -999,6 +999,8 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	struct fs_enet_private *fep;
 	struct fs_platform_info *fpi;
 	const u32 *data;
+	struct clk *clk;
+	int err;
 	const u8 *mac_addr;
 	const char *phy_connection_type;
 	int privsize, len, ret = -ENODEV;
@@ -1036,6 +1038,21 @@ static int fs_enet_probe(struct platform_device *ofdev)
 			fpi->use_rmii = 1;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found,
+	 * keep a reference to the clock upon successful acquisition
+	 */
+	clk = devm_clk_get(&ofdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			devm_clk_put(&ofdev->dev, clk);
+			ret = err;
+			goto out_free_fpi;
+		}
+		fpi->clk_per = clk;
+	}
+
 	privsize = sizeof(*fep) +
 	           sizeof(struct sk_buff **) *
 	           (fpi->rx_ring + fpi->tx_ring);
@@ -1107,6 +1124,10 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+	if (fpi->clk_per) {
+		clk_disable_unprepare(fpi->clk_per);
+		devm_clk_put(&ofdev->dev, fpi->clk_per);
+	}
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1123,6 +1144,10 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per) {
+		clk_disable_unprepare(fep->fpi->clk_per);
+		devm_clk_put(&ofdev->dev, fep->fpi->clk_per);
+	}
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 09/31] powerpc/fsl-pci: improve clock API use
  2013-07-22 12:14       ` Gerhard Sittig
  (?)
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

make the Freescale PCI driver get, prepare and enable the PCI clock
during probe()

clock lookup is non-fatal as not all platforms may provide clock specs
in their device tree, but failure to enable specified clocks are fatal

the driver appears to not have a remove() routine, so no reference to
the clock is kept during use, and the clock isn't released (the devm
approach will put the clock, but it won't get disabled or unprepared)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..5e2f411 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -926,12 +928,33 @@ void fsl_pci_assign_primary(void)
 
 static int fsl_pci_probe(struct platform_device *pdev)
 {
+	struct clk *clk;
 	int ret;
 	struct device_node *node;
 #ifdef CONFIG_SWIOTLB
 	struct pci_controller *hose;
 #endif
 
+	/*
+	 * clock lookup is non-fatal since the driver is shared among
+	 * platforms and not all of them provide clocks specs in their
+	 * device tree, but failure to enable a specified clock is
+	 * considered fatal
+	 */
+	clk = devm_clk_get(&pdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			dev_err(dev, "Could not enable peripheral clock\n");
+			devm_clk_put(&pdev->dev, clk);
+			return ret;
+		}
+		/*
+		 * TODO where to store the 'clk' reference?  there appears
+		 * to be no remove() routine which undoes what probe() does
+		 */
+	}
+
 	node = pdev->dev.of_node;
 	ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 09/31] powerpc/fsl-pci: improve clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the Freescale PCI driver get, prepare and enable the PCI clock
during probe()

clock lookup is non-fatal as not all platforms may provide clock specs
in their device tree, but failure to enable specified clocks are fatal

the driver appears to not have a remove() routine, so no reference to
the clock is kept during use, and the clock isn't released (the devm
approach will put the clock, but it won't get disabled or unprepared)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..5e2f411 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -926,12 +928,33 @@ void fsl_pci_assign_primary(void)
 
 static int fsl_pci_probe(struct platform_device *pdev)
 {
+	struct clk *clk;
 	int ret;
 	struct device_node *node;
 #ifdef CONFIG_SWIOTLB
 	struct pci_controller *hose;
 #endif
 
+	/*
+	 * clock lookup is non-fatal since the driver is shared among
+	 * platforms and not all of them provide clocks specs in their
+	 * device tree, but failure to enable a specified clock is
+	 * considered fatal
+	 */
+	clk = devm_clk_get(&pdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			dev_err(dev, "Could not enable peripheral clock\n");
+			devm_clk_put(&pdev->dev, clk);
+			return ret;
+		}
+		/*
+		 * TODO where to store the 'clk' reference?  there appears
+		 * to be no remove() routine which undoes what probe() does
+		 */
+	}
+
 	node = pdev->dev.of_node;
 	ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 09/31] powerpc/fsl-pci: improve clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

make the Freescale PCI driver get, prepare and enable the PCI clock
during probe()

clock lookup is non-fatal as not all platforms may provide clock specs
in their device tree, but failure to enable specified clocks are fatal

the driver appears to not have a remove() routine, so no reference to
the clock is kept during use, and the clock isn't released (the devm
approach will put the clock, but it won't get disabled or unprepared)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..5e2f411 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -926,12 +928,33 @@ void fsl_pci_assign_primary(void)
 
 static int fsl_pci_probe(struct platform_device *pdev)
 {
+	struct clk *clk;
 	int ret;
 	struct device_node *node;
 #ifdef CONFIG_SWIOTLB
 	struct pci_controller *hose;
 #endif
 
+	/*
+	 * clock lookup is non-fatal since the driver is shared among
+	 * platforms and not all of them provide clocks specs in their
+	 * device tree, but failure to enable a specified clock is
+	 * considered fatal
+	 */
+	clk = devm_clk_get(&pdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			dev_err(dev, "Could not enable peripheral clock\n");
+			devm_clk_put(&pdev->dev, clk);
+			return ret;
+		}
+		/*
+		 * TODO where to store the 'clk' reference?  there appears
+		 * to be no remove() routine which undoes what probe() does
+		 */
+	}
+
 	node = pdev->dev.of_node;
 	ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 10/31] net: can: mscan: add a comment on reg to idx mapping
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 10/31] net: can: mscan: add a comment on reg to idx mapping
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 11/31] net: can: mscan: improve clock API use
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the .get_clock() callback is run from probe() and might allocate
resources, introduce a .put_clock() callback that is run from remove()
to undo any allocation activities

use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
upon driver unload

assume that resources get prepared but not necessarily enabled in the
setup phase, make the open() and close() callbacks of the CAN network
device enable and disable a previously acquired and prepared clock

store pointers to data structures upon successful allocation already
instead of deferral until complete setup, such that subroutines in the
setup sequence may access those data structures as well to track their
resource acquisition

since clock allocation remains optional, the release callback as well as
the enable/disable calls in open/close are optional as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |   18 ++++++++++++------
 drivers/net/can/mscan/mscan.c       |    9 +++++++++
 drivers/net/can/mscan/mscan.h       |    2 ++
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..e59b3a3 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
 			 int *mscan_clksrc);
+	void (*put_clock)(struct platform_device *ofdev);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 			clockdiv = 1;
 
 		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
+			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
 			if (IS_ERR(sys_clk)) {
 				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
 				goto exit_unmap;
@@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		}
 
 		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
+			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
 			if (IS_ERR(ref_clk)) {
 				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
 				goto exit_unmap;
@@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	dev = alloc_mscandev();
 	if (!dev)
 		goto exit_dispose_irq;
+	platform_set_drvdata(ofdev, dev);
+	SET_NETDEV_DEV(dev, &ofdev->dev);
 
 	priv = netdev_priv(dev);
 	priv->reg_base = base;
@@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	SET_NETDEV_DEV(dev, &ofdev->dev);
-
 	err = register_mscandev(dev, mscan_clksrc);
 	if (err) {
 		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
@@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	platform_set_drvdata(ofdev, dev);
-
 	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
 		 priv->reg_base, dev->irq, priv->can.clock.freq);
 
@@ -324,10 +323,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data && data->put_clock)
+		data->put_clock(ofdev);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e6b4095..1c08ffe 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -573,6 +573,12 @@ static int mscan_open(struct net_device *dev)
 	struct mscan_priv *priv = netdev_priv(dev);
 	struct mscan_regs __iomem *regs = priv->reg_base;
 
+	if (priv->clk_can) {
+		ret = clk_enable(priv->clk_can);
+		if (ret)
+			return ret;
+	}
+
 	/* common open */
 	ret = open_candev(dev);
 	if (ret)
@@ -621,6 +627,9 @@ static int mscan_close(struct net_device *dev)
 	close_candev(dev);
 	free_irq(dev->irq, dev);
 
+	if (priv->clk_can)
+		clk_disable(priv->clk_can);
+
 	return 0;
 }
 
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..f32e190 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,7 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_can;	/* clock for registers or bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

the .get_clock() callback is run from probe() and might allocate
resources, introduce a .put_clock() callback that is run from remove()
to undo any allocation activities

use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
upon driver unload

assume that resources get prepared but not necessarily enabled in the
setup phase, make the open() and close() callbacks of the CAN network
device enable and disable a previously acquired and prepared clock

store pointers to data structures upon successful allocation already
instead of deferral until complete setup, such that subroutines in the
setup sequence may access those data structures as well to track their
resource acquisition

since clock allocation remains optional, the release callback as well as
the enable/disable calls in open/close are optional as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |   18 ++++++++++++------
 drivers/net/can/mscan/mscan.c       |    9 +++++++++
 drivers/net/can/mscan/mscan.h       |    2 ++
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..e59b3a3 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
 			 int *mscan_clksrc);
+	void (*put_clock)(struct platform_device *ofdev);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 			clockdiv = 1;
 
 		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
+			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
 			if (IS_ERR(sys_clk)) {
 				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
 				goto exit_unmap;
@@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		}
 
 		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
+			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
 			if (IS_ERR(ref_clk)) {
 				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
 				goto exit_unmap;
@@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	dev = alloc_mscandev();
 	if (!dev)
 		goto exit_dispose_irq;
+	platform_set_drvdata(ofdev, dev);
+	SET_NETDEV_DEV(dev, &ofdev->dev);
 
 	priv = netdev_priv(dev);
 	priv->reg_base = base;
@@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	SET_NETDEV_DEV(dev, &ofdev->dev);
-
 	err = register_mscandev(dev, mscan_clksrc);
 	if (err) {
 		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
@@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	platform_set_drvdata(ofdev, dev);
-
 	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
 		 priv->reg_base, dev->irq, priv->can.clock.freq);
 
@@ -324,10 +323,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data && data->put_clock)
+		data->put_clock(ofdev);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e6b4095..1c08ffe 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -573,6 +573,12 @@ static int mscan_open(struct net_device *dev)
 	struct mscan_priv *priv = netdev_priv(dev);
 	struct mscan_regs __iomem *regs = priv->reg_base;
 
+	if (priv->clk_can) {
+		ret = clk_enable(priv->clk_can);
+		if (ret)
+			return ret;
+	}
+
 	/* common open */
 	ret = open_candev(dev);
 	if (ret)
@@ -621,6 +627,9 @@ static int mscan_close(struct net_device *dev)
 	close_candev(dev);
 	free_irq(dev->irq, dev);
 
+	if (priv->clk_can)
+		clk_disable(priv->clk_can);
+
 	return 0;
 }
 
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..f32e190 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,7 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_can;	/* clock for registers or bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 13/31] clk: wrap I/O access for improved portability
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 13/31] clk: wrap I/O access for improved portability
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 14/31] dts: mpc512x: prepare for preprocessor support
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 14/31] dts: mpc512x: prepare for preprocessor support
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..46c560e
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,59 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ *
+ * Unfortunately the clock number declaration cannot be an enum but
+ * needs to be a list of #define directives since when referenced from
+ * within DTS files they need to get resolved "at compile time".
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_SDHC		24
+#define MPC512x_CLK_PCI			25
+#define MPC512x_CLK_PSC_MCLK_IN		26
+#define MPC512x_CLK_SPDIF_TX		27
+#define MPC512x_CLK_SPDIF_RX		28
+#define MPC512x_CLK_SPDIF_MCLK		29
+#define MPC512x_CLK_AC97		30
+#define MPC512x_CLK_PSC0_MCLK		31
+#define MPC512x_CLK_PSC1_MCLK		32
+#define MPC512x_CLK_PSC2_MCLK		33
+#define MPC512x_CLK_PSC3_MCLK		34
+#define MPC512x_CLK_PSC4_MCLK		35
+#define MPC512x_CLK_PSC5_MCLK		36
+#define MPC512x_CLK_PSC6_MCLK		37
+#define MPC512x_CLK_PSC7_MCLK		38
+#define MPC512x_CLK_PSC8_MCLK		39
+#define MPC512x_CLK_PSC9_MCLK		40
+#define MPC512x_CLK_PSC10_MCLK		41
+#define MPC512x_CLK_PSC11_MCLK		42
+#define MPC512x_CLK_PSC_FIFO		43
+
+#define MPC512x_CLK_LAST_PUBLIC		43
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc@80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock@f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc@80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock@f00 {
+		clks: clock@f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc at 80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock at f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc at 80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock at f00 {
+		clks: clock at f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this change implements a clock driver for the MPC512x PowerPC platform
which follows the COMMON_CLK approach and uses common clock drivers
shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and remains in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

some of the clock items get pre-enabled in the clock driver to not have
them automatically disabled by the underlying clock subsystem because of
their being unused -- this approach is desirable because
- some of the clocks are useful to have for diagnostics and information
  despite their not getting claimed by any drivers (CPU, internal and
  external RAM, internal busses, boot media)
- some of the clocks aren't claimed by their peripheral drivers yet,
  either because of missing driver support or because device tree specs
  aren't available yet (but the workarounds will get removed as the
  drivers get adjusted and the device tree provides the clock specs)
- some help introduce support for and migrate to the common
  infrastructure, while more appropriate support for specific hardware
  constraints isn't available yet (remaining changes are strictly
  internal to the clock driver and won't affect peripheral drivers)

clkdev registration provides "alias names" for few clock items
- to not break those peripheral drivers which encode their component
  index into the name that is used for clock lookup (UART, SPI, USB)
- to not break those drivers which use names for the clock lookup which
  were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
this workaround will get removed as these drivers get adjusted after
device tree based clock lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 818 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..762ee85
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,786 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	/* clkdev registration for compatibility reasons */
+	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

this change implements a clock driver for the MPC512x PowerPC platform
which follows the COMMON_CLK approach and uses common clock drivers
shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and remains in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

some of the clock items get pre-enabled in the clock driver to not have
them automatically disabled by the underlying clock subsystem because of
their being unused -- this approach is desirable because
- some of the clocks are useful to have for diagnostics and information
  despite their not getting claimed by any drivers (CPU, internal and
  external RAM, internal busses, boot media)
- some of the clocks aren't claimed by their peripheral drivers yet,
  either because of missing driver support or because device tree specs
  aren't available yet (but the workarounds will get removed as the
  drivers get adjusted and the device tree provides the clock specs)
- some help introduce support for and migrate to the common
  infrastructure, while more appropriate support for specific hardware
  constraints isn't available yet (remaining changes are strictly
  internal to the clock driver and won't affect peripheral drivers)

clkdev registration provides "alias names" for few clock items
- to not break those peripheral drivers which encode their component
  index into the name that is used for clock lookup (UART, SPI, USB)
- to not break those drivers which use names for the clock lookup which
  were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
this workaround will get removed as these drivers get adjusted after
device tree based clock lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 818 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..762ee85
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,786 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	/* clkdev registration for compatibility reasons */
+	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the client side of device tree based clock lookups

add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..3657ae6 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram@30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "per";
 	};
 
 	localbus@80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc@1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c@1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol@1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display@2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can@2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can@2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu@2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "per";
 		};
 
 		mdio@2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet@2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo@11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma@14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the client side of device tree based clock lookups

add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..3657ae6 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram at 30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "per";
 	};
 
 	localbus at 80000020 {
@@ -153,12 +159,22 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can at 1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		sdhc at 1500 {
@@ -167,6 +183,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c at 1700 {
@@ -175,6 +194,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1720 {
@@ -183,6 +204,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1740 {
@@ -191,6 +214,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol at 1760 {
@@ -202,30 +227,46 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display at 2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can at 2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		can at 2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>;
+			clock-names = "ips", "sys", "ref", "mclk";
 		};
 
 		viu at 2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "per";
 		};
 
 		mdio at 2800 {
@@ -233,6 +274,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet at 2800 {
@@ -241,6 +284,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +297,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +310,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +330,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +343,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC1 */
@@ -301,6 +354,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC2 */
@@ -310,6 +365,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC3 */
@@ -319,6 +376,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC4 */
@@ -328,6 +387,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC5 */
@@ -337,6 +398,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC6 */
@@ -346,6 +409,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC7 */
@@ -355,6 +420,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC8 */
@@ -364,6 +431,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC9 */
@@ -373,6 +442,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC10 */
@@ -382,6 +453,8 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
+			clock-names = "mclk";
 		};
 
 		/* PSC11 */
@@ -391,12 +464,16 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
+			clock-names = "mclk";
 		};
 
 		pscfifo at 11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma at 14000 {
@@ -414,6 +491,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the device tree nodes provide clock specs for client side lookups,
peripheral drivers can attach to their clocks and the clock driver need
no longer pre-enable those clock items

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 762ee85..8b71ceb 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -713,9 +713,7 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after the device tree nodes provide clock specs for client side lookups,
peripheral drivers can attach to their clocks and the clock driver need
no longer pre-enable those clock items

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 762ee85..8b71ceb 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -713,9 +713,7 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 20/31] spi: mpc512x: remove now obsolete clock lookup name
  2013-07-22 12:14       ` Gerhard Sittig
  (?)
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 823e5e0..1a4a983 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -474,8 +474,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
@@ -519,9 +517,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = devm_clk_get(dev, clk_name);
+	clk = devm_clk_get(dev, "mclk");
 	if (IS_ERR(clk))
 		goto free_irq;
 	ret = clk_prepare_enable(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 20/31] spi: mpc512x: remove now obsolete clock lookup name
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 823e5e0..1a4a983 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -474,8 +474,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
@@ -519,9 +517,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = devm_clk_get(dev, clk_name);
+	clk = devm_clk_get(dev, "mclk");
 	if (IS_ERR(clk))
 		goto free_irq;
 	ret = clk_prepare_enable(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 20/31] spi: mpc512x: remove now obsolete clock lookup name
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 823e5e0..1a4a983 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -474,8 +474,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
@@ -519,9 +517,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = devm_clk_get(dev, clk_name);
+	clk = devm_clk_get(dev, "mclk");
 	if (IS_ERR(clk))
 		goto free_irq;
 	ret = clk_prepare_enable(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 21/31] serial: mpc512x: remove now obsolete clock lookup name
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 8f16ed9..04dc564 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -623,14 +623,11 @@ 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)
 {
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 	int err;
+	int psc_num;
 
-	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);
+	clk = devm_clk_get(port->dev, "mclk");
 	if (IS_ERR(clk)) {
 		dev_err(port->dev, "Failed to get MCLK!\n");
 		return PTR_ERR(clk);
@@ -641,6 +638,7 @@ static int mpc512x_psc_alloc_clock(struct uart_port *port)
 		devm_clk_put(port->dev, clk);
 		return err;
 	}
+	psc_num = (port->mapbase & 0xf00) >> 8;
 	psc_mclk_clk[psc_num] = clk;
 	return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 21/31] serial: mpc512x: remove now obsolete clock lookup name
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use "mclk"

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 8f16ed9..04dc564 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -623,14 +623,11 @@ 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)
 {
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 	int err;
+	int psc_num;
 
-	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);
+	clk = devm_clk_get(port->dev, "mclk");
 	if (IS_ERR(clk)) {
 		dev_err(port->dev, "Failed to get MCLK!\n");
 		return PTR_ERR(clk);
@@ -641,6 +638,7 @@ static int mpc512x_psc_alloc_clock(struct uart_port *port)
 		devm_clk_put(port->dev, clk);
 		return err;
 	}
+	psc_num = (port->mapbase & 0xf00) >> 8;
 	psc_mclk_clk[psc_num] = clk;
 	return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 22/31] clk: mpc512x: remove clkdev registration (uart, spi)
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the UART and SPI peripheral drivers have switched to device tree
based clock lookup and no longer construct clock names from their PSC
component index, the "psc%d_mclk" alias names have become obsolete --
remove the corresponding clk_register_clkdev() calls

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   11 -----------
 1 file changed, 11 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 8b71ceb..a860ded 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -529,17 +529,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from device tree specs, and device tree nodes need to
-	 * provide the clock specs, before this clkdev registration
-	 * becomes obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 22/31] clk: mpc512x: remove clkdev registration (uart, spi)
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after the UART and SPI peripheral drivers have switched to device tree
based clock lookup and no longer construct clock names from their PSC
component index, the "psc%d_mclk" alias names have become obsolete --
remove the corresponding clk_register_clkdev() calls

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   11 -----------
 1 file changed, 11 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 8b71ceb..a860ded 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -529,17 +529,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
 				entry->name_mclk,
 				entry->name_mux1, 1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from device tree specs, and device tree nodes need to
-	 * provide the clock specs, before this clkdev registration
-	 * becomes obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 23/31] serial: mpc512x: setup the PSC FIFO clock as well
  2013-07-22 12:14       ` Gerhard Sittig
  (?)
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

prepare and enable the FIFO clock upon PSC FIFO initialization,
check for and propagage errors when enabling the PSC FIFO clock,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

devm_{get,put}_clk() doesn't apply here, as the SoC provides a
single FIFO component which is shared among several PSC components,
thus the FIFO isn't associated with a device (while the PSCs are)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   46 +++++++++++++++++++++----
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index a860ded..53f772b 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -698,8 +698,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 04dc564..23eef91 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -568,36 +569,69 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
+	int err;
 	struct device_node *np;
+	struct clk *clk;
+
+	/* default error code, potentially overwritten by clock calls */
+	err = -ENODEV;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
 	}
 
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		err = PTR_ERR(clk);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		clk_put(clk);
+		goto out_ofnode_put;
+	}
+	psc_fifoc_clk = clk;
+
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return err;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 23/31] serial: mpc512x: setup the PSC FIFO clock as well
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare and enable the FIFO clock upon PSC FIFO initialization,
check for and propagage errors when enabling the PSC FIFO clock,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

devm_{get,put}_clk() doesn't apply here, as the SoC provides a
single FIFO component which is shared among several PSC components,
thus the FIFO isn't associated with a device (while the PSCs are)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   46 +++++++++++++++++++++----
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index a860ded..53f772b 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -698,8 +698,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 04dc564..23eef91 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -568,36 +569,69 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
+	int err;
 	struct device_node *np;
+	struct clk *clk;
+
+	/* default error code, potentially overwritten by clock calls */
+	err = -ENODEV;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
 	}
 
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		err = PTR_ERR(clk);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		clk_put(clk);
+		goto out_ofnode_put;
+	}
+	psc_fifoc_clk = clk;
+
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return err;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 23/31] serial: mpc512x: setup the PSC FIFO clock as well
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

prepare and enable the FIFO clock upon PSC FIFO initialization,
check for and propagage errors when enabling the PSC FIFO clock,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

devm_{get,put}_clk() doesn't apply here, as the SoC provides a
single FIFO component which is shared among several PSC components,
thus the FIFO isn't associated with a device (while the PSCs are)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   46 +++++++++++++++++++++----
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index a860ded..53f772b 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -698,8 +698,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 04dc564..23eef91 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -568,36 +569,69 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
+	int err;
 	struct device_node *np;
+	struct clk *clk;
+
+	/* default error code, potentially overwritten by clock calls */
+	err = -ENODEV;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
 	}
 
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		err = PTR_ERR(clk);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		clk_put(clk);
+		goto out_ofnode_put;
+	}
+	psc_fifoc_clk = clk;
+
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return err;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the component
index -- remove the "usb%d_clk" template and unconditionally use "per",
remove the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/usb/host/fsl-mph-dr-of.c              |   13 +------------
 2 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 53f772b..d0286a5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -678,8 +678,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
 
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 5e51384..49c1da8 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
 	int err;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = devm_clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the component
index -- remove the "usb%d_clk" template and unconditionally use "per",
remove the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/usb/host/fsl-mph-dr-of.c              |   13 +------------
 2 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 53f772b..d0286a5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -678,8 +678,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
 
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 5e51384..49c1da8 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
 	int err;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = devm_clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 25/31] mtd: mpc5121_nfc: remove now obsolete clock lookup name
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the NAND flash
driver need no longer use the previous "nfc_clk" name but can switch to
the fixed "per" clock name -- adjust the peripheral driver and remove
the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/mtd/nand/mpc5121_nfc.c                |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index d0286a5..24e1706 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -677,7 +677,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
 
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 9c0b8fe..6a5f851 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -731,7 +731,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	clk = devm_clk_get(dev, "nfc_clk");
+	clk = devm_clk_get(dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
 		retval = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 25/31] mtd: mpc5121_nfc: remove now obsolete clock lookup name
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the NAND flash
driver need no longer use the previous "nfc_clk" name but can switch to
the fixed "per" clock name -- adjust the peripheral driver and remove
the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/mtd/nand/mpc5121_nfc.c                |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index d0286a5..24e1706 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -677,7 +677,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
 
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 9c0b8fe..6a5f851 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -731,7 +731,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	clk = devm_clk_get(dev, "nfc_clk");
+	clk = devm_clk_get(dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
 		retval = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 26/31] [media] fsl-viu: remove now obsolete clock lookup name
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the VIU driver
need no longer use the previous "viu_clk" name but can switch to the
fixed "per" clock name -- adjust the peripheral driver and remove the
clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/media/platform/fsl-viu.c              |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 24e1706..f047d4c 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -676,7 +676,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* clkdev registration for compatibility reasons */
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 48fced4..8a17433 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1578,7 +1578,7 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	clk = devm_clk_get(&op->dev, "viu_clk");
+	clk = devm_clk_get(&op->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&op->dev, "failed to lookup the clock!\n");
 		ret = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 26/31] [media] fsl-viu: remove now obsolete clock lookup name
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the VIU driver
need no longer use the previous "viu_clk" name but can switch to the
fixed "per" clock name -- adjust the peripheral driver and remove the
clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/media/platform/fsl-viu.c              |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 24e1706..f047d4c 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -676,7 +676,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* clkdev registration for compatibility reasons */
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 48fced4..8a17433 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1578,7 +1578,7 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	clk = devm_clk_get(&op->dev, "viu_clk");
+	clk = devm_clk_get(&op->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&op->dev, "failed to lookup the clock!\n");
 		ret = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
  2013-07-22 12:14       ` Gerhard Sittig
  (?)
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

implement a .get_clock() callback for the MPC512x platform which uses
the common clock infrastructure (eliminating direct access to the clock
control registers from within the CAN network driver), and provide the
corresponding .put_clock() callback to release resources after use

keep the previous implementation of MPC512x support in place during
migration, since common clock support is optional

this change is neutral to the MPC5200 platform

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index e59b3a3..4897929 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+	struct mscan_priv *priv;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = devm_clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		if (clk_prepare(clk_can)) {
+			devm_clk_put(&ofdev->dev, clk_can);
+			goto err_notavail;
+		}
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = devm_clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		if (clk_prepare(clk_can)) {
+			devm_clk_put(&ofdev->dev, clk_can);
+			goto err_notavail;
+		}
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+	struct mscan_priv *priv;
+
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	if (priv->clk_can) {
+		clk_unprepare(priv->clk_can);
+		devm_clk_put(&ofdev->dev, priv->clk_can);
+	}
+}
+
+#else	/* COMMON_CLK */
+
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -239,12 +400,18 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+
+#define mpc512x_can_put_clock NULL
+
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
 {
 	return 0;
 }
+#define mpc512x_can_put_clock NULL
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	/* .put_clock not applicable */
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

implement a .get_clock() callback for the MPC512x platform which uses
the common clock infrastructure (eliminating direct access to the clock
control registers from within the CAN network driver), and provide the
corresponding .put_clock() callback to release resources after use

keep the previous implementation of MPC512x support in place during
migration, since common clock support is optional

this change is neutral to the MPC5200 platform

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index e59b3a3..4897929 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+	struct mscan_priv *priv;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = devm_clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		if (clk_prepare(clk_can)) {
+			devm_clk_put(&ofdev->dev, clk_can);
+			goto err_notavail;
+		}
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = devm_clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		if (clk_prepare(clk_can)) {
+			devm_clk_put(&ofdev->dev, clk_can);
+			goto err_notavail;
+		}
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+	struct mscan_priv *priv;
+
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	if (priv->clk_can) {
+		clk_unprepare(priv->clk_can);
+		devm_clk_put(&ofdev->dev, priv->clk_can);
+	}
+}
+
+#else	/* COMMON_CLK */
+
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -239,12 +400,18 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+
+#define mpc512x_can_put_clock NULL
+
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
 {
 	return 0;
 }
+#define mpc512x_can_put_clock NULL
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	/* .put_clock not applicable */
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

implement a .get_clock() callback for the MPC512x platform which uses
the common clock infrastructure (eliminating direct access to the clock
control registers from within the CAN network driver), and provide the
corresponding .put_clock() callback to release resources after use

keep the previous implementation of MPC512x support in place during
migration, since common clock support is optional

this change is neutral to the MPC5200 platform

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index e59b3a3..4897929 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+	struct mscan_priv *priv;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = devm_clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		if (clk_prepare(clk_can)) {
+			devm_clk_put(&ofdev->dev, clk_can);
+			goto err_notavail;
+		}
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = devm_clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		if (clk_prepare(clk_can)) {
+			devm_clk_put(&ofdev->dev, clk_can);
+			goto err_notavail;
+		}
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
+	return 0;
+}
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+	struct mscan_priv *priv;
+
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	if (priv->clk_can) {
+		clk_unprepare(priv->clk_can);
+		devm_clk_put(&ofdev->dev, priv->clk_can);
+	}
+}
+
+#else	/* COMMON_CLK */
+
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -239,12 +400,18 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+
+#define mpc512x_can_put_clock NULL
+
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
 {
 	return 0;
 }
+#define mpc512x_can_put_clock NULL
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	/* .put_clock not applicable */
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 28/31] powerpc/mpc512x: improve DIU related clock setup
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index f047d4c..893fbe5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -696,7 +696,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 28/31] powerpc/mpc512x: improve DIU related clock setup
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

adapt the DIU clock initialization to the COMMON_CLK approach: device
tree based clock lookup, prepare and unprepare for clocks, work with
frequencies not dividers, call the appropriate clk_*() routines and
don't access CCM registers, remove the pre-enable workaround in the
platform's clock driver

the "best clock" determination now completely relies on the platform's
clock driver to pick a frequency close to what the caller requests, and
merely checks whether the desired frequency was met (is acceptable since
it meets the tolerance of the monitor) -- this approach shall succeed
upon first try in the usual case, will test a few less desirable yet
acceptable frequencies in edge cases, and will fallback to "best effort"
if none of the previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index f047d4c..893fbe5 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -696,7 +696,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 	/*
 	 * some have their individual clock subtree with separate clock
 	 * items and their individual enable counters, yet share a
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  2013-07-22 12:14       ` Gerhard Sittig
  (?)
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 30/31] net: can: mscan: remove non-common_clock code for MPC512x
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

transition to the common clock framework has completed and the PPC_CLOCK
is no longer available for the MPC512x platform, remove the now obsolete
code path of the mpc5xxx mscan driver which accessed clock control
module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  141 -----------------------------------
 1 file changed, 141 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 4897929..dd6bdaa 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,9 +109,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -267,144 +264,6 @@ static void mpc512x_can_put_clock(struct platform_device *ofdev)
 		devm_clk_put(&ofdev->dev, priv->clk_can);
 	}
 }
-
-#else	/* COMMON_CLK */
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-
-#define mpc512x_can_put_clock NULL
-
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 30/31] net: can: mscan: remove non-common_clock code for MPC512x
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

transition to the common clock framework has completed and the PPC_CLOCK
is no longer available for the MPC512x platform, remove the now obsolete
code path of the mpc5xxx mscan driver which accessed clock control
module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  141 -----------------------------------
 1 file changed, 141 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 4897929..dd6bdaa 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,9 +109,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -267,144 +264,6 @@ static void mpc512x_can_put_clock(struct platform_device *ofdev)
 		devm_clk_put(&ofdev->dev, priv->clk_can);
 	}
 }
-
-#else	/* COMMON_CLK */
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-
-#define mpc512x_can_put_clock NULL
-
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 31/31] clk: mpc512x: remove clkdev registration (sys/ref, header)
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:14         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

remove the last clkdev registration call ("sys_clk" and "ref_clk"
for mscan), as well as the clkdev header inclusion and the "compat
registration" comment

all client lookups for clock items are device tree based now, no
compatibility alias names need to get provided any longer

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 893fbe5..e9451a7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -673,10 +672,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* fixed frequency for AC97, always 24.567MHz */
 	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
 
-	/* clkdev registration for compatibility reasons */
-	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
 	pr_debug("derived PPC freq [%d]\n", freq);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v3 31/31] clk: mpc512x: remove clkdev registration (sys/ref, header)
@ 2013-07-22 12:14         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:14 UTC (permalink / raw)
  To: linux-arm-kernel

remove the last clkdev registration call ("sys_clk" and "ref_clk"
for mscan), as well as the clkdev header inclusion and the "compat
registration" comment

all client lookups for clock items are device tree based now, no
compatibility alias names need to get provided any longer

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 893fbe5..e9451a7 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -673,10 +672,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* fixed frequency for AC97, always 24.567MHz */
 	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
 
-	/* clkdev registration for compatibility reasons */
-	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-
 	pr_debug("clock tree setup complete\n");
 	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
 	pr_debug("derived PPC freq [%d]\n", freq);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 08/31] fs_enet: cleanup clock API use
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-07-22 12:28           ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 12:28 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 629 bytes --]

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> make the Freescale ethernet driver get, prepare and enable the FEC clock
> during probe(); disable, unprepare and put the clock upon remove(); hold
> a reference to the clock over the period of use; use devm_{get,put}_clk()

There's no need for devm_clk_put(), devm will take care of this.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

[-- Attachment #2: Type: text/plain, Size: 150 bytes --]

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

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 08/31] fs_enet: cleanup clock API use
@ 2013-07-22 12:28           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 12:28 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 629 bytes --]

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> make the Freescale ethernet driver get, prepare and enable the FEC clock
> during probe(); disable, unprepare and put the clock upon remove(); hold
> a reference to the clock over the period of use; use devm_{get,put}_clk()

There's no need for devm_clk_put(), devm will take care of this.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 08/31] fs_enet: cleanup clock API use
@ 2013-07-22 12:28           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> make the Freescale ethernet driver get, prepare and enable the FEC clock
> during probe(); disable, unprepare and put the clock upon remove(); hold
> a reference to the clock over the period of use; use devm_{get,put}_clk()

There's no need for devm_clk_put(), devm will take care of this.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130722/3ac63ea1/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 11/31] net: can: mscan: improve clock API use
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-07-22 12:31           ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 12:31 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 944 bytes --]

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities

looks good

> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> upon driver unload

fine

> assume that resources get prepared but not necessarily enabled in the
> setup phase, make the open() and close() callbacks of the CAN network
> device enable and disable a previously acquired and prepared clock

I think you should call prepare_enable and disable_unprepare in the
open/close functions.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

[-- Attachment #2: Type: text/plain, Size: 150 bytes --]

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

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-07-22 12:31           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 12:31 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 944 bytes --]

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities

looks good

> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> upon driver unload

fine

> assume that resources get prepared but not necessarily enabled in the
> setup phase, make the open() and close() callbacks of the CAN network
> device enable and disable a previously acquired and prepared clock

I think you should call prepare_enable and disable_unprepare in the
open/close functions.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-07-22 12:31           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 12:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities

looks good

> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> upon driver unload

fine

> assume that resources get prepared but not necessarily enabled in the
> setup phase, make the open() and close() callbacks of the CAN network
> device enable and disable a previously acquired and prepared clock

I think you should call prepare_enable and disable_unprepare in the
open/close functions.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130722/2eeb3687/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-07-22 12:33         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:33 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

[ manually added devicetree at vger now ]

On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> 
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
>   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
>   handle clocks (appropriately acquire and setup them, hold references
>   during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
>   Kconfig option) in the PowerPC based MPC512x platform, which brings
>   device tree based clock lookup as well

Haven't noticed before that the ozlabs device tree list started
actively rejecting reception.  And the scope of the series has
widened to include clock related fixes in many more drivers while
the initial submission only introduced CCF for MPC512x.

Shall I resend (with vger devicetree included and more subsystems
lists added)?  Which other lists to include without spamming too
many channels?  Poor moderators have to ACK messages for lists
that I'm not subscribed to.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-07-22 12:33         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-22 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

[ manually added devicetree at vger now ]

On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> 
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
>   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
>   handle clocks (appropriately acquire and setup them, hold references
>   during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
>   Kconfig option) in the PowerPC based MPC512x platform, which brings
>   device tree based clock lookup as well

Haven't noticed before that the ozlabs device tree list started
actively rejecting reception.  And the scope of the series has
widened to include clock related fixes in many more drivers while
the initial submission only introduced CCF for MPC512x.

Shall I resend (with vger devicetree included and more subsystems
lists added)?  Which other lists to include without spamming too
many channels?  Poor moderators have to ACK messages for lists
that I'm not subscribed to.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-07-22 13:04           ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 13:04 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Pantelis Antoniou, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 8266 bytes --]

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> implement a .get_clock() callback for the MPC512x platform which uses
> the common clock infrastructure (eliminating direct access to the clock
> control registers from within the CAN network driver), and provide the
> corresponding .put_clock() callback to release resources after use
> 
> keep the previous implementation of MPC512x support in place during
> migration, since common clock support is optional
> 
> this change is neutral to the MPC5200 platform
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index e59b3a3..4897929 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>  #endif /* CONFIG_PPC_MPC52xx */
>  
>  #ifdef CONFIG_PPC_MPC512x
> +
> +#if IS_ENABLED(CONFIG_COMMON_CLK)
> +
> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> +				 const char *clock_source, int *mscan_clksrc)
> +{
> +	struct device_node *np;
> +	u32 clockdiv;
> +	enum {
> +		CLK_FROM_AUTO,
> +		CLK_FROM_IPS,
> +		CLK_FROM_SYS,
> +		CLK_FROM_REF,
> +	} clk_from;
> +	struct clk *clk_in, *clk_can;
> +	unsigned long freq_calc;
> +	struct mscan_priv *priv;
> +
> +	/* the caller passed in the clock source spec that was read from
> +	 * the device tree, get the optional clock divider as well
> +	 */
> +	np = ofdev->dev.of_node;
> +	clockdiv = 1;
> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> +		clock_source ? clock_source : "<NULL>", clockdiv);
> +
> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> +	 * get set, and the 'ips' clock is the input to the MSCAN
> +	 * component
> +	 *
> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> +	 * bit needs to get cleared, an optional clock-divider may have
> +	 * been specified (the default value is 1), the appropriate
> +	 * MSCAN related MCLK is the input to the MSCAN component
> +	 *
> +	 * in the absence of a clock-source spec, first an optimal clock
> +	 * gets determined based on the 'sys' clock, if that fails the
> +	 * 'ref' clock is used
> +	 */
> +	clk_from = CLK_FROM_AUTO;
> +	if (clock_source) {
> +		/* interpret the device tree's spec for the clock source */
> +		if (!strcmp(clock_source, "ip"))
> +			clk_from = CLK_FROM_IPS;
> +		else if (!strcmp(clock_source, "sys"))
> +			clk_from = CLK_FROM_SYS;
> +		else if (!strcmp(clock_source, "ref"))
> +			clk_from = CLK_FROM_REF;
> +		else
> +			goto err_invalid;
> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, try the 'sys' clock; round to the
> +		 * next MHz and see if we can get a multiple of 16MHz
> +		 */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> +		clk_in = devm_clk_get(&ofdev->dev, "sys");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc +=  499999;
> +		freq_calc /= 1000000;
> +		freq_calc *= 1000000;
> +		if ((freq_calc % 16000000) == 0) {
> +			clk_from = CLK_FROM_SYS;
> +			clockdiv = freq_calc / 16000000;
> +			dev_dbg(&ofdev->dev,
> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> +				freq_calc, clockdiv, freq_calc / clockdiv);
> +		}
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, use the 'ref' clock */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> +		clk_in = devm_clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_from = CLK_FROM_REF;
> +		freq_calc = clk_get_rate(clk_in);
> +		dev_dbg(&ofdev->dev,
> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> +			freq_calc, freq_calc);
> +	}
> +
> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> +	 * setup the MCLK mux source and rate if applicable, apply the
> +	 * optionally specified or derived above divider, and determine
> +	 * the actual resulting clock rate to return to the caller
> +	 */
> +	switch (clk_from) {
> +	case CLK_FROM_IPS:
> +		clk_can = devm_clk_get(&ofdev->dev, "ips");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		if (clk_prepare(clk_can)) {

I would just call prepare_enable in the main mscan driver, then we don't
need a special "clock is prepared but not enabled" contract.

> +			devm_clk_put(&ofdev->dev, clk_can);

not needed, as this driver instance will fail, doesn't it?

> +			goto err_notavail;
> +		}
> +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +		priv->clk_can = clk_can;
> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	case CLK_FROM_SYS:
> +	case CLK_FROM_REF:
> +		clk_can = devm_clk_get(&ofdev->dev, "mclk");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		if (clk_prepare(clk_can)) {
> +			devm_clk_put(&ofdev->dev, clk_can);

same here

> +			goto err_notavail;
> +		}
> +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +		priv->clk_can = clk_can;
> +		if (clk_from == CLK_FROM_SYS)
> +			clk_in = devm_clk_get(&ofdev->dev, "sys");
> +		if (clk_from == CLK_FROM_REF)
> +			clk_in = devm_clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_set_parent(clk_can, clk_in);
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc /= clockdiv;
> +		clk_set_rate(clk_can, freq_calc);
> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> +		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	default:
> +		goto err_invalid;
> +	}
> +
> +	return freq_calc;
> +
> +err_invalid:
> +	dev_err(&ofdev->dev, "invalid clock source specification\n");
> +	return 0;

return 0 in case of error? Please add a comment what this 0 means here.
> +
> +err_notavail:
> +	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
> +	return 0;
> +}
> +
> +static void mpc512x_can_put_clock(struct platform_device *ofdev)
> +{
> +	struct mscan_priv *priv;
> +
> +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +	if (priv->clk_can) {
> +		clk_unprepare(priv->clk_can);
> +		devm_clk_put(&ofdev->dev, priv->clk_can);

devm_clk_put can be removed, it's called automatically.

> +	}
> +}
> +
> +#else	/* COMMON_CLK */
> +
>  struct mpc512x_clockctl {
>  	u32 spmr;		/* System PLL Mode Reg */
>  	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
> @@ -239,12 +400,18 @@ exit_put:
>  	of_node_put(np_clock);
>  	return freq;
>  }
> +
> +#define mpc512x_can_put_clock NULL
> +
> +#endif	/* COMMON_CLK */
> +
>  #else /* !CONFIG_PPC_MPC512x */
>  static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  				 const char *clock_name, int *mscan_clksrc)
>  {
>  	return 0;
>  }
> +#define mpc512x_can_put_clock NULL
>  #endif /* CONFIG_PPC_MPC512x */
>  
>  static const struct of_device_id mpc5xxx_can_table[];
> @@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
>  static const struct mpc5xxx_can_data mpc5200_can_data = {
>  	.type = MSCAN_TYPE_MPC5200,
>  	.get_clock = mpc52xx_can_get_clock,
> +	/* .put_clock not applicable */
>  };
>  
>  static const struct mpc5xxx_can_data mpc5121_can_data = {
>  	.type = MSCAN_TYPE_MPC5121,
>  	.get_clock = mpc512x_can_get_clock,
> +	.put_clock = mpc512x_can_put_clock,
>  };
>  
>  static const struct of_device_id mpc5xxx_can_table[] = {
> 

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-07-22 13:04           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 13:04 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 8266 bytes --]

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> implement a .get_clock() callback for the MPC512x platform which uses
> the common clock infrastructure (eliminating direct access to the clock
> control registers from within the CAN network driver), and provide the
> corresponding .put_clock() callback to release resources after use
> 
> keep the previous implementation of MPC512x support in place during
> migration, since common clock support is optional
> 
> this change is neutral to the MPC5200 platform
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index e59b3a3..4897929 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>  #endif /* CONFIG_PPC_MPC52xx */
>  
>  #ifdef CONFIG_PPC_MPC512x
> +
> +#if IS_ENABLED(CONFIG_COMMON_CLK)
> +
> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> +				 const char *clock_source, int *mscan_clksrc)
> +{
> +	struct device_node *np;
> +	u32 clockdiv;
> +	enum {
> +		CLK_FROM_AUTO,
> +		CLK_FROM_IPS,
> +		CLK_FROM_SYS,
> +		CLK_FROM_REF,
> +	} clk_from;
> +	struct clk *clk_in, *clk_can;
> +	unsigned long freq_calc;
> +	struct mscan_priv *priv;
> +
> +	/* the caller passed in the clock source spec that was read from
> +	 * the device tree, get the optional clock divider as well
> +	 */
> +	np = ofdev->dev.of_node;
> +	clockdiv = 1;
> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> +		clock_source ? clock_source : "<NULL>", clockdiv);
> +
> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> +	 * get set, and the 'ips' clock is the input to the MSCAN
> +	 * component
> +	 *
> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> +	 * bit needs to get cleared, an optional clock-divider may have
> +	 * been specified (the default value is 1), the appropriate
> +	 * MSCAN related MCLK is the input to the MSCAN component
> +	 *
> +	 * in the absence of a clock-source spec, first an optimal clock
> +	 * gets determined based on the 'sys' clock, if that fails the
> +	 * 'ref' clock is used
> +	 */
> +	clk_from = CLK_FROM_AUTO;
> +	if (clock_source) {
> +		/* interpret the device tree's spec for the clock source */
> +		if (!strcmp(clock_source, "ip"))
> +			clk_from = CLK_FROM_IPS;
> +		else if (!strcmp(clock_source, "sys"))
> +			clk_from = CLK_FROM_SYS;
> +		else if (!strcmp(clock_source, "ref"))
> +			clk_from = CLK_FROM_REF;
> +		else
> +			goto err_invalid;
> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, try the 'sys' clock; round to the
> +		 * next MHz and see if we can get a multiple of 16MHz
> +		 */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> +		clk_in = devm_clk_get(&ofdev->dev, "sys");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc +=  499999;
> +		freq_calc /= 1000000;
> +		freq_calc *= 1000000;
> +		if ((freq_calc % 16000000) == 0) {
> +			clk_from = CLK_FROM_SYS;
> +			clockdiv = freq_calc / 16000000;
> +			dev_dbg(&ofdev->dev,
> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> +				freq_calc, clockdiv, freq_calc / clockdiv);
> +		}
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, use the 'ref' clock */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> +		clk_in = devm_clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_from = CLK_FROM_REF;
> +		freq_calc = clk_get_rate(clk_in);
> +		dev_dbg(&ofdev->dev,
> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> +			freq_calc, freq_calc);
> +	}
> +
> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> +	 * setup the MCLK mux source and rate if applicable, apply the
> +	 * optionally specified or derived above divider, and determine
> +	 * the actual resulting clock rate to return to the caller
> +	 */
> +	switch (clk_from) {
> +	case CLK_FROM_IPS:
> +		clk_can = devm_clk_get(&ofdev->dev, "ips");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		if (clk_prepare(clk_can)) {

I would just call prepare_enable in the main mscan driver, then we don't
need a special "clock is prepared but not enabled" contract.

> +			devm_clk_put(&ofdev->dev, clk_can);

not needed, as this driver instance will fail, doesn't it?

> +			goto err_notavail;
> +		}
> +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +		priv->clk_can = clk_can;
> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	case CLK_FROM_SYS:
> +	case CLK_FROM_REF:
> +		clk_can = devm_clk_get(&ofdev->dev, "mclk");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		if (clk_prepare(clk_can)) {
> +			devm_clk_put(&ofdev->dev, clk_can);

same here

> +			goto err_notavail;
> +		}
> +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +		priv->clk_can = clk_can;
> +		if (clk_from == CLK_FROM_SYS)
> +			clk_in = devm_clk_get(&ofdev->dev, "sys");
> +		if (clk_from == CLK_FROM_REF)
> +			clk_in = devm_clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_set_parent(clk_can, clk_in);
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc /= clockdiv;
> +		clk_set_rate(clk_can, freq_calc);
> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> +		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	default:
> +		goto err_invalid;
> +	}
> +
> +	return freq_calc;
> +
> +err_invalid:
> +	dev_err(&ofdev->dev, "invalid clock source specification\n");
> +	return 0;

return 0 in case of error? Please add a comment what this 0 means here.
> +
> +err_notavail:
> +	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
> +	return 0;
> +}
> +
> +static void mpc512x_can_put_clock(struct platform_device *ofdev)
> +{
> +	struct mscan_priv *priv;
> +
> +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +	if (priv->clk_can) {
> +		clk_unprepare(priv->clk_can);
> +		devm_clk_put(&ofdev->dev, priv->clk_can);

devm_clk_put can be removed, it's called automatically.

> +	}
> +}
> +
> +#else	/* COMMON_CLK */
> +
>  struct mpc512x_clockctl {
>  	u32 spmr;		/* System PLL Mode Reg */
>  	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
> @@ -239,12 +400,18 @@ exit_put:
>  	of_node_put(np_clock);
>  	return freq;
>  }
> +
> +#define mpc512x_can_put_clock NULL
> +
> +#endif	/* COMMON_CLK */
> +
>  #else /* !CONFIG_PPC_MPC512x */
>  static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  				 const char *clock_name, int *mscan_clksrc)
>  {
>  	return 0;
>  }
> +#define mpc512x_can_put_clock NULL
>  #endif /* CONFIG_PPC_MPC512x */
>  
>  static const struct of_device_id mpc5xxx_can_table[];
> @@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
>  static const struct mpc5xxx_can_data mpc5200_can_data = {
>  	.type = MSCAN_TYPE_MPC5200,
>  	.get_clock = mpc52xx_can_get_clock,
> +	/* .put_clock not applicable */
>  };
>  
>  static const struct mpc5xxx_can_data mpc5121_can_data = {
>  	.type = MSCAN_TYPE_MPC5121,
>  	.get_clock = mpc512x_can_get_clock,
> +	.put_clock = mpc512x_can_put_clock,
>  };
>  
>  static const struct of_device_id mpc5xxx_can_table[] = {
> 

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-07-22 13:04           ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> implement a .get_clock() callback for the MPC512x platform which uses
> the common clock infrastructure (eliminating direct access to the clock
> control registers from within the CAN network driver), and provide the
> corresponding .put_clock() callback to release resources after use
> 
> keep the previous implementation of MPC512x support in place during
> migration, since common clock support is optional
> 
> this change is neutral to the MPC5200 platform
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index e59b3a3..4897929 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
>  #endif /* CONFIG_PPC_MPC52xx */
>  
>  #ifdef CONFIG_PPC_MPC512x
> +
> +#if IS_ENABLED(CONFIG_COMMON_CLK)
> +
> +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> +				 const char *clock_source, int *mscan_clksrc)
> +{
> +	struct device_node *np;
> +	u32 clockdiv;
> +	enum {
> +		CLK_FROM_AUTO,
> +		CLK_FROM_IPS,
> +		CLK_FROM_SYS,
> +		CLK_FROM_REF,
> +	} clk_from;
> +	struct clk *clk_in, *clk_can;
> +	unsigned long freq_calc;
> +	struct mscan_priv *priv;
> +
> +	/* the caller passed in the clock source spec that was read from
> +	 * the device tree, get the optional clock divider as well
> +	 */
> +	np = ofdev->dev.of_node;
> +	clockdiv = 1;
> +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> +		clock_source ? clock_source : "<NULL>", clockdiv);
> +
> +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> +	 * get set, and the 'ips' clock is the input to the MSCAN
> +	 * component
> +	 *
> +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> +	 * bit needs to get cleared, an optional clock-divider may have
> +	 * been specified (the default value is 1), the appropriate
> +	 * MSCAN related MCLK is the input to the MSCAN component
> +	 *
> +	 * in the absence of a clock-source spec, first an optimal clock
> +	 * gets determined based on the 'sys' clock, if that fails the
> +	 * 'ref' clock is used
> +	 */
> +	clk_from = CLK_FROM_AUTO;
> +	if (clock_source) {
> +		/* interpret the device tree's spec for the clock source */
> +		if (!strcmp(clock_source, "ip"))
> +			clk_from = CLK_FROM_IPS;
> +		else if (!strcmp(clock_source, "sys"))
> +			clk_from = CLK_FROM_SYS;
> +		else if (!strcmp(clock_source, "ref"))
> +			clk_from = CLK_FROM_REF;
> +		else
> +			goto err_invalid;
> +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, try the 'sys' clock; round to the
> +		 * next MHz and see if we can get a multiple of 16MHz
> +		 */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> +		clk_in = devm_clk_get(&ofdev->dev, "sys");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc +=  499999;
> +		freq_calc /= 1000000;
> +		freq_calc *= 1000000;
> +		if ((freq_calc % 16000000) == 0) {
> +			clk_from = CLK_FROM_SYS;
> +			clockdiv = freq_calc / 16000000;
> +			dev_dbg(&ofdev->dev,
> +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> +				freq_calc, clockdiv, freq_calc / clockdiv);
> +		}
> +	}
> +	if (clk_from == CLK_FROM_AUTO) {
> +		/* no spec so far, use the 'ref' clock */
> +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> +		clk_in = devm_clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_from = CLK_FROM_REF;
> +		freq_calc = clk_get_rate(clk_in);
> +		dev_dbg(&ofdev->dev,
> +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> +			freq_calc, freq_calc);
> +	}
> +
> +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> +	 * setup the MCLK mux source and rate if applicable, apply the
> +	 * optionally specified or derived above divider, and determine
> +	 * the actual resulting clock rate to return to the caller
> +	 */
> +	switch (clk_from) {
> +	case CLK_FROM_IPS:
> +		clk_can = devm_clk_get(&ofdev->dev, "ips");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		if (clk_prepare(clk_can)) {

I would just call prepare_enable in the main mscan driver, then we don't
need a special "clock is prepared but not enabled" contract.

> +			devm_clk_put(&ofdev->dev, clk_can);

not needed, as this driver instance will fail, doesn't it?

> +			goto err_notavail;
> +		}
> +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +		priv->clk_can = clk_can;
> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	case CLK_FROM_SYS:
> +	case CLK_FROM_REF:
> +		clk_can = devm_clk_get(&ofdev->dev, "mclk");
> +		if (IS_ERR(clk_can))
> +			goto err_notavail;
> +		if (clk_prepare(clk_can)) {
> +			devm_clk_put(&ofdev->dev, clk_can);

same here

> +			goto err_notavail;
> +		}
> +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +		priv->clk_can = clk_can;
> +		if (clk_from == CLK_FROM_SYS)
> +			clk_in = devm_clk_get(&ofdev->dev, "sys");
> +		if (clk_from == CLK_FROM_REF)
> +			clk_in = devm_clk_get(&ofdev->dev, "ref");
> +		if (IS_ERR(clk_in))
> +			goto err_notavail;
> +		clk_set_parent(clk_can, clk_in);
> +		freq_calc = clk_get_rate(clk_in);
> +		freq_calc /= clockdiv;
> +		clk_set_rate(clk_can, freq_calc);
> +		freq_calc = clk_get_rate(clk_can);
> +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> +		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
> +			*mscan_clksrc, freq_calc);
> +		break;
> +	default:
> +		goto err_invalid;
> +	}
> +
> +	return freq_calc;
> +
> +err_invalid:
> +	dev_err(&ofdev->dev, "invalid clock source specification\n");
> +	return 0;

return 0 in case of error? Please add a comment what this 0 means here.
> +
> +err_notavail:
> +	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
> +	return 0;
> +}
> +
> +static void mpc512x_can_put_clock(struct platform_device *ofdev)
> +{
> +	struct mscan_priv *priv;
> +
> +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> +	if (priv->clk_can) {
> +		clk_unprepare(priv->clk_can);
> +		devm_clk_put(&ofdev->dev, priv->clk_can);

devm_clk_put can be removed, it's called automatically.

> +	}
> +}
> +
> +#else	/* COMMON_CLK */
> +
>  struct mpc512x_clockctl {
>  	u32 spmr;		/* System PLL Mode Reg */
>  	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
> @@ -239,12 +400,18 @@ exit_put:
>  	of_node_put(np_clock);
>  	return freq;
>  }
> +
> +#define mpc512x_can_put_clock NULL
> +
> +#endif	/* COMMON_CLK */
> +
>  #else /* !CONFIG_PPC_MPC512x */
>  static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  				 const char *clock_name, int *mscan_clksrc)
>  {
>  	return 0;
>  }
> +#define mpc512x_can_put_clock NULL
>  #endif /* CONFIG_PPC_MPC512x */
>  
>  static const struct of_device_id mpc5xxx_can_table[];
> @@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
>  static const struct mpc5xxx_can_data mpc5200_can_data = {
>  	.type = MSCAN_TYPE_MPC5200,
>  	.get_clock = mpc52xx_can_get_clock,
> +	/* .put_clock not applicable */
>  };
>  
>  static const struct mpc5xxx_can_data mpc5121_can_data = {
>  	.type = MSCAN_TYPE_MPC5121,
>  	.get_clock = mpc512x_can_get_clock,
> +	.put_clock = mpc512x_can_put_clock,
>  };
>  
>  static const struct of_device_id mpc5xxx_can_table[] = {
> 

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130722/62e0a5f8/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-07-22 14:09           ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-22 14:09 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Pantelis Antoniou,
	Anatolij Gustschin, linuxppc-dev, linux-arm-kernel,
	Mauro Carvalho Chehab


[-- Attachment #1.1: Type: text/plain, Size: 278 bytes --]

On Mon, Jul 22, 2013 at 02:14:28PM +0200, Gerhard Sittig wrote:

> +	ret = clk_prepare_enable(clk);
> +	if (ret) {
> +		devm_clk_put(dev, clk);
> +		goto free_irq;

The main point of the devm_ APIs is to avoid the need for explicit
freeing so you should just remove these puts.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
@ 2013-07-22 14:09           ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-22 14:09 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 278 bytes --]

On Mon, Jul 22, 2013 at 02:14:28PM +0200, Gerhard Sittig wrote:

> +	ret = clk_prepare_enable(clk);
> +	if (ret) {
> +		devm_clk_put(dev, clk);
> +		goto free_irq;

The main point of the devm_ APIs is to avoid the need for explicit
freeing so you should just remove these puts.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
@ 2013-07-22 14:09           ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-07-22 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 22, 2013 at 02:14:28PM +0200, Gerhard Sittig wrote:

> +	ret = clk_prepare_enable(clk);
> +	if (ret) {
> +		devm_clk_put(dev, clk);
> +		goto free_irq;

The main point of the devm_ APIs is to avoid the need for explicit
freeing so you should just remove these puts.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130722/d3cc5152/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 11/31] net: can: mscan: improve clock API use
  2013-07-22 12:31           ` Marc Kleine-Budde
@ 2013-07-23 11:53             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 11:53 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, David Woodhouse,
	devicetree-discuss, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
> 
> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> > the .get_clock() callback is run from probe() and might allocate
> > resources, introduce a .put_clock() callback that is run from remove()
> > to undo any allocation activities
> 
> looks good
> 
> > use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> > upon driver unload
> 
> fine
> 
> > assume that resources get prepared but not necessarily enabled in the
> > setup phase, make the open() and close() callbacks of the CAN network
> > device enable and disable a previously acquired and prepared clock
> 
> I think you should call prepare_enable and disable_unprepare in the
> open/close functions.

After more local research, which totally eliminated the need to
pre-enable the CAN related clocks, but might need more discussion
as it touches the common gate support, I've learned something
more:

The CAN clock needs to get enabled during probe() already, since
registers get accessed between probe() for the driver and open()
for the network device -- while access to peripheral registers
crashes the kernel when clocks still are disabled (other hardware
may just hang or provide fake data, neither of this is OK).

But I see the point in your suggestion to prepare _and_ enable
the clock during open() as well -- to have open() cope with
whatever probe() did, after all the driver is shared among
platforms, which may differ in what they do during probe().

So I will:
- make open() of the network device prepare _and_ enable the
  clock for the peripheral (if acquired during probe())
- adjust open() because ATM it leaves the clock enabled when the
  network device operation fails (the error path is incomplete in
  v3)
- make the MPC512x specific probe() time .get_clock() routine not
  just prepare but enable the clock as well
- and of course address all the shutdown counter parts of the
  above setup paths

This results in:
- specific chip drivers only need to balance their private get
  and put clock routines which are called from probe and remove,
  common paths DTRT for all of them
- correct operation for MPC512x, where common clock is used
- still everything is neutral for MPC5200 where common clock
  isn't used, behaviour is identical to before the change
- no assumptions are made about what occurs or doesn't occur
  during probe(), when the network device is used then the clock
  is fully setup and operational
- when the CAN network device isn't setup (because device tree
  doesn't describe it, or disables that node), then its clock
  remains idle (neither gets setup nor enabled)
- complete preparation for future improvement wrt power
  consumption, where potential changes remain isolated to the
  specific chip (probe() time setup, get_clock() routine) while
  the ndo part need not get touched any more

So this is the most appropriate approach I can come up with.


Removing unnecessary devm_put_clk() calls is orthogonal to that.
Putting these in isn't totally wrong (they won't harm, and they
do signal "visual balance" more clearly such that the next person
won't stop and wonder), but it's true that they are redundant.
"Trained persons" will wonder as much about their presence as
untrained persons wonder about their absence. :)  Apparently I'm
not well trained yet.

I thought that being explicit and cautious would be good, but the
feedback I got suggests that encoding unnecessary instructions
isn't desirable.  So I will remove those devm_put_clk() in v4.

To save us one more iteration, shall I remove those calls only
from error paths during setup?  Or shall I remove them from
regular shutdown paths as well?  How much pain does the community
feel with harmless yet unnecessary instructions? :)


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-07-23 11:53             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 11:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
> 
> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> > the .get_clock() callback is run from probe() and might allocate
> > resources, introduce a .put_clock() callback that is run from remove()
> > to undo any allocation activities
> 
> looks good
> 
> > use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> > upon driver unload
> 
> fine
> 
> > assume that resources get prepared but not necessarily enabled in the
> > setup phase, make the open() and close() callbacks of the CAN network
> > device enable and disable a previously acquired and prepared clock
> 
> I think you should call prepare_enable and disable_unprepare in the
> open/close functions.

After more local research, which totally eliminated the need to
pre-enable the CAN related clocks, but might need more discussion
as it touches the common gate support, I've learned something
more:

The CAN clock needs to get enabled during probe() already, since
registers get accessed between probe() for the driver and open()
for the network device -- while access to peripheral registers
crashes the kernel when clocks still are disabled (other hardware
may just hang or provide fake data, neither of this is OK).

But I see the point in your suggestion to prepare _and_ enable
the clock during open() as well -- to have open() cope with
whatever probe() did, after all the driver is shared among
platforms, which may differ in what they do during probe().

So I will:
- make open() of the network device prepare _and_ enable the
  clock for the peripheral (if acquired during probe())
- adjust open() because ATM it leaves the clock enabled when the
  network device operation fails (the error path is incomplete in
  v3)
- make the MPC512x specific probe() time .get_clock() routine not
  just prepare but enable the clock as well
- and of course address all the shutdown counter parts of the
  above setup paths

This results in:
- specific chip drivers only need to balance their private get
  and put clock routines which are called from probe and remove,
  common paths DTRT for all of them
- correct operation for MPC512x, where common clock is used
- still everything is neutral for MPC5200 where common clock
  isn't used, behaviour is identical to before the change
- no assumptions are made about what occurs or doesn't occur
  during probe(), when the network device is used then the clock
  is fully setup and operational
- when the CAN network device isn't setup (because device tree
  doesn't describe it, or disables that node), then its clock
  remains idle (neither gets setup nor enabled)
- complete preparation for future improvement wrt power
  consumption, where potential changes remain isolated to the
  specific chip (probe() time setup, get_clock() routine) while
  the ndo part need not get touched any more

So this is the most appropriate approach I can come up with.


Removing unnecessary devm_put_clk() calls is orthogonal to that.
Putting these in isn't totally wrong (they won't harm, and they
do signal "visual balance" more clearly such that the next person
won't stop and wonder), but it's true that they are redundant.
"Trained persons" will wonder as much about their presence as
untrained persons wonder about their absence. :)  Apparently I'm
not well trained yet.

I thought that being explicit and cautious would be good, but the
feedback I got suggests that encoding unnecessary instructions
isn't desirable.  So I will remove those devm_put_clk() in v4.

To save us one more iteration, shall I remove those calls only
from error paths during setup?  Or shall I remove them from
regular shutdown paths as well?  How much pain does the community
feel with harmless yet unnecessary instructions? :)


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
  2013-07-22 14:09           ` Mark Brown
@ 2013-07-23 11:58             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 11:58 UTC (permalink / raw)
  To: Mark Brown
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	Greg Kroah-Hartman, linuxppc-dev, Rob Herring, Marc Kleine-Budde,
	linux-arm-kernel, Anatolij Gustschin, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

[ devicetree@vger adjusted ]

On Mon, Jul 22, 2013 at 15:09 +0100, Mark Brown wrote:
> 
> On Mon, Jul 22, 2013 at 02:14:28PM +0200, Gerhard Sittig wrote:
> 
> > +	ret = clk_prepare_enable(clk);
> > +	if (ret) {
> > +		devm_clk_put(dev, clk);
> > +		goto free_irq;
> 
> The main point of the devm_ APIs is to avoid the need for explicit
> freeing so you should just remove these puts.

OK, will do in v4.

Shall these get removed everywhere including regular shutdown
paths, or just from error paths during setup?

[ the same topic came up for the CAN patch, might answer there ]


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 01/31] spi: mpc512x: cleanup clock API use
@ 2013-07-23 11:58             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 11:58 UTC (permalink / raw)
  To: linux-arm-kernel

[ devicetree at vger adjusted ]

On Mon, Jul 22, 2013 at 15:09 +0100, Mark Brown wrote:
> 
> On Mon, Jul 22, 2013 at 02:14:28PM +0200, Gerhard Sittig wrote:
> 
> > +	ret = clk_prepare_enable(clk);
> > +	if (ret) {
> > +		devm_clk_put(dev, clk);
> > +		goto free_irq;
> 
> The main point of the devm_ APIs is to avoid the need for explicit
> freeing so you should just remove these puts.

OK, will do in v4.

Shall these get removed everywhere including regular shutdown
paths, or just from error paths during setup?

[ the same topic came up for the CAN patch, might answer there ]


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
  2013-07-22 13:04           ` Marc Kleine-Budde
@ 2013-07-23 12:07             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 12:07 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[ adjusted devtree to use the vger address ]

On Mon, Jul 22, 2013 at 15:04 +0200, Marc Kleine-Budde wrote:
> 
> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> > implement a .get_clock() callback for the MPC512x platform which uses
> > the common clock infrastructure (eliminating direct access to the clock
> > control registers from within the CAN network driver), and provide the
> > corresponding .put_clock() callback to release resources after use
> > 
> > keep the previous implementation of MPC512x support in place during
> > migration, since common clock support is optional
> > 
> > this change is neutral to the MPC5200 platform
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 169 insertions(+)
> > 
> > diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> > index e59b3a3..4897929 100644
> > --- a/drivers/net/can/mscan/mpc5xxx_can.c
> > +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> > @@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
> >  #endif /* CONFIG_PPC_MPC52xx */
> >  
> >  #ifdef CONFIG_PPC_MPC512x
> > +
> > +#if IS_ENABLED(CONFIG_COMMON_CLK)
> > +
> > +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> > +				 const char *clock_source, int *mscan_clksrc)
> > +{
> > +	struct device_node *np;
> > +	u32 clockdiv;
> > +	enum {
> > +		CLK_FROM_AUTO,
> > +		CLK_FROM_IPS,
> > +		CLK_FROM_SYS,
> > +		CLK_FROM_REF,
> > +	} clk_from;
> > +	struct clk *clk_in, *clk_can;
> > +	unsigned long freq_calc;
> > +	struct mscan_priv *priv;
> > +
> > +	/* the caller passed in the clock source spec that was read from
> > +	 * the device tree, get the optional clock divider as well
> > +	 */
> > +	np = ofdev->dev.of_node;
> > +	clockdiv = 1;
> > +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> > +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> > +		clock_source ? clock_source : "<NULL>", clockdiv);
> > +
> > +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> > +	 * get set, and the 'ips' clock is the input to the MSCAN
> > +	 * component
> > +	 *
> > +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> > +	 * bit needs to get cleared, an optional clock-divider may have
> > +	 * been specified (the default value is 1), the appropriate
> > +	 * MSCAN related MCLK is the input to the MSCAN component
> > +	 *
> > +	 * in the absence of a clock-source spec, first an optimal clock
> > +	 * gets determined based on the 'sys' clock, if that fails the
> > +	 * 'ref' clock is used
> > +	 */
> > +	clk_from = CLK_FROM_AUTO;
> > +	if (clock_source) {
> > +		/* interpret the device tree's spec for the clock source */
> > +		if (!strcmp(clock_source, "ip"))
> > +			clk_from = CLK_FROM_IPS;
> > +		else if (!strcmp(clock_source, "sys"))
> > +			clk_from = CLK_FROM_SYS;
> > +		else if (!strcmp(clock_source, "ref"))
> > +			clk_from = CLK_FROM_REF;
> > +		else
> > +			goto err_invalid;
> > +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, try the 'sys' clock; round to the
> > +		 * next MHz and see if we can get a multiple of 16MHz
> > +		 */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> > +		clk_in = devm_clk_get(&ofdev->dev, "sys");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc +=  499999;
> > +		freq_calc /= 1000000;
> > +		freq_calc *= 1000000;
> > +		if ((freq_calc % 16000000) == 0) {
> > +			clk_from = CLK_FROM_SYS;
> > +			clockdiv = freq_calc / 16000000;
> > +			dev_dbg(&ofdev->dev,
> > +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> > +				freq_calc, clockdiv, freq_calc / clockdiv);
> > +		}
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, use the 'ref' clock */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> > +		clk_in = devm_clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_from = CLK_FROM_REF;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		dev_dbg(&ofdev->dev,
> > +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> > +			freq_calc, freq_calc);
> > +	}
> > +
> > +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> > +	 * setup the MCLK mux source and rate if applicable, apply the
> > +	 * optionally specified or derived above divider, and determine
> > +	 * the actual resulting clock rate to return to the caller
> > +	 */
> > +	switch (clk_from) {
> > +	case CLK_FROM_IPS:
> > +		clk_can = devm_clk_get(&ofdev->dev, "ips");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		if (clk_prepare(clk_can)) {
> 
> I would just call prepare_enable in the main mscan driver, then we don't
> need a special "clock is prepared but not enabled" contract.

Yes, I addressed this concern (although differently after
learning more from a local test setup), see the other reply for
the CAN driver adjustment for clock API use.

> 
> > +			devm_clk_put(&ofdev->dev, clk_can);
> 
> not needed, as this driver instance will fail, doesn't it?

This is discussed in the other subthread as well.  The only
remaining question is how many of them to remove, before I'll
update the series.

> > +			goto err_notavail;
> > +		}
> > +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> > +		priv->clk_can = clk_can;
> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> > +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	case CLK_FROM_SYS:
> > +	case CLK_FROM_REF:
> > +		clk_can = devm_clk_get(&ofdev->dev, "mclk");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		if (clk_prepare(clk_can)) {
> > +			devm_clk_put(&ofdev->dev, clk_can);
> 
> same here
> 
> > +			goto err_notavail;
> > +		}
> > +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> > +		priv->clk_can = clk_can;
> > +		if (clk_from == CLK_FROM_SYS)
> > +			clk_in = devm_clk_get(&ofdev->dev, "sys");
> > +		if (clk_from == CLK_FROM_REF)
> > +			clk_in = devm_clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_set_parent(clk_can, clk_in);
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc /= clockdiv;
> > +		clk_set_rate(clk_can, freq_calc);
> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> > +		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	default:
> > +		goto err_invalid;
> > +	}
> > +
> > +	return freq_calc;
> > +
> > +err_invalid:
> > +	dev_err(&ofdev->dev, "invalid clock source specification\n");
> > +	return 0;
> 
> return 0 in case of error? Please add a comment what this 0 means here.

The .get_clock() callback is supposed to return the resulting
rate after the clock source was determined and the clock subtree
was setup.  It wasn't (explicitly) documented before (in the
non-common-clock case), so I did not bother to comment it in the
parallel common-clock case.

But it's true that returning zero in the error case may be
unexpected, and I will add a comment in v4 (in all the
.get_clock() implementations).

> > +
> > +err_notavail:
> > +	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
> > +	return 0;
> > +}
> > +
> > +static void mpc512x_can_put_clock(struct platform_device *ofdev)
> > +{
> > +	struct mscan_priv *priv;
> > +
> > +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> > +	if (priv->clk_can) {
> > +		clk_unprepare(priv->clk_can);
> > +		devm_clk_put(&ofdev->dev, priv->clk_can);
> 
> devm_clk_put can be removed, it's called automatically.
> 
> > +	}
> > +}
> > +
> > +#else	/* COMMON_CLK */
> > +
> >  struct mpc512x_clockctl {
> >  	u32 spmr;		/* System PLL Mode Reg */
> >  	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
> > @@ -239,12 +400,18 @@ exit_put:
> >  	of_node_put(np_clock);
> >  	return freq;
> >  }
> > +
> > +#define mpc512x_can_put_clock NULL
> > +
> > +#endif	/* COMMON_CLK */
> > +
> >  #else /* !CONFIG_PPC_MPC512x */
> >  static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> >  				 const char *clock_name, int *mscan_clksrc)
> >  {
> >  	return 0;
> >  }
> > +#define mpc512x_can_put_clock NULL
> >  #endif /* CONFIG_PPC_MPC512x */
> >  
> >  static const struct of_device_id mpc5xxx_can_table[];
> > @@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
> >  static const struct mpc5xxx_can_data mpc5200_can_data = {
> >  	.type = MSCAN_TYPE_MPC5200,
> >  	.get_clock = mpc52xx_can_get_clock,
> > +	/* .put_clock not applicable */
> >  };
> >  
> >  static const struct mpc5xxx_can_data mpc5121_can_data = {
> >  	.type = MSCAN_TYPE_MPC5121,
> >  	.get_clock = mpc512x_can_get_clock,
> > +	.put_clock = mpc512x_can_put_clock,
> >  };
> >  
> >  static const struct of_device_id mpc5xxx_can_table[] = {
> > 
> 
> Marc

Thank you for the fast and detailled review.  It's very much
appreciated.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-07-23 12:07             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

[ adjusted devtree to use the vger address ]

On Mon, Jul 22, 2013 at 15:04 +0200, Marc Kleine-Budde wrote:
> 
> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> > implement a .get_clock() callback for the MPC512x platform which uses
> > the common clock infrastructure (eliminating direct access to the clock
> > control registers from within the CAN network driver), and provide the
> > corresponding .put_clock() callback to release resources after use
> > 
> > keep the previous implementation of MPC512x support in place during
> > migration, since common clock support is optional
> > 
> > this change is neutral to the MPC5200 platform
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  drivers/net/can/mscan/mpc5xxx_can.c |  169 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 169 insertions(+)
> > 
> > diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> > index e59b3a3..4897929 100644
> > --- a/drivers/net/can/mscan/mpc5xxx_can.c
> > +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> > @@ -109,6 +109,167 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
> >  #endif /* CONFIG_PPC_MPC52xx */
> >  
> >  #ifdef CONFIG_PPC_MPC512x
> > +
> > +#if IS_ENABLED(CONFIG_COMMON_CLK)
> > +
> > +static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> > +				 const char *clock_source, int *mscan_clksrc)
> > +{
> > +	struct device_node *np;
> > +	u32 clockdiv;
> > +	enum {
> > +		CLK_FROM_AUTO,
> > +		CLK_FROM_IPS,
> > +		CLK_FROM_SYS,
> > +		CLK_FROM_REF,
> > +	} clk_from;
> > +	struct clk *clk_in, *clk_can;
> > +	unsigned long freq_calc;
> > +	struct mscan_priv *priv;
> > +
> > +	/* the caller passed in the clock source spec that was read from
> > +	 * the device tree, get the optional clock divider as well
> > +	 */
> > +	np = ofdev->dev.of_node;
> > +	clockdiv = 1;
> > +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
> > +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
> > +		clock_source ? clock_source : "<NULL>", clockdiv);
> > +
> > +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
> > +	 * get set, and the 'ips' clock is the input to the MSCAN
> > +	 * component
> > +	 *
> > +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
> > +	 * bit needs to get cleared, an optional clock-divider may have
> > +	 * been specified (the default value is 1), the appropriate
> > +	 * MSCAN related MCLK is the input to the MSCAN component
> > +	 *
> > +	 * in the absence of a clock-source spec, first an optimal clock
> > +	 * gets determined based on the 'sys' clock, if that fails the
> > +	 * 'ref' clock is used
> > +	 */
> > +	clk_from = CLK_FROM_AUTO;
> > +	if (clock_source) {
> > +		/* interpret the device tree's spec for the clock source */
> > +		if (!strcmp(clock_source, "ip"))
> > +			clk_from = CLK_FROM_IPS;
> > +		else if (!strcmp(clock_source, "sys"))
> > +			clk_from = CLK_FROM_SYS;
> > +		else if (!strcmp(clock_source, "ref"))
> > +			clk_from = CLK_FROM_REF;
> > +		else
> > +			goto err_invalid;
> > +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, try the 'sys' clock; round to the
> > +		 * next MHz and see if we can get a multiple of 16MHz
> > +		 */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
> > +		clk_in = devm_clk_get(&ofdev->dev, "sys");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc +=  499999;
> > +		freq_calc /= 1000000;
> > +		freq_calc *= 1000000;
> > +		if ((freq_calc % 16000000) == 0) {
> > +			clk_from = CLK_FROM_SYS;
> > +			clockdiv = freq_calc / 16000000;
> > +			dev_dbg(&ofdev->dev,
> > +				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
> > +				freq_calc, clockdiv, freq_calc / clockdiv);
> > +		}
> > +	}
> > +	if (clk_from == CLK_FROM_AUTO) {
> > +		/* no spec so far, use the 'ref' clock */
> > +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
> > +		clk_in = devm_clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_from = CLK_FROM_REF;
> > +		freq_calc = clk_get_rate(clk_in);
> > +		dev_dbg(&ofdev->dev,
> > +			"clk fit, ref[%lu] (no div) freq[%lu]\n",
> > +			freq_calc, freq_calc);
> > +	}
> > +
> > +	/* select IPS or MCLK as the MSCAN input (returned to the caller),
> > +	 * setup the MCLK mux source and rate if applicable, apply the
> > +	 * optionally specified or derived above divider, and determine
> > +	 * the actual resulting clock rate to return to the caller
> > +	 */
> > +	switch (clk_from) {
> > +	case CLK_FROM_IPS:
> > +		clk_can = devm_clk_get(&ofdev->dev, "ips");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		if (clk_prepare(clk_can)) {
> 
> I would just call prepare_enable in the main mscan driver, then we don't
> need a special "clock is prepared but not enabled" contract.

Yes, I addressed this concern (although differently after
learning more from a local test setup), see the other reply for
the CAN driver adjustment for clock API use.

> 
> > +			devm_clk_put(&ofdev->dev, clk_can);
> 
> not needed, as this driver instance will fail, doesn't it?

This is discussed in the other subthread as well.  The only
remaining question is how many of them to remove, before I'll
update the series.

> > +			goto err_notavail;
> > +		}
> > +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> > +		priv->clk_can = clk_can;
> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> > +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	case CLK_FROM_SYS:
> > +	case CLK_FROM_REF:
> > +		clk_can = devm_clk_get(&ofdev->dev, "mclk");
> > +		if (IS_ERR(clk_can))
> > +			goto err_notavail;
> > +		if (clk_prepare(clk_can)) {
> > +			devm_clk_put(&ofdev->dev, clk_can);
> 
> same here
> 
> > +			goto err_notavail;
> > +		}
> > +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> > +		priv->clk_can = clk_can;
> > +		if (clk_from == CLK_FROM_SYS)
> > +			clk_in = devm_clk_get(&ofdev->dev, "sys");
> > +		if (clk_from == CLK_FROM_REF)
> > +			clk_in = devm_clk_get(&ofdev->dev, "ref");
> > +		if (IS_ERR(clk_in))
> > +			goto err_notavail;
> > +		clk_set_parent(clk_can, clk_in);
> > +		freq_calc = clk_get_rate(clk_in);
> > +		freq_calc /= clockdiv;
> > +		clk_set_rate(clk_can, freq_calc);
> > +		freq_calc = clk_get_rate(clk_can);
> > +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> > +		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
> > +			*mscan_clksrc, freq_calc);
> > +		break;
> > +	default:
> > +		goto err_invalid;
> > +	}
> > +
> > +	return freq_calc;
> > +
> > +err_invalid:
> > +	dev_err(&ofdev->dev, "invalid clock source specification\n");
> > +	return 0;
> 
> return 0 in case of error? Please add a comment what this 0 means here.

The .get_clock() callback is supposed to return the resulting
rate after the clock source was determined and the clock subtree
was setup.  It wasn't (explicitly) documented before (in the
non-common-clock case), so I did not bother to comment it in the
parallel common-clock case.

But it's true that returning zero in the error case may be
unexpected, and I will add a comment in v4 (in all the
.get_clock() implementations).

> > +
> > +err_notavail:
> > +	dev_err(&ofdev->dev, "cannot acquire or setup clock source\n");
> > +	return 0;
> > +}
> > +
> > +static void mpc512x_can_put_clock(struct platform_device *ofdev)
> > +{
> > +	struct mscan_priv *priv;
> > +
> > +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
> > +	if (priv->clk_can) {
> > +		clk_unprepare(priv->clk_can);
> > +		devm_clk_put(&ofdev->dev, priv->clk_can);
> 
> devm_clk_put can be removed, it's called automatically.
> 
> > +	}
> > +}
> > +
> > +#else	/* COMMON_CLK */
> > +
> >  struct mpc512x_clockctl {
> >  	u32 spmr;		/* System PLL Mode Reg */
> >  	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
> > @@ -239,12 +400,18 @@ exit_put:
> >  	of_node_put(np_clock);
> >  	return freq;
> >  }
> > +
> > +#define mpc512x_can_put_clock NULL
> > +
> > +#endif	/* COMMON_CLK */
> > +
> >  #else /* !CONFIG_PPC_MPC512x */
> >  static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
> >  				 const char *clock_name, int *mscan_clksrc)
> >  {
> >  	return 0;
> >  }
> > +#define mpc512x_can_put_clock NULL
> >  #endif /* CONFIG_PPC_MPC512x */
> >  
> >  static const struct of_device_id mpc5xxx_can_table[];
> > @@ -386,11 +553,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
> >  static const struct mpc5xxx_can_data mpc5200_can_data = {
> >  	.type = MSCAN_TYPE_MPC5200,
> >  	.get_clock = mpc52xx_can_get_clock,
> > +	/* .put_clock not applicable */
> >  };
> >  
> >  static const struct mpc5xxx_can_data mpc5121_can_data = {
> >  	.type = MSCAN_TYPE_MPC5121,
> >  	.get_clock = mpc512x_can_get_clock,
> > +	.put_clock = mpc512x_can_put_clock,
> >  };
> >  
> >  static const struct of_device_id mpc5xxx_can_table[] = {
> > 
> 
> Marc

Thank you for the fast and detailled review.  It's very much
appreciated.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 11/31] net: can: mscan: improve clock API use
  2013-07-23 11:53             ` Gerhard Sittig
  (?)
@ 2013-07-23 12:33               ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-23 12:33 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss, Wolfram Sang,
	Mauro Carvalho Chehab, David Woodhouse, Wolfgang Grandegger,
	Pantelis Antoniou, Mark Brown, Greg Kroah-Hartman, Rob Herring,
	Detlev Zundel


[-- Attachment #1.1: Type: text/plain, Size: 3732 bytes --]

On 07/23/2013 01:53 PM, Gerhard Sittig wrote:
> On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
>>
>> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
>>> the .get_clock() callback is run from probe() and might allocate
>>> resources, introduce a .put_clock() callback that is run from remove()
>>> to undo any allocation activities
>>
>> looks good
>>
>>> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
>>> upon driver unload
>>
>> fine
>>
>>> assume that resources get prepared but not necessarily enabled in the
>>> setup phase, make the open() and close() callbacks of the CAN network
>>> device enable and disable a previously acquired and prepared clock
>>
>> I think you should call prepare_enable and disable_unprepare in the
>> open/close functions.
> 
> After more local research, which totally eliminated the need to
> pre-enable the CAN related clocks, but might need more discussion
> as it touches the common gate support, I've learned something
> more:
> 
> The CAN clock needs to get enabled during probe() already, since
> registers get accessed between probe() for the driver and open()
> for the network device -- while access to peripheral registers
> crashes the kernel when clocks still are disabled (other hardware
> may just hang or provide fake data, neither of this is OK).

Then call prepare_enable(); before and disable_unprepare(); after
accessing the registers. Have a look at the flexcan driver.

> But I see the point in your suggestion to prepare _and_ enable
> the clock during open() as well -- to have open() cope with
> whatever probe() did, after all the driver is shared among
> platforms, which may differ in what they do during probe().

If you enable a clock to access the registers before open() (and disable
it afterwards), it should not harm any architecture that doesn't need
this clock enabled.

> So I will:
> - make open() of the network device prepare _and_ enable the
>   clock for the peripheral (if acquired during probe())

good

> - adjust open() because ATM it leaves the clock enabled when the
>   network device operation fails (the error path is incomplete in
>   v3)

yes, clock should be disabled if open() fails.

> - make the MPC512x specific probe() time .get_clock() routine not
>   just prepare but enable the clock as well

If needed enable the clock, but disable after probe() has finished.

> - and of course address all the shutdown counter parts of the
>   above setup paths

> This results in:
> - specific chip drivers only need to balance their private get
>   and put clock routines which are called from probe and remove,
>   common paths DTRT for all of them

Yes, but clock should not stay enabled between probe() and open().

[...]

> Removing unnecessary devm_put_clk() calls is orthogonal to that.
> Putting these in isn't totally wrong (they won't harm, and they
> do signal "visual balance" more clearly such that the next person
> won't stop and wonder), but it's true that they are redundant.
> "Trained persons" will wonder as much about their presence as
> untrained persons wonder about their absence. :)  Apparently I'm
> not well trained yet.

The whole point about devm_* is to get rid of auto manually tear down
functions. So please remove all devm_put_clk() calls, as it will be
called automatically if a driver instance is removed.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

[-- Attachment #2: Type: text/plain, Size: 150 bytes --]

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

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-07-23 12:33               ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-23 12:33 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree-discuss, Wolfram Sang,
	Mauro Carvalho Chehab, David Woodhouse, Wolfgang Grandegger,
	Pantelis Antoniou, Mark Brown, Greg Kroah-Hartman, Rob Herring,
	Detlev Zundel

[-- Attachment #1: Type: text/plain, Size: 3732 bytes --]

On 07/23/2013 01:53 PM, Gerhard Sittig wrote:
> On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
>>
>> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
>>> the .get_clock() callback is run from probe() and might allocate
>>> resources, introduce a .put_clock() callback that is run from remove()
>>> to undo any allocation activities
>>
>> looks good
>>
>>> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
>>> upon driver unload
>>
>> fine
>>
>>> assume that resources get prepared but not necessarily enabled in the
>>> setup phase, make the open() and close() callbacks of the CAN network
>>> device enable and disable a previously acquired and prepared clock
>>
>> I think you should call prepare_enable and disable_unprepare in the
>> open/close functions.
> 
> After more local research, which totally eliminated the need to
> pre-enable the CAN related clocks, but might need more discussion
> as it touches the common gate support, I've learned something
> more:
> 
> The CAN clock needs to get enabled during probe() already, since
> registers get accessed between probe() for the driver and open()
> for the network device -- while access to peripheral registers
> crashes the kernel when clocks still are disabled (other hardware
> may just hang or provide fake data, neither of this is OK).

Then call prepare_enable(); before and disable_unprepare(); after
accessing the registers. Have a look at the flexcan driver.

> But I see the point in your suggestion to prepare _and_ enable
> the clock during open() as well -- to have open() cope with
> whatever probe() did, after all the driver is shared among
> platforms, which may differ in what they do during probe().

If you enable a clock to access the registers before open() (and disable
it afterwards), it should not harm any architecture that doesn't need
this clock enabled.

> So I will:
> - make open() of the network device prepare _and_ enable the
>   clock for the peripheral (if acquired during probe())

good

> - adjust open() because ATM it leaves the clock enabled when the
>   network device operation fails (the error path is incomplete in
>   v3)

yes, clock should be disabled if open() fails.

> - make the MPC512x specific probe() time .get_clock() routine not
>   just prepare but enable the clock as well

If needed enable the clock, but disable after probe() has finished.

> - and of course address all the shutdown counter parts of the
>   above setup paths

> This results in:
> - specific chip drivers only need to balance their private get
>   and put clock routines which are called from probe and remove,
>   common paths DTRT for all of them

Yes, but clock should not stay enabled between probe() and open().

[...]

> Removing unnecessary devm_put_clk() calls is orthogonal to that.
> Putting these in isn't totally wrong (they won't harm, and they
> do signal "visual balance" more clearly such that the next person
> won't stop and wonder), but it's true that they are redundant.
> "Trained persons" will wonder as much about their presence as
> untrained persons wonder about their absence. :)  Apparently I'm
> not well trained yet.

The whole point about devm_* is to get rid of auto manually tear down
functions. So please remove all devm_put_clk() calls, as it will be
called automatically if a driver instance is removed.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-07-23 12:33               ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-23 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/23/2013 01:53 PM, Gerhard Sittig wrote:
> On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
>>
>> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
>>> the .get_clock() callback is run from probe() and might allocate
>>> resources, introduce a .put_clock() callback that is run from remove()
>>> to undo any allocation activities
>>
>> looks good
>>
>>> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
>>> upon driver unload
>>
>> fine
>>
>>> assume that resources get prepared but not necessarily enabled in the
>>> setup phase, make the open() and close() callbacks of the CAN network
>>> device enable and disable a previously acquired and prepared clock
>>
>> I think you should call prepare_enable and disable_unprepare in the
>> open/close functions.
> 
> After more local research, which totally eliminated the need to
> pre-enable the CAN related clocks, but might need more discussion
> as it touches the common gate support, I've learned something
> more:
> 
> The CAN clock needs to get enabled during probe() already, since
> registers get accessed between probe() for the driver and open()
> for the network device -- while access to peripheral registers
> crashes the kernel when clocks still are disabled (other hardware
> may just hang or provide fake data, neither of this is OK).

Then call prepare_enable(); before and disable_unprepare(); after
accessing the registers. Have a look at the flexcan driver.

> But I see the point in your suggestion to prepare _and_ enable
> the clock during open() as well -- to have open() cope with
> whatever probe() did, after all the driver is shared among
> platforms, which may differ in what they do during probe().

If you enable a clock to access the registers before open() (and disable
it afterwards), it should not harm any architecture that doesn't need
this clock enabled.

> So I will:
> - make open() of the network device prepare _and_ enable the
>   clock for the peripheral (if acquired during probe())

good

> - adjust open() because ATM it leaves the clock enabled when the
>   network device operation fails (the error path is incomplete in
>   v3)

yes, clock should be disabled if open() fails.

> - make the MPC512x specific probe() time .get_clock() routine not
>   just prepare but enable the clock as well

If needed enable the clock, but disable after probe() has finished.

> - and of course address all the shutdown counter parts of the
>   above setup paths

> This results in:
> - specific chip drivers only need to balance their private get
>   and put clock routines which are called from probe and remove,
>   common paths DTRT for all of them

Yes, but clock should not stay enabled between probe() and open().

[...]

> Removing unnecessary devm_put_clk() calls is orthogonal to that.
> Putting these in isn't totally wrong (they won't harm, and they
> do signal "visual balance" more clearly such that the next person
> won't stop and wonder), but it's true that they are redundant.
> "Trained persons" will wonder as much about their presence as
> untrained persons wonder about their absence. :)  Apparently I'm
> not well trained yet.

The whole point about devm_* is to get rid of auto manually tear down
functions. So please remove all devm_put_clk() calls, as it will be
called automatically if a driver instance is removed.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130723/b5b60aaf/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
  2013-07-23 12:07             ` Gerhard Sittig
@ 2013-07-23 12:37               ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-23 12:37 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree, Wolfram Sang,
	Mauro Carvalho Chehab, David Woodhouse, Wolfgang Grandegger,
	Pantelis Antoniou, Mark Brown, Greg Kroah-Hartman, Rob Herring,
	Detlev Zundel

[-- Attachment #1: Type: text/plain, Size: 1255 bytes --]

On 07/23/2013 02:07 PM, Gerhard Sittig wrote:
[...]

>>> +	return freq_calc;
>>> +
>>> +err_invalid:
>>> +	dev_err(&ofdev->dev, "invalid clock source specification\n");
>>> +	return 0;
>>
>> return 0 in case of error? Please add a comment what this 0 means here.
> 
> The .get_clock() callback is supposed to return the resulting
> rate after the clock source was determined and the clock subtree
> was setup.  It wasn't (explicitly) documented before (in the
> non-common-clock case), so I did not bother to comment it in the
> parallel common-clock case.

Yes, but returning 0 in case of error should be documented, as it's very
uncommon.

> But it's true that returning zero in the error case may be
> unexpected, and I will add a comment in v4 (in all the
> .get_clock() implementations).

I think a one liner stating that the return value is the clock rate and
"0" indicates is an invalid clock rate, this meaning an error here, is
enough.

Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-07-23 12:37               ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-07-23 12:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/23/2013 02:07 PM, Gerhard Sittig wrote:
[...]

>>> +	return freq_calc;
>>> +
>>> +err_invalid:
>>> +	dev_err(&ofdev->dev, "invalid clock source specification\n");
>>> +	return 0;
>>
>> return 0 in case of error? Please add a comment what this 0 means here.
> 
> The .get_clock() callback is supposed to return the resulting
> rate after the clock source was determined and the clock subtree
> was setup.  It wasn't (explicitly) documented before (in the
> non-common-clock case), so I did not bother to comment it in the
> parallel common-clock case.

Yes, but returning 0 in case of error should be documented, as it's very
uncommon.

> But it's true that returning zero in the error case may be
> unexpected, and I will add a comment in v4 (in all the
> .get_clock() implementations).

I think a one liner stating that the return value is the clock rate and
"0" indicates is an invalid clock rate, this meaning an error here, is
enough.

Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130723/e4b5a260/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-22 12:14         ` Gerhard Sittig
@ 2013-07-23 13:14           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 13:14 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

[ summary: "shared gate" support desirable? approach acceptable? ]

On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> 
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
> 
> [ ... ]
> 
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> [ ... ]
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)

This remark was related to the CAN clocks of the MPC512x SoC.

The clock subtrees which are involved in generating CAN bitrates
include one path from the XTAL to an internal MCLK (this is part
of the CCF support for the platform), and another path from the
MCLK or yet another IP bus clock to the actual bitrate on the
wire (this is taken care of within the mscan(4) driver).

The MCLK generation for CAN is documented in the MPC5121e
Reference Manual, chapter 5, section 5.2.5 "MSCAN Clock
Generation".  SYS, REF (both internal), PSC_MCLK_IN, and SPDIF_TX
(both external) are muxed, gated, and divided.  The result is
muxed with IP.  The result is fed into the MSCAN component and
gets muxed with IP again (can't tell why, maybe for backwards
compatibility).

In parallel to this MCLK block there is SCCR2[25], the "BDLC and
MSCAN clock enable", documented in section 5.3.1.3 "System Clock
Control Register 2".  So there is a gate that "somehow needs to
get setup" yet isn't part of the visible MCLK chain.

The series up to and including v3 approaches the problem by
- adding a gate after the second MCLK mux, which gets exported
  for client lookups and is the MCLK input for the mscan(4)
  driver
- creating that gate for each of the four MSCAN clocks of the
  SoC, all of them referencing the single "enable" bit in the
  SCCR2 register
- pre-enabling the MSCAN clocks from within the clock driver, and
  thus avoid having the clock disabled from the common
  infrastructure, because disabling one of these clocks had
  closed the shared gate and thus had broken all other clock uses

> clkdev registration provides "alias names" for few clock items
> [ ... ]
> 
[ ... ]
> +
> +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> +{
> +	size_t clks_idx_pub, clks_idx_int;
> +	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
> +	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
> +	int sccr_bit;
> +	int div;
> +
> +	/* derive a few parameters from the component type and index */
> +	switch (entry->type) {
> +	case MCLK_TYPE_PSC:
> +		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> +		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +			     + (entry->comp_idx) * MCLK_MAX_IDX;
> +		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> +		break;
> +	case MCLK_TYPE_MSCAN:
> +		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> +		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> +		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> +		break;
> +	case MCLK_TYPE_SPDIF:
> +		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> +		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> +		mccr_reg = &clkregs->spccr;
> +		break;
> +	default:
> +		return;
> +	}
> +	if (entry->bit_sccr1 >= 0) {
> +		sccr_reg = &clkregs->sccr1;
> +		sccr_bit = entry->bit_sccr1;
> +	} else if (entry->bit_sccr2 >= 0) {
> +		sccr_reg = &clkregs->sccr2;
> +		sccr_bit = entry->bit_sccr2;
> +	} else {
> +		sccr_reg = NULL;
> +	}
> +
> +	/*
> +	 * this was grabbed from the PPC_CLOCK implementation, which
> +	 * enforced a specific MCLK divider while the clock was gated
> +	 * during setup (that's a documented hardware requirement)
> +	 *
> +	 * the PPC_CLOCK implementation might even have violated the
> +	 * "MCLK <= IPS" constraint, the fixed divider value of 1
> +	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
> +	 * CSB which is greater than IPS; the serial port setup may have
> +	 * adjusted the divider which the clock setup might have left in
> +	 * an undesirable state
> +	 *
> +	 * initial setup is:
> +	 * - MCLK 0 from SYS
> +	 * - MCLK DIV such to not exceed the IPS clock
> +	 * - MCLK 0 enabled
> +	 * - MCLK 1 from MCLK DIV
> +	 */
> +	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> +	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> +	out_be32(mccr_reg, (0 << 16));
> +	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> +	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> +
> +	/*
> +	 * create the 'struct clk' items of the MCLK's clock subtree
> +	 *
> +	 * note that by design we always create all nodes and won't take
> +	 * shortcuts here, because
> +	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> +	 *   selectable inputs to the CFM while those who "actually use"
> +	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> +	 *   for their bitrate
> +	 * - in the absence of "aliases" for clocks we need to create
> +	 *   individial 'struct clk' items for whatever might get
> +	 *   referenced or looked up, even if several of those items are
> +	 *   identical from the logical POV (their rate value)
> +	 * - for easier future maintenance and for better reflection of
> +	 *   the SoC's documentation, it appears appropriate to generate
> +	 *   clock items even for those muxers which actually are NOPs
> +	 *   (those with two inputs of which one is reserved)
> +	 */
> +	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> +			entry->name_mux0,
> +			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> +			mccr_reg, 14, 2);
> +	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> +			entry->name_en0, entry->name_mux0,
> +			mccr_reg, 16);
> +	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> +			entry->name_div0,
> +			entry->name_en0, CLK_SET_RATE_GATE,
> +			mccr_reg, 17, 15, 0);
> +	if (entry->has_mclk1) {
> +		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> +				entry->name_mux1,
> +				&entry->parent_names_mux1[0],
> +				ARRAY_SIZE(entry->parent_names_mux1),
> +				mccr_reg, 7, 1);
> +	} else {
> +		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> +				entry->name_mux1, entry->parent_names_mux1[0],
> +				1, 1);
> +	}
> +	if (sccr_reg) {
> +		clks[clks_idx_pub] = mpc512x_clk_gated(
> +				entry->name_mclk,
> +				entry->name_mux1, sccr_reg, sccr_bit);
> +	} else {
> +		clks[clks_idx_pub] = mpc512x_clk_factor(
> +				entry->name_mclk,
> +				entry->name_mux1, 1, 1);
> +	}
> +
> +	/*
> +	 * without this "clock device" registration, "simple" lookups in
> +	 * the SPI master initialization and serial port setup will fail
> +	 *
> +	 * those drivers need to get adjusted to lookup their required
> +	 * clocks from device tree specs, and device tree nodes need to
> +	 * provide the clock specs, before this clkdev registration
> +	 * becomes obsolete
> +	 */
> +	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> +}
> [ ... ]

This was the routine which sets up _one_ MCLK block, note the
assignment at the routine's end to the "published" clock item
that's the gate's output after the second mux stage.

> [ ... ]
> +	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> +						  &clkregs->sccr2, 26);
> +	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> +	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> +						   &clkregs->sccr2, 24);
> +	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> [ ... ]

This is the invocation of the routine which sets up four MCLK
blocks for the MSCAN components, while all of them refer to bit
25 of SCCR2.

> [ ... ]
> +
> +	/* enable some of the clocks here unconditionally because ... */
> +	pr_debug("automatically enabling some clocks\n");
> +	/* some are essential yet never get claimed by any driver */
> +	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> +	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
> +	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
> +	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
> +	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
> +	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
> +	/* some are required yet no dependencies were declared */
> +	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> +	/* some are not yet acquired by their respective drivers */
> +	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> +	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
> +	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
> +	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> +	/*
> +	 * some have their individual clock subtree with separate clock
> +	 * items and their individual enable counters, yet share a
> +	 * common gate (refer to the same register location) while the
> +	 * common clock driver code is not aware of the fact and the
> +	 * platform's code doesn't provide specific support either
> +	 *
> +	 * what might happen is that e.g. enabling two MSCAN clock items
> +	 * and disabling one of them will disable the common gate and
> +	 * thus break the other MSCAN clock as well
> +	 */
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> +}

This is the pre-enable workaround for the MSCAN0 to MSCAN3 clock
items.

The above approach does work in that it introduces complete
support for common clock on the MPC512x platform, with the CAN
component being operational, and the clock driver using shared
logic across platforms.

The remaining issue is that regardless of whether CAN is used,
the (chip internal) clock is enabled.  This may not be a problem
when bitrates aren't generated and the wire isn't driven.


The question now is how to correctly support the situation where
a gate is shared between subtrees yet isn't really part of any
path within the subtrees.  I really cannot find a single spot
where to introduce the gate such that it's not duplicated.

The appropriate solution would not be to pre-enable those clocks,
but to either introduce another gate clock type which supports a
shared reference, or to add support for the shared reference to
the existing gate code.


I'd rather not duplicate most or all of the code of clk-gate.c,
instead I looked into how to add "shared gate" support to the
existing driver.

My question is whether the approach is acceptable.  It adds
minimal overhead and shall be OK for the enable/disable path from
a technical POV.  And it doesn't feel like too much of a stretch.
But there may be non-technical reasons to reject the approach.
I'd like to learn whether to follow that path before preparing
another version of the patch series.

The diffs were taken with the '-w -b' options to demonstrate
their essence and not drown it in whitespace changes.  The
implementation assumes that the caller which registers the gate
(the platform's clock driver) provides both the counter cell and
the lock.  And that all gates with a "shared use counter" use the
same lock (which is satisfied as they all get registered from the
same spot in the platform's clock driver).

The CLK_IGNORE_UNUSED flag addresses a different problem.  The
SoC has four MSCAN components, while two of them are enabled in
the device tree (the other two are present but disabled).  So
during probe two of the clocks get enabled.  After probe all
unused clocks automatically get disabled (that's another two).
So the "shared use counter" drops to zero although components are
in use, because "disable, it's unused" isn't told from "disable
after enable, regular use".  The flag would become obsolete if
the common gate logic would implement a separate disable_unused()
routine, but I guess this isn't necessary and the use of the flag
is appropriate.

That the example use creates a field for just one counter is to
better demonstrate the use and potential extension as need
arises.  Reducing this to a mere integer variable would be a
micro optimization.


The extension of the existing clk_gate implementation:

--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 	struct clk_gate *gate = to_clk_gate(hw);
 	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
 	unsigned long flags = 0;
+	int need_reg_access;
 	u32 reg;
 
 	set ^= enable;
@@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 	if (gate->lock)
 		spin_lock_irqsave(gate->lock, flags);
 
+	/*
+	 * if a "shared use counter" was specified, keep track of enable
+	 * and disable calls and only access hardware registers upon the
+	 * very first enable or very last disable call
+	 */
+	if (!gate->share_count) {
+		need_reg_access = 1;
+	} else if (enable) {
+		need_reg_access = (*gate->share_count)++ == 0;
+	} else {
+		need_reg_access = --(*gate->share_count) == 0;
+	}
+
+	if (need_reg_access) {
 		if (gate->flags & CLK_GATE_HIWORD_MASK) {
 			reg = BIT(gate->bit_idx + 16);
 			if (set)
@@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		}
 
 		clk_writel(reg, gate->reg);
+	}
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
  * @clk_gate_flags: gate-specific flags for this clock
  * @lock: shared register lock for this clock
  */
-struct clk *clk_register_gate(struct device *dev, const char *name,
+struct clk *clk_register_gate_shared(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
-		u8 clk_gate_flags, spinlock_t *lock)
+		u8 clk_gate_flags, spinlock_t *lock,
+		int *share_count)
 {
 	struct clk_gate *gate;
 	struct clk *clk;
@@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	gate->bit_idx = bit_idx;
 	gate->flags = clk_gate_flags;
 	gate->lock = lock;
+	gate->share_count = share_count;
 	gate->hw.init = &init;
 
 	clk = clk_register(dev, &gate->hw);
@@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 
 	return clk;
 }
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock)
+{
+
+	return clk_register_gate_shared(dev, name, parent_name, flags,
+					reg, bit_idx, clk_gate_flags,
+					lock, NULL);
+}
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -222,6 +222,7 @@ struct clk_gate {
 	u8		bit_idx;
 	u8		flags;
 	spinlock_t	*lock;
+	int		*share_count;
 };
 
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
@@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
 		u8 clk_gate_flags, spinlock_t *lock);
+struct clk *clk_register_gate_shared(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock,
+		int *share_count);
 
 struct clk_div_table {
 	unsigned int	val;


How to use these shared gates:

--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
				 reg, pos, 0, &clklock);
 }
 
+enum mpc512x_clk_shared_gate_id_t {
+	MPC512x_CLK_SHARED_GATE_MSCAN,
+	MPC512x_CLK_SHARED_GATE_MAX,
+};
+
+static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
+
+/*
+ * implementor's note:  since clk_gate items don't implement a separate
+ * .disable_unused() callback, their .disable() routine gets called and
+ * "disable the clock as we can't see it's in use" cannot be told from
+ * "regular disable, count these events please"
+ *
+ * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
+ * the "disable, unused" call, so use counts won't get unbalanced, the
+ * clock either never got enabled and thus need not get disabled, or
+ * part of the hardware got enabled while disabling the other part isn't
+ * wanted
+ */
+static inline struct clk *mpc512x_clk_gated_shared(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos,
+	enum mpc512x_clk_shared_gate_id_t share_id)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	clkflags |= CLK_IGNORE_UNUSED;
+	return clk_register_gate_shared(NULL, name, parent_name, clkflags,
+					reg, pos, 0, &clklock,
+					&mpc512x_clk_gate_counters[share_id]);
+}
+
 static inline struct clk *mpc512x_clk_muxed(const char *name,
	const char **parent_names, int parent_count,
	u32 __iomem *reg, u8 pos, u8 len)
@@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
				1, 1);
	}
	if (sccr_reg) {
+		if (entry->type == MCLK_TYPE_MSCAN) {
+			clks[clks_idx_pub] = mpc512x_clk_gated_shared(
+					entry->name_mclk,
+					entry->name_mux1, sccr_reg, sccr_bit,
+					MPC512x_CLK_SHARED_GATE_MSCAN);
+		} else {
			clks[clks_idx_pub] = mpc512x_clk_gated(
					entry->name_mclk,
					entry->name_mux1, sccr_reg, sccr_bit);
+		}
	} else {
		clks[clks_idx_pub] = mpc512x_clk_factor(
				entry->name_mclk,

Local tests have shown that the extension solves the problem of
how to satisfy the SoC's constraints on the MPC512x platform.
The MSCAN clocks no longer need to get pre-enabled, instead they
get setup and enabled only as the mscan(4) driver probes devices
according to how it was instructed (device tree nodes).

What do you think?  Is the "shared gate" support in the common
logic appropriate?  I'd rather not duplicate all of this code
just to introduce the specific gate I need, while most of the
logic is identical to the existing gate implementation.  The
desire isn't to override the gate's operations, but to wrap them
and to consult a counter in addition, while the register access
still applies.



virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-07-23 13:14           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-07-23 13:14 UTC (permalink / raw)
  To: linux-arm-kernel

[ summary: "shared gate" support desirable? approach acceptable? ]

On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> 
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
> 
> [ ... ]
> 
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> [ ... ]
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)

This remark was related to the CAN clocks of the MPC512x SoC.

The clock subtrees which are involved in generating CAN bitrates
include one path from the XTAL to an internal MCLK (this is part
of the CCF support for the platform), and another path from the
MCLK or yet another IP bus clock to the actual bitrate on the
wire (this is taken care of within the mscan(4) driver).

The MCLK generation for CAN is documented in the MPC5121e
Reference Manual, chapter 5, section 5.2.5 "MSCAN Clock
Generation".  SYS, REF (both internal), PSC_MCLK_IN, and SPDIF_TX
(both external) are muxed, gated, and divided.  The result is
muxed with IP.  The result is fed into the MSCAN component and
gets muxed with IP again (can't tell why, maybe for backwards
compatibility).

In parallel to this MCLK block there is SCCR2[25], the "BDLC and
MSCAN clock enable", documented in section 5.3.1.3 "System Clock
Control Register 2".  So there is a gate that "somehow needs to
get setup" yet isn't part of the visible MCLK chain.

The series up to and including v3 approaches the problem by
- adding a gate after the second MCLK mux, which gets exported
  for client lookups and is the MCLK input for the mscan(4)
  driver
- creating that gate for each of the four MSCAN clocks of the
  SoC, all of them referencing the single "enable" bit in the
  SCCR2 register
- pre-enabling the MSCAN clocks from within the clock driver, and
  thus avoid having the clock disabled from the common
  infrastructure, because disabling one of these clocks had
  closed the shared gate and thus had broken all other clock uses

> clkdev registration provides "alias names" for few clock items
> [ ... ]
> 
[ ... ]
> +
> +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> +{
> +	size_t clks_idx_pub, clks_idx_int;
> +	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
> +	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
> +	int sccr_bit;
> +	int div;
> +
> +	/* derive a few parameters from the component type and index */
> +	switch (entry->type) {
> +	case MCLK_TYPE_PSC:
> +		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> +		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +			     + (entry->comp_idx) * MCLK_MAX_IDX;
> +		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> +		break;
> +	case MCLK_TYPE_MSCAN:
> +		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> +		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> +		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> +		break;
> +	case MCLK_TYPE_SPDIF:
> +		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> +		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> +		mccr_reg = &clkregs->spccr;
> +		break;
> +	default:
> +		return;
> +	}
> +	if (entry->bit_sccr1 >= 0) {
> +		sccr_reg = &clkregs->sccr1;
> +		sccr_bit = entry->bit_sccr1;
> +	} else if (entry->bit_sccr2 >= 0) {
> +		sccr_reg = &clkregs->sccr2;
> +		sccr_bit = entry->bit_sccr2;
> +	} else {
> +		sccr_reg = NULL;
> +	}
> +
> +	/*
> +	 * this was grabbed from the PPC_CLOCK implementation, which
> +	 * enforced a specific MCLK divider while the clock was gated
> +	 * during setup (that's a documented hardware requirement)
> +	 *
> +	 * the PPC_CLOCK implementation might even have violated the
> +	 * "MCLK <= IPS" constraint, the fixed divider value of 1
> +	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
> +	 * CSB which is greater than IPS; the serial port setup may have
> +	 * adjusted the divider which the clock setup might have left in
> +	 * an undesirable state
> +	 *
> +	 * initial setup is:
> +	 * - MCLK 0 from SYS
> +	 * - MCLK DIV such to not exceed the IPS clock
> +	 * - MCLK 0 enabled
> +	 * - MCLK 1 from MCLK DIV
> +	 */
> +	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> +	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> +	out_be32(mccr_reg, (0 << 16));
> +	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> +	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> +
> +	/*
> +	 * create the 'struct clk' items of the MCLK's clock subtree
> +	 *
> +	 * note that by design we always create all nodes and won't take
> +	 * shortcuts here, because
> +	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> +	 *   selectable inputs to the CFM while those who "actually use"
> +	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> +	 *   for their bitrate
> +	 * - in the absence of "aliases" for clocks we need to create
> +	 *   individial 'struct clk' items for whatever might get
> +	 *   referenced or looked up, even if several of those items are
> +	 *   identical from the logical POV (their rate value)
> +	 * - for easier future maintenance and for better reflection of
> +	 *   the SoC's documentation, it appears appropriate to generate
> +	 *   clock items even for those muxers which actually are NOPs
> +	 *   (those with two inputs of which one is reserved)
> +	 */
> +	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> +			entry->name_mux0,
> +			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> +			mccr_reg, 14, 2);
> +	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> +			entry->name_en0, entry->name_mux0,
> +			mccr_reg, 16);
> +	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> +			entry->name_div0,
> +			entry->name_en0, CLK_SET_RATE_GATE,
> +			mccr_reg, 17, 15, 0);
> +	if (entry->has_mclk1) {
> +		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> +				entry->name_mux1,
> +				&entry->parent_names_mux1[0],
> +				ARRAY_SIZE(entry->parent_names_mux1),
> +				mccr_reg, 7, 1);
> +	} else {
> +		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> +				entry->name_mux1, entry->parent_names_mux1[0],
> +				1, 1);
> +	}
> +	if (sccr_reg) {
> +		clks[clks_idx_pub] = mpc512x_clk_gated(
> +				entry->name_mclk,
> +				entry->name_mux1, sccr_reg, sccr_bit);
> +	} else {
> +		clks[clks_idx_pub] = mpc512x_clk_factor(
> +				entry->name_mclk,
> +				entry->name_mux1, 1, 1);
> +	}
> +
> +	/*
> +	 * without this "clock device" registration, "simple" lookups in
> +	 * the SPI master initialization and serial port setup will fail
> +	 *
> +	 * those drivers need to get adjusted to lookup their required
> +	 * clocks from device tree specs, and device tree nodes need to
> +	 * provide the clock specs, before this clkdev registration
> +	 * becomes obsolete
> +	 */
> +	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> +}
> [ ... ]

This was the routine which sets up _one_ MCLK block, note the
assignment at the routine's end to the "published" clock item
that's the gate's output after the second mux stage.

> [ ... ]
> +	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> +						  &clkregs->sccr2, 26);
> +	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> +	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> +						   &clkregs->sccr2, 24);
> +	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> [ ... ]

This is the invocation of the routine which sets up four MCLK
blocks for the MSCAN components, while all of them refer to bit
25 of SCCR2.

> [ ... ]
> +
> +	/* enable some of the clocks here unconditionally because ... */
> +	pr_debug("automatically enabling some clocks\n");
> +	/* some are essential yet never get claimed by any driver */
> +	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> +	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
> +	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
> +	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
> +	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
> +	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
> +	/* some are required yet no dependencies were declared */
> +	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> +	/* some are not yet acquired by their respective drivers */
> +	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> +	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
> +	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
> +	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> +	/*
> +	 * some have their individual clock subtree with separate clock
> +	 * items and their individual enable counters, yet share a
> +	 * common gate (refer to the same register location) while the
> +	 * common clock driver code is not aware of the fact and the
> +	 * platform's code doesn't provide specific support either
> +	 *
> +	 * what might happen is that e.g. enabling two MSCAN clock items
> +	 * and disabling one of them will disable the common gate and
> +	 * thus break the other MSCAN clock as well
> +	 */
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> +	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> +}

This is the pre-enable workaround for the MSCAN0 to MSCAN3 clock
items.

The above approach does work in that it introduces complete
support for common clock on the MPC512x platform, with the CAN
component being operational, and the clock driver using shared
logic across platforms.

The remaining issue is that regardless of whether CAN is used,
the (chip internal) clock is enabled.  This may not be a problem
when bitrates aren't generated and the wire isn't driven.


The question now is how to correctly support the situation where
a gate is shared between subtrees yet isn't really part of any
path within the subtrees.  I really cannot find a single spot
where to introduce the gate such that it's not duplicated.

The appropriate solution would not be to pre-enable those clocks,
but to either introduce another gate clock type which supports a
shared reference, or to add support for the shared reference to
the existing gate code.


I'd rather not duplicate most or all of the code of clk-gate.c,
instead I looked into how to add "shared gate" support to the
existing driver.

My question is whether the approach is acceptable.  It adds
minimal overhead and shall be OK for the enable/disable path from
a technical POV.  And it doesn't feel like too much of a stretch.
But there may be non-technical reasons to reject the approach.
I'd like to learn whether to follow that path before preparing
another version of the patch series.

The diffs were taken with the '-w -b' options to demonstrate
their essence and not drown it in whitespace changes.  The
implementation assumes that the caller which registers the gate
(the platform's clock driver) provides both the counter cell and
the lock.  And that all gates with a "shared use counter" use the
same lock (which is satisfied as they all get registered from the
same spot in the platform's clock driver).

The CLK_IGNORE_UNUSED flag addresses a different problem.  The
SoC has four MSCAN components, while two of them are enabled in
the device tree (the other two are present but disabled).  So
during probe two of the clocks get enabled.  After probe all
unused clocks automatically get disabled (that's another two).
So the "shared use counter" drops to zero although components are
in use, because "disable, it's unused" isn't told from "disable
after enable, regular use".  The flag would become obsolete if
the common gate logic would implement a separate disable_unused()
routine, but I guess this isn't necessary and the use of the flag
is appropriate.

That the example use creates a field for just one counter is to
better demonstrate the use and potential extension as need
arises.  Reducing this to a mere integer variable would be a
micro optimization.


The extension of the existing clk_gate implementation:

--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 	struct clk_gate *gate = to_clk_gate(hw);
 	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
 	unsigned long flags = 0;
+	int need_reg_access;
 	u32 reg;
 
 	set ^= enable;
@@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 	if (gate->lock)
 		spin_lock_irqsave(gate->lock, flags);
 
+	/*
+	 * if a "shared use counter" was specified, keep track of enable
+	 * and disable calls and only access hardware registers upon the
+	 * very first enable or very last disable call
+	 */
+	if (!gate->share_count) {
+		need_reg_access = 1;
+	} else if (enable) {
+		need_reg_access = (*gate->share_count)++ == 0;
+	} else {
+		need_reg_access = --(*gate->share_count) == 0;
+	}
+
+	if (need_reg_access) {
 		if (gate->flags & CLK_GATE_HIWORD_MASK) {
 			reg = BIT(gate->bit_idx + 16);
 			if (set)
@@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		}
 
 		clk_writel(reg, gate->reg);
+	}
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
  * @clk_gate_flags: gate-specific flags for this clock
  * @lock: shared register lock for this clock
  */
-struct clk *clk_register_gate(struct device *dev, const char *name,
+struct clk *clk_register_gate_shared(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
-		u8 clk_gate_flags, spinlock_t *lock)
+		u8 clk_gate_flags, spinlock_t *lock,
+		int *share_count)
 {
 	struct clk_gate *gate;
 	struct clk *clk;
@@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	gate->bit_idx = bit_idx;
 	gate->flags = clk_gate_flags;
 	gate->lock = lock;
+	gate->share_count = share_count;
 	gate->hw.init = &init;
 
 	clk = clk_register(dev, &gate->hw);
@@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 
 	return clk;
 }
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock)
+{
+
+	return clk_register_gate_shared(dev, name, parent_name, flags,
+					reg, bit_idx, clk_gate_flags,
+					lock, NULL);
+}
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -222,6 +222,7 @@ struct clk_gate {
 	u8		bit_idx;
 	u8		flags;
 	spinlock_t	*lock;
+	int		*share_count;
 };
 
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
@@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
 		u8 clk_gate_flags, spinlock_t *lock);
+struct clk *clk_register_gate_shared(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock,
+		int *share_count);
 
 struct clk_div_table {
 	unsigned int	val;


How to use these shared gates:

--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
				 reg, pos, 0, &clklock);
 }
 
+enum mpc512x_clk_shared_gate_id_t {
+	MPC512x_CLK_SHARED_GATE_MSCAN,
+	MPC512x_CLK_SHARED_GATE_MAX,
+};
+
+static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
+
+/*
+ * implementor's note:  since clk_gate items don't implement a separate
+ * .disable_unused() callback, their .disable() routine gets called and
+ * "disable the clock as we can't see it's in use" cannot be told from
+ * "regular disable, count these events please"
+ *
+ * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
+ * the "disable, unused" call, so use counts won't get unbalanced, the
+ * clock either never got enabled and thus need not get disabled, or
+ * part of the hardware got enabled while disabling the other part isn't
+ * wanted
+ */
+static inline struct clk *mpc512x_clk_gated_shared(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos,
+	enum mpc512x_clk_shared_gate_id_t share_id)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	clkflags |= CLK_IGNORE_UNUSED;
+	return clk_register_gate_shared(NULL, name, parent_name, clkflags,
+					reg, pos, 0, &clklock,
+					&mpc512x_clk_gate_counters[share_id]);
+}
+
 static inline struct clk *mpc512x_clk_muxed(const char *name,
	const char **parent_names, int parent_count,
	u32 __iomem *reg, u8 pos, u8 len)
@@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
				1, 1);
	}
	if (sccr_reg) {
+		if (entry->type == MCLK_TYPE_MSCAN) {
+			clks[clks_idx_pub] = mpc512x_clk_gated_shared(
+					entry->name_mclk,
+					entry->name_mux1, sccr_reg, sccr_bit,
+					MPC512x_CLK_SHARED_GATE_MSCAN);
+		} else {
			clks[clks_idx_pub] = mpc512x_clk_gated(
					entry->name_mclk,
					entry->name_mux1, sccr_reg, sccr_bit);
+		}
	} else {
		clks[clks_idx_pub] = mpc512x_clk_factor(
				entry->name_mclk,

Local tests have shown that the extension solves the problem of
how to satisfy the SoC's constraints on the MPC512x platform.
The MSCAN clocks no longer need to get pre-enabled, instead they
get setup and enabled only as the mscan(4) driver probes devices
according to how it was instructed (device tree nodes).

What do you think?  Is the "shared gate" support in the common
logic appropriate?  I'd rather not duplicate all of this code
just to introduce the specific gate I need, while most of the
logic is identical to the existing gate implementation.  The
desire isn't to override the gate's operations, but to wrap them
and to consult a counter in addition, while the register access
still applies.



virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
  2013-07-18 17:47               ` Nicolas Pitre
  (?)
@ 2013-08-02 22:09                 ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:09 UTC (permalink / raw)
  To: Nicolas Pitre, Russell King - ARM Linux
  Cc: Detlev Zundel, Wolfram Sang, devicetree-discuss,
	Greg Kroah-Hartman, Gerhard Sittig, linuxppc-dev, Rob Herring,
	Mark Brown, Marc Kleine-Budde, Wolfgang Grandegger,
	David Woodhouse, Sascha Hauer, linux-arm-kernel,
	Mauro Carvalho Chehab

Quoting Nicolas Pitre (2013-07-18 10:47:22)
> On Thu, 18 Jul 2013, Russell King - ARM Linux wrote:
> 
> > 1. clk_get() and clk_put() are NOT part of the common clock API.
> >    They're separate - they're part of the clk API, and the infrastructure
> >    behind that is clkdev, which is a separately owned thing (by me.)
> > 
> > 2. The "contract" of the clk API is defined by the clk API, not by some
> >    random implementation like the common clock API.  The clk API is
> >    maintained by myself, and is described in include/linux/clk.h
> > 
> > 3. clk_prepare() and clk_unprepare() are functions MUST only be called
> >    from contexts where sleeping is permitted.  These functions MAY sleep
> >    for whatever reason they require to, and as long as they require to.
> >    (This is the whole reason these two functions were created in the
> >    first place.)
> > 
> > 4. clk_enable() and clk_disable() MAY be called from any context, but
> >    MUST never sleep.  If you need to talk over a non-atomic bus for these,
> >    then these functions should be no-ops, and the code which does that
> >    must be executed from the clk_prepare()/clk_unprepare() operations.
> 
> Could the above be included in some form in Documentation/clk.txt (this 
> is likely one of the first location people look for information) and 
> elsewhere if appropriate please?
> 
> A *lot* of people are confused by the prepare-enable-disable-unprepare 
> sequence and when I try to find some rational for the prepare/enable 
> split I can only direct them to mail archive posts since this is nowhere 
> to be found in the kernel.
> 
> The comments in include/linux/clk.h, while correct, are very terse and 
> don't provide any insight to the reason why there is a split in the API.
> 
> The content of Documentation/clk.txt does refer to prepare and enable 
> (and their counterparts) but again doesn't provide any clue about the 
> reason for their existence.
> 
> Since there've been several good posts with usage example now buried 
> into list archives, I think this would go a long way helping people get 
> it right if those were part of the kernel documentation as well.

I'll update Documentation/clk.txt with more verbosity. The document was
originally intended as a "porting guide" to help migrate from legacy
frameworks to the common struct clk implementation. However the scope of
the document should probably be generalized a bit more.

Regards,
Mike

> 
> 
> Nicolas

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-08-02 22:09                 ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:09 UTC (permalink / raw)
  To: Nicolas Pitre, Russell King - ARM Linux
  Cc: Detlev Zundel, Wolfram Sang, devicetree-discuss,
	Greg Kroah-Hartman, Gerhard Sittig, linuxppc-dev, Rob Herring,
	Mark Brown, Marc Kleine-Budde, Wolfgang Grandegger,
	David Woodhouse, Sascha Hauer, linux-arm-kernel,
	Mauro Carvalho Chehab

Quoting Nicolas Pitre (2013-07-18 10:47:22)
> On Thu, 18 Jul 2013, Russell King - ARM Linux wrote:
> =

> > 1. clk_get() and clk_put() are NOT part of the common clock API.
> >    They're separate - they're part of the clk API, and the infrastructu=
re
> >    behind that is clkdev, which is a separately owned thing (by me.)
> > =

> > 2. The "contract" of the clk API is defined by the clk API, not by some
> >    random implementation like the common clock API.  The clk API is
> >    maintained by myself, and is described in include/linux/clk.h
> > =

> > 3. clk_prepare() and clk_unprepare() are functions MUST only be called
> >    from contexts where sleeping is permitted.  These functions MAY sleep
> >    for whatever reason they require to, and as long as they require to.
> >    (This is the whole reason these two functions were created in the
> >    first place.)
> > =

> > 4. clk_enable() and clk_disable() MAY be called from any context, but
> >    MUST never sleep.  If you need to talk over a non-atomic bus for the=
se,
> >    then these functions should be no-ops, and the code which does that
> >    must be executed from the clk_prepare()/clk_unprepare() operations.
> =

> Could the above be included in some form in Documentation/clk.txt (this =

> is likely one of the first location people look for information) and =

> elsewhere if appropriate please?
> =

> A *lot* of people are confused by the prepare-enable-disable-unprepare =

> sequence and when I try to find some rational for the prepare/enable =

> split I can only direct them to mail archive posts since this is nowhere =

> to be found in the kernel.
> =

> The comments in include/linux/clk.h, while correct, are very terse and =

> don't provide any insight to the reason why there is a split in the API.
> =

> The content of Documentation/clk.txt does refer to prepare and enable =

> (and their counterparts) but again doesn't provide any clue about the =

> reason for their existence.
> =

> Since there've been several good posts with usage example now buried =

> into list archives, I think this would go a long way helping people get =

> it right if those were part of the kernel documentation as well.

I'll update Documentation/clk.txt with more verbosity. The document was
originally intended as a "porting guide" to help migrate from legacy
frameworks to the common struct clk implementation. However the scope of
the document should probably be generalized a bit more.

Regards,
Mike

> =

> =

> Nicolas

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v1 05/24] clk: wrap I/O access for improved portability
@ 2013-08-02 22:09                 ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:09 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Nicolas Pitre (2013-07-18 10:47:22)
> On Thu, 18 Jul 2013, Russell King - ARM Linux wrote:
> 
> > 1. clk_get() and clk_put() are NOT part of the common clock API.
> >    They're separate - they're part of the clk API, and the infrastructure
> >    behind that is clkdev, which is a separately owned thing (by me.)
> > 
> > 2. The "contract" of the clk API is defined by the clk API, not by some
> >    random implementation like the common clock API.  The clk API is
> >    maintained by myself, and is described in include/linux/clk.h
> > 
> > 3. clk_prepare() and clk_unprepare() are functions MUST only be called
> >    from contexts where sleeping is permitted.  These functions MAY sleep
> >    for whatever reason they require to, and as long as they require to.
> >    (This is the whole reason these two functions were created in the
> >    first place.)
> > 
> > 4. clk_enable() and clk_disable() MAY be called from any context, but
> >    MUST never sleep.  If you need to talk over a non-atomic bus for these,
> >    then these functions should be no-ops, and the code which does that
> >    must be executed from the clk_prepare()/clk_unprepare() operations.
> 
> Could the above be included in some form in Documentation/clk.txt (this 
> is likely one of the first location people look for information) and 
> elsewhere if appropriate please?
> 
> A *lot* of people are confused by the prepare-enable-disable-unprepare 
> sequence and when I try to find some rational for the prepare/enable 
> split I can only direct them to mail archive posts since this is nowhere 
> to be found in the kernel.
> 
> The comments in include/linux/clk.h, while correct, are very terse and 
> don't provide any insight to the reason why there is a split in the API.
> 
> The content of Documentation/clk.txt does refer to prepare and enable 
> (and their counterparts) but again doesn't provide any clue about the 
> reason for their existence.
> 
> Since there've been several good posts with usage example now buried 
> into list archives, I think this would go a long way helping people get 
> it right if those were part of the kernel documentation as well.

I'll update Documentation/clk.txt with more verbosity. The document was
originally intended as a "porting guide" to help migrate from legacy
frameworks to the common struct clk implementation. However the scope of
the document should probably be generalized a bit more.

Regards,
Mike

> 
> 
> Nicolas

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 13/31] clk: wrap I/O access for improved portability
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-08-02 22:30           ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:30 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:40)
> the common clock drivers were motivated/initiated by ARM development
> and apparently assume little endian peripherals
> 
> wrap register/peripherals access in the common code (div, gate, mux)
> in preparation of adding COMMON_CLK support for other platforms
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

I've taken this into clk-next for testing. regmap deserves investigation
but I don't think your series should be blocked on that. We can always
overhaul the basic clock primitives with regmap support later on if that
makes sense.

Regards,
Mike

> ---
>  drivers/clk/clk-divider.c    |    6 +++---
>  drivers/clk/clk-gate.c       |    6 +++---
>  drivers/clk/clk-mux.c        |    6 +++---
>  include/linux/clk-provider.h |   17 +++++++++++++++++
>  4 files changed, 26 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 6d55eb2..2c07061 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>         struct clk_divider *divider = to_clk_divider(hw);
>         unsigned int div, val;
>  
> -       val = readl(divider->reg) >> divider->shift;
> +       val = clk_readl(divider->reg) >> divider->shift;
>         val &= div_mask(divider);
>  
>         div = _get_div(divider, val);
> @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
>         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
>                 val = div_mask(divider) << (divider->shift + 16);
>         } else {
> -               val = readl(divider->reg);
> +               val = clk_readl(divider->reg);
>                 val &= ~(div_mask(divider) << divider->shift);
>         }
>         val |= value << divider->shift;
> -       writel(val, divider->reg);
> +       clk_writel(val, divider->reg);
>  
>         if (divider->lock)
>                 spin_unlock_irqrestore(divider->lock, flags);
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> index 790306e..b7fbd96 100644
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                 if (set)
>                         reg |= BIT(gate->bit_idx);
>         } else {
> -               reg = readl(gate->reg);
> +               reg = clk_readl(gate->reg);
>  
>                 if (set)
>                         reg |= BIT(gate->bit_idx);
> @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                         reg &= ~BIT(gate->bit_idx);
>         }
>  
> -       writel(reg, gate->reg);
> +       clk_writel(reg, gate->reg);
>  
>         if (gate->lock)
>                 spin_unlock_irqrestore(gate->lock, flags);
> @@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
>         u32 reg;
>         struct clk_gate *gate = to_clk_gate(hw);
>  
> -       reg = readl(gate->reg);
> +       reg = clk_readl(gate->reg);
>  
>         /* if a set bit disables this clk, flip it before masking */
>         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
> diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> index 614444c..02ef506 100644
> --- a/drivers/clk/clk-mux.c
> +++ b/drivers/clk/clk-mux.c
> @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
>          * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
>          * val = 0x4 really means "bit 2, index starts at bit 0"
>          */
> -       val = readl(mux->reg) >> mux->shift;
> +       val = clk_readl(mux->reg) >> mux->shift;
>         val &= mux->mask;
>  
>         if (mux->table) {
> @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
>         if (mux->flags & CLK_MUX_HIWORD_MASK) {
>                 val = mux->mask << (mux->shift + 16);
>         } else {
> -               val = readl(mux->reg);
> +               val = clk_readl(mux->reg);
>                 val &= ~(mux->mask << mux->shift);
>         }
>         val |= index << mux->shift;
> -       writel(val, mux->reg);
> +       clk_writel(val, mux->reg);
>  
>         if (mux->lock)
>                 spin_unlock_irqrestore(mux->lock, flags);
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 1ec14a7..c4f7799 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -12,6 +12,7 @@
>  #define __LINUX_CLK_PROVIDER_H
>  
>  #include <linux/clk.h>
> +#include <linux/io.h>
>  
>  #ifdef CONFIG_COMMON_CLK
>  
> @@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
>  #define of_clk_init(matches) \
>         { while (0); }
>  #endif /* CONFIG_OF */
> +
> +/*
> + * wrap access to peripherals in accessor routines
> + * for improved portability across platforms
> + */
> +
> +static inline u32 clk_readl(u32 __iomem *reg)
> +{
> +       return readl(reg);
> +}
> +
> +static inline void clk_writel(u32 val, u32 __iomem *reg)
> +{
> +       writel(val, reg);
> +}
> +
>  #endif /* CONFIG_COMMON_CLK */
>  #endif /* CLK_PROVIDER_H */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 13/31] clk: wrap I/O access for improved portability
@ 2013-08-02 22:30           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:30 UTC (permalink / raw)
  To: Gerhard Sittig, linuxppc-dev, Anatolij Gustschin,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:40)
> the common clock drivers were motivated/initiated by ARM development
> and apparently assume little endian peripherals
> =

> wrap register/peripherals access in the common code (div, gate, mux)
> in preparation of adding COMMON_CLK support for other platforms
> =

> Signed-off-by: Gerhard Sittig <gsi@denx.de>

I've taken this into clk-next for testing. regmap deserves investigation
but I don't think your series should be blocked on that. We can always
overhaul the basic clock primitives with regmap support later on if that
makes sense.

Regards,
Mike

> ---
>  drivers/clk/clk-divider.c    |    6 +++---
>  drivers/clk/clk-gate.c       |    6 +++---
>  drivers/clk/clk-mux.c        |    6 +++---
>  include/linux/clk-provider.h |   17 +++++++++++++++++
>  4 files changed, 26 insertions(+), 9 deletions(-)
> =

> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 6d55eb2..2c07061 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct c=
lk_hw *hw,
>         struct clk_divider *divider =3D to_clk_divider(hw);
>         unsigned int div, val;
>  =

> -       val =3D readl(divider->reg) >> divider->shift;
> +       val =3D clk_readl(divider->reg) >> divider->shift;
>         val &=3D div_mask(divider);
>  =

>         div =3D _get_div(divider, val);
> @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, =
unsigned long rate,
>         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
>                 val =3D div_mask(divider) << (divider->shift + 16);
>         } else {
> -               val =3D readl(divider->reg);
> +               val =3D clk_readl(divider->reg);
>                 val &=3D ~(div_mask(divider) << divider->shift);
>         }
>         val |=3D value << divider->shift;
> -       writel(val, divider->reg);
> +       clk_writel(val, divider->reg);
>  =

>         if (divider->lock)
>                 spin_unlock_irqrestore(divider->lock, flags);
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> index 790306e..b7fbd96 100644
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int e=
nable)
>                 if (set)
>                         reg |=3D BIT(gate->bit_idx);
>         } else {
> -               reg =3D readl(gate->reg);
> +               reg =3D clk_readl(gate->reg);
>  =

>                 if (set)
>                         reg |=3D BIT(gate->bit_idx);
> @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int e=
nable)
>                         reg &=3D ~BIT(gate->bit_idx);
>         }
>  =

> -       writel(reg, gate->reg);
> +       clk_writel(reg, gate->reg);
>  =

>         if (gate->lock)
>                 spin_unlock_irqrestore(gate->lock, flags);
> @@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
>         u32 reg;
>         struct clk_gate *gate =3D to_clk_gate(hw);
>  =

> -       reg =3D readl(gate->reg);
> +       reg =3D clk_readl(gate->reg);
>  =

>         /* if a set bit disables this clk, flip it before masking */
>         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
> diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> index 614444c..02ef506 100644
> --- a/drivers/clk/clk-mux.c
> +++ b/drivers/clk/clk-mux.c
> @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
>          * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock,=
 so
>          * val =3D 0x4 really means "bit 2, index starts at bit 0"
>          */
> -       val =3D readl(mux->reg) >> mux->shift;
> +       val =3D clk_readl(mux->reg) >> mux->shift;
>         val &=3D mux->mask;
>  =

>         if (mux->table) {
> @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 i=
ndex)
>         if (mux->flags & CLK_MUX_HIWORD_MASK) {
>                 val =3D mux->mask << (mux->shift + 16);
>         } else {
> -               val =3D readl(mux->reg);
> +               val =3D clk_readl(mux->reg);
>                 val &=3D ~(mux->mask << mux->shift);
>         }
>         val |=3D index << mux->shift;
> -       writel(val, mux->reg);
> +       clk_writel(val, mux->reg);
>  =

>         if (mux->lock)
>                 spin_unlock_irqrestore(mux->lock, flags);
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 1ec14a7..c4f7799 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -12,6 +12,7 @@
>  #define __LINUX_CLK_PROVIDER_H
>  =

>  #include <linux/clk.h>
> +#include <linux/io.h>
>  =

>  #ifdef CONFIG_COMMON_CLK
>  =

> @@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(str=
uct device_node *np,
>  #define of_clk_init(matches) \
>         { while (0); }
>  #endif /* CONFIG_OF */
> +
> +/*
> + * wrap access to peripherals in accessor routines
> + * for improved portability across platforms
> + */
> +
> +static inline u32 clk_readl(u32 __iomem *reg)
> +{
> +       return readl(reg);
> +}
> +
> +static inline void clk_writel(u32 val, u32 __iomem *reg)
> +{
> +       writel(val, reg);
> +}
> +
>  #endif /* CONFIG_COMMON_CLK */
>  #endif /* CLK_PROVIDER_H */
> -- =

> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 13/31] clk: wrap I/O access for improved portability
@ 2013-08-02 22:30           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:30 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-07-22 05:14:40)
> the common clock drivers were motivated/initiated by ARM development
> and apparently assume little endian peripherals
> 
> wrap register/peripherals access in the common code (div, gate, mux)
> in preparation of adding COMMON_CLK support for other platforms
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

I've taken this into clk-next for testing. regmap deserves investigation
but I don't think your series should be blocked on that. We can always
overhaul the basic clock primitives with regmap support later on if that
makes sense.

Regards,
Mike

> ---
>  drivers/clk/clk-divider.c    |    6 +++---
>  drivers/clk/clk-gate.c       |    6 +++---
>  drivers/clk/clk-mux.c        |    6 +++---
>  include/linux/clk-provider.h |   17 +++++++++++++++++
>  4 files changed, 26 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 6d55eb2..2c07061 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>         struct clk_divider *divider = to_clk_divider(hw);
>         unsigned int div, val;
>  
> -       val = readl(divider->reg) >> divider->shift;
> +       val = clk_readl(divider->reg) >> divider->shift;
>         val &= div_mask(divider);
>  
>         div = _get_div(divider, val);
> @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
>         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
>                 val = div_mask(divider) << (divider->shift + 16);
>         } else {
> -               val = readl(divider->reg);
> +               val = clk_readl(divider->reg);
>                 val &= ~(div_mask(divider) << divider->shift);
>         }
>         val |= value << divider->shift;
> -       writel(val, divider->reg);
> +       clk_writel(val, divider->reg);
>  
>         if (divider->lock)
>                 spin_unlock_irqrestore(divider->lock, flags);
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> index 790306e..b7fbd96 100644
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                 if (set)
>                         reg |= BIT(gate->bit_idx);
>         } else {
> -               reg = readl(gate->reg);
> +               reg = clk_readl(gate->reg);
>  
>                 if (set)
>                         reg |= BIT(gate->bit_idx);
> @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                         reg &= ~BIT(gate->bit_idx);
>         }
>  
> -       writel(reg, gate->reg);
> +       clk_writel(reg, gate->reg);
>  
>         if (gate->lock)
>                 spin_unlock_irqrestore(gate->lock, flags);
> @@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
>         u32 reg;
>         struct clk_gate *gate = to_clk_gate(hw);
>  
> -       reg = readl(gate->reg);
> +       reg = clk_readl(gate->reg);
>  
>         /* if a set bit disables this clk, flip it before masking */
>         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
> diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> index 614444c..02ef506 100644
> --- a/drivers/clk/clk-mux.c
> +++ b/drivers/clk/clk-mux.c
> @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
>          * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
>          * val = 0x4 really means "bit 2, index starts at bit 0"
>          */
> -       val = readl(mux->reg) >> mux->shift;
> +       val = clk_readl(mux->reg) >> mux->shift;
>         val &= mux->mask;
>  
>         if (mux->table) {
> @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
>         if (mux->flags & CLK_MUX_HIWORD_MASK) {
>                 val = mux->mask << (mux->shift + 16);
>         } else {
> -               val = readl(mux->reg);
> +               val = clk_readl(mux->reg);
>                 val &= ~(mux->mask << mux->shift);
>         }
>         val |= index << mux->shift;
> -       writel(val, mux->reg);
> +       clk_writel(val, mux->reg);
>  
>         if (mux->lock)
>                 spin_unlock_irqrestore(mux->lock, flags);
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 1ec14a7..c4f7799 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -12,6 +12,7 @@
>  #define __LINUX_CLK_PROVIDER_H
>  
>  #include <linux/clk.h>
> +#include <linux/io.h>
>  
>  #ifdef CONFIG_COMMON_CLK
>  
> @@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
>  #define of_clk_init(matches) \
>         { while (0); }
>  #endif /* CONFIG_OF */
> +
> +/*
> + * wrap access to peripherals in accessor routines
> + * for improved portability across platforms
> + */
> +
> +static inline u32 clk_readl(u32 __iomem *reg)
> +{
> +       return readl(reg);
> +}
> +
> +static inline void clk_writel(u32 val, u32 __iomem *reg)
> +{
> +       writel(val, reg);
> +}
> +
>  #endif /* CONFIG_COMMON_CLK */
>  #endif /* CLK_PROVIDER_H */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-08-02 22:43           ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, Pantelis Antoniou,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:42)
> introduce a dt-bindings/ header file for MPC512x clocks,
> providing symbolic identifiers for those SoC clocks which
> clients will reference from their device tree nodes
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
> 
> diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
> new file mode 100644
> index 0000000..46c560e
> --- /dev/null
> +++ b/include/dt-bindings/clock/mpc512x-clock.h
> @@ -0,0 +1,59 @@
> +/*
> + * This header provides constants for MPC512x clock specs in DT bindings.
> + *
> + * Unfortunately the clock number declaration cannot be an enum but
> + * needs to be a list of #define directives since when referenced from
> + * within DTS files they need to get resolved "at compile time".

Above comment is not really necessary. Otherwise,

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> + */
> +
> +#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> +#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> +
> +#define MPC512x_CLK_DUMMY              0
> +#define MPC512x_CLK_REF                        1
> +#define MPC512x_CLK_SYS                        2
> +#define MPC512x_CLK_DIU                        3
> +#define MPC512x_CLK_VIU                        4
> +#define MPC512x_CLK_CSB                        5
> +#define MPC512x_CLK_E300               6
> +#define MPC512x_CLK_IPS                        7
> +#define MPC512x_CLK_FEC                        8
> +#define MPC512x_CLK_SATA               9
> +#define MPC512x_CLK_PATA               10
> +#define MPC512x_CLK_NFC                        11
> +#define MPC512x_CLK_LPC                        12
> +#define MPC512x_CLK_MBX_BUS            13
> +#define MPC512x_CLK_MBX                        14
> +#define MPC512x_CLK_MBX_3D             15
> +#define MPC512x_CLK_AXE                        16
> +#define MPC512x_CLK_USB1               17
> +#define MPC512x_CLK_USB2               18
> +#define MPC512x_CLK_I2C                        19
> +#define MPC512x_CLK_MSCAN0_MCLK                20
> +#define MPC512x_CLK_MSCAN1_MCLK                21
> +#define MPC512x_CLK_MSCAN2_MCLK                22
> +#define MPC512x_CLK_MSCAN3_MCLK                23
> +#define MPC512x_CLK_SDHC               24
> +#define MPC512x_CLK_PCI                        25
> +#define MPC512x_CLK_PSC_MCLK_IN                26
> +#define MPC512x_CLK_SPDIF_TX           27
> +#define MPC512x_CLK_SPDIF_RX           28
> +#define MPC512x_CLK_SPDIF_MCLK         29
> +#define MPC512x_CLK_AC97               30
> +#define MPC512x_CLK_PSC0_MCLK          31
> +#define MPC512x_CLK_PSC1_MCLK          32
> +#define MPC512x_CLK_PSC2_MCLK          33
> +#define MPC512x_CLK_PSC3_MCLK          34
> +#define MPC512x_CLK_PSC4_MCLK          35
> +#define MPC512x_CLK_PSC5_MCLK          36
> +#define MPC512x_CLK_PSC6_MCLK          37
> +#define MPC512x_CLK_PSC7_MCLK          38
> +#define MPC512x_CLK_PSC8_MCLK          39
> +#define MPC512x_CLK_PSC9_MCLK          40
> +#define MPC512x_CLK_PSC10_MCLK         41
> +#define MPC512x_CLK_PSC11_MCLK         42
> +#define MPC512x_CLK_PSC_FIFO           43
> +
> +#define MPC512x_CLK_LAST_PUBLIC                43
> +
> +#endif
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-08-02 22:43           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:43 UTC (permalink / raw)
  To: Gerhard Sittig, linuxppc-dev, Anatolij Gustschin,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:42)
> introduce a dt-bindings/ header file for MPC512x clocks,
> providing symbolic identifiers for those SoC clocks which
> clients will reference from their device tree nodes
> =

> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++=
++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
> =

> diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindi=
ngs/clock/mpc512x-clock.h
> new file mode 100644
> index 0000000..46c560e
> --- /dev/null
> +++ b/include/dt-bindings/clock/mpc512x-clock.h
> @@ -0,0 +1,59 @@
> +/*
> + * This header provides constants for MPC512x clock specs in DT bindings.
> + *
> + * Unfortunately the clock number declaration cannot be an enum but
> + * needs to be a list of #define directives since when referenced from
> + * within DTS files they need to get resolved "at compile time".

Above comment is not really necessary. Otherwise,

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> + */
> +
> +#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> +#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> +
> +#define MPC512x_CLK_DUMMY              0
> +#define MPC512x_CLK_REF                        1
> +#define MPC512x_CLK_SYS                        2
> +#define MPC512x_CLK_DIU                        3
> +#define MPC512x_CLK_VIU                        4
> +#define MPC512x_CLK_CSB                        5
> +#define MPC512x_CLK_E300               6
> +#define MPC512x_CLK_IPS                        7
> +#define MPC512x_CLK_FEC                        8
> +#define MPC512x_CLK_SATA               9
> +#define MPC512x_CLK_PATA               10
> +#define MPC512x_CLK_NFC                        11
> +#define MPC512x_CLK_LPC                        12
> +#define MPC512x_CLK_MBX_BUS            13
> +#define MPC512x_CLK_MBX                        14
> +#define MPC512x_CLK_MBX_3D             15
> +#define MPC512x_CLK_AXE                        16
> +#define MPC512x_CLK_USB1               17
> +#define MPC512x_CLK_USB2               18
> +#define MPC512x_CLK_I2C                        19
> +#define MPC512x_CLK_MSCAN0_MCLK                20
> +#define MPC512x_CLK_MSCAN1_MCLK                21
> +#define MPC512x_CLK_MSCAN2_MCLK                22
> +#define MPC512x_CLK_MSCAN3_MCLK                23
> +#define MPC512x_CLK_SDHC               24
> +#define MPC512x_CLK_PCI                        25
> +#define MPC512x_CLK_PSC_MCLK_IN                26
> +#define MPC512x_CLK_SPDIF_TX           27
> +#define MPC512x_CLK_SPDIF_RX           28
> +#define MPC512x_CLK_SPDIF_MCLK         29
> +#define MPC512x_CLK_AC97               30
> +#define MPC512x_CLK_PSC0_MCLK          31
> +#define MPC512x_CLK_PSC1_MCLK          32
> +#define MPC512x_CLK_PSC2_MCLK          33
> +#define MPC512x_CLK_PSC3_MCLK          34
> +#define MPC512x_CLK_PSC4_MCLK          35
> +#define MPC512x_CLK_PSC5_MCLK          36
> +#define MPC512x_CLK_PSC6_MCLK          37
> +#define MPC512x_CLK_PSC7_MCLK          38
> +#define MPC512x_CLK_PSC8_MCLK          39
> +#define MPC512x_CLK_PSC9_MCLK          40
> +#define MPC512x_CLK_PSC10_MCLK         41
> +#define MPC512x_CLK_PSC11_MCLK         42
> +#define MPC512x_CLK_PSC_FIFO           43
> +
> +#define MPC512x_CLK_LAST_PUBLIC                43
> +
> +#endif
> -- =

> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-08-02 22:43           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:43 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-07-22 05:14:42)
> introduce a dt-bindings/ header file for MPC512x clocks,
> providing symbolic identifiers for those SoC clocks which
> clients will reference from their device tree nodes
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
>  1 file changed, 59 insertions(+)
>  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
> 
> diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
> new file mode 100644
> index 0000000..46c560e
> --- /dev/null
> +++ b/include/dt-bindings/clock/mpc512x-clock.h
> @@ -0,0 +1,59 @@
> +/*
> + * This header provides constants for MPC512x clock specs in DT bindings.
> + *
> + * Unfortunately the clock number declaration cannot be an enum but
> + * needs to be a list of #define directives since when referenced from
> + * within DTS files they need to get resolved "at compile time".

Above comment is not really necessary. Otherwise,

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> + */
> +
> +#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> +#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> +
> +#define MPC512x_CLK_DUMMY              0
> +#define MPC512x_CLK_REF                        1
> +#define MPC512x_CLK_SYS                        2
> +#define MPC512x_CLK_DIU                        3
> +#define MPC512x_CLK_VIU                        4
> +#define MPC512x_CLK_CSB                        5
> +#define MPC512x_CLK_E300               6
> +#define MPC512x_CLK_IPS                        7
> +#define MPC512x_CLK_FEC                        8
> +#define MPC512x_CLK_SATA               9
> +#define MPC512x_CLK_PATA               10
> +#define MPC512x_CLK_NFC                        11
> +#define MPC512x_CLK_LPC                        12
> +#define MPC512x_CLK_MBX_BUS            13
> +#define MPC512x_CLK_MBX                        14
> +#define MPC512x_CLK_MBX_3D             15
> +#define MPC512x_CLK_AXE                        16
> +#define MPC512x_CLK_USB1               17
> +#define MPC512x_CLK_USB2               18
> +#define MPC512x_CLK_I2C                        19
> +#define MPC512x_CLK_MSCAN0_MCLK                20
> +#define MPC512x_CLK_MSCAN1_MCLK                21
> +#define MPC512x_CLK_MSCAN2_MCLK                22
> +#define MPC512x_CLK_MSCAN3_MCLK                23
> +#define MPC512x_CLK_SDHC               24
> +#define MPC512x_CLK_PCI                        25
> +#define MPC512x_CLK_PSC_MCLK_IN                26
> +#define MPC512x_CLK_SPDIF_TX           27
> +#define MPC512x_CLK_SPDIF_RX           28
> +#define MPC512x_CLK_SPDIF_MCLK         29
> +#define MPC512x_CLK_AC97               30
> +#define MPC512x_CLK_PSC0_MCLK          31
> +#define MPC512x_CLK_PSC1_MCLK          32
> +#define MPC512x_CLK_PSC2_MCLK          33
> +#define MPC512x_CLK_PSC3_MCLK          34
> +#define MPC512x_CLK_PSC4_MCLK          35
> +#define MPC512x_CLK_PSC5_MCLK          36
> +#define MPC512x_CLK_PSC6_MCLK          37
> +#define MPC512x_CLK_PSC7_MCLK          38
> +#define MPC512x_CLK_PSC8_MCLK          39
> +#define MPC512x_CLK_PSC9_MCLK          40
> +#define MPC512x_CLK_PSC10_MCLK         41
> +#define MPC512x_CLK_PSC11_MCLK         42
> +#define MPC512x_CLK_PSC_FIFO           43
> +
> +#define MPC512x_CLK_LAST_PUBLIC                43
> +
> +#endif
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-08-02 22:46           ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:46 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:43)
> this addresses the clock driver aka provider's side of clocks
> - prepare for future '<&clks ID>' phandle references for device tree
>   based clock lookup in client drivers
> - introduce a 'clocks' subtree with an 'osc' node for the crystal
>   or oscillator SoC input (fixed frequency)
> - provide default values with 33MHz oscillator frequency in the
>   common include (the 66MHz IPS bus already was there), add
>   override values for the ifm AC14xx board which deviates from
>   the reference design (25MHz xtal, 80MHz IPS bus)
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> ---
>  arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
>  arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
>  2 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
> index a543c40..a1b8837 100644
> --- a/arch/powerpc/boot/dts/ac14xx.dts
> +++ b/arch/powerpc/boot/dts/ac14xx.dts
> @@ -139,7 +139,14 @@
>                 };
>         };
>  
> +       clocks {
> +               osc {
> +                       clock-frequency = <25000000>;
> +               };
> +       };
> +
>         soc@80000000 {
> +               bus-frequency = <80000000>;     /* 80 MHz ips bus */
>  
>                 clock@f00 {
>                         compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
> diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
> index bd14c00..8f4cba0 100644
> --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> @@ -9,6 +9,8 @@
>   * option) any later version.
>   */
>  
> +#include <dt-bindings/clock/mpc512x-clock.h>
> +
>  /dts-v1/;
>  
>  / {
> @@ -73,6 +75,16 @@
>                 ranges = <0x0 0x0 0xfc000000 0x04000000>;
>         };
>  
> +       clocks {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               osc {
> +                       compatible = "fsl,mpc512x-osc", "fixed-clock";
> +                       clock-frequency = <33000000>;
> +               };
> +       };
> +
>         soc@80000000 {
>                 compatible = "fsl,mpc5121-immr";
>                 #address-cells = <1>;
> @@ -118,9 +130,10 @@
>                 };
>  
>                 /* Clock control */
> -               clock@f00 {
> +               clks: clock@f00 {
>                         compatible = "fsl,mpc5121-clock";
>                         reg = <0xf00 0x100>;
> +                       #clock-cells = <1>;
>                 };
>  
>                 /* Power Management Controller */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs
@ 2013-08-02 22:46           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:46 UTC (permalink / raw)
  To: Gerhard Sittig, linuxppc-dev, Anatolij Gustschin,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:43)
> this addresses the clock driver aka provider's side of clocks
> - prepare for future '<&clks ID>' phandle references for device tree
>   based clock lookup in client drivers
> - introduce a 'clocks' subtree with an 'osc' node for the crystal
>   or oscillator SoC input (fixed frequency)
> - provide default values with 33MHz oscillator frequency in the
>   common include (the 66MHz IPS bus already was there), add
>   override values for the ifm AC14xx board which deviates from
>   the reference design (25MHz xtal, 80MHz IPS bus)
> =

> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> ---
>  arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
>  arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
>  2 files changed, 21 insertions(+), 1 deletion(-)
> =

> diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac1=
4xx.dts
> index a543c40..a1b8837 100644
> --- a/arch/powerpc/boot/dts/ac14xx.dts
> +++ b/arch/powerpc/boot/dts/ac14xx.dts
> @@ -139,7 +139,14 @@
>                 };
>         };
>  =

> +       clocks {
> +               osc {
> +                       clock-frequency =3D <25000000>;
> +               };
> +       };
> +
>         soc@80000000 {
> +               bus-frequency =3D <80000000>;     /* 80 MHz ips bus */
>  =

>                 clock@f00 {
>                         compatible =3D "fsl,mpc5121rev2-clock", "fsl,mpc5=
121-clock";
> diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/m=
pc5121.dtsi
> index bd14c00..8f4cba0 100644
> --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> @@ -9,6 +9,8 @@
>   * option) any later version.
>   */
>  =

> +#include <dt-bindings/clock/mpc512x-clock.h>
> +
>  /dts-v1/;
>  =

>  / {
> @@ -73,6 +75,16 @@
>                 ranges =3D <0x0 0x0 0xfc000000 0x04000000>;
>         };
>  =

> +       clocks {
> +               #address-cells =3D <1>;
> +               #size-cells =3D <0>;
> +
> +               osc {
> +                       compatible =3D "fsl,mpc512x-osc", "fixed-clock";
> +                       clock-frequency =3D <33000000>;
> +               };
> +       };
> +
>         soc@80000000 {
>                 compatible =3D "fsl,mpc5121-immr";
>                 #address-cells =3D <1>;
> @@ -118,9 +130,10 @@
>                 };
>  =

>                 /* Clock control */
> -               clock@f00 {
> +               clks: clock@f00 {
>                         compatible =3D "fsl,mpc5121-clock";
>                         reg =3D <0xf00 0x100>;
> +                       #clock-cells =3D <1>;
>                 };
>  =

>                 /* Power Management Controller */
> -- =

> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs
@ 2013-08-02 22:46           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 22:46 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-07-22 05:14:43)
> this addresses the clock driver aka provider's side of clocks
> - prepare for future '<&clks ID>' phandle references for device tree
>   based clock lookup in client drivers
> - introduce a 'clocks' subtree with an 'osc' node for the crystal
>   or oscillator SoC input (fixed frequency)
> - provide default values with 33MHz oscillator frequency in the
>   common include (the 66MHz IPS bus already was there), add
>   override values for the ifm AC14xx board which deviates from
>   the reference design (25MHz xtal, 80MHz IPS bus)
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> ---
>  arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
>  arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
>  2 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
> index a543c40..a1b8837 100644
> --- a/arch/powerpc/boot/dts/ac14xx.dts
> +++ b/arch/powerpc/boot/dts/ac14xx.dts
> @@ -139,7 +139,14 @@
>                 };
>         };
>  
> +       clocks {
> +               osc {
> +                       clock-frequency = <25000000>;
> +               };
> +       };
> +
>         soc at 80000000 {
> +               bus-frequency = <80000000>;     /* 80 MHz ips bus */
>  
>                 clock at f00 {
>                         compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
> diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
> index bd14c00..8f4cba0 100644
> --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> @@ -9,6 +9,8 @@
>   * option) any later version.
>   */
>  
> +#include <dt-bindings/clock/mpc512x-clock.h>
> +
>  /dts-v1/;
>  
>  / {
> @@ -73,6 +75,16 @@
>                 ranges = <0x0 0x0 0xfc000000 0x04000000>;
>         };
>  
> +       clocks {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               osc {
> +                       compatible = "fsl,mpc512x-osc", "fixed-clock";
> +                       clock-frequency = <33000000>;
> +               };
> +       };
> +
>         soc at 80000000 {
>                 compatible = "fsl,mpc5121-immr";
>                 #address-cells = <1>;
> @@ -118,9 +130,10 @@
>                 };
>  
>                 /* Clock control */
> -               clock at f00 {
> +               clks: clock at f00 {
>                         compatible = "fsl,mpc5121-clock";
>                         reg = <0xf00 0x100>;
> +                       #clock-cells = <1>;
>                 };
>  
>                 /* Power Management Controller */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-23 13:14           ` Gerhard Sittig
@ 2013-08-02 23:30             ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:30 UTC (permalink / raw)
  To: Gerhard Sittig, linuxppc-dev, Anatolij Gustschin,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-23 06:14:06)
> [ summary: "shared gate" support desirable? approach acceptable? ]
> =

> On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> > =

> > this change implements a clock driver for the MPC512x PowerPC platform
> > which follows the COMMON_CLK approach and uses common clock drivers
> > shared with other platforms
> > =

> > [ ... ]
> > =

> > some of the clock items get pre-enabled in the clock driver to not have
> > them automatically disabled by the underlying clock subsystem because of
> > their being unused -- this approach is desirable because
> > [ ... ]
> > - some help introduce support for and migrate to the common
> >   infrastructure, while more appropriate support for specific hardware
> >   constraints isn't available yet (remaining changes are strictly
> >   internal to the clock driver and won't affect peripheral drivers)
> =

> This remark was related to the CAN clocks of the MPC512x SoC.

Gerhard,

Thanks for the patch (way far down below here). I'll check into it to
see if that implementation looks OK. It would be helpful if another
platform with shared gates could weigh in on whether the implementation
works for them.

Still, a shared gate solution is not a prerequisite for this series,
correct?

Regards,
Mike

> =

> The clock subtrees which are involved in generating CAN bitrates
> include one path from the XTAL to an internal MCLK (this is part
> of the CCF support for the platform), and another path from the
> MCLK or yet another IP bus clock to the actual bitrate on the
> wire (this is taken care of within the mscan(4) driver).
> =

> The MCLK generation for CAN is documented in the MPC5121e
> Reference Manual, chapter 5, section 5.2.5 "MSCAN Clock
> Generation".  SYS, REF (both internal), PSC_MCLK_IN, and SPDIF_TX
> (both external) are muxed, gated, and divided.  The result is
> muxed with IP.  The result is fed into the MSCAN component and
> gets muxed with IP again (can't tell why, maybe for backwards
> compatibility).
> =

> In parallel to this MCLK block there is SCCR2[25], the "BDLC and
> MSCAN clock enable", documented in section 5.3.1.3 "System Clock
> Control Register 2".  So there is a gate that "somehow needs to
> get setup" yet isn't part of the visible MCLK chain.
> =

> The series up to and including v3 approaches the problem by
> - adding a gate after the second MCLK mux, which gets exported
>   for client lookups and is the MCLK input for the mscan(4)
>   driver
> - creating that gate for each of the four MSCAN clocks of the
>   SoC, all of them referencing the single "enable" bit in the
>   SCCR2 register
> - pre-enabling the MSCAN clocks from within the clock driver, and
>   thus avoid having the clock disabled from the common
>   infrastructure, because disabling one of these clocks had
>   closed the shared gate and thus had broken all other clock uses
> =

> > clkdev registration provides "alias names" for few clock items
> > [ ... ]
> > =

> [ ... ]
> > +
> > +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> > +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> > +{
> > +     size_t clks_idx_pub, clks_idx_int;
> > +     u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> > +     u32 __iomem *sccr_reg;  /* system clock control register (enable)=
 */
> > +     int sccr_bit;
> > +     int div;
> > +
> > +     /* derive a few parameters from the component type and index */
> > +     switch (entry->type) {
> > +     case MCLK_TYPE_PSC:
> > +             clks_idx_pub =3D MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> > +             clks_idx_int =3D MPC512x_CLK_MCLKS_FIRST
> > +                          + (entry->comp_idx) * MCLK_MAX_IDX;
> > +             mccr_reg =3D &clkregs->psc_ccr[entry->comp_idx];
> > +             break;
> > +     case MCLK_TYPE_MSCAN:
> > +             clks_idx_pub =3D MPC512x_CLK_MSCAN0_MCLK + entry->comp_id=
x;
> > +             clks_idx_int =3D MPC512x_CLK_MCLKS_FIRST
> > +                          + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> > +             mccr_reg =3D &clkregs->mscan_ccr[entry->comp_idx];
> > +             break;
> > +     case MCLK_TYPE_SPDIF:
> > +             clks_idx_pub =3D MPC512x_CLK_SPDIF_MCLK;
> > +             clks_idx_int =3D MPC512x_CLK_MCLKS_FIRST
> > +                          + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> > +             mccr_reg =3D &clkregs->spccr;
> > +             break;
> > +     default:
> > +             return;
> > +     }
> > +     if (entry->bit_sccr1 >=3D 0) {
> > +             sccr_reg =3D &clkregs->sccr1;
> > +             sccr_bit =3D entry->bit_sccr1;
> > +     } else if (entry->bit_sccr2 >=3D 0) {
> > +             sccr_reg =3D &clkregs->sccr2;
> > +             sccr_bit =3D entry->bit_sccr2;
> > +     } else {
> > +             sccr_reg =3D NULL;
> > +     }
> > +
> > +     /*
> > +      * this was grabbed from the PPC_CLOCK implementation, which
> > +      * enforced a specific MCLK divider while the clock was gated
> > +      * during setup (that's a documented hardware requirement)
> > +      *
> > +      * the PPC_CLOCK implementation might even have violated the
> > +      * "MCLK <=3D IPS" constraint, the fixed divider value of 1
> > +      * results in a divider of 2 and thus MCLK =3D SYS/2 which equals
> > +      * CSB which is greater than IPS; the serial port setup may have
> > +      * adjusted the divider which the clock setup might have left in
> > +      * an undesirable state
> > +      *
> > +      * initial setup is:
> > +      * - MCLK 0 from SYS
> > +      * - MCLK DIV such to not exceed the IPS clock
> > +      * - MCLK 0 enabled
> > +      * - MCLK 1 from MCLK DIV
> > +      */
> > +     div =3D clk_get_rate(clks[MPC512x_CLK_SYS]);
> > +     div /=3D clk_get_rate(clks[MPC512x_CLK_IPS]);
> > +     out_be32(mccr_reg, (0 << 16));
> > +     out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> > +     out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> > +
> > +     /*
> > +      * create the 'struct clk' items of the MCLK's clock subtree
> > +      *
> > +      * note that by design we always create all nodes and won't take
> > +      * shortcuts here, because
> > +      * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> > +      *   selectable inputs to the CFM while those who "actually use"
> > +      *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> > +      *   for their bitrate
> > +      * - in the absence of "aliases" for clocks we need to create
> > +      *   individial 'struct clk' items for whatever might get
> > +      *   referenced or looked up, even if several of those items are
> > +      *   identical from the logical POV (their rate value)
> > +      * - for easier future maintenance and for better reflection of
> > +      *   the SoC's documentation, it appears appropriate to generate
> > +      *   clock items even for those muxers which actually are NOPs
> > +      *   (those with two inputs of which one is reserved)
> > +      */
> > +     clks[clks_idx_int + MCLK_IDX_MUX0] =3D mpc512x_clk_muxed(
> > +                     entry->name_mux0,
> > +                     &parent_names_mux0[0], ARRAY_SIZE(parent_names_mu=
x0),
> > +                     mccr_reg, 14, 2);
> > +     clks[clks_idx_int + MCLK_IDX_EN0] =3D mpc512x_clk_gated(
> > +                     entry->name_en0, entry->name_mux0,
> > +                     mccr_reg, 16);
> > +     clks[clks_idx_int + MCLK_IDX_DIV0] =3D mpc512x_clk_divider(
> > +                     entry->name_div0,
> > +                     entry->name_en0, CLK_SET_RATE_GATE,
> > +                     mccr_reg, 17, 15, 0);
> > +     if (entry->has_mclk1) {
> > +             clks[clks_idx_int + MCLK_IDX_MUX1] =3D mpc512x_clk_muxed(
> > +                             entry->name_mux1,
> > +                             &entry->parent_names_mux1[0],
> > +                             ARRAY_SIZE(entry->parent_names_mux1),
> > +                             mccr_reg, 7, 1);
> > +     } else {
> > +             clks[clks_idx_int + MCLK_IDX_MUX1] =3D mpc512x_clk_factor(
> > +                             entry->name_mux1, entry->parent_names_mux=
1[0],
> > +                             1, 1);
> > +     }
> > +     if (sccr_reg) {
> > +             clks[clks_idx_pub] =3D mpc512x_clk_gated(
> > +                             entry->name_mclk,
> > +                             entry->name_mux1, sccr_reg, sccr_bit);
> > +     } else {
> > +             clks[clks_idx_pub] =3D mpc512x_clk_factor(
> > +                             entry->name_mclk,
> > +                             entry->name_mux1, 1, 1);
> > +     }
> > +
> > +     /*
> > +      * without this "clock device" registration, "simple" lookups in
> > +      * the SPI master initialization and serial port setup will fail
> > +      *
> > +      * those drivers need to get adjusted to lookup their required
> > +      * clocks from device tree specs, and device tree nodes need to
> > +      * provide the clock specs, before this clkdev registration
> > +      * becomes obsolete
> > +      */
> > +     clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> > +}
> > [ ... ]
> =

> This was the routine which sets up _one_ MCLK block, note the
> assignment at the routine's end to the "published" clock item
> that's the gate's output after the second mux stage.
> =

> > [ ... ]
> > +     clks[MPC512x_CLK_I2C] =3D mpc512x_clk_gated("i2c", "ips",
> > +                                               &clkregs->sccr2, 26);
> > +     mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_da=
ta));
> > +     clks[MPC512x_CLK_SDHC] =3D mpc512x_clk_gated("sdhc", "sdhc-ug",
> > +                                                &clkregs->sccr2, 24);
> > +     mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_da=
ta));
> > [ ... ]
> =

> This is the invocation of the routine which sets up four MCLK
> blocks for the MSCAN components, while all of them refer to bit
> 25 of SCCR2.
> =

> > [ ... ]
> > +
> > +     /* enable some of the clocks here unconditionally because ... */
> > +     pr_debug("automatically enabling some clocks\n");
> > +     /* some are essential yet never get claimed by any driver */
> > +     clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> > +     clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> > +     clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> > +     clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> > +     clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> > +     /* some are required yet no dependencies were declared */
> > +     clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> > +     /* some are not yet acquired by their respective drivers */
> > +     clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console=
 */
> > +     clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> > +     clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> > +     clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> > +     /*
> > +      * some have their individual clock subtree with separate clock
> > +      * items and their individual enable counters, yet share a
> > +      * common gate (refer to the same register location) while the
> > +      * common clock driver code is not aware of the fact and the
> > +      * platform's code doesn't provide specific support either
> > +      *
> > +      * what might happen is that e.g. enabling two MSCAN clock items
> > +      * and disabling one of them will disable the common gate and
> > +      * thus break the other MSCAN clock as well
> > +      */
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> > +}
> =

> This is the pre-enable workaround for the MSCAN0 to MSCAN3 clock
> items.
> =

> The above approach does work in that it introduces complete
> support for common clock on the MPC512x platform, with the CAN
> component being operational, and the clock driver using shared
> logic across platforms.
> =

> The remaining issue is that regardless of whether CAN is used,
> the (chip internal) clock is enabled.  This may not be a problem
> when bitrates aren't generated and the wire isn't driven.
> =

> =

> The question now is how to correctly support the situation where
> a gate is shared between subtrees yet isn't really part of any
> path within the subtrees.  I really cannot find a single spot
> where to introduce the gate such that it's not duplicated.
> =

> The appropriate solution would not be to pre-enable those clocks,
> but to either introduce another gate clock type which supports a
> shared reference, or to add support for the shared reference to
> the existing gate code.
> =

> =

> I'd rather not duplicate most or all of the code of clk-gate.c,
> instead I looked into how to add "shared gate" support to the
> existing driver.
> =

> My question is whether the approach is acceptable.  It adds
> minimal overhead and shall be OK for the enable/disable path from
> a technical POV.  And it doesn't feel like too much of a stretch.
> But there may be non-technical reasons to reject the approach.
> I'd like to learn whether to follow that path before preparing
> another version of the patch series.
> =

> The diffs were taken with the '-w -b' options to demonstrate
> their essence and not drown it in whitespace changes.  The
> implementation assumes that the caller which registers the gate
> (the platform's clock driver) provides both the counter cell and
> the lock.  And that all gates with a "shared use counter" use the
> same lock (which is satisfied as they all get registered from the
> same spot in the platform's clock driver).
> =

> The CLK_IGNORE_UNUSED flag addresses a different problem.  The
> SoC has four MSCAN components, while two of them are enabled in
> the device tree (the other two are present but disabled).  So
> during probe two of the clocks get enabled.  After probe all
> unused clocks automatically get disabled (that's another two).
> So the "shared use counter" drops to zero although components are
> in use, because "disable, it's unused" isn't told from "disable
> after enable, regular use".  The flag would become obsolete if
> the common gate logic would implement a separate disable_unused()
> routine, but I guess this isn't necessary and the use of the flag
> is appropriate.
> =

> That the example use creates a field for just one counter is to
> better demonstrate the use and potential extension as need
> arises.  Reducing this to a mere integer variable would be a
> micro optimization.
> =

> =

> The extension of the existing clk_gate implementation:
> =

> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int e=
nable)
>         struct clk_gate *gate =3D to_clk_gate(hw);
>         int set =3D gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
>         unsigned long flags =3D 0;
> +       int need_reg_access;
>         u32 reg;
>  =

>         set ^=3D enable;
> @@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int =
enable)
>         if (gate->lock)
>                 spin_lock_irqsave(gate->lock, flags);
>  =

> +       /*
> +        * if a "shared use counter" was specified, keep track of enable
> +        * and disable calls and only access hardware registers upon the
> +        * very first enable or very last disable call
> +        */
> +       if (!gate->share_count) {
> +               need_reg_access =3D 1;
> +       } else if (enable) {
> +               need_reg_access =3D (*gate->share_count)++ =3D=3D 0;
> +       } else {
> +               need_reg_access =3D --(*gate->share_count) =3D=3D 0;
> +       }
> +
> +       if (need_reg_access) {
>                 if (gate->flags & CLK_GATE_HIWORD_MASK) {
>                         reg =3D BIT(gate->bit_idx + 16);
>                         if (set)
> @@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int e=
nable)
>                 }
>  =

>                 clk_writel(reg, gate->reg);
> +       }
>  =

>         if (gate->lock)
>                 spin_unlock_irqrestore(gate->lock, flags);
> @@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
>   * @clk_gate_flags: gate-specific flags for this clock
>   * @lock: shared register lock for this clock
>   */
> -struct clk *clk_register_gate(struct device *dev, const char *name,
> +struct clk *clk_register_gate_shared(struct device *dev, const char *nam=
e,
>                 const char *parent_name, unsigned long flags,
>                 void __iomem *reg, u8 bit_idx,
> -               u8 clk_gate_flags, spinlock_t *lock)
> +               u8 clk_gate_flags, spinlock_t *lock,
> +               int *share_count)
>  {
>         struct clk_gate *gate;
>         struct clk *clk;
> @@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, con=
st char *name,
>         gate->bit_idx =3D bit_idx;
>         gate->flags =3D clk_gate_flags;
>         gate->lock =3D lock;
> +       gate->share_count =3D share_count;
>         gate->hw.init =3D &init;
>  =

>         clk =3D clk_register(dev, &gate->hw);
> @@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, co=
nst char *name,
>  =

>         return clk;
>  }
> +
> +struct clk *clk_register_gate(struct device *dev, const char *name,
> +               const char *parent_name, unsigned long flags,
> +               void __iomem *reg, u8 bit_idx,
> +               u8 clk_gate_flags, spinlock_t *lock)
> +{
> +
> +       return clk_register_gate_shared(dev, name, parent_name, flags,
> +                                       reg, bit_idx, clk_gate_flags,
> +                                       lock, NULL);
> +}
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -222,6 +222,7 @@ struct clk_gate {
>         u8              bit_idx;
>         u8              flags;
>         spinlock_t      *lock;
> +       int             *share_count;
>  };
>  =

>  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> @@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, co=
nst char *name,
>                 const char *parent_name, unsigned long flags,
>                 void __iomem *reg, u8 bit_idx,
>                 u8 clk_gate_flags, spinlock_t *lock);
> +struct clk *clk_register_gate_shared(struct device *dev, const char *nam=
e,
> +               const char *parent_name, unsigned long flags,
> +               void __iomem *reg, u8 bit_idx,
> +               u8 clk_gate_flags, spinlock_t *lock,
> +               int *share_count);
>  =

>  struct clk_div_table {
>         unsigned int    val;
> =

> =

> How to use these shared gates:
> =

> --- a/arch/powerpc/platforms/512x/clock-commonclk.c
> +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> @@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
>                                  reg, pos, 0, &clklock);
>  }
>  =

> +enum mpc512x_clk_shared_gate_id_t {
> +       MPC512x_CLK_SHARED_GATE_MSCAN,
> +       MPC512x_CLK_SHARED_GATE_MAX,
> +};
> +
> +static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
> +
> +/*
> + * implementor's note:  since clk_gate items don't implement a separate
> + * .disable_unused() callback, their .disable() routine gets called and
> + * "disable the clock as we can't see it's in use" cannot be told from
> + * "regular disable, count these events please"
> + *
> + * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
> + * the "disable, unused" call, so use counts won't get unbalanced, the
> + * clock either never got enabled and thus need not get disabled, or
> + * part of the hardware got enabled while disabling the other part isn't
> + * wanted
> + */
> +static inline struct clk *mpc512x_clk_gated_shared(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos,
> +       enum mpc512x_clk_shared_gate_id_t share_id)
> +{
> +       int clkflags;
> +
> +       clkflags =3D CLK_SET_RATE_PARENT;
> +       clkflags |=3D CLK_IGNORE_UNUSED;
> +       return clk_register_gate_shared(NULL, name, parent_name, clkflags,
> +                                       reg, pos, 0, &clklock,
> +                                       &mpc512x_clk_gate_counters[share_=
id]);
> +}
> +
>  static inline struct clk *mpc512x_clk_muxed(const char *name,
>         const char **parent_names, int parent_count,
>         u32 __iomem *reg, u8 pos, u8 len)
> @@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup=
_data *entry)
>                                 1, 1);
>         }
>         if (sccr_reg) {
> +               if (entry->type =3D=3D MCLK_TYPE_MSCAN) {
> +                       clks[clks_idx_pub] =3D mpc512x_clk_gated_shared(
> +                                       entry->name_mclk,
> +                                       entry->name_mux1, sccr_reg, sccr_=
bit,
> +                                       MPC512x_CLK_SHARED_GATE_MSCAN);
> +               } else {
>                         clks[clks_idx_pub] =3D mpc512x_clk_gated(
>                                         entry->name_mclk,
>                                         entry->name_mux1, sccr_reg, sccr_=
bit);
> +               }
>         } else {
>                 clks[clks_idx_pub] =3D mpc512x_clk_factor(
>                                 entry->name_mclk,
> =

> Local tests have shown that the extension solves the problem of
> how to satisfy the SoC's constraints on the MPC512x platform.
> The MSCAN clocks no longer need to get pre-enabled, instead they
> get setup and enabled only as the mscan(4) driver probes devices
> according to how it was instructed (device tree nodes).
> =

> What do you think?  Is the "shared gate" support in the common
> logic appropriate?  I'd rather not duplicate all of this code
> just to introduce the specific gate I need, while most of the
> logic is identical to the existing gate implementation.  The
> desire isn't to override the gate's operations, but to wrap them
> and to consult a counter in addition, while the register access
> still applies.
> =

> =

> =

> virtually yours
> Gerhard Sittig
> -- =

> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-02 23:30             ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:30 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-07-23 06:14:06)
> [ summary: "shared gate" support desirable? approach acceptable? ]
> 
> On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> > 
> > this change implements a clock driver for the MPC512x PowerPC platform
> > which follows the COMMON_CLK approach and uses common clock drivers
> > shared with other platforms
> > 
> > [ ... ]
> > 
> > some of the clock items get pre-enabled in the clock driver to not have
> > them automatically disabled by the underlying clock subsystem because of
> > their being unused -- this approach is desirable because
> > [ ... ]
> > - some help introduce support for and migrate to the common
> >   infrastructure, while more appropriate support for specific hardware
> >   constraints isn't available yet (remaining changes are strictly
> >   internal to the clock driver and won't affect peripheral drivers)
> 
> This remark was related to the CAN clocks of the MPC512x SoC.

Gerhard,

Thanks for the patch (way far down below here). I'll check into it to
see if that implementation looks OK. It would be helpful if another
platform with shared gates could weigh in on whether the implementation
works for them.

Still, a shared gate solution is not a prerequisite for this series,
correct?

Regards,
Mike

> 
> The clock subtrees which are involved in generating CAN bitrates
> include one path from the XTAL to an internal MCLK (this is part
> of the CCF support for the platform), and another path from the
> MCLK or yet another IP bus clock to the actual bitrate on the
> wire (this is taken care of within the mscan(4) driver).
> 
> The MCLK generation for CAN is documented in the MPC5121e
> Reference Manual, chapter 5, section 5.2.5 "MSCAN Clock
> Generation".  SYS, REF (both internal), PSC_MCLK_IN, and SPDIF_TX
> (both external) are muxed, gated, and divided.  The result is
> muxed with IP.  The result is fed into the MSCAN component and
> gets muxed with IP again (can't tell why, maybe for backwards
> compatibility).
> 
> In parallel to this MCLK block there is SCCR2[25], the "BDLC and
> MSCAN clock enable", documented in section 5.3.1.3 "System Clock
> Control Register 2".  So there is a gate that "somehow needs to
> get setup" yet isn't part of the visible MCLK chain.
> 
> The series up to and including v3 approaches the problem by
> - adding a gate after the second MCLK mux, which gets exported
>   for client lookups and is the MCLK input for the mscan(4)
>   driver
> - creating that gate for each of the four MSCAN clocks of the
>   SoC, all of them referencing the single "enable" bit in the
>   SCCR2 register
> - pre-enabling the MSCAN clocks from within the clock driver, and
>   thus avoid having the clock disabled from the common
>   infrastructure, because disabling one of these clocks had
>   closed the shared gate and thus had broken all other clock uses
> 
> > clkdev registration provides "alias names" for few clock items
> > [ ... ]
> > 
> [ ... ]
> > +
> > +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> > +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> > +{
> > +     size_t clks_idx_pub, clks_idx_int;
> > +     u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> > +     u32 __iomem *sccr_reg;  /* system clock control register (enable) */
> > +     int sccr_bit;
> > +     int div;
> > +
> > +     /* derive a few parameters from the component type and index */
> > +     switch (entry->type) {
> > +     case MCLK_TYPE_PSC:
> > +             clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> > +             clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                          + (entry->comp_idx) * MCLK_MAX_IDX;
> > +             mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> > +             break;
> > +     case MCLK_TYPE_MSCAN:
> > +             clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> > +             clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                          + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> > +             mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> > +             break;
> > +     case MCLK_TYPE_SPDIF:
> > +             clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> > +             clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                          + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> > +             mccr_reg = &clkregs->spccr;
> > +             break;
> > +     default:
> > +             return;
> > +     }
> > +     if (entry->bit_sccr1 >= 0) {
> > +             sccr_reg = &clkregs->sccr1;
> > +             sccr_bit = entry->bit_sccr1;
> > +     } else if (entry->bit_sccr2 >= 0) {
> > +             sccr_reg = &clkregs->sccr2;
> > +             sccr_bit = entry->bit_sccr2;
> > +     } else {
> > +             sccr_reg = NULL;
> > +     }
> > +
> > +     /*
> > +      * this was grabbed from the PPC_CLOCK implementation, which
> > +      * enforced a specific MCLK divider while the clock was gated
> > +      * during setup (that's a documented hardware requirement)
> > +      *
> > +      * the PPC_CLOCK implementation might even have violated the
> > +      * "MCLK <= IPS" constraint, the fixed divider value of 1
> > +      * results in a divider of 2 and thus MCLK = SYS/2 which equals
> > +      * CSB which is greater than IPS; the serial port setup may have
> > +      * adjusted the divider which the clock setup might have left in
> > +      * an undesirable state
> > +      *
> > +      * initial setup is:
> > +      * - MCLK 0 from SYS
> > +      * - MCLK DIV such to not exceed the IPS clock
> > +      * - MCLK 0 enabled
> > +      * - MCLK 1 from MCLK DIV
> > +      */
> > +     div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> > +     div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> > +     out_be32(mccr_reg, (0 << 16));
> > +     out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> > +     out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> > +
> > +     /*
> > +      * create the 'struct clk' items of the MCLK's clock subtree
> > +      *
> > +      * note that by design we always create all nodes and won't take
> > +      * shortcuts here, because
> > +      * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> > +      *   selectable inputs to the CFM while those who "actually use"
> > +      *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> > +      *   for their bitrate
> > +      * - in the absence of "aliases" for clocks we need to create
> > +      *   individial 'struct clk' items for whatever might get
> > +      *   referenced or looked up, even if several of those items are
> > +      *   identical from the logical POV (their rate value)
> > +      * - for easier future maintenance and for better reflection of
> > +      *   the SoC's documentation, it appears appropriate to generate
> > +      *   clock items even for those muxers which actually are NOPs
> > +      *   (those with two inputs of which one is reserved)
> > +      */
> > +     clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> > +                     entry->name_mux0,
> > +                     &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> > +                     mccr_reg, 14, 2);
> > +     clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> > +                     entry->name_en0, entry->name_mux0,
> > +                     mccr_reg, 16);
> > +     clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> > +                     entry->name_div0,
> > +                     entry->name_en0, CLK_SET_RATE_GATE,
> > +                     mccr_reg, 17, 15, 0);
> > +     if (entry->has_mclk1) {
> > +             clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> > +                             entry->name_mux1,
> > +                             &entry->parent_names_mux1[0],
> > +                             ARRAY_SIZE(entry->parent_names_mux1),
> > +                             mccr_reg, 7, 1);
> > +     } else {
> > +             clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> > +                             entry->name_mux1, entry->parent_names_mux1[0],
> > +                             1, 1);
> > +     }
> > +     if (sccr_reg) {
> > +             clks[clks_idx_pub] = mpc512x_clk_gated(
> > +                             entry->name_mclk,
> > +                             entry->name_mux1, sccr_reg, sccr_bit);
> > +     } else {
> > +             clks[clks_idx_pub] = mpc512x_clk_factor(
> > +                             entry->name_mclk,
> > +                             entry->name_mux1, 1, 1);
> > +     }
> > +
> > +     /*
> > +      * without this "clock device" registration, "simple" lookups in
> > +      * the SPI master initialization and serial port setup will fail
> > +      *
> > +      * those drivers need to get adjusted to lookup their required
> > +      * clocks from device tree specs, and device tree nodes need to
> > +      * provide the clock specs, before this clkdev registration
> > +      * becomes obsolete
> > +      */
> > +     clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> > +}
> > [ ... ]
> 
> This was the routine which sets up _one_ MCLK block, note the
> assignment at the routine's end to the "published" clock item
> that's the gate's output after the second mux stage.
> 
> > [ ... ]
> > +     clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> > +                                               &clkregs->sccr2, 26);
> > +     mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> > +     clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> > +                                                &clkregs->sccr2, 24);
> > +     mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> > [ ... ]
> 
> This is the invocation of the routine which sets up four MCLK
> blocks for the MSCAN components, while all of them refer to bit
> 25 of SCCR2.
> 
> > [ ... ]
> > +
> > +     /* enable some of the clocks here unconditionally because ... */
> > +     pr_debug("automatically enabling some clocks\n");
> > +     /* some are essential yet never get claimed by any driver */
> > +     clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> > +     clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> > +     clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> > +     clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> > +     clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> > +     /* some are required yet no dependencies were declared */
> > +     clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> > +     /* some are not yet acquired by their respective drivers */
> > +     clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> > +     clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> > +     clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> > +     clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> > +     /*
> > +      * some have their individual clock subtree with separate clock
> > +      * items and their individual enable counters, yet share a
> > +      * common gate (refer to the same register location) while the
> > +      * common clock driver code is not aware of the fact and the
> > +      * platform's code doesn't provide specific support either
> > +      *
> > +      * what might happen is that e.g. enabling two MSCAN clock items
> > +      * and disabling one of them will disable the common gate and
> > +      * thus break the other MSCAN clock as well
> > +      */
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> > +     clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> > +}
> 
> This is the pre-enable workaround for the MSCAN0 to MSCAN3 clock
> items.
> 
> The above approach does work in that it introduces complete
> support for common clock on the MPC512x platform, with the CAN
> component being operational, and the clock driver using shared
> logic across platforms.
> 
> The remaining issue is that regardless of whether CAN is used,
> the (chip internal) clock is enabled.  This may not be a problem
> when bitrates aren't generated and the wire isn't driven.
> 
> 
> The question now is how to correctly support the situation where
> a gate is shared between subtrees yet isn't really part of any
> path within the subtrees.  I really cannot find a single spot
> where to introduce the gate such that it's not duplicated.
> 
> The appropriate solution would not be to pre-enable those clocks,
> but to either introduce another gate clock type which supports a
> shared reference, or to add support for the shared reference to
> the existing gate code.
> 
> 
> I'd rather not duplicate most or all of the code of clk-gate.c,
> instead I looked into how to add "shared gate" support to the
> existing driver.
> 
> My question is whether the approach is acceptable.  It adds
> minimal overhead and shall be OK for the enable/disable path from
> a technical POV.  And it doesn't feel like too much of a stretch.
> But there may be non-technical reasons to reject the approach.
> I'd like to learn whether to follow that path before preparing
> another version of the patch series.
> 
> The diffs were taken with the '-w -b' options to demonstrate
> their essence and not drown it in whitespace changes.  The
> implementation assumes that the caller which registers the gate
> (the platform's clock driver) provides both the counter cell and
> the lock.  And that all gates with a "shared use counter" use the
> same lock (which is satisfied as they all get registered from the
> same spot in the platform's clock driver).
> 
> The CLK_IGNORE_UNUSED flag addresses a different problem.  The
> SoC has four MSCAN components, while two of them are enabled in
> the device tree (the other two are present but disabled).  So
> during probe two of the clocks get enabled.  After probe all
> unused clocks automatically get disabled (that's another two).
> So the "shared use counter" drops to zero although components are
> in use, because "disable, it's unused" isn't told from "disable
> after enable, regular use".  The flag would become obsolete if
> the common gate logic would implement a separate disable_unused()
> routine, but I guess this isn't necessary and the use of the flag
> is appropriate.
> 
> That the example use creates a field for just one counter is to
> better demonstrate the use and potential extension as need
> arises.  Reducing this to a mere integer variable would be a
> micro optimization.
> 
> 
> The extension of the existing clk_gate implementation:
> 
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>         struct clk_gate *gate = to_clk_gate(hw);
>         int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
>         unsigned long flags = 0;
> +       int need_reg_access;
>         u32 reg;
>  
>         set ^= enable;
> @@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>         if (gate->lock)
>                 spin_lock_irqsave(gate->lock, flags);
>  
> +       /*
> +        * if a "shared use counter" was specified, keep track of enable
> +        * and disable calls and only access hardware registers upon the
> +        * very first enable or very last disable call
> +        */
> +       if (!gate->share_count) {
> +               need_reg_access = 1;
> +       } else if (enable) {
> +               need_reg_access = (*gate->share_count)++ == 0;
> +       } else {
> +               need_reg_access = --(*gate->share_count) == 0;
> +       }
> +
> +       if (need_reg_access) {
>                 if (gate->flags & CLK_GATE_HIWORD_MASK) {
>                         reg = BIT(gate->bit_idx + 16);
>                         if (set)
> @@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
>                 }
>  
>                 clk_writel(reg, gate->reg);
> +       }
>  
>         if (gate->lock)
>                 spin_unlock_irqrestore(gate->lock, flags);
> @@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
>   * @clk_gate_flags: gate-specific flags for this clock
>   * @lock: shared register lock for this clock
>   */
> -struct clk *clk_register_gate(struct device *dev, const char *name,
> +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
>                 const char *parent_name, unsigned long flags,
>                 void __iomem *reg, u8 bit_idx,
> -               u8 clk_gate_flags, spinlock_t *lock)
> +               u8 clk_gate_flags, spinlock_t *lock,
> +               int *share_count)
>  {
>         struct clk_gate *gate;
>         struct clk *clk;
> @@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
>         gate->bit_idx = bit_idx;
>         gate->flags = clk_gate_flags;
>         gate->lock = lock;
> +       gate->share_count = share_count;
>         gate->hw.init = &init;
>  
>         clk = clk_register(dev, &gate->hw);
> @@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
>  
>         return clk;
>  }
> +
> +struct clk *clk_register_gate(struct device *dev, const char *name,
> +               const char *parent_name, unsigned long flags,
> +               void __iomem *reg, u8 bit_idx,
> +               u8 clk_gate_flags, spinlock_t *lock)
> +{
> +
> +       return clk_register_gate_shared(dev, name, parent_name, flags,
> +                                       reg, bit_idx, clk_gate_flags,
> +                                       lock, NULL);
> +}
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -222,6 +222,7 @@ struct clk_gate {
>         u8              bit_idx;
>         u8              flags;
>         spinlock_t      *lock;
> +       int             *share_count;
>  };
>  
>  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> @@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
>                 const char *parent_name, unsigned long flags,
>                 void __iomem *reg, u8 bit_idx,
>                 u8 clk_gate_flags, spinlock_t *lock);
> +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> +               const char *parent_name, unsigned long flags,
> +               void __iomem *reg, u8 bit_idx,
> +               u8 clk_gate_flags, spinlock_t *lock,
> +               int *share_count);
>  
>  struct clk_div_table {
>         unsigned int    val;
> 
> 
> How to use these shared gates:
> 
> --- a/arch/powerpc/platforms/512x/clock-commonclk.c
> +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> @@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
>                                  reg, pos, 0, &clklock);
>  }
>  
> +enum mpc512x_clk_shared_gate_id_t {
> +       MPC512x_CLK_SHARED_GATE_MSCAN,
> +       MPC512x_CLK_SHARED_GATE_MAX,
> +};
> +
> +static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
> +
> +/*
> + * implementor's note:  since clk_gate items don't implement a separate
> + * .disable_unused() callback, their .disable() routine gets called and
> + * "disable the clock as we can't see it's in use" cannot be told from
> + * "regular disable, count these events please"
> + *
> + * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
> + * the "disable, unused" call, so use counts won't get unbalanced, the
> + * clock either never got enabled and thus need not get disabled, or
> + * part of the hardware got enabled while disabling the other part isn't
> + * wanted
> + */
> +static inline struct clk *mpc512x_clk_gated_shared(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos,
> +       enum mpc512x_clk_shared_gate_id_t share_id)
> +{
> +       int clkflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       clkflags |= CLK_IGNORE_UNUSED;
> +       return clk_register_gate_shared(NULL, name, parent_name, clkflags,
> +                                       reg, pos, 0, &clklock,
> +                                       &mpc512x_clk_gate_counters[share_id]);
> +}
> +
>  static inline struct clk *mpc512x_clk_muxed(const char *name,
>         const char **parent_names, int parent_count,
>         u32 __iomem *reg, u8 pos, u8 len)
> @@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
>                                 1, 1);
>         }
>         if (sccr_reg) {
> +               if (entry->type == MCLK_TYPE_MSCAN) {
> +                       clks[clks_idx_pub] = mpc512x_clk_gated_shared(
> +                                       entry->name_mclk,
> +                                       entry->name_mux1, sccr_reg, sccr_bit,
> +                                       MPC512x_CLK_SHARED_GATE_MSCAN);
> +               } else {
>                         clks[clks_idx_pub] = mpc512x_clk_gated(
>                                         entry->name_mclk,
>                                         entry->name_mux1, sccr_reg, sccr_bit);
> +               }
>         } else {
>                 clks[clks_idx_pub] = mpc512x_clk_factor(
>                                 entry->name_mclk,
> 
> Local tests have shown that the extension solves the problem of
> how to satisfy the SoC's constraints on the MPC512x platform.
> The MSCAN clocks no longer need to get pre-enabled, instead they
> get setup and enabled only as the mscan(4) driver probes devices
> according to how it was instructed (device tree nodes).
> 
> What do you think?  Is the "shared gate" support in the common
> logic appropriate?  I'd rather not duplicate all of this code
> just to introduce the specific gate I need, while most of the
> logic is identical to the existing gate implementation.  The
> desire isn't to override the gate's operations, but to wrap them
> and to consult a counter in addition, while the register access
> still applies.
> 
> 
> 
> virtually yours
> Gerhard Sittig
> -- 
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-08-02 23:41           ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:41 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:45)
> this addresses the client side of device tree based clock lookups
> 
> add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
> mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
> mpc5121.dtsi include
> 
> these specs map 'clock-names' encoded in drivers to their respective
> 'struct clk' items in the platform's clock driver
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> ---
>  arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
> 
> diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
> index 8f4cba0..3657ae6 100644
> --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> @@ -51,6 +51,10 @@
>                 compatible = "fsl,mpc5121-mbx";
>                 reg = <0x20000000 0x4000>;
>                 interrupts = <66 0x8>;
> +               clocks = <&clks MPC512x_CLK_MBX_BUS>,
> +                        <&clks MPC512x_CLK_MBX_3D>,
> +                        <&clks MPC512x_CLK_MBX>;
> +               clock-names = "mbx-bus", "mbx-3d", "mbx";
>         };
>  
>         sram@30000000 {
> @@ -64,6 +68,8 @@
>                 interrupts = <6 8>;
>                 #address-cells = <1>;
>                 #size-cells = <1>;
> +               clocks = <&clks MPC512x_CLK_NFC>;
> +               clock-names = "per";
>         };
>  
>         localbus@80000020 {
> @@ -153,12 +159,22 @@
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x1300 0x80>;
>                         interrupts = <12 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN0_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 can@1380 {
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x1380 0x80>;
>                         interrupts = <13 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN1_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 sdhc@1500 {
> @@ -167,6 +183,9 @@
>                         interrupts = <8 0x8>;
>                         dmas = <&dma0 30>;
>                         dma-names = "rx-tx";
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SDHC>;
> +                       clock-names = "ipg", "per";
>                 };
>  
>                 i2c@1700 {
> @@ -175,6 +194,8 @@
>                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg = <0x1700 0x20>;
>                         interrupts = <9 0x8>;
> +                       clocks = <&clks MPC512x_CLK_I2C>;
> +                       clock-names = "per";
>                 };
>  
>                 i2c@1720 {
> @@ -183,6 +204,8 @@
>                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg = <0x1720 0x20>;
>                         interrupts = <10 0x8>;
> +                       clocks = <&clks MPC512x_CLK_I2C>;
> +                       clock-names = "per";
>                 };
>  
>                 i2c@1740 {
> @@ -191,6 +214,8 @@
>                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg = <0x1740 0x20>;
>                         interrupts = <11 0x8>;
> +                       clocks = <&clks MPC512x_CLK_I2C>;
> +                       clock-names = "per";
>                 };
>  
>                 i2ccontrol@1760 {
> @@ -202,30 +227,46 @@
>                         compatible = "fsl,mpc5121-axe";
>                         reg = <0x2000 0x100>;
>                         interrupts = <42 0x8>;
> +                       clocks = <&clks MPC512x_CLK_AXE>;
> +                       clock-names = "per";
>                 };
>  
>                 display@2100 {
>                         compatible = "fsl,mpc5121-diu";
>                         reg = <0x2100 0x100>;
>                         interrupts = <64 0x8>;
> +                       clocks = <&clks MPC512x_CLK_DIU>;
> +                       clock-names = "per";
>                 };
>  
>                 can@2300 {
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x2300 0x80>;
>                         interrupts = <90 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN2_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 can@2380 {
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x2380 0x80>;
>                         interrupts = <91 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN3_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 viu@2400 {
>                         compatible = "fsl,mpc5121-viu";
>                         reg = <0x2400 0x400>;
>                         interrupts = <67 0x8>;
> +                       clocks = <&clks MPC512x_CLK_VIU>;
> +                       clock-names = "per";
>                 };
>  
>                 mdio@2800 {
> @@ -233,6 +274,8 @@
>                         reg = <0x2800 0x800>;
>                         #address-cells = <1>;
>                         #size-cells = <0>;
> +                       clocks = <&clks MPC512x_CLK_FEC>;
> +                       clock-names = "per";
>                 };
>  
>                 eth0: ethernet@2800 {
> @@ -241,6 +284,8 @@
>                         reg = <0x2800 0x800>;
>                         local-mac-address = [ 00 00 00 00 00 00 ];
>                         interrupts = <4 0x8>;
> +                       clocks = <&clks MPC512x_CLK_FEC>;
> +                       clock-names = "per";
>                 };
>  
>                 /* USB1 using external ULPI PHY */
> @@ -252,6 +297,8 @@
>                         interrupts = <43 0x8>;
>                         dr_mode = "otg";
>                         phy_type = "ulpi";
> +                       clocks = <&clks MPC512x_CLK_USB1>;
> +                       clock-names = "per";
>                 };
>  
>                 /* USB0 using internal UTMI PHY */
> @@ -263,6 +310,8 @@
>                         interrupts = <44 0x8>;
>                         dr_mode = "otg";
>                         phy_type = "utmi_wide";
> +                       clocks = <&clks MPC512x_CLK_USB2>;
> +                       clock-names = "per";
>                 };
>  
>                 /* IO control */
> @@ -281,6 +330,8 @@
>                         compatible = "fsl,mpc5121-pata";
>                         reg = <0x10200 0x100>;
>                         interrupts = <5 0x8>;
> +                       clocks = <&clks MPC512x_CLK_PATA>;
> +                       clock-names = "per";
>                 };
>  
>                 /* 512x PSCs are not 52xx PSC compatible */
> @@ -292,6 +343,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC1 */
> @@ -301,6 +354,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC2 */
> @@ -310,6 +365,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC3 */
> @@ -319,6 +376,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC4 */
> @@ -328,6 +387,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC5 */
> @@ -337,6 +398,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC6 */
> @@ -346,6 +409,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC7 */
> @@ -355,6 +420,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC8 */
> @@ -364,6 +431,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC9 */
> @@ -373,6 +442,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC10 */
> @@ -382,6 +453,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC11 */
> @@ -391,12 +464,16 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 pscfifo@11f00 {
>                         compatible = "fsl,mpc5121-psc-fifo";
>                         reg = <0x11f00 0x100>;
>                         interrupts = <40 0x8>;
> +                       clocks = <&clks MPC512x_CLK_PSC_FIFO>;
> +                       clock-names = "per";
>                 };
>  
>                 dma0: dma@14000 {
> @@ -414,6 +491,8 @@
>                 #address-cells = <3>;
>                 #size-cells = <2>;
>                 #interrupt-cells = <1>;
> +               clocks = <&clks MPC512x_CLK_PCI>;
> +               clock-names = "per";
>  
>                 reg = <0x80008500 0x100 /* internal registers */
>                        0x80008300 0x8>; /* config space access registers */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
@ 2013-08-02 23:41           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:41 UTC (permalink / raw)
  To: Gerhard Sittig, linuxppc-dev, Anatolij Gustschin,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:45)
> this addresses the client side of device tree based clock lookups
> =

> add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
> mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
> mpc5121.dtsi include
> =

> these specs map 'clock-names' encoded in drivers to their respective
> 'struct clk' items in the platform's clock driver
> =

> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> ---
>  arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++=
++++++
>  1 file changed, 79 insertions(+)
> =

> diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/m=
pc5121.dtsi
> index 8f4cba0..3657ae6 100644
> --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> @@ -51,6 +51,10 @@
>                 compatible =3D "fsl,mpc5121-mbx";
>                 reg =3D <0x20000000 0x4000>;
>                 interrupts =3D <66 0x8>;
> +               clocks =3D <&clks MPC512x_CLK_MBX_BUS>,
> +                        <&clks MPC512x_CLK_MBX_3D>,
> +                        <&clks MPC512x_CLK_MBX>;
> +               clock-names =3D "mbx-bus", "mbx-3d", "mbx";
>         };
>  =

>         sram@30000000 {
> @@ -64,6 +68,8 @@
>                 interrupts =3D <6 8>;
>                 #address-cells =3D <1>;
>                 #size-cells =3D <1>;
> +               clocks =3D <&clks MPC512x_CLK_NFC>;
> +               clock-names =3D "per";
>         };
>  =

>         localbus@80000020 {
> @@ -153,12 +159,22 @@
>                         compatible =3D "fsl,mpc5121-mscan";
>                         reg =3D <0x1300 0x80>;
>                         interrupts =3D <12 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN0_MCLK>;
> +                       clock-names =3D "ips", "sys", "ref", "mclk";
>                 };
>  =

>                 can@1380 {
>                         compatible =3D "fsl,mpc5121-mscan";
>                         reg =3D <0x1380 0x80>;
>                         interrupts =3D <13 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN1_MCLK>;
> +                       clock-names =3D "ips", "sys", "ref", "mclk";
>                 };
>  =

>                 sdhc@1500 {
> @@ -167,6 +183,9 @@
>                         interrupts =3D <8 0x8>;
>                         dmas =3D <&dma0 30>;
>                         dma-names =3D "rx-tx";
> +                       clocks =3D <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SDHC>;
> +                       clock-names =3D "ipg", "per";
>                 };
>  =

>                 i2c@1700 {
> @@ -175,6 +194,8 @@
>                         compatible =3D "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg =3D <0x1700 0x20>;
>                         interrupts =3D <9 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_I2C>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 i2c@1720 {
> @@ -183,6 +204,8 @@
>                         compatible =3D "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg =3D <0x1720 0x20>;
>                         interrupts =3D <10 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_I2C>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 i2c@1740 {
> @@ -191,6 +214,8 @@
>                         compatible =3D "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg =3D <0x1740 0x20>;
>                         interrupts =3D <11 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_I2C>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 i2ccontrol@1760 {
> @@ -202,30 +227,46 @@
>                         compatible =3D "fsl,mpc5121-axe";
>                         reg =3D <0x2000 0x100>;
>                         interrupts =3D <42 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_AXE>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 display@2100 {
>                         compatible =3D "fsl,mpc5121-diu";
>                         reg =3D <0x2100 0x100>;
>                         interrupts =3D <64 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_DIU>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 can@2300 {
>                         compatible =3D "fsl,mpc5121-mscan";
>                         reg =3D <0x2300 0x80>;
>                         interrupts =3D <90 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN2_MCLK>;
> +                       clock-names =3D "ips", "sys", "ref", "mclk";
>                 };
>  =

>                 can@2380 {
>                         compatible =3D "fsl,mpc5121-mscan";
>                         reg =3D <0x2380 0x80>;
>                         interrupts =3D <91 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN3_MCLK>;
> +                       clock-names =3D "ips", "sys", "ref", "mclk";
>                 };
>  =

>                 viu@2400 {
>                         compatible =3D "fsl,mpc5121-viu";
>                         reg =3D <0x2400 0x400>;
>                         interrupts =3D <67 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_VIU>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 mdio@2800 {
> @@ -233,6 +274,8 @@
>                         reg =3D <0x2800 0x800>;
>                         #address-cells =3D <1>;
>                         #size-cells =3D <0>;
> +                       clocks =3D <&clks MPC512x_CLK_FEC>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 eth0: ethernet@2800 {
> @@ -241,6 +284,8 @@
>                         reg =3D <0x2800 0x800>;
>                         local-mac-address =3D [ 00 00 00 00 00 00 ];
>                         interrupts =3D <4 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_FEC>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 /* USB1 using external ULPI PHY */
> @@ -252,6 +297,8 @@
>                         interrupts =3D <43 0x8>;
>                         dr_mode =3D "otg";
>                         phy_type =3D "ulpi";
> +                       clocks =3D <&clks MPC512x_CLK_USB1>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 /* USB0 using internal UTMI PHY */
> @@ -263,6 +310,8 @@
>                         interrupts =3D <44 0x8>;
>                         dr_mode =3D "otg";
>                         phy_type =3D "utmi_wide";
> +                       clocks =3D <&clks MPC512x_CLK_USB2>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 /* IO control */
> @@ -281,6 +330,8 @@
>                         compatible =3D "fsl,mpc5121-pata";
>                         reg =3D <0x10200 0x100>;
>                         interrupts =3D <5 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_PATA>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 /* 512x PSCs are not 52xx PSC compatible */
> @@ -292,6 +343,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC0_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC1 */
> @@ -301,6 +354,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC1_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC2 */
> @@ -310,6 +365,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC2_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC3 */
> @@ -319,6 +376,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC3_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC4 */
> @@ -328,6 +387,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC4_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC5 */
> @@ -337,6 +398,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC5_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC6 */
> @@ -346,6 +409,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC6_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC7 */
> @@ -355,6 +420,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC7_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC8 */
> @@ -364,6 +431,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC8_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC9 */
> @@ -373,6 +442,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC9_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC10 */
> @@ -382,6 +453,8 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC10_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 /* PSC11 */
> @@ -391,12 +464,16 @@
>                         interrupts =3D <40 0x8>;
>                         fsl,rx-fifo-size =3D <16>;
>                         fsl,tx-fifo-size =3D <16>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC11_MCLK>;
> +                       clock-names =3D "mclk";
>                 };
>  =

>                 pscfifo@11f00 {
>                         compatible =3D "fsl,mpc5121-psc-fifo";
>                         reg =3D <0x11f00 0x100>;
>                         interrupts =3D <40 0x8>;
> +                       clocks =3D <&clks MPC512x_CLK_PSC_FIFO>;
> +                       clock-names =3D "per";
>                 };
>  =

>                 dma0: dma@14000 {
> @@ -414,6 +491,8 @@
>                 #address-cells =3D <3>;
>                 #size-cells =3D <2>;
>                 #interrupt-cells =3D <1>;
> +               clocks =3D <&clks MPC512x_CLK_PCI>;
> +               clock-names =3D "per";
>  =

>                 reg =3D <0x80008500 0x100 /* internal registers */
>                        0x80008300 0x8>; /* config space access registers =
*/
> -- =

> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
@ 2013-08-02 23:41           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:41 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-07-22 05:14:45)
> this addresses the client side of device tree based clock lookups
> 
> add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
> mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
> mpc5121.dtsi include
> 
> these specs map 'clock-names' encoded in drivers to their respective
> 'struct clk' items in the platform's clock driver
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Reviewed-by: Mike Turquette <mturquette@linaro.org>

> ---
>  arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
> 
> diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
> index 8f4cba0..3657ae6 100644
> --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> @@ -51,6 +51,10 @@
>                 compatible = "fsl,mpc5121-mbx";
>                 reg = <0x20000000 0x4000>;
>                 interrupts = <66 0x8>;
> +               clocks = <&clks MPC512x_CLK_MBX_BUS>,
> +                        <&clks MPC512x_CLK_MBX_3D>,
> +                        <&clks MPC512x_CLK_MBX>;
> +               clock-names = "mbx-bus", "mbx-3d", "mbx";
>         };
>  
>         sram at 30000000 {
> @@ -64,6 +68,8 @@
>                 interrupts = <6 8>;
>                 #address-cells = <1>;
>                 #size-cells = <1>;
> +               clocks = <&clks MPC512x_CLK_NFC>;
> +               clock-names = "per";
>         };
>  
>         localbus at 80000020 {
> @@ -153,12 +159,22 @@
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x1300 0x80>;
>                         interrupts = <12 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN0_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 can at 1380 {
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x1380 0x80>;
>                         interrupts = <13 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN1_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 sdhc at 1500 {
> @@ -167,6 +183,9 @@
>                         interrupts = <8 0x8>;
>                         dmas = <&dma0 30>;
>                         dma-names = "rx-tx";
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SDHC>;
> +                       clock-names = "ipg", "per";
>                 };
>  
>                 i2c at 1700 {
> @@ -175,6 +194,8 @@
>                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg = <0x1700 0x20>;
>                         interrupts = <9 0x8>;
> +                       clocks = <&clks MPC512x_CLK_I2C>;
> +                       clock-names = "per";
>                 };
>  
>                 i2c at 1720 {
> @@ -183,6 +204,8 @@
>                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg = <0x1720 0x20>;
>                         interrupts = <10 0x8>;
> +                       clocks = <&clks MPC512x_CLK_I2C>;
> +                       clock-names = "per";
>                 };
>  
>                 i2c at 1740 {
> @@ -191,6 +214,8 @@
>                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
>                         reg = <0x1740 0x20>;
>                         interrupts = <11 0x8>;
> +                       clocks = <&clks MPC512x_CLK_I2C>;
> +                       clock-names = "per";
>                 };
>  
>                 i2ccontrol at 1760 {
> @@ -202,30 +227,46 @@
>                         compatible = "fsl,mpc5121-axe";
>                         reg = <0x2000 0x100>;
>                         interrupts = <42 0x8>;
> +                       clocks = <&clks MPC512x_CLK_AXE>;
> +                       clock-names = "per";
>                 };
>  
>                 display at 2100 {
>                         compatible = "fsl,mpc5121-diu";
>                         reg = <0x2100 0x100>;
>                         interrupts = <64 0x8>;
> +                       clocks = <&clks MPC512x_CLK_DIU>;
> +                       clock-names = "per";
>                 };
>  
>                 can at 2300 {
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x2300 0x80>;
>                         interrupts = <90 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN2_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 can at 2380 {
>                         compatible = "fsl,mpc5121-mscan";
>                         reg = <0x2380 0x80>;
>                         interrupts = <91 0x8>;
> +                       clocks = <&clks MPC512x_CLK_IPS>,
> +                                <&clks MPC512x_CLK_SYS>,
> +                                <&clks MPC512x_CLK_REF>,
> +                                <&clks MPC512x_CLK_MSCAN3_MCLK>;
> +                       clock-names = "ips", "sys", "ref", "mclk";
>                 };
>  
>                 viu at 2400 {
>                         compatible = "fsl,mpc5121-viu";
>                         reg = <0x2400 0x400>;
>                         interrupts = <67 0x8>;
> +                       clocks = <&clks MPC512x_CLK_VIU>;
> +                       clock-names = "per";
>                 };
>  
>                 mdio at 2800 {
> @@ -233,6 +274,8 @@
>                         reg = <0x2800 0x800>;
>                         #address-cells = <1>;
>                         #size-cells = <0>;
> +                       clocks = <&clks MPC512x_CLK_FEC>;
> +                       clock-names = "per";
>                 };
>  
>                 eth0: ethernet at 2800 {
> @@ -241,6 +284,8 @@
>                         reg = <0x2800 0x800>;
>                         local-mac-address = [ 00 00 00 00 00 00 ];
>                         interrupts = <4 0x8>;
> +                       clocks = <&clks MPC512x_CLK_FEC>;
> +                       clock-names = "per";
>                 };
>  
>                 /* USB1 using external ULPI PHY */
> @@ -252,6 +297,8 @@
>                         interrupts = <43 0x8>;
>                         dr_mode = "otg";
>                         phy_type = "ulpi";
> +                       clocks = <&clks MPC512x_CLK_USB1>;
> +                       clock-names = "per";
>                 };
>  
>                 /* USB0 using internal UTMI PHY */
> @@ -263,6 +310,8 @@
>                         interrupts = <44 0x8>;
>                         dr_mode = "otg";
>                         phy_type = "utmi_wide";
> +                       clocks = <&clks MPC512x_CLK_USB2>;
> +                       clock-names = "per";
>                 };
>  
>                 /* IO control */
> @@ -281,6 +330,8 @@
>                         compatible = "fsl,mpc5121-pata";
>                         reg = <0x10200 0x100>;
>                         interrupts = <5 0x8>;
> +                       clocks = <&clks MPC512x_CLK_PATA>;
> +                       clock-names = "per";
>                 };
>  
>                 /* 512x PSCs are not 52xx PSC compatible */
> @@ -292,6 +343,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC1 */
> @@ -301,6 +354,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC2 */
> @@ -310,6 +365,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC3 */
> @@ -319,6 +376,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC4 */
> @@ -328,6 +387,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC5 */
> @@ -337,6 +398,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC6 */
> @@ -346,6 +409,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC7 */
> @@ -355,6 +420,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC8 */
> @@ -364,6 +431,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC9 */
> @@ -373,6 +442,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC10 */
> @@ -382,6 +453,8 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 /* PSC11 */
> @@ -391,12 +464,16 @@
>                         interrupts = <40 0x8>;
>                         fsl,rx-fifo-size = <16>;
>                         fsl,tx-fifo-size = <16>;
> +                       clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
> +                       clock-names = "mclk";
>                 };
>  
>                 pscfifo at 11f00 {
>                         compatible = "fsl,mpc5121-psc-fifo";
>                         reg = <0x11f00 0x100>;
>                         interrupts = <40 0x8>;
> +                       clocks = <&clks MPC512x_CLK_PSC_FIFO>;
> +                       clock-names = "per";
>                 };
>  
>                 dma0: dma at 14000 {
> @@ -414,6 +491,8 @@
>                 #address-cells = <3>;
>                 #size-cells = <2>;
>                 #interrupt-cells = <1>;
> +               clocks = <&clks MPC512x_CLK_PCI>;
> +               clock-names = "per";
>  
>                 reg = <0x80008500 0x100 /* internal registers */
>                        0x80008300 0x8>; /* config space access registers */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-08-02 23:41           ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:41 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:44)
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
> 
> this driver implements the publicly announced set of clocks (which can
> get referenced by means of symbolic identifiers from the dt-bindings
> header file), as well as generates additional 'struct clk' items where
> the SoC hardware cannot easily get mapped to the common primitives of
> the clock API, or requires "intermediate" clock nodes to represent
> clocks that have both gates and dividers
> 
> the previous PPC_CLOCK implementation is kept in place and remains in
> parallel to the common clock implementation for test and comparison
> during migration, a compile time option picks one of the two
> alternatives (Kconfig switch, common clock used by default)
> 
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> - some of the clocks are useful to have for diagnostics and information
>   despite their not getting claimed by any drivers (CPU, internal and
>   external RAM, internal busses, boot media)
> - some of the clocks aren't claimed by their peripheral drivers yet,
>   either because of missing driver support or because device tree specs
>   aren't available yet (but the workarounds will get removed as the
>   drivers get adjusted and the device tree provides the clock specs)
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)
> 
> clkdev registration provides "alias names" for few clock items
> - to not break those peripheral drivers which encode their component
>   index into the name that is used for clock lookup (UART, SPI, USB)
> - to not break those drivers which use names for the clock lookup which
>   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> this workaround will get removed as these drivers get adjusted after
> device tree based clock lookup has become available
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Hi Gerhard,

This looks OK to me. Do you want me to take it or will you keep the
series together? Note that I took "clk: wrap I/O access for improved
portability" into the clk tree already.

Regards,
Mike

> ---
>  arch/powerpc/platforms/512x/Kconfig           |   14 +-
>  arch/powerpc/platforms/512x/Makefile          |    4 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
>  include/linux/clk-provider.h                  |   16 +
>  4 files changed, 818 insertions(+), 2 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> 
> diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
> index fc9c1cb..c5fcdd0 100644
> --- a/arch/powerpc/platforms/512x/Kconfig
> +++ b/arch/powerpc/platforms/512x/Kconfig
> @@ -1,9 +1,21 @@
> +config MPC512x_COMMON_CLK
> +       bool "MPC512x platform uses COMMON_CLK"
> +       default y
> +       depends on PPC_MPC512x
> +       help
> +         This option is only here to support tests and comparison
> +         during development and migration.  This option will get
> +         removed after the COMMON_CLK support for MPC512x has become
> +         fully operational and all drivers were adjusted to explicitly
> +         acquire their required clocks.
> +
>  config PPC_MPC512x
>         bool "512x-based boards"
>         depends on 6xx
>         select FSL_SOC
>         select IPIC
> -       select PPC_CLOCK
> +       select PPC_CLOCK if !MPC512x_COMMON_CLK
> +       select COMMON_CLK if MPC512x_COMMON_CLK
>         select PPC_PCI_CHOICE
>         select FSL_PCI if PCI
>         select ARCH_WANT_OPTIONAL_GPIOLIB
> diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
> index 72fb934..1e05f9d 100644
> --- a/arch/powerpc/platforms/512x/Makefile
> +++ b/arch/powerpc/platforms/512x/Makefile
> @@ -1,7 +1,9 @@
>  #
>  # Makefile for the Freescale PowerPC 512x linux kernel.
>  #
> -obj-y                          += clock.o mpc512x_shared.o
> +obj-$(CONFIG_PPC_CLOCK)                += clock.o
> +obj-$(CONFIG_COMMON_CLK)       += clock-commonclk.o
> +obj-y                          += mpc512x_shared.o
>  obj-$(CONFIG_MPC5121_ADS)      += mpc5121_ads.o mpc5121_ads_cpld.o
>  obj-$(CONFIG_MPC512x_GENERIC)  += mpc512x_generic.o
>  obj-$(CONFIG_PDM360NG)         += pdm360ng.o
> diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
> new file mode 100644
> index 0000000..762ee85
> --- /dev/null
> +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> @@ -0,0 +1,786 @@
> +/*
> + * Copyright (C) 2013 DENX Software Engineering
> + *
> + * Gerhard Sittig, <gsi@denx.de>
> + *
> + * common clock driver support for the MPC512x platform
> + *
> + * This 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +
> +#include <asm/mpc5121.h>
> +#include <dt-bindings/clock/mpc512x-clock.h>
> +
> +#include "mpc512x.h"           /* our public mpc5121_clk_init() API */
> +
> +/* helpers to keep the MCLK intermediates "somewhere" in our table */
> +enum {
> +       MCLK_IDX_MUX0,
> +       MCLK_IDX_EN0,
> +       MCLK_IDX_DIV0,
> +       MCLK_IDX_MUX1,
> +       MCLK_MAX_IDX,
> +};
> +
> +#define NR_PSCS                        12
> +#define NR_MSCANS              4
> +#define NR_SPDIFS              1
> +#define NR_MCLKS               (NR_PSCS + NR_MSCANS + NR_SPDIFS)
> +
> +/* extend the public set of clocks by adding internal slots for management */
> +enum {
> +       /* arrange for adjacent numbers after the public set */
> +       MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
> +       /* clocks which aren't announced to the public */
> +       MPC512x_CLK_DDR,
> +       MPC512x_CLK_MEM,
> +       MPC512x_CLK_IIM,
> +       MPC512x_CLK_SDHC_2,
> +       /* intermediates in div+gate combos or fractional dividers */
> +       MPC512x_CLK_DDR_UG,
> +       MPC512x_CLK_SDHC_x4,
> +       MPC512x_CLK_SDHC_UG,
> +       MPC512x_CLK_DIU_x4,
> +       MPC512x_CLK_DIU_UG,
> +       MPC512x_CLK_MBX_BUS_UG,
> +       MPC512x_CLK_MBX_UG,
> +       MPC512x_CLK_MBX_3D_UG,
> +       MPC512x_CLK_PCI_UG,
> +       MPC512x_CLK_NFC_UG,
> +       MPC512x_CLK_LPC_UG,
> +       MPC512x_CLK_SPDIF_TX_IN,
> +       /* intermediates for the mux+gate+div+mux MCLK generation */
> +       MPC512x_CLK_MCLKS_FIRST,
> +       MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
> +                               + NR_MCLKS * MCLK_MAX_IDX,
> +       /* internal, symbolic spec for the number of slots */
> +       MPC512x_CLK_LAST_PRIVATE,
> +};
> +
> +/* data required for the OF clock provider registration */
> +static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
> +static struct clk_onecell_data clk_data;
> +
> +/* CCM register access */
> +static struct mpc512x_ccm __iomem *clkregs;
> +static DEFINE_SPINLOCK(clklock);
> +
> +/* convenience wrappers around the common clk API */
> +static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
> +{
> +       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
> +}
> +
> +static inline struct clk *mpc512x_clk_factor(
> +       const char *name, const char *parent_name,
> +       int mul, int div)
> +{
> +       int clkflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
> +                                        mul, div);
> +}
> +
> +static inline struct clk *mpc512x_clk_divider(
> +       const char *name, const char *parent_name, u8 clkflags,
> +       u32 __iomem *reg, u8 pos, u8 len, int divflags)
> +{
> +       return clk_register_divider(NULL, name, parent_name, clkflags,
> +                                   reg, pos, len, divflags, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_divtable(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos, u8 len,
> +       const struct clk_div_table *divtab)
> +{
> +       u8 divflags;
> +
> +       divflags = 0;
> +       return clk_register_divider_table(NULL, name, parent_name, 0,
> +                                         reg, pos, len, divflags,
> +                                         divtab, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_gated(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos)
> +{
> +       int clkflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       return clk_register_gate(NULL, name, parent_name, clkflags,
> +                                reg, pos, 0, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_muxed(const char *name,
> +       const char **parent_names, int parent_count,
> +       u32 __iomem *reg, u8 pos, u8 len)
> +{
> +       int clkflags;
> +       u8 muxflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       muxflags = 0;
> +       return clk_register_mux(NULL, name,
> +                               parent_names, parent_count, clkflags,
> +                               reg, pos, len, muxflags, &clklock);
> +}
> +
> +/* helper to isolate a bit field from a register */
> +static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
> +{
> +       uint32_t val;
> +
> +       val = in_be32(reg);
> +       val >>= pos;
> +       val &= (1 << len) - 1;
> +       return val;
> +}
> +
> +/* get the SPMF and translate it into the "sys pll" multiplier */
> +static int get_spmf_mult(void)
> +{
> +       static int spmf_to_mult[] = {
> +               68, 1, 12, 16, 20, 24, 28, 32,
> +               36, 40, 44, 48, 52, 56, 60, 64,
> +       };
> +       int spmf;
> +
> +       spmf = get_bit_field(&clkregs->spmr, 24, 4);
> +       return spmf_to_mult[spmf];
> +}
> +
> +/*
> + * get the SYS_DIV value and translate it into a divide factor
> + *
> + * values returned from here are a multiple of the real factor since the
> + * divide ratio is fractional
> + */
> +static int get_sys_div_x2(void)
> +{
> +       static int sysdiv_code_to_x2[] = {
> +               4, 5, 6, 7, 8, 9, 10, 14,
> +               12, 16, 18, 22, 20, 24, 26, 30,
> +               28, 32, 34, 38, 36, 40, 42, 46,
> +               44, 48, 50, 54, 52, 56, 58, 62,
> +               60, 64, 66,
> +       };
> +       int divcode;
> +
> +       divcode = get_bit_field(&clkregs->scfr2, 26, 6);
> +       return sysdiv_code_to_x2[divcode];
> +}
> +
> +/*
> + * get the CPMF value and translate it into a multiplier factor
> + *
> + * values returned from here are a multiple of the real factor since the
> + * multiplier ratio is fractional
> + */
> +static int get_cpmf_mult_x2(void)
> +{
> +       static int cpmf_to_mult[] = {
> +               72, 2, 2, 3, 4, 5, 6, 7,
> +       };
> +       int cpmf;
> +
> +       cpmf = get_bit_field(&clkregs->spmr, 16, 4);
> +       return cpmf_to_mult[cpmf];
> +}
> +
> +/*
> + * some of the clock dividers do scale in a linear way, yet not all of
> + * their bit combinations are legal; use a divider table to get a
> + * resulting set of applicable divider values
> + */
> +
> +/* applies to the IPS_DIV, and PCI_DIV values */
> +static struct clk_div_table divtab_2346[] = {
> +       { .val = 2, .div = 2, },
> +       { .val = 3, .div = 3, },
> +       { .val = 4, .div = 4, },
> +       { .val = 6, .div = 6, },
> +       { .div = 0, },
> +};
> +
> +/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
> +static struct clk_div_table divtab_1234[] = {
> +       { .val = 1, .div = 1, },
> +       { .val = 2, .div = 2, },
> +       { .val = 3, .div = 3, },
> +       { .val = 4, .div = 4, },
> +       { .div = 0, },
> +};
> +
> +static int get_freq_from_dt(char *propname)
> +{
> +       struct device_node *np;
> +       const unsigned int *prop;
> +       int val;
> +
> +       val = 0;
> +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> +       if (np) {
> +               prop = of_get_property(np, propname, NULL);
> +               if (prop)
> +                       val = *prop;
> +           of_node_put(np);
> +       }
> +       return val;
> +}
> +
> +static void mpc512x_clk_preset_data(void)
> +{
> +       size_t i;
> +
> +       for (i = 0; i < ARRAY_SIZE(clks); i++)
> +               clks[i] = ERR_PTR(-ENODEV);
> +}
> +
> +/*
> + * - receives the "bus frequency" from the caller (that's the IPS clock
> + *   rate, the historical source of clock information)
> + * - fetches the system PLL multiplier and divider values as well as the
> + *   IPS divider value from hardware
> + * - determines the REF clock rate either from the XTAL/OSC spec (if
> + *   there is a device tree node describing the oscillator) or from the
> + *   IPS bus clock (supported for backwards compatibility, such that
> + *   setups without XTAL/OSC specs keep working)
> + * - creates the "ref" clock item in the clock tree, such that
> + *   subsequent code can create the remainder of the hierarchy (REF ->
> + *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
> + *   values
> + */
> +static void mpc512x_clk_setup_ref_clock(int bus_freq,
> +       int *sys_mul, int *sys_div, int *ips_div)
> +{
> +       struct clk *osc_clk;
> +       int calc_freq;
> +
> +       /* fetch mul/div factors from the hardware */
> +       *sys_mul = get_spmf_mult();
> +       *sys_mul *= 2;          /* compensate for the fractional divider */
> +       *sys_div = get_sys_div_x2();
> +       *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
> +
> +       /* lookup the oscillator node */
> +       osc_clk = clk_get(NULL, "osc");
> +       if (osc_clk) {
> +               /* descend REF directly from OSC, verify the IPS rate */
> +               clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
> +               calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
> +               calc_freq *= *sys_mul;
> +               calc_freq /= *sys_div;
> +               calc_freq /= 2;
> +               calc_freq /= *ips_div;
> +               if (bus_freq && calc_freq != bus_freq)
> +                       pr_warn("calc rate %d != OF spec %d\n",
> +                               calc_freq, bus_freq);
> +       } else {
> +               /* calculate OSC rate and create REF from the freq value */
> +               calc_freq = bus_freq;   /* start with IPS */
> +               calc_freq *= *ips_div;  /* IPS -> CSB */
> +               calc_freq *= 2;         /* CSB -> SYS */
> +               calc_freq *= *sys_div;  /* SYS -> PLL out */
> +               calc_freq /= *sys_mul;  /* PLL out -> REF == OSC */
> +               clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
> +       }
> +}
> +
> +/*
> + * helper code for the MCLK subtree setup
> + *
> + * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
> + * suggests that all instances of the "PSC clock generation" are equal,
> + * and that one might re-use the PSC setup for MSCAN clock generation
> + * (section 5.2.5) as well, at least the logic if not the data for
> + * description
> + *
> + * the details (starting at page 5-20) show differences in the specific
> + * inputs of the first mux stage ("can clk in", "spdif tx"), and the
> + * factual non-availability of the second mux stage (it's present yet
> + * only one input is valid)
> + *
> + * the MSCAN clock related registers (starting at page 5-35) all
> + * reference "spdif clk" at the first mux stage and don't mention any
> + * "can clk" at all, which somehow is unexpected
> + *
> + * TODO re-check the document, and clarify whether the RM is correct in
> + * the overview or in the details, and whether the difference is a
> + * clipboard induced error or results from chip revisions
> + *
> + * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
> + * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
> + * first a doc update is required which better reflects reality in the
> + * SoC before the implementation should follow while no questions remain
> + */
> +
> +/*
> + * note that this declaration raises a checkpatch warning, but
> + * it's the very data type which <linux/clk-provider.h> expects,
> + * making this declaration pass checkpatch will break compilation
> + */
> +static const char *parent_names_mux0[] = {
> +       "sys", "ref", "psc-mclk-in", "spdif-tx",
> +};
> +
> +enum mclk_type {
> +       MCLK_TYPE_PSC,
> +       MCLK_TYPE_MSCAN,
> +       MCLK_TYPE_SPDIF,
> +};
> +
> +struct mclk_setup_data {
> +       enum mclk_type type;
> +       int comp_idx;
> +       bool has_mclk1;
> +       int bit_sccr1, bit_sccr2;
> +       const char *name_mux0;
> +       const char *name_en0;
> +       const char *name_div0;
> +       const char *parent_names_mux1[2];
> +       const char *name_mux1;
> +       const char *name_mclk;
> +};
> +
> +#define MCLK_SETUP_DATA_PSC(id) { \
> +       MCLK_TYPE_PSC, id, \
> +       0, 27 - id, -1, \
> +       "psc" #id "-mux0", \
> +       "psc" #id "-en0", \
> +       "psc" #id "_mclk_div", \
> +       { "psc" #id "_mclk_div", "dummy", }, \
> +       "psc" #id "_mclk_out", \
> +       "psc" #id "_mclk", \
> +}
> +
> +#define MCLK_SETUP_DATA_MSCAN(id) { \
> +       MCLK_TYPE_MSCAN, id, \
> +       0, -1, 25, \
> +       "mscan" #id "-mux0", \
> +       "mscan" #id "-en0", \
> +       "mscan" #id "_mclk_div", \
> +       { "mscan" #id "_mclk_div", "dummy", }, \
> +       "mscan" #id "_mclk_out", \
> +       "mscan" #id "_mclk", \
> +}
> +
> +#define MCLK_SETUP_DATA_SPDIF { \
> +       MCLK_TYPE_SPDIF, 0, \
> +       1, -1, 23, \
> +       "spdif-mux0", \
> +       "spdif-en0", \
> +       "spdif_mclk_div", \
> +       { "spdif_mclk_div", "spdif-rx", }, \
> +       "spdif_mclk_out", \
> +       "spdif_mclk", \
> +}
> +
> +static struct mclk_setup_data mclk_psc_data[] = {
> +       MCLK_SETUP_DATA_PSC(0),
> +       MCLK_SETUP_DATA_PSC(1),
> +       MCLK_SETUP_DATA_PSC(2),
> +       MCLK_SETUP_DATA_PSC(3),
> +       MCLK_SETUP_DATA_PSC(4),
> +       MCLK_SETUP_DATA_PSC(5),
> +       MCLK_SETUP_DATA_PSC(6),
> +       MCLK_SETUP_DATA_PSC(7),
> +       MCLK_SETUP_DATA_PSC(8),
> +       MCLK_SETUP_DATA_PSC(9),
> +       MCLK_SETUP_DATA_PSC(10),
> +       MCLK_SETUP_DATA_PSC(11),
> +};
> +
> +static struct mclk_setup_data mclk_mscan_data[] = {
> +       MCLK_SETUP_DATA_MSCAN(0),
> +       MCLK_SETUP_DATA_MSCAN(1),
> +       MCLK_SETUP_DATA_MSCAN(2),
> +       MCLK_SETUP_DATA_MSCAN(3),
> +};
> +
> +static struct mclk_setup_data mclk_spdif_data[] = {
> +       MCLK_SETUP_DATA_SPDIF,
> +};
> +
> +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> +{
> +       size_t clks_idx_pub, clks_idx_int;
> +       u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> +       u32 __iomem *sccr_reg;  /* system clock control register (enable) */
> +       int sccr_bit;
> +       int div;
> +
> +       /* derive a few parameters from the component type and index */
> +       switch (entry->type) {
> +       case MCLK_TYPE_PSC:
> +               clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +                            + (entry->comp_idx) * MCLK_MAX_IDX;
> +               mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> +               break;
> +       case MCLK_TYPE_MSCAN:
> +               clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +                            + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> +               mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> +               break;
> +       case MCLK_TYPE_SPDIF:
> +               clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +                            + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> +               mccr_reg = &clkregs->spccr;
> +               break;
> +       default:
> +               return;
> +       }
> +       if (entry->bit_sccr1 >= 0) {
> +               sccr_reg = &clkregs->sccr1;
> +               sccr_bit = entry->bit_sccr1;
> +       } else if (entry->bit_sccr2 >= 0) {
> +               sccr_reg = &clkregs->sccr2;
> +               sccr_bit = entry->bit_sccr2;
> +       } else {
> +               sccr_reg = NULL;
> +       }
> +
> +       /*
> +        * this was grabbed from the PPC_CLOCK implementation, which
> +        * enforced a specific MCLK divider while the clock was gated
> +        * during setup (that's a documented hardware requirement)
> +        *
> +        * the PPC_CLOCK implementation might even have violated the
> +        * "MCLK <= IPS" constraint, the fixed divider value of 1
> +        * results in a divider of 2 and thus MCLK = SYS/2 which equals
> +        * CSB which is greater than IPS; the serial port setup may have
> +        * adjusted the divider which the clock setup might have left in
> +        * an undesirable state
> +        *
> +        * initial setup is:
> +        * - MCLK 0 from SYS
> +        * - MCLK DIV such to not exceed the IPS clock
> +        * - MCLK 0 enabled
> +        * - MCLK 1 from MCLK DIV
> +        */
> +       div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> +       div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> +       out_be32(mccr_reg, (0 << 16));
> +       out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> +       out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> +
> +       /*
> +        * create the 'struct clk' items of the MCLK's clock subtree
> +        *
> +        * note that by design we always create all nodes and won't take
> +        * shortcuts here, because
> +        * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> +        *   selectable inputs to the CFM while those who "actually use"
> +        *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> +        *   for their bitrate
> +        * - in the absence of "aliases" for clocks we need to create
> +        *   individial 'struct clk' items for whatever might get
> +        *   referenced or looked up, even if several of those items are
> +        *   identical from the logical POV (their rate value)
> +        * - for easier future maintenance and for better reflection of
> +        *   the SoC's documentation, it appears appropriate to generate
> +        *   clock items even for those muxers which actually are NOPs
> +        *   (those with two inputs of which one is reserved)
> +        */
> +       clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> +                       entry->name_mux0,
> +                       &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> +                       mccr_reg, 14, 2);
> +       clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> +                       entry->name_en0, entry->name_mux0,
> +                       mccr_reg, 16);
> +       clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> +                       entry->name_div0,
> +                       entry->name_en0, CLK_SET_RATE_GATE,
> +                       mccr_reg, 17, 15, 0);
> +       if (entry->has_mclk1) {
> +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> +                               entry->name_mux1,
> +                               &entry->parent_names_mux1[0],
> +                               ARRAY_SIZE(entry->parent_names_mux1),
> +                               mccr_reg, 7, 1);
> +       } else {
> +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> +                               entry->name_mux1, entry->parent_names_mux1[0],
> +                               1, 1);
> +       }
> +       if (sccr_reg) {
> +               clks[clks_idx_pub] = mpc512x_clk_gated(
> +                               entry->name_mclk,
> +                               entry->name_mux1, sccr_reg, sccr_bit);
> +       } else {
> +               clks[clks_idx_pub] = mpc512x_clk_factor(
> +                               entry->name_mclk,
> +                               entry->name_mux1, 1, 1);
> +       }
> +
> +       /*
> +        * without this "clock device" registration, "simple" lookups in
> +        * the SPI master initialization and serial port setup will fail
> +        *
> +        * those drivers need to get adjusted to lookup their required
> +        * clocks from device tree specs, and device tree nodes need to
> +        * provide the clock specs, before this clkdev registration
> +        * becomes obsolete
> +        */
> +       clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> +}
> +
> +static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
> +{
> +       while (count-- > 0)
> +               mpc512x_clk_setup_mclk(table++);
> +}
> +
> +static void mpc512x_clk_setup_clock_tree(int busfreq)
> +{
> +       int sys_mul, sys_div, ips_div;
> +       int mul, div;
> +       int freq;
> +
> +       /*
> +        * TODO
> +        * - consider whether to handle clocks which have both gates and
> +        *   dividers via intermediates or by means of composites
> +        * - fractional dividers appear to not map well to composites
> +        *   since they can be seen as a fixed multiplier and an
> +        *   adjustable divider, while composites can only combine at
> +        *   most one of a mux, div, and gate each into one 'struct clk'
> +        *   item
> +        * - PSC/MSCAN/SPDIF clock generation OTOH already is very
> +        *   specific and cannot get mapped to componsites (at least not
> +        *   a single one, maybe two of them, but see the comment about
> +        *   "intermediates are referenced from elsewhere, too")
> +        * - trim the list of auto-enabled clocks after drivers acquire
> +        *   them correctly as needed
> +        */
> +
> +       /* regardless of whether XTAL/OSC exists, have REF created */
> +       mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
> +
> +       /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
> +       clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
> +                                                  sys_mul, sys_div);
> +       clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
> +       clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
> +                                                    &clkregs->scfr1, 23, 3,
> +                                                    divtab_2346);
> +
> +       /* now setup anything below SYS and CSB and IPS */
> +       clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
> +       clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
> +       clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
> +                                                       &clkregs->scfr2, 0, 8,
> +                                                       CLK_DIVIDER_ONE_BASED);
> +       clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
> +       clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
> +                                                      &clkregs->scfr1, 0, 8,
> +                                                      CLK_DIVIDER_ONE_BASED);
> +
> +       /*
> +        * the "power architecture PLL" was setup from data which was
> +        * sampled from the reset config word, at this point in time the
> +        * configuration can be considered fixed and read only (i.e. no
> +        * longer adjustable, or no longer in need of adjustment), which
> +        * is why we don't register a PLL here but assume fixed factors
> +        */
> +       mul = get_cpmf_mult_x2();
> +       div = 2;        /* compensate for the fractional factor */
> +       clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
> +
> +       clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
> +                                                         1, 2);
> +       clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
> +                                                       &clkregs->scfr1, 14, 3,
> +                                                       divtab_1234);
> +       clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
> +                                                        1, 1);
> +       clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
> +                                                       &clkregs->scfr1, 20, 3,
> +                                                       divtab_2346);
> +       clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
> +                                                       &clkregs->scfr1, 8, 3,
> +                                                       divtab_1234);
> +       clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
> +                                                       &clkregs->scfr1, 11, 3,
> +                                                       divtab_1234);
> +
> +       clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
> +                                                 &clkregs->sccr1, 30);
> +       clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
> +                                                 &clkregs->sccr1, 29);
> +       clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
> +                                                  &clkregs->sccr1, 28);
> +       mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
> +       clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
> +                                                      &clkregs->sccr1, 15);
> +       clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
> +                                                  &clkregs->sccr1, 14);
> +       clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
> +                                                 &clkregs->sccr1, 13);
> +       clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
> +                                                 &clkregs->sccr1, 11);
> +       clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
> +                                                 &clkregs->sccr1, 10);
> +
> +       clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
> +                                                 &clkregs->sccr2, 31);
> +       clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
> +                                                 &clkregs->sccr2, 30);
> +       clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
> +                                                 &clkregs->sccr2, 29);
> +       clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
> +                                                  &clkregs->sccr2, 28);
> +       clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
> +                                                  &clkregs->sccr2, 27);
> +       clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> +                                                 &clkregs->sccr2, 26);
> +       mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> +       clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> +                                                  &clkregs->sccr2, 24);
> +       mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> +       clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
> +                                                     &clkregs->sccr2, 22);
> +       clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
> +                                                 &clkregs->sccr2, 21);
> +       clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
> +                                                    &clkregs->sccr2, 20);
> +       clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
> +                                                 &clkregs->sccr2, 19);
> +       clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
> +                                                 &clkregs->sccr2, 18);
> +       clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
> +                                                    &clkregs->sccr2, 17);
> +
> +       /*
> +        * externally provided clocks (when implemented in hardware,
> +        * device tree may specify values which otherwise were unknown)
> +        */
> +       freq = get_freq_from_dt("psc_mclk_in");
> +       if (!freq)
> +               freq = 25000000;
> +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> +       freq = get_freq_from_dt("spdif_tx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> +       freq = get_freq_from_dt("spdif_rx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
> +
> +       /* fixed frequency for AC97, always 24.567MHz */
> +       clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
> +
> +       /* clkdev registration for compatibility reasons */
> +       clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
> +
> +       pr_debug("clock tree setup complete\n");
> +       freq = clk_get_rate(clks[MPC512x_CLK_E300]);
> +       pr_debug("derived PPC freq [%d]\n", freq);
> +       freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
> +       pr_debug("derived IPS freq [%d]\n", freq);
> +       freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
> +       pr_debug("derived LPC freq [%d]\n", freq);
> +
> +       /* enable some of the clocks here unconditionally because ... */
> +       pr_debug("automatically enabling some clocks\n");
> +       /* some are essential yet never get claimed by any driver */
> +       clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> +       clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> +       clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> +       clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> +       clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> +       clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> +       /* some are required yet no dependencies were declared */
> +       clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> +       /* some are not yet acquired by their respective drivers */
> +       clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> +       clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> +       clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> +       clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> +       /*
> +        * some have their individual clock subtree with separate clock
> +        * items and their individual enable counters, yet share a
> +        * common gate (refer to the same register location) while the
> +        * common clock driver code is not aware of the fact and the
> +        * platform's code doesn't provide specific support either
> +        *
> +        * what might happen is that e.g. enabling two MSCAN clock items
> +        * and disabling one of them will disable the common gate and
> +        * thus break the other MSCAN clock as well
> +        */
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> +}
> +
> +/*
> + * registers the set of public clocks (those listed in the dt-bindings/
> + * header file) for OF lookups, keeps the intermediates private to us
> + */
> +static void mpc5121_clk_register_of_provider(struct device_node *np)
> +{
> +       clk_data.clks = clks;
> +       clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */
> +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +}
> +
> +int __init mpc5121_clk_init(void)
> +{
> +       struct device_node *clk_np;
> +       int busfreq;
> +
> +       /* map the clock control registers */
> +       clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
> +       if (!clk_np)
> +               return -ENODEV;
> +       clkregs = of_iomap(clk_np, 0);
> +       WARN_ON(!clkregs);
> +
> +       /* invalidate all not yet registered clock slots */
> +       mpc512x_clk_preset_data();
> +
> +       /*
> +        * have the device tree scanned for "fixed-clock" nodes (which
> +        * includes the oscillator node if the board's DT provides one)
> +        */
> +       of_clk_init(NULL);
> +
> +       /*
> +        * add a dummy clock for those situations where a clock spec is
> +        * required yet no real clock is involved
> +        */
> +       clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
> +
> +       /*
> +        * have all the real nodes in the clock tree populated from REF
> +        * down to all leaves, either starting from the OSC node or from
> +        * a REF root that was created from the IPS bus clock input
> +        */
> +       busfreq = get_freq_from_dt("bus-frequency");
> +       mpc512x_clk_setup_clock_tree(busfreq);
> +
> +       /* register as an OF clock provider */
> +       mpc5121_clk_register_of_provider(clk_np);
> +
> +       return 0;
> +}
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index c4f7799..7f8fc64 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
>   * for improved portability across platforms
>   */
>  
> +#if IS_ENABLED(CONFIG_PPC)
> +
> +static inline u32 clk_readl(u32 __iomem *reg)
> +{
> +       return ioread32be(reg);
> +}
> +
> +static inline void clk_writel(u32 val, u32 __iomem *reg)
> +{
> +       iowrite32be(val, reg);
> +}
> +
> +#else  /* platform dependent I/O accessors */
> +
>  static inline u32 clk_readl(u32 __iomem *reg)
>  {
>         return readl(reg);
> @@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
>         writel(val, reg);
>  }
>  
> +#endif /* platform dependent I/O accessors */
> +
>  #endif /* CONFIG_COMMON_CLK */
>  #endif /* CLK_PROVIDER_H */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-02 23:41           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:41 UTC (permalink / raw)
  To: Gerhard Sittig, linuxppc-dev, Anatolij Gustschin,
	linux-arm-kernel, devicetree-discuss
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

Quoting Gerhard Sittig (2013-07-22 05:14:44)
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
> =

> this driver implements the publicly announced set of clocks (which can
> get referenced by means of symbolic identifiers from the dt-bindings
> header file), as well as generates additional 'struct clk' items where
> the SoC hardware cannot easily get mapped to the common primitives of
> the clock API, or requires "intermediate" clock nodes to represent
> clocks that have both gates and dividers
> =

> the previous PPC_CLOCK implementation is kept in place and remains in
> parallel to the common clock implementation for test and comparison
> during migration, a compile time option picks one of the two
> alternatives (Kconfig switch, common clock used by default)
> =

> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> - some of the clocks are useful to have for diagnostics and information
>   despite their not getting claimed by any drivers (CPU, internal and
>   external RAM, internal busses, boot media)
> - some of the clocks aren't claimed by their peripheral drivers yet,
>   either because of missing driver support or because device tree specs
>   aren't available yet (but the workarounds will get removed as the
>   drivers get adjusted and the device tree provides the clock specs)
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)
> =

> clkdev registration provides "alias names" for few clock items
> - to not break those peripheral drivers which encode their component
>   index into the name that is used for clock lookup (UART, SPI, USB)
> - to not break those drivers which use names for the clock lookup which
>   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> this workaround will get removed as these drivers get adjusted after
> device tree based clock lookup has become available
> =

> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Hi Gerhard,

This looks OK to me. Do you want me to take it or will you keep the
series together? Note that I took "clk: wrap I/O access for improved
portability" into the clk tree already.

Regards,
Mike

> ---
>  arch/powerpc/platforms/512x/Kconfig           |   14 +-
>  arch/powerpc/platforms/512x/Makefile          |    4 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++=
++++++
>  include/linux/clk-provider.h                  |   16 +
>  4 files changed, 818 insertions(+), 2 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> =

> diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms=
/512x/Kconfig
> index fc9c1cb..c5fcdd0 100644
> --- a/arch/powerpc/platforms/512x/Kconfig
> +++ b/arch/powerpc/platforms/512x/Kconfig
> @@ -1,9 +1,21 @@
> +config MPC512x_COMMON_CLK
> +       bool "MPC512x platform uses COMMON_CLK"
> +       default y
> +       depends on PPC_MPC512x
> +       help
> +         This option is only here to support tests and comparison
> +         during development and migration.  This option will get
> +         removed after the COMMON_CLK support for MPC512x has become
> +         fully operational and all drivers were adjusted to explicitly
> +         acquire their required clocks.
> +
>  config PPC_MPC512x
>         bool "512x-based boards"
>         depends on 6xx
>         select FSL_SOC
>         select IPIC
> -       select PPC_CLOCK
> +       select PPC_CLOCK if !MPC512x_COMMON_CLK
> +       select COMMON_CLK if MPC512x_COMMON_CLK
>         select PPC_PCI_CHOICE
>         select FSL_PCI if PCI
>         select ARCH_WANT_OPTIONAL_GPIOLIB
> diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platform=
s/512x/Makefile
> index 72fb934..1e05f9d 100644
> --- a/arch/powerpc/platforms/512x/Makefile
> +++ b/arch/powerpc/platforms/512x/Makefile
> @@ -1,7 +1,9 @@
>  #
>  # Makefile for the Freescale PowerPC 512x linux kernel.
>  #
> -obj-y                          +=3D clock.o mpc512x_shared.o
> +obj-$(CONFIG_PPC_CLOCK)                +=3D clock.o
> +obj-$(CONFIG_COMMON_CLK)       +=3D clock-commonclk.o
> +obj-y                          +=3D mpc512x_shared.o
>  obj-$(CONFIG_MPC5121_ADS)      +=3D mpc5121_ads.o mpc5121_ads_cpld.o
>  obj-$(CONFIG_MPC512x_GENERIC)  +=3D mpc512x_generic.o
>  obj-$(CONFIG_PDM360NG)         +=3D pdm360ng.o
> diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc=
/platforms/512x/clock-commonclk.c
> new file mode 100644
> index 0000000..762ee85
> --- /dev/null
> +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> @@ -0,0 +1,786 @@
> +/*
> + * Copyright (C) 2013 DENX Software Engineering
> + *
> + * Gerhard Sittig, <gsi@denx.de>
> + *
> + * common clock driver support for the MPC512x platform
> + *
> + * This 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +
> +#include <asm/mpc5121.h>
> +#include <dt-bindings/clock/mpc512x-clock.h>
> +
> +#include "mpc512x.h"           /* our public mpc5121_clk_init() API */
> +
> +/* helpers to keep the MCLK intermediates "somewhere" in our table */
> +enum {
> +       MCLK_IDX_MUX0,
> +       MCLK_IDX_EN0,
> +       MCLK_IDX_DIV0,
> +       MCLK_IDX_MUX1,
> +       MCLK_MAX_IDX,
> +};
> +
> +#define NR_PSCS                        12
> +#define NR_MSCANS              4
> +#define NR_SPDIFS              1
> +#define NR_MCLKS               (NR_PSCS + NR_MSCANS + NR_SPDIFS)
> +
> +/* extend the public set of clocks by adding internal slots for manageme=
nt */
> +enum {
> +       /* arrange for adjacent numbers after the public set */
> +       MPC512x_CLK_START_PRIVATE =3D MPC512x_CLK_LAST_PUBLIC,
> +       /* clocks which aren't announced to the public */
> +       MPC512x_CLK_DDR,
> +       MPC512x_CLK_MEM,
> +       MPC512x_CLK_IIM,
> +       MPC512x_CLK_SDHC_2,
> +       /* intermediates in div+gate combos or fractional dividers */
> +       MPC512x_CLK_DDR_UG,
> +       MPC512x_CLK_SDHC_x4,
> +       MPC512x_CLK_SDHC_UG,
> +       MPC512x_CLK_DIU_x4,
> +       MPC512x_CLK_DIU_UG,
> +       MPC512x_CLK_MBX_BUS_UG,
> +       MPC512x_CLK_MBX_UG,
> +       MPC512x_CLK_MBX_3D_UG,
> +       MPC512x_CLK_PCI_UG,
> +       MPC512x_CLK_NFC_UG,
> +       MPC512x_CLK_LPC_UG,
> +       MPC512x_CLK_SPDIF_TX_IN,
> +       /* intermediates for the mux+gate+div+mux MCLK generation */
> +       MPC512x_CLK_MCLKS_FIRST,
> +       MPC512x_CLK_MCLKS_LAST =3D MPC512x_CLK_MCLKS_FIRST
> +                               + NR_MCLKS * MCLK_MAX_IDX,
> +       /* internal, symbolic spec for the number of slots */
> +       MPC512x_CLK_LAST_PRIVATE,
> +};
> +
> +/* data required for the OF clock provider registration */
> +static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
> +static struct clk_onecell_data clk_data;
> +
> +/* CCM register access */
> +static struct mpc512x_ccm __iomem *clkregs;
> +static DEFINE_SPINLOCK(clklock);
> +
> +/* convenience wrappers around the common clk API */
> +static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
> +{
> +       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rat=
e);
> +}
> +
> +static inline struct clk *mpc512x_clk_factor(
> +       const char *name, const char *parent_name,
> +       int mul, int div)
> +{
> +       int clkflags;
> +
> +       clkflags =3D CLK_SET_RATE_PARENT;
> +       return clk_register_fixed_factor(NULL, name, parent_name, clkflag=
s,
> +                                        mul, div);
> +}
> +
> +static inline struct clk *mpc512x_clk_divider(
> +       const char *name, const char *parent_name, u8 clkflags,
> +       u32 __iomem *reg, u8 pos, u8 len, int divflags)
> +{
> +       return clk_register_divider(NULL, name, parent_name, clkflags,
> +                                   reg, pos, len, divflags, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_divtable(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos, u8 len,
> +       const struct clk_div_table *divtab)
> +{
> +       u8 divflags;
> +
> +       divflags =3D 0;
> +       return clk_register_divider_table(NULL, name, parent_name, 0,
> +                                         reg, pos, len, divflags,
> +                                         divtab, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_gated(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos)
> +{
> +       int clkflags;
> +
> +       clkflags =3D CLK_SET_RATE_PARENT;
> +       return clk_register_gate(NULL, name, parent_name, clkflags,
> +                                reg, pos, 0, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_muxed(const char *name,
> +       const char **parent_names, int parent_count,
> +       u32 __iomem *reg, u8 pos, u8 len)
> +{
> +       int clkflags;
> +       u8 muxflags;
> +
> +       clkflags =3D CLK_SET_RATE_PARENT;
> +       muxflags =3D 0;
> +       return clk_register_mux(NULL, name,
> +                               parent_names, parent_count, clkflags,
> +                               reg, pos, len, muxflags, &clklock);
> +}
> +
> +/* helper to isolate a bit field from a register */
> +static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint=
8_t len)
> +{
> +       uint32_t val;
> +
> +       val =3D in_be32(reg);
> +       val >>=3D pos;
> +       val &=3D (1 << len) - 1;
> +       return val;
> +}
> +
> +/* get the SPMF and translate it into the "sys pll" multiplier */
> +static int get_spmf_mult(void)
> +{
> +       static int spmf_to_mult[] =3D {
> +               68, 1, 12, 16, 20, 24, 28, 32,
> +               36, 40, 44, 48, 52, 56, 60, 64,
> +       };
> +       int spmf;
> +
> +       spmf =3D get_bit_field(&clkregs->spmr, 24, 4);
> +       return spmf_to_mult[spmf];
> +}
> +
> +/*
> + * get the SYS_DIV value and translate it into a divide factor
> + *
> + * values returned from here are a multiple of the real factor since the
> + * divide ratio is fractional
> + */
> +static int get_sys_div_x2(void)
> +{
> +       static int sysdiv_code_to_x2[] =3D {
> +               4, 5, 6, 7, 8, 9, 10, 14,
> +               12, 16, 18, 22, 20, 24, 26, 30,
> +               28, 32, 34, 38, 36, 40, 42, 46,
> +               44, 48, 50, 54, 52, 56, 58, 62,
> +               60, 64, 66,
> +       };
> +       int divcode;
> +
> +       divcode =3D get_bit_field(&clkregs->scfr2, 26, 6);
> +       return sysdiv_code_to_x2[divcode];
> +}
> +
> +/*
> + * get the CPMF value and translate it into a multiplier factor
> + *
> + * values returned from here are a multiple of the real factor since the
> + * multiplier ratio is fractional
> + */
> +static int get_cpmf_mult_x2(void)
> +{
> +       static int cpmf_to_mult[] =3D {
> +               72, 2, 2, 3, 4, 5, 6, 7,
> +       };
> +       int cpmf;
> +
> +       cpmf =3D get_bit_field(&clkregs->spmr, 16, 4);
> +       return cpmf_to_mult[cpmf];
> +}
> +
> +/*
> + * some of the clock dividers do scale in a linear way, yet not all of
> + * their bit combinations are legal; use a divider table to get a
> + * resulting set of applicable divider values
> + */
> +
> +/* applies to the IPS_DIV, and PCI_DIV values */
> +static struct clk_div_table divtab_2346[] =3D {
> +       { .val =3D 2, .div =3D 2, },
> +       { .val =3D 3, .div =3D 3, },
> +       { .val =3D 4, .div =3D 4, },
> +       { .val =3D 6, .div =3D 6, },
> +       { .div =3D 0, },
> +};
> +
> +/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
> +static struct clk_div_table divtab_1234[] =3D {
> +       { .val =3D 1, .div =3D 1, },
> +       { .val =3D 2, .div =3D 2, },
> +       { .val =3D 3, .div =3D 3, },
> +       { .val =3D 4, .div =3D 4, },
> +       { .div =3D 0, },
> +};
> +
> +static int get_freq_from_dt(char *propname)
> +{
> +       struct device_node *np;
> +       const unsigned int *prop;
> +       int val;
> +
> +       val =3D 0;
> +       np =3D of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> +       if (np) {
> +               prop =3D of_get_property(np, propname, NULL);
> +               if (prop)
> +                       val =3D *prop;
> +           of_node_put(np);
> +       }
> +       return val;
> +}
> +
> +static void mpc512x_clk_preset_data(void)
> +{
> +       size_t i;
> +
> +       for (i =3D 0; i < ARRAY_SIZE(clks); i++)
> +               clks[i] =3D ERR_PTR(-ENODEV);
> +}
> +
> +/*
> + * - receives the "bus frequency" from the caller (that's the IPS clock
> + *   rate, the historical source of clock information)
> + * - fetches the system PLL multiplier and divider values as well as the
> + *   IPS divider value from hardware
> + * - determines the REF clock rate either from the XTAL/OSC spec (if
> + *   there is a device tree node describing the oscillator) or from the
> + *   IPS bus clock (supported for backwards compatibility, such that
> + *   setups without XTAL/OSC specs keep working)
> + * - creates the "ref" clock item in the clock tree, such that
> + *   subsequent code can create the remainder of the hierarchy (REF ->
> + *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
> + *   values
> + */
> +static void mpc512x_clk_setup_ref_clock(int bus_freq,
> +       int *sys_mul, int *sys_div, int *ips_div)
> +{
> +       struct clk *osc_clk;
> +       int calc_freq;
> +
> +       /* fetch mul/div factors from the hardware */
> +       *sys_mul =3D get_spmf_mult();
> +       *sys_mul *=3D 2;          /* compensate for the fractional divide=
r */
> +       *sys_div =3D get_sys_div_x2();
> +       *ips_div =3D get_bit_field(&clkregs->scfr1, 23, 3);
> +
> +       /* lookup the oscillator node */
> +       osc_clk =3D clk_get(NULL, "osc");
> +       if (osc_clk) {
> +               /* descend REF directly from OSC, verify the IPS rate */
> +               clks[MPC512x_CLK_REF] =3D mpc512x_clk_factor("ref", "osc"=
, 1, 1);
> +               calc_freq =3D clk_get_rate(clks[MPC512x_CLK_REF]);
> +               calc_freq *=3D *sys_mul;
> +               calc_freq /=3D *sys_div;
> +               calc_freq /=3D 2;
> +               calc_freq /=3D *ips_div;
> +               if (bus_freq && calc_freq !=3D bus_freq)
> +                       pr_warn("calc rate %d !=3D OF spec %d\n",
> +                               calc_freq, bus_freq);
> +       } else {
> +               /* calculate OSC rate and create REF from the freq value =
*/
> +               calc_freq =3D bus_freq;   /* start with IPS */
> +               calc_freq *=3D *ips_div;  /* IPS -> CSB */
> +               calc_freq *=3D 2;         /* CSB -> SYS */
> +               calc_freq *=3D *sys_div;  /* SYS -> PLL out */
> +               calc_freq /=3D *sys_mul;  /* PLL out -> REF =3D=3D OSC */
> +               clks[MPC512x_CLK_REF] =3D mpc512x_clk_fixed("ref", calc_f=
req);
> +       }
> +}
> +
> +/*
> + * helper code for the MCLK subtree setup
> + *
> + * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
> + * suggests that all instances of the "PSC clock generation" are equal,
> + * and that one might re-use the PSC setup for MSCAN clock generation
> + * (section 5.2.5) as well, at least the logic if not the data for
> + * description
> + *
> + * the details (starting at page 5-20) show differences in the specific
> + * inputs of the first mux stage ("can clk in", "spdif tx"), and the
> + * factual non-availability of the second mux stage (it's present yet
> + * only one input is valid)
> + *
> + * the MSCAN clock related registers (starting at page 5-35) all
> + * reference "spdif clk" at the first mux stage and don't mention any
> + * "can clk" at all, which somehow is unexpected
> + *
> + * TODO re-check the document, and clarify whether the RM is correct in
> + * the overview or in the details, and whether the difference is a
> + * clipboard induced error or results from chip revisions
> + *
> + * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
> + * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
> + * first a doc update is required which better reflects reality in the
> + * SoC before the implementation should follow while no questions remain
> + */
> +
> +/*
> + * note that this declaration raises a checkpatch warning, but
> + * it's the very data type which <linux/clk-provider.h> expects,
> + * making this declaration pass checkpatch will break compilation
> + */
> +static const char *parent_names_mux0[] =3D {
> +       "sys", "ref", "psc-mclk-in", "spdif-tx",
> +};
> +
> +enum mclk_type {
> +       MCLK_TYPE_PSC,
> +       MCLK_TYPE_MSCAN,
> +       MCLK_TYPE_SPDIF,
> +};
> +
> +struct mclk_setup_data {
> +       enum mclk_type type;
> +       int comp_idx;
> +       bool has_mclk1;
> +       int bit_sccr1, bit_sccr2;
> +       const char *name_mux0;
> +       const char *name_en0;
> +       const char *name_div0;
> +       const char *parent_names_mux1[2];
> +       const char *name_mux1;
> +       const char *name_mclk;
> +};
> +
> +#define MCLK_SETUP_DATA_PSC(id) { \
> +       MCLK_TYPE_PSC, id, \
> +       0, 27 - id, -1, \
> +       "psc" #id "-mux0", \
> +       "psc" #id "-en0", \
> +       "psc" #id "_mclk_div", \
> +       { "psc" #id "_mclk_div", "dummy", }, \
> +       "psc" #id "_mclk_out", \
> +       "psc" #id "_mclk", \
> +}
> +
> +#define MCLK_SETUP_DATA_MSCAN(id) { \
> +       MCLK_TYPE_MSCAN, id, \
> +       0, -1, 25, \
> +       "mscan" #id "-mux0", \
> +       "mscan" #id "-en0", \
> +       "mscan" #id "_mclk_div", \
> +       { "mscan" #id "_mclk_div", "dummy", }, \
> +       "mscan" #id "_mclk_out", \
> +       "mscan" #id "_mclk", \
> +}
> +
> +#define MCLK_SETUP_DATA_SPDIF { \
> +       MCLK_TYPE_SPDIF, 0, \
> +       1, -1, 23, \
> +       "spdif-mux0", \
> +       "spdif-en0", \
> +       "spdif_mclk_div", \
> +       { "spdif_mclk_div", "spdif-rx", }, \
> +       "spdif_mclk_out", \
> +       "spdif_mclk", \
> +}
> +
> +static struct mclk_setup_data mclk_psc_data[] =3D {
> +       MCLK_SETUP_DATA_PSC(0),
> +       MCLK_SETUP_DATA_PSC(1),
> +       MCLK_SETUP_DATA_PSC(2),
> +       MCLK_SETUP_DATA_PSC(3),
> +       MCLK_SETUP_DATA_PSC(4),
> +       MCLK_SETUP_DATA_PSC(5),
> +       MCLK_SETUP_DATA_PSC(6),
> +       MCLK_SETUP_DATA_PSC(7),
> +       MCLK_SETUP_DATA_PSC(8),
> +       MCLK_SETUP_DATA_PSC(9),
> +       MCLK_SETUP_DATA_PSC(10),
> +       MCLK_SETUP_DATA_PSC(11),
> +};
> +
> +static struct mclk_setup_data mclk_mscan_data[] =3D {
> +       MCLK_SETUP_DATA_MSCAN(0),
> +       MCLK_SETUP_DATA_MSCAN(1),
> +       MCLK_SETUP_DATA_MSCAN(2),
> +       MCLK_SETUP_DATA_MSCAN(3),
> +};
> +
> +static struct mclk_setup_data mclk_spdif_data[] =3D {
> +       MCLK_SETUP_DATA_SPDIF,
> +};
> +
> +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> +{
> +       size_t clks_idx_pub, clks_idx_int;
> +       u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> +       u32 __iomem *sccr_reg;  /* system clock control register (enable)=
 */
> +       int sccr_bit;
> +       int div;
> +
> +       /* derive a few parameters from the component type and index */
> +       switch (entry->type) {
> +       case MCLK_TYPE_PSC:
> +               clks_idx_pub =3D MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> +               clks_idx_int =3D MPC512x_CLK_MCLKS_FIRST
> +                            + (entry->comp_idx) * MCLK_MAX_IDX;
> +               mccr_reg =3D &clkregs->psc_ccr[entry->comp_idx];
> +               break;
> +       case MCLK_TYPE_MSCAN:
> +               clks_idx_pub =3D MPC512x_CLK_MSCAN0_MCLK + entry->comp_id=
x;
> +               clks_idx_int =3D MPC512x_CLK_MCLKS_FIRST
> +                            + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> +               mccr_reg =3D &clkregs->mscan_ccr[entry->comp_idx];
> +               break;
> +       case MCLK_TYPE_SPDIF:
> +               clks_idx_pub =3D MPC512x_CLK_SPDIF_MCLK;
> +               clks_idx_int =3D MPC512x_CLK_MCLKS_FIRST
> +                            + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> +               mccr_reg =3D &clkregs->spccr;
> +               break;
> +       default:
> +               return;
> +       }
> +       if (entry->bit_sccr1 >=3D 0) {
> +               sccr_reg =3D &clkregs->sccr1;
> +               sccr_bit =3D entry->bit_sccr1;
> +       } else if (entry->bit_sccr2 >=3D 0) {
> +               sccr_reg =3D &clkregs->sccr2;
> +               sccr_bit =3D entry->bit_sccr2;
> +       } else {
> +               sccr_reg =3D NULL;
> +       }
> +
> +       /*
> +        * this was grabbed from the PPC_CLOCK implementation, which
> +        * enforced a specific MCLK divider while the clock was gated
> +        * during setup (that's a documented hardware requirement)
> +        *
> +        * the PPC_CLOCK implementation might even have violated the
> +        * "MCLK <=3D IPS" constraint, the fixed divider value of 1
> +        * results in a divider of 2 and thus MCLK =3D SYS/2 which equals
> +        * CSB which is greater than IPS; the serial port setup may have
> +        * adjusted the divider which the clock setup might have left in
> +        * an undesirable state
> +        *
> +        * initial setup is:
> +        * - MCLK 0 from SYS
> +        * - MCLK DIV such to not exceed the IPS clock
> +        * - MCLK 0 enabled
> +        * - MCLK 1 from MCLK DIV
> +        */
> +       div =3D clk_get_rate(clks[MPC512x_CLK_SYS]);
> +       div /=3D clk_get_rate(clks[MPC512x_CLK_IPS]);
> +       out_be32(mccr_reg, (0 << 16));
> +       out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> +       out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> +
> +       /*
> +        * create the 'struct clk' items of the MCLK's clock subtree
> +        *
> +        * note that by design we always create all nodes and won't take
> +        * shortcuts here, because
> +        * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> +        *   selectable inputs to the CFM while those who "actually use"
> +        *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> +        *   for their bitrate
> +        * - in the absence of "aliases" for clocks we need to create
> +        *   individial 'struct clk' items for whatever might get
> +        *   referenced or looked up, even if several of those items are
> +        *   identical from the logical POV (their rate value)
> +        * - for easier future maintenance and for better reflection of
> +        *   the SoC's documentation, it appears appropriate to generate
> +        *   clock items even for those muxers which actually are NOPs
> +        *   (those with two inputs of which one is reserved)
> +        */
> +       clks[clks_idx_int + MCLK_IDX_MUX0] =3D mpc512x_clk_muxed(
> +                       entry->name_mux0,
> +                       &parent_names_mux0[0], ARRAY_SIZE(parent_names_mu=
x0),
> +                       mccr_reg, 14, 2);
> +       clks[clks_idx_int + MCLK_IDX_EN0] =3D mpc512x_clk_gated(
> +                       entry->name_en0, entry->name_mux0,
> +                       mccr_reg, 16);
> +       clks[clks_idx_int + MCLK_IDX_DIV0] =3D mpc512x_clk_divider(
> +                       entry->name_div0,
> +                       entry->name_en0, CLK_SET_RATE_GATE,
> +                       mccr_reg, 17, 15, 0);
> +       if (entry->has_mclk1) {
> +               clks[clks_idx_int + MCLK_IDX_MUX1] =3D mpc512x_clk_muxed(
> +                               entry->name_mux1,
> +                               &entry->parent_names_mux1[0],
> +                               ARRAY_SIZE(entry->parent_names_mux1),
> +                               mccr_reg, 7, 1);
> +       } else {
> +               clks[clks_idx_int + MCLK_IDX_MUX1] =3D mpc512x_clk_factor(
> +                               entry->name_mux1, entry->parent_names_mux=
1[0],
> +                               1, 1);
> +       }
> +       if (sccr_reg) {
> +               clks[clks_idx_pub] =3D mpc512x_clk_gated(
> +                               entry->name_mclk,
> +                               entry->name_mux1, sccr_reg, sccr_bit);
> +       } else {
> +               clks[clks_idx_pub] =3D mpc512x_clk_factor(
> +                               entry->name_mclk,
> +                               entry->name_mux1, 1, 1);
> +       }
> +
> +       /*
> +        * without this "clock device" registration, "simple" lookups in
> +        * the SPI master initialization and serial port setup will fail
> +        *
> +        * those drivers need to get adjusted to lookup their required
> +        * clocks from device tree specs, and device tree nodes need to
> +        * provide the clock specs, before this clkdev registration
> +        * becomes obsolete
> +        */
> +       clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> +}
> +
> +static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_=
t count)
> +{
> +       while (count-- > 0)
> +               mpc512x_clk_setup_mclk(table++);
> +}
> +
> +static void mpc512x_clk_setup_clock_tree(int busfreq)
> +{
> +       int sys_mul, sys_div, ips_div;
> +       int mul, div;
> +       int freq;
> +
> +       /*
> +        * TODO
> +        * - consider whether to handle clocks which have both gates and
> +        *   dividers via intermediates or by means of composites
> +        * - fractional dividers appear to not map well to composites
> +        *   since they can be seen as a fixed multiplier and an
> +        *   adjustable divider, while composites can only combine at
> +        *   most one of a mux, div, and gate each into one 'struct clk'
> +        *   item
> +        * - PSC/MSCAN/SPDIF clock generation OTOH already is very
> +        *   specific and cannot get mapped to componsites (at least not
> +        *   a single one, maybe two of them, but see the comment about
> +        *   "intermediates are referenced from elsewhere, too")
> +        * - trim the list of auto-enabled clocks after drivers acquire
> +        *   them correctly as needed
> +        */
> +
> +       /* regardless of whether XTAL/OSC exists, have REF created */
> +       mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div=
);
> +
> +       /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
> +       clks[MPC512x_CLK_SYS] =3D mpc512x_clk_factor("sys", "ref",
> +                                                  sys_mul, sys_div);
> +       clks[MPC512x_CLK_CSB] =3D mpc512x_clk_factor("csb", "sys", 1, 2);
> +       clks[MPC512x_CLK_IPS] =3D mpc512x_clk_divtable("ips", "csb",
> +                                                    &clkregs->scfr1, 23,=
 3,
> +                                                    divtab_2346);
> +
> +       /* now setup anything below SYS and CSB and IPS */
> +       clks[MPC512x_CLK_DDR_UG] =3D mpc512x_clk_factor("ddr-ug", "sys", =
1, 2);
> +       clks[MPC512x_CLK_SDHC_x4] =3D mpc512x_clk_factor("sdhc-x4", "csb"=
, 4, 1);
> +       clks[MPC512x_CLK_SDHC_UG] =3D mpc512x_clk_divider("sdhc-ug", "sdh=
c-x4", 0,
> +                                                       &clkregs->scfr2, =
0, 8,
> +                                                       CLK_DIVIDER_ONE_B=
ASED);
> +       clks[MPC512x_CLK_DIU_x4] =3D mpc512x_clk_factor("diu-x4", "csb", =
4, 1);
> +       clks[MPC512x_CLK_DIU_UG] =3D mpc512x_clk_divider("diu-ug", "diu-x=
4", 0,
> +                                                      &clkregs->scfr1, 0=
, 8,
> +                                                      CLK_DIVIDER_ONE_BA=
SED);
> +
> +       /*
> +        * the "power architecture PLL" was setup from data which was
> +        * sampled from the reset config word, at this point in time the
> +        * configuration can be considered fixed and read only (i.e. no
> +        * longer adjustable, or no longer in need of adjustment), which
> +        * is why we don't register a PLL here but assume fixed factors
> +        */
> +       mul =3D get_cpmf_mult_x2();
> +       div =3D 2;        /* compensate for the fractional factor */
> +       clks[MPC512x_CLK_E300] =3D mpc512x_clk_factor("e300", "csb", mul,=
 div);
> +
> +       clks[MPC512x_CLK_MBX_BUS_UG] =3D mpc512x_clk_factor("mbx-bus-ug",=
 "csb",
> +                                                         1, 2);
> +       clks[MPC512x_CLK_MBX_UG] =3D mpc512x_clk_divtable("mbx-ug", "mbx-=
bus-ug",
> +                                                       &clkregs->scfr1, =
14, 3,
> +                                                       divtab_1234);
> +       clks[MPC512x_CLK_MBX_3D_UG] =3D mpc512x_clk_factor("mbx-3d-ug", "=
mbx-ug",
> +                                                        1, 1);
> +       clks[MPC512x_CLK_PCI_UG] =3D mpc512x_clk_divtable("pci-ug", "csb",
> +                                                       &clkregs->scfr1, =
20, 3,
> +                                                       divtab_2346);
> +       clks[MPC512x_CLK_NFC_UG] =3D mpc512x_clk_divtable("nfc-ug", "ips",
> +                                                       &clkregs->scfr1, =
8, 3,
> +                                                       divtab_1234);
> +       clks[MPC512x_CLK_LPC_UG] =3D mpc512x_clk_divtable("lpc-ug", "ips",
> +                                                       &clkregs->scfr1, =
11, 3,
> +                                                       divtab_1234);
> +
> +       clks[MPC512x_CLK_LPC] =3D mpc512x_clk_gated("lpc", "lpc-ug",
> +                                                 &clkregs->sccr1, 30);
> +       clks[MPC512x_CLK_NFC] =3D mpc512x_clk_gated("nfc", "nfc-ug",
> +                                                 &clkregs->sccr1, 29);
> +       clks[MPC512x_CLK_PATA] =3D mpc512x_clk_gated("pata", "ips",
> +                                                  &clkregs->sccr1, 28);
> +       mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
> +       clks[MPC512x_CLK_PSC_FIFO] =3D mpc512x_clk_gated("psc-fifo", "ips=
",
> +                                                      &clkregs->sccr1, 1=
5);
> +       clks[MPC512x_CLK_SATA] =3D mpc512x_clk_gated("sata", "ips",
> +                                                  &clkregs->sccr1, 14);
> +       clks[MPC512x_CLK_FEC] =3D mpc512x_clk_gated("fec", "ips",
> +                                                 &clkregs->sccr1, 13);
> +       clks[MPC512x_CLK_PCI] =3D mpc512x_clk_gated("pci", "pci-ug",
> +                                                 &clkregs->sccr1, 11);
> +       clks[MPC512x_CLK_DDR] =3D mpc512x_clk_gated("ddr", "ddr-ug",
> +                                                 &clkregs->sccr1, 10);
> +
> +       clks[MPC512x_CLK_DIU] =3D mpc512x_clk_gated("diu", "diu-ug",
> +                                                 &clkregs->sccr2, 31);
> +       clks[MPC512x_CLK_AXE] =3D mpc512x_clk_gated("axe", "csb",
> +                                                 &clkregs->sccr2, 30);
> +       clks[MPC512x_CLK_MEM] =3D mpc512x_clk_gated("mem", "ips",
> +                                                 &clkregs->sccr2, 29);
> +       clks[MPC512x_CLK_USB1] =3D mpc512x_clk_gated("usb1", "csb",
> +                                                  &clkregs->sccr2, 28);
> +       clks[MPC512x_CLK_USB2] =3D mpc512x_clk_gated("usb2", "csb",
> +                                                  &clkregs->sccr2, 27);
> +       clks[MPC512x_CLK_I2C] =3D mpc512x_clk_gated("i2c", "ips",
> +                                                 &clkregs->sccr2, 26);
> +       mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_da=
ta));
> +       clks[MPC512x_CLK_SDHC] =3D mpc512x_clk_gated("sdhc", "sdhc-ug",
> +                                                  &clkregs->sccr2, 24);
> +       mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_da=
ta));
> +       clks[MPC512x_CLK_MBX_BUS] =3D mpc512x_clk_gated("mbx-bus", "mbx-b=
us-ug",
> +                                                     &clkregs->sccr2, 22=
);
> +       clks[MPC512x_CLK_MBX] =3D mpc512x_clk_gated("mbx", "mbx-ug",
> +                                                 &clkregs->sccr2, 21);
> +       clks[MPC512x_CLK_MBX_3D] =3D mpc512x_clk_gated("mbx-3d", "mbx-3d-=
ug",
> +                                                    &clkregs->sccr2, 20);
> +       clks[MPC512x_CLK_IIM] =3D mpc512x_clk_gated("iim", "csb",
> +                                                 &clkregs->sccr2, 19);
> +       clks[MPC512x_CLK_VIU] =3D mpc512x_clk_gated("viu", "csb",
> +                                                 &clkregs->sccr2, 18);
> +       clks[MPC512x_CLK_SDHC_2] =3D mpc512x_clk_gated("sdhc-2", "sdhc-ug=
",
> +                                                    &clkregs->sccr2, 17);
> +
> +       /*
> +        * externally provided clocks (when implemented in hardware,
> +        * device tree may specify values which otherwise were unknown)
> +        */
> +       freq =3D get_freq_from_dt("psc_mclk_in");
> +       if (!freq)
> +               freq =3D 25000000;
> +       clks[MPC512x_CLK_PSC_MCLK_IN] =3D mpc512x_clk_fixed("psc_mclk_in"=
, freq);
> +       freq =3D get_freq_from_dt("spdif_tx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] =3D mpc512x_clk_fixed("spdif_tx_in"=
, freq);
> +       freq =3D get_freq_from_dt("spdif_rx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] =3D mpc512x_clk_fixed("spdif_rx_in"=
, freq);
> +
> +       /* fixed frequency for AC97, always 24.567MHz */
> +       clks[MPC512x_CLK_AC97] =3D mpc512x_clk_fixed("ac97", 24567000);
> +
> +       /* clkdev registration for compatibility reasons */
> +       clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
> +
> +       pr_debug("clock tree setup complete\n");
> +       freq =3D clk_get_rate(clks[MPC512x_CLK_E300]);
> +       pr_debug("derived PPC freq [%d]\n", freq);
> +       freq =3D clk_get_rate(clks[MPC512x_CLK_IPS]);
> +       pr_debug("derived IPS freq [%d]\n", freq);
> +       freq =3D clk_get_rate(clks[MPC512x_CLK_LPC]);
> +       pr_debug("derived LPC freq [%d]\n", freq);
> +
> +       /* enable some of the clocks here unconditionally because ... */
> +       pr_debug("automatically enabling some clocks\n");
> +       /* some are essential yet never get claimed by any driver */
> +       clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> +       clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> +       clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> +       clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> +       clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> +       clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> +       /* some are required yet no dependencies were declared */
> +       clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> +       /* some are not yet acquired by their respective drivers */
> +       clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console=
 */
> +       clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> +       clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> +       clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> +       /*
> +        * some have their individual clock subtree with separate clock
> +        * items and their individual enable counters, yet share a
> +        * common gate (refer to the same register location) while the
> +        * common clock driver code is not aware of the fact and the
> +        * platform's code doesn't provide specific support either
> +        *
> +        * what might happen is that e.g. enabling two MSCAN clock items
> +        * and disabling one of them will disable the common gate and
> +        * thus break the other MSCAN clock as well
> +        */
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> +}
> +
> +/*
> + * registers the set of public clocks (those listed in the dt-bindings/
> + * header file) for OF lookups, keeps the intermediates private to us
> + */
> +static void mpc5121_clk_register_of_provider(struct device_node *np)
> +{
> +       clk_data.clks =3D clks;
> +       clk_data.clk_num =3D MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_=
SIZE() */
> +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +}
> +
> +int __init mpc5121_clk_init(void)
> +{
> +       struct device_node *clk_np;
> +       int busfreq;
> +
> +       /* map the clock control registers */
> +       clk_np =3D of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock=
");
> +       if (!clk_np)
> +               return -ENODEV;
> +       clkregs =3D of_iomap(clk_np, 0);
> +       WARN_ON(!clkregs);
> +
> +       /* invalidate all not yet registered clock slots */
> +       mpc512x_clk_preset_data();
> +
> +       /*
> +        * have the device tree scanned for "fixed-clock" nodes (which
> +        * includes the oscillator node if the board's DT provides one)
> +        */
> +       of_clk_init(NULL);
> +
> +       /*
> +        * add a dummy clock for those situations where a clock spec is
> +        * required yet no real clock is involved
> +        */
> +       clks[MPC512x_CLK_DUMMY] =3D mpc512x_clk_fixed("dummy", 0);
> +
> +       /*
> +        * have all the real nodes in the clock tree populated from REF
> +        * down to all leaves, either starting from the OSC node or from
> +        * a REF root that was created from the IPS bus clock input
> +        */
> +       busfreq =3D get_freq_from_dt("bus-frequency");
> +       mpc512x_clk_setup_clock_tree(busfreq);
> +
> +       /* register as an OF clock provider */
> +       mpc5121_clk_register_of_provider(clk_np);
> +
> +       return 0;
> +}
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index c4f7799..7f8fc64 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(str=
uct device_node *np,
>   * for improved portability across platforms
>   */
>  =

> +#if IS_ENABLED(CONFIG_PPC)
> +
> +static inline u32 clk_readl(u32 __iomem *reg)
> +{
> +       return ioread32be(reg);
> +}
> +
> +static inline void clk_writel(u32 val, u32 __iomem *reg)
> +{
> +       iowrite32be(val, reg);
> +}
> +
> +#else  /* platform dependent I/O accessors */
> +
>  static inline u32 clk_readl(u32 __iomem *reg)
>  {
>         return readl(reg);
> @@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *r=
eg)
>         writel(val, reg);
>  }
>  =

> +#endif /* platform dependent I/O accessors */
> +
>  #endif /* CONFIG_COMMON_CLK */
>  #endif /* CLK_PROVIDER_H */
> -- =

> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-02 23:41           ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-02 23:41 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-07-22 05:14:44)
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
> 
> this driver implements the publicly announced set of clocks (which can
> get referenced by means of symbolic identifiers from the dt-bindings
> header file), as well as generates additional 'struct clk' items where
> the SoC hardware cannot easily get mapped to the common primitives of
> the clock API, or requires "intermediate" clock nodes to represent
> clocks that have both gates and dividers
> 
> the previous PPC_CLOCK implementation is kept in place and remains in
> parallel to the common clock implementation for test and comparison
> during migration, a compile time option picks one of the two
> alternatives (Kconfig switch, common clock used by default)
> 
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> - some of the clocks are useful to have for diagnostics and information
>   despite their not getting claimed by any drivers (CPU, internal and
>   external RAM, internal busses, boot media)
> - some of the clocks aren't claimed by their peripheral drivers yet,
>   either because of missing driver support or because device tree specs
>   aren't available yet (but the workarounds will get removed as the
>   drivers get adjusted and the device tree provides the clock specs)
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)
> 
> clkdev registration provides "alias names" for few clock items
> - to not break those peripheral drivers which encode their component
>   index into the name that is used for clock lookup (UART, SPI, USB)
> - to not break those drivers which use names for the clock lookup which
>   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> this workaround will get removed as these drivers get adjusted after
> device tree based clock lookup has become available
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Hi Gerhard,

This looks OK to me. Do you want me to take it or will you keep the
series together? Note that I took "clk: wrap I/O access for improved
portability" into the clk tree already.

Regards,
Mike

> ---
>  arch/powerpc/platforms/512x/Kconfig           |   14 +-
>  arch/powerpc/platforms/512x/Makefile          |    4 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
>  include/linux/clk-provider.h                  |   16 +
>  4 files changed, 818 insertions(+), 2 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> 
> diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
> index fc9c1cb..c5fcdd0 100644
> --- a/arch/powerpc/platforms/512x/Kconfig
> +++ b/arch/powerpc/platforms/512x/Kconfig
> @@ -1,9 +1,21 @@
> +config MPC512x_COMMON_CLK
> +       bool "MPC512x platform uses COMMON_CLK"
> +       default y
> +       depends on PPC_MPC512x
> +       help
> +         This option is only here to support tests and comparison
> +         during development and migration.  This option will get
> +         removed after the COMMON_CLK support for MPC512x has become
> +         fully operational and all drivers were adjusted to explicitly
> +         acquire their required clocks.
> +
>  config PPC_MPC512x
>         bool "512x-based boards"
>         depends on 6xx
>         select FSL_SOC
>         select IPIC
> -       select PPC_CLOCK
> +       select PPC_CLOCK if !MPC512x_COMMON_CLK
> +       select COMMON_CLK if MPC512x_COMMON_CLK
>         select PPC_PCI_CHOICE
>         select FSL_PCI if PCI
>         select ARCH_WANT_OPTIONAL_GPIOLIB
> diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
> index 72fb934..1e05f9d 100644
> --- a/arch/powerpc/platforms/512x/Makefile
> +++ b/arch/powerpc/platforms/512x/Makefile
> @@ -1,7 +1,9 @@
>  #
>  # Makefile for the Freescale PowerPC 512x linux kernel.
>  #
> -obj-y                          += clock.o mpc512x_shared.o
> +obj-$(CONFIG_PPC_CLOCK)                += clock.o
> +obj-$(CONFIG_COMMON_CLK)       += clock-commonclk.o
> +obj-y                          += mpc512x_shared.o
>  obj-$(CONFIG_MPC5121_ADS)      += mpc5121_ads.o mpc5121_ads_cpld.o
>  obj-$(CONFIG_MPC512x_GENERIC)  += mpc512x_generic.o
>  obj-$(CONFIG_PDM360NG)         += pdm360ng.o
> diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
> new file mode 100644
> index 0000000..762ee85
> --- /dev/null
> +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> @@ -0,0 +1,786 @@
> +/*
> + * Copyright (C) 2013 DENX Software Engineering
> + *
> + * Gerhard Sittig, <gsi@denx.de>
> + *
> + * common clock driver support for the MPC512x platform
> + *
> + * This 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +
> +#include <asm/mpc5121.h>
> +#include <dt-bindings/clock/mpc512x-clock.h>
> +
> +#include "mpc512x.h"           /* our public mpc5121_clk_init() API */
> +
> +/* helpers to keep the MCLK intermediates "somewhere" in our table */
> +enum {
> +       MCLK_IDX_MUX0,
> +       MCLK_IDX_EN0,
> +       MCLK_IDX_DIV0,
> +       MCLK_IDX_MUX1,
> +       MCLK_MAX_IDX,
> +};
> +
> +#define NR_PSCS                        12
> +#define NR_MSCANS              4
> +#define NR_SPDIFS              1
> +#define NR_MCLKS               (NR_PSCS + NR_MSCANS + NR_SPDIFS)
> +
> +/* extend the public set of clocks by adding internal slots for management */
> +enum {
> +       /* arrange for adjacent numbers after the public set */
> +       MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
> +       /* clocks which aren't announced to the public */
> +       MPC512x_CLK_DDR,
> +       MPC512x_CLK_MEM,
> +       MPC512x_CLK_IIM,
> +       MPC512x_CLK_SDHC_2,
> +       /* intermediates in div+gate combos or fractional dividers */
> +       MPC512x_CLK_DDR_UG,
> +       MPC512x_CLK_SDHC_x4,
> +       MPC512x_CLK_SDHC_UG,
> +       MPC512x_CLK_DIU_x4,
> +       MPC512x_CLK_DIU_UG,
> +       MPC512x_CLK_MBX_BUS_UG,
> +       MPC512x_CLK_MBX_UG,
> +       MPC512x_CLK_MBX_3D_UG,
> +       MPC512x_CLK_PCI_UG,
> +       MPC512x_CLK_NFC_UG,
> +       MPC512x_CLK_LPC_UG,
> +       MPC512x_CLK_SPDIF_TX_IN,
> +       /* intermediates for the mux+gate+div+mux MCLK generation */
> +       MPC512x_CLK_MCLKS_FIRST,
> +       MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
> +                               + NR_MCLKS * MCLK_MAX_IDX,
> +       /* internal, symbolic spec for the number of slots */
> +       MPC512x_CLK_LAST_PRIVATE,
> +};
> +
> +/* data required for the OF clock provider registration */
> +static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
> +static struct clk_onecell_data clk_data;
> +
> +/* CCM register access */
> +static struct mpc512x_ccm __iomem *clkregs;
> +static DEFINE_SPINLOCK(clklock);
> +
> +/* convenience wrappers around the common clk API */
> +static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
> +{
> +       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
> +}
> +
> +static inline struct clk *mpc512x_clk_factor(
> +       const char *name, const char *parent_name,
> +       int mul, int div)
> +{
> +       int clkflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
> +                                        mul, div);
> +}
> +
> +static inline struct clk *mpc512x_clk_divider(
> +       const char *name, const char *parent_name, u8 clkflags,
> +       u32 __iomem *reg, u8 pos, u8 len, int divflags)
> +{
> +       return clk_register_divider(NULL, name, parent_name, clkflags,
> +                                   reg, pos, len, divflags, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_divtable(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos, u8 len,
> +       const struct clk_div_table *divtab)
> +{
> +       u8 divflags;
> +
> +       divflags = 0;
> +       return clk_register_divider_table(NULL, name, parent_name, 0,
> +                                         reg, pos, len, divflags,
> +                                         divtab, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_gated(
> +       const char *name, const char *parent_name,
> +       u32 __iomem *reg, u8 pos)
> +{
> +       int clkflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       return clk_register_gate(NULL, name, parent_name, clkflags,
> +                                reg, pos, 0, &clklock);
> +}
> +
> +static inline struct clk *mpc512x_clk_muxed(const char *name,
> +       const char **parent_names, int parent_count,
> +       u32 __iomem *reg, u8 pos, u8 len)
> +{
> +       int clkflags;
> +       u8 muxflags;
> +
> +       clkflags = CLK_SET_RATE_PARENT;
> +       muxflags = 0;
> +       return clk_register_mux(NULL, name,
> +                               parent_names, parent_count, clkflags,
> +                               reg, pos, len, muxflags, &clklock);
> +}
> +
> +/* helper to isolate a bit field from a register */
> +static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
> +{
> +       uint32_t val;
> +
> +       val = in_be32(reg);
> +       val >>= pos;
> +       val &= (1 << len) - 1;
> +       return val;
> +}
> +
> +/* get the SPMF and translate it into the "sys pll" multiplier */
> +static int get_spmf_mult(void)
> +{
> +       static int spmf_to_mult[] = {
> +               68, 1, 12, 16, 20, 24, 28, 32,
> +               36, 40, 44, 48, 52, 56, 60, 64,
> +       };
> +       int spmf;
> +
> +       spmf = get_bit_field(&clkregs->spmr, 24, 4);
> +       return spmf_to_mult[spmf];
> +}
> +
> +/*
> + * get the SYS_DIV value and translate it into a divide factor
> + *
> + * values returned from here are a multiple of the real factor since the
> + * divide ratio is fractional
> + */
> +static int get_sys_div_x2(void)
> +{
> +       static int sysdiv_code_to_x2[] = {
> +               4, 5, 6, 7, 8, 9, 10, 14,
> +               12, 16, 18, 22, 20, 24, 26, 30,
> +               28, 32, 34, 38, 36, 40, 42, 46,
> +               44, 48, 50, 54, 52, 56, 58, 62,
> +               60, 64, 66,
> +       };
> +       int divcode;
> +
> +       divcode = get_bit_field(&clkregs->scfr2, 26, 6);
> +       return sysdiv_code_to_x2[divcode];
> +}
> +
> +/*
> + * get the CPMF value and translate it into a multiplier factor
> + *
> + * values returned from here are a multiple of the real factor since the
> + * multiplier ratio is fractional
> + */
> +static int get_cpmf_mult_x2(void)
> +{
> +       static int cpmf_to_mult[] = {
> +               72, 2, 2, 3, 4, 5, 6, 7,
> +       };
> +       int cpmf;
> +
> +       cpmf = get_bit_field(&clkregs->spmr, 16, 4);
> +       return cpmf_to_mult[cpmf];
> +}
> +
> +/*
> + * some of the clock dividers do scale in a linear way, yet not all of
> + * their bit combinations are legal; use a divider table to get a
> + * resulting set of applicable divider values
> + */
> +
> +/* applies to the IPS_DIV, and PCI_DIV values */
> +static struct clk_div_table divtab_2346[] = {
> +       { .val = 2, .div = 2, },
> +       { .val = 3, .div = 3, },
> +       { .val = 4, .div = 4, },
> +       { .val = 6, .div = 6, },
> +       { .div = 0, },
> +};
> +
> +/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
> +static struct clk_div_table divtab_1234[] = {
> +       { .val = 1, .div = 1, },
> +       { .val = 2, .div = 2, },
> +       { .val = 3, .div = 3, },
> +       { .val = 4, .div = 4, },
> +       { .div = 0, },
> +};
> +
> +static int get_freq_from_dt(char *propname)
> +{
> +       struct device_node *np;
> +       const unsigned int *prop;
> +       int val;
> +
> +       val = 0;
> +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> +       if (np) {
> +               prop = of_get_property(np, propname, NULL);
> +               if (prop)
> +                       val = *prop;
> +           of_node_put(np);
> +       }
> +       return val;
> +}
> +
> +static void mpc512x_clk_preset_data(void)
> +{
> +       size_t i;
> +
> +       for (i = 0; i < ARRAY_SIZE(clks); i++)
> +               clks[i] = ERR_PTR(-ENODEV);
> +}
> +
> +/*
> + * - receives the "bus frequency" from the caller (that's the IPS clock
> + *   rate, the historical source of clock information)
> + * - fetches the system PLL multiplier and divider values as well as the
> + *   IPS divider value from hardware
> + * - determines the REF clock rate either from the XTAL/OSC spec (if
> + *   there is a device tree node describing the oscillator) or from the
> + *   IPS bus clock (supported for backwards compatibility, such that
> + *   setups without XTAL/OSC specs keep working)
> + * - creates the "ref" clock item in the clock tree, such that
> + *   subsequent code can create the remainder of the hierarchy (REF ->
> + *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
> + *   values
> + */
> +static void mpc512x_clk_setup_ref_clock(int bus_freq,
> +       int *sys_mul, int *sys_div, int *ips_div)
> +{
> +       struct clk *osc_clk;
> +       int calc_freq;
> +
> +       /* fetch mul/div factors from the hardware */
> +       *sys_mul = get_spmf_mult();
> +       *sys_mul *= 2;          /* compensate for the fractional divider */
> +       *sys_div = get_sys_div_x2();
> +       *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
> +
> +       /* lookup the oscillator node */
> +       osc_clk = clk_get(NULL, "osc");
> +       if (osc_clk) {
> +               /* descend REF directly from OSC, verify the IPS rate */
> +               clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
> +               calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
> +               calc_freq *= *sys_mul;
> +               calc_freq /= *sys_div;
> +               calc_freq /= 2;
> +               calc_freq /= *ips_div;
> +               if (bus_freq && calc_freq != bus_freq)
> +                       pr_warn("calc rate %d != OF spec %d\n",
> +                               calc_freq, bus_freq);
> +       } else {
> +               /* calculate OSC rate and create REF from the freq value */
> +               calc_freq = bus_freq;   /* start with IPS */
> +               calc_freq *= *ips_div;  /* IPS -> CSB */
> +               calc_freq *= 2;         /* CSB -> SYS */
> +               calc_freq *= *sys_div;  /* SYS -> PLL out */
> +               calc_freq /= *sys_mul;  /* PLL out -> REF == OSC */
> +               clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
> +       }
> +}
> +
> +/*
> + * helper code for the MCLK subtree setup
> + *
> + * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
> + * suggests that all instances of the "PSC clock generation" are equal,
> + * and that one might re-use the PSC setup for MSCAN clock generation
> + * (section 5.2.5) as well, at least the logic if not the data for
> + * description
> + *
> + * the details (starting at page 5-20) show differences in the specific
> + * inputs of the first mux stage ("can clk in", "spdif tx"), and the
> + * factual non-availability of the second mux stage (it's present yet
> + * only one input is valid)
> + *
> + * the MSCAN clock related registers (starting at page 5-35) all
> + * reference "spdif clk" at the first mux stage and don't mention any
> + * "can clk" at all, which somehow is unexpected
> + *
> + * TODO re-check the document, and clarify whether the RM is correct in
> + * the overview or in the details, and whether the difference is a
> + * clipboard induced error or results from chip revisions
> + *
> + * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
> + * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
> + * first a doc update is required which better reflects reality in the
> + * SoC before the implementation should follow while no questions remain
> + */
> +
> +/*
> + * note that this declaration raises a checkpatch warning, but
> + * it's the very data type which <linux/clk-provider.h> expects,
> + * making this declaration pass checkpatch will break compilation
> + */
> +static const char *parent_names_mux0[] = {
> +       "sys", "ref", "psc-mclk-in", "spdif-tx",
> +};
> +
> +enum mclk_type {
> +       MCLK_TYPE_PSC,
> +       MCLK_TYPE_MSCAN,
> +       MCLK_TYPE_SPDIF,
> +};
> +
> +struct mclk_setup_data {
> +       enum mclk_type type;
> +       int comp_idx;
> +       bool has_mclk1;
> +       int bit_sccr1, bit_sccr2;
> +       const char *name_mux0;
> +       const char *name_en0;
> +       const char *name_div0;
> +       const char *parent_names_mux1[2];
> +       const char *name_mux1;
> +       const char *name_mclk;
> +};
> +
> +#define MCLK_SETUP_DATA_PSC(id) { \
> +       MCLK_TYPE_PSC, id, \
> +       0, 27 - id, -1, \
> +       "psc" #id "-mux0", \
> +       "psc" #id "-en0", \
> +       "psc" #id "_mclk_div", \
> +       { "psc" #id "_mclk_div", "dummy", }, \
> +       "psc" #id "_mclk_out", \
> +       "psc" #id "_mclk", \
> +}
> +
> +#define MCLK_SETUP_DATA_MSCAN(id) { \
> +       MCLK_TYPE_MSCAN, id, \
> +       0, -1, 25, \
> +       "mscan" #id "-mux0", \
> +       "mscan" #id "-en0", \
> +       "mscan" #id "_mclk_div", \
> +       { "mscan" #id "_mclk_div", "dummy", }, \
> +       "mscan" #id "_mclk_out", \
> +       "mscan" #id "_mclk", \
> +}
> +
> +#define MCLK_SETUP_DATA_SPDIF { \
> +       MCLK_TYPE_SPDIF, 0, \
> +       1, -1, 23, \
> +       "spdif-mux0", \
> +       "spdif-en0", \
> +       "spdif_mclk_div", \
> +       { "spdif_mclk_div", "spdif-rx", }, \
> +       "spdif_mclk_out", \
> +       "spdif_mclk", \
> +}
> +
> +static struct mclk_setup_data mclk_psc_data[] = {
> +       MCLK_SETUP_DATA_PSC(0),
> +       MCLK_SETUP_DATA_PSC(1),
> +       MCLK_SETUP_DATA_PSC(2),
> +       MCLK_SETUP_DATA_PSC(3),
> +       MCLK_SETUP_DATA_PSC(4),
> +       MCLK_SETUP_DATA_PSC(5),
> +       MCLK_SETUP_DATA_PSC(6),
> +       MCLK_SETUP_DATA_PSC(7),
> +       MCLK_SETUP_DATA_PSC(8),
> +       MCLK_SETUP_DATA_PSC(9),
> +       MCLK_SETUP_DATA_PSC(10),
> +       MCLK_SETUP_DATA_PSC(11),
> +};
> +
> +static struct mclk_setup_data mclk_mscan_data[] = {
> +       MCLK_SETUP_DATA_MSCAN(0),
> +       MCLK_SETUP_DATA_MSCAN(1),
> +       MCLK_SETUP_DATA_MSCAN(2),
> +       MCLK_SETUP_DATA_MSCAN(3),
> +};
> +
> +static struct mclk_setup_data mclk_spdif_data[] = {
> +       MCLK_SETUP_DATA_SPDIF,
> +};
> +
> +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> +{
> +       size_t clks_idx_pub, clks_idx_int;
> +       u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> +       u32 __iomem *sccr_reg;  /* system clock control register (enable) */
> +       int sccr_bit;
> +       int div;
> +
> +       /* derive a few parameters from the component type and index */
> +       switch (entry->type) {
> +       case MCLK_TYPE_PSC:
> +               clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +                            + (entry->comp_idx) * MCLK_MAX_IDX;
> +               mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> +               break;
> +       case MCLK_TYPE_MSCAN:
> +               clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +                            + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> +               mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> +               break;
> +       case MCLK_TYPE_SPDIF:
> +               clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> +                            + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> +               mccr_reg = &clkregs->spccr;
> +               break;
> +       default:
> +               return;
> +       }
> +       if (entry->bit_sccr1 >= 0) {
> +               sccr_reg = &clkregs->sccr1;
> +               sccr_bit = entry->bit_sccr1;
> +       } else if (entry->bit_sccr2 >= 0) {
> +               sccr_reg = &clkregs->sccr2;
> +               sccr_bit = entry->bit_sccr2;
> +       } else {
> +               sccr_reg = NULL;
> +       }
> +
> +       /*
> +        * this was grabbed from the PPC_CLOCK implementation, which
> +        * enforced a specific MCLK divider while the clock was gated
> +        * during setup (that's a documented hardware requirement)
> +        *
> +        * the PPC_CLOCK implementation might even have violated the
> +        * "MCLK <= IPS" constraint, the fixed divider value of 1
> +        * results in a divider of 2 and thus MCLK = SYS/2 which equals
> +        * CSB which is greater than IPS; the serial port setup may have
> +        * adjusted the divider which the clock setup might have left in
> +        * an undesirable state
> +        *
> +        * initial setup is:
> +        * - MCLK 0 from SYS
> +        * - MCLK DIV such to not exceed the IPS clock
> +        * - MCLK 0 enabled
> +        * - MCLK 1 from MCLK DIV
> +        */
> +       div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> +       div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> +       out_be32(mccr_reg, (0 << 16));
> +       out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> +       out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> +
> +       /*
> +        * create the 'struct clk' items of the MCLK's clock subtree
> +        *
> +        * note that by design we always create all nodes and won't take
> +        * shortcuts here, because
> +        * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> +        *   selectable inputs to the CFM while those who "actually use"
> +        *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> +        *   for their bitrate
> +        * - in the absence of "aliases" for clocks we need to create
> +        *   individial 'struct clk' items for whatever might get
> +        *   referenced or looked up, even if several of those items are
> +        *   identical from the logical POV (their rate value)
> +        * - for easier future maintenance and for better reflection of
> +        *   the SoC's documentation, it appears appropriate to generate
> +        *   clock items even for those muxers which actually are NOPs
> +        *   (those with two inputs of which one is reserved)
> +        */
> +       clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> +                       entry->name_mux0,
> +                       &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> +                       mccr_reg, 14, 2);
> +       clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> +                       entry->name_en0, entry->name_mux0,
> +                       mccr_reg, 16);
> +       clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> +                       entry->name_div0,
> +                       entry->name_en0, CLK_SET_RATE_GATE,
> +                       mccr_reg, 17, 15, 0);
> +       if (entry->has_mclk1) {
> +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> +                               entry->name_mux1,
> +                               &entry->parent_names_mux1[0],
> +                               ARRAY_SIZE(entry->parent_names_mux1),
> +                               mccr_reg, 7, 1);
> +       } else {
> +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> +                               entry->name_mux1, entry->parent_names_mux1[0],
> +                               1, 1);
> +       }
> +       if (sccr_reg) {
> +               clks[clks_idx_pub] = mpc512x_clk_gated(
> +                               entry->name_mclk,
> +                               entry->name_mux1, sccr_reg, sccr_bit);
> +       } else {
> +               clks[clks_idx_pub] = mpc512x_clk_factor(
> +                               entry->name_mclk,
> +                               entry->name_mux1, 1, 1);
> +       }
> +
> +       /*
> +        * without this "clock device" registration, "simple" lookups in
> +        * the SPI master initialization and serial port setup will fail
> +        *
> +        * those drivers need to get adjusted to lookup their required
> +        * clocks from device tree specs, and device tree nodes need to
> +        * provide the clock specs, before this clkdev registration
> +        * becomes obsolete
> +        */
> +       clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> +}
> +
> +static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
> +{
> +       while (count-- > 0)
> +               mpc512x_clk_setup_mclk(table++);
> +}
> +
> +static void mpc512x_clk_setup_clock_tree(int busfreq)
> +{
> +       int sys_mul, sys_div, ips_div;
> +       int mul, div;
> +       int freq;
> +
> +       /*
> +        * TODO
> +        * - consider whether to handle clocks which have both gates and
> +        *   dividers via intermediates or by means of composites
> +        * - fractional dividers appear to not map well to composites
> +        *   since they can be seen as a fixed multiplier and an
> +        *   adjustable divider, while composites can only combine at
> +        *   most one of a mux, div, and gate each into one 'struct clk'
> +        *   item
> +        * - PSC/MSCAN/SPDIF clock generation OTOH already is very
> +        *   specific and cannot get mapped to componsites (at least not
> +        *   a single one, maybe two of them, but see the comment about
> +        *   "intermediates are referenced from elsewhere, too")
> +        * - trim the list of auto-enabled clocks after drivers acquire
> +        *   them correctly as needed
> +        */
> +
> +       /* regardless of whether XTAL/OSC exists, have REF created */
> +       mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
> +
> +       /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
> +       clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
> +                                                  sys_mul, sys_div);
> +       clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
> +       clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
> +                                                    &clkregs->scfr1, 23, 3,
> +                                                    divtab_2346);
> +
> +       /* now setup anything below SYS and CSB and IPS */
> +       clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
> +       clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
> +       clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
> +                                                       &clkregs->scfr2, 0, 8,
> +                                                       CLK_DIVIDER_ONE_BASED);
> +       clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
> +       clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
> +                                                      &clkregs->scfr1, 0, 8,
> +                                                      CLK_DIVIDER_ONE_BASED);
> +
> +       /*
> +        * the "power architecture PLL" was setup from data which was
> +        * sampled from the reset config word, at this point in time the
> +        * configuration can be considered fixed and read only (i.e. no
> +        * longer adjustable, or no longer in need of adjustment), which
> +        * is why we don't register a PLL here but assume fixed factors
> +        */
> +       mul = get_cpmf_mult_x2();
> +       div = 2;        /* compensate for the fractional factor */
> +       clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
> +
> +       clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
> +                                                         1, 2);
> +       clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
> +                                                       &clkregs->scfr1, 14, 3,
> +                                                       divtab_1234);
> +       clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
> +                                                        1, 1);
> +       clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
> +                                                       &clkregs->scfr1, 20, 3,
> +                                                       divtab_2346);
> +       clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
> +                                                       &clkregs->scfr1, 8, 3,
> +                                                       divtab_1234);
> +       clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
> +                                                       &clkregs->scfr1, 11, 3,
> +                                                       divtab_1234);
> +
> +       clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
> +                                                 &clkregs->sccr1, 30);
> +       clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
> +                                                 &clkregs->sccr1, 29);
> +       clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
> +                                                  &clkregs->sccr1, 28);
> +       mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
> +       clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
> +                                                      &clkregs->sccr1, 15);
> +       clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
> +                                                  &clkregs->sccr1, 14);
> +       clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
> +                                                 &clkregs->sccr1, 13);
> +       clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
> +                                                 &clkregs->sccr1, 11);
> +       clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
> +                                                 &clkregs->sccr1, 10);
> +
> +       clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
> +                                                 &clkregs->sccr2, 31);
> +       clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
> +                                                 &clkregs->sccr2, 30);
> +       clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
> +                                                 &clkregs->sccr2, 29);
> +       clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
> +                                                  &clkregs->sccr2, 28);
> +       clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
> +                                                  &clkregs->sccr2, 27);
> +       clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> +                                                 &clkregs->sccr2, 26);
> +       mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> +       clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> +                                                  &clkregs->sccr2, 24);
> +       mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> +       clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
> +                                                     &clkregs->sccr2, 22);
> +       clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
> +                                                 &clkregs->sccr2, 21);
> +       clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
> +                                                    &clkregs->sccr2, 20);
> +       clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
> +                                                 &clkregs->sccr2, 19);
> +       clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
> +                                                 &clkregs->sccr2, 18);
> +       clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
> +                                                    &clkregs->sccr2, 17);
> +
> +       /*
> +        * externally provided clocks (when implemented in hardware,
> +        * device tree may specify values which otherwise were unknown)
> +        */
> +       freq = get_freq_from_dt("psc_mclk_in");
> +       if (!freq)
> +               freq = 25000000;
> +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> +       freq = get_freq_from_dt("spdif_tx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> +       freq = get_freq_from_dt("spdif_rx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
> +
> +       /* fixed frequency for AC97, always 24.567MHz */
> +       clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
> +
> +       /* clkdev registration for compatibility reasons */
> +       clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
> +       clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
> +
> +       pr_debug("clock tree setup complete\n");
> +       freq = clk_get_rate(clks[MPC512x_CLK_E300]);
> +       pr_debug("derived PPC freq [%d]\n", freq);
> +       freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
> +       pr_debug("derived IPS freq [%d]\n", freq);
> +       freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
> +       pr_debug("derived LPC freq [%d]\n", freq);
> +
> +       /* enable some of the clocks here unconditionally because ... */
> +       pr_debug("automatically enabling some clocks\n");
> +       /* some are essential yet never get claimed by any driver */
> +       clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> +       clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> +       clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> +       clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> +       clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> +       clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> +       /* some are required yet no dependencies were declared */
> +       clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> +       /* some are not yet acquired by their respective drivers */
> +       clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> +       clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> +       clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> +       clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> +       /*
> +        * some have their individual clock subtree with separate clock
> +        * items and their individual enable counters, yet share a
> +        * common gate (refer to the same register location) while the
> +        * common clock driver code is not aware of the fact and the
> +        * platform's code doesn't provide specific support either
> +        *
> +        * what might happen is that e.g. enabling two MSCAN clock items
> +        * and disabling one of them will disable the common gate and
> +        * thus break the other MSCAN clock as well
> +        */
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> +}
> +
> +/*
> + * registers the set of public clocks (those listed in the dt-bindings/
> + * header file) for OF lookups, keeps the intermediates private to us
> + */
> +static void mpc5121_clk_register_of_provider(struct device_node *np)
> +{
> +       clk_data.clks = clks;
> +       clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */
> +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +}
> +
> +int __init mpc5121_clk_init(void)
> +{
> +       struct device_node *clk_np;
> +       int busfreq;
> +
> +       /* map the clock control registers */
> +       clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
> +       if (!clk_np)
> +               return -ENODEV;
> +       clkregs = of_iomap(clk_np, 0);
> +       WARN_ON(!clkregs);
> +
> +       /* invalidate all not yet registered clock slots */
> +       mpc512x_clk_preset_data();
> +
> +       /*
> +        * have the device tree scanned for "fixed-clock" nodes (which
> +        * includes the oscillator node if the board's DT provides one)
> +        */
> +       of_clk_init(NULL);
> +
> +       /*
> +        * add a dummy clock for those situations where a clock spec is
> +        * required yet no real clock is involved
> +        */
> +       clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
> +
> +       /*
> +        * have all the real nodes in the clock tree populated from REF
> +        * down to all leaves, either starting from the OSC node or from
> +        * a REF root that was created from the IPS bus clock input
> +        */
> +       busfreq = get_freq_from_dt("bus-frequency");
> +       mpc512x_clk_setup_clock_tree(busfreq);
> +
> +       /* register as an OF clock provider */
> +       mpc5121_clk_register_of_provider(clk_np);
> +
> +       return 0;
> +}
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index c4f7799..7f8fc64 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
>   * for improved portability across platforms
>   */
>  
> +#if IS_ENABLED(CONFIG_PPC)
> +
> +static inline u32 clk_readl(u32 __iomem *reg)
> +{
> +       return ioread32be(reg);
> +}
> +
> +static inline void clk_writel(u32 val, u32 __iomem *reg)
> +{
> +       iowrite32be(val, reg);
> +}
> +
> +#else  /* platform dependent I/O accessors */
> +
>  static inline u32 clk_readl(u32 __iomem *reg)
>  {
>         return readl(reg);
> @@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
>         writel(val, reg);
>  }
>  
> +#endif /* platform dependent I/O accessors */
> +
>  #endif /* CONFIG_COMMON_CLK */
>  #endif /* CLK_PROVIDER_H */
> -- 
> 1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 13/31] clk: wrap I/O access for improved portability
  2013-08-02 22:30           ` Mike Turquette
@ 2013-08-03 14:08             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 14:08 UTC (permalink / raw)
  To: Mike Turquette; +Cc: Anatolij Gustschin, linuxppc-dev, linux-arm-kernel

[ trimming the CC: list for this strictly clock related and
  source code adjusting change, to not spam the device tree ML or
  other subsystem maintainers, just keeping ARM (for clock) and
  PPC lists and people in the loop ]

On Fri, Aug 02, 2013 at 15:30 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:40)
> > the common clock drivers were motivated/initiated by ARM development
> > and apparently assume little endian peripherals
> > 
> > wrap register/peripherals access in the common code (div, gate, mux)
> > in preparation of adding COMMON_CLK support for other platforms
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> I've taken this into clk-next for testing. regmap deserves investigation
> but I don't think your series should be blocked on that. We can always
> overhaul the basic clock primitives with regmap support later on if that
> makes sense.
> 
> Regards,
> Mike

That's fine.  Though I will re-post this change when updating the
series, but this should not harm (won't conflict) as this
specific patch is stable and won't change any longer.  Keeping
this one patch in the series keeps the series applicable on top
of v3.11-rcN as well as clk-next.

Note that this patch only changes those parts of the code under
drivers/clk/ which get shared among platforms (div, gate, mux).
It doesn't touch non-shared and platform specific drivers.  I
felt this was the most appropriate thing to do.


> > ---
> >  drivers/clk/clk-divider.c    |    6 +++---
> >  drivers/clk/clk-gate.c       |    6 +++---
> >  drivers/clk/clk-mux.c        |    6 +++---
> >  include/linux/clk-provider.h |   17 +++++++++++++++++
> >  4 files changed, 26 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 6d55eb2..2c07061 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> >         struct clk_divider *divider = to_clk_divider(hw);
> >         unsigned int div, val;
> >  
> > -       val = readl(divider->reg) >> divider->shift;
> > +       val = clk_readl(divider->reg) >> divider->shift;
> >         val &= div_mask(divider);
> >  
> >         div = _get_div(divider, val);
> > @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> >         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
> >                 val = div_mask(divider) << (divider->shift + 16);
> >         } else {
> > -               val = readl(divider->reg);
> > +               val = clk_readl(divider->reg);
> >                 val &= ~(div_mask(divider) << divider->shift);
> >         }
> >         val |= value << divider->shift;
> > -       writel(val, divider->reg);
> > +       clk_writel(val, divider->reg);
> >  
> >         if (divider->lock)
> >                 spin_unlock_irqrestore(divider->lock, flags);
> > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> > index 790306e..b7fbd96 100644
> > --- a/drivers/clk/clk-gate.c
> > +++ b/drivers/clk/clk-gate.c
> > @@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >                 if (set)
> >                         reg |= BIT(gate->bit_idx);
> >         } else {
> > -               reg = readl(gate->reg);
> > +               reg = clk_readl(gate->reg);
> >  
> >                 if (set)
> >                         reg |= BIT(gate->bit_idx);
> > @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >                         reg &= ~BIT(gate->bit_idx);
> >         }
> >  
> > -       writel(reg, gate->reg);
> > +       clk_writel(reg, gate->reg);
> >  
> >         if (gate->lock)
> >                 spin_unlock_irqrestore(gate->lock, flags);
> > @@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
> >         u32 reg;
> >         struct clk_gate *gate = to_clk_gate(hw);
> >  
> > -       reg = readl(gate->reg);
> > +       reg = clk_readl(gate->reg);
> >  
> >         /* if a set bit disables this clk, flip it before masking */
> >         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
> > diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> > index 614444c..02ef506 100644
> > --- a/drivers/clk/clk-mux.c
> > +++ b/drivers/clk/clk-mux.c
> > @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
> >          * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
> >          * val = 0x4 really means "bit 2, index starts at bit 0"
> >          */
> > -       val = readl(mux->reg) >> mux->shift;
> > +       val = clk_readl(mux->reg) >> mux->shift;
> >         val &= mux->mask;
> >  
> >         if (mux->table) {
> > @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
> >         if (mux->flags & CLK_MUX_HIWORD_MASK) {
> >                 val = mux->mask << (mux->shift + 16);
> >         } else {
> > -               val = readl(mux->reg);
> > +               val = clk_readl(mux->reg);
> >                 val &= ~(mux->mask << mux->shift);
> >         }
> >         val |= index << mux->shift;
> > -       writel(val, mux->reg);
> > +       clk_writel(val, mux->reg);
> >  
> >         if (mux->lock)
> >                 spin_unlock_irqrestore(mux->lock, flags);
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index 1ec14a7..c4f7799 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -12,6 +12,7 @@
> >  #define __LINUX_CLK_PROVIDER_H
> >  
> >  #include <linux/clk.h>
> > +#include <linux/io.h>
> >  
> >  #ifdef CONFIG_COMMON_CLK
> >  
> > @@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
> >  #define of_clk_init(matches) \
> >         { while (0); }
> >  #endif /* CONFIG_OF */
> > +
> > +/*
> > + * wrap access to peripherals in accessor routines
> > + * for improved portability across platforms
> > + */
> > +
> > +static inline u32 clk_readl(u32 __iomem *reg)
> > +{
> > +       return readl(reg);
> > +}
> > +
> > +static inline void clk_writel(u32 val, u32 __iomem *reg)
> > +{
> > +       writel(val, reg);
> > +}
> > +
> >  #endif /* CONFIG_COMMON_CLK */
> >  #endif /* CLK_PROVIDER_H */
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 13/31] clk: wrap I/O access for improved portability
@ 2013-08-03 14:08             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

[ trimming the CC: list for this strictly clock related and
  source code adjusting change, to not spam the device tree ML or
  other subsystem maintainers, just keeping ARM (for clock) and
  PPC lists and people in the loop ]

On Fri, Aug 02, 2013 at 15:30 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:40)
> > the common clock drivers were motivated/initiated by ARM development
> > and apparently assume little endian peripherals
> > 
> > wrap register/peripherals access in the common code (div, gate, mux)
> > in preparation of adding COMMON_CLK support for other platforms
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> I've taken this into clk-next for testing. regmap deserves investigation
> but I don't think your series should be blocked on that. We can always
> overhaul the basic clock primitives with regmap support later on if that
> makes sense.
> 
> Regards,
> Mike

That's fine.  Though I will re-post this change when updating the
series, but this should not harm (won't conflict) as this
specific patch is stable and won't change any longer.  Keeping
this one patch in the series keeps the series applicable on top
of v3.11-rcN as well as clk-next.

Note that this patch only changes those parts of the code under
drivers/clk/ which get shared among platforms (div, gate, mux).
It doesn't touch non-shared and platform specific drivers.  I
felt this was the most appropriate thing to do.


> > ---
> >  drivers/clk/clk-divider.c    |    6 +++---
> >  drivers/clk/clk-gate.c       |    6 +++---
> >  drivers/clk/clk-mux.c        |    6 +++---
> >  include/linux/clk-provider.h |   17 +++++++++++++++++
> >  4 files changed, 26 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 6d55eb2..2c07061 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> >         struct clk_divider *divider = to_clk_divider(hw);
> >         unsigned int div, val;
> >  
> > -       val = readl(divider->reg) >> divider->shift;
> > +       val = clk_readl(divider->reg) >> divider->shift;
> >         val &= div_mask(divider);
> >  
> >         div = _get_div(divider, val);
> > @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> >         if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
> >                 val = div_mask(divider) << (divider->shift + 16);
> >         } else {
> > -               val = readl(divider->reg);
> > +               val = clk_readl(divider->reg);
> >                 val &= ~(div_mask(divider) << divider->shift);
> >         }
> >         val |= value << divider->shift;
> > -       writel(val, divider->reg);
> > +       clk_writel(val, divider->reg);
> >  
> >         if (divider->lock)
> >                 spin_unlock_irqrestore(divider->lock, flags);
> > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> > index 790306e..b7fbd96 100644
> > --- a/drivers/clk/clk-gate.c
> > +++ b/drivers/clk/clk-gate.c
> > @@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >                 if (set)
> >                         reg |= BIT(gate->bit_idx);
> >         } else {
> > -               reg = readl(gate->reg);
> > +               reg = clk_readl(gate->reg);
> >  
> >                 if (set)
> >                         reg |= BIT(gate->bit_idx);
> > @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >                         reg &= ~BIT(gate->bit_idx);
> >         }
> >  
> > -       writel(reg, gate->reg);
> > +       clk_writel(reg, gate->reg);
> >  
> >         if (gate->lock)
> >                 spin_unlock_irqrestore(gate->lock, flags);
> > @@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
> >         u32 reg;
> >         struct clk_gate *gate = to_clk_gate(hw);
> >  
> > -       reg = readl(gate->reg);
> > +       reg = clk_readl(gate->reg);
> >  
> >         /* if a set bit disables this clk, flip it before masking */
> >         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
> > diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> > index 614444c..02ef506 100644
> > --- a/drivers/clk/clk-mux.c
> > +++ b/drivers/clk/clk-mux.c
> > @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
> >          * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
> >          * val = 0x4 really means "bit 2, index starts at bit 0"
> >          */
> > -       val = readl(mux->reg) >> mux->shift;
> > +       val = clk_readl(mux->reg) >> mux->shift;
> >         val &= mux->mask;
> >  
> >         if (mux->table) {
> > @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
> >         if (mux->flags & CLK_MUX_HIWORD_MASK) {
> >                 val = mux->mask << (mux->shift + 16);
> >         } else {
> > -               val = readl(mux->reg);
> > +               val = clk_readl(mux->reg);
> >                 val &= ~(mux->mask << mux->shift);
> >         }
> >         val |= index << mux->shift;
> > -       writel(val, mux->reg);
> > +       clk_writel(val, mux->reg);
> >  
> >         if (mux->lock)
> >                 spin_unlock_irqrestore(mux->lock, flags);
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index 1ec14a7..c4f7799 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -12,6 +12,7 @@
> >  #define __LINUX_CLK_PROVIDER_H
> >  
> >  #include <linux/clk.h>
> > +#include <linux/io.h>
> >  
> >  #ifdef CONFIG_COMMON_CLK
> >  
> > @@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
> >  #define of_clk_init(matches) \
> >         { while (0); }
> >  #endif /* CONFIG_OF */
> > +
> > +/*
> > + * wrap access to peripherals in accessor routines
> > + * for improved portability across platforms
> > + */
> > +
> > +static inline u32 clk_readl(u32 __iomem *reg)
> > +{
> > +       return readl(reg);
> > +}
> > +
> > +static inline void clk_writel(u32 val, u32 __iomem *reg)
> > +{
> > +       writel(val, reg);
> > +}
> > +
> >  #endif /* CONFIG_COMMON_CLK */
> >  #endif /* CLK_PROVIDER_H */
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
  2013-08-02 22:43           ` Mike Turquette
@ 2013-08-03 14:19             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 14:19 UTC (permalink / raw)
  To: Mike Turquette
  Cc: devicetree, Detlev Zundel, Wolfram Sang, David Woodhouse,
	Greg Kroah-Hartman, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

On Fri, Aug 02, 2013 at 15:43 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:42)
> > introduce a dt-bindings/ header file for MPC512x clocks,
> > providing symbolic identifiers for those SoC clocks which
> > clients will reference from their device tree nodes
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
> >  1 file changed, 59 insertions(+)
> >  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
> > 
> > diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
> > new file mode 100644
> > index 0000000..46c560e
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/mpc512x-clock.h
> > @@ -0,0 +1,59 @@
> > +/*
> > + * This header provides constants for MPC512x clock specs in DT bindings.
> > + *
> > + * Unfortunately the clock number declaration cannot be an enum but
> > + * needs to be a list of #define directives since when referenced from
> > + * within DTS files they need to get resolved "at compile time".
> 
> Above comment is not really necessary. Otherwise,
> 
> Reviewed-by: Mike Turquette <mturquette@linaro.org>

OK, the next update of the series will remove this comment.


> > + */
> > +
> > +#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> > +#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> > +
> > +#define MPC512x_CLK_DUMMY              0
> > +#define MPC512x_CLK_REF                        1
> > +#define MPC512x_CLK_SYS                        2
> > +#define MPC512x_CLK_DIU                        3
> > +#define MPC512x_CLK_VIU                        4
> > +#define MPC512x_CLK_CSB                        5
> > +#define MPC512x_CLK_E300               6
> > +#define MPC512x_CLK_IPS                        7
> > +#define MPC512x_CLK_FEC                        8
> > +#define MPC512x_CLK_SATA               9
> > +#define MPC512x_CLK_PATA               10
> > +#define MPC512x_CLK_NFC                        11
> > +#define MPC512x_CLK_LPC                        12
> > +#define MPC512x_CLK_MBX_BUS            13
> > +#define MPC512x_CLK_MBX                        14
> > +#define MPC512x_CLK_MBX_3D             15
> > +#define MPC512x_CLK_AXE                        16
> > +#define MPC512x_CLK_USB1               17
> > +#define MPC512x_CLK_USB2               18
> > +#define MPC512x_CLK_I2C                        19
> > +#define MPC512x_CLK_MSCAN0_MCLK                20
> > +#define MPC512x_CLK_MSCAN1_MCLK                21
> > +#define MPC512x_CLK_MSCAN2_MCLK                22
> > +#define MPC512x_CLK_MSCAN3_MCLK                23
> > +#define MPC512x_CLK_SDHC               24
> > +#define MPC512x_CLK_PCI                        25
> > +#define MPC512x_CLK_PSC_MCLK_IN                26
> > +#define MPC512x_CLK_SPDIF_TX           27
> > +#define MPC512x_CLK_SPDIF_RX           28
> > +#define MPC512x_CLK_SPDIF_MCLK         29
> > +#define MPC512x_CLK_AC97               30
> > +#define MPC512x_CLK_PSC0_MCLK          31
> > +#define MPC512x_CLK_PSC1_MCLK          32
> > +#define MPC512x_CLK_PSC2_MCLK          33
> > +#define MPC512x_CLK_PSC3_MCLK          34
> > +#define MPC512x_CLK_PSC4_MCLK          35
> > +#define MPC512x_CLK_PSC5_MCLK          36
> > +#define MPC512x_CLK_PSC6_MCLK          37
> > +#define MPC512x_CLK_PSC7_MCLK          38
> > +#define MPC512x_CLK_PSC8_MCLK          39
> > +#define MPC512x_CLK_PSC9_MCLK          40
> > +#define MPC512x_CLK_PSC10_MCLK         41
> > +#define MPC512x_CLK_PSC11_MCLK         42
> > +#define MPC512x_CLK_PSC_FIFO           43
> > +
> > +#define MPC512x_CLK_LAST_PUBLIC                43
> > +
> > +#endif
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-08-03 14:19             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 14:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 02, 2013 at 15:43 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:42)
> > introduce a dt-bindings/ header file for MPC512x clocks,
> > providing symbolic identifiers for those SoC clocks which
> > clients will reference from their device tree nodes
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  include/dt-bindings/clock/mpc512x-clock.h |   59 +++++++++++++++++++++++++++++
> >  1 file changed, 59 insertions(+)
> >  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
> > 
> > diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
> > new file mode 100644
> > index 0000000..46c560e
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/mpc512x-clock.h
> > @@ -0,0 +1,59 @@
> > +/*
> > + * This header provides constants for MPC512x clock specs in DT bindings.
> > + *
> > + * Unfortunately the clock number declaration cannot be an enum but
> > + * needs to be a list of #define directives since when referenced from
> > + * within DTS files they need to get resolved "at compile time".
> 
> Above comment is not really necessary. Otherwise,
> 
> Reviewed-by: Mike Turquette <mturquette@linaro.org>

OK, the next update of the series will remove this comment.


> > + */
> > +
> > +#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> > +#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
> > +
> > +#define MPC512x_CLK_DUMMY              0
> > +#define MPC512x_CLK_REF                        1
> > +#define MPC512x_CLK_SYS                        2
> > +#define MPC512x_CLK_DIU                        3
> > +#define MPC512x_CLK_VIU                        4
> > +#define MPC512x_CLK_CSB                        5
> > +#define MPC512x_CLK_E300               6
> > +#define MPC512x_CLK_IPS                        7
> > +#define MPC512x_CLK_FEC                        8
> > +#define MPC512x_CLK_SATA               9
> > +#define MPC512x_CLK_PATA               10
> > +#define MPC512x_CLK_NFC                        11
> > +#define MPC512x_CLK_LPC                        12
> > +#define MPC512x_CLK_MBX_BUS            13
> > +#define MPC512x_CLK_MBX                        14
> > +#define MPC512x_CLK_MBX_3D             15
> > +#define MPC512x_CLK_AXE                        16
> > +#define MPC512x_CLK_USB1               17
> > +#define MPC512x_CLK_USB2               18
> > +#define MPC512x_CLK_I2C                        19
> > +#define MPC512x_CLK_MSCAN0_MCLK                20
> > +#define MPC512x_CLK_MSCAN1_MCLK                21
> > +#define MPC512x_CLK_MSCAN2_MCLK                22
> > +#define MPC512x_CLK_MSCAN3_MCLK                23
> > +#define MPC512x_CLK_SDHC               24
> > +#define MPC512x_CLK_PCI                        25
> > +#define MPC512x_CLK_PSC_MCLK_IN                26
> > +#define MPC512x_CLK_SPDIF_TX           27
> > +#define MPC512x_CLK_SPDIF_RX           28
> > +#define MPC512x_CLK_SPDIF_MCLK         29
> > +#define MPC512x_CLK_AC97               30
> > +#define MPC512x_CLK_PSC0_MCLK          31
> > +#define MPC512x_CLK_PSC1_MCLK          32
> > +#define MPC512x_CLK_PSC2_MCLK          33
> > +#define MPC512x_CLK_PSC3_MCLK          34
> > +#define MPC512x_CLK_PSC4_MCLK          35
> > +#define MPC512x_CLK_PSC5_MCLK          36
> > +#define MPC512x_CLK_PSC6_MCLK          37
> > +#define MPC512x_CLK_PSC7_MCLK          38
> > +#define MPC512x_CLK_PSC8_MCLK          39
> > +#define MPC512x_CLK_PSC9_MCLK          40
> > +#define MPC512x_CLK_PSC10_MCLK         41
> > +#define MPC512x_CLK_PSC11_MCLK         42
> > +#define MPC512x_CLK_PSC_FIFO           43
> > +
> > +#define MPC512x_CLK_LAST_PUBLIC                43
> > +
> > +#endif
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-08-02 23:30             ` Mike Turquette
@ 2013-08-03 14:39               ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 14:39 UTC (permalink / raw)
  To: Mike Turquette; +Cc: Anatolij Gustschin, linuxppc-dev, linux-arm-kernel

[ we are strictly talking about clocks and source code again,
  I have trimmed the CC: list to not spam the device tree ML or
  subsystem maintainers ]

On Fri, Aug 02, 2013 at 16:30 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-23 06:14:06)
> > [ summary: "shared gate" support desirable? approach acceptable? ]
> > 
> > On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> > > 
> > > this change implements a clock driver for the MPC512x PowerPC platform
> > > which follows the COMMON_CLK approach and uses common clock drivers
> > > shared with other platforms
> > > 
> > > [ ... ]
> > > 
> > > some of the clock items get pre-enabled in the clock driver to not have
> > > them automatically disabled by the underlying clock subsystem because of
> > > their being unused -- this approach is desirable because
> > > [ ... ]
> > > - some help introduce support for and migrate to the common
> > >   infrastructure, while more appropriate support for specific hardware
> > >   constraints isn't available yet (remaining changes are strictly
> > >   internal to the clock driver and won't affect peripheral drivers)
> > 
> > This remark was related to the CAN clocks of the MPC512x SoC.
> 
> Gerhard,
> 
> Thanks for the patch (way far down below here). I'll check into it to
> see if that implementation looks OK. It would be helpful if another
> platform with shared gates could weigh in on whether the implementation
> works for them.
> 
> Still, a shared gate solution is not a prerequisite for this series,
> correct?

Well, the recent CAN driver related discussion suggested that I
had a mental misconception there.  The need for "shared gates"
was felt because of mixing up unrelated paths in the clock tree.
But the MCLK subtree is for bitrate generation, while the BDLC
gate is for register access into the peripheral controller.

Currently I'm investigating how I can cleanly tell those
individual aspects apart.  Telling the gate for register access
(in ARM speak often referred to as 'ipg') from the bitrate
generation (the 'per' clock, or 'mclk' here) seems so much more
appropriate.

After clean separation, and more testing to make sure nothing
gets broken throughout the series, there will be v4.


So "shared gate" support might have become obsolete for the
MPC512x platform.  But if others need it, the outlined approach
(patch below) may be viable.  The change to the common code is
minimal.  The use in the platform's clock driver was kind of
overengineered for the case of exactly one such gate, but this
immediately makes it a working approach for several gates, if
others need it.

I'll trim the motivation and just leave the suggested approach
for "shared gates" here.  Feel free to drop it or to only
resurrect it as the need may re-arise later.  So far nobody
appears to have felt the need up to now ...

> > [ ... ]
> > 
> > The question now is how to correctly support the situation where
> > a gate is shared between subtrees yet isn't really part of any
> > path within the subtrees.  I really cannot find a single spot
> > where to introduce the gate such that it's not duplicated.
> > 
> > The appropriate solution would not be to pre-enable those clocks,
> > but to either introduce another gate clock type which supports a
> > shared reference, or to add support for the shared reference to
> > the existing gate code.
> > 
> > 
> > I'd rather not duplicate most or all of the code of clk-gate.c,
> > instead I looked into how to add "shared gate" support to the
> > existing driver.
> > 
> > My question is whether the approach is acceptable.  It adds
> > minimal overhead and shall be OK for the enable/disable path from
> > a technical POV.  And it doesn't feel like too much of a stretch.
> > But there may be non-technical reasons to reject the approach.
> > I'd like to learn whether to follow that path before preparing
> > another version of the patch series.
> > 
> > The diffs were taken with the '-w -b' options to demonstrate
> > their essence and not drown it in whitespace changes.  The
> > implementation assumes that the caller which registers the gate
> > (the platform's clock driver) provides both the counter cell and
> > the lock.  And that all gates with a "shared use counter" use the
> > same lock (which is satisfied as they all get registered from the
> > same spot in the platform's clock driver).
> > 
> > The CLK_IGNORE_UNUSED flag addresses a different problem.  The
> > SoC has four MSCAN components, while two of them are enabled in
> > the device tree (the other two are present but disabled).  So
> > during probe two of the clocks get enabled.  After probe all
> > unused clocks automatically get disabled (that's another two).
> > So the "shared use counter" drops to zero although components are
> > in use, because "disable, it's unused" isn't told from "disable
> > after enable, regular use".  The flag would become obsolete if
> > the common gate logic would implement a separate disable_unused()
> > routine, but I guess this isn't necessary and the use of the flag
> > is appropriate.
> > 
> > That the example use creates a field for just one counter is to
> > better demonstrate the use and potential extension as need
> > arises.  Reducing this to a mere integer variable would be a
> > micro optimization.
> > 
> > 
> > The extension of the existing clk_gate implementation:
> > 
> > --- a/drivers/clk/clk-gate.c
> > +++ b/drivers/clk/clk-gate.c
> > @@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >         struct clk_gate *gate = to_clk_gate(hw);
> >         int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
> >         unsigned long flags = 0;
> > +       int need_reg_access;
> >         u32 reg;
> >  
> >         set ^= enable;
> > @@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >         if (gate->lock)
> >                 spin_lock_irqsave(gate->lock, flags);
> >  
> > +       /*
> > +        * if a "shared use counter" was specified, keep track of enable
> > +        * and disable calls and only access hardware registers upon the
> > +        * very first enable or very last disable call
> > +        */
> > +       if (!gate->share_count) {
> > +               need_reg_access = 1;
> > +       } else if (enable) {
> > +               need_reg_access = (*gate->share_count)++ == 0;
> > +       } else {
> > +               need_reg_access = --(*gate->share_count) == 0;
> > +       }
> > +
> > +       if (need_reg_access) {
> >                 if (gate->flags & CLK_GATE_HIWORD_MASK) {
> >                         reg = BIT(gate->bit_idx + 16);
> >                         if (set)
> > @@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >                 }
> >  
> >                 clk_writel(reg, gate->reg);
> > +       }
> >  
> >         if (gate->lock)
> >                 spin_unlock_irqrestore(gate->lock, flags);
> > @@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
> >   * @clk_gate_flags: gate-specific flags for this clock
> >   * @lock: shared register lock for this clock
> >   */
> > -struct clk *clk_register_gate(struct device *dev, const char *name,
> > +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> >                 const char *parent_name, unsigned long flags,
> >                 void __iomem *reg, u8 bit_idx,
> > -               u8 clk_gate_flags, spinlock_t *lock)
> > +               u8 clk_gate_flags, spinlock_t *lock,
> > +               int *share_count)
> >  {
> >         struct clk_gate *gate;
> >         struct clk *clk;
> > @@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> >         gate->bit_idx = bit_idx;
> >         gate->flags = clk_gate_flags;
> >         gate->lock = lock;
> > +       gate->share_count = share_count;
> >         gate->hw.init = &init;
> >  
> >         clk = clk_register(dev, &gate->hw);
> > @@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> >  
> >         return clk;
> >  }
> > +
> > +struct clk *clk_register_gate(struct device *dev, const char *name,
> > +               const char *parent_name, unsigned long flags,
> > +               void __iomem *reg, u8 bit_idx,
> > +               u8 clk_gate_flags, spinlock_t *lock)
> > +{
> > +
> > +       return clk_register_gate_shared(dev, name, parent_name, flags,
> > +                                       reg, bit_idx, clk_gate_flags,
> > +                                       lock, NULL);
> > +}
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -222,6 +222,7 @@ struct clk_gate {
> >         u8              bit_idx;
> >         u8              flags;
> >         spinlock_t      *lock;
> > +       int             *share_count;
> >  };
> >  
> >  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> > @@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> >                 const char *parent_name, unsigned long flags,
> >                 void __iomem *reg, u8 bit_idx,
> >                 u8 clk_gate_flags, spinlock_t *lock);
> > +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> > +               const char *parent_name, unsigned long flags,
> > +               void __iomem *reg, u8 bit_idx,
> > +               u8 clk_gate_flags, spinlock_t *lock,
> > +               int *share_count);
> >  
> >  struct clk_div_table {
> >         unsigned int    val;
> > 
> > 
> > How to use these shared gates:
> > 
> > --- a/arch/powerpc/platforms/512x/clock-commonclk.c
> > +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> > @@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
> >                                  reg, pos, 0, &clklock);
> >  }
> >  
> > +enum mpc512x_clk_shared_gate_id_t {
> > +       MPC512x_CLK_SHARED_GATE_MSCAN,
> > +       MPC512x_CLK_SHARED_GATE_MAX,
> > +};
> > +
> > +static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
> > +
> > +/*
> > + * implementor's note:  since clk_gate items don't implement a separate
> > + * .disable_unused() callback, their .disable() routine gets called and
> > + * "disable the clock as we can't see it's in use" cannot be told from
> > + * "regular disable, count these events please"
> > + *
> > + * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
> > + * the "disable, unused" call, so use counts won't get unbalanced, the
> > + * clock either never got enabled and thus need not get disabled, or
> > + * part of the hardware got enabled while disabling the other part isn't
> > + * wanted
> > + */
> > +static inline struct clk *mpc512x_clk_gated_shared(
> > +       const char *name, const char *parent_name,
> > +       u32 __iomem *reg, u8 pos,
> > +       enum mpc512x_clk_shared_gate_id_t share_id)
> > +{
> > +       int clkflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       clkflags |= CLK_IGNORE_UNUSED;
> > +       return clk_register_gate_shared(NULL, name, parent_name, clkflags,
> > +                                       reg, pos, 0, &clklock,
> > +                                       &mpc512x_clk_gate_counters[share_id]);
> > +}
> > +
> >  static inline struct clk *mpc512x_clk_muxed(const char *name,
> >         const char **parent_names, int parent_count,
> >         u32 __iomem *reg, u8 pos, u8 len)
> > @@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> >                                 1, 1);
> >         }
> >         if (sccr_reg) {
> > +               if (entry->type == MCLK_TYPE_MSCAN) {
> > +                       clks[clks_idx_pub] = mpc512x_clk_gated_shared(
> > +                                       entry->name_mclk,
> > +                                       entry->name_mux1, sccr_reg, sccr_bit,
> > +                                       MPC512x_CLK_SHARED_GATE_MSCAN);
> > +               } else {
> >                         clks[clks_idx_pub] = mpc512x_clk_gated(
> >                                         entry->name_mclk,
> >                                         entry->name_mux1, sccr_reg, sccr_bit);
> > +               }
> >         } else {
> >                 clks[clks_idx_pub] = mpc512x_clk_factor(
> >                                 entry->name_mclk,
> > 
> > Local tests have shown that the extension solves the problem of
> > how to satisfy the SoC's constraints on the MPC512x platform.
> > The MSCAN clocks no longer need to get pre-enabled, instead they
> > get setup and enabled only as the mscan(4) driver probes devices
> > according to how it was instructed (device tree nodes).
> > 
> > What do you think?  Is the "shared gate" support in the common
> > logic appropriate?  I'd rather not duplicate all of this code
> > just to introduce the specific gate I need, while most of the
> > logic is identical to the existing gate implementation.  The
> > desire isn't to override the gate's operations, but to wrap them
> > and to consult a counter in addition, while the register access
> > still applies.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-03 14:39               ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 14:39 UTC (permalink / raw)
  To: linux-arm-kernel

[ we are strictly talking about clocks and source code again,
  I have trimmed the CC: list to not spam the device tree ML or
  subsystem maintainers ]

On Fri, Aug 02, 2013 at 16:30 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-23 06:14:06)
> > [ summary: "shared gate" support desirable? approach acceptable? ]
> > 
> > On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> > > 
> > > this change implements a clock driver for the MPC512x PowerPC platform
> > > which follows the COMMON_CLK approach and uses common clock drivers
> > > shared with other platforms
> > > 
> > > [ ... ]
> > > 
> > > some of the clock items get pre-enabled in the clock driver to not have
> > > them automatically disabled by the underlying clock subsystem because of
> > > their being unused -- this approach is desirable because
> > > [ ... ]
> > > - some help introduce support for and migrate to the common
> > >   infrastructure, while more appropriate support for specific hardware
> > >   constraints isn't available yet (remaining changes are strictly
> > >   internal to the clock driver and won't affect peripheral drivers)
> > 
> > This remark was related to the CAN clocks of the MPC512x SoC.
> 
> Gerhard,
> 
> Thanks for the patch (way far down below here). I'll check into it to
> see if that implementation looks OK. It would be helpful if another
> platform with shared gates could weigh in on whether the implementation
> works for them.
> 
> Still, a shared gate solution is not a prerequisite for this series,
> correct?

Well, the recent CAN driver related discussion suggested that I
had a mental misconception there.  The need for "shared gates"
was felt because of mixing up unrelated paths in the clock tree.
But the MCLK subtree is for bitrate generation, while the BDLC
gate is for register access into the peripheral controller.

Currently I'm investigating how I can cleanly tell those
individual aspects apart.  Telling the gate for register access
(in ARM speak often referred to as 'ipg') from the bitrate
generation (the 'per' clock, or 'mclk' here) seems so much more
appropriate.

After clean separation, and more testing to make sure nothing
gets broken throughout the series, there will be v4.


So "shared gate" support might have become obsolete for the
MPC512x platform.  But if others need it, the outlined approach
(patch below) may be viable.  The change to the common code is
minimal.  The use in the platform's clock driver was kind of
overengineered for the case of exactly one such gate, but this
immediately makes it a working approach for several gates, if
others need it.

I'll trim the motivation and just leave the suggested approach
for "shared gates" here.  Feel free to drop it or to only
resurrect it as the need may re-arise later.  So far nobody
appears to have felt the need up to now ...

> > [ ... ]
> > 
> > The question now is how to correctly support the situation where
> > a gate is shared between subtrees yet isn't really part of any
> > path within the subtrees.  I really cannot find a single spot
> > where to introduce the gate such that it's not duplicated.
> > 
> > The appropriate solution would not be to pre-enable those clocks,
> > but to either introduce another gate clock type which supports a
> > shared reference, or to add support for the shared reference to
> > the existing gate code.
> > 
> > 
> > I'd rather not duplicate most or all of the code of clk-gate.c,
> > instead I looked into how to add "shared gate" support to the
> > existing driver.
> > 
> > My question is whether the approach is acceptable.  It adds
> > minimal overhead and shall be OK for the enable/disable path from
> > a technical POV.  And it doesn't feel like too much of a stretch.
> > But there may be non-technical reasons to reject the approach.
> > I'd like to learn whether to follow that path before preparing
> > another version of the patch series.
> > 
> > The diffs were taken with the '-w -b' options to demonstrate
> > their essence and not drown it in whitespace changes.  The
> > implementation assumes that the caller which registers the gate
> > (the platform's clock driver) provides both the counter cell and
> > the lock.  And that all gates with a "shared use counter" use the
> > same lock (which is satisfied as they all get registered from the
> > same spot in the platform's clock driver).
> > 
> > The CLK_IGNORE_UNUSED flag addresses a different problem.  The
> > SoC has four MSCAN components, while two of them are enabled in
> > the device tree (the other two are present but disabled).  So
> > during probe two of the clocks get enabled.  After probe all
> > unused clocks automatically get disabled (that's another two).
> > So the "shared use counter" drops to zero although components are
> > in use, because "disable, it's unused" isn't told from "disable
> > after enable, regular use".  The flag would become obsolete if
> > the common gate logic would implement a separate disable_unused()
> > routine, but I guess this isn't necessary and the use of the flag
> > is appropriate.
> > 
> > That the example use creates a field for just one counter is to
> > better demonstrate the use and potential extension as need
> > arises.  Reducing this to a mere integer variable would be a
> > micro optimization.
> > 
> > 
> > The extension of the existing clk_gate implementation:
> > 
> > --- a/drivers/clk/clk-gate.c
> > +++ b/drivers/clk/clk-gate.c
> > @@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >         struct clk_gate *gate = to_clk_gate(hw);
> >         int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
> >         unsigned long flags = 0;
> > +       int need_reg_access;
> >         u32 reg;
> >  
> >         set ^= enable;
> > @@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >         if (gate->lock)
> >                 spin_lock_irqsave(gate->lock, flags);
> >  
> > +       /*
> > +        * if a "shared use counter" was specified, keep track of enable
> > +        * and disable calls and only access hardware registers upon the
> > +        * very first enable or very last disable call
> > +        */
> > +       if (!gate->share_count) {
> > +               need_reg_access = 1;
> > +       } else if (enable) {
> > +               need_reg_access = (*gate->share_count)++ == 0;
> > +       } else {
> > +               need_reg_access = --(*gate->share_count) == 0;
> > +       }
> > +
> > +       if (need_reg_access) {
> >                 if (gate->flags & CLK_GATE_HIWORD_MASK) {
> >                         reg = BIT(gate->bit_idx + 16);
> >                         if (set)
> > @@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> >                 }
> >  
> >                 clk_writel(reg, gate->reg);
> > +       }
> >  
> >         if (gate->lock)
> >                 spin_unlock_irqrestore(gate->lock, flags);
> > @@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
> >   * @clk_gate_flags: gate-specific flags for this clock
> >   * @lock: shared register lock for this clock
> >   */
> > -struct clk *clk_register_gate(struct device *dev, const char *name,
> > +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> >                 const char *parent_name, unsigned long flags,
> >                 void __iomem *reg, u8 bit_idx,
> > -               u8 clk_gate_flags, spinlock_t *lock)
> > +               u8 clk_gate_flags, spinlock_t *lock,
> > +               int *share_count)
> >  {
> >         struct clk_gate *gate;
> >         struct clk *clk;
> > @@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> >         gate->bit_idx = bit_idx;
> >         gate->flags = clk_gate_flags;
> >         gate->lock = lock;
> > +       gate->share_count = share_count;
> >         gate->hw.init = &init;
> >  
> >         clk = clk_register(dev, &gate->hw);
> > @@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> >  
> >         return clk;
> >  }
> > +
> > +struct clk *clk_register_gate(struct device *dev, const char *name,
> > +               const char *parent_name, unsigned long flags,
> > +               void __iomem *reg, u8 bit_idx,
> > +               u8 clk_gate_flags, spinlock_t *lock)
> > +{
> > +
> > +       return clk_register_gate_shared(dev, name, parent_name, flags,
> > +                                       reg, bit_idx, clk_gate_flags,
> > +                                       lock, NULL);
> > +}
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -222,6 +222,7 @@ struct clk_gate {
> >         u8              bit_idx;
> >         u8              flags;
> >         spinlock_t      *lock;
> > +       int             *share_count;
> >  };
> >  
> >  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> > @@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> >                 const char *parent_name, unsigned long flags,
> >                 void __iomem *reg, u8 bit_idx,
> >                 u8 clk_gate_flags, spinlock_t *lock);
> > +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> > +               const char *parent_name, unsigned long flags,
> > +               void __iomem *reg, u8 bit_idx,
> > +               u8 clk_gate_flags, spinlock_t *lock,
> > +               int *share_count);
> >  
> >  struct clk_div_table {
> >         unsigned int    val;
> > 
> > 
> > How to use these shared gates:
> > 
> > --- a/arch/powerpc/platforms/512x/clock-commonclk.c
> > +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> > @@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
> >                                  reg, pos, 0, &clklock);
> >  }
> >  
> > +enum mpc512x_clk_shared_gate_id_t {
> > +       MPC512x_CLK_SHARED_GATE_MSCAN,
> > +       MPC512x_CLK_SHARED_GATE_MAX,
> > +};
> > +
> > +static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
> > +
> > +/*
> > + * implementor's note:  since clk_gate items don't implement a separate
> > + * .disable_unused() callback, their .disable() routine gets called and
> > + * "disable the clock as we can't see it's in use" cannot be told from
> > + * "regular disable, count these events please"
> > + *
> > + * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
> > + * the "disable, unused" call, so use counts won't get unbalanced, the
> > + * clock either never got enabled and thus need not get disabled, or
> > + * part of the hardware got enabled while disabling the other part isn't
> > + * wanted
> > + */
> > +static inline struct clk *mpc512x_clk_gated_shared(
> > +       const char *name, const char *parent_name,
> > +       u32 __iomem *reg, u8 pos,
> > +       enum mpc512x_clk_shared_gate_id_t share_id)
> > +{
> > +       int clkflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       clkflags |= CLK_IGNORE_UNUSED;
> > +       return clk_register_gate_shared(NULL, name, parent_name, clkflags,
> > +                                       reg, pos, 0, &clklock,
> > +                                       &mpc512x_clk_gate_counters[share_id]);
> > +}
> > +
> >  static inline struct clk *mpc512x_clk_muxed(const char *name,
> >         const char **parent_names, int parent_count,
> >         u32 __iomem *reg, u8 pos, u8 len)
> > @@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> >                                 1, 1);
> >         }
> >         if (sccr_reg) {
> > +               if (entry->type == MCLK_TYPE_MSCAN) {
> > +                       clks[clks_idx_pub] = mpc512x_clk_gated_shared(
> > +                                       entry->name_mclk,
> > +                                       entry->name_mux1, sccr_reg, sccr_bit,
> > +                                       MPC512x_CLK_SHARED_GATE_MSCAN);
> > +               } else {
> >                         clks[clks_idx_pub] = mpc512x_clk_gated(
> >                                         entry->name_mclk,
> >                                         entry->name_mux1, sccr_reg, sccr_bit);
> > +               }
> >         } else {
> >                 clks[clks_idx_pub] = mpc512x_clk_factor(
> >                                 entry->name_mclk,
> > 
> > Local tests have shown that the extension solves the problem of
> > how to satisfy the SoC's constraints on the MPC512x platform.
> > The MSCAN clocks no longer need to get pre-enabled, instead they
> > get setup and enabled only as the mscan(4) driver probes devices
> > according to how it was instructed (device tree nodes).
> > 
> > What do you think?  Is the "shared gate" support in the common
> > logic appropriate?  I'd rather not duplicate all of this code
> > just to introduce the specific gate I need, while most of the
> > logic is identical to the existing gate implementation.  The
> > desire isn't to override the gate's operations, but to wrap them
> > and to consult a counter in addition, while the register access
> > still applies.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-08-02 23:41           ` Mike Turquette
@ 2013-08-03 15:03             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 15:03 UTC (permalink / raw)
  To: Mike Turquette; +Cc: Anatolij Gustschin, linuxppc-dev, linux-arm-kernel

[ this is about the MPC512x platform's clock driver, the core of
  the series; trim the CC: list and only keep ARM (for clock) and
  PPC lists and people ]

On Fri, Aug 02, 2013 at 16:41 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:44)
> > this change implements a clock driver for the MPC512x PowerPC platform
> > which follows the COMMON_CLK approach and uses common clock drivers
> > shared with other platforms
> > 
> > this driver implements the publicly announced set of clocks (which can
> > get referenced by means of symbolic identifiers from the dt-bindings
> > header file), as well as generates additional 'struct clk' items where
> > the SoC hardware cannot easily get mapped to the common primitives of
> > the clock API, or requires "intermediate" clock nodes to represent
> > clocks that have both gates and dividers
> > 
> > the previous PPC_CLOCK implementation is kept in place and remains in
> > parallel to the common clock implementation for test and comparison
> > during migration, a compile time option picks one of the two
> > alternatives (Kconfig switch, common clock used by default)
> > 
> > some of the clock items get pre-enabled in the clock driver to not have
> > them automatically disabled by the underlying clock subsystem because of
> > their being unused -- this approach is desirable because
> > - some of the clocks are useful to have for diagnostics and information
> >   despite their not getting claimed by any drivers (CPU, internal and
> >   external RAM, internal busses, boot media)
> > - some of the clocks aren't claimed by their peripheral drivers yet,
> >   either because of missing driver support or because device tree specs
> >   aren't available yet (but the workarounds will get removed as the
> >   drivers get adjusted and the device tree provides the clock specs)
> > - some help introduce support for and migrate to the common
> >   infrastructure, while more appropriate support for specific hardware
> >   constraints isn't available yet (remaining changes are strictly
> >   internal to the clock driver and won't affect peripheral drivers)
> > 
> > clkdev registration provides "alias names" for few clock items
> > - to not break those peripheral drivers which encode their component
> >   index into the name that is used for clock lookup (UART, SPI, USB)
> > - to not break those drivers which use names for the clock lookup which
> >   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> > this workaround will get removed as these drivers get adjusted after
> > device tree based clock lookup has become available
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> Hi Gerhard,
> 
> This looks OK to me. Do you want me to take it or will you keep the
> series together? Note that I took "clk: wrap I/O access for improved
> portability" into the clk tree already.
> 
> Regards,
> Mike

Thank you for the feedback and for the interest!  It's nice to
hear that you like the central part of the series. :)


There will be another version of the series (v4), addressing the
remaining feedback, further reducing pre-enable workarounds,
eliminating the need for "shared gates" by adding more 'ipg'
clocks for serial communication (UART, SPI, CAN).  It's true that
the series has widened its scope after initial submission, but it
as well has much improved from the feedback.

This specific patch introduces an alternative clock driver which
is enabled by default, so it depends on the device tree data
being available before the code becomes operational.  And the
common clock platform driver might break those peripheral drivers
which haven't received their clock API use cleanup yet (earlier
parts of the series).


So I'd like to keep the series together until it has passed
review.  I will make sure that the series remains bisectable and
always keeps working when applied in sequence, and would prefer
to only start splitting it or staging parts of it later if
needed.


> > ---
> >  arch/powerpc/platforms/512x/Kconfig           |   14 +-
> >  arch/powerpc/platforms/512x/Makefile          |    4 +-
> >  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
> >  include/linux/clk-provider.h                  |   16 +
> >  4 files changed, 818 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> > 
> > diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
> > index fc9c1cb..c5fcdd0 100644
> > --- a/arch/powerpc/platforms/512x/Kconfig
> > +++ b/arch/powerpc/platforms/512x/Kconfig
> > @@ -1,9 +1,21 @@
> > +config MPC512x_COMMON_CLK
> > +       bool "MPC512x platform uses COMMON_CLK"
> > +       default y
> > +       depends on PPC_MPC512x
> > +       help
> > +         This option is only here to support tests and comparison
> > +         during development and migration.  This option will get
> > +         removed after the COMMON_CLK support for MPC512x has become
> > +         fully operational and all drivers were adjusted to explicitly
> > +         acquire their required clocks.
> > +
> >  config PPC_MPC512x
> >         bool "512x-based boards"
> >         depends on 6xx
> >         select FSL_SOC
> >         select IPIC
> > -       select PPC_CLOCK
> > +       select PPC_CLOCK if !MPC512x_COMMON_CLK
> > +       select COMMON_CLK if MPC512x_COMMON_CLK
> >         select PPC_PCI_CHOICE
> >         select FSL_PCI if PCI
> >         select ARCH_WANT_OPTIONAL_GPIOLIB
> > diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
> > index 72fb934..1e05f9d 100644
> > --- a/arch/powerpc/platforms/512x/Makefile
> > +++ b/arch/powerpc/platforms/512x/Makefile
> > @@ -1,7 +1,9 @@
> >  #
> >  # Makefile for the Freescale PowerPC 512x linux kernel.
> >  #
> > -obj-y                          += clock.o mpc512x_shared.o
> > +obj-$(CONFIG_PPC_CLOCK)                += clock.o
> > +obj-$(CONFIG_COMMON_CLK)       += clock-commonclk.o
> > +obj-y                          += mpc512x_shared.o
> >  obj-$(CONFIG_MPC5121_ADS)      += mpc5121_ads.o mpc5121_ads_cpld.o
> >  obj-$(CONFIG_MPC512x_GENERIC)  += mpc512x_generic.o
> >  obj-$(CONFIG_PDM360NG)         += pdm360ng.o
> > diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
> > new file mode 100644
> > index 0000000..762ee85
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> > @@ -0,0 +1,786 @@
> > +/*
> > + * Copyright (C) 2013 DENX Software Engineering
> > + *
> > + * Gerhard Sittig, <gsi@denx.de>
> > + *
> > + * common clock driver support for the MPC512x platform
> > + *
> > + * This 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/clkdev.h>
> > +#include <linux/device.h>
> > +#include <linux/errno.h>
> > +#include <linux/io.h>
> > +#include <linux/of.h>
> > +
> > +#include <asm/mpc5121.h>
> > +#include <dt-bindings/clock/mpc512x-clock.h>
> > +
> > +#include "mpc512x.h"           /* our public mpc5121_clk_init() API */
> > +
> > +/* helpers to keep the MCLK intermediates "somewhere" in our table */
> > +enum {
> > +       MCLK_IDX_MUX0,
> > +       MCLK_IDX_EN0,
> > +       MCLK_IDX_DIV0,
> > +       MCLK_IDX_MUX1,
> > +       MCLK_MAX_IDX,
> > +};
> > +
> > +#define NR_PSCS                        12
> > +#define NR_MSCANS              4
> > +#define NR_SPDIFS              1
> > +#define NR_MCLKS               (NR_PSCS + NR_MSCANS + NR_SPDIFS)
> > +
> > +/* extend the public set of clocks by adding internal slots for management */
> > +enum {
> > +       /* arrange for adjacent numbers after the public set */
> > +       MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
> > +       /* clocks which aren't announced to the public */
> > +       MPC512x_CLK_DDR,
> > +       MPC512x_CLK_MEM,
> > +       MPC512x_CLK_IIM,
> > +       MPC512x_CLK_SDHC_2,
> > +       /* intermediates in div+gate combos or fractional dividers */
> > +       MPC512x_CLK_DDR_UG,
> > +       MPC512x_CLK_SDHC_x4,
> > +       MPC512x_CLK_SDHC_UG,
> > +       MPC512x_CLK_DIU_x4,
> > +       MPC512x_CLK_DIU_UG,
> > +       MPC512x_CLK_MBX_BUS_UG,
> > +       MPC512x_CLK_MBX_UG,
> > +       MPC512x_CLK_MBX_3D_UG,
> > +       MPC512x_CLK_PCI_UG,
> > +       MPC512x_CLK_NFC_UG,
> > +       MPC512x_CLK_LPC_UG,
> > +       MPC512x_CLK_SPDIF_TX_IN,
> > +       /* intermediates for the mux+gate+div+mux MCLK generation */
> > +       MPC512x_CLK_MCLKS_FIRST,
> > +       MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
> > +                               + NR_MCLKS * MCLK_MAX_IDX,
> > +       /* internal, symbolic spec for the number of slots */
> > +       MPC512x_CLK_LAST_PRIVATE,
> > +};
> > +
> > +/* data required for the OF clock provider registration */
> > +static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
> > +static struct clk_onecell_data clk_data;
> > +
> > +/* CCM register access */
> > +static struct mpc512x_ccm __iomem *clkregs;
> > +static DEFINE_SPINLOCK(clklock);
> > +
> > +/* convenience wrappers around the common clk API */
> > +static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
> > +{
> > +       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_factor(
> > +       const char *name, const char *parent_name,
> > +       int mul, int div)
> > +{
> > +       int clkflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
> > +                                        mul, div);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_divider(
> > +       const char *name, const char *parent_name, u8 clkflags,
> > +       u32 __iomem *reg, u8 pos, u8 len, int divflags)
> > +{
> > +       return clk_register_divider(NULL, name, parent_name, clkflags,
> > +                                   reg, pos, len, divflags, &clklock);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_divtable(
> > +       const char *name, const char *parent_name,
> > +       u32 __iomem *reg, u8 pos, u8 len,
> > +       const struct clk_div_table *divtab)
> > +{
> > +       u8 divflags;
> > +
> > +       divflags = 0;
> > +       return clk_register_divider_table(NULL, name, parent_name, 0,
> > +                                         reg, pos, len, divflags,
> > +                                         divtab, &clklock);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_gated(
> > +       const char *name, const char *parent_name,
> > +       u32 __iomem *reg, u8 pos)
> > +{
> > +       int clkflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       return clk_register_gate(NULL, name, parent_name, clkflags,
> > +                                reg, pos, 0, &clklock);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_muxed(const char *name,
> > +       const char **parent_names, int parent_count,
> > +       u32 __iomem *reg, u8 pos, u8 len)
> > +{
> > +       int clkflags;
> > +       u8 muxflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       muxflags = 0;
> > +       return clk_register_mux(NULL, name,
> > +                               parent_names, parent_count, clkflags,
> > +                               reg, pos, len, muxflags, &clklock);
> > +}
> > +
> > +/* helper to isolate a bit field from a register */
> > +static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
> > +{
> > +       uint32_t val;
> > +
> > +       val = in_be32(reg);
> > +       val >>= pos;
> > +       val &= (1 << len) - 1;
> > +       return val;
> > +}
> > +
> > +/* get the SPMF and translate it into the "sys pll" multiplier */
> > +static int get_spmf_mult(void)
> > +{
> > +       static int spmf_to_mult[] = {
> > +               68, 1, 12, 16, 20, 24, 28, 32,
> > +               36, 40, 44, 48, 52, 56, 60, 64,
> > +       };
> > +       int spmf;
> > +
> > +       spmf = get_bit_field(&clkregs->spmr, 24, 4);
> > +       return spmf_to_mult[spmf];
> > +}
> > +
> > +/*
> > + * get the SYS_DIV value and translate it into a divide factor
> > + *
> > + * values returned from here are a multiple of the real factor since the
> > + * divide ratio is fractional
> > + */
> > +static int get_sys_div_x2(void)
> > +{
> > +       static int sysdiv_code_to_x2[] = {
> > +               4, 5, 6, 7, 8, 9, 10, 14,
> > +               12, 16, 18, 22, 20, 24, 26, 30,
> > +               28, 32, 34, 38, 36, 40, 42, 46,
> > +               44, 48, 50, 54, 52, 56, 58, 62,
> > +               60, 64, 66,
> > +       };
> > +       int divcode;
> > +
> > +       divcode = get_bit_field(&clkregs->scfr2, 26, 6);
> > +       return sysdiv_code_to_x2[divcode];
> > +}
> > +
> > +/*
> > + * get the CPMF value and translate it into a multiplier factor
> > + *
> > + * values returned from here are a multiple of the real factor since the
> > + * multiplier ratio is fractional
> > + */
> > +static int get_cpmf_mult_x2(void)
> > +{
> > +       static int cpmf_to_mult[] = {
> > +               72, 2, 2, 3, 4, 5, 6, 7,
> > +       };
> > +       int cpmf;
> > +
> > +       cpmf = get_bit_field(&clkregs->spmr, 16, 4);
> > +       return cpmf_to_mult[cpmf];
> > +}
> > +
> > +/*
> > + * some of the clock dividers do scale in a linear way, yet not all of
> > + * their bit combinations are legal; use a divider table to get a
> > + * resulting set of applicable divider values
> > + */
> > +
> > +/* applies to the IPS_DIV, and PCI_DIV values */
> > +static struct clk_div_table divtab_2346[] = {
> > +       { .val = 2, .div = 2, },
> > +       { .val = 3, .div = 3, },
> > +       { .val = 4, .div = 4, },
> > +       { .val = 6, .div = 6, },
> > +       { .div = 0, },
> > +};
> > +
> > +/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
> > +static struct clk_div_table divtab_1234[] = {
> > +       { .val = 1, .div = 1, },
> > +       { .val = 2, .div = 2, },
> > +       { .val = 3, .div = 3, },
> > +       { .val = 4, .div = 4, },
> > +       { .div = 0, },
> > +};
> > +
> > +static int get_freq_from_dt(char *propname)
> > +{
> > +       struct device_node *np;
> > +       const unsigned int *prop;
> > +       int val;
> > +
> > +       val = 0;
> > +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> > +       if (np) {
> > +               prop = of_get_property(np, propname, NULL);
> > +               if (prop)
> > +                       val = *prop;
> > +           of_node_put(np);
> > +       }
> > +       return val;
> > +}
> > +
> > +static void mpc512x_clk_preset_data(void)
> > +{
> > +       size_t i;
> > +
> > +       for (i = 0; i < ARRAY_SIZE(clks); i++)
> > +               clks[i] = ERR_PTR(-ENODEV);
> > +}
> > +
> > +/*
> > + * - receives the "bus frequency" from the caller (that's the IPS clock
> > + *   rate, the historical source of clock information)
> > + * - fetches the system PLL multiplier and divider values as well as the
> > + *   IPS divider value from hardware
> > + * - determines the REF clock rate either from the XTAL/OSC spec (if
> > + *   there is a device tree node describing the oscillator) or from the
> > + *   IPS bus clock (supported for backwards compatibility, such that
> > + *   setups without XTAL/OSC specs keep working)
> > + * - creates the "ref" clock item in the clock tree, such that
> > + *   subsequent code can create the remainder of the hierarchy (REF ->
> > + *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
> > + *   values
> > + */
> > +static void mpc512x_clk_setup_ref_clock(int bus_freq,
> > +       int *sys_mul, int *sys_div, int *ips_div)
> > +{
> > +       struct clk *osc_clk;
> > +       int calc_freq;
> > +
> > +       /* fetch mul/div factors from the hardware */
> > +       *sys_mul = get_spmf_mult();
> > +       *sys_mul *= 2;          /* compensate for the fractional divider */
> > +       *sys_div = get_sys_div_x2();
> > +       *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
> > +
> > +       /* lookup the oscillator node */
> > +       osc_clk = clk_get(NULL, "osc");
> > +       if (osc_clk) {
> > +               /* descend REF directly from OSC, verify the IPS rate */
> > +               clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
> > +               calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
> > +               calc_freq *= *sys_mul;
> > +               calc_freq /= *sys_div;
> > +               calc_freq /= 2;
> > +               calc_freq /= *ips_div;
> > +               if (bus_freq && calc_freq != bus_freq)
> > +                       pr_warn("calc rate %d != OF spec %d\n",
> > +                               calc_freq, bus_freq);
> > +       } else {
> > +               /* calculate OSC rate and create REF from the freq value */
> > +               calc_freq = bus_freq;   /* start with IPS */
> > +               calc_freq *= *ips_div;  /* IPS -> CSB */
> > +               calc_freq *= 2;         /* CSB -> SYS */
> > +               calc_freq *= *sys_div;  /* SYS -> PLL out */
> > +               calc_freq /= *sys_mul;  /* PLL out -> REF == OSC */
> > +               clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
> > +       }
> > +}
> > +
> > +/*
> > + * helper code for the MCLK subtree setup
> > + *
> > + * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
> > + * suggests that all instances of the "PSC clock generation" are equal,
> > + * and that one might re-use the PSC setup for MSCAN clock generation
> > + * (section 5.2.5) as well, at least the logic if not the data for
> > + * description
> > + *
> > + * the details (starting at page 5-20) show differences in the specific
> > + * inputs of the first mux stage ("can clk in", "spdif tx"), and the
> > + * factual non-availability of the second mux stage (it's present yet
> > + * only one input is valid)
> > + *
> > + * the MSCAN clock related registers (starting at page 5-35) all
> > + * reference "spdif clk" at the first mux stage and don't mention any
> > + * "can clk" at all, which somehow is unexpected
> > + *
> > + * TODO re-check the document, and clarify whether the RM is correct in
> > + * the overview or in the details, and whether the difference is a
> > + * clipboard induced error or results from chip revisions
> > + *
> > + * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
> > + * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
> > + * first a doc update is required which better reflects reality in the
> > + * SoC before the implementation should follow while no questions remain
> > + */
> > +
> > +/*
> > + * note that this declaration raises a checkpatch warning, but
> > + * it's the very data type which <linux/clk-provider.h> expects,
> > + * making this declaration pass checkpatch will break compilation
> > + */
> > +static const char *parent_names_mux0[] = {
> > +       "sys", "ref", "psc-mclk-in", "spdif-tx",
> > +};
> > +
> > +enum mclk_type {
> > +       MCLK_TYPE_PSC,
> > +       MCLK_TYPE_MSCAN,
> > +       MCLK_TYPE_SPDIF,
> > +};
> > +
> > +struct mclk_setup_data {
> > +       enum mclk_type type;
> > +       int comp_idx;
> > +       bool has_mclk1;
> > +       int bit_sccr1, bit_sccr2;
> > +       const char *name_mux0;
> > +       const char *name_en0;
> > +       const char *name_div0;
> > +       const char *parent_names_mux1[2];
> > +       const char *name_mux1;
> > +       const char *name_mclk;
> > +};
> > +
> > +#define MCLK_SETUP_DATA_PSC(id) { \
> > +       MCLK_TYPE_PSC, id, \
> > +       0, 27 - id, -1, \
> > +       "psc" #id "-mux0", \
> > +       "psc" #id "-en0", \
> > +       "psc" #id "_mclk_div", \
> > +       { "psc" #id "_mclk_div", "dummy", }, \
> > +       "psc" #id "_mclk_out", \
> > +       "psc" #id "_mclk", \
> > +}
> > +
> > +#define MCLK_SETUP_DATA_MSCAN(id) { \
> > +       MCLK_TYPE_MSCAN, id, \
> > +       0, -1, 25, \
> > +       "mscan" #id "-mux0", \
> > +       "mscan" #id "-en0", \
> > +       "mscan" #id "_mclk_div", \
> > +       { "mscan" #id "_mclk_div", "dummy", }, \
> > +       "mscan" #id "_mclk_out", \
> > +       "mscan" #id "_mclk", \
> > +}
> > +
> > +#define MCLK_SETUP_DATA_SPDIF { \
> > +       MCLK_TYPE_SPDIF, 0, \
> > +       1, -1, 23, \
> > +       "spdif-mux0", \
> > +       "spdif-en0", \
> > +       "spdif_mclk_div", \
> > +       { "spdif_mclk_div", "spdif-rx", }, \
> > +       "spdif_mclk_out", \
> > +       "spdif_mclk", \
> > +}
> > +
> > +static struct mclk_setup_data mclk_psc_data[] = {
> > +       MCLK_SETUP_DATA_PSC(0),
> > +       MCLK_SETUP_DATA_PSC(1),
> > +       MCLK_SETUP_DATA_PSC(2),
> > +       MCLK_SETUP_DATA_PSC(3),
> > +       MCLK_SETUP_DATA_PSC(4),
> > +       MCLK_SETUP_DATA_PSC(5),
> > +       MCLK_SETUP_DATA_PSC(6),
> > +       MCLK_SETUP_DATA_PSC(7),
> > +       MCLK_SETUP_DATA_PSC(8),
> > +       MCLK_SETUP_DATA_PSC(9),
> > +       MCLK_SETUP_DATA_PSC(10),
> > +       MCLK_SETUP_DATA_PSC(11),
> > +};
> > +
> > +static struct mclk_setup_data mclk_mscan_data[] = {
> > +       MCLK_SETUP_DATA_MSCAN(0),
> > +       MCLK_SETUP_DATA_MSCAN(1),
> > +       MCLK_SETUP_DATA_MSCAN(2),
> > +       MCLK_SETUP_DATA_MSCAN(3),
> > +};
> > +
> > +static struct mclk_setup_data mclk_spdif_data[] = {
> > +       MCLK_SETUP_DATA_SPDIF,
> > +};
> > +
> > +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> > +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> > +{
> > +       size_t clks_idx_pub, clks_idx_int;
> > +       u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> > +       u32 __iomem *sccr_reg;  /* system clock control register (enable) */
> > +       int sccr_bit;
> > +       int div;
> > +
> > +       /* derive a few parameters from the component type and index */
> > +       switch (entry->type) {
> > +       case MCLK_TYPE_PSC:
> > +               clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> > +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                            + (entry->comp_idx) * MCLK_MAX_IDX;
> > +               mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> > +               break;
> > +       case MCLK_TYPE_MSCAN:
> > +               clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> > +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                            + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> > +               mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> > +               break;
> > +       case MCLK_TYPE_SPDIF:
> > +               clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> > +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                            + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> > +               mccr_reg = &clkregs->spccr;
> > +               break;
> > +       default:
> > +               return;
> > +       }
> > +       if (entry->bit_sccr1 >= 0) {
> > +               sccr_reg = &clkregs->sccr1;
> > +               sccr_bit = entry->bit_sccr1;
> > +       } else if (entry->bit_sccr2 >= 0) {
> > +               sccr_reg = &clkregs->sccr2;
> > +               sccr_bit = entry->bit_sccr2;
> > +       } else {
> > +               sccr_reg = NULL;
> > +       }
> > +
> > +       /*
> > +        * this was grabbed from the PPC_CLOCK implementation, which
> > +        * enforced a specific MCLK divider while the clock was gated
> > +        * during setup (that's a documented hardware requirement)
> > +        *
> > +        * the PPC_CLOCK implementation might even have violated the
> > +        * "MCLK <= IPS" constraint, the fixed divider value of 1
> > +        * results in a divider of 2 and thus MCLK = SYS/2 which equals
> > +        * CSB which is greater than IPS; the serial port setup may have
> > +        * adjusted the divider which the clock setup might have left in
> > +        * an undesirable state
> > +        *
> > +        * initial setup is:
> > +        * - MCLK 0 from SYS
> > +        * - MCLK DIV such to not exceed the IPS clock
> > +        * - MCLK 0 enabled
> > +        * - MCLK 1 from MCLK DIV
> > +        */
> > +       div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> > +       div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> > +       out_be32(mccr_reg, (0 << 16));
> > +       out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> > +       out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> > +
> > +       /*
> > +        * create the 'struct clk' items of the MCLK's clock subtree
> > +        *
> > +        * note that by design we always create all nodes and won't take
> > +        * shortcuts here, because
> > +        * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> > +        *   selectable inputs to the CFM while those who "actually use"
> > +        *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> > +        *   for their bitrate
> > +        * - in the absence of "aliases" for clocks we need to create
> > +        *   individial 'struct clk' items for whatever might get
> > +        *   referenced or looked up, even if several of those items are
> > +        *   identical from the logical POV (their rate value)
> > +        * - for easier future maintenance and for better reflection of
> > +        *   the SoC's documentation, it appears appropriate to generate
> > +        *   clock items even for those muxers which actually are NOPs
> > +        *   (those with two inputs of which one is reserved)
> > +        */
> > +       clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> > +                       entry->name_mux0,
> > +                       &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> > +                       mccr_reg, 14, 2);
> > +       clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> > +                       entry->name_en0, entry->name_mux0,
> > +                       mccr_reg, 16);
> > +       clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> > +                       entry->name_div0,
> > +                       entry->name_en0, CLK_SET_RATE_GATE,
> > +                       mccr_reg, 17, 15, 0);
> > +       if (entry->has_mclk1) {
> > +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> > +                               entry->name_mux1,
> > +                               &entry->parent_names_mux1[0],
> > +                               ARRAY_SIZE(entry->parent_names_mux1),
> > +                               mccr_reg, 7, 1);
> > +       } else {
> > +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> > +                               entry->name_mux1, entry->parent_names_mux1[0],
> > +                               1, 1);
> > +       }
> > +       if (sccr_reg) {
> > +               clks[clks_idx_pub] = mpc512x_clk_gated(
> > +                               entry->name_mclk,
> > +                               entry->name_mux1, sccr_reg, sccr_bit);
> > +       } else {
> > +               clks[clks_idx_pub] = mpc512x_clk_factor(
> > +                               entry->name_mclk,
> > +                               entry->name_mux1, 1, 1);
> > +       }
> > +
> > +       /*
> > +        * without this "clock device" registration, "simple" lookups in
> > +        * the SPI master initialization and serial port setup will fail
> > +        *
> > +        * those drivers need to get adjusted to lookup their required
> > +        * clocks from device tree specs, and device tree nodes need to
> > +        * provide the clock specs, before this clkdev registration
> > +        * becomes obsolete
> > +        */
> > +       clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> > +}
> > +
> > +static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
> > +{
> > +       while (count-- > 0)
> > +               mpc512x_clk_setup_mclk(table++);
> > +}
> > +
> > +static void mpc512x_clk_setup_clock_tree(int busfreq)
> > +{
> > +       int sys_mul, sys_div, ips_div;
> > +       int mul, div;
> > +       int freq;
> > +
> > +       /*
> > +        * TODO
> > +        * - consider whether to handle clocks which have both gates and
> > +        *   dividers via intermediates or by means of composites
> > +        * - fractional dividers appear to not map well to composites
> > +        *   since they can be seen as a fixed multiplier and an
> > +        *   adjustable divider, while composites can only combine at
> > +        *   most one of a mux, div, and gate each into one 'struct clk'
> > +        *   item
> > +        * - PSC/MSCAN/SPDIF clock generation OTOH already is very
> > +        *   specific and cannot get mapped to componsites (at least not
> > +        *   a single one, maybe two of them, but see the comment about
> > +        *   "intermediates are referenced from elsewhere, too")
> > +        * - trim the list of auto-enabled clocks after drivers acquire
> > +        *   them correctly as needed
> > +        */
> > +
> > +       /* regardless of whether XTAL/OSC exists, have REF created */
> > +       mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
> > +
> > +       /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
> > +       clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
> > +                                                  sys_mul, sys_div);
> > +       clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
> > +       clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
> > +                                                    &clkregs->scfr1, 23, 3,
> > +                                                    divtab_2346);
> > +
> > +       /* now setup anything below SYS and CSB and IPS */
> > +       clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
> > +       clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
> > +       clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
> > +                                                       &clkregs->scfr2, 0, 8,
> > +                                                       CLK_DIVIDER_ONE_BASED);
> > +       clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
> > +       clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
> > +                                                      &clkregs->scfr1, 0, 8,
> > +                                                      CLK_DIVIDER_ONE_BASED);
> > +
> > +       /*
> > +        * the "power architecture PLL" was setup from data which was
> > +        * sampled from the reset config word, at this point in time the
> > +        * configuration can be considered fixed and read only (i.e. no
> > +        * longer adjustable, or no longer in need of adjustment), which
> > +        * is why we don't register a PLL here but assume fixed factors
> > +        */
> > +       mul = get_cpmf_mult_x2();
> > +       div = 2;        /* compensate for the fractional factor */
> > +       clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
> > +
> > +       clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
> > +                                                         1, 2);
> > +       clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
> > +                                                       &clkregs->scfr1, 14, 3,
> > +                                                       divtab_1234);
> > +       clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
> > +                                                        1, 1);
> > +       clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
> > +                                                       &clkregs->scfr1, 20, 3,
> > +                                                       divtab_2346);
> > +       clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
> > +                                                       &clkregs->scfr1, 8, 3,
> > +                                                       divtab_1234);
> > +       clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
> > +                                                       &clkregs->scfr1, 11, 3,
> > +                                                       divtab_1234);
> > +
> > +       clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
> > +                                                 &clkregs->sccr1, 30);
> > +       clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
> > +                                                 &clkregs->sccr1, 29);
> > +       clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
> > +                                                  &clkregs->sccr1, 28);
> > +       mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
> > +       clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
> > +                                                      &clkregs->sccr1, 15);
> > +       clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
> > +                                                  &clkregs->sccr1, 14);
> > +       clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
> > +                                                 &clkregs->sccr1, 13);
> > +       clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
> > +                                                 &clkregs->sccr1, 11);
> > +       clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
> > +                                                 &clkregs->sccr1, 10);
> > +
> > +       clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
> > +                                                 &clkregs->sccr2, 31);
> > +       clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
> > +                                                 &clkregs->sccr2, 30);
> > +       clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
> > +                                                 &clkregs->sccr2, 29);
> > +       clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
> > +                                                  &clkregs->sccr2, 28);
> > +       clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
> > +                                                  &clkregs->sccr2, 27);
> > +       clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> > +                                                 &clkregs->sccr2, 26);
> > +       mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> > +       clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> > +                                                  &clkregs->sccr2, 24);
> > +       mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> > +       clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
> > +                                                     &clkregs->sccr2, 22);
> > +       clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
> > +                                                 &clkregs->sccr2, 21);
> > +       clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
> > +                                                    &clkregs->sccr2, 20);
> > +       clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
> > +                                                 &clkregs->sccr2, 19);
> > +       clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
> > +                                                 &clkregs->sccr2, 18);
> > +       clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
> > +                                                    &clkregs->sccr2, 17);
> > +
> > +       /*
> > +        * externally provided clocks (when implemented in hardware,
> > +        * device tree may specify values which otherwise were unknown)
> > +        */
> > +       freq = get_freq_from_dt("psc_mclk_in");
> > +       if (!freq)
> > +               freq = 25000000;
> > +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> > +       freq = get_freq_from_dt("spdif_tx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> > +       freq = get_freq_from_dt("spdif_rx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
> > +
> > +       /* fixed frequency for AC97, always 24.567MHz */
> > +       clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
> > +
> > +       /* clkdev registration for compatibility reasons */
> > +       clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
> > +
> > +       pr_debug("clock tree setup complete\n");
> > +       freq = clk_get_rate(clks[MPC512x_CLK_E300]);
> > +       pr_debug("derived PPC freq [%d]\n", freq);
> > +       freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
> > +       pr_debug("derived IPS freq [%d]\n", freq);
> > +       freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
> > +       pr_debug("derived LPC freq [%d]\n", freq);
> > +
> > +       /* enable some of the clocks here unconditionally because ... */
> > +       pr_debug("automatically enabling some clocks\n");
> > +       /* some are essential yet never get claimed by any driver */
> > +       clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> > +       clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> > +       clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> > +       clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> > +       clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> > +       /* some are required yet no dependencies were declared */
> > +       clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> > +       /* some are not yet acquired by their respective drivers */
> > +       clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> > +       clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> > +       clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> > +       clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> > +       /*
> > +        * some have their individual clock subtree with separate clock
> > +        * items and their individual enable counters, yet share a
> > +        * common gate (refer to the same register location) while the
> > +        * common clock driver code is not aware of the fact and the
> > +        * platform's code doesn't provide specific support either
> > +        *
> > +        * what might happen is that e.g. enabling two MSCAN clock items
> > +        * and disabling one of them will disable the common gate and
> > +        * thus break the other MSCAN clock as well
> > +        */
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> > +}
> > +
> > +/*
> > + * registers the set of public clocks (those listed in the dt-bindings/
> > + * header file) for OF lookups, keeps the intermediates private to us
> > + */
> > +static void mpc5121_clk_register_of_provider(struct device_node *np)
> > +{
> > +       clk_data.clks = clks;
> > +       clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */
> > +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> > +}
> > +
> > +int __init mpc5121_clk_init(void)
> > +{
> > +       struct device_node *clk_np;
> > +       int busfreq;
> > +
> > +       /* map the clock control registers */
> > +       clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
> > +       if (!clk_np)
> > +               return -ENODEV;
> > +       clkregs = of_iomap(clk_np, 0);
> > +       WARN_ON(!clkregs);
> > +
> > +       /* invalidate all not yet registered clock slots */
> > +       mpc512x_clk_preset_data();
> > +
> > +       /*
> > +        * have the device tree scanned for "fixed-clock" nodes (which
> > +        * includes the oscillator node if the board's DT provides one)
> > +        */
> > +       of_clk_init(NULL);
> > +
> > +       /*
> > +        * add a dummy clock for those situations where a clock spec is
> > +        * required yet no real clock is involved
> > +        */
> > +       clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
> > +
> > +       /*
> > +        * have all the real nodes in the clock tree populated from REF
> > +        * down to all leaves, either starting from the OSC node or from
> > +        * a REF root that was created from the IPS bus clock input
> > +        */
> > +       busfreq = get_freq_from_dt("bus-frequency");
> > +       mpc512x_clk_setup_clock_tree(busfreq);
> > +
> > +       /* register as an OF clock provider */
> > +       mpc5121_clk_register_of_provider(clk_np);
> > +
> > +       return 0;
> > +}
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index c4f7799..7f8fc64 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
> >   * for improved portability across platforms
> >   */
> >  
> > +#if IS_ENABLED(CONFIG_PPC)
> > +
> > +static inline u32 clk_readl(u32 __iomem *reg)
> > +{
> > +       return ioread32be(reg);
> > +}
> > +
> > +static inline void clk_writel(u32 val, u32 __iomem *reg)
> > +{
> > +       iowrite32be(val, reg);
> > +}
> > +
> > +#else  /* platform dependent I/O accessors */
> > +
> >  static inline u32 clk_readl(u32 __iomem *reg)
> >  {
> >         return readl(reg);
> > @@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
> >         writel(val, reg);
> >  }
> >  
> > +#endif /* platform dependent I/O accessors */
> > +
> >  #endif /* CONFIG_COMMON_CLK */
> >  #endif /* CLK_PROVIDER_H */
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-03 15:03             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 15:03 UTC (permalink / raw)
  To: linux-arm-kernel

[ this is about the MPC512x platform's clock driver, the core of
  the series; trim the CC: list and only keep ARM (for clock) and
  PPC lists and people ]

On Fri, Aug 02, 2013 at 16:41 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:44)
> > this change implements a clock driver for the MPC512x PowerPC platform
> > which follows the COMMON_CLK approach and uses common clock drivers
> > shared with other platforms
> > 
> > this driver implements the publicly announced set of clocks (which can
> > get referenced by means of symbolic identifiers from the dt-bindings
> > header file), as well as generates additional 'struct clk' items where
> > the SoC hardware cannot easily get mapped to the common primitives of
> > the clock API, or requires "intermediate" clock nodes to represent
> > clocks that have both gates and dividers
> > 
> > the previous PPC_CLOCK implementation is kept in place and remains in
> > parallel to the common clock implementation for test and comparison
> > during migration, a compile time option picks one of the two
> > alternatives (Kconfig switch, common clock used by default)
> > 
> > some of the clock items get pre-enabled in the clock driver to not have
> > them automatically disabled by the underlying clock subsystem because of
> > their being unused -- this approach is desirable because
> > - some of the clocks are useful to have for diagnostics and information
> >   despite their not getting claimed by any drivers (CPU, internal and
> >   external RAM, internal busses, boot media)
> > - some of the clocks aren't claimed by their peripheral drivers yet,
> >   either because of missing driver support or because device tree specs
> >   aren't available yet (but the workarounds will get removed as the
> >   drivers get adjusted and the device tree provides the clock specs)
> > - some help introduce support for and migrate to the common
> >   infrastructure, while more appropriate support for specific hardware
> >   constraints isn't available yet (remaining changes are strictly
> >   internal to the clock driver and won't affect peripheral drivers)
> > 
> > clkdev registration provides "alias names" for few clock items
> > - to not break those peripheral drivers which encode their component
> >   index into the name that is used for clock lookup (UART, SPI, USB)
> > - to not break those drivers which use names for the clock lookup which
> >   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> > this workaround will get removed as these drivers get adjusted after
> > device tree based clock lookup has become available
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> Hi Gerhard,
> 
> This looks OK to me. Do you want me to take it or will you keep the
> series together? Note that I took "clk: wrap I/O access for improved
> portability" into the clk tree already.
> 
> Regards,
> Mike

Thank you for the feedback and for the interest!  It's nice to
hear that you like the central part of the series. :)


There will be another version of the series (v4), addressing the
remaining feedback, further reducing pre-enable workarounds,
eliminating the need for "shared gates" by adding more 'ipg'
clocks for serial communication (UART, SPI, CAN).  It's true that
the series has widened its scope after initial submission, but it
as well has much improved from the feedback.

This specific patch introduces an alternative clock driver which
is enabled by default, so it depends on the device tree data
being available before the code becomes operational.  And the
common clock platform driver might break those peripheral drivers
which haven't received their clock API use cleanup yet (earlier
parts of the series).


So I'd like to keep the series together until it has passed
review.  I will make sure that the series remains bisectable and
always keeps working when applied in sequence, and would prefer
to only start splitting it or staging parts of it later if
needed.


> > ---
> >  arch/powerpc/platforms/512x/Kconfig           |   14 +-
> >  arch/powerpc/platforms/512x/Makefile          |    4 +-
> >  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
> >  include/linux/clk-provider.h                  |   16 +
> >  4 files changed, 818 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> > 
> > diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
> > index fc9c1cb..c5fcdd0 100644
> > --- a/arch/powerpc/platforms/512x/Kconfig
> > +++ b/arch/powerpc/platforms/512x/Kconfig
> > @@ -1,9 +1,21 @@
> > +config MPC512x_COMMON_CLK
> > +       bool "MPC512x platform uses COMMON_CLK"
> > +       default y
> > +       depends on PPC_MPC512x
> > +       help
> > +         This option is only here to support tests and comparison
> > +         during development and migration.  This option will get
> > +         removed after the COMMON_CLK support for MPC512x has become
> > +         fully operational and all drivers were adjusted to explicitly
> > +         acquire their required clocks.
> > +
> >  config PPC_MPC512x
> >         bool "512x-based boards"
> >         depends on 6xx
> >         select FSL_SOC
> >         select IPIC
> > -       select PPC_CLOCK
> > +       select PPC_CLOCK if !MPC512x_COMMON_CLK
> > +       select COMMON_CLK if MPC512x_COMMON_CLK
> >         select PPC_PCI_CHOICE
> >         select FSL_PCI if PCI
> >         select ARCH_WANT_OPTIONAL_GPIOLIB
> > diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
> > index 72fb934..1e05f9d 100644
> > --- a/arch/powerpc/platforms/512x/Makefile
> > +++ b/arch/powerpc/platforms/512x/Makefile
> > @@ -1,7 +1,9 @@
> >  #
> >  # Makefile for the Freescale PowerPC 512x linux kernel.
> >  #
> > -obj-y                          += clock.o mpc512x_shared.o
> > +obj-$(CONFIG_PPC_CLOCK)                += clock.o
> > +obj-$(CONFIG_COMMON_CLK)       += clock-commonclk.o
> > +obj-y                          += mpc512x_shared.o
> >  obj-$(CONFIG_MPC5121_ADS)      += mpc5121_ads.o mpc5121_ads_cpld.o
> >  obj-$(CONFIG_MPC512x_GENERIC)  += mpc512x_generic.o
> >  obj-$(CONFIG_PDM360NG)         += pdm360ng.o
> > diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
> > new file mode 100644
> > index 0000000..762ee85
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> > @@ -0,0 +1,786 @@
> > +/*
> > + * Copyright (C) 2013 DENX Software Engineering
> > + *
> > + * Gerhard Sittig, <gsi@denx.de>
> > + *
> > + * common clock driver support for the MPC512x platform
> > + *
> > + * This 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/clkdev.h>
> > +#include <linux/device.h>
> > +#include <linux/errno.h>
> > +#include <linux/io.h>
> > +#include <linux/of.h>
> > +
> > +#include <asm/mpc5121.h>
> > +#include <dt-bindings/clock/mpc512x-clock.h>
> > +
> > +#include "mpc512x.h"           /* our public mpc5121_clk_init() API */
> > +
> > +/* helpers to keep the MCLK intermediates "somewhere" in our table */
> > +enum {
> > +       MCLK_IDX_MUX0,
> > +       MCLK_IDX_EN0,
> > +       MCLK_IDX_DIV0,
> > +       MCLK_IDX_MUX1,
> > +       MCLK_MAX_IDX,
> > +};
> > +
> > +#define NR_PSCS                        12
> > +#define NR_MSCANS              4
> > +#define NR_SPDIFS              1
> > +#define NR_MCLKS               (NR_PSCS + NR_MSCANS + NR_SPDIFS)
> > +
> > +/* extend the public set of clocks by adding internal slots for management */
> > +enum {
> > +       /* arrange for adjacent numbers after the public set */
> > +       MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
> > +       /* clocks which aren't announced to the public */
> > +       MPC512x_CLK_DDR,
> > +       MPC512x_CLK_MEM,
> > +       MPC512x_CLK_IIM,
> > +       MPC512x_CLK_SDHC_2,
> > +       /* intermediates in div+gate combos or fractional dividers */
> > +       MPC512x_CLK_DDR_UG,
> > +       MPC512x_CLK_SDHC_x4,
> > +       MPC512x_CLK_SDHC_UG,
> > +       MPC512x_CLK_DIU_x4,
> > +       MPC512x_CLK_DIU_UG,
> > +       MPC512x_CLK_MBX_BUS_UG,
> > +       MPC512x_CLK_MBX_UG,
> > +       MPC512x_CLK_MBX_3D_UG,
> > +       MPC512x_CLK_PCI_UG,
> > +       MPC512x_CLK_NFC_UG,
> > +       MPC512x_CLK_LPC_UG,
> > +       MPC512x_CLK_SPDIF_TX_IN,
> > +       /* intermediates for the mux+gate+div+mux MCLK generation */
> > +       MPC512x_CLK_MCLKS_FIRST,
> > +       MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
> > +                               + NR_MCLKS * MCLK_MAX_IDX,
> > +       /* internal, symbolic spec for the number of slots */
> > +       MPC512x_CLK_LAST_PRIVATE,
> > +};
> > +
> > +/* data required for the OF clock provider registration */
> > +static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
> > +static struct clk_onecell_data clk_data;
> > +
> > +/* CCM register access */
> > +static struct mpc512x_ccm __iomem *clkregs;
> > +static DEFINE_SPINLOCK(clklock);
> > +
> > +/* convenience wrappers around the common clk API */
> > +static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
> > +{
> > +       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_factor(
> > +       const char *name, const char *parent_name,
> > +       int mul, int div)
> > +{
> > +       int clkflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
> > +                                        mul, div);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_divider(
> > +       const char *name, const char *parent_name, u8 clkflags,
> > +       u32 __iomem *reg, u8 pos, u8 len, int divflags)
> > +{
> > +       return clk_register_divider(NULL, name, parent_name, clkflags,
> > +                                   reg, pos, len, divflags, &clklock);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_divtable(
> > +       const char *name, const char *parent_name,
> > +       u32 __iomem *reg, u8 pos, u8 len,
> > +       const struct clk_div_table *divtab)
> > +{
> > +       u8 divflags;
> > +
> > +       divflags = 0;
> > +       return clk_register_divider_table(NULL, name, parent_name, 0,
> > +                                         reg, pos, len, divflags,
> > +                                         divtab, &clklock);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_gated(
> > +       const char *name, const char *parent_name,
> > +       u32 __iomem *reg, u8 pos)
> > +{
> > +       int clkflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       return clk_register_gate(NULL, name, parent_name, clkflags,
> > +                                reg, pos, 0, &clklock);
> > +}
> > +
> > +static inline struct clk *mpc512x_clk_muxed(const char *name,
> > +       const char **parent_names, int parent_count,
> > +       u32 __iomem *reg, u8 pos, u8 len)
> > +{
> > +       int clkflags;
> > +       u8 muxflags;
> > +
> > +       clkflags = CLK_SET_RATE_PARENT;
> > +       muxflags = 0;
> > +       return clk_register_mux(NULL, name,
> > +                               parent_names, parent_count, clkflags,
> > +                               reg, pos, len, muxflags, &clklock);
> > +}
> > +
> > +/* helper to isolate a bit field from a register */
> > +static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
> > +{
> > +       uint32_t val;
> > +
> > +       val = in_be32(reg);
> > +       val >>= pos;
> > +       val &= (1 << len) - 1;
> > +       return val;
> > +}
> > +
> > +/* get the SPMF and translate it into the "sys pll" multiplier */
> > +static int get_spmf_mult(void)
> > +{
> > +       static int spmf_to_mult[] = {
> > +               68, 1, 12, 16, 20, 24, 28, 32,
> > +               36, 40, 44, 48, 52, 56, 60, 64,
> > +       };
> > +       int spmf;
> > +
> > +       spmf = get_bit_field(&clkregs->spmr, 24, 4);
> > +       return spmf_to_mult[spmf];
> > +}
> > +
> > +/*
> > + * get the SYS_DIV value and translate it into a divide factor
> > + *
> > + * values returned from here are a multiple of the real factor since the
> > + * divide ratio is fractional
> > + */
> > +static int get_sys_div_x2(void)
> > +{
> > +       static int sysdiv_code_to_x2[] = {
> > +               4, 5, 6, 7, 8, 9, 10, 14,
> > +               12, 16, 18, 22, 20, 24, 26, 30,
> > +               28, 32, 34, 38, 36, 40, 42, 46,
> > +               44, 48, 50, 54, 52, 56, 58, 62,
> > +               60, 64, 66,
> > +       };
> > +       int divcode;
> > +
> > +       divcode = get_bit_field(&clkregs->scfr2, 26, 6);
> > +       return sysdiv_code_to_x2[divcode];
> > +}
> > +
> > +/*
> > + * get the CPMF value and translate it into a multiplier factor
> > + *
> > + * values returned from here are a multiple of the real factor since the
> > + * multiplier ratio is fractional
> > + */
> > +static int get_cpmf_mult_x2(void)
> > +{
> > +       static int cpmf_to_mult[] = {
> > +               72, 2, 2, 3, 4, 5, 6, 7,
> > +       };
> > +       int cpmf;
> > +
> > +       cpmf = get_bit_field(&clkregs->spmr, 16, 4);
> > +       return cpmf_to_mult[cpmf];
> > +}
> > +
> > +/*
> > + * some of the clock dividers do scale in a linear way, yet not all of
> > + * their bit combinations are legal; use a divider table to get a
> > + * resulting set of applicable divider values
> > + */
> > +
> > +/* applies to the IPS_DIV, and PCI_DIV values */
> > +static struct clk_div_table divtab_2346[] = {
> > +       { .val = 2, .div = 2, },
> > +       { .val = 3, .div = 3, },
> > +       { .val = 4, .div = 4, },
> > +       { .val = 6, .div = 6, },
> > +       { .div = 0, },
> > +};
> > +
> > +/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
> > +static struct clk_div_table divtab_1234[] = {
> > +       { .val = 1, .div = 1, },
> > +       { .val = 2, .div = 2, },
> > +       { .val = 3, .div = 3, },
> > +       { .val = 4, .div = 4, },
> > +       { .div = 0, },
> > +};
> > +
> > +static int get_freq_from_dt(char *propname)
> > +{
> > +       struct device_node *np;
> > +       const unsigned int *prop;
> > +       int val;
> > +
> > +       val = 0;
> > +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> > +       if (np) {
> > +               prop = of_get_property(np, propname, NULL);
> > +               if (prop)
> > +                       val = *prop;
> > +           of_node_put(np);
> > +       }
> > +       return val;
> > +}
> > +
> > +static void mpc512x_clk_preset_data(void)
> > +{
> > +       size_t i;
> > +
> > +       for (i = 0; i < ARRAY_SIZE(clks); i++)
> > +               clks[i] = ERR_PTR(-ENODEV);
> > +}
> > +
> > +/*
> > + * - receives the "bus frequency" from the caller (that's the IPS clock
> > + *   rate, the historical source of clock information)
> > + * - fetches the system PLL multiplier and divider values as well as the
> > + *   IPS divider value from hardware
> > + * - determines the REF clock rate either from the XTAL/OSC spec (if
> > + *   there is a device tree node describing the oscillator) or from the
> > + *   IPS bus clock (supported for backwards compatibility, such that
> > + *   setups without XTAL/OSC specs keep working)
> > + * - creates the "ref" clock item in the clock tree, such that
> > + *   subsequent code can create the remainder of the hierarchy (REF ->
> > + *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
> > + *   values
> > + */
> > +static void mpc512x_clk_setup_ref_clock(int bus_freq,
> > +       int *sys_mul, int *sys_div, int *ips_div)
> > +{
> > +       struct clk *osc_clk;
> > +       int calc_freq;
> > +
> > +       /* fetch mul/div factors from the hardware */
> > +       *sys_mul = get_spmf_mult();
> > +       *sys_mul *= 2;          /* compensate for the fractional divider */
> > +       *sys_div = get_sys_div_x2();
> > +       *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
> > +
> > +       /* lookup the oscillator node */
> > +       osc_clk = clk_get(NULL, "osc");
> > +       if (osc_clk) {
> > +               /* descend REF directly from OSC, verify the IPS rate */
> > +               clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
> > +               calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
> > +               calc_freq *= *sys_mul;
> > +               calc_freq /= *sys_div;
> > +               calc_freq /= 2;
> > +               calc_freq /= *ips_div;
> > +               if (bus_freq && calc_freq != bus_freq)
> > +                       pr_warn("calc rate %d != OF spec %d\n",
> > +                               calc_freq, bus_freq);
> > +       } else {
> > +               /* calculate OSC rate and create REF from the freq value */
> > +               calc_freq = bus_freq;   /* start with IPS */
> > +               calc_freq *= *ips_div;  /* IPS -> CSB */
> > +               calc_freq *= 2;         /* CSB -> SYS */
> > +               calc_freq *= *sys_div;  /* SYS -> PLL out */
> > +               calc_freq /= *sys_mul;  /* PLL out -> REF == OSC */
> > +               clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
> > +       }
> > +}
> > +
> > +/*
> > + * helper code for the MCLK subtree setup
> > + *
> > + * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
> > + * suggests that all instances of the "PSC clock generation" are equal,
> > + * and that one might re-use the PSC setup for MSCAN clock generation
> > + * (section 5.2.5) as well, at least the logic if not the data for
> > + * description
> > + *
> > + * the details (starting at page 5-20) show differences in the specific
> > + * inputs of the first mux stage ("can clk in", "spdif tx"), and the
> > + * factual non-availability of the second mux stage (it's present yet
> > + * only one input is valid)
> > + *
> > + * the MSCAN clock related registers (starting at page 5-35) all
> > + * reference "spdif clk" at the first mux stage and don't mention any
> > + * "can clk" at all, which somehow is unexpected
> > + *
> > + * TODO re-check the document, and clarify whether the RM is correct in
> > + * the overview or in the details, and whether the difference is a
> > + * clipboard induced error or results from chip revisions
> > + *
> > + * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
> > + * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
> > + * first a doc update is required which better reflects reality in the
> > + * SoC before the implementation should follow while no questions remain
> > + */
> > +
> > +/*
> > + * note that this declaration raises a checkpatch warning, but
> > + * it's the very data type which <linux/clk-provider.h> expects,
> > + * making this declaration pass checkpatch will break compilation
> > + */
> > +static const char *parent_names_mux0[] = {
> > +       "sys", "ref", "psc-mclk-in", "spdif-tx",
> > +};
> > +
> > +enum mclk_type {
> > +       MCLK_TYPE_PSC,
> > +       MCLK_TYPE_MSCAN,
> > +       MCLK_TYPE_SPDIF,
> > +};
> > +
> > +struct mclk_setup_data {
> > +       enum mclk_type type;
> > +       int comp_idx;
> > +       bool has_mclk1;
> > +       int bit_sccr1, bit_sccr2;
> > +       const char *name_mux0;
> > +       const char *name_en0;
> > +       const char *name_div0;
> > +       const char *parent_names_mux1[2];
> > +       const char *name_mux1;
> > +       const char *name_mclk;
> > +};
> > +
> > +#define MCLK_SETUP_DATA_PSC(id) { \
> > +       MCLK_TYPE_PSC, id, \
> > +       0, 27 - id, -1, \
> > +       "psc" #id "-mux0", \
> > +       "psc" #id "-en0", \
> > +       "psc" #id "_mclk_div", \
> > +       { "psc" #id "_mclk_div", "dummy", }, \
> > +       "psc" #id "_mclk_out", \
> > +       "psc" #id "_mclk", \
> > +}
> > +
> > +#define MCLK_SETUP_DATA_MSCAN(id) { \
> > +       MCLK_TYPE_MSCAN, id, \
> > +       0, -1, 25, \
> > +       "mscan" #id "-mux0", \
> > +       "mscan" #id "-en0", \
> > +       "mscan" #id "_mclk_div", \
> > +       { "mscan" #id "_mclk_div", "dummy", }, \
> > +       "mscan" #id "_mclk_out", \
> > +       "mscan" #id "_mclk", \
> > +}
> > +
> > +#define MCLK_SETUP_DATA_SPDIF { \
> > +       MCLK_TYPE_SPDIF, 0, \
> > +       1, -1, 23, \
> > +       "spdif-mux0", \
> > +       "spdif-en0", \
> > +       "spdif_mclk_div", \
> > +       { "spdif_mclk_div", "spdif-rx", }, \
> > +       "spdif_mclk_out", \
> > +       "spdif_mclk", \
> > +}
> > +
> > +static struct mclk_setup_data mclk_psc_data[] = {
> > +       MCLK_SETUP_DATA_PSC(0),
> > +       MCLK_SETUP_DATA_PSC(1),
> > +       MCLK_SETUP_DATA_PSC(2),
> > +       MCLK_SETUP_DATA_PSC(3),
> > +       MCLK_SETUP_DATA_PSC(4),
> > +       MCLK_SETUP_DATA_PSC(5),
> > +       MCLK_SETUP_DATA_PSC(6),
> > +       MCLK_SETUP_DATA_PSC(7),
> > +       MCLK_SETUP_DATA_PSC(8),
> > +       MCLK_SETUP_DATA_PSC(9),
> > +       MCLK_SETUP_DATA_PSC(10),
> > +       MCLK_SETUP_DATA_PSC(11),
> > +};
> > +
> > +static struct mclk_setup_data mclk_mscan_data[] = {
> > +       MCLK_SETUP_DATA_MSCAN(0),
> > +       MCLK_SETUP_DATA_MSCAN(1),
> > +       MCLK_SETUP_DATA_MSCAN(2),
> > +       MCLK_SETUP_DATA_MSCAN(3),
> > +};
> > +
> > +static struct mclk_setup_data mclk_spdif_data[] = {
> > +       MCLK_SETUP_DATA_SPDIF,
> > +};
> > +
> > +/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
> > +static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> > +{
> > +       size_t clks_idx_pub, clks_idx_int;
> > +       u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
> > +       u32 __iomem *sccr_reg;  /* system clock control register (enable) */
> > +       int sccr_bit;
> > +       int div;
> > +
> > +       /* derive a few parameters from the component type and index */
> > +       switch (entry->type) {
> > +       case MCLK_TYPE_PSC:
> > +               clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
> > +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                            + (entry->comp_idx) * MCLK_MAX_IDX;
> > +               mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
> > +               break;
> > +       case MCLK_TYPE_MSCAN:
> > +               clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
> > +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                            + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
> > +               mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
> > +               break;
> > +       case MCLK_TYPE_SPDIF:
> > +               clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
> > +               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
> > +                            + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
> > +               mccr_reg = &clkregs->spccr;
> > +               break;
> > +       default:
> > +               return;
> > +       }
> > +       if (entry->bit_sccr1 >= 0) {
> > +               sccr_reg = &clkregs->sccr1;
> > +               sccr_bit = entry->bit_sccr1;
> > +       } else if (entry->bit_sccr2 >= 0) {
> > +               sccr_reg = &clkregs->sccr2;
> > +               sccr_bit = entry->bit_sccr2;
> > +       } else {
> > +               sccr_reg = NULL;
> > +       }
> > +
> > +       /*
> > +        * this was grabbed from the PPC_CLOCK implementation, which
> > +        * enforced a specific MCLK divider while the clock was gated
> > +        * during setup (that's a documented hardware requirement)
> > +        *
> > +        * the PPC_CLOCK implementation might even have violated the
> > +        * "MCLK <= IPS" constraint, the fixed divider value of 1
> > +        * results in a divider of 2 and thus MCLK = SYS/2 which equals
> > +        * CSB which is greater than IPS; the serial port setup may have
> > +        * adjusted the divider which the clock setup might have left in
> > +        * an undesirable state
> > +        *
> > +        * initial setup is:
> > +        * - MCLK 0 from SYS
> > +        * - MCLK DIV such to not exceed the IPS clock
> > +        * - MCLK 0 enabled
> > +        * - MCLK 1 from MCLK DIV
> > +        */
> > +       div = clk_get_rate(clks[MPC512x_CLK_SYS]);
> > +       div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
> > +       out_be32(mccr_reg, (0 << 16));
> > +       out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
> > +       out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
> > +
> > +       /*
> > +        * create the 'struct clk' items of the MCLK's clock subtree
> > +        *
> > +        * note that by design we always create all nodes and won't take
> > +        * shortcuts here, because
> > +        * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
> > +        *   selectable inputs to the CFM while those who "actually use"
> > +        *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
> > +        *   for their bitrate
> > +        * - in the absence of "aliases" for clocks we need to create
> > +        *   individial 'struct clk' items for whatever might get
> > +        *   referenced or looked up, even if several of those items are
> > +        *   identical from the logical POV (their rate value)
> > +        * - for easier future maintenance and for better reflection of
> > +        *   the SoC's documentation, it appears appropriate to generate
> > +        *   clock items even for those muxers which actually are NOPs
> > +        *   (those with two inputs of which one is reserved)
> > +        */
> > +       clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
> > +                       entry->name_mux0,
> > +                       &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
> > +                       mccr_reg, 14, 2);
> > +       clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
> > +                       entry->name_en0, entry->name_mux0,
> > +                       mccr_reg, 16);
> > +       clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
> > +                       entry->name_div0,
> > +                       entry->name_en0, CLK_SET_RATE_GATE,
> > +                       mccr_reg, 17, 15, 0);
> > +       if (entry->has_mclk1) {
> > +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
> > +                               entry->name_mux1,
> > +                               &entry->parent_names_mux1[0],
> > +                               ARRAY_SIZE(entry->parent_names_mux1),
> > +                               mccr_reg, 7, 1);
> > +       } else {
> > +               clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
> > +                               entry->name_mux1, entry->parent_names_mux1[0],
> > +                               1, 1);
> > +       }
> > +       if (sccr_reg) {
> > +               clks[clks_idx_pub] = mpc512x_clk_gated(
> > +                               entry->name_mclk,
> > +                               entry->name_mux1, sccr_reg, sccr_bit);
> > +       } else {
> > +               clks[clks_idx_pub] = mpc512x_clk_factor(
> > +                               entry->name_mclk,
> > +                               entry->name_mux1, 1, 1);
> > +       }
> > +
> > +       /*
> > +        * without this "clock device" registration, "simple" lookups in
> > +        * the SPI master initialization and serial port setup will fail
> > +        *
> > +        * those drivers need to get adjusted to lookup their required
> > +        * clocks from device tree specs, and device tree nodes need to
> > +        * provide the clock specs, before this clkdev registration
> > +        * becomes obsolete
> > +        */
> > +       clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
> > +}
> > +
> > +static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
> > +{
> > +       while (count-- > 0)
> > +               mpc512x_clk_setup_mclk(table++);
> > +}
> > +
> > +static void mpc512x_clk_setup_clock_tree(int busfreq)
> > +{
> > +       int sys_mul, sys_div, ips_div;
> > +       int mul, div;
> > +       int freq;
> > +
> > +       /*
> > +        * TODO
> > +        * - consider whether to handle clocks which have both gates and
> > +        *   dividers via intermediates or by means of composites
> > +        * - fractional dividers appear to not map well to composites
> > +        *   since they can be seen as a fixed multiplier and an
> > +        *   adjustable divider, while composites can only combine at
> > +        *   most one of a mux, div, and gate each into one 'struct clk'
> > +        *   item
> > +        * - PSC/MSCAN/SPDIF clock generation OTOH already is very
> > +        *   specific and cannot get mapped to componsites (at least not
> > +        *   a single one, maybe two of them, but see the comment about
> > +        *   "intermediates are referenced from elsewhere, too")
> > +        * - trim the list of auto-enabled clocks after drivers acquire
> > +        *   them correctly as needed
> > +        */
> > +
> > +       /* regardless of whether XTAL/OSC exists, have REF created */
> > +       mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
> > +
> > +       /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
> > +       clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
> > +                                                  sys_mul, sys_div);
> > +       clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
> > +       clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
> > +                                                    &clkregs->scfr1, 23, 3,
> > +                                                    divtab_2346);
> > +
> > +       /* now setup anything below SYS and CSB and IPS */
> > +       clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
> > +       clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
> > +       clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
> > +                                                       &clkregs->scfr2, 0, 8,
> > +                                                       CLK_DIVIDER_ONE_BASED);
> > +       clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
> > +       clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
> > +                                                      &clkregs->scfr1, 0, 8,
> > +                                                      CLK_DIVIDER_ONE_BASED);
> > +
> > +       /*
> > +        * the "power architecture PLL" was setup from data which was
> > +        * sampled from the reset config word, at this point in time the
> > +        * configuration can be considered fixed and read only (i.e. no
> > +        * longer adjustable, or no longer in need of adjustment), which
> > +        * is why we don't register a PLL here but assume fixed factors
> > +        */
> > +       mul = get_cpmf_mult_x2();
> > +       div = 2;        /* compensate for the fractional factor */
> > +       clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
> > +
> > +       clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
> > +                                                         1, 2);
> > +       clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
> > +                                                       &clkregs->scfr1, 14, 3,
> > +                                                       divtab_1234);
> > +       clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
> > +                                                        1, 1);
> > +       clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
> > +                                                       &clkregs->scfr1, 20, 3,
> > +                                                       divtab_2346);
> > +       clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
> > +                                                       &clkregs->scfr1, 8, 3,
> > +                                                       divtab_1234);
> > +       clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
> > +                                                       &clkregs->scfr1, 11, 3,
> > +                                                       divtab_1234);
> > +
> > +       clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
> > +                                                 &clkregs->sccr1, 30);
> > +       clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
> > +                                                 &clkregs->sccr1, 29);
> > +       clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
> > +                                                  &clkregs->sccr1, 28);
> > +       mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
> > +       clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
> > +                                                      &clkregs->sccr1, 15);
> > +       clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
> > +                                                  &clkregs->sccr1, 14);
> > +       clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
> > +                                                 &clkregs->sccr1, 13);
> > +       clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
> > +                                                 &clkregs->sccr1, 11);
> > +       clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
> > +                                                 &clkregs->sccr1, 10);
> > +
> > +       clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
> > +                                                 &clkregs->sccr2, 31);
> > +       clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
> > +                                                 &clkregs->sccr2, 30);
> > +       clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
> > +                                                 &clkregs->sccr2, 29);
> > +       clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
> > +                                                  &clkregs->sccr2, 28);
> > +       clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
> > +                                                  &clkregs->sccr2, 27);
> > +       clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
> > +                                                 &clkregs->sccr2, 26);
> > +       mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
> > +       clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
> > +                                                  &clkregs->sccr2, 24);
> > +       mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
> > +       clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
> > +                                                     &clkregs->sccr2, 22);
> > +       clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
> > +                                                 &clkregs->sccr2, 21);
> > +       clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
> > +                                                    &clkregs->sccr2, 20);
> > +       clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
> > +                                                 &clkregs->sccr2, 19);
> > +       clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
> > +                                                 &clkregs->sccr2, 18);
> > +       clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
> > +                                                    &clkregs->sccr2, 17);
> > +
> > +       /*
> > +        * externally provided clocks (when implemented in hardware,
> > +        * device tree may specify values which otherwise were unknown)
> > +        */
> > +       freq = get_freq_from_dt("psc_mclk_in");
> > +       if (!freq)
> > +               freq = 25000000;
> > +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> > +       freq = get_freq_from_dt("spdif_tx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> > +       freq = get_freq_from_dt("spdif_rx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
> > +
> > +       /* fixed frequency for AC97, always 24.567MHz */
> > +       clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
> > +
> > +       /* clkdev registration for compatibility reasons */
> > +       clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
> > +       clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
> > +
> > +       pr_debug("clock tree setup complete\n");
> > +       freq = clk_get_rate(clks[MPC512x_CLK_E300]);
> > +       pr_debug("derived PPC freq [%d]\n", freq);
> > +       freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
> > +       pr_debug("derived IPS freq [%d]\n", freq);
> > +       freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
> > +       pr_debug("derived LPC freq [%d]\n", freq);
> > +
> > +       /* enable some of the clocks here unconditionally because ... */
> > +       pr_debug("automatically enabling some clocks\n");
> > +       /* some are essential yet never get claimed by any driver */
> > +       clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
> > +       clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
> > +       clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
> > +       clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
> > +       clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
> > +       /* some are required yet no dependencies were declared */
> > +       clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
> > +       /* some are not yet acquired by their respective drivers */
> > +       clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
> > +       clk_prepare_enable(clks[MPC512x_CLK_FEC]);      /* network, NFS */
> > +       clk_prepare_enable(clks[MPC512x_CLK_DIU]);      /* display */
> > +       clk_prepare_enable(clks[MPC512x_CLK_I2C]);
> > +       /*
> > +        * some have their individual clock subtree with separate clock
> > +        * items and their individual enable counters, yet share a
> > +        * common gate (refer to the same register location) while the
> > +        * common clock driver code is not aware of the fact and the
> > +        * platform's code doesn't provide specific support either
> > +        *
> > +        * what might happen is that e.g. enabling two MSCAN clock items
> > +        * and disabling one of them will disable the common gate and
> > +        * thus break the other MSCAN clock as well
> > +        */
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
> > +       clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
> > +}
> > +
> > +/*
> > + * registers the set of public clocks (those listed in the dt-bindings/
> > + * header file) for OF lookups, keeps the intermediates private to us
> > + */
> > +static void mpc5121_clk_register_of_provider(struct device_node *np)
> > +{
> > +       clk_data.clks = clks;
> > +       clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */
> > +       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> > +}
> > +
> > +int __init mpc5121_clk_init(void)
> > +{
> > +       struct device_node *clk_np;
> > +       int busfreq;
> > +
> > +       /* map the clock control registers */
> > +       clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
> > +       if (!clk_np)
> > +               return -ENODEV;
> > +       clkregs = of_iomap(clk_np, 0);
> > +       WARN_ON(!clkregs);
> > +
> > +       /* invalidate all not yet registered clock slots */
> > +       mpc512x_clk_preset_data();
> > +
> > +       /*
> > +        * have the device tree scanned for "fixed-clock" nodes (which
> > +        * includes the oscillator node if the board's DT provides one)
> > +        */
> > +       of_clk_init(NULL);
> > +
> > +       /*
> > +        * add a dummy clock for those situations where a clock spec is
> > +        * required yet no real clock is involved
> > +        */
> > +       clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
> > +
> > +       /*
> > +        * have all the real nodes in the clock tree populated from REF
> > +        * down to all leaves, either starting from the OSC node or from
> > +        * a REF root that was created from the IPS bus clock input
> > +        */
> > +       busfreq = get_freq_from_dt("bus-frequency");
> > +       mpc512x_clk_setup_clock_tree(busfreq);
> > +
> > +       /* register as an OF clock provider */
> > +       mpc5121_clk_register_of_provider(clk_np);
> > +
> > +       return 0;
> > +}
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index c4f7799..7f8fc64 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
> >   * for improved portability across platforms
> >   */
> >  
> > +#if IS_ENABLED(CONFIG_PPC)
> > +
> > +static inline u32 clk_readl(u32 __iomem *reg)
> > +{
> > +       return ioread32be(reg);
> > +}
> > +
> > +static inline void clk_writel(u32 val, u32 __iomem *reg)
> > +{
> > +       iowrite32be(val, reg);
> > +}
> > +
> > +#else  /* platform dependent I/O accessors */
> > +
> >  static inline u32 clk_readl(u32 __iomem *reg)
> >  {
> >         return readl(reg);
> > @@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
> >         writel(val, reg);
> >  }
> >  
> > +#endif /* platform dependent I/O accessors */
> > +
> >  #endif /* CONFIG_COMMON_CLK */
> >  #endif /* CLK_PROVIDER_H */
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
  2013-08-02 23:41           ` Mike Turquette
@ 2013-08-03 15:36             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 15:36 UTC (permalink / raw)
  To: Mike Turquette
  Cc: devicetree, Anatolij Gustschin, linuxppc-dev, Rob Herring,
	linux-arm-kernel

[ trimming the CC: list to device tree and ARM(clock) and PPC ]

On Fri, Aug 02, 2013 at 16:41 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:45)
> > this addresses the client side of device tree based clock lookups
> > 
> > add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
> > mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
> > mpc5121.dtsi include
> > 
> > these specs map 'clock-names' encoded in drivers to their respective
> > 'struct clk' items in the platform's clock driver
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> Reviewed-by: Mike Turquette <mturquette@linaro.org>

Thank you for the review, Mike!

Please note that there will be another update for the series.
These clock specs for client side lookups will have additional
'ipg' clock items next to 'mclk' for the PSC (UART, SPI) and
MSCAN (CAN) nodes.  But this change is straight forward.


> > ---
> >  arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 79 insertions(+)
> > 
> > diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
> > index 8f4cba0..3657ae6 100644
> > --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> > +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> > @@ -51,6 +51,10 @@
> >                 compatible = "fsl,mpc5121-mbx";
> >                 reg = <0x20000000 0x4000>;
> >                 interrupts = <66 0x8>;
> > +               clocks = <&clks MPC512x_CLK_MBX_BUS>,
> > +                        <&clks MPC512x_CLK_MBX_3D>,
> > +                        <&clks MPC512x_CLK_MBX>;
> > +               clock-names = "mbx-bus", "mbx-3d", "mbx";
> >         };
> >  
> >         sram@30000000 {
> > @@ -64,6 +68,8 @@
> >                 interrupts = <6 8>;
> >                 #address-cells = <1>;
> >                 #size-cells = <1>;
> > +               clocks = <&clks MPC512x_CLK_NFC>;
> > +               clock-names = "per";
> >         };
> >  
> >         localbus@80000020 {
> > @@ -153,12 +159,22 @@
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x1300 0x80>;
> >                         interrupts = <12 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN0_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 can@1380 {
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x1380 0x80>;
> >                         interrupts = <13 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN1_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 sdhc@1500 {
> > @@ -167,6 +183,9 @@
> >                         interrupts = <8 0x8>;
> >                         dmas = <&dma0 30>;
> >                         dma-names = "rx-tx";
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SDHC>;
> > +                       clock-names = "ipg", "per";
> >                 };
> >  
> >                 i2c@1700 {
> > @@ -175,6 +194,8 @@
> >                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
> >                         reg = <0x1700 0x20>;
> >                         interrupts = <9 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_I2C>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 i2c@1720 {
> > @@ -183,6 +204,8 @@
> >                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
> >                         reg = <0x1720 0x20>;
> >                         interrupts = <10 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_I2C>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 i2c@1740 {
> > @@ -191,6 +214,8 @@
> >                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
> >                         reg = <0x1740 0x20>;
> >                         interrupts = <11 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_I2C>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 i2ccontrol@1760 {
> > @@ -202,30 +227,46 @@
> >                         compatible = "fsl,mpc5121-axe";
> >                         reg = <0x2000 0x100>;
> >                         interrupts = <42 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_AXE>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 display@2100 {
> >                         compatible = "fsl,mpc5121-diu";
> >                         reg = <0x2100 0x100>;
> >                         interrupts = <64 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_DIU>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 can@2300 {
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x2300 0x80>;
> >                         interrupts = <90 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN2_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 can@2380 {
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x2380 0x80>;
> >                         interrupts = <91 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN3_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 viu@2400 {
> >                         compatible = "fsl,mpc5121-viu";
> >                         reg = <0x2400 0x400>;
> >                         interrupts = <67 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_VIU>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 mdio@2800 {
> > @@ -233,6 +274,8 @@
> >                         reg = <0x2800 0x800>;
> >                         #address-cells = <1>;
> >                         #size-cells = <0>;
> > +                       clocks = <&clks MPC512x_CLK_FEC>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 eth0: ethernet@2800 {
> > @@ -241,6 +284,8 @@
> >                         reg = <0x2800 0x800>;
> >                         local-mac-address = [ 00 00 00 00 00 00 ];
> >                         interrupts = <4 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_FEC>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* USB1 using external ULPI PHY */
> > @@ -252,6 +297,8 @@
> >                         interrupts = <43 0x8>;
> >                         dr_mode = "otg";
> >                         phy_type = "ulpi";
> > +                       clocks = <&clks MPC512x_CLK_USB1>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* USB0 using internal UTMI PHY */
> > @@ -263,6 +310,8 @@
> >                         interrupts = <44 0x8>;
> >                         dr_mode = "otg";
> >                         phy_type = "utmi_wide";
> > +                       clocks = <&clks MPC512x_CLK_USB2>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* IO control */
> > @@ -281,6 +330,8 @@
> >                         compatible = "fsl,mpc5121-pata";
> >                         reg = <0x10200 0x100>;
> >                         interrupts = <5 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_PATA>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* 512x PSCs are not 52xx PSC compatible */
> > @@ -292,6 +343,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC1 */
> > @@ -301,6 +354,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC2 */
> > @@ -310,6 +365,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC3 */
> > @@ -319,6 +376,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC4 */
> > @@ -328,6 +387,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC5 */
> > @@ -337,6 +398,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC6 */
> > @@ -346,6 +409,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC7 */
> > @@ -355,6 +420,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC8 */
> > @@ -364,6 +431,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC9 */
> > @@ -373,6 +442,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC10 */
> > @@ -382,6 +453,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC11 */
> > @@ -391,12 +464,16 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 pscfifo@11f00 {
> >                         compatible = "fsl,mpc5121-psc-fifo";
> >                         reg = <0x11f00 0x100>;
> >                         interrupts = <40 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_PSC_FIFO>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 dma0: dma@14000 {
> > @@ -414,6 +491,8 @@
> >                 #address-cells = <3>;
> >                 #size-cells = <2>;
> >                 #interrupt-cells = <1>;
> > +               clocks = <&clks MPC512x_CLK_PCI>;
> > +               clock-names = "per";
> >  
> >                 reg = <0x80008500 0x100 /* internal registers */
> >                        0x80008300 0x8>; /* config space access registers */
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups
@ 2013-08-03 15:36             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 15:36 UTC (permalink / raw)
  To: linux-arm-kernel

[ trimming the CC: list to device tree and ARM(clock) and PPC ]

On Fri, Aug 02, 2013 at 16:41 -0700, Mike Turquette wrote:
> 
> Quoting Gerhard Sittig (2013-07-22 05:14:45)
> > this addresses the client side of device tree based clock lookups
> > 
> > add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
> > mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
> > mpc5121.dtsi include
> > 
> > these specs map 'clock-names' encoded in drivers to their respective
> > 'struct clk' items in the platform's clock driver
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> Reviewed-by: Mike Turquette <mturquette@linaro.org>

Thank you for the review, Mike!

Please note that there will be another update for the series.
These clock specs for client side lookups will have additional
'ipg' clock items next to 'mclk' for the PSC (UART, SPI) and
MSCAN (CAN) nodes.  But this change is straight forward.


> > ---
> >  arch/powerpc/boot/dts/mpc5121.dtsi |   79 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 79 insertions(+)
> > 
> > diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
> > index 8f4cba0..3657ae6 100644
> > --- a/arch/powerpc/boot/dts/mpc5121.dtsi
> > +++ b/arch/powerpc/boot/dts/mpc5121.dtsi
> > @@ -51,6 +51,10 @@
> >                 compatible = "fsl,mpc5121-mbx";
> >                 reg = <0x20000000 0x4000>;
> >                 interrupts = <66 0x8>;
> > +               clocks = <&clks MPC512x_CLK_MBX_BUS>,
> > +                        <&clks MPC512x_CLK_MBX_3D>,
> > +                        <&clks MPC512x_CLK_MBX>;
> > +               clock-names = "mbx-bus", "mbx-3d", "mbx";
> >         };
> >  
> >         sram at 30000000 {
> > @@ -64,6 +68,8 @@
> >                 interrupts = <6 8>;
> >                 #address-cells = <1>;
> >                 #size-cells = <1>;
> > +               clocks = <&clks MPC512x_CLK_NFC>;
> > +               clock-names = "per";
> >         };
> >  
> >         localbus at 80000020 {
> > @@ -153,12 +159,22 @@
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x1300 0x80>;
> >                         interrupts = <12 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN0_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 can at 1380 {
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x1380 0x80>;
> >                         interrupts = <13 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN1_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 sdhc at 1500 {
> > @@ -167,6 +183,9 @@
> >                         interrupts = <8 0x8>;
> >                         dmas = <&dma0 30>;
> >                         dma-names = "rx-tx";
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SDHC>;
> > +                       clock-names = "ipg", "per";
> >                 };
> >  
> >                 i2c at 1700 {
> > @@ -175,6 +194,8 @@
> >                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
> >                         reg = <0x1700 0x20>;
> >                         interrupts = <9 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_I2C>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 i2c at 1720 {
> > @@ -183,6 +204,8 @@
> >                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
> >                         reg = <0x1720 0x20>;
> >                         interrupts = <10 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_I2C>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 i2c at 1740 {
> > @@ -191,6 +214,8 @@
> >                         compatible = "fsl,mpc5121-i2c", "fsl-i2c";
> >                         reg = <0x1740 0x20>;
> >                         interrupts = <11 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_I2C>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 i2ccontrol at 1760 {
> > @@ -202,30 +227,46 @@
> >                         compatible = "fsl,mpc5121-axe";
> >                         reg = <0x2000 0x100>;
> >                         interrupts = <42 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_AXE>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 display at 2100 {
> >                         compatible = "fsl,mpc5121-diu";
> >                         reg = <0x2100 0x100>;
> >                         interrupts = <64 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_DIU>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 can at 2300 {
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x2300 0x80>;
> >                         interrupts = <90 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN2_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 can at 2380 {
> >                         compatible = "fsl,mpc5121-mscan";
> >                         reg = <0x2380 0x80>;
> >                         interrupts = <91 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_IPS>,
> > +                                <&clks MPC512x_CLK_SYS>,
> > +                                <&clks MPC512x_CLK_REF>,
> > +                                <&clks MPC512x_CLK_MSCAN3_MCLK>;
> > +                       clock-names = "ips", "sys", "ref", "mclk";
> >                 };
> >  
> >                 viu at 2400 {
> >                         compatible = "fsl,mpc5121-viu";
> >                         reg = <0x2400 0x400>;
> >                         interrupts = <67 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_VIU>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 mdio at 2800 {
> > @@ -233,6 +274,8 @@
> >                         reg = <0x2800 0x800>;
> >                         #address-cells = <1>;
> >                         #size-cells = <0>;
> > +                       clocks = <&clks MPC512x_CLK_FEC>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 eth0: ethernet at 2800 {
> > @@ -241,6 +284,8 @@
> >                         reg = <0x2800 0x800>;
> >                         local-mac-address = [ 00 00 00 00 00 00 ];
> >                         interrupts = <4 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_FEC>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* USB1 using external ULPI PHY */
> > @@ -252,6 +297,8 @@
> >                         interrupts = <43 0x8>;
> >                         dr_mode = "otg";
> >                         phy_type = "ulpi";
> > +                       clocks = <&clks MPC512x_CLK_USB1>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* USB0 using internal UTMI PHY */
> > @@ -263,6 +310,8 @@
> >                         interrupts = <44 0x8>;
> >                         dr_mode = "otg";
> >                         phy_type = "utmi_wide";
> > +                       clocks = <&clks MPC512x_CLK_USB2>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* IO control */
> > @@ -281,6 +330,8 @@
> >                         compatible = "fsl,mpc5121-pata";
> >                         reg = <0x10200 0x100>;
> >                         interrupts = <5 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_PATA>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 /* 512x PSCs are not 52xx PSC compatible */
> > @@ -292,6 +343,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC0_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC1 */
> > @@ -301,6 +354,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC1_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC2 */
> > @@ -310,6 +365,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC2_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC3 */
> > @@ -319,6 +376,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC3_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC4 */
> > @@ -328,6 +387,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC4_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC5 */
> > @@ -337,6 +398,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC5_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC6 */
> > @@ -346,6 +409,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC6_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC7 */
> > @@ -355,6 +420,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC7_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC8 */
> > @@ -364,6 +431,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC8_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC9 */
> > @@ -373,6 +442,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC9_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC10 */
> > @@ -382,6 +453,8 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC10_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 /* PSC11 */
> > @@ -391,12 +464,16 @@
> >                         interrupts = <40 0x8>;
> >                         fsl,rx-fifo-size = <16>;
> >                         fsl,tx-fifo-size = <16>;
> > +                       clocks = <&clks MPC512x_CLK_PSC11_MCLK>;
> > +                       clock-names = "mclk";
> >                 };
> >  
> >                 pscfifo at 11f00 {
> >                         compatible = "fsl,mpc5121-psc-fifo";
> >                         reg = <0x11f00 0x100>;
> >                         interrupts = <40 0x8>;
> > +                       clocks = <&clks MPC512x_CLK_PSC_FIFO>;
> > +                       clock-names = "per";
> >                 };
> >  
> >                 dma0: dma at 14000 {
> > @@ -414,6 +491,8 @@
> >                 #address-cells = <3>;
> >                 #size-cells = <2>;
> >                 #interrupt-cells = <1>;
> > +               clocks = <&clks MPC512x_CLK_PCI>;
> > +               clock-names = "per";
> >  
> >                 reg = <0x80008500 0x100 /* internal registers */
> >                        0x80008300 0x8>; /* config space access registers */
> > -- 
> > 1.7.10.4


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 11/31] net: can: mscan: improve clock API use
  2013-07-23 12:33               ` Marc Kleine-Budde
@ 2013-08-03 17:07                 ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 17:07 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Mike Turquette, Detlev Zundel, Greg Kroah-Hartman, Mark Brown,
	linux-arm-kernel, Anatolij Gustschin, linuxppc-dev,
	Wolfgang Grandegger

[ trimming the CC: list a bit, as this is CAN and clock specific,
  keeping Mark Brown and Greg KH for the UART and SPI part ]

On Tue, Jul 23, 2013 at 14:33 +0200, Marc Kleine-Budde wrote:
> 
> On 07/23/2013 01:53 PM, Gerhard Sittig wrote:
> > On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
> >>
> >> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> >>> the .get_clock() callback is run from probe() and might allocate
> >>> resources, introduce a .put_clock() callback that is run from remove()
> >>> to undo any allocation activities
> >>
> >> looks good
> >>
> >>> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> >>> upon driver unload
> >>
> >> fine
> >>
> >>> assume that resources get prepared but not necessarily enabled in the
> >>> setup phase, make the open() and close() callbacks of the CAN network
> >>> device enable and disable a previously acquired and prepared clock
> >>
> >> I think you should call prepare_enable and disable_unprepare in the
> >> open/close functions.
> > 
> > After more local research, which totally eliminated the need to
> > pre-enable the CAN related clocks, but might need more discussion
> > as it touches the common gate support, I've learned something
> > more:
> > 
> > The CAN clock needs to get enabled during probe() already, since
> > registers get accessed between probe() for the driver and open()
> > for the network device -- while access to peripheral registers
> > crashes the kernel when clocks still are disabled (other hardware
> > may just hang or provide fake data, neither of this is OK).
> 
> Then call prepare_enable(); before and disable_unprepare(); after
> accessing the registers. Have a look at the flexcan driver.

OK, your feedback made me notice that I mentally have mixed
peripheral access clocks ('ipg') and bitrate clocks ('per') in
the past versions of the driver.

Fixing this, telling 'ipg' and 'per' apart, "in bypassing"
eliminates the need for "shared clock gates".  Since the MCLK
subtree of the clock tree apply to both the CAN controller and
the PSC controller, I will have to adjust all of the following:
- the platform's clock driver, telling the gate for the registers
  and the mux/div for the bitrate apart
- the CAN driver, acquiring both the 'ipg' clock item for
  register access and the "can" clock for the bitrate, the latter
  may get derived from either 'ips' or 'mclk', while 'mclk' may
  be derived from either 'sys' or 'ref' (or 'ips' in this
  hardware while the mscan(4) driver doesn't use this feature)
- the UART and SPI drivers, acquiring both the 'ipg' clock item
  for register access and the 'mclk' item for the bitrate

This obsoletes the request for "shared gates" and eliminates
another pre-enable workaround in the clock driver backend.

It also is an improvement for the MPC512x platform, and remains
neutral to the MPC52xx platform.  It's clearly desirable and
useful, and doesn't break anything.  So I will do it.

[ the above applied to CAN, SPI, and UART; the remainder is
  specific to CAN only ]


But I won't try to even further widen the scope of the series, I
won't try to address each and every potential for improvement
which drivers may have had for several years and which happened
to not have been addressed yet.  This needs to stop at some
reasonable point.  I'm not refusing to improve, but I'm asking to
check what is reasonable and what needs to get avoided.

I already introduced a bug in a recent version of the series
which went unnoticed during review (the unbalanced error path in
the network device open routine).  I'd rather not mess with power
management aspects "in bypassing" in a driver that I'm unable to
test thoroughly.  Not when I'm trying to work on something
totally different (introducing proper common clock support) and
try to minimize risk and avoid damage.


> > But I see the point in your suggestion to prepare _and_ enable
> > the clock during open() as well -- to have open() cope with
> > whatever probe() did, after all the driver is shared among
> > platforms, which may differ in what they do during probe().
> 
> If you enable a clock to access the registers before open() (and disable
> it afterwards), it should not harm any architecture that doesn't need
> this clock enabled.

You suggest to turn on the clock during initialization, and turn
it off until the network device actually gets used?  I had a look
at the flexcan driver, saw that it used two clock items, as
outlined above for register access and for wired communication.
This is good.  But I somehow doubt that the flexcan driver will
work if the ipg clock gets disabled (I assume it's a shared clock
that happens to remain enabled since others use it as well).

I'd rather not open that can of worms, too.  My gut is telling me
that either the peripheral does weird things or will lose data
when its (register access) clock gets disabled.  I won't try to
address power management and save/restore issues in that driver
now, and I won't try to hunt down and instrument any register
access in the shared code paths of a driver for multiple
platforms which is full of callbacks.

That's just out of the scope of the series.  It may be desirable
to address this issue as well, but it shall be done in a separate
action, not now "in bypassing".  Thank you for understanding. :)
And I do appreciate your feedback and desire for even better
drivers, just disagree on what to do now in this very moment.


What we already have is:
- probe() and remove() for the driver, calling into clock setup
  and allocation and deallocation routines
- no allocation for MPC52xx and thus no deallocation, keeping the
  status of how things used to be
- allocation of a "can" clock for MPC512x and the respective
  deallocation
- open() and close() for the network device, which prepare/enable
  and disable/unprepare the allocated clocks

What I will add is:
- allocation and release of both the 'ipg' and a "can" clock for
  the MPC512x case
- handling of all allocated clocks in open() and close() (such
  that no assumption is made what occurs at probe() and remove()
  time)
- permanently enabled 'ipg' clock when allocated, such that the
  driver may happily access the controller's registers and may
  assume things remain there
- usually disabled 'can' clock, but enable/disable between open()
  and close()

This shall result in:
- no change in behaviour for MPC52xx
- disabled clocks and hardware for MPC512x when CAN isn't probed
  (not listed in the device tree, or disabled)
- enabled internal peripherals but wire disabled for MPC512x when
  CAN is probed and attached but not in use
- only enabled wire related clock when the network device is open
  and in actual use

The above goal of the next update in the series won't break any
operation of peripherals, will be a clear improvement in that the
driver finally does properly use the clock API, and will result
in an appropriate use of hardware.  There may be potential to
conserve even more power, but it's not essential given the
previous status of the driver, and it's out of the scope for the
very series we are talking about.


> > So I will:
> > - make open() of the network device prepare _and_ enable the
> >   clock for the peripheral (if acquired during probe())
> 
> good
> 
> > - adjust open() because ATM it leaves the clock enabled when the
> >   network device operation fails (the error path is incomplete in
> >   v3)
> 
> yes, clock should be disabled if open() fails.
> 
> > - make the MPC512x specific probe() time .get_clock() routine not
> >   just prepare but enable the clock as well
> 
> If needed enable the clock, but disable after probe() has finished.
> 
> > - and of course address all the shutdown counter parts of the
> >   above setup paths
> 
> > This results in:
> > - specific chip drivers only need to balance their private get
> >   and put clock routines which are called from probe and remove,
> >   common paths DTRT for all of them
> 
> Yes, but clock should not stay enabled between probe() and open().

For this one I offered the compromise of only enabling the "can"
clock during network device operation, but keeping the 'ipg'
clock active over the driver's complete attachment period.  This
shall be acceptable.  Anything else can be done later and
independently.

> [...]
> 
> > Removing unnecessary devm_put_clk() calls is orthogonal to that.
> > Putting these in isn't totally wrong (they won't harm, and they
> > do signal "visual balance" more clearly such that the next person
> > won't stop and wonder), but it's true that they are redundant.
> > "Trained persons" will wonder as much about their presence as
> > untrained persons wonder about their absence. :)  Apparently I'm
> > not well trained yet.
> 
> The whole point about devm_* is to get rid of auto manually tear down
> functions. So please remove all devm_put_clk() calls, as it will be
> called automatically if a driver instance is removed.

Ah, yes, the devm_*() feedback was processed as well.  Release
won't occur explicitly, as it's done implicitly by common code.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 11/31] net: can: mscan: improve clock API use
@ 2013-08-03 17:07                 ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-03 17:07 UTC (permalink / raw)
  To: linux-arm-kernel

[ trimming the CC: list a bit, as this is CAN and clock specific,
  keeping Mark Brown and Greg KH for the UART and SPI part ]

On Tue, Jul 23, 2013 at 14:33 +0200, Marc Kleine-Budde wrote:
> 
> On 07/23/2013 01:53 PM, Gerhard Sittig wrote:
> > On Mon, Jul 22, 2013 at 14:31 +0200, Marc Kleine-Budde wrote:
> >>
> >> On 07/22/2013 02:14 PM, Gerhard Sittig wrote:
> >>> the .get_clock() callback is run from probe() and might allocate
> >>> resources, introduce a .put_clock() callback that is run from remove()
> >>> to undo any allocation activities
> >>
> >> looks good
> >>
> >>> use devm_get_clk() upon lookup (for SYS and REF) to have the clocks put
> >>> upon driver unload
> >>
> >> fine
> >>
> >>> assume that resources get prepared but not necessarily enabled in the
> >>> setup phase, make the open() and close() callbacks of the CAN network
> >>> device enable and disable a previously acquired and prepared clock
> >>
> >> I think you should call prepare_enable and disable_unprepare in the
> >> open/close functions.
> > 
> > After more local research, which totally eliminated the need to
> > pre-enable the CAN related clocks, but might need more discussion
> > as it touches the common gate support, I've learned something
> > more:
> > 
> > The CAN clock needs to get enabled during probe() already, since
> > registers get accessed between probe() for the driver and open()
> > for the network device -- while access to peripheral registers
> > crashes the kernel when clocks still are disabled (other hardware
> > may just hang or provide fake data, neither of this is OK).
> 
> Then call prepare_enable(); before and disable_unprepare(); after
> accessing the registers. Have a look at the flexcan driver.

OK, your feedback made me notice that I mentally have mixed
peripheral access clocks ('ipg') and bitrate clocks ('per') in
the past versions of the driver.

Fixing this, telling 'ipg' and 'per' apart, "in bypassing"
eliminates the need for "shared clock gates".  Since the MCLK
subtree of the clock tree apply to both the CAN controller and
the PSC controller, I will have to adjust all of the following:
- the platform's clock driver, telling the gate for the registers
  and the mux/div for the bitrate apart
- the CAN driver, acquiring both the 'ipg' clock item for
  register access and the "can" clock for the bitrate, the latter
  may get derived from either 'ips' or 'mclk', while 'mclk' may
  be derived from either 'sys' or 'ref' (or 'ips' in this
  hardware while the mscan(4) driver doesn't use this feature)
- the UART and SPI drivers, acquiring both the 'ipg' clock item
  for register access and the 'mclk' item for the bitrate

This obsoletes the request for "shared gates" and eliminates
another pre-enable workaround in the clock driver backend.

It also is an improvement for the MPC512x platform, and remains
neutral to the MPC52xx platform.  It's clearly desirable and
useful, and doesn't break anything.  So I will do it.

[ the above applied to CAN, SPI, and UART; the remainder is
  specific to CAN only ]


But I won't try to even further widen the scope of the series, I
won't try to address each and every potential for improvement
which drivers may have had for several years and which happened
to not have been addressed yet.  This needs to stop at some
reasonable point.  I'm not refusing to improve, but I'm asking to
check what is reasonable and what needs to get avoided.

I already introduced a bug in a recent version of the series
which went unnoticed during review (the unbalanced error path in
the network device open routine).  I'd rather not mess with power
management aspects "in bypassing" in a driver that I'm unable to
test thoroughly.  Not when I'm trying to work on something
totally different (introducing proper common clock support) and
try to minimize risk and avoid damage.


> > But I see the point in your suggestion to prepare _and_ enable
> > the clock during open() as well -- to have open() cope with
> > whatever probe() did, after all the driver is shared among
> > platforms, which may differ in what they do during probe().
> 
> If you enable a clock to access the registers before open() (and disable
> it afterwards), it should not harm any architecture that doesn't need
> this clock enabled.

You suggest to turn on the clock during initialization, and turn
it off until the network device actually gets used?  I had a look
at the flexcan driver, saw that it used two clock items, as
outlined above for register access and for wired communication.
This is good.  But I somehow doubt that the flexcan driver will
work if the ipg clock gets disabled (I assume it's a shared clock
that happens to remain enabled since others use it as well).

I'd rather not open that can of worms, too.  My gut is telling me
that either the peripheral does weird things or will lose data
when its (register access) clock gets disabled.  I won't try to
address power management and save/restore issues in that driver
now, and I won't try to hunt down and instrument any register
access in the shared code paths of a driver for multiple
platforms which is full of callbacks.

That's just out of the scope of the series.  It may be desirable
to address this issue as well, but it shall be done in a separate
action, not now "in bypassing".  Thank you for understanding. :)
And I do appreciate your feedback and desire for even better
drivers, just disagree on what to do now in this very moment.


What we already have is:
- probe() and remove() for the driver, calling into clock setup
  and allocation and deallocation routines
- no allocation for MPC52xx and thus no deallocation, keeping the
  status of how things used to be
- allocation of a "can" clock for MPC512x and the respective
  deallocation
- open() and close() for the network device, which prepare/enable
  and disable/unprepare the allocated clocks

What I will add is:
- allocation and release of both the 'ipg' and a "can" clock for
  the MPC512x case
- handling of all allocated clocks in open() and close() (such
  that no assumption is made what occurs at probe() and remove()
  time)
- permanently enabled 'ipg' clock when allocated, such that the
  driver may happily access the controller's registers and may
  assume things remain there
- usually disabled 'can' clock, but enable/disable between open()
  and close()

This shall result in:
- no change in behaviour for MPC52xx
- disabled clocks and hardware for MPC512x when CAN isn't probed
  (not listed in the device tree, or disabled)
- enabled internal peripherals but wire disabled for MPC512x when
  CAN is probed and attached but not in use
- only enabled wire related clock when the network device is open
  and in actual use

The above goal of the next update in the series won't break any
operation of peripherals, will be a clear improvement in that the
driver finally does properly use the clock API, and will result
in an appropriate use of hardware.  There may be potential to
conserve even more power, but it's not essential given the
previous status of the driver, and it's out of the scope for the
very series we are talking about.


> > So I will:
> > - make open() of the network device prepare _and_ enable the
> >   clock for the peripheral (if acquired during probe())
> 
> good
> 
> > - adjust open() because ATM it leaves the clock enabled when the
> >   network device operation fails (the error path is incomplete in
> >   v3)
> 
> yes, clock should be disabled if open() fails.
> 
> > - make the MPC512x specific probe() time .get_clock() routine not
> >   just prepare but enable the clock as well
> 
> If needed enable the clock, but disable after probe() has finished.
> 
> > - and of course address all the shutdown counter parts of the
> >   above setup paths
> 
> > This results in:
> > - specific chip drivers only need to balance their private get
> >   and put clock routines which are called from probe and remove,
> >   common paths DTRT for all of them
> 
> Yes, but clock should not stay enabled between probe() and open().

For this one I offered the compromise of only enabling the "can"
clock during network device operation, but keeping the 'ipg'
clock active over the driver's complete attachment period.  This
shall be acceptable.  Anything else can be done later and
independently.

> [...]
> 
> > Removing unnecessary devm_put_clk() calls is orthogonal to that.
> > Putting these in isn't totally wrong (they won't harm, and they
> > do signal "visual balance" more clearly such that the next person
> > won't stop and wonder), but it's true that they are redundant.
> > "Trained persons" will wonder as much about their presence as
> > untrained persons wonder about their absence. :)  Apparently I'm
> > not well trained yet.
> 
> The whole point about devm_* is to get rid of auto manually tear down
> functions. So please remove all devm_put_clk() calls, as it will be
> called automatically if a driver instance is removed.

Ah, yes, the devm_*() feedback was processed as well.  Release
won't occur explicitly, as it's done implicitly by common code.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-07-22 12:14         ` Gerhard Sittig
  (?)
@ 2013-08-05 11:37           ` Mark Rutland
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Rutland @ 2013-08-05 11:37 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, rob.herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Pantelis Antoniou, Anatolij Gustschin,
	linuxppc-dev, David Woodhouse, linux-arm-kernel,
	Mauro Carvalho Chehab

On Mon, Jul 22, 2013 at 01:14:44PM +0100, Gerhard Sittig wrote:
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
>
> this driver implements the publicly announced set of clocks (which can
> get referenced by means of symbolic identifiers from the dt-bindings
> header file), as well as generates additional 'struct clk' items where
> the SoC hardware cannot easily get mapped to the common primitives of
> the clock API, or requires "intermediate" clock nodes to represent
> clocks that have both gates and dividers
>
> the previous PPC_CLOCK implementation is kept in place and remains in
> parallel to the common clock implementation for test and comparison
> during migration, a compile time option picks one of the two
> alternatives (Kconfig switch, common clock used by default)
>
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> - some of the clocks are useful to have for diagnostics and information
>   despite their not getting claimed by any drivers (CPU, internal and
>   external RAM, internal busses, boot media)
> - some of the clocks aren't claimed by their peripheral drivers yet,
>   either because of missing driver support or because device tree specs
>   aren't available yet (but the workarounds will get removed as the
>   drivers get adjusted and the device tree provides the clock specs)
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)
>
> clkdev registration provides "alias names" for few clock items
> - to not break those peripheral drivers which encode their component
>   index into the name that is used for clock lookup (UART, SPI, USB)
> - to not break those drivers which use names for the clock lookup which
>   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> this workaround will get removed as these drivers get adjusted after
> device tree based clock lookup has become available
>
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/platforms/512x/Kconfig           |   14 +-
>  arch/powerpc/platforms/512x/Makefile          |    4 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
>  include/linux/clk-provider.h                  |   16 +
>  4 files changed, 818 insertions(+), 2 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
>

[...]

> +static int get_freq_from_dt(char *propname)
> +{
> +       struct device_node *np;
> +       const unsigned int *prop;
> +       int val;
> +
> +       val = 0;
> +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> +       if (np) {
> +               prop = of_get_property(np, propname, NULL);
> +               if (prop)
> +                       val = *prop;
> +           of_node_put(np);
> +       }
> +       return val;
> +}

Can you not use of_property_read_u32 here rather than of_get_property?

Also, this seems rather unlike the common clock bindings method for
describing frequencies in the dt. Given there's nothing in mainline
using this yet, we can do it 'right' from the start.

[...]

> +       /*
> +        * externally provided clocks (when implemented in hardware,
> +        * device tree may specify values which otherwise were unknown)
> +        */
> +       freq = get_freq_from_dt("psc_mclk_in");
> +       if (!freq)
> +               freq = 25000000;
> +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> +       freq = get_freq_from_dt("spdif_tx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> +       freq = get_freq_from_dt("spdif_rx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);

Can we not just use fixed-clocks for these in the dt? It feels odd to
describe them in a compeltely differnet way in the dt, especially as
we'll have to maintain some backwards compatibility for a while...

I see for psc_mclk_in we assume a default value if not present. I'm not
sure how to handle that, but I assume there's some way of finding out if
we've already registered a clock output with the same name?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-05 11:37           ` Mark Rutland
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Rutland @ 2013-08-05 11:37 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Mike Turquette, Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman,
	devicetree-discuss, rob.herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jul 22, 2013 at 01:14:44PM +0100, Gerhard Sittig wrote:
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
>
> this driver implements the publicly announced set of clocks (which can
> get referenced by means of symbolic identifiers from the dt-bindings
> header file), as well as generates additional 'struct clk' items where
> the SoC hardware cannot easily get mapped to the common primitives of
> the clock API, or requires "intermediate" clock nodes to represent
> clocks that have both gates and dividers
>
> the previous PPC_CLOCK implementation is kept in place and remains in
> parallel to the common clock implementation for test and comparison
> during migration, a compile time option picks one of the two
> alternatives (Kconfig switch, common clock used by default)
>
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> - some of the clocks are useful to have for diagnostics and information
>   despite their not getting claimed by any drivers (CPU, internal and
>   external RAM, internal busses, boot media)
> - some of the clocks aren't claimed by their peripheral drivers yet,
>   either because of missing driver support or because device tree specs
>   aren't available yet (but the workarounds will get removed as the
>   drivers get adjusted and the device tree provides the clock specs)
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)
>
> clkdev registration provides "alias names" for few clock items
> - to not break those peripheral drivers which encode their component
>   index into the name that is used for clock lookup (UART, SPI, USB)
> - to not break those drivers which use names for the clock lookup which
>   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> this workaround will get removed as these drivers get adjusted after
> device tree based clock lookup has become available
>
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/platforms/512x/Kconfig           |   14 +-
>  arch/powerpc/platforms/512x/Makefile          |    4 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
>  include/linux/clk-provider.h                  |   16 +
>  4 files changed, 818 insertions(+), 2 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
>

[...]

> +static int get_freq_from_dt(char *propname)
> +{
> +       struct device_node *np;
> +       const unsigned int *prop;
> +       int val;
> +
> +       val = 0;
> +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> +       if (np) {
> +               prop = of_get_property(np, propname, NULL);
> +               if (prop)
> +                       val = *prop;
> +           of_node_put(np);
> +       }
> +       return val;
> +}

Can you not use of_property_read_u32 here rather than of_get_property?

Also, this seems rather unlike the common clock bindings method for
describing frequencies in the dt. Given there's nothing in mainline
using this yet, we can do it 'right' from the start.

[...]

> +       /*
> +        * externally provided clocks (when implemented in hardware,
> +        * device tree may specify values which otherwise were unknown)
> +        */
> +       freq = get_freq_from_dt("psc_mclk_in");
> +       if (!freq)
> +               freq = 25000000;
> +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> +       freq = get_freq_from_dt("spdif_tx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> +       freq = get_freq_from_dt("spdif_rx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);

Can we not just use fixed-clocks for these in the dt? It feels odd to
describe them in a compeltely differnet way in the dt, especially as
we'll have to maintain some backwards compatibility for a while...

I see for psc_mclk_in we assume a default value if not present. I'm not
sure how to handle that, but I assume there's some way of finding out if
we've already registered a clock output with the same name?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-05 11:37           ` Mark Rutland
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Rutland @ 2013-08-05 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 22, 2013 at 01:14:44PM +0100, Gerhard Sittig wrote:
> this change implements a clock driver for the MPC512x PowerPC platform
> which follows the COMMON_CLK approach and uses common clock drivers
> shared with other platforms
>
> this driver implements the publicly announced set of clocks (which can
> get referenced by means of symbolic identifiers from the dt-bindings
> header file), as well as generates additional 'struct clk' items where
> the SoC hardware cannot easily get mapped to the common primitives of
> the clock API, or requires "intermediate" clock nodes to represent
> clocks that have both gates and dividers
>
> the previous PPC_CLOCK implementation is kept in place and remains in
> parallel to the common clock implementation for test and comparison
> during migration, a compile time option picks one of the two
> alternatives (Kconfig switch, common clock used by default)
>
> some of the clock items get pre-enabled in the clock driver to not have
> them automatically disabled by the underlying clock subsystem because of
> their being unused -- this approach is desirable because
> - some of the clocks are useful to have for diagnostics and information
>   despite their not getting claimed by any drivers (CPU, internal and
>   external RAM, internal busses, boot media)
> - some of the clocks aren't claimed by their peripheral drivers yet,
>   either because of missing driver support or because device tree specs
>   aren't available yet (but the workarounds will get removed as the
>   drivers get adjusted and the device tree provides the clock specs)
> - some help introduce support for and migrate to the common
>   infrastructure, while more appropriate support for specific hardware
>   constraints isn't available yet (remaining changes are strictly
>   internal to the clock driver and won't affect peripheral drivers)
>
> clkdev registration provides "alias names" for few clock items
> - to not break those peripheral drivers which encode their component
>   index into the name that is used for clock lookup (UART, SPI, USB)
> - to not break those drivers which use names for the clock lookup which
>   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> this workaround will get removed as these drivers get adjusted after
> device tree based clock lookup has become available
>
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/platforms/512x/Kconfig           |   14 +-
>  arch/powerpc/platforms/512x/Makefile          |    4 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
>  include/linux/clk-provider.h                  |   16 +
>  4 files changed, 818 insertions(+), 2 deletions(-)
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
>

[...]

> +static int get_freq_from_dt(char *propname)
> +{
> +       struct device_node *np;
> +       const unsigned int *prop;
> +       int val;
> +
> +       val = 0;
> +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> +       if (np) {
> +               prop = of_get_property(np, propname, NULL);
> +               if (prop)
> +                       val = *prop;
> +           of_node_put(np);
> +       }
> +       return val;
> +}

Can you not use of_property_read_u32 here rather than of_get_property?

Also, this seems rather unlike the common clock bindings method for
describing frequencies in the dt. Given there's nothing in mainline
using this yet, we can do it 'right' from the start.

[...]

> +       /*
> +        * externally provided clocks (when implemented in hardware,
> +        * device tree may specify values which otherwise were unknown)
> +        */
> +       freq = get_freq_from_dt("psc_mclk_in");
> +       if (!freq)
> +               freq = 25000000;
> +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> +       freq = get_freq_from_dt("spdif_tx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> +       freq = get_freq_from_dt("spdif_rx_in");
> +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);

Can we not just use fixed-clocks for these in the dt? It feels odd to
describe them in a compeltely differnet way in the dt, especially as
we'll have to maintain some backwards compatibility for a while...

I see for psc_mclk_in we assume a default value if not present. I'm not
sure how to handle that, but I assume there's some way of finding out if
we've already registered a clock output with the same name?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-08-05 11:37           ` Mark Rutland
@ 2013-08-05 17:01             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-05 17:01 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	Greg Kroah-Hartman, rob.herring, Mark Brown, Marc Kleine-Budde,
	linux-arm-kernel, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, Wolfgang Grandegger, Mauro Carvalho Chehab

On Mon, Aug 05, 2013 at 12:37 +0100, Mark Rutland wrote:
> 
> On Mon, Jul 22, 2013 at 01:14:44PM +0100, Gerhard Sittig wrote:
> > this change implements a clock driver for the MPC512x PowerPC platform
> > which follows the COMMON_CLK approach and uses common clock drivers
> > shared with other platforms
> >
> > this driver implements the publicly announced set of clocks (which can
> > get referenced by means of symbolic identifiers from the dt-bindings
> > header file), as well as generates additional 'struct clk' items where
> > the SoC hardware cannot easily get mapped to the common primitives of
> > the clock API, or requires "intermediate" clock nodes to represent
> > clocks that have both gates and dividers
> >
> > the previous PPC_CLOCK implementation is kept in place and remains in
> > parallel to the common clock implementation for test and comparison
> > during migration, a compile time option picks one of the two
> > alternatives (Kconfig switch, common clock used by default)
> >
> > some of the clock items get pre-enabled in the clock driver to not have
> > them automatically disabled by the underlying clock subsystem because of
> > their being unused -- this approach is desirable because
> > - some of the clocks are useful to have for diagnostics and information
> >   despite their not getting claimed by any drivers (CPU, internal and
> >   external RAM, internal busses, boot media)
> > - some of the clocks aren't claimed by their peripheral drivers yet,
> >   either because of missing driver support or because device tree specs
> >   aren't available yet (but the workarounds will get removed as the
> >   drivers get adjusted and the device tree provides the clock specs)
> > - some help introduce support for and migrate to the common
> >   infrastructure, while more appropriate support for specific hardware
> >   constraints isn't available yet (remaining changes are strictly
> >   internal to the clock driver and won't affect peripheral drivers)
> >
> > clkdev registration provides "alias names" for few clock items
> > - to not break those peripheral drivers which encode their component
> >   index into the name that is used for clock lookup (UART, SPI, USB)
> > - to not break those drivers which use names for the clock lookup which
> >   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> > this workaround will get removed as these drivers get adjusted after
> > device tree based clock lookup has become available
> >
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  arch/powerpc/platforms/512x/Kconfig           |   14 +-
> >  arch/powerpc/platforms/512x/Makefile          |    4 +-
> >  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
> >  include/linux/clk-provider.h                  |   16 +
> >  4 files changed, 818 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> >
> 
> [...]
> 
> > +static int get_freq_from_dt(char *propname)
> > +{
> > +       struct device_node *np;
> > +       const unsigned int *prop;
> > +       int val;
> > +
> > +       val = 0;
> > +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> > +       if (np) {
> > +               prop = of_get_property(np, propname, NULL);
> > +               if (prop)
> > +                       val = *prop;
> > +           of_node_put(np);
> > +       }
> > +       return val;
> > +}
> 
> Can you not use of_property_read_u32 here rather than of_get_property?
> 
> Also, this seems rather unlike the common clock bindings method for
> describing frequencies in the dt. Given there's nothing in mainline
> using this yet, we can do it 'right' from the start.

This specific routine was taken in verbatim form from the former
PPC_CLOCK implementation.  Although I could re-implement it in
other ways if that was considered necessary.

> 
> [...]
> 
> > +       /*
> > +        * externally provided clocks (when implemented in hardware,
> > +        * device tree may specify values which otherwise were unknown)
> > +        */
> > +       freq = get_freq_from_dt("psc_mclk_in");
> > +       if (!freq)
> > +               freq = 25000000;
> > +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> > +       freq = get_freq_from_dt("spdif_tx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> > +       freq = get_freq_from_dt("spdif_rx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
> 
> Can we not just use fixed-clocks for these in the dt? It feels odd to
> describe them in a compeltely differnet way in the dt, especially as
> we'll have to maintain some backwards compatibility for a while...
> 
> I see for psc_mclk_in we assume a default value if not present. I'm not
> sure how to handle that, but I assume there's some way of finding out if
> we've already registered a clock output with the same name?

I guess using fixed-clocks (i.e. clock items that completely get
described in the device tree, and are taken care of by a common
driver which attaches to anything that is said to be compatible)
would change behaviour, which I did not intend to introduce.

The above code does what the PPC_CLOCK implementation did: Always
create the clock items, while their _rate_ may or may not be
specified or overridden from device tree specs, and defaults
(non-zero or zero) always apply.


Thank you for the feedback and suggestions.  I've yet to find out
how much compatibility I'm allowed to break. :)  ATM I assume
that my changes do keep compatibility where appropriate, and only
change the device tree or its interpretation where the device
tree may be considered wrong (not that it would provide false
information, but it certainly lacked essential information about
the hardware, like clock related information, and thus it shall
be acceptable to require an update of the dtb to fix that gap).


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-05 17:01             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-05 17:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 05, 2013 at 12:37 +0100, Mark Rutland wrote:
> 
> On Mon, Jul 22, 2013 at 01:14:44PM +0100, Gerhard Sittig wrote:
> > this change implements a clock driver for the MPC512x PowerPC platform
> > which follows the COMMON_CLK approach and uses common clock drivers
> > shared with other platforms
> >
> > this driver implements the publicly announced set of clocks (which can
> > get referenced by means of symbolic identifiers from the dt-bindings
> > header file), as well as generates additional 'struct clk' items where
> > the SoC hardware cannot easily get mapped to the common primitives of
> > the clock API, or requires "intermediate" clock nodes to represent
> > clocks that have both gates and dividers
> >
> > the previous PPC_CLOCK implementation is kept in place and remains in
> > parallel to the common clock implementation for test and comparison
> > during migration, a compile time option picks one of the two
> > alternatives (Kconfig switch, common clock used by default)
> >
> > some of the clock items get pre-enabled in the clock driver to not have
> > them automatically disabled by the underlying clock subsystem because of
> > their being unused -- this approach is desirable because
> > - some of the clocks are useful to have for diagnostics and information
> >   despite their not getting claimed by any drivers (CPU, internal and
> >   external RAM, internal busses, boot media)
> > - some of the clocks aren't claimed by their peripheral drivers yet,
> >   either because of missing driver support or because device tree specs
> >   aren't available yet (but the workarounds will get removed as the
> >   drivers get adjusted and the device tree provides the clock specs)
> > - some help introduce support for and migrate to the common
> >   infrastructure, while more appropriate support for specific hardware
> >   constraints isn't available yet (remaining changes are strictly
> >   internal to the clock driver and won't affect peripheral drivers)
> >
> > clkdev registration provides "alias names" for few clock items
> > - to not break those peripheral drivers which encode their component
> >   index into the name that is used for clock lookup (UART, SPI, USB)
> > - to not break those drivers which use names for the clock lookup which
> >   were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
> > this workaround will get removed as these drivers get adjusted after
> > device tree based clock lookup has become available
> >
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > ---
> >  arch/powerpc/platforms/512x/Kconfig           |   14 +-
> >  arch/powerpc/platforms/512x/Makefile          |    4 +-
> >  arch/powerpc/platforms/512x/clock-commonclk.c |  786 +++++++++++++++++++++++++
> >  include/linux/clk-provider.h                  |   16 +
> >  4 files changed, 818 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> >
> 
> [...]
> 
> > +static int get_freq_from_dt(char *propname)
> > +{
> > +       struct device_node *np;
> > +       const unsigned int *prop;
> > +       int val;
> > +
> > +       val = 0;
> > +       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
> > +       if (np) {
> > +               prop = of_get_property(np, propname, NULL);
> > +               if (prop)
> > +                       val = *prop;
> > +           of_node_put(np);
> > +       }
> > +       return val;
> > +}
> 
> Can you not use of_property_read_u32 here rather than of_get_property?
> 
> Also, this seems rather unlike the common clock bindings method for
> describing frequencies in the dt. Given there's nothing in mainline
> using this yet, we can do it 'right' from the start.

This specific routine was taken in verbatim form from the former
PPC_CLOCK implementation.  Although I could re-implement it in
other ways if that was considered necessary.

> 
> [...]
> 
> > +       /*
> > +        * externally provided clocks (when implemented in hardware,
> > +        * device tree may specify values which otherwise were unknown)
> > +        */
> > +       freq = get_freq_from_dt("psc_mclk_in");
> > +       if (!freq)
> > +               freq = 25000000;
> > +       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
> > +       freq = get_freq_from_dt("spdif_tx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
> > +       freq = get_freq_from_dt("spdif_rx_in");
> > +       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
> 
> Can we not just use fixed-clocks for these in the dt? It feels odd to
> describe them in a compeltely differnet way in the dt, especially as
> we'll have to maintain some backwards compatibility for a while...
> 
> I see for psc_mclk_in we assume a default value if not present. I'm not
> sure how to handle that, but I assume there's some way of finding out if
> we've already registered a clock output with the same name?

I guess using fixed-clocks (i.e. clock items that completely get
described in the device tree, and are taken care of by a common
driver which attaches to anything that is said to be compatible)
would change behaviour, which I did not intend to introduce.

The above code does what the PPC_CLOCK implementation did: Always
create the clock items, while their _rate_ may or may not be
specified or overridden from device tree specs, and defaults
(non-zero or zero) always apply.


Thank you for the feedback and suggestions.  I've yet to find out
how much compatibility I'm allowed to break. :)  ATM I assume
that my changes do keep compatibility where appropriate, and only
change the device tree or its interpretation where the device
tree may be considered wrong (not that it would provide false
information, but it certainly lacked essential information about
the hardware, like clock related information, and thus it shall
be acceptable to require an update of the dtb to fix that gap).


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-08-03 14:39               ` Gerhard Sittig
@ 2013-08-05 17:11                 ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-05 17:11 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: Anatolij Gustschin, linuxppc-dev, linux-arm-kernel

Quoting Gerhard Sittig (2013-08-03 07:39:56)
> [ we are strictly talking about clocks and source code again,
>   I have trimmed the CC: list to not spam the device tree ML or
>   subsystem maintainers ]
> =

> On Fri, Aug 02, 2013 at 16:30 -0700, Mike Turquette wrote:
> > =

> > Quoting Gerhard Sittig (2013-07-23 06:14:06)
> > > [ summary: "shared gate" support desirable? approach acceptable? ]
> > > =

> > > On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> > > > =

> > > > this change implements a clock driver for the MPC512x PowerPC platf=
orm
> > > > which follows the COMMON_CLK approach and uses common clock drivers
> > > > shared with other platforms
> > > > =

> > > > [ ... ]
> > > > =

> > > > some of the clock items get pre-enabled in the clock driver to not =
have
> > > > them automatically disabled by the underlying clock subsystem becau=
se of
> > > > their being unused -- this approach is desirable because
> > > > [ ... ]
> > > > - some help introduce support for and migrate to the common
> > > >   infrastructure, while more appropriate support for specific hardw=
are
> > > >   constraints isn't available yet (remaining changes are strictly
> > > >   internal to the clock driver and won't affect peripheral drivers)
> > > =

> > > This remark was related to the CAN clocks of the MPC512x SoC.
> > =

> > Gerhard,
> > =

> > Thanks for the patch (way far down below here). I'll check into it to
> > see if that implementation looks OK. It would be helpful if another
> > platform with shared gates could weigh in on whether the implementation
> > works for them.
> > =

> > Still, a shared gate solution is not a prerequisite for this series,
> > correct?
> =

> Well, the recent CAN driver related discussion suggested that I
> had a mental misconception there.  The need for "shared gates"
> was felt because of mixing up unrelated paths in the clock tree.
> But the MCLK subtree is for bitrate generation, while the BDLC
> gate is for register access into the peripheral controller.
> =

> Currently I'm investigating how I can cleanly tell those
> individual aspects apart.  Telling the gate for register access
> (in ARM speak often referred to as 'ipg') from the bitrate
> generation (the 'per' clock, or 'mclk' here) seems so much more
> appropriate.
> =

> After clean separation, and more testing to make sure nothing
> gets broken throughout the series, there will be v4.
> =

> =

> So "shared gate" support might have become obsolete for the
> MPC512x platform.  But if others need it, the outlined approach
> (patch below) may be viable.  The change to the common code is
> minimal.  The use in the platform's clock driver was kind of
> overengineered for the case of exactly one such gate, but this
> immediately makes it a working approach for several gates, if
> others need it.
> =

> I'll trim the motivation and just leave the suggested approach
> for "shared gates" here.  Feel free to drop it or to only
> resurrect it as the need may re-arise later.  So far nobody
> appears to have felt the need up to now ...

You can drop it. If your platform does not need it and nobody else has
said that they require shared gates then there is no reason to spend
more time on it.

Regards,
Mike

> =

> > > [ ... ]
> > > =

> > > The question now is how to correctly support the situation where
> > > a gate is shared between subtrees yet isn't really part of any
> > > path within the subtrees.  I really cannot find a single spot
> > > where to introduce the gate such that it's not duplicated.
> > > =

> > > The appropriate solution would not be to pre-enable those clocks,
> > > but to either introduce another gate clock type which supports a
> > > shared reference, or to add support for the shared reference to
> > > the existing gate code.
> > > =

> > > =

> > > I'd rather not duplicate most or all of the code of clk-gate.c,
> > > instead I looked into how to add "shared gate" support to the
> > > existing driver.
> > > =

> > > My question is whether the approach is acceptable.  It adds
> > > minimal overhead and shall be OK for the enable/disable path from
> > > a technical POV.  And it doesn't feel like too much of a stretch.
> > > But there may be non-technical reasons to reject the approach.
> > > I'd like to learn whether to follow that path before preparing
> > > another version of the patch series.
> > > =

> > > The diffs were taken with the '-w -b' options to demonstrate
> > > their essence and not drown it in whitespace changes.  The
> > > implementation assumes that the caller which registers the gate
> > > (the platform's clock driver) provides both the counter cell and
> > > the lock.  And that all gates with a "shared use counter" use the
> > > same lock (which is satisfied as they all get registered from the
> > > same spot in the platform's clock driver).
> > > =

> > > The CLK_IGNORE_UNUSED flag addresses a different problem.  The
> > > SoC has four MSCAN components, while two of them are enabled in
> > > the device tree (the other two are present but disabled).  So
> > > during probe two of the clocks get enabled.  After probe all
> > > unused clocks automatically get disabled (that's another two).
> > > So the "shared use counter" drops to zero although components are
> > > in use, because "disable, it's unused" isn't told from "disable
> > > after enable, regular use".  The flag would become obsolete if
> > > the common gate logic would implement a separate disable_unused()
> > > routine, but I guess this isn't necessary and the use of the flag
> > > is appropriate.
> > > =

> > > That the example use creates a field for just one counter is to
> > > better demonstrate the use and potential extension as need
> > > arises.  Reducing this to a mere integer variable would be a
> > > micro optimization.
> > > =

> > > =

> > > The extension of the existing clk_gate implementation:
> > > =

> > > --- a/drivers/clk/clk-gate.c
> > > +++ b/drivers/clk/clk-gate.c
> > > @@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, i=
nt enable)
> > >         struct clk_gate *gate =3D to_clk_gate(hw);
> > >         int set =3D gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
> > >         unsigned long flags =3D 0;
> > > +       int need_reg_access;
> > >         u32 reg;
> > >  =

> > >         set ^=3D enable;
> > > @@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, =
int enable)
> > >         if (gate->lock)
> > >                 spin_lock_irqsave(gate->lock, flags);
> > >  =

> > > +       /*
> > > +        * if a "shared use counter" was specified, keep track of ena=
ble
> > > +        * and disable calls and only access hardware registers upon =
the
> > > +        * very first enable or very last disable call
> > > +        */
> > > +       if (!gate->share_count) {
> > > +               need_reg_access =3D 1;
> > > +       } else if (enable) {
> > > +               need_reg_access =3D (*gate->share_count)++ =3D=3D 0;
> > > +       } else {
> > > +               need_reg_access =3D --(*gate->share_count) =3D=3D 0;
> > > +       }
> > > +
> > > +       if (need_reg_access) {
> > >                 if (gate->flags & CLK_GATE_HIWORD_MASK) {
> > >                         reg =3D BIT(gate->bit_idx + 16);
> > >                         if (set)
> > > @@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, i=
nt enable)
> > >                 }
> > >  =

> > >                 clk_writel(reg, gate->reg);
> > > +       }
> > >  =

> > >         if (gate->lock)
> > >                 spin_unlock_irqrestore(gate->lock, flags);
> > > @@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
> > >   * @clk_gate_flags: gate-specific flags for this clock
> > >   * @lock: shared register lock for this clock
> > >   */
> > > -struct clk *clk_register_gate(struct device *dev, const char *name,
> > > +struct clk *clk_register_gate_shared(struct device *dev, const char =
*name,
> > >                 const char *parent_name, unsigned long flags,
> > >                 void __iomem *reg, u8 bit_idx,
> > > -               u8 clk_gate_flags, spinlock_t *lock)
> > > +               u8 clk_gate_flags, spinlock_t *lock,
> > > +               int *share_count)
> > >  {
> > >         struct clk_gate *gate;
> > >         struct clk *clk;
> > > @@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev,=
 const char *name,
> > >         gate->bit_idx =3D bit_idx;
> > >         gate->flags =3D clk_gate_flags;
> > >         gate->lock =3D lock;
> > > +       gate->share_count =3D share_count;
> > >         gate->hw.init =3D &init;
> > >  =

> > >         clk =3D clk_register(dev, &gate->hw);
> > > @@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev=
, const char *name,
> > >  =

> > >         return clk;
> > >  }
> > > +
> > > +struct clk *clk_register_gate(struct device *dev, const char *name,
> > > +               const char *parent_name, unsigned long flags,
> > > +               void __iomem *reg, u8 bit_idx,
> > > +               u8 clk_gate_flags, spinlock_t *lock)
> > > +{
> > > +
> > > +       return clk_register_gate_shared(dev, name, parent_name, flags,
> > > +                                       reg, bit_idx, clk_gate_flags,
> > > +                                       lock, NULL);
> > > +}
> > > --- a/include/linux/clk-provider.h
> > > +++ b/include/linux/clk-provider.h
> > > @@ -222,6 +222,7 @@ struct clk_gate {
> > >         u8              bit_idx;
> > >         u8              flags;
> > >         spinlock_t      *lock;
> > > +       int             *share_count;
> > >  };
> > >  =

> > >  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> > > @@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev=
, const char *name,
> > >                 const char *parent_name, unsigned long flags,
> > >                 void __iomem *reg, u8 bit_idx,
> > >                 u8 clk_gate_flags, spinlock_t *lock);
> > > +struct clk *clk_register_gate_shared(struct device *dev, const char =
*name,
> > > +               const char *parent_name, unsigned long flags,
> > > +               void __iomem *reg, u8 bit_idx,
> > > +               u8 clk_gate_flags, spinlock_t *lock,
> > > +               int *share_count);
> > >  =

> > >  struct clk_div_table {
> > >         unsigned int    val;
> > > =

> > > =

> > > How to use these shared gates:
> > > =

> > > --- a/arch/powerpc/platforms/512x/clock-commonclk.c
> > > +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> > > @@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
> > >                                  reg, pos, 0, &clklock);
> > >  }
> > >  =

> > > +enum mpc512x_clk_shared_gate_id_t {
> > > +       MPC512x_CLK_SHARED_GATE_MSCAN,
> > > +       MPC512x_CLK_SHARED_GATE_MAX,
> > > +};
> > > +
> > > +static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
> > > +
> > > +/*
> > > + * implementor's note:  since clk_gate items don't implement a separ=
ate
> > > + * .disable_unused() callback, their .disable() routine gets called =
and
> > > + * "disable the clock as we can't see it's in use" cannot be told fr=
om
> > > + * "regular disable, count these events please"
> > > + *
> > > + * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppr=
ess
> > > + * the "disable, unused" call, so use counts won't get unbalanced, t=
he
> > > + * clock either never got enabled and thus need not get disabled, or
> > > + * part of the hardware got enabled while disabling the other part i=
sn't
> > > + * wanted
> > > + */
> > > +static inline struct clk *mpc512x_clk_gated_shared(
> > > +       const char *name, const char *parent_name,
> > > +       u32 __iomem *reg, u8 pos,
> > > +       enum mpc512x_clk_shared_gate_id_t share_id)
> > > +{
> > > +       int clkflags;
> > > +
> > > +       clkflags =3D CLK_SET_RATE_PARENT;
> > > +       clkflags |=3D CLK_IGNORE_UNUSED;
> > > +       return clk_register_gate_shared(NULL, name, parent_name, clkf=
lags,
> > > +                                       reg, pos, 0, &clklock,
> > > +                                       &mpc512x_clk_gate_counters[sh=
are_id]);
> > > +}
> > > +
> > >  static inline struct clk *mpc512x_clk_muxed(const char *name,
> > >         const char **parent_names, int parent_count,
> > >         u32 __iomem *reg, u8 pos, u8 len)
> > > @@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_s=
etup_data *entry)
> > >                                 1, 1);
> > >         }
> > >         if (sccr_reg) {
> > > +               if (entry->type =3D=3D MCLK_TYPE_MSCAN) {
> > > +                       clks[clks_idx_pub] =3D mpc512x_clk_gated_shar=
ed(
> > > +                                       entry->name_mclk,
> > > +                                       entry->name_mux1, sccr_reg, s=
ccr_bit,
> > > +                                       MPC512x_CLK_SHARED_GATE_MSCAN=
);
> > > +               } else {
> > >                         clks[clks_idx_pub] =3D mpc512x_clk_gated(
> > >                                         entry->name_mclk,
> > >                                         entry->name_mux1, sccr_reg, s=
ccr_bit);
> > > +               }
> > >         } else {
> > >                 clks[clks_idx_pub] =3D mpc512x_clk_factor(
> > >                                 entry->name_mclk,
> > > =

> > > Local tests have shown that the extension solves the problem of
> > > how to satisfy the SoC's constraints on the MPC512x platform.
> > > The MSCAN clocks no longer need to get pre-enabled, instead they
> > > get setup and enabled only as the mscan(4) driver probes devices
> > > according to how it was instructed (device tree nodes).
> > > =

> > > What do you think?  Is the "shared gate" support in the common
> > > logic appropriate?  I'd rather not duplicate all of this code
> > > just to introduce the specific gate I need, while most of the
> > > logic is identical to the existing gate implementation.  The
> > > desire isn't to override the gate's operations, but to wrap them
> > > and to consult a counter in addition, while the register access
> > > still applies.
> =

> =

> virtually yours
> Gerhard Sittig
> -- =

> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-05 17:11                 ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-05 17:11 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gerhard Sittig (2013-08-03 07:39:56)
> [ we are strictly talking about clocks and source code again,
>   I have trimmed the CC: list to not spam the device tree ML or
>   subsystem maintainers ]
> 
> On Fri, Aug 02, 2013 at 16:30 -0700, Mike Turquette wrote:
> > 
> > Quoting Gerhard Sittig (2013-07-23 06:14:06)
> > > [ summary: "shared gate" support desirable? approach acceptable? ]
> > > 
> > > On Mon, Jul 22, 2013 at 14:14 +0200, Gerhard Sittig wrote:
> > > > 
> > > > this change implements a clock driver for the MPC512x PowerPC platform
> > > > which follows the COMMON_CLK approach and uses common clock drivers
> > > > shared with other platforms
> > > > 
> > > > [ ... ]
> > > > 
> > > > some of the clock items get pre-enabled in the clock driver to not have
> > > > them automatically disabled by the underlying clock subsystem because of
> > > > their being unused -- this approach is desirable because
> > > > [ ... ]
> > > > - some help introduce support for and migrate to the common
> > > >   infrastructure, while more appropriate support for specific hardware
> > > >   constraints isn't available yet (remaining changes are strictly
> > > >   internal to the clock driver and won't affect peripheral drivers)
> > > 
> > > This remark was related to the CAN clocks of the MPC512x SoC.
> > 
> > Gerhard,
> > 
> > Thanks for the patch (way far down below here). I'll check into it to
> > see if that implementation looks OK. It would be helpful if another
> > platform with shared gates could weigh in on whether the implementation
> > works for them.
> > 
> > Still, a shared gate solution is not a prerequisite for this series,
> > correct?
> 
> Well, the recent CAN driver related discussion suggested that I
> had a mental misconception there.  The need for "shared gates"
> was felt because of mixing up unrelated paths in the clock tree.
> But the MCLK subtree is for bitrate generation, while the BDLC
> gate is for register access into the peripheral controller.
> 
> Currently I'm investigating how I can cleanly tell those
> individual aspects apart.  Telling the gate for register access
> (in ARM speak often referred to as 'ipg') from the bitrate
> generation (the 'per' clock, or 'mclk' here) seems so much more
> appropriate.
> 
> After clean separation, and more testing to make sure nothing
> gets broken throughout the series, there will be v4.
> 
> 
> So "shared gate" support might have become obsolete for the
> MPC512x platform.  But if others need it, the outlined approach
> (patch below) may be viable.  The change to the common code is
> minimal.  The use in the platform's clock driver was kind of
> overengineered for the case of exactly one such gate, but this
> immediately makes it a working approach for several gates, if
> others need it.
> 
> I'll trim the motivation and just leave the suggested approach
> for "shared gates" here.  Feel free to drop it or to only
> resurrect it as the need may re-arise later.  So far nobody
> appears to have felt the need up to now ...

You can drop it. If your platform does not need it and nobody else has
said that they require shared gates then there is no reason to spend
more time on it.

Regards,
Mike

> 
> > > [ ... ]
> > > 
> > > The question now is how to correctly support the situation where
> > > a gate is shared between subtrees yet isn't really part of any
> > > path within the subtrees.  I really cannot find a single spot
> > > where to introduce the gate such that it's not duplicated.
> > > 
> > > The appropriate solution would not be to pre-enable those clocks,
> > > but to either introduce another gate clock type which supports a
> > > shared reference, or to add support for the shared reference to
> > > the existing gate code.
> > > 
> > > 
> > > I'd rather not duplicate most or all of the code of clk-gate.c,
> > > instead I looked into how to add "shared gate" support to the
> > > existing driver.
> > > 
> > > My question is whether the approach is acceptable.  It adds
> > > minimal overhead and shall be OK for the enable/disable path from
> > > a technical POV.  And it doesn't feel like too much of a stretch.
> > > But there may be non-technical reasons to reject the approach.
> > > I'd like to learn whether to follow that path before preparing
> > > another version of the patch series.
> > > 
> > > The diffs were taken with the '-w -b' options to demonstrate
> > > their essence and not drown it in whitespace changes.  The
> > > implementation assumes that the caller which registers the gate
> > > (the platform's clock driver) provides both the counter cell and
> > > the lock.  And that all gates with a "shared use counter" use the
> > > same lock (which is satisfied as they all get registered from the
> > > same spot in the platform's clock driver).
> > > 
> > > The CLK_IGNORE_UNUSED flag addresses a different problem.  The
> > > SoC has four MSCAN components, while two of them are enabled in
> > > the device tree (the other two are present but disabled).  So
> > > during probe two of the clocks get enabled.  After probe all
> > > unused clocks automatically get disabled (that's another two).
> > > So the "shared use counter" drops to zero although components are
> > > in use, because "disable, it's unused" isn't told from "disable
> > > after enable, regular use".  The flag would become obsolete if
> > > the common gate logic would implement a separate disable_unused()
> > > routine, but I guess this isn't necessary and the use of the flag
> > > is appropriate.
> > > 
> > > That the example use creates a field for just one counter is to
> > > better demonstrate the use and potential extension as need
> > > arises.  Reducing this to a mere integer variable would be a
> > > micro optimization.
> > > 
> > > 
> > > The extension of the existing clk_gate implementation:
> > > 
> > > --- a/drivers/clk/clk-gate.c
> > > +++ b/drivers/clk/clk-gate.c
> > > @@ -46,6 +46,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> > >         struct clk_gate *gate = to_clk_gate(hw);
> > >         int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
> > >         unsigned long flags = 0;
> > > +       int need_reg_access;
> > >         u32 reg;
> > >  
> > >         set ^= enable;
> > > @@ -53,6 +54,20 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> > >         if (gate->lock)
> > >                 spin_lock_irqsave(gate->lock, flags);
> > >  
> > > +       /*
> > > +        * if a "shared use counter" was specified, keep track of enable
> > > +        * and disable calls and only access hardware registers upon the
> > > +        * very first enable or very last disable call
> > > +        */
> > > +       if (!gate->share_count) {
> > > +               need_reg_access = 1;
> > > +       } else if (enable) {
> > > +               need_reg_access = (*gate->share_count)++ == 0;
> > > +       } else {
> > > +               need_reg_access = --(*gate->share_count) == 0;
> > > +       }
> > > +
> > > +       if (need_reg_access) {
> > >                 if (gate->flags & CLK_GATE_HIWORD_MASK) {
> > >                         reg = BIT(gate->bit_idx + 16);
> > >                         if (set)
> > > @@ -67,6 +82,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
> > >                 }
> > >  
> > >                 clk_writel(reg, gate->reg);
> > > +       }
> > >  
> > >         if (gate->lock)
> > >                 spin_unlock_irqrestore(gate->lock, flags);
> > > @@ -118,10 +134,11 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
> > >   * @clk_gate_flags: gate-specific flags for this clock
> > >   * @lock: shared register lock for this clock
> > >   */
> > > -struct clk *clk_register_gate(struct device *dev, const char *name,
> > > +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> > >                 const char *parent_name, unsigned long flags,
> > >                 void __iomem *reg, u8 bit_idx,
> > > -               u8 clk_gate_flags, spinlock_t *lock)
> > > +               u8 clk_gate_flags, spinlock_t *lock,
> > > +               int *share_count)
> > >  {
> > >         struct clk_gate *gate;
> > >         struct clk *clk;
> > > @@ -152,6 +169,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> > >         gate->bit_idx = bit_idx;
> > >         gate->flags = clk_gate_flags;
> > >         gate->lock = lock;
> > > +       gate->share_count = share_count;
> > >         gate->hw.init = &init;
> > >  
> > >         clk = clk_register(dev, &gate->hw);
> > > @@ -161,3 +179,14 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> > >  
> > >         return clk;
> > >  }
> > > +
> > > +struct clk *clk_register_gate(struct device *dev, const char *name,
> > > +               const char *parent_name, unsigned long flags,
> > > +               void __iomem *reg, u8 bit_idx,
> > > +               u8 clk_gate_flags, spinlock_t *lock)
> > > +{
> > > +
> > > +       return clk_register_gate_shared(dev, name, parent_name, flags,
> > > +                                       reg, bit_idx, clk_gate_flags,
> > > +                                       lock, NULL);
> > > +}
> > > --- a/include/linux/clk-provider.h
> > > +++ b/include/linux/clk-provider.h
> > > @@ -222,6 +222,7 @@ struct clk_gate {
> > >         u8              bit_idx;
> > >         u8              flags;
> > >         spinlock_t      *lock;
> > > +       int             *share_count;
> > >  };
> > >  
> > >  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> > > @@ -232,6 +233,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
> > >                 const char *parent_name, unsigned long flags,
> > >                 void __iomem *reg, u8 bit_idx,
> > >                 u8 clk_gate_flags, spinlock_t *lock);
> > > +struct clk *clk_register_gate_shared(struct device *dev, const char *name,
> > > +               const char *parent_name, unsigned long flags,
> > > +               void __iomem *reg, u8 bit_idx,
> > > +               u8 clk_gate_flags, spinlock_t *lock,
> > > +               int *share_count);
> > >  
> > >  struct clk_div_table {
> > >         unsigned int    val;
> > > 
> > > 
> > > How to use these shared gates:
> > > 
> > > --- a/arch/powerpc/platforms/512x/clock-commonclk.c
> > > +++ b/arch/powerpc/platforms/512x/clock-commonclk.c
> > > @@ -123,6 +123,39 @@ static inline struct clk *mpc512x_clk_gated(
> > >                                  reg, pos, 0, &clklock);
> > >  }
> > >  
> > > +enum mpc512x_clk_shared_gate_id_t {
> > > +       MPC512x_CLK_SHARED_GATE_MSCAN,
> > > +       MPC512x_CLK_SHARED_GATE_MAX,
> > > +};
> > > +
> > > +static int mpc512x_clk_gate_counters[MPC512x_CLK_SHARED_GATE_MAX];
> > > +
> > > +/*
> > > + * implementor's note:  since clk_gate items don't implement a separate
> > > + * .disable_unused() callback, their .disable() routine gets called and
> > > + * "disable the clock as we can't see it's in use" cannot be told from
> > > + * "regular disable, count these events please"
> > > + *
> > > + * passing the CLK_IGNORE_UNUSED flag upon clock creation will suppress
> > > + * the "disable, unused" call, so use counts won't get unbalanced, the
> > > + * clock either never got enabled and thus need not get disabled, or
> > > + * part of the hardware got enabled while disabling the other part isn't
> > > + * wanted
> > > + */
> > > +static inline struct clk *mpc512x_clk_gated_shared(
> > > +       const char *name, const char *parent_name,
> > > +       u32 __iomem *reg, u8 pos,
> > > +       enum mpc512x_clk_shared_gate_id_t share_id)
> > > +{
> > > +       int clkflags;
> > > +
> > > +       clkflags = CLK_SET_RATE_PARENT;
> > > +       clkflags |= CLK_IGNORE_UNUSED;
> > > +       return clk_register_gate_shared(NULL, name, parent_name, clkflags,
> > > +                                       reg, pos, 0, &clklock,
> > > +                                       &mpc512x_clk_gate_counters[share_id]);
> > > +}
> > > +
> > >  static inline struct clk *mpc512x_clk_muxed(const char *name,
> > >         const char **parent_names, int parent_count,
> > >         u32 __iomem *reg, u8 pos, u8 len)
> > > @@ -520,9 +553,16 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
> > >                                 1, 1);
> > >         }
> > >         if (sccr_reg) {
> > > +               if (entry->type == MCLK_TYPE_MSCAN) {
> > > +                       clks[clks_idx_pub] = mpc512x_clk_gated_shared(
> > > +                                       entry->name_mclk,
> > > +                                       entry->name_mux1, sccr_reg, sccr_bit,
> > > +                                       MPC512x_CLK_SHARED_GATE_MSCAN);
> > > +               } else {
> > >                         clks[clks_idx_pub] = mpc512x_clk_gated(
> > >                                         entry->name_mclk,
> > >                                         entry->name_mux1, sccr_reg, sccr_bit);
> > > +               }
> > >         } else {
> > >                 clks[clks_idx_pub] = mpc512x_clk_factor(
> > >                                 entry->name_mclk,
> > > 
> > > Local tests have shown that the extension solves the problem of
> > > how to satisfy the SoC's constraints on the MPC512x platform.
> > > The MSCAN clocks no longer need to get pre-enabled, instead they
> > > get setup and enabled only as the mscan(4) driver probes devices
> > > according to how it was instructed (device tree nodes).
> > > 
> > > What do you think?  Is the "shared gate" support in the common
> > > logic appropriate?  I'd rather not duplicate all of this code
> > > just to introduce the specific gate I need, while most of the
> > > logic is identical to the existing gate implementation.  The
> > > desire isn't to override the gate's operations, but to wrap them
> > > and to consult a counter in addition, while the register access
> > > still applies.
> 
> 
> virtually yours
> Gerhard Sittig
> -- 
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-07-22 12:14       ` Gerhard Sittig
@ 2013-08-06 20:43         ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this series
- fixes several drivers that are used in the MPC512x platform (UART,
  SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
  handle clocks (appropriately acquire and setup them, hold references
  during use, release clocks after use)
- introduces support for the common clock framework (CCF, COMMON_CLK
  Kconfig option) in the PowerPC based MPC512x platform, which brings
  device tree based clock lookup as well

although the series does touch several subsystems -- tty (serial), spi,
net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
the patches are strictly clock related or trivial

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #431: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:334:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 807 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v4:
- remove explicit devm_clk_put() calls as these will occur implicitly
  upon device release (01/31, 02/31, 03/31, 04/31, 05/31, 06/31, 08/31,
  09/31, 27/31)
- split the PSC (SPI, UART) and MSCAN (CAN) related MCLK subtrees into
  separate 'ipg'/'bdlc' gated clock items for register access as well as
  the 'mclk' clock subtrees that apply to bitrates -- this eliminates
  the need for "shared gates" and further reduces clock pre-enable
  workarounds (11/31, 15/31, 17/31, 18/31, 20/31, 21/31, 22/31, 27/31)
- further adjust the CAN clock driver, fix an incomplete error code path
  in the network device open callback (11/31), only enable the bitrate
  clock when the network device is open (27/31)
- remove debug output in the clock tree setup when introducing the
  platform's clock driver, there already is CONFIG_COMMON_CLK_DEBUG to
  retrieve more complete information (17/31)
- remove an "enums don't work here" comment in the dt-bindings header
  file (15/31)
- reword and update commit messages (body and/or subject) where
  appropriate (03/31, 04/31, 05/31, 06/31, 08/31, 09/31, 11/31, 12/31,
  17/31, 20/31, 21/31, 22/31, 27/31, 28/31, 30/31, 31/31)
- add 'Reviewed-By' attributes which were received for v3

changes in v3:
- rebase the series against v3.11-rc2
- re-ordered the series to first address all general clock handling
  concerns in existing drivers, before introducing common clock support
  in the platform's clock driver
- slightly rework the SPI (01/31), UART (02/31), and PSC FIFO (23/31)
  clock handling in comparison to v2 which introduced those fixes
  (devm_{get,put}_clk() calls, fewer goto labels in error paths)
- fix and improve clock handling (balance allocation and release of
  clocks, check for errors during setup) in all of the other drivers
  which this series has touched before in naive ways: USB (03/31), NAND
  flash (04/31), video capture (05/31), I2C (06/31), ethernet (08/31),
  PCI (09/31), CAN (11/31)
- silence a build warning in the ethernet driver (07/31)
- eliminate all PPC_CLOCK references, use 'per' clock names for NAND
  flash (25/31) and VIU (26/31) as well
- unbreak CAN operation for the period between introducing common clock
  support in the platform's clock driver and introducing common clock
  support in the CAN peripheral driver as well as providing clock specs
  in the device tree (provide clkdev aliases for SYS and REF)
- improve common clock support for CAN (devm_{get,put}_clk() calls,
  check enable() errors, keep a reference to used clocks, disable and
  put clocks after use)
- reworded several commit messages to better reflect the kind of change
  and because fixes were applied before adding common infrastructure
  support
- point to individual numbered patches of the series in the list of
  changes for v2 as well

changes in v2:
- cleanup of the UART (02/24) and SPI (01/24) clock handling before the
  introduction of common clock support for the platform, as incomplete
  clock handling becomes fatal or more dangerous later (which in turn
  changes the context of the "device tree lookup only" followup patch
  later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced, which have become 11-14/24 now)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration (09/24)
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine (14/24)
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call (13/24)


Gerhard Sittig (31):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  USB: fsl-mph-dr-of: cleanup clock API use
  mtd: mpc5121_nfc: cleanup clock API use
  [media] fsl-viu: cleanup clock API use
  i2c: mpc: cleanup clock API use
  fs_enet: silence a build warning (unused variable)
  fs_enet: cleanup clock API use
  powerpc/fsl-pci: improve clock API use
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: improve clock API use
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  clk: mpc512x: don't pre-enable FEC and I2C clocks
  spi: mpc512x: switch to CCF names in clock lookup
  serial: mpc512x: switch to CCF names in clock lookup
  clk: mpc512x: remove PSC (UART, SPI) compat workarounds
  serial: mpc512x: setup the PSC FIFO clock as well
  USB: fsl-mph-dr-of: remove now obsolete clock lookup name
  mtd: mpc5121_nfc: remove now obsolete clock lookup name
  [media] fsl-viu: remove now obsolete clock lookup name
  net: can: mscan: add common clock support for mpc512x
  powerpc/mpc512x: improve DIU related clock setup
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove non-CCF code for MPC512x
  clk: mpc512x: remove remaining migration workarounds

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |  110 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  716 +++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 --------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   22 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |   24 +
 drivers/media/platform/fsl-viu.c                   |   23 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |   21 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  281 +++++---
 drivers/net/can/mscan/mscan.c                      |   27 +-
 drivers/net/can/mscan/mscan.h                      |    3 +
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   21 +-
 drivers/spi/spi-mpc512x-psc.c                      |   60 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  179 ++++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   27 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   69 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 28 files changed, 1534 insertions(+), 1058 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc4-00031-gb38a1de ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      6           6            320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk   0           0            80000000
          mscan3-mux0           0           0            320000000
             mscan3-en0         0           0            320000000
                mscan3_mclk_div 0           0            80000000
                   mscan3_mclk  0           0            80000000
          mscan2-mux0           0           0            320000000
             mscan2-en0         0           0            320000000
                mscan2_mclk_div 0           0            80000000
                   mscan2_mclk  0           0            80000000
          mscan1-mux0           0           0            320000000
             mscan1-en0         0           0            320000000
                mscan1_mclk_div 0           0            16000000
                   mscan1_mclk  0           0            16000000
          mscan0-mux0           0           0            320000000
             mscan0-en0         0           0            320000000
                mscan0_mclk_div 0           0            16000000
                   mscan0_mclk  0           0            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk   0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk   0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk    0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk    0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk    1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk    0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk    1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk    1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk    2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk    0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk    0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk    0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                12          12           80000000
                spdif           0           0            80000000
                bdlc            2           2            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                psc11           0           0            80000000
                psc10           0           0            80000000
                psc9            0           0            80000000
                psc8            0           0            80000000
                psc7            1           1            80000000
                psc6            0           0            80000000
                psc5            1           1            80000000
                psc4            1           1            80000000
                psc3            1           1            80000000
                psc2            0           0            80000000
                psc1            0           0            80000000
                psc0            0           0            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-08-06 20:43         ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

this series
- fixes several drivers that are used in the MPC512x platform (UART,
  SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
  handle clocks (appropriately acquire and setup them, hold references
  during use, release clocks after use)
- introduces support for the common clock framework (CCF, COMMON_CLK
  Kconfig option) in the PowerPC based MPC512x platform, which brings
  device tree based clock lookup as well

although the series does touch several subsystems -- tty (serial), spi,
net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
the patches are strictly clock related or trivial

it appears most appropriate to take this series through either the clk
or the powerpc trees after it has passed review and other subsystem
maintainers ACKed the clock setup related driver modifications

the series passes 'checkpatch.pl --strict' except for one warning which
cannot get resolved, since that either breaks compilation (the data type
is preset by the clk-provider.h API) or requires a cast which shadows
real mismatches:

  WARNING: static const char * array should probably be static const char * const
  #431: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:334:
  +static const char *parent_names_mux0[] = {

  total: 0 errors, 1 warnings, 0 checks, 807 lines checked

each step in the series was build and run tested (with a display that is
attached to the DIU as well as SPI, with an SPI attached NOR flash, with
multiple UART ports such that one is not the boot console, with EEPROMs
attached to I2C, with an SD card, booting from network)


changes in v4:
- remove explicit devm_clk_put() calls as these will occur implicitly
  upon device release (01/31, 02/31, 03/31, 04/31, 05/31, 06/31, 08/31,
  09/31, 27/31)
- split the PSC (SPI, UART) and MSCAN (CAN) related MCLK subtrees into
  separate 'ipg'/'bdlc' gated clock items for register access as well as
  the 'mclk' clock subtrees that apply to bitrates -- this eliminates
  the need for "shared gates" and further reduces clock pre-enable
  workarounds (11/31, 15/31, 17/31, 18/31, 20/31, 21/31, 22/31, 27/31)
- further adjust the CAN clock driver, fix an incomplete error code path
  in the network device open callback (11/31), only enable the bitrate
  clock when the network device is open (27/31)
- remove debug output in the clock tree setup when introducing the
  platform's clock driver, there already is CONFIG_COMMON_CLK_DEBUG to
  retrieve more complete information (17/31)
- remove an "enums don't work here" comment in the dt-bindings header
  file (15/31)
- reword and update commit messages (body and/or subject) where
  appropriate (03/31, 04/31, 05/31, 06/31, 08/31, 09/31, 11/31, 12/31,
  17/31, 20/31, 21/31, 22/31, 27/31, 28/31, 30/31, 31/31)
- add 'Reviewed-By' attributes which were received for v3

changes in v3:
- rebase the series against v3.11-rc2
- re-ordered the series to first address all general clock handling
  concerns in existing drivers, before introducing common clock support
  in the platform's clock driver
- slightly rework the SPI (01/31), UART (02/31), and PSC FIFO (23/31)
  clock handling in comparison to v2 which introduced those fixes
  (devm_{get,put}_clk() calls, fewer goto labels in error paths)
- fix and improve clock handling (balance allocation and release of
  clocks, check for errors during setup) in all of the other drivers
  which this series has touched before in naive ways: USB (03/31), NAND
  flash (04/31), video capture (05/31), I2C (06/31), ethernet (08/31),
  PCI (09/31), CAN (11/31)
- silence a build warning in the ethernet driver (07/31)
- eliminate all PPC_CLOCK references, use 'per' clock names for NAND
  flash (25/31) and VIU (26/31) as well
- unbreak CAN operation for the period between introducing common clock
  support in the platform's clock driver and introducing common clock
  support in the CAN peripheral driver as well as providing clock specs
  in the device tree (provide clkdev aliases for SYS and REF)
- improve common clock support for CAN (devm_{get,put}_clk() calls,
  check enable() errors, keep a reference to used clocks, disable and
  put clocks after use)
- reworded several commit messages to better reflect the kind of change
  and because fixes were applied before adding common infrastructure
  support
- point to individual numbered patches of the series in the list of
  changes for v2 as well

changes in v2:
- cleanup of the UART (02/24) and SPI (01/24) clock handling before the
  introduction of common clock support for the platform, as incomplete
  clock handling becomes fatal or more dangerous later (which in turn
  changes the context of the "device tree lookup only" followup patch
  later)
- reordered the sequence of patches to keep the serial communication
  related parts together (UART, SPI, and PSC FIFO changes after common
  clock support was introduced, which have become 11-14/24 now)
- updated commit messages for the clock API use cleanup in the serial
  communication drivers, updated comments and reworded commit messages
  in the core clock driver to expand on the pre-enable workaround and
  clkdev registration (09/24)
- keep a reference to the PSC FIFO clock during use instead of looking
  up the clock again in the uninit() routine (14/24)
- remove the clkdev.h header file inclusion directive with the removal
  of the clkdev registration call (13/24)


Gerhard Sittig (31):
  spi: mpc512x: cleanup clock API use
  serial: mpc512x: cleanup clock API use
  USB: fsl-mph-dr-of: cleanup clock API use
  mtd: mpc5121_nfc: cleanup clock API use
  [media] fsl-viu: cleanup clock API use
  i2c: mpc: cleanup clock API use
  fs_enet: silence a build warning (unused variable)
  fs_enet: cleanup clock API use
  powerpc/fsl-pci: improve clock API use
  net: can: mscan: add a comment on reg to idx mapping
  net: can: mscan: improve clock API use
  powerpc: mpc512x: array decl for MCLK registers in CCM
  clk: wrap I/O access for improved portability
  dts: mpc512x: prepare for preprocessor support
  dts: mpc512x: introduce dt-bindings/clock/ header
  dts: mpc512x: add clock related device tree specs
  clk: mpc512x: introduce COMMON_CLK for MPC512x
  dts: mpc512x: add clock specs for client lookups
  clk: mpc512x: don't pre-enable FEC and I2C clocks
  spi: mpc512x: switch to CCF names in clock lookup
  serial: mpc512x: switch to CCF names in clock lookup
  clk: mpc512x: remove PSC (UART, SPI) compat workarounds
  serial: mpc512x: setup the PSC FIFO clock as well
  USB: fsl-mph-dr-of: remove now obsolete clock lookup name
  mtd: mpc5121_nfc: remove now obsolete clock lookup name
  [media] fsl-viu: remove now obsolete clock lookup name
  net: can: mscan: add common clock support for mpc512x
  powerpc/mpc512x: improve DIU related clock setup
  clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  net: can: mscan: remove non-CCF code for MPC512x
  clk: mpc512x: remove remaining migration workarounds

 arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
 arch/powerpc/boot/dts/include/dt-bindings          |    1 +
 arch/powerpc/boot/dts/mpc5121.dtsi                 |  110 ++-
 arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
 arch/powerpc/include/asm/mpc5121.h                 |   18 +-
 arch/powerpc/platforms/512x/Kconfig                |    2 +-
 arch/powerpc/platforms/512x/Makefile               |    3 +-
 arch/powerpc/platforms/512x/clock-commonclk.c      |  716 +++++++++++++++++++
 arch/powerpc/platforms/512x/clock.c                |  753 --------------------
 arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   22 +
 drivers/clk/clk-divider.c                          |    6 +-
 drivers/clk/clk-gate.c                             |    6 +-
 drivers/clk/clk-mux.c                              |    6 +-
 drivers/i2c/busses/i2c-mpc.c                       |   24 +
 drivers/media/platform/fsl-viu.c                   |   23 +-
 drivers/mtd/nand/mpc5121_nfc.c                     |   21 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  281 +++++---
 drivers/net/can/mscan/mscan.c                      |   27 +-
 drivers/net/can/mscan/mscan.h                      |    3 +
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   21 +-
 drivers/spi/spi-mpc512x-psc.c                      |   60 +-
 drivers/tty/serial/mpc52xx_uart.c                  |  179 ++++-
 drivers/usb/host/fsl-mph-dr-of.c                   |   27 +-
 include/dt-bindings/clock/mpc512x-clock.h          |   69 ++
 include/linux/clk-provider.h                       |   33 +
 include/linux/fs_enet_pd.h                         |    3 +
 28 files changed, 1534 insertions(+), 1058 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
 delete mode 100644 arch/powerpc/platforms/512x/clock.c
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


# uname -srm
Linux 3.11.0-rc4-00031-gb38a1de ppc
# cat /sys/kernel/debug/clk/clk_summary
   clock                        enable_cnt  prepare_cnt  rate
---------------------------------------------------------------------
 ac97                           0           0            24567000
 spdif_rx_in                    0           0            0
 spdif_tx_in                    0           0            0
 psc_mclk_in                    0           0            25000000
 dummy                          1           1            0
 osc                            1           1            25000000
    ref                         1           1            25000000
       sys                      6           6            320000000
          spdif-mux0            0           0            320000000
             spdif-en0          0           0            320000000
                spdif_mclk_div  0           0            80000000
                   spdif_mclk   0           0            80000000
          mscan3-mux0           0           0            320000000
             mscan3-en0         0           0            320000000
                mscan3_mclk_div 0           0            80000000
                   mscan3_mclk  0           0            80000000
          mscan2-mux0           0           0            320000000
             mscan2-en0         0           0            320000000
                mscan2_mclk_div 0           0            80000000
                   mscan2_mclk  0           0            80000000
          mscan1-mux0           0           0            320000000
             mscan1-en0         0           0            320000000
                mscan1_mclk_div 0           0            16000000
                   mscan1_mclk  0           0            16000000
          mscan0-mux0           0           0            320000000
             mscan0-en0         0           0            320000000
                mscan0_mclk_div 0           0            16000000
                   mscan0_mclk  0           0            16000000
          psc11-mux0            0           0            320000000
             psc11-en0          0           0            320000000
                psc11_mclk_div  0           0            80000000
                   psc11_mclk   0           0            80000000
          psc10-mux0            0           0            320000000
             psc10-en0          0           0            320000000
                psc10_mclk_div  0           0            80000000
                   psc10_mclk   0           0            80000000
          psc9-mux0             0           0            320000000
             psc9-en0           0           0            320000000
                psc9_mclk_div   0           0            80000000
                   psc9_mclk    0           0            80000000
          psc8-mux0             0           0            320000000
             psc8-en0           0           0            320000000
                psc8_mclk_div   0           0            80000000
                   psc8_mclk    0           0            80000000
          psc7-mux0             1           1            320000000
             psc7-en0           1           1            320000000
                psc7_mclk_div   1           1            80000000
                   psc7_mclk    1           1            80000000
          psc6-mux0             0           0            320000000
             psc6-en0           0           0            320000000
                psc6_mclk_div   0           0            80000000
                   psc6_mclk    0           0            80000000
          psc5-mux0             1           1            320000000
             psc5-en0           1           1            320000000
                psc5_mclk_div   1           1            80000000
                   psc5_mclk    1           1            80000000
          psc4-mux0             1           1            320000000
             psc4-en0           1           1            320000000
                psc4_mclk_div   1           1            80000000
                   psc4_mclk    1           1            80000000
          psc3-mux0             1           1            320000000
             psc3-en0           1           1            320000000
                psc3_mclk_div   1           1            80000000
                   psc3_mclk    2           2            80000000
          psc2-mux0             0           0            320000000
             psc2-en0           0           0            320000000
                psc2_mclk_div   0           0            80000000
                   psc2_mclk    0           0            80000000
          psc1-mux0             0           0            320000000
             psc1-en0           0           0            320000000
                psc1_mclk_div   0           0            80000000
                   psc1_mclk    0           0            80000000
          psc0-mux0             0           0            320000000
             psc0-en0           0           0            320000000
                psc0_mclk_div   0           0            80000000
                   psc0_mclk    0           0            80000000
          ddr-ug                1           1            160000000
             ddr                1           1            160000000
          csb                   4           4            160000000
             viu                0           0            160000000
             iim                0           0            160000000
             usb2               0           0            160000000
             usb1               0           0            160000000
             axe                0           0            160000000
             pci-ug             0           0            26666666
                pci             0           0            26666666
             mbx-bus-ug         0           0            80000000
                mbx-bus         0           0            80000000
                mbx-ug          0           0            80000000
                   mbx          0           0            80000000
                   mbx-3d-ug    0           0            80000000
                      mbx-3d    0           0            80000000
             e300               1           1            400000000
             diu-x4             1           1            640000000
                diu-ug          1           1            2509803
                   diu          2           2            2509803
             sdhc-x4            1           1            640000000
                sdhc-ug         1           1            53333333
                   sdhc-2       0           0            53333333
                   sdhc         1           1            53333333
             ips                12          12           80000000
                spdif           0           0            80000000
                bdlc            2           2            80000000
                i2c             3           3            80000000
                mem             1           1            80000000
                fec             1           1            80000000
                sata            0           0            80000000
                psc-fifo        1           1            80000000
                psc11           0           0            80000000
                psc10           0           0            80000000
                psc9            0           0            80000000
                psc8            0           0            80000000
                psc7            1           1            80000000
                psc6            0           0            80000000
                psc5            1           1            80000000
                psc4            1           1            80000000
                psc3            1           1            80000000
                psc2            0           0            80000000
                psc1            0           0            80000000
                psc0            0           0            80000000
                pata            0           0            80000000
                lpc-ug          1           1            40000000
                   lpc          1           1            40000000
                nfc-ug          0           0            40000000
                   nfc          0           0            40000000

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   48 +++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..85581f3 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
+	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +519,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	clk = devm_clk_get(dev, clk_name);
+	if (IS_ERR(clk))
+		goto free_irq;
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		goto free_irq;
+	mps->clk_mclk = clk;
+	mps->mclk_rate = clk_get_rate(clk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	return ret;
 
+free_clock:
+	clk_disable_unprepare(mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

cleanup the MPC512x SoC's SPI master's use of the clock API
- get, prepare, and enable the MCLK during probe; disable, unprepare and
  put the MCLK upon remove; hold a reference to the clock over the
  period of use
- fetch MCLK rate (reference) once during probe and slightly reword BCLK
  (bitrate) determination to reduce redundancy as well as to not exceed
  the maximum text line length
- 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

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   48 +++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 29fce6a..85581f3 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
-	u32 mclk;
+	struct clk *clk_mclk;
+	u32 mclk_rate;
 
 	struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
 	sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = cs->speed_hz;
+	if (!speed)
+		speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
 	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
 	u32 sicr;
 	u32 ccr;
+	int speed;
 	u16 bclkdiv;
 
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
 	/* Reset the PSC into a known state */
 	out_8(&psc->command, MPC52xx_PSC_RST_RX);
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	ccr = in_be32(&psc->ccr);
 	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	speed = 1000000;	/* default 1MHz */
+	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
 	out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
 	mps->bits_per_word = 8;
 
-	return ret;
+	return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -479,6 +474,9 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
+	int psc_num;
+	char clk_name[16];
+	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
 	if (master == NULL)
@@ -521,16 +519,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
+	psc_num = master->bus_num;
+	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+	clk = devm_clk_get(dev, clk_name);
+	if (IS_ERR(clk))
+		goto free_irq;
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		goto free_irq;
+	mps->clk_mclk = clk;
+	mps->mclk_rate = clk_get_rate(clk);
+
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_irq;
+		goto free_clock;
 
 	return ret;
 
+free_clock:
+	clk_disable_unprepare(mps->clk_mclk);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
 	spi_unregister_master(master);
+	clk_disable_unprepare(mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 02/31] serial: mpc512x: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

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 <gsi@denx.de>
---
 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 *port, struct device_node *np)
@@ -873,7 +917,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +952,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1214,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1241,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 02/31] serial: mpc512x: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

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 <gsi@denx.de>
---
 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 *port, struct device_node *np)
@@ -873,7 +917,9 @@ static struct psc_ops mpc5125_psc_ops = {
 	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
 	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
 	.set_baudrate = mpc5125_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -906,7 +952,9 @@ static struct psc_ops mpc512x_psc_ops = {
 	.cw_disable_ints = mpc512x_psc_cw_disable_ints,
 	.cw_restore_ints = mpc512x_psc_cw_restore_ints,
 	.set_baudrate = mpc512x_psc_set_baudrate,
-	.clock = mpc512x_psc_clock,
+	.clock_alloc = mpc512x_psc_alloc_clock,
+	.clock_relse = mpc512x_psc_relse_clock,
+	.clock = mpc512x_psc_endis_clock,
 	.fifoc_init = mpc512x_psc_fifoc_init,
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
@@ -1166,6 +1214,9 @@ mpc52xx_uart_type(struct uart_port *port)
 static void
 mpc52xx_uart_release_port(struct uart_port *port)
 {
+	if (psc_ops->clock_relse)
+		psc_ops->clock_relse(port);
+
 	/* remapped by us ? */
 	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
@@ -1190,11 +1241,24 @@ mpc52xx_uart_request_port(struct uart_port *port)
 	err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
 			"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
 
-	if (err && (port->flags & UPF_IOREMAP)) {
+	if (err)
+		goto out_membase;
+
+	if (psc_ops->clock_alloc) {
+		err = psc_ops->clock_alloc(port);
+		if (err)
+			goto out_mapregion;
+	}
+
+	return 0;
+
+out_mapregion:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+out_membase:
+	if (port->flags & UPF_IOREMAP) {
 		iounmap(port->membase);
 		port->membase = NULL;
 	}
-
 	return err;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 03/31] USB: fsl-mph-dr-of: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

use devm_get_clk() for automatic put upon device close, check for and
propagate errors when enabling clocks, must prepare clocks before they
can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..b8a1866 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,6 +260,7 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
+	int err;
 	char clk_name[10];
 	int base, clk_num;
 
@@ -272,13 +273,16 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 		return -ENODEV;
 
 	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, clk_name);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -302,10 +306,8 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 
 	pdata->regs = NULL;
 
-	if (pdata->clk) {
-		clk_disable(pdata->clk);
-		clk_put(pdata->clk);
-	}
+	if (pdata->clk)
+		clk_disable_unprepare(pdata->clk);
 }
 
 static struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 03/31] USB: fsl-mph-dr-of: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

use devm_get_clk() for automatic put upon device close, check for and
propagate errors when enabling clocks, must prepare clocks before they
can get enabled, unprepare after disable

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/usb/host/fsl-mph-dr-of.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..b8a1866 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -260,6 +260,7 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
+	int err;
 	char clk_name[10];
 	int base, clk_num;
 
@@ -272,13 +273,16 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 		return -ENODEV;
 
 	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, clk_name);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
 	}
-
-	clk_enable(clk);
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable clk\n");
+		return err;
+	}
 	pdata->clk = clk;
 
 	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
@@ -302,10 +306,8 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
 
 	pdata->regs = NULL;
 
-	if (pdata->clk) {
-		clk_disable(pdata->clk);
-		clk_put(pdata->clk);
-	}
+	if (pdata->clk)
+		clk_disable_unprepare(pdata->clk);
 }
 
 static struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 04/31] mtd: mpc5121_nfc: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

use devm_clk_get() for automatic put after device close, check for and
propagate errors when enabling clocks, need to prepare clocks before
they can get enabled, adjust error code paths to correctly balance
get/put and prepare/unprepare and enable/disable calls

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |   21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..3c60a00 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -617,10 +617,8 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct nand_chip *chip = mtd->priv;
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
-	if (prv->clk) {
-		clk_disable(prv->clk);
-		clk_put(prv->clk);
-	}
+	if (prv->clk)
+		clk_disable_unprepare(prv->clk);
 
 	if (prv->csreg)
 		iounmap(prv->csreg);
@@ -629,6 +627,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
+	struct clk *clk;
 	struct device *dev = &op->dev;
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
@@ -730,14 +729,18 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	prv->clk = clk_get(dev, "nfc_clk");
-	if (IS_ERR(prv->clk)) {
+	clk = devm_clk_get(dev, "nfc_clk");
+	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
-		retval = PTR_ERR(prv->clk);
+		retval = PTR_ERR(clk);
 		goto error;
 	}
-
-	clk_enable(prv->clk);
+	retval = clk_prepare_enable(clk);
+	if (retval) {
+		dev_err(dev, "Unable to enable NFC clock!\n");
+		goto error;
+	}
+	prv->clk = clk;
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 04/31] mtd: mpc5121_nfc: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

use devm_clk_get() for automatic put after device close, check for and
propagate errors when enabling clocks, need to prepare clocks before
they can get enabled, adjust error code paths to correctly balance
get/put and prepare/unprepare and enable/disable calls

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/mtd/nand/mpc5121_nfc.c |   21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c9cdcb..3c60a00 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -617,10 +617,8 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 	struct nand_chip *chip = mtd->priv;
 	struct mpc5121_nfc_prv *prv = chip->priv;
 
-	if (prv->clk) {
-		clk_disable(prv->clk);
-		clk_put(prv->clk);
-	}
+	if (prv->clk)
+		clk_disable_unprepare(prv->clk);
 
 	if (prv->csreg)
 		iounmap(prv->csreg);
@@ -629,6 +627,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
+	struct clk *clk;
 	struct device *dev = &op->dev;
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
@@ -730,14 +729,18 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	prv->clk = clk_get(dev, "nfc_clk");
-	if (IS_ERR(prv->clk)) {
+	clk = devm_clk_get(dev, "nfc_clk");
+	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
-		retval = PTR_ERR(prv->clk);
+		retval = PTR_ERR(clk);
 		goto error;
 	}
-
-	clk_enable(prv->clk);
+	retval = clk_prepare_enable(clk);
+	if (retval) {
+		dev_err(dev, "Unable to enable NFC clock!\n");
+		goto error;
+	}
+	prv->clk = clk;
 
 	/* Reset NAND Flash controller */
 	nfc_set(mtd, NFC_CONFIG1, NFC_RESET);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 05/31] [media] fsl-viu: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

use devm_clk_get() for automatic put after device close, check for and
propagate errors when enabling clocks, need to prepare clocks before
they can get enabled, adjust code paths to correctly balance get/put and
prepare/unprepare and enable/disable calls

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..fe9898c 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1485,6 +1485,7 @@ static int viu_of_probe(struct platform_device *op)
 	struct viu_reg __iomem *viu_regs;
 	struct i2c_adapter *ad;
 	int ret, viu_irq;
+	struct clk *clk;
 
 	ret = of_address_to_resource(op->dev.of_node, 0, &r);
 	if (ret) {
@@ -1577,14 +1578,18 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	viu_dev->clk = clk_get(&op->dev, "viu_clk");
-	if (IS_ERR(viu_dev->clk)) {
-		dev_err(&op->dev, "failed to find the clock module!\n");
-		ret = -ENODEV;
+	clk = devm_clk_get(&op->dev, "viu_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&op->dev, "failed to lookup the clock!\n");
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
 	}
+	viu_dev->clk = clk;
 
 	/* reset VIU module */
 	viu_reset(viu_dev->vr);
@@ -1602,8 +1607,7 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
-	clk_put(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
 err_vdev:
@@ -1626,8 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
+	clk_disable_unprepare(dev->clk);
 
 	video_unregister_device(dev->vdev);
 	i2c_put_adapter(client->adapter);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 05/31] [media] fsl-viu: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

use devm_clk_get() for automatic put after device close, check for and
propagate errors when enabling clocks, need to prepare clocks before
they can get enabled, adjust code paths to correctly balance get/put and
prepare/unprepare and enable/disable calls

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/media/platform/fsl-viu.c |   23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 221ec42..fe9898c 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1485,6 +1485,7 @@ static int viu_of_probe(struct platform_device *op)
 	struct viu_reg __iomem *viu_regs;
 	struct i2c_adapter *ad;
 	int ret, viu_irq;
+	struct clk *clk;
 
 	ret = of_address_to_resource(op->dev.of_node, 0, &r);
 	if (ret) {
@@ -1577,14 +1578,18 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	viu_dev->clk = clk_get(&op->dev, "viu_clk");
-	if (IS_ERR(viu_dev->clk)) {
-		dev_err(&op->dev, "failed to find the clock module!\n");
-		ret = -ENODEV;
+	clk = devm_clk_get(&op->dev, "viu_clk");
+	if (IS_ERR(clk)) {
+		dev_err(&op->dev, "failed to lookup the clock!\n");
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&op->dev, "failed to enable the clock!\n");
 		goto err_clk;
-	} else {
-		clk_enable(viu_dev->clk);
 	}
+	viu_dev->clk = clk;
 
 	/* reset VIU module */
 	viu_reset(viu_dev->vr);
@@ -1602,8 +1607,7 @@ static int viu_of_probe(struct platform_device *op)
 	return ret;
 
 err_irq:
-	clk_disable(viu_dev->clk);
-	clk_put(viu_dev->clk);
+	clk_disable_unprepare(viu_dev->clk);
 err_clk:
 	video_unregister_device(viu_dev->vdev);
 err_vdev:
@@ -1626,8 +1630,7 @@ static int viu_of_remove(struct platform_device *op)
 	free_irq(dev->irq, (void *)dev);
 	irq_dispose_mapping(dev->irq);
 
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
+	clk_disable_unprepare(dev->clk);
 
 	video_unregister_device(dev->vdev);
 	i2c_put_adapter(client->adapter);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 06/31] i2c: mpc: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the MPC I2C driver get, prepare and enable the peripheral clock
during probe ('per' for access to the peripheral's registers); disable
and unprepare the clock upon remove(), put is done by the devm approach;
hold a reference to the clock over the period of use

clock lookup is non-fatal in this implementation as not all platforms
may provide clock specs in their device tree, but enable errors for
specified clocks are considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/i2c/busses/i2c-mpc.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..4b00dd0 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -67,6 +68,7 @@ struct mpc_i2c {
 #ifdef CONFIG_PM
 	u8 fdr, dfsrr;
 #endif
+	struct clk *clk_per;
 };
 
 struct mpc_i2c_divider {
@@ -623,6 +625,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
+	struct clk *clk;
+	int err;
 
 	match = of_match_device(mpc_i2c_of_match, &op->dev);
 	if (!match)
@@ -653,6 +657,21 @@ static int fsl_i2c_probe(struct platform_device *op)
 		}
 	}
 
+	/*
+	 * enable clock for the I2C peripheral (non fatal),
+	 * keep a reference upon successful allocation
+	 */
+	clk = devm_clk_get(&op->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			dev_err(&op->dev, "failed to enable clock\n");
+			goto fail_request;
+		} else {
+			i2c->clk_per = clk;
+		}
+	}
+
 	if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) {
 		clock = MPC_I2C_CLOCK_PRESERVE;
 	} else {
@@ -696,6 +715,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	return result;
 
  fail_add:
+	if (i2c->clk_per)
+		clk_disable_unprepare(i2c->clk_per);
 	free_irq(i2c->irq, i2c);
  fail_request:
 	irq_dispose_mapping(i2c->irq);
@@ -711,6 +732,9 @@ static int fsl_i2c_remove(struct platform_device *op)
 
 	i2c_del_adapter(&i2c->adap);
 
+	if (i2c->clk_per)
+		clk_disable_unprepare(i2c->clk_per);
+
 	if (i2c->irq)
 		free_irq(i2c->irq, i2c);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 06/31] i2c: mpc: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

make the MPC I2C driver get, prepare and enable the peripheral clock
during probe ('per' for access to the peripheral's registers); disable
and unprepare the clock upon remove(), put is done by the devm approach;
hold a reference to the clock over the period of use

clock lookup is non-fatal in this implementation as not all platforms
may provide clock specs in their device tree, but enable errors for
specified clocks are considered fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/i2c/busses/i2c-mpc.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 7607dc0..4b00dd0 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -21,6 +21,7 @@
 #include <linux/of_i2c.h>
 #include <linux/slab.h>
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
@@ -67,6 +68,7 @@ struct mpc_i2c {
 #ifdef CONFIG_PM
 	u8 fdr, dfsrr;
 #endif
+	struct clk *clk_per;
 };
 
 struct mpc_i2c_divider {
@@ -623,6 +625,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
+	struct clk *clk;
+	int err;
 
 	match = of_match_device(mpc_i2c_of_match, &op->dev);
 	if (!match)
@@ -653,6 +657,21 @@ static int fsl_i2c_probe(struct platform_device *op)
 		}
 	}
 
+	/*
+	 * enable clock for the I2C peripheral (non fatal),
+	 * keep a reference upon successful allocation
+	 */
+	clk = devm_clk_get(&op->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			dev_err(&op->dev, "failed to enable clock\n");
+			goto fail_request;
+		} else {
+			i2c->clk_per = clk;
+		}
+	}
+
 	if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) {
 		clock = MPC_I2C_CLOCK_PRESERVE;
 	} else {
@@ -696,6 +715,8 @@ static int fsl_i2c_probe(struct platform_device *op)
 	return result;
 
  fail_add:
+	if (i2c->clk_per)
+		clk_disable_unprepare(i2c->clk_per);
 	free_irq(i2c->irq, i2c);
  fail_request:
 	irq_dispose_mapping(i2c->irq);
@@ -711,6 +732,9 @@ static int fsl_i2c_remove(struct platform_device *op)
 
 	i2c_del_adapter(&i2c->adap);
 
+	if (i2c->clk_per)
+		clk_disable_unprepare(i2c->clk_per);
+
 	if (i2c->irq)
 		free_irq(i2c->irq, i2c);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 07/31] fs_enet: silence a build warning (unused variable)
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab


Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..c04eb3a 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -583,7 +583,6 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
 					       struct sk_buff *skb)
 {
 	struct sk_buff *new_skb;
-	struct fs_enet_private *fep = netdev_priv(dev);
 
 	/* Alloc new skb */
 	new_skb = netdev_alloc_skb(dev, skb->len + 4);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 07/31] fs_enet: silence a build warning (unused variable)
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel


Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 8de53a1..c04eb3a 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -583,7 +583,6 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
 					       struct sk_buff *skb)
 {
 	struct sk_buff *new_skb;
-	struct fs_enet_private *fep = netdev_priv(dev);
 
 	/* Alloc new skb */
 	new_skb = netdev_alloc_skb(dev, skb->len + 4);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 08/31] fs_enet: cleanup clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the Freescale ethernet driver get, prepare and enable the FEC clock
during probe(); disable and unprepare the clock upon remove(), put is
done by the devm approach; hold a reference to the clock over the period
of use

clock lookup is non-fatal as not all platforms provide clock specs in
their device tree; failure to enable specified clocks is fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   20 ++++++++++++++++++++
 include/linux/fs_enet_pd.h                         |    3 +++
 2 files changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index c04eb3a..6b60582 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -999,6 +999,8 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	struct fs_enet_private *fep;
 	struct fs_platform_info *fpi;
 	const u32 *data;
+	struct clk *clk;
+	int err;
 	const u8 *mac_addr;
 	const char *phy_connection_type;
 	int privsize, len, ret = -ENODEV;
@@ -1036,6 +1038,20 @@ static int fs_enet_probe(struct platform_device *ofdev)
 			fpi->use_rmii = 1;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found,
+	 * keep a reference to the clock upon successful acquisition
+	 */
+	clk = devm_clk_get(&ofdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			ret = err;
+			goto out_free_fpi;
+		}
+		fpi->clk_per = clk;
+	}
+
 	privsize = sizeof(*fep) +
 	           sizeof(struct sk_buff **) *
 	           (fpi->rx_ring + fpi->tx_ring);
@@ -1107,6 +1123,8 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1123,6 +1141,8 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per)
+		clk_disable_unprepare(fep->fpi->clk_per);
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 08/31] fs_enet: cleanup clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

make the Freescale ethernet driver get, prepare and enable the FEC clock
during probe(); disable and unprepare the clock upon remove(), put is
done by the devm approach; hold a reference to the clock over the period
of use

clock lookup is non-fatal as not all platforms provide clock specs in
their device tree; failure to enable specified clocks is fatal

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   20 ++++++++++++++++++++
 include/linux/fs_enet_pd.h                         |    3 +++
 2 files changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index c04eb3a..6b60582 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -999,6 +999,8 @@ static int fs_enet_probe(struct platform_device *ofdev)
 	struct fs_enet_private *fep;
 	struct fs_platform_info *fpi;
 	const u32 *data;
+	struct clk *clk;
+	int err;
 	const u8 *mac_addr;
 	const char *phy_connection_type;
 	int privsize, len, ret = -ENODEV;
@@ -1036,6 +1038,20 @@ static int fs_enet_probe(struct platform_device *ofdev)
 			fpi->use_rmii = 1;
 	}
 
+	/* make clock lookup non-fatal (the driver is shared among platforms),
+	 * but require enable to succeed when a clock was specified/found,
+	 * keep a reference to the clock upon successful acquisition
+	 */
+	clk = devm_clk_get(&ofdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		err = clk_prepare_enable(clk);
+		if (err) {
+			ret = err;
+			goto out_free_fpi;
+		}
+		fpi->clk_per = clk;
+	}
+
 	privsize = sizeof(*fep) +
 	           sizeof(struct sk_buff **) *
 	           (fpi->rx_ring + fpi->tx_ring);
@@ -1107,6 +1123,8 @@ out_free_dev:
 	free_netdev(ndev);
 out_put:
 	of_node_put(fpi->phy_node);
+	if (fpi->clk_per)
+		clk_disable_unprepare(fpi->clk_per);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1123,6 +1141,8 @@ static int fs_enet_remove(struct platform_device *ofdev)
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
 	of_node_put(fep->fpi->phy_node);
+	if (fep->fpi->clk_per)
+		clk_disable_unprepare(fep->fpi->clk_per);
 	free_netdev(ndev);
 	return 0;
 }
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 51b7934..a978d0d 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -16,6 +16,7 @@
 #ifndef FS_ENET_PD_H
 #define FS_ENET_PD_H
 
+#include <linux/clk.h>
 #include <linux/string.h>
 #include <linux/of_mdio.h>
 #include <asm/types.h>
@@ -142,6 +143,8 @@ struct fs_platform_info {
 
 	int use_rmii;		/* use RMII mode 	       */
 	int has_phy;            /* if the network is phy container as well...*/
+
+	struct clk *clk_per;	/* 'per' clock for register access */
 };
 struct fs_mii_fec_platform_info {
 	u32 irq[32];
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

make the Freescale PCI driver get, prepare and enable the PCI clock
during probe(); the clock gets put upon device close by the devm approach

clock lookup is non-fatal as not all platforms may provide clock specs
in their device tree, but failure to enable specified clocks are fatal

the driver appears to not have a remove() routine, so no reference to
the clock is kept during use, and the clock isn't released (the devm
approach will put the clock, but it won't get disabled or unprepared)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..549ff08 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -926,12 +928,32 @@ void fsl_pci_assign_primary(void)
 
 static int fsl_pci_probe(struct platform_device *pdev)
 {
+	struct clk *clk;
 	int ret;
 	struct device_node *node;
 #ifdef CONFIG_SWIOTLB
 	struct pci_controller *hose;
 #endif
 
+	/*
+	 * clock lookup is non-fatal since the driver is shared among
+	 * platforms and not all of them provide clocks specs in their
+	 * device tree, but failure to enable a specified clock is
+	 * considered fatal
+	 */
+	clk = devm_clk_get(&pdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			dev_err(dev, "Could not enable peripheral clock\n");
+			return ret;
+		}
+		/*
+		 * TODO where to store the 'clk' reference?  there appears
+		 * to be no remove() routine which undoes what probe() does
+		 */
+	}
+
 	node = pdev->dev.of_node;
 	ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

make the Freescale PCI driver get, prepare and enable the PCI clock
during probe(); the clock gets put upon device close by the devm approach

clock lookup is non-fatal as not all platforms may provide clock specs
in their device tree, but failure to enable specified clocks are fatal

the driver appears to not have a remove() routine, so no reference to
the clock is kept during use, and the clock isn't released (the devm
approach will put the clock, but it won't get disabled or unprepared)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/sysdev/fsl_pci.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 46ac1dd..549ff08 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -17,6 +17,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -926,12 +928,32 @@ void fsl_pci_assign_primary(void)
 
 static int fsl_pci_probe(struct platform_device *pdev)
 {
+	struct clk *clk;
 	int ret;
 	struct device_node *node;
 #ifdef CONFIG_SWIOTLB
 	struct pci_controller *hose;
 #endif
 
+	/*
+	 * clock lookup is non-fatal since the driver is shared among
+	 * platforms and not all of them provide clocks specs in their
+	 * device tree, but failure to enable a specified clock is
+	 * considered fatal
+	 */
+	clk = devm_clk_get(&pdev->dev, "per");
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			dev_err(dev, "Could not enable peripheral clock\n");
+			return ret;
+		}
+		/*
+		 * TODO where to store the 'clk' reference?  there appears
+		 * to be no remove() routine which undoes what probe() does
+		 */
+	}
+
 	node = pdev->dev.of_node;
 	ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 10/31] net: can: mscan: add a comment on reg to idx mapping
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 10/31] net: can: mscan: add a comment on reg to idx mapping
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		goto exit_put;
 	}
 
-	/* Determine the MSCAN device index from the physical address */
+	/* Determine the MSCAN device index from the peripheral's
+	 * physical address. Register address offsets against the
+	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+	 */
 	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
 	BUG_ON(!pval || plen < sizeof(*pval));
 	clockidx = (*pval & 0x80) ? 1 : 0;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 11/31] net: can: mscan: improve clock API use
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the .get_clock() callback is run from probe() and might allocate
resources, introduce a .put_clock() callback that is run from remove()
to undo any allocation activities

prepare and enable the clocks in open(), disable and unprepare the
clocks in close() if clocks were acquired during probe(), to not assume
knowledge about which activities are done in probe() and remove()

use devm_get_clk() to lookup the SYS and REF clocks, to have the clocks
put upon device shutdown

store pointers to data structures upon successful allocation already
instead of deferral until complete setup, such that subroutines in the
setup sequence may access those data structures as well to track their
resource acquisition

since clock allocation remains optional, the release callback as well as
the enable/disable calls in open/close are optional as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |   18 ++++++++++++------
 drivers/net/can/mscan/mscan.c       |   27 ++++++++++++++++++++++++++-
 drivers/net/can/mscan/mscan.h       |    3 +++
 3 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..e59b3a3 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
 			 int *mscan_clksrc);
+	void (*put_clock)(struct platform_device *ofdev);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 			clockdiv = 1;
 
 		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
+			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
 			if (IS_ERR(sys_clk)) {
 				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
 				goto exit_unmap;
@@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		}
 
 		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
+			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
 			if (IS_ERR(ref_clk)) {
 				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
 				goto exit_unmap;
@@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	dev = alloc_mscandev();
 	if (!dev)
 		goto exit_dispose_irq;
+	platform_set_drvdata(ofdev, dev);
+	SET_NETDEV_DEV(dev, &ofdev->dev);
 
 	priv = netdev_priv(dev);
 	priv->reg_base = base;
@@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	SET_NETDEV_DEV(dev, &ofdev->dev);
-
 	err = register_mscandev(dev, mscan_clksrc);
 	if (err) {
 		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
@@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	platform_set_drvdata(ofdev, dev);
-
 	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
 		 priv->reg_base, dev->irq, priv->can.clock.freq);
 
@@ -324,10 +323,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data && data->put_clock)
+		data->put_clock(ofdev);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e6b4095..4f998f5 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
 	struct mscan_priv *priv = netdev_priv(dev);
 	struct mscan_regs __iomem *regs = priv->reg_base;
 
+	if (priv->clk_ipg) {
+		ret = clk_prepare_enable(priv->clk_ipg);
+		if (ret)
+			goto exit_retcode;
+	}
+	if (priv->clk_can) {
+		ret = clk_prepare_enable(priv->clk_can);
+		if (ret) {
+			if (priv->clk_ipg)
+				clk_disable_unprepare(priv->clk_ipg);
+			goto exit_retcode;
+		}
+	}
+
 	/* common open */
 	ret = open_candev(dev);
 	if (ret)
-		return ret;
+		goto exit_dis_clock;
 
 	napi_enable(&priv->napi);
 
@@ -604,6 +618,12 @@ exit_free_irq:
 exit_napi_disable:
 	napi_disable(&priv->napi);
 	close_candev(dev);
+exit_dis_clock:
+	if (priv->clk_can)
+		clk_disable_unprepare(priv->clk_can);
+	if (priv->clk_ipg)
+		clk_disable_unprepare(priv->clk_ipg);
+exit_retcode:
 	return ret;
 }
 
@@ -621,6 +641,11 @@ static int mscan_close(struct net_device *dev)
 	close_candev(dev);
 	free_irq(dev->irq, dev);
 
+	if (priv->clk_can)
+		clk_disable_unprepare(priv->clk_can);
+	if (priv->clk_ipg)
+		clk_disable_unprepare(priv->clk_ipg);
+
 	return 0;
 }
 
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..9c24d60 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,8 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_ipg;	/* clock for registers */
+	struct clk *clk_can;	/* clock for bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 11/31] net: can: mscan: improve clock API use
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

the .get_clock() callback is run from probe() and might allocate
resources, introduce a .put_clock() callback that is run from remove()
to undo any allocation activities

prepare and enable the clocks in open(), disable and unprepare the
clocks in close() if clocks were acquired during probe(), to not assume
knowledge about which activities are done in probe() and remove()

use devm_get_clk() to lookup the SYS and REF clocks, to have the clocks
put upon device shutdown

store pointers to data structures upon successful allocation already
instead of deferral until complete setup, such that subroutines in the
setup sequence may access those data structures as well to track their
resource acquisition

since clock allocation remains optional, the release callback as well as
the enable/disable calls in open/close are optional as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |   18 ++++++++++++------
 drivers/net/can/mscan/mscan.c       |   27 ++++++++++++++++++++++++++-
 drivers/net/can/mscan/mscan.h       |    3 +++
 3 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..e59b3a3 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
 	unsigned int type;
 	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
 			 int *mscan_clksrc);
+	void (*put_clock)(struct platform_device *ofdev);
 };
 
 #ifdef CONFIG_PPC_MPC52xx
@@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 			clockdiv = 1;
 
 		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = clk_get(&ofdev->dev, "sys_clk");
+			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
 			if (IS_ERR(sys_clk)) {
 				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
 				goto exit_unmap;
@@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 		}
 
 		if (clocksrc < 0) {
-			ref_clk = clk_get(&ofdev->dev, "ref_clk");
+			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
 			if (IS_ERR(ref_clk)) {
 				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
 				goto exit_unmap;
@@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 	dev = alloc_mscandev();
 	if (!dev)
 		goto exit_dispose_irq;
+	platform_set_drvdata(ofdev, dev);
+	SET_NETDEV_DEV(dev, &ofdev->dev);
 
 	priv = netdev_priv(dev);
 	priv->reg_base = base;
@@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	SET_NETDEV_DEV(dev, &ofdev->dev);
-
 	err = register_mscandev(dev, mscan_clksrc);
 	if (err) {
 		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
@@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
 		goto exit_free_mscan;
 	}
 
-	platform_set_drvdata(ofdev, dev);
-
 	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
 		 priv->reg_base, dev->irq, priv->can.clock.freq);
 
@@ -324,10 +323,17 @@ exit_unmap_mem:
 
 static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
+	const struct mpc5xxx_can_data *data;
 	struct net_device *dev = platform_get_drvdata(ofdev);
 	struct mscan_priv *priv = netdev_priv(dev);
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	data = match ? match->data : NULL;
+
 	unregister_mscandev(dev);
+	if (data && data->put_clock)
+		data->put_clock(ofdev);
 	iounmap(priv->reg_base);
 	irq_dispose_mapping(dev->irq);
 	free_candev(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e6b4095..4f998f5 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
 	struct mscan_priv *priv = netdev_priv(dev);
 	struct mscan_regs __iomem *regs = priv->reg_base;
 
+	if (priv->clk_ipg) {
+		ret = clk_prepare_enable(priv->clk_ipg);
+		if (ret)
+			goto exit_retcode;
+	}
+	if (priv->clk_can) {
+		ret = clk_prepare_enable(priv->clk_can);
+		if (ret) {
+			if (priv->clk_ipg)
+				clk_disable_unprepare(priv->clk_ipg);
+			goto exit_retcode;
+		}
+	}
+
 	/* common open */
 	ret = open_candev(dev);
 	if (ret)
-		return ret;
+		goto exit_dis_clock;
 
 	napi_enable(&priv->napi);
 
@@ -604,6 +618,12 @@ exit_free_irq:
 exit_napi_disable:
 	napi_disable(&priv->napi);
 	close_candev(dev);
+exit_dis_clock:
+	if (priv->clk_can)
+		clk_disable_unprepare(priv->clk_can);
+	if (priv->clk_ipg)
+		clk_disable_unprepare(priv->clk_ipg);
+exit_retcode:
 	return ret;
 }
 
@@ -621,6 +641,11 @@ static int mscan_close(struct net_device *dev)
 	close_candev(dev);
 	free_irq(dev->irq, dev);
 
+	if (priv->clk_can)
+		clk_disable_unprepare(priv->clk_can);
+	if (priv->clk_ipg)
+		clk_disable_unprepare(priv->clk_ipg);
+
 	return 0;
 }
 
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..9c24d60 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
 #ifndef __MSCAN_H__
 #define __MSCAN_H__
 
+#include <linux/clk.h>
 #include <linux/types.h>
 
 /* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,8 @@ struct mscan_priv {
 	unsigned int type; 	/* MSCAN type variants */
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	struct clk *clk_ipg;	/* clock for registers */
+	struct clk *clk_can;	/* clock for bitrates */
 	u8 shadow_statflg;
 	u8 shadow_canrier;
 	u8 cur_pri;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC controller
or CAN controller component number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC controller
or CAN controller component number

this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
 	u32	scfr2;	/* System Clock Frequency Register 2 */
 	u32	scfr2s;	/* System Clock Frequency Shadow Register 2 */
 	u32	bcr;	/* Bread Crumb Register */
-	u32	p0ccr;	/* PSC0 Clock Control Register */
-	u32	p1ccr;	/* PSC1 CCR */
-	u32	p2ccr;	/* PSC2 CCR */
-	u32	p3ccr;	/* PSC3 CCR */
-	u32	p4ccr;	/* PSC4 CCR */
-	u32	p5ccr;	/* PSC5 CCR */
-	u32	p6ccr;	/* PSC6 CCR */
-	u32	p7ccr;	/* PSC7 CCR */
-	u32	p8ccr;	/* PSC8 CCR */
-	u32	p9ccr;	/* PSC9 CCR */
-	u32	p10ccr;	/* PSC10 CCR */
-	u32	p11ccr;	/* PSC11 CCR */
+	u32	psc_ccr[12];	/* PSC Clock Control Registers */
 	u32	spccr;	/* SPDIF Clock Control Register */
 	u32	cccr;	/* CFM Clock Control Register */
 	u32	dccr;	/* DIU Clock Control Register */
-	u32	m1ccr;	/* MSCAN1 CCR */
-	u32	m2ccr;	/* MSCAN2 CCR */
-	u32	m3ccr;	/* MSCAN3 CCR */
-	u32	m4ccr;	/* MSCAN4 CCR */
+	u32	mscan_ccr[4];	/* MSCAN Clock Control Registers */
 	u8	res[0x98]; /* Reserved */
 };
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 13/31] clk: wrap I/O access for improved portability
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 13/31] clk: wrap I/O access for improved portability
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals

wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/clk/clk-divider.c    |    6 +++---
 drivers/clk/clk-gate.c       |    6 +++---
 drivers/clk/clk-mux.c        |    6 +++---
 include/linux/clk-provider.h |   17 +++++++++++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	struct clk_divider *divider = to_clk_divider(hw);
 	unsigned int div, val;
 
-	val = readl(divider->reg) >> divider->shift;
+	val = clk_readl(divider->reg) >> divider->shift;
 	val &= div_mask(divider);
 
 	div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
 		val = div_mask(divider) << (divider->shift + 16);
 	} else {
-		val = readl(divider->reg);
+		val = clk_readl(divider->reg);
 		val &= ~(div_mask(divider) << divider->shift);
 	}
 	val |= value << divider->shift;
-	writel(val, divider->reg);
+	clk_writel(val, divider->reg);
 
 	if (divider->lock)
 		spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 		if (set)
 			reg |= BIT(gate->bit_idx);
 	} else {
-		reg = readl(gate->reg);
+		reg = clk_readl(gate->reg);
 
 		if (set)
 			reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 			reg &= ~BIT(gate->bit_idx);
 	}
 
-	writel(reg, gate->reg);
+	clk_writel(reg, gate->reg);
 
 	if (gate->lock)
 		spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
 	u32 reg;
 	struct clk_gate *gate = to_clk_gate(hw);
 
-	reg = readl(gate->reg);
+	reg = clk_readl(gate->reg);
 
 	/* if a set bit disables this clk, flip it before masking */
 	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
 	 * val = 0x4 really means "bit 2, index starts at bit 0"
 	 */
-	val = readl(mux->reg) >> mux->shift;
+	val = clk_readl(mux->reg) >> mux->shift;
 	val &= mux->mask;
 
 	if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
 		val = mux->mask << (mux->shift + 16);
 	} else {
-		val = readl(mux->reg);
+		val = clk_readl(mux->reg);
 		val &= ~(mux->mask << mux->shift);
 	}
 	val |= index << mux->shift;
-	writel(val, mux->reg);
+	clk_writel(val, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
 #define __LINUX_CLK_PROVIDER_H
 
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #ifdef CONFIG_COMMON_CLK
 
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	writel(val, reg);
+}
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 14/31] dts: mpc512x: prepare for preprocessor support
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 14/31] dts: mpc512x: prepare for preprocessor support
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
 arch/powerpc/boot/dts/include/dt-bindings |    1 +
 arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
 arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
  */
 
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
  * option) any later version.
  */
 
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
 
 / {
 	model = "pdm360ng";
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Reviewed-by: Mike Turquette <mturquette@linaro.org>	# for v3: w/o bdlc, PSC ipg
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   69 +++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..9e81b3b
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,69 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_BDLC		24
+#define MPC512x_CLK_SDHC		25
+#define MPC512x_CLK_PCI			26
+#define MPC512x_CLK_PSC_MCLK_IN		27
+#define MPC512x_CLK_SPDIF_TX		28
+#define MPC512x_CLK_SPDIF_RX		29
+#define MPC512x_CLK_SPDIF_MCLK		30
+#define MPC512x_CLK_SPDIF		31
+#define MPC512x_CLK_AC97		32
+#define MPC512x_CLK_PSC0_MCLK		33
+#define MPC512x_CLK_PSC1_MCLK		34
+#define MPC512x_CLK_PSC2_MCLK		35
+#define MPC512x_CLK_PSC3_MCLK		36
+#define MPC512x_CLK_PSC4_MCLK		37
+#define MPC512x_CLK_PSC5_MCLK		38
+#define MPC512x_CLK_PSC6_MCLK		39
+#define MPC512x_CLK_PSC7_MCLK		40
+#define MPC512x_CLK_PSC8_MCLK		41
+#define MPC512x_CLK_PSC9_MCLK		42
+#define MPC512x_CLK_PSC10_MCLK		43
+#define MPC512x_CLK_PSC11_MCLK		44
+#define MPC512x_CLK_PSC_FIFO		45
+#define MPC512x_CLK_PSC0		46
+#define MPC512x_CLK_PSC1		47
+#define MPC512x_CLK_PSC2		48
+#define MPC512x_CLK_PSC3		49
+#define MPC512x_CLK_PSC4		50
+#define MPC512x_CLK_PSC5		51
+#define MPC512x_CLK_PSC6		52
+#define MPC512x_CLK_PSC7		53
+#define MPC512x_CLK_PSC8		54
+#define MPC512x_CLK_PSC9		55
+#define MPC512x_CLK_PSC10		56
+#define MPC512x_CLK_PSC11		57
+
+#define MPC512x_CLK_LAST_PUBLIC		57
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes

Reviewed-by: Mike Turquette <mturquette@linaro.org>	# for v3: w/o bdlc, PSC ipg
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 include/dt-bindings/clock/mpc512x-clock.h |   69 +++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 include/dt-bindings/clock/mpc512x-clock.h

diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..9e81b3b
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,69 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY		0
+#define MPC512x_CLK_REF			1
+#define MPC512x_CLK_SYS			2
+#define MPC512x_CLK_DIU			3
+#define MPC512x_CLK_VIU			4
+#define MPC512x_CLK_CSB			5
+#define MPC512x_CLK_E300		6
+#define MPC512x_CLK_IPS			7
+#define MPC512x_CLK_FEC			8
+#define MPC512x_CLK_SATA		9
+#define MPC512x_CLK_PATA		10
+#define MPC512x_CLK_NFC			11
+#define MPC512x_CLK_LPC			12
+#define MPC512x_CLK_MBX_BUS		13
+#define MPC512x_CLK_MBX			14
+#define MPC512x_CLK_MBX_3D		15
+#define MPC512x_CLK_AXE			16
+#define MPC512x_CLK_USB1		17
+#define MPC512x_CLK_USB2		18
+#define MPC512x_CLK_I2C			19
+#define MPC512x_CLK_MSCAN0_MCLK		20
+#define MPC512x_CLK_MSCAN1_MCLK		21
+#define MPC512x_CLK_MSCAN2_MCLK		22
+#define MPC512x_CLK_MSCAN3_MCLK		23
+#define MPC512x_CLK_BDLC		24
+#define MPC512x_CLK_SDHC		25
+#define MPC512x_CLK_PCI			26
+#define MPC512x_CLK_PSC_MCLK_IN		27
+#define MPC512x_CLK_SPDIF_TX		28
+#define MPC512x_CLK_SPDIF_RX		29
+#define MPC512x_CLK_SPDIF_MCLK		30
+#define MPC512x_CLK_SPDIF		31
+#define MPC512x_CLK_AC97		32
+#define MPC512x_CLK_PSC0_MCLK		33
+#define MPC512x_CLK_PSC1_MCLK		34
+#define MPC512x_CLK_PSC2_MCLK		35
+#define MPC512x_CLK_PSC3_MCLK		36
+#define MPC512x_CLK_PSC4_MCLK		37
+#define MPC512x_CLK_PSC5_MCLK		38
+#define MPC512x_CLK_PSC6_MCLK		39
+#define MPC512x_CLK_PSC7_MCLK		40
+#define MPC512x_CLK_PSC8_MCLK		41
+#define MPC512x_CLK_PSC9_MCLK		42
+#define MPC512x_CLK_PSC10_MCLK		43
+#define MPC512x_CLK_PSC11_MCLK		44
+#define MPC512x_CLK_PSC_FIFO		45
+#define MPC512x_CLK_PSC0		46
+#define MPC512x_CLK_PSC1		47
+#define MPC512x_CLK_PSC2		48
+#define MPC512x_CLK_PSC3		49
+#define MPC512x_CLK_PSC4		50
+#define MPC512x_CLK_PSC5		51
+#define MPC512x_CLK_PSC6		52
+#define MPC512x_CLK_PSC7		53
+#define MPC512x_CLK_PSC8		54
+#define MPC512x_CLK_PSC9		55
+#define MPC512x_CLK_PSC10		56
+#define MPC512x_CLK_PSC11		57
+
+#define MPC512x_CLK_LAST_PUBLIC		57
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 16/31] dts: mpc512x: add clock related device tree specs
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Reviewed-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc@80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock@f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc@80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock@f00 {
+		clks: clock@f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 16/31] dts: mpc512x: add clock related device tree specs
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
  based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
  or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
  common include (the 66MHz IPS bus already was there), add
  override values for the ifm AC14xx board which deviates from
  the reference design (25MHz xtal, 80MHz IPS bus)

Reviewed-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/ac14xx.dts   |    7 +++++++
 arch/powerpc/boot/dts/mpc5121.dtsi |   15 ++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
 		};
 	};
 
+	clocks {
+		osc {
+			clock-frequency = <25000000>;
+		};
+	};
+
 	soc at 80000000 {
+		bus-frequency = <80000000>;	/* 80 MHz ips bus */
 
 		clock at f00 {
 			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
@@ -73,6 +75,16 @@
 		ranges = <0x0 0x0 0xfc000000 0x04000000>;
 	};
 
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,mpc512x-osc", "fixed-clock";
+			clock-frequency = <33000000>;
+		};
+	};
+
 	soc at 80000000 {
 		compatible = "fsl,mpc5121-immr";
 		#address-cells = <1>;
@@ -118,9 +130,10 @@
 		};
 
 		/* Clock control */
-		clock at f00 {
+		clks: clock at f00 {
 			compatible = "fsl,mpc5121-clock";
 			reg = <0xf00 0x100>;
+			#clock-cells = <1>;
 		};
 
 		/* Power Management Controller */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this change implements a clock driver for the MPC512x PowerPC platform
which follows the COMMON_CLK approach and uses common clock drivers
shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and remains in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

some of the clock items get pre-enabled in the clock driver to not have
them automatically disabled by the underlying clock subsystem because of
their being unused -- this approach is desirable because
- some of the clocks are useful to have for diagnostics and information
  despite their not getting claimed by any drivers (CPU, internal and
  external RAM, internal busses, boot media)
- some of the clocks aren't claimed by their peripheral drivers yet,
  either because of missing driver support or because device tree specs
  aren't available yet (but the workarounds will get removed as the
  drivers get adjusted and the device tree provides the clock specs)

clkdev registration provides "alias names" for few clock items
- to not break those peripheral drivers which encode their component
  index into the name that is used for clock lookup (UART, SPI, USB)
- to not break those drivers which use names for the clock lookup which
  were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
this workaround will get removed as these drivers get adjusted after
device tree based clock lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  748 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 780 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..09721d5
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,748 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	bool has_mclk1;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, 0, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, 0, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 1, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_pub] = mpc512x_clk_muxed(
+				entry->name_mclk,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->parent_names_mux1[0],
+				1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	size_t mclk_idx;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	/* for PSCs there is a "registers" gate and a bitrate MCLK subtree */
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++) {
+		char name[12];
+		snprintf(name, sizeof(name), "psc%d", mclk_idx);
+		clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated(
+				name, "ips", &clkregs->sccr1, 27 - mclk_idx);
+		mpc512x_clk_setup_mclk(&mclk_psc_data[mclk_idx], mclk_idx);
+	}
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	/* MSCAN differs from PSC with just one gate for multiple components */
+	clks[MPC512x_CLK_BDLC] = mpc512x_clk_gated("bdlc", "ips",
+						   &clkregs->sccr2, 25);
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+		mpc512x_clk_setup_mclk(&mclk_mscan_data[mclk_idx], mclk_idx);
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	/* there is only one SPDIF component, which shares MCLK support code */
+	clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated("spdif", "ips",
+						    &clkregs->sccr2, 23);
+	mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0);
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	/* clkdev registration for compatibility reasons */
+	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
+		clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
+	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+		clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

this change implements a clock driver for the MPC512x PowerPC platform
which follows the COMMON_CLK approach and uses common clock drivers
shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and remains in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

some of the clock items get pre-enabled in the clock driver to not have
them automatically disabled by the underlying clock subsystem because of
their being unused -- this approach is desirable because
- some of the clocks are useful to have for diagnostics and information
  despite their not getting claimed by any drivers (CPU, internal and
  external RAM, internal busses, boot media)
- some of the clocks aren't claimed by their peripheral drivers yet,
  either because of missing driver support or because device tree specs
  aren't available yet (but the workarounds will get removed as the
  drivers get adjusted and the device tree provides the clock specs)

clkdev registration provides "alias names" for few clock items
- to not break those peripheral drivers which encode their component
  index into the name that is used for clock lookup (UART, SPI, USB)
- to not break those drivers which use names for the clock lookup which
  were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
this workaround will get removed as these drivers get adjusted after
device tree based clock lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  748 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 780 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..09721d5
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,748 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	bool has_mclk1;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, 0, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, 0, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 1, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_pub] = mpc512x_clk_muxed(
+				entry->name_mclk,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->parent_names_mux1[0],
+				1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	size_t mclk_idx;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	/* for PSCs there is a "registers" gate and a bitrate MCLK subtree */
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++) {
+		char name[12];
+		snprintf(name, sizeof(name), "psc%d", mclk_idx);
+		clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated(
+				name, "ips", &clkregs->sccr1, 27 - mclk_idx);
+		mpc512x_clk_setup_mclk(&mclk_psc_data[mclk_idx], mclk_idx);
+	}
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	/* MSCAN differs from PSC with just one gate for multiple components */
+	clks[MPC512x_CLK_BDLC] = mpc512x_clk_gated("bdlc", "ips",
+						   &clkregs->sccr2, 25);
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+		mpc512x_clk_setup_mclk(&mclk_mscan_data[mclk_idx], mclk_idx);
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	/* there is only one SPDIF component, which shares MCLK support code */
+	clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated("spdif", "ips",
+						    &clkregs->sccr2, 23);
+	mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0);
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	/* clkdev registration for compatibility reasons */
+	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
+	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
+		clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
+	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
+	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+		clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 18/31] dts: mpc512x: add clock specs for client lookups
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

this addresses the client side of device tree based clock lookups

add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver

Reviewed-by: Mike Turquette <mturquette@linaro.org>	# for v3: w/o bdlc, PSC ipg
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   95 ++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..4cef164 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram@30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "per";
 	};
 
 	localbus@80000020 {
@@ -153,12 +159,24 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		can@1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		sdhc@1500 {
@@ -167,6 +185,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c@1700 {
@@ -175,6 +196,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1720 {
@@ -183,6 +206,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c@1740 {
@@ -191,6 +216,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol@1760 {
@@ -202,30 +229,48 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display@2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can@2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		can@2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		viu@2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "per";
 		};
 
 		mdio@2800 {
@@ -233,6 +278,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet@2800 {
@@ -241,6 +288,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +301,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +314,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +334,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +347,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>,
+				 <&clks MPC512x_CLK_PSC0>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC1 */
@@ -301,6 +359,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>,
+				 <&clks MPC512x_CLK_PSC1>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC2 */
@@ -310,6 +371,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>,
+				 <&clks MPC512x_CLK_PSC2>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC3 */
@@ -319,6 +383,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>,
+				 <&clks MPC512x_CLK_PSC3>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC4 */
@@ -328,6 +395,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>,
+				 <&clks MPC512x_CLK_PSC4>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC5 */
@@ -337,6 +407,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>,
+				 <&clks MPC512x_CLK_PSC5>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC6 */
@@ -346,6 +419,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>,
+				 <&clks MPC512x_CLK_PSC6>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC7 */
@@ -355,6 +431,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>,
+				 <&clks MPC512x_CLK_PSC7>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC8 */
@@ -364,6 +443,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>,
+				 <&clks MPC512x_CLK_PSC8>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC9 */
@@ -373,6 +455,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>,
+				 <&clks MPC512x_CLK_PSC9>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC10 */
@@ -382,6 +467,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>,
+				 <&clks MPC512x_CLK_PSC10>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC11 */
@@ -391,12 +479,17 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>,
+				 <&clks MPC512x_CLK_PSC11>;
+			clock-names = "mclk", "ipg";
 		};
 
 		pscfifo@11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma@14000 {
@@ -414,6 +507,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 18/31] dts: mpc512x: add clock specs for client lookups
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

this addresses the client side of device tree based clock lookups

add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
mpc5121.dtsi include

these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver

Reviewed-by: Mike Turquette <mturquette@linaro.org>	# for v3: w/o bdlc, PSC ipg
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/boot/dts/mpc5121.dtsi |   95 ++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..4cef164 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
 		compatible = "fsl,mpc5121-mbx";
 		reg = <0x20000000 0x4000>;
 		interrupts = <66 0x8>;
+		clocks = <&clks MPC512x_CLK_MBX_BUS>,
+			 <&clks MPC512x_CLK_MBX_3D>,
+			 <&clks MPC512x_CLK_MBX>;
+		clock-names = "mbx-bus", "mbx-3d", "mbx";
 	};
 
 	sram at 30000000 {
@@ -64,6 +68,8 @@
 		interrupts = <6 8>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+		clocks = <&clks MPC512x_CLK_NFC>;
+		clock-names = "per";
 	};
 
 	localbus at 80000020 {
@@ -153,12 +159,24 @@
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1300 0x80>;
 			interrupts = <12 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN0_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		can at 1380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x1380 0x80>;
 			interrupts = <13 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN1_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		sdhc at 1500 {
@@ -167,6 +185,9 @@
 			interrupts = <8 0x8>;
 			dmas = <&dma0 30>;
 			dma-names = "rx-tx";
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SDHC>;
+			clock-names = "ipg", "per";
 		};
 
 		i2c at 1700 {
@@ -175,6 +196,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1700 0x20>;
 			interrupts = <9 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1720 {
@@ -183,6 +206,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1720 0x20>;
 			interrupts = <10 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2c at 1740 {
@@ -191,6 +216,8 @@
 			compatible = "fsl,mpc5121-i2c", "fsl-i2c";
 			reg = <0x1740 0x20>;
 			interrupts = <11 0x8>;
+			clocks = <&clks MPC512x_CLK_I2C>;
+			clock-names = "per";
 		};
 
 		i2ccontrol at 1760 {
@@ -202,30 +229,48 @@
 			compatible = "fsl,mpc5121-axe";
 			reg = <0x2000 0x100>;
 			interrupts = <42 0x8>;
+			clocks = <&clks MPC512x_CLK_AXE>;
+			clock-names = "per";
 		};
 
 		display at 2100 {
 			compatible = "fsl,mpc5121-diu";
 			reg = <0x2100 0x100>;
 			interrupts = <64 0x8>;
+			clocks = <&clks MPC512x_CLK_DIU>;
+			clock-names = "per";
 		};
 
 		can at 2300 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2300 0x80>;
 			interrupts = <90 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN2_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		can at 2380 {
 			compatible = "fsl,mpc5121-mscan";
 			reg = <0x2380 0x80>;
 			interrupts = <91 0x8>;
+			clocks = <&clks MPC512x_CLK_IPS>,
+				 <&clks MPC512x_CLK_SYS>,
+				 <&clks MPC512x_CLK_REF>,
+				 <&clks MPC512x_CLK_MSCAN3_MCLK>,
+				 <&clks MPC512x_CLK_BDLC>;
+			clock-names = "ips", "sys", "ref", "mclk", "ipg";
 		};
 
 		viu at 2400 {
 			compatible = "fsl,mpc5121-viu";
 			reg = <0x2400 0x400>;
 			interrupts = <67 0x8>;
+			clocks = <&clks MPC512x_CLK_VIU>;
+			clock-names = "per";
 		};
 
 		mdio at 2800 {
@@ -233,6 +278,8 @@
 			reg = <0x2800 0x800>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		eth0: ethernet at 2800 {
@@ -241,6 +288,8 @@
 			reg = <0x2800 0x800>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <4 0x8>;
+			clocks = <&clks MPC512x_CLK_FEC>;
+			clock-names = "per";
 		};
 
 		/* USB1 using external ULPI PHY */
@@ -252,6 +301,8 @@
 			interrupts = <43 0x8>;
 			dr_mode = "otg";
 			phy_type = "ulpi";
+			clocks = <&clks MPC512x_CLK_USB1>;
+			clock-names = "per";
 		};
 
 		/* USB0 using internal UTMI PHY */
@@ -263,6 +314,8 @@
 			interrupts = <44 0x8>;
 			dr_mode = "otg";
 			phy_type = "utmi_wide";
+			clocks = <&clks MPC512x_CLK_USB2>;
+			clock-names = "per";
 		};
 
 		/* IO control */
@@ -281,6 +334,8 @@
 			compatible = "fsl,mpc5121-pata";
 			reg = <0x10200 0x100>;
 			interrupts = <5 0x8>;
+			clocks = <&clks MPC512x_CLK_PATA>;
+			clock-names = "per";
 		};
 
 		/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +347,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC0_MCLK>,
+				 <&clks MPC512x_CLK_PSC0>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC1 */
@@ -301,6 +359,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC1_MCLK>,
+				 <&clks MPC512x_CLK_PSC1>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC2 */
@@ -310,6 +371,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC2_MCLK>,
+				 <&clks MPC512x_CLK_PSC2>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC3 */
@@ -319,6 +383,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC3_MCLK>,
+				 <&clks MPC512x_CLK_PSC3>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC4 */
@@ -328,6 +395,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC4_MCLK>,
+				 <&clks MPC512x_CLK_PSC4>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC5 */
@@ -337,6 +407,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC5_MCLK>,
+				 <&clks MPC512x_CLK_PSC5>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC6 */
@@ -346,6 +419,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC6_MCLK>,
+				 <&clks MPC512x_CLK_PSC6>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC7 */
@@ -355,6 +431,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC7_MCLK>,
+				 <&clks MPC512x_CLK_PSC7>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC8 */
@@ -364,6 +443,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC8_MCLK>,
+				 <&clks MPC512x_CLK_PSC8>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC9 */
@@ -373,6 +455,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC9_MCLK>,
+				 <&clks MPC512x_CLK_PSC9>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC10 */
@@ -382,6 +467,9 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC10_MCLK>,
+				 <&clks MPC512x_CLK_PSC10>;
+			clock-names = "mclk", "ipg";
 		};
 
 		/* PSC11 */
@@ -391,12 +479,17 @@
 			interrupts = <40 0x8>;
 			fsl,rx-fifo-size = <16>;
 			fsl,tx-fifo-size = <16>;
+			clocks = <&clks MPC512x_CLK_PSC11_MCLK>,
+				 <&clks MPC512x_CLK_PSC11>;
+			clock-names = "mclk", "ipg";
 		};
 
 		pscfifo at 11f00 {
 			compatible = "fsl,mpc5121-psc-fifo";
 			reg = <0x11f00 0x100>;
 			interrupts = <40 0x8>;
+			clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+			clock-names = "per";
 		};
 
 		dma0: dma at 14000 {
@@ -414,6 +507,8 @@
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
+		clocks = <&clks MPC512x_CLK_PCI>;
+		clock-names = "per";
 
 		reg = <0x80008500 0x100	/* internal registers */
 		       0x80008300 0x8>;	/* config space access registers */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:43           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the device tree nodes provide clock specs for client side lookups,
peripheral drivers can attach to their clocks and the clock driver need
no longer pre-enable those clock items

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 09721d5..3f559fe 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -685,9 +685,7 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
 		clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
 	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks
@ 2013-08-06 20:43           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

after the device tree nodes provide clock specs for client side lookups,
peripheral drivers can attach to their clocks and the clock driver need
no longer pre-enable those clock items

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 09721d5..3f559fe 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -685,9 +685,7 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
 	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
 		clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
 	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 20/31] spi: mpc512x: switch to CCF names in clock lookup
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use 'mclk'

acquire and release the 'ipg' clock for register access as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 85581f3..daedee7 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,6 +38,7 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
+	struct clk *clk_ipg;
 	struct clk *clk_mclk;
 	u32 mclk_rate;
 
@@ -474,8 +475,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
@@ -519,29 +518,41 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = devm_clk_get(dev, clk_name);
-	if (IS_ERR(clk))
+	clk = devm_clk_get(dev, "ipg");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
 		goto free_irq;
+	}
 	ret = clk_prepare_enable(clk);
 	if (ret)
 		goto free_irq;
+	mps->clk_ipg = clk;
+
+	clk = devm_clk_get(dev, "mclk");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto free_ipg_clock;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		goto free_ipg_clock;
 	mps->clk_mclk = clk;
 	mps->mclk_rate = clk_get_rate(clk);
 
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_clock;
+		goto free_mclk_clock;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_clock;
+		goto free_mclk_clock;
 
 	return ret;
 
-free_clock:
+free_mclk_clock:
 	clk_disable_unprepare(mps->clk_mclk);
+free_ipg_clock:
+	clk_disable_unprepare(mps->clk_ipg);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -559,6 +570,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 
 	spi_unregister_master(master);
 	clk_disable_unprepare(mps->clk_mclk);
+	clk_disable_unprepare(mps->clk_ipg);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 20/31] spi: mpc512x: switch to CCF names in clock lookup
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use 'mclk'

acquire and release the 'ipg' clock for register access as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/spi/spi-mpc512x-psc.c |   30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 85581f3..daedee7 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,6 +38,7 @@ struct mpc512x_psc_spi {
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
+	struct clk *clk_ipg;
 	struct clk *clk_mclk;
 	u32 mclk_rate;
 
@@ -474,8 +475,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 	struct spi_master *master;
 	int ret;
 	void *tempp;
-	int psc_num;
-	char clk_name[16];
 	struct clk *clk;
 
 	master = spi_alloc_master(dev, sizeof *mps);
@@ -519,29 +518,41 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 		goto free_master;
 	init_completion(&mps->txisrdone);
 
-	psc_num = master->bus_num;
-	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-	clk = devm_clk_get(dev, clk_name);
-	if (IS_ERR(clk))
+	clk = devm_clk_get(dev, "ipg");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
 		goto free_irq;
+	}
 	ret = clk_prepare_enable(clk);
 	if (ret)
 		goto free_irq;
+	mps->clk_ipg = clk;
+
+	clk = devm_clk_get(dev, "mclk");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto free_ipg_clock;
+	}
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		goto free_ipg_clock;
 	mps->clk_mclk = clk;
 	mps->mclk_rate = clk_get_rate(clk);
 
 	ret = mpc512x_psc_spi_port_config(master, mps);
 	if (ret < 0)
-		goto free_clock;
+		goto free_mclk_clock;
 
 	ret = spi_register_master(master);
 	if (ret < 0)
-		goto free_clock;
+		goto free_mclk_clock;
 
 	return ret;
 
-free_clock:
+free_mclk_clock:
 	clk_disable_unprepare(mps->clk_mclk);
+free_ipg_clock:
+	clk_disable_unprepare(mps->clk_ipg);
 free_irq:
 	free_irq(mps->irq, mps);
 free_master:
@@ -559,6 +570,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
 
 	spi_unregister_master(master);
 	clk_disable_unprepare(mps->clk_mclk);
+	clk_disable_unprepare(mps->clk_ipg);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 21/31] serial: mpc512x: switch to CCF names in clock lookup
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use 'mclk'

acquire and release the 'ipg' clock for register access as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |   45 ++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 5be1df3..f4d2b70 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -618,30 +618,58 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
 	return IRQ_NONE;
 }
 
+static struct clk *psc_ipg_clk[MPC52xx_PSC_MAXNUM];
 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)
 {
 	int psc_num;
-	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);
+
+	clk = devm_clk_get(port->dev, "ipg");
+	if (IS_ERR(clk)) {
+		dev_err(port->dev, "Failed to get IPG clock!\n");
+		err = PTR_ERR(clk);
+		goto out_err;
+	}
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(port->dev, "Failed to enable IPG clock!\n");
+		goto out_err;
+	}
+	psc_ipg_clk[psc_num] = clk;
+
+	clk = devm_clk_get(port->dev, "mclk");
 	if (IS_ERR(clk)) {
 		dev_err(port->dev, "Failed to get MCLK!\n");
-		return PTR_ERR(clk);
+		err = PTR_ERR(clk);
+		goto out_err;
 	}
 	err = clk_prepare_enable(clk);
 	if (err) {
 		dev_err(port->dev, "Failed to enable MCLK!\n");
-		return err;
+		goto out_err;
 	}
 	psc_mclk_clk[psc_num] = clk;
+
 	return 0;
+
+out_err:
+	clk = psc_mclk_clk[psc_num];
+	if (clk) {
+		clk_disable_unprepare(clk);
+		psc_mclk_clk[psc_num] = NULL;
+	}
+	clk = psc_ipg_clk[psc_num];
+	if (clk) {
+		clk_disable_unprepare(clk);
+		psc_ipg_clk[psc_num] = NULL;
+	}
+	return err;
 }
 
 /* called from within the .release_port() callback (release) */
@@ -651,11 +679,18 @@ static void mpc512x_psc_relse_clock(struct uart_port *port)
 	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;
 	}
+
+	clk = psc_ipg_clk[psc_num];
+	if (clk) {
+		clk_disable_unprepare(clk);
+		psc_ipg_clk[psc_num] = NULL;
+	}
 }
 
 /* implementation of the .clock() callback (enable/disable) */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 21/31] serial: mpc512x: switch to CCF names in clock lookup
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use 'mclk'

acquire and release the 'ipg' clock for register access as well

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/tty/serial/mpc52xx_uart.c |   45 ++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 5be1df3..f4d2b70 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -618,30 +618,58 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
 	return IRQ_NONE;
 }
 
+static struct clk *psc_ipg_clk[MPC52xx_PSC_MAXNUM];
 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)
 {
 	int psc_num;
-	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);
+
+	clk = devm_clk_get(port->dev, "ipg");
+	if (IS_ERR(clk)) {
+		dev_err(port->dev, "Failed to get IPG clock!\n");
+		err = PTR_ERR(clk);
+		goto out_err;
+	}
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(port->dev, "Failed to enable IPG clock!\n");
+		goto out_err;
+	}
+	psc_ipg_clk[psc_num] = clk;
+
+	clk = devm_clk_get(port->dev, "mclk");
 	if (IS_ERR(clk)) {
 		dev_err(port->dev, "Failed to get MCLK!\n");
-		return PTR_ERR(clk);
+		err = PTR_ERR(clk);
+		goto out_err;
 	}
 	err = clk_prepare_enable(clk);
 	if (err) {
 		dev_err(port->dev, "Failed to enable MCLK!\n");
-		return err;
+		goto out_err;
 	}
 	psc_mclk_clk[psc_num] = clk;
+
 	return 0;
+
+out_err:
+	clk = psc_mclk_clk[psc_num];
+	if (clk) {
+		clk_disable_unprepare(clk);
+		psc_mclk_clk[psc_num] = NULL;
+	}
+	clk = psc_ipg_clk[psc_num];
+	if (clk) {
+		clk_disable_unprepare(clk);
+		psc_ipg_clk[psc_num] = NULL;
+	}
+	return err;
 }
 
 /* called from within the .release_port() callback (release) */
@@ -651,11 +679,18 @@ static void mpc512x_psc_relse_clock(struct uart_port *port)
 	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;
 	}
+
+	clk = psc_ipg_clk[psc_num];
+	if (clk) {
+		clk_disable_unprepare(clk);
+		psc_ipg_clk[psc_num] = NULL;
+	}
 }
 
 /* implementation of the .clock() callback (enable/disable) */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 22/31] clk: mpc512x: remove PSC (UART, SPI) compat workarounds
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after the UART and SPI peripheral drivers have switched to device tree
based clock lookup and no longer construct clock names from their PSC
component index, the "psc%d_mclk" alias names have become obsolete --
remove the corresponding clk_register_clkdev() calls

after the UART and SPI peripheral drivers acquire the 'ipg' clock item,
the platform's clock driver need no longer pre-enable it

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 3f559fe..bd704b3 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -500,17 +500,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
 				entry->parent_names_mux1[0],
 				1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from device tree specs, and device tree nodes need to
-	 * provide the clock specs, before this clkdev registration
-	 * becomes obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_clock_tree(int busfreq)
@@ -686,8 +675,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
-		clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
 	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
 	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
 		clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 22/31] clk: mpc512x: remove PSC (UART, SPI) compat workarounds
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

after the UART and SPI peripheral drivers have switched to device tree
based clock lookup and no longer construct clock names from their PSC
component index, the "psc%d_mclk" alias names have become obsolete --
remove the corresponding clk_register_clkdev() calls

after the UART and SPI peripheral drivers acquire the 'ipg' clock item,
the platform's clock driver need no longer pre-enable it

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |   13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 3f559fe..bd704b3 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -500,17 +500,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
 				entry->parent_names_mux1[0],
 				1, 1);
 	}
-
-	/*
-	 * without this "clock device" registration, "simple" lookups in
-	 * the SPI master initialization and serial port setup will fail
-	 *
-	 * those drivers need to get adjusted to lookup their required
-	 * clocks from device tree specs, and device tree nodes need to
-	 * provide the clock specs, before this clkdev registration
-	 * becomes obsolete
-	 */
-	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
 }
 
 static void mpc512x_clk_setup_clock_tree(int busfreq)
@@ -686,8 +675,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
-		clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
 	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
 	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
 		clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

prepare and enable the FIFO clock upon PSC FIFO initialization,
check for and propagage errors when enabling the PSC FIFO clock,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

devm_{get,put}_clk() doesn't apply here, as the SoC provides a
single FIFO component which is shared among several PSC components,
thus the FIFO isn't associated with a device (while the PSCs are)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   46 +++++++++++++++++++++----
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index bd704b3..803f3be 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -670,8 +670,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index f4d2b70..d16ed6c 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -568,36 +569,69 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
+	int err;
 	struct device_node *np;
+	struct clk *clk;
+
+	/* default error code, potentially overwritten by clock calls */
+	err = -ENODEV;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
 	}
 
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		err = PTR_ERR(clk);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		clk_put(clk);
+		goto out_ofnode_put;
+	}
+	psc_fifoc_clk = clk;
+
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return err;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

prepare and enable the FIFO clock upon PSC FIFO initialization,
check for and propagage errors when enabling the PSC FIFO clock,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver

devm_{get,put}_clk() doesn't apply here, as the SoC provides a
single FIFO component which is shared among several PSC components,
thus the FIFO isn't associated with a device (while the PSCs are)

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/tty/serial/mpc52xx_uart.c             |   46 +++++++++++++++++++++----
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index bd704b3..803f3be 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -670,8 +670,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
 	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
-	/* some are required yet no dependencies were declared */
-	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index f4d2b70..d16ed6c 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -568,36 +569,69 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
+	int err;
 	struct device_node *np;
+	struct clk *clk;
+
+	/* default error code, potentially overwritten by clock calls */
+	err = -ENODEV;
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
 	if (!np) {
 		pr_err("%s: Can't find FIFOC node\n", __func__);
-		return -ENODEV;
+		goto out_err;
 	}
 
+	clk = of_clk_get_by_name(np, "per");
+	if (IS_ERR(clk)) {
+		pr_err("%s: Can't lookup FIFO clock\n", __func__);
+		err = PTR_ERR(clk);
+		goto out_ofnode_put;
+	}
+	if (clk_prepare_enable(clk)) {
+		pr_err("%s: Can't enable FIFO clock\n", __func__);
+		clk_put(clk);
+		goto out_ofnode_put;
+	}
+	psc_fifoc_clk = clk;
+
 	psc_fifoc = of_iomap(np, 0);
 	if (!psc_fifoc) {
 		pr_err("%s: Can't map FIFOC\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
+		goto out_clk_disable;
 	}
 
 	psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (psc_fifoc_irq == 0) {
 		pr_err("%s: Can't get FIFOC irq\n", __func__);
-		iounmap(psc_fifoc);
-		return -ENODEV;
+		goto out_unmap;
 	}
 
+	of_node_put(np);
 	return 0;
+
+out_unmap:
+	iounmap(psc_fifoc);
+out_clk_disable:
+	clk_disable_unprepare(psc_fifoc_clk);
+	clk_put(psc_fifoc_clk);
+out_ofnode_put:
+	of_node_put(np);
+out_err:
+	return err;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
 	iounmap(psc_fifoc);
+
+	/* disable the clock, errors are not fatal */
+	if (psc_fifoc_clk) {
+		clk_disable_unprepare(psc_fifoc_clk);
+		clk_put(psc_fifoc_clk);
+		psc_fifoc_clk = NULL;
+	}
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the component
index -- remove the "usb%d_clk" template and unconditionally use "per",
remove the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/usb/host/fsl-mph-dr-of.c              |   13 +------------
 2 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 803f3be..4615fad 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -658,8 +658,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
 
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index b8a1866..2b323fb 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
 	int err;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = devm_clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the component
index -- remove the "usb%d_clk" template and unconditionally use "per",
remove the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    2 --
 drivers/usb/host/fsl-mph-dr-of.c              |   13 +------------
 2 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 803f3be..4615fad 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -658,8 +658,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
 
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index b8a1866..2b323fb 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 	struct clk *clk;
 	int err;
-	char clk_name[10];
-	int base, clk_num;
-
-	base = pdev->resource->start & 0xf000;
-	if (base == 0x3000)
-		clk_num = 1;
-	else if (base == 0x4000)
-		clk_num = 2;
-	else
-		return -ENODEV;
 
-	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-	clk = devm_clk_get(&pdev->dev, clk_name);
+	clk = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		return PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 25/31] mtd: mpc5121_nfc: remove now obsolete clock lookup name
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the NAND flash
driver need no longer use the previous "nfc_clk" name but can switch to
the fixed "per" clock name -- adjust the peripheral driver and remove
the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/mtd/nand/mpc5121_nfc.c                |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 4615fad..0e23b45 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -657,7 +657,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
 
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c60a00..e541ec0 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -729,7 +729,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	clk = devm_clk_get(dev, "nfc_clk");
+	clk = devm_clk_get(dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
 		retval = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 25/31] mtd: mpc5121_nfc: remove now obsolete clock lookup name
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the NAND flash
driver need no longer use the previous "nfc_clk" name but can switch to
the fixed "per" clock name -- adjust the peripheral driver and remove
the clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/mtd/nand/mpc5121_nfc.c                |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 4615fad..0e23b45 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -657,7 +657,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
 
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c60a00..e541ec0 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -729,7 +729,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 	of_node_put(rootnode);
 
 	/* Enable NFC clock */
-	clk = devm_clk_get(dev, "nfc_clk");
+	clk = devm_clk_get(dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
 		retval = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 26/31] [media] fsl-viu: remove now obsolete clock lookup name
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

after device tree based clock lookup became available, the VIU driver
need no longer use the previous "viu_clk" name but can switch to the
fixed "per" clock name -- adjust the peripheral driver and remove the
clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/media/platform/fsl-viu.c              |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 0e23b45..e5e9cbe 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -656,7 +656,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* clkdev registration for compatibility reasons */
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index fe9898c..1b1a070 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1578,7 +1578,7 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	clk = devm_clk_get(&op->dev, "viu_clk");
+	clk = devm_clk_get(&op->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&op->dev, "failed to lookup the clock!\n");
 		ret = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 26/31] [media] fsl-viu: remove now obsolete clock lookup name
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

after device tree based clock lookup became available, the VIU driver
need no longer use the previous "viu_clk" name but can switch to the
fixed "per" clock name -- adjust the peripheral driver and remove the
clock driver's clkdev registration

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 drivers/media/platform/fsl-viu.c              |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 0e23b45..e5e9cbe 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -656,7 +656,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* clkdev registration for compatibility reasons */
 	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
 	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
 
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index fe9898c..1b1a070 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1578,7 +1578,7 @@ static int viu_of_probe(struct platform_device *op)
 	}
 
 	/* enable VIU clock */
-	clk = devm_clk_get(&op->dev, "viu_clk");
+	clk = devm_clk_get(&op->dev, "per");
 	if (IS_ERR(clk)) {
 		dev_err(&op->dev, "failed to lookup the clock!\n");
 		ret = PTR_ERR(clk);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 27/31] net: can: mscan: add common clock support for mpc512x
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

implement a .get_clock() callback for the MPC512x platform which uses
the common clock infrastructure (eliminating direct access to the clock
control registers from within the CAN network driver), and provide the
corresponding .put_clock() callback to release resources after use

keep the previous implementation of MPC512x support in place during
migration, since common clock support is optional

acquire both the 'ipg' as well as "can" clock items in the mscan driver,
remove pre-enable workarounds for the BDLC (CAN related 'ipg') as well
as the CAN related MCLK (bitrate) items in the platform's clock driver

this change is neutral to the MPC5200 platform

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    3 -
 drivers/net/can/mscan/mpc5xxx_can.c           |  179 +++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index e5e9cbe..afbb01d 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -669,9 +669,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
-	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
-		clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
 }
 
 /*
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index e59b3a3..f48f129 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,6 +109,177 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+	struct mscan_priv *priv;
+	struct clk *clk_ipg;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = devm_clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = devm_clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	/* the above clk_can item is used for the bitrate, access to
+	 * the peripheral's register set needs the clk_ipg item
+	 */
+	clk_ipg = devm_clk_get(&ofdev->dev, "ipg");
+	if (IS_ERR(clk_ipg))
+		goto err_notavail_ipg;
+	if (clk_prepare_enable(clk_ipg))
+		goto err_notavail_ipg;
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	priv->clk_ipg = clk_ipg;
+
+	/* return the determined clock source rate */
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	/* clock source rate could not get determined */
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n");
+	/* clock source rate could not get determined */
+	return 0;
+
+err_notavail_ipg:
+	dev_err(&ofdev->dev, "cannot acquire or setup register clock\n");
+	/* clock source rate could not get determined */
+	return 0;
+}
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+	struct mscan_priv *priv;
+
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	if (priv->clk_ipg)
+		clk_disable_unprepare(priv->clk_ipg);
+}
+
+#else	/* COMMON_CLK */
+
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -239,12 +410,18 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+
+#define mpc512x_can_put_clock NULL
+
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
 {
 	return 0;
 }
+#define mpc512x_can_put_clock NULL
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +563,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	/* .put_clock not applicable */
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 27/31] net: can: mscan: add common clock support for mpc512x
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

implement a .get_clock() callback for the MPC512x platform which uses
the common clock infrastructure (eliminating direct access to the clock
control registers from within the CAN network driver), and provide the
corresponding .put_clock() callback to release resources after use

keep the previous implementation of MPC512x support in place during
migration, since common clock support is optional

acquire both the 'ipg' as well as "can" clock items in the mscan driver,
remove pre-enable workarounds for the BDLC (CAN related 'ipg') as well
as the CAN related MCLK (bitrate) items in the platform's clock driver

this change is neutral to the MPC5200 platform

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    3 -
 drivers/net/can/mscan/mpc5xxx_can.c           |  179 +++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index e5e9cbe..afbb01d 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -669,9 +669,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
 	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
-	clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
-	for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
-		clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
 }
 
 /*
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index e59b3a3..f48f129 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,6 +109,177 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+				 const char *clock_source, int *mscan_clksrc)
+{
+	struct device_node *np;
+	u32 clockdiv;
+	enum {
+		CLK_FROM_AUTO,
+		CLK_FROM_IPS,
+		CLK_FROM_SYS,
+		CLK_FROM_REF,
+	} clk_from;
+	struct clk *clk_in, *clk_can;
+	unsigned long freq_calc;
+	struct mscan_priv *priv;
+	struct clk *clk_ipg;
+
+	/* the caller passed in the clock source spec that was read from
+	 * the device tree, get the optional clock divider as well
+	 */
+	np = ofdev->dev.of_node;
+	clockdiv = 1;
+	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+		clock_source ? clock_source : "<NULL>", clockdiv);
+
+	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+	 * get set, and the 'ips' clock is the input to the MSCAN
+	 * component
+	 *
+	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+	 * bit needs to get cleared, an optional clock-divider may have
+	 * been specified (the default value is 1), the appropriate
+	 * MSCAN related MCLK is the input to the MSCAN component
+	 *
+	 * in the absence of a clock-source spec, first an optimal clock
+	 * gets determined based on the 'sys' clock, if that fails the
+	 * 'ref' clock is used
+	 */
+	clk_from = CLK_FROM_AUTO;
+	if (clock_source) {
+		/* interpret the device tree's spec for the clock source */
+		if (!strcmp(clock_source, "ip"))
+			clk_from = CLK_FROM_IPS;
+		else if (!strcmp(clock_source, "sys"))
+			clk_from = CLK_FROM_SYS;
+		else if (!strcmp(clock_source, "ref"))
+			clk_from = CLK_FROM_REF;
+		else
+			goto err_invalid;
+		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, try the 'sys' clock; round to the
+		 * next MHz and see if we can get a multiple of 16MHz
+		 */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+		clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc +=  499999;
+		freq_calc /= 1000000;
+		freq_calc *= 1000000;
+		if ((freq_calc % 16000000) == 0) {
+			clk_from = CLK_FROM_SYS;
+			clockdiv = freq_calc / 16000000;
+			dev_dbg(&ofdev->dev,
+				"clk fit, sys[%lu] div[%d] freq[%lu]\n",
+				freq_calc, clockdiv, freq_calc / clockdiv);
+		}
+	}
+	if (clk_from == CLK_FROM_AUTO) {
+		/* no spec so far, use the 'ref' clock */
+		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+		clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_from = CLK_FROM_REF;
+		freq_calc = clk_get_rate(clk_in);
+		dev_dbg(&ofdev->dev,
+			"clk fit, ref[%lu] (no div) freq[%lu]\n",
+			freq_calc, freq_calc);
+	}
+
+	/* select IPS or MCLK as the MSCAN input (returned to the caller),
+	 * setup the MCLK mux source and rate if applicable, apply the
+	 * optionally specified or derived above divider, and determine
+	 * the actual resulting clock rate to return to the caller
+	 */
+	switch (clk_from) {
+	case CLK_FROM_IPS:
+		clk_can = devm_clk_get(&ofdev->dev, "ips");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	case CLK_FROM_SYS:
+	case CLK_FROM_REF:
+		clk_can = devm_clk_get(&ofdev->dev, "mclk");
+		if (IS_ERR(clk_can))
+			goto err_notavail;
+		priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+		priv->clk_can = clk_can;
+		if (clk_from == CLK_FROM_SYS)
+			clk_in = devm_clk_get(&ofdev->dev, "sys");
+		if (clk_from == CLK_FROM_REF)
+			clk_in = devm_clk_get(&ofdev->dev, "ref");
+		if (IS_ERR(clk_in))
+			goto err_notavail;
+		clk_set_parent(clk_can, clk_in);
+		freq_calc = clk_get_rate(clk_in);
+		freq_calc /= clockdiv;
+		clk_set_rate(clk_can, freq_calc);
+		freq_calc = clk_get_rate(clk_can);
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+			*mscan_clksrc, freq_calc);
+		break;
+	default:
+		goto err_invalid;
+	}
+
+	/* the above clk_can item is used for the bitrate, access to
+	 * the peripheral's register set needs the clk_ipg item
+	 */
+	clk_ipg = devm_clk_get(&ofdev->dev, "ipg");
+	if (IS_ERR(clk_ipg))
+		goto err_notavail_ipg;
+	if (clk_prepare_enable(clk_ipg))
+		goto err_notavail_ipg;
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	priv->clk_ipg = clk_ipg;
+
+	/* return the determined clock source rate */
+	return freq_calc;
+
+err_invalid:
+	dev_err(&ofdev->dev, "invalid clock source specification\n");
+	/* clock source rate could not get determined */
+	return 0;
+
+err_notavail:
+	dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n");
+	/* clock source rate could not get determined */
+	return 0;
+
+err_notavail_ipg:
+	dev_err(&ofdev->dev, "cannot acquire or setup register clock\n");
+	/* clock source rate could not get determined */
+	return 0;
+}
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+	struct mscan_priv *priv;
+
+	priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+	if (priv->clk_ipg)
+		clk_disable_unprepare(priv->clk_ipg);
+}
+
+#else	/* COMMON_CLK */
+
 struct mpc512x_clockctl {
 	u32 spmr;		/* System PLL Mode Reg */
 	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
@@ -239,12 +410,18 @@ exit_put:
 	of_node_put(np_clock);
 	return freq;
 }
+
+#define mpc512x_can_put_clock NULL
+
+#endif	/* COMMON_CLK */
+
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
 {
 	return 0;
 }
+#define mpc512x_can_put_clock NULL
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +563,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
 	.type = MSCAN_TYPE_MPC5200,
 	.get_clock = mpc52xx_can_get_clock,
+	/* .put_clock not applicable */
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
 	.type = MSCAN_TYPE_MPC5121,
 	.get_clock = mpc512x_can_get_clock,
+	.put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 28/31] powerpc/mpc512x: improve DIU related clock setup
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

adapt the DIU clock initialization to the COMMON_CLK approach:
device tree based clock lookup, prepare and unprepare for clocks,
work with frequencies not dividers, call the appropriate clk_*()
routines and don't access CCM registers, remove the pre-enable
workaround in the platform's clock driver

the "best clock" determination now completely relies on the
platform's clock driver to pick a frequency close to what the
caller requests, and merely checks whether the desired frequency
was met (is acceptable since it meets the tolerance of the monitor)

this approach shall succeed upon first try in the usual case,
will test a few less desirable yet acceptable frequencies in
edge cases, and will fallback to "best effort" if none of the
previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index afbb01d..fa95814 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -668,7 +668,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 }
 
 /*
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 28/31] powerpc/mpc512x: improve DIU related clock setup
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

adapt the DIU clock initialization to the COMMON_CLK approach:
device tree based clock lookup, prepare and unprepare for clocks,
work with frequencies not dividers, call the appropriate clk_*()
routines and don't access CCM registers, remove the pre-enable
workaround in the platform's clock driver

the "best clock" determination now completely relies on the
platform's clock driver to pick a frequency close to what the
caller requests, and merely checks whether the desired frequency
was met (is acceptable since it meets the tolerance of the monitor)

this approach shall succeed upon first try in the usual case,
will test a few less desirable yet acceptable frequencies in
edge cases, and will fallback to "best effort" if none of the
previously tried frequencies pass the test

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    1 -
 arch/powerpc/platforms/512x/mpc512x_shared.c  |  165 +++++++++++++------------
 2 files changed, 88 insertions(+), 78 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index afbb01d..fa95814 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -668,7 +668,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
 	/* some are not yet acquired by their respective drivers */
 	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
-	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
 }
 
 /*
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-#define DIU_DIV_MASK	0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-	unsigned long bestval, bestfreq, speed, busfreq;
-	unsigned long minpixclock, maxpixclock, pixval;
-	struct mpc512x_ccm __iomem *ccm;
 	struct device_node *np;
-	u32 temp;
-	long err;
-	int i;
+	struct clk *clk_diu;
+	unsigned long epsilon, minpixclock, maxpixclock;
+	unsigned long offset, want, got, delta;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	/* lookup and enable the DIU clock */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
 	if (!np) {
-		pr_err("Can't find clock control module.\n");
+		pr_err("Could not find DIU device tree node.\n");
 		return;
 	}
-
-	ccm = of_iomap(np, 0);
+	clk_diu = of_clk_get_by_name(np, "per");
 	of_node_put(np);
-	if (!ccm) {
-		pr_err("Can't map clock control module reg.\n");
+	if (IS_ERR(clk_diu)) {
+		pr_err("Could not lookup DIU clock.\n");
 		return;
 	}
-
-	np = of_find_node_by_type(NULL, "cpu");
-	if (np) {
-		const unsigned int *prop =
-			of_get_property(np, "bus-frequency", NULL);
-
-		of_node_put(np);
-		if (prop) {
-			busfreq = *prop;
-		} else {
-			pr_err("Can't get bus-frequency property\n");
-			return;
-		}
-	} else {
-		pr_err("Can't find 'cpu' node.\n");
+	if (clk_prepare_enable(clk_diu)) {
+		pr_err("Could not enable DIU clock.\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-	speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = (1000000000 / pixclock) * 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = temp / 20; /* pixclock * 0.05 */
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = LONG_MAX;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed / (pixval+i);
-		pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-			i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-			pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval + i;
-			bestfreq = temp;
-		}
+	/*
+	 * convert the picoseconds spec into the desired clock rate,
+	 * determine the acceptable clock range for the monitor (+/- 5%),
+	 * do the calculation in steps to avoid integer overflow
+	 */
+	pr_debug("DIU pixclock in ps - %u\n", pixclock);
+	pixclock = (1000000000 / pixclock) * 1000;
+	pr_debug("DIU pixclock freq  - %u\n", pixclock);
+	epsilon = pixclock / 20; /* pixclock * 0.05 */
+	pr_debug("DIU deviation      - %lu\n", epsilon);
+	minpixclock = pixclock - epsilon;
+	maxpixclock = pixclock + epsilon;
+	pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+	pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+	/*
+	 * check whether the DIU supports the desired pixel clock
+	 *
+	 * - simply request the desired clock and see what the
+	 *   platform's clock driver will make of it, assuming that it
+	 *   will setup the best approximation of the requested value
+	 * - try other candidate frequencies in the order of decreasing
+	 *   preference (i.e. with increasing distance from the desired
+	 *   pixel clock, and checking the lower frequency before the
+	 *   higher frequency to not overload the hardware) until the
+	 *   first match is found -- any potential subsequent match
+	 *   would only be as good as the former match or typically
+	 *   would be less preferrable
+	 *
+	 * the offset increment of pixelclock divided by 64 is an
+	 * arbitrary choice -- it's simple to calculate, in the typical
+	 * case we expect the first check to succeed already, in the
+	 * worst case seven frequencies get tested (the exact center and
+	 * three more values each to the left and to the right) before
+	 * the 5% tolerance window is exceeded, resulting in fast enough
+	 * execution yet high enough probability of finding a suitable
+	 * value, while the error rate will be in the order of single
+	 * percents
+	 */
+	for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+		want = pixclock - offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
+		if (!offset)
+			continue;
+		want = pixclock + offset;
+		pr_debug("DIU checking clock - %lu\n", want);
+		clk_set_rate(clk_diu, want);
+		got = clk_get_rate(clk_diu);
+		delta = abs(pixclock - got);
+		if (delta < epsilon)
+			break;
 	}
+	if (offset <= epsilon) {
+		pr_debug("DIU clock accepted - %lu\n", want);
+		pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+			 pixclock, got, delta, epsilon);
+		return;
+	}
+	pr_warn("DIU pixclock auto search unsuccessful\n");
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify DIU_DIV in CCM SCFR1 */
-	temp = in_be32(&ccm->scfr1);
-	pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-	temp &= ~DIU_DIV_MASK;
-	temp |= (bestval & DIU_DIV_MASK);
-	out_be32(&ccm->scfr1, temp);
-	pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-	iounmap(ccm);
+	/*
+	 * what is the most appropriate action to take when the search
+	 * for an available pixel clock which is acceptable to the
+	 * monitor has failed?  disable the DIU (clock) or just provide
+	 * a "best effort"?  we go with the latter
+	 */
+	pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+	clk_set_rate(clk_diu, pixclock);
+	got = clk_get_rate(clk_diu);
+	delta = abs(pixclock - got);
+	pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+		 pixclock, got, delta, epsilon);
 }
 
 enum fsl_diu_monitor_port
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig  |   14 +-
 arch/powerpc/platforms/512x/Makefile |    3 +-
 arch/powerpc/platforms/512x/clock.c  |  753 ----------------------------------
 3 files changed, 2 insertions(+), 768 deletions(-)
 delete mode 100644 arch/powerpc/platforms/512x/clock.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
-	bool "MPC512x platform uses COMMON_CLK"
-	default y
-	depends on PPC_MPC512x
-	help
-	  This option is only here to support tests and comparison
-	  during development and migration.  This option will get
-	  removed after the COMMON_CLK support for MPC512x has become
-	  fully operational and all drivers were adjusted to explicitly
-	  acquire their required clocks.
-
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
+	select COMMON_CLK
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK if !MPC512x_COMMON_CLK
-	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-$(CONFIG_PPC_CLOCK)		+= clock.o
-obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= clock-commonclk.o
 obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions Limited.
- *
- * 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 <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE	0x1	/* has rate in MHz */
-#define CLK_HAS_CTRL	0x2	/* has control reg and bit */
-
-struct clk {
-	struct list_head node;
-	char name[32];
-	int flags;
-	struct device *dev;
-	unsigned long rate;
-	struct module *owner;
-	void (*calc) (struct clk *);
-	struct clk *parent;
-	int reg, bit;		/* CLK_HAS_CTRL */
-	int div_shift;		/* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match;
-	int id_match;
-
-	if (dev == NULL || id == NULL)
-		return clk;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		dev_match = id_match = 0;
-
-		if (dev == p->dev)
-			dev_match++;
-		if (strcmp(id, p->name) == 0)
-			id_match++;
-		if ((dev_match || id_match) && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-	struct clk *p;
-
-	mutex_lock(&clocks_mutex);
-	printk(KERN_INFO "CLOCKS:\n");
-	list_for_each_entry(p, &clocks, node) {
-		pr_info("  %s=%ld", p->name, p->rate);
-		if (p->parent)
-			pr_cont(" %s=%ld", p->parent->name,
-			       p->parent->rate);
-		if (p->flags & CLK_HAS_CTRL)
-			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-		pr_cont("\n");
-	}
-	mutex_unlock(&clocks_mutex);
-}
-#define	DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define	DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[NRPSC];	/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask |= 1 << clk->bit;
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-	return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-	unsigned int mask;
-
-	if (clk->flags & CLK_HAS_CTRL) {
-		mask = in_be32(&clockctl->sccr[clk->reg]);
-		mask &= ~(1 << clk->bit);
-		out_be32(&clockctl->sccr[clk->reg], mask);
-	}
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-	if (clk->flags & CLK_HAS_RATE)
-		return clk->rate;
-	else
-		return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-	/*
-	 * Convert spmf to multiplier
-	 */
-	static int spmf_to_mult[] = {
-		68, 1, 12, 16,
-		20, 24, 28, 32,
-		36, 40, 44, 48,
-		52, 56, 60, 64
-	};
-	int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-	return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-	/*
-	 * Convert sysdiv to divisor x 2
-	 * Some divisors have fractional parts so
-	 * multiply by 2 then divide by this value
-	 */
-	static int sysdiv_to_div_x_2[] = {
-		4, 5, 6, 7,
-		8, 9, 10, 14,
-		12, 16, 18, 22,
-		20, 24, 26, 30,
-		28, 32, 34, 38,
-		36, 40, 42, 46,
-		44, 48, 50, 54,
-		52, 56, 58, 62,
-		60, 64, 66,
-	};
-	int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-	return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-	rate *= spmf_mult();
-	rate *= 2;
-	rate /= sysdiv_div_x_2();
-
-	return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-	rate *= sysdiv_div_x_2();
-	rate /= 2;
-	rate /= spmf_mult();
-
-	return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-	int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-	rate *= ips_div;	/* csb_clk = ips_clk * ips_div */
-	rate *= 2;		/* sys_clk = csb_clk * 2 */
-	return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-	struct device_node *np;
-	const unsigned int *prop;
-	unsigned int val = 0;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-	if (np) {
-		prop = of_get_property(np, clockname, NULL);
-		if (prop)
-			val = *prop;
-	    of_node_put(np);
-	}
-	return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = devtree_getfreq("bus-frequency");
-	if (rate == 0) {
-		printk(KERN_ERR "No bus-frequency in dev tree\n");
-		clk->rate = 0;
-		return;
-	}
-	clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-	.name = "ref_clk",
-	.calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-	clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-	.name = "sys_clk",
-	.calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-	int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-
-	rate *= 2;
-	rate /= diudiv_x_2;
-
-	clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-	unsigned long rate;
-
-	rate = sys_clk.rate;
-	rate /= 2;
-	clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-	int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-	clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-	.name = "csb_clk",
-	.calc = half_clk_calc,
-	.parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-	int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-	int ratex2 = clk->parent->rate * spmf;
-
-	clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-	.name = "e300_clk",
-	.calc = e300_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-	.name = "ips_clk",
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-	.name = "lpc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 30,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 29,
-	.calc = generic_div_clk_calc,
-	.parent = &ips_clk,
-	.div_shift = 8,
-};
-
-static struct clk pata_clk = {
-	.name = "pata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-	.name = "sata_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 14,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 13,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-	.name = "pci_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 0,
-	.bit = 11,
-	.calc = generic_div_clk_calc,
-	.parent = &csb_clk,
-	.div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-	.name = "diu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 31,
-	.calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-	.name = "viu_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 18,
-	.calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-	.name = "axe_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 30,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-	.name = "usb1_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 28,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-	.name = "usb2_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 27,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-	.name = "i2c_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 26,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-	.name = "mscan_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 25,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-	.name = "sdhc_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 24,
-	.calc = unity_clk_calc,
-	.parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-	.name = "mbx_bus_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 22,
-	.calc = half_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 21,
-	.calc = unity_clk_calc,
-	.parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-	.name = "mbx_3d_clk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 20,
-	.calc = generic_div_clk_calc,
-	.parent = &mbx_bus_clk,
-	.div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-	clk->rate = devtree_getfreq("psc_mclk_in");
-	if (!clk->rate)
-		clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-	.name = "psc_mclk_in",
-	.calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-	.name = "spdif_txclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-	.name = "spdif_rxclk",
-	.flags = CLK_HAS_CTRL,
-	.reg = 1,
-	.bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-	/* ac97 bit clock is always 24.567 MHz */
-	clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-	.name = "ac97_clk_in",
-	.calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-	&ref_clk,
-	&sys_clk,
-	&diu_clk,
-	&viu_clk,
-	&csb_clk,
-	&e300_clk,
-	&ips_clk,
-	&fec_clk,
-	&sata_clk,
-	&pata_clk,
-	&nfc_clk,
-	&lpc_clk,
-	&mbx_bus_clk,
-	&mbx_clk,
-	&mbx_3d_clk,
-	&axe_clk,
-	&usb1_clk,
-	&usb2_clk,
-	&i2c_clk,
-	&mscan_clk,
-	&sdhc_clk,
-	&pci_clk,
-	&psc_mclk_in,
-	&spdif_txclk,
-	&spdif_rxclk,
-	&ac97_clk,
-	NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-	if (clk->calc) {
-		clk->calc(clk);
-		clk->flags |= CLK_HAS_RATE;
-		clk_register(clk);
-	} else {
-		printk(KERN_WARNING
-		       "Could not initialize clk %s without a calc routine\n",
-		       clk->name);
-	}
-}
-
-static void rate_clks_init(void)
-{
-	struct clk **cpp, *clk;
-
-	cpp = rate_clks;
-	while ((clk = *cpp++))
-		rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-	int reg, bit;
-	struct clk *clk;
-
-	reg = 0;
-	bit = 27 - pscnum;
-
-	clk = &dev_clks[reg][bit];
-	clk->reg = 0;
-	clk->bit = bit;
-	return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-	unsigned long mclk_src = sys_clk.rate;
-	unsigned long mclk_div;
-
-	/*
-	 * Can only change value of mclk divider
-	 * when the divider is disabled.
-	 *
-	 * Zero is not a valid divider so minimum
-	 * divider is 1
-	 *
-	 * disable/set divider/enable
-	 */
-	out_be32(&clockctl->pccr[pscnum], 0);
-	out_be32(&clockctl->pccr[pscnum], 0x00020000);
-	out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-	if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-		clk->rate = spdif_rxclk.rate;
-		return;
-	}
-
-	switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-	case 0:
-		mclk_src = sys_clk.rate;
-		break;
-	case 1:
-		mclk_src = ref_clk.rate;
-		break;
-	case 2:
-		mclk_src = psc_mclk_in.rate;
-		break;
-	case 3:
-		mclk_src = spdif_txclk.rate;
-		break;
-	}
-
-	mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-	clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-	struct device_node *np;
-	struct platform_device *ofdev;
-	u32 reg;
-	const char *psc_compat;
-
-	psc_compat = mpc512x_select_psc_compat();
-	if (!psc_compat)
-		return;
-
-	for_each_compatible_node(np, NULL, psc_compat) {
-		if (!of_property_read_u32(np, "reg", &reg)) {
-			int pscnum = (reg & 0xf00) >> 8;
-			struct clk *clk = psc_dev_clk(pscnum);
-
-			clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-			ofdev = of_find_device_by_node(np);
-			clk->dev = &ofdev->dev;
-			/*
-			 * AC97 is special rate clock does
-			 * not go through normal path
-			 */
-			if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-				clk->rate = ac97_clk.rate;
-			else
-				psc_calc_rate(clk, pscnum, np);
-			sprintf(clk->name, "psc%d_mclk", pscnum);
-			clk_register(clk);
-			clk_enable(clk);
-		}
-	}
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-	.clk_get		= mpc5121_clk_get,
-	.clk_enable		= mpc5121_clk_enable,
-	.clk_disable		= mpc5121_clk_disable,
-	.clk_get_rate		= mpc5121_clk_get_rate,
-	.clk_put		= mpc5121_clk_put,
-	.clk_round_rate		= mpc5121_clk_round_rate,
-	.clk_set_rate		= mpc5121_clk_set_rate,
-	.clk_set_parent		= NULL,
-	.clk_get_parent		= NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-	if (np) {
-		clockctl = of_iomap(np, 0);
-		of_node_put(np);
-	}
-
-	if (!clockctl) {
-		printk(KERN_ERR "Could not map clock control registers\n");
-		return 0;
-	}
-
-	rate_clks_init();
-	psc_clks_init();
-
-	/* leave clockctl mapped forever */
-	/*iounmap(clockctl); */
-	DEBUG_CLK_DUMP();
-	clocks_initialized++;
-	clk_functions = mpc5121_clk_functions;
-	return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 30/31] net: can: mscan: remove non-CCF code for MPC512x
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

transition to the common clock framework has completed and the PPC_CLOCK
is no longer available for the MPC512x platform, remove the now obsolete
code path of the mpc5xxx mscan driver which accessed clock control
module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  141 -----------------------------------
 1 file changed, 141 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index f48f129..6b0c995 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,9 +109,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -277,144 +274,6 @@ static void mpc512x_can_put_clock(struct platform_device *ofdev)
 	if (priv->clk_ipg)
 		clk_disable_unprepare(priv->clk_ipg);
 }
-
-#else	/* COMMON_CLK */
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-
-#define mpc512x_can_put_clock NULL
-
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 30/31] net: can: mscan: remove non-CCF code for MPC512x
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

transition to the common clock framework has completed and the PPC_CLOCK
is no longer available for the MPC512x platform, remove the now obsolete
code path of the mpc5xxx mscan driver which accessed clock control
module registers directly

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 drivers/net/can/mscan/mpc5xxx_can.c |  141 -----------------------------------
 1 file changed, 141 deletions(-)

diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index f48f129..6b0c995 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,9 +109,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_source, int *mscan_clksrc)
 {
@@ -277,144 +274,6 @@ static void mpc512x_can_put_clock(struct platform_device *ofdev)
 	if (priv->clk_ipg)
 		clk_disable_unprepare(priv->clk_ipg);
 }
-
-#else	/* COMMON_CLK */
-
-struct mpc512x_clockctl {
-	u32 spmr;		/* System PLL Mode Reg */
-	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
-	u32 scfr1;		/* System Clk Freq Reg 1 */
-	u32 scfr2;		/* System Clk Freq Reg 2 */
-	u32 reserved;
-	u32 bcr;		/* Bread Crumb Reg */
-	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
-	u32 spccr;		/* SPDIF Clk Ctrl Reg */
-	u32 cccr;		/* CFM Clk Ctrl Reg */
-	u32 dccr;		/* DIU Clk Cnfg Reg */
-	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-	{ .compatible = "fsl,mpc5121-clock", },
-	{}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-				 const char *clock_name, int *mscan_clksrc)
-{
-	struct mpc512x_clockctl __iomem *clockctl;
-	struct device_node *np_clock;
-	struct clk *sys_clk, *ref_clk;
-	int plen, clockidx, clocksrc = -1;
-	u32 sys_freq, val, clockdiv = 1, freq = 0;
-	const u32 *pval;
-
-	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-	if (!np_clock) {
-		dev_err(&ofdev->dev, "couldn't find clock node\n");
-		return 0;
-	}
-	clockctl = of_iomap(np_clock, 0);
-	if (!clockctl) {
-		dev_err(&ofdev->dev, "couldn't map clock registers\n");
-		goto exit_put;
-	}
-
-	/* Determine the MSCAN device index from the peripheral's
-	 * physical address. Register address offsets against the
-	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
-	 */
-	pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-	BUG_ON(!pval || plen < sizeof(*pval));
-	clockidx = (*pval & 0x80) ? 1 : 0;
-	if (*pval & 0x2000)
-		clockidx += 2;
-
-	/*
-	 * Clock source and divider selection: 3 different clock sources
-	 * can be selected: "ip", "ref" or "sys". For the latter two, a
-	 * clock divider can be defined as well. If the clock source is
-	 * not specified by the device tree, we first try to find an
-	 * optimal CAN source clock based on the system clock. If that
-	 * is not posslible, the reference clock will be used.
-	 */
-	if (clock_name && !strcmp(clock_name, "ip")) {
-		*mscan_clksrc = MSCAN_CLKSRC_IPS;
-		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-	} else {
-		*mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-		pval = of_get_property(ofdev->dev.of_node,
-				       "fsl,mscan-clock-divider", &plen);
-		if (pval && plen == sizeof(*pval))
-			clockdiv = *pval;
-		if (!clockdiv)
-			clockdiv = 1;
-
-		if (!clock_name || !strcmp(clock_name, "sys")) {
-			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
-			if (IS_ERR(sys_clk)) {
-				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-				goto exit_unmap;
-			}
-			/* Get and round up/down sys clock rate */
-			sys_freq = 1000000 *
-				((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-			if (!clock_name) {
-				/* A multiple of 16 MHz would be optimal */
-				if ((sys_freq % 16000000) == 0) {
-					clocksrc = 0;
-					clockdiv = sys_freq / 16000000;
-					freq = sys_freq / clockdiv;
-				}
-			} else {
-				clocksrc = 0;
-				freq = sys_freq / clockdiv;
-			}
-		}
-
-		if (clocksrc < 0) {
-			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
-			if (IS_ERR(ref_clk)) {
-				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-				goto exit_unmap;
-			}
-			clocksrc = 1;
-			freq = clk_get_rate(ref_clk) / clockdiv;
-		}
-	}
-
-	/* Disable clock */
-	out_be32(&clockctl->mccr[clockidx], 0x0);
-	if (clocksrc >= 0) {
-		/* Set source and divider */
-		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-		out_be32(&clockctl->mccr[clockidx], val);
-		/* Enable clock */
-		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-	}
-
-	/* Enable MSCAN clock domain */
-	val = in_be32(&clockctl->sccr[1]);
-	if (!(val & (1 << 25)))
-		out_be32(&clockctl->sccr[1], val | (1 << 25));
-
-	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
-	iounmap(clockctl);
-exit_put:
-	of_node_put(np_clock);
-	return freq;
-}
-
-#define mpc512x_can_put_clock NULL
-
-#endif	/* COMMON_CLK */
-
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 				 const char *clock_name, int *mscan_clksrc)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 31/31] clk: mpc512x: remove remaining migration workarounds
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 20:44           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
	Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

remove the last clkdev registration call ("sys_clk" and "ref_clk"
for CAN), as well as the clkdev header inclusion and the "compat
registration" comment

all client lookups for clock items are device tree based now, no
compatibility alias names need to get provided any longer

remove the now obsolete TODO comment on trimming the list of pre-enabled
clock items, after all the respective peripheral drivers were adjusted

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index fa95814..621a8d9 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -522,8 +521,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	 *   specific and cannot get mapped to componsites (at least not
 	 *   a single one, maybe two of them, but see the comment about
 	 *   "intermediates are referenced from elsewhere, too")
-	 * - trim the list of auto-enabled clocks after drivers acquire
-	 *   them correctly as needed
 	 */
 
 	/* regardless of whether XTAL/OSC exists, have REF created */
@@ -653,10 +650,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* fixed frequency for AC97, always 24.567MHz */
 	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
 
-	/* clkdev registration for compatibility reasons */
-	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
 	/* some are essential yet never get claimed by any driver */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* [PATCH v4 31/31] clk: mpc512x: remove remaining migration workarounds
@ 2013-08-06 20:44           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

remove the last clkdev registration call ("sys_clk" and "ref_clk"
for CAN), as well as the clkdev header inclusion and the "compat
registration" comment

all client lookups for clock items are device tree based now, no
compatibility alias names need to get provided any longer

remove the now obsolete TODO comment on trimming the list of pre-enabled
clock items, after all the respective peripheral drivers were adjusted

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/clock-commonclk.c |    7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index fa95814..621a8d9 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
@@ -522,8 +521,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	 *   specific and cannot get mapped to componsites (at least not
 	 *   a single one, maybe two of them, but see the comment about
 	 *   "intermediates are referenced from elsewhere, too")
-	 * - trim the list of auto-enabled clocks after drivers acquire
-	 *   them correctly as needed
 	 */
 
 	/* regardless of whether XTAL/OSC exists, have REF created */
@@ -653,10 +650,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
 	/* fixed frequency for AC97, always 24.567MHz */
 	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
 
-	/* clkdev registration for compatibility reasons */
-	clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
-	clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-
 	/* enable some of the clocks here unconditionally because ... */
 	pr_debug("automatically enabling some clocks\n");
 	/* some are essential yet never get claimed by any driver */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-06 21:31           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 21:31 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

[ this is an overview on how to split the series if necessary ]

On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> 
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
>   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
>   handle clocks (appropriately acquire and setup them, hold references
>   during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
>   Kconfig option) in the PowerPC based MPC512x platform, which brings
>   device tree based clock lookup as well
> 
> although the series does touch several subsystems -- tty (serial), spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> the patches are strictly clock related or trivial
> 
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications

It was suggested that the series may not be kept together when
applying, i.e. that individual patches may need to take separate
routes through individual subsystem trees.

Here is how the parts of the series interact:
- parts 01-14 are apparent fixes and improvements to existing
  drivers, they may immediately get applied via their respective
  subsystems when they are considered acceptable in review
  (number 13 already was taken into clk-next)
- parts 15-16 are device tree improvements (providing previously
  lacking information on the hardware, plus introducing support
  for symbolic references in DT nodes), and can get applied
  immediately via their respective subsystem
- part 17 introduces the platform clock driver which provides
  common clock support (uses shared drivers and common
  infrastructure, is an OF clock provider) -- this patch
  introduces _and_ enables the driver which strictly depends on
  the device tree update from part 16, and when common clock
  support gets enabled all peripheral drivers shall have received
  their clock API use cleanup
- part 18 introduces clock specs in the device tree which is used
  for client side lookups (from within peripheral drivers), this
  part must not get applied before the OF clock provider from
  part 17
- parts 19-21 and 23-28 further adjust peripheral drivers _after_
  the common clock support and OF clock lookup have become
  available, they strictly depend on parts 17 and 18, finally
  bring peripheral drivers into the common clock world and remove
  workarounds in the backend which support migration
- parts 22 and 29-31 finally remove remaining compat and
  migration stuff that has become obsolete after everything else
  was adjusted (I'd happily re-spin the series to move 22 to the
  end if eliminating this seemingly out-of-order item helps,
  currently it's at that position since it finishes what patch 20
  and 21 have prepared, while I did not dare to squash SPI and
  UART related patches since they reside in different subsystems)

The above results in the following stages, when the series needs
to get split:
- parts 01-16 could be taken immediately and need not be kept in
  any order, as they don't depend on each other
- parts 17-18 could be taken after 01-16 all are in place (while
  18 requires 17)
- parts 19-28 (see the remark on 22) could be taken after 17 and
  18 are in place (22 depends on 20 and 21 but may get moved to
  any later position at will, all other parts don't depend on
  each other and can get applied in any order)
- parts 29-31 (and 22 if not applied so far) could be taken after
  all parts up to 28 were applied


Please consider that I'm not trying to be pushy :)  but that I
want to provide all the possible help and information on how the
series might get applied, assuming that it will pass review.  So
far there has not been objection, all feedback got addressed,
while explicit ACKs still are pending.

For your reference here is the stats and the (numbered) list of
files again:

0000-cover-letter.patch
0001-spi-mpc512x-cleanup-clock-API-use.patch
0002-serial-mpc512x-cleanup-clock-API-use.patch
0003-USB-fsl-mph-dr-of-cleanup-clock-API-use.patch
0004-mtd-mpc5121_nfc-cleanup-clock-API-use.patch
0005-media-fsl-viu-cleanup-clock-API-use.patch
0006-i2c-mpc-cleanup-clock-API-use.patch
0007-fs_enet-silence-a-build-warning-unused-variable.patch
0008-fs_enet-cleanup-clock-API-use.patch
0009-powerpc-fsl-pci-improve-clock-API-use.patch
0010-net-can-mscan-add-a-comment-on-reg-to-idx-mapping.patch
0011-net-can-mscan-improve-clock-API-use.patch
0012-powerpc-mpc512x-array-decl-for-MCLK-registers-in-CCM.patch
0013-clk-wrap-I-O-access-for-improved-portability.patch
0014-dts-mpc512x-prepare-for-preprocessor-support.patch
0015-dts-mpc512x-introduce-dt-bindings-clock-header.patch
0016-dts-mpc512x-add-clock-related-device-tree-specs.patch
0017-clk-mpc512x-introduce-COMMON_CLK-for-MPC512x.patch
0018-dts-mpc512x-add-clock-specs-for-client-lookups.patch
0019-clk-mpc512x-don-t-pre-enable-FEC-and-I2C-clocks.patch
0020-spi-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
0021-serial-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
0022-clk-mpc512x-remove-PSC-UART-SPI-compat-workarounds.patch
0023-serial-mpc512x-setup-the-PSC-FIFO-clock-as-well.patch
0024-USB-fsl-mph-dr-of-remove-now-obsolete-clock-lookup-n.patch
0025-mtd-mpc5121_nfc-remove-now-obsolete-clock-lookup-nam.patch
0026-media-fsl-viu-remove-now-obsolete-clock-lookup-name.patch
0027-net-can-mscan-add-common-clock-support-for-mpc512x.patch
0028-powerpc-mpc512x-improve-DIU-related-clock-setup.patch
0029-clk-mpc512x-switch-to-COMMON_CLK-remove-PPC_CLOCK.patch
0030-net-can-mscan-remove-non-CCF-code-for-MPC512x.patch
0031-clk-mpc512x-remove-remaining-migration-workarounds.patch

> Gerhard Sittig (31):
>   spi: mpc512x: cleanup clock API use
>   serial: mpc512x: cleanup clock API use
>   USB: fsl-mph-dr-of: cleanup clock API use
>   mtd: mpc5121_nfc: cleanup clock API use
>   [media] fsl-viu: cleanup clock API use
>   i2c: mpc: cleanup clock API use
>   fs_enet: silence a build warning (unused variable)
>   fs_enet: cleanup clock API use
>   powerpc/fsl-pci: improve clock API use
>   net: can: mscan: add a comment on reg to idx mapping
>   net: can: mscan: improve clock API use
>   powerpc: mpc512x: array decl for MCLK registers in CCM
>   clk: wrap I/O access for improved portability
>   dts: mpc512x: prepare for preprocessor support
>   dts: mpc512x: introduce dt-bindings/clock/ header
>   dts: mpc512x: add clock related device tree specs
>   clk: mpc512x: introduce COMMON_CLK for MPC512x
>   dts: mpc512x: add clock specs for client lookups
>   clk: mpc512x: don't pre-enable FEC and I2C clocks
>   spi: mpc512x: switch to CCF names in clock lookup
>   serial: mpc512x: switch to CCF names in clock lookup
>   clk: mpc512x: remove PSC (UART, SPI) compat workarounds
>   serial: mpc512x: setup the PSC FIFO clock as well
>   USB: fsl-mph-dr-of: remove now obsolete clock lookup name
>   mtd: mpc5121_nfc: remove now obsolete clock lookup name
>   [media] fsl-viu: remove now obsolete clock lookup name
>   net: can: mscan: add common clock support for mpc512x
>   powerpc/mpc512x: improve DIU related clock setup
>   clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
>   net: can: mscan: remove non-CCF code for MPC512x
>   clk: mpc512x: remove remaining migration workarounds
> 
>  arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
>  arch/powerpc/boot/dts/include/dt-bindings          |    1 +
>  arch/powerpc/boot/dts/mpc5121.dtsi                 |  110 ++-
>  arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
>  arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
>  arch/powerpc/include/asm/mpc5121.h                 |   18 +-
>  arch/powerpc/platforms/512x/Kconfig                |    2 +-
>  arch/powerpc/platforms/512x/Makefile               |    3 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c      |  716 +++++++++++++++++++
>  arch/powerpc/platforms/512x/clock.c                |  753 --------------------
>  arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
>  arch/powerpc/sysdev/fsl_pci.c                      |   22 +
>  drivers/clk/clk-divider.c                          |    6 +-
>  drivers/clk/clk-gate.c                             |    6 +-
>  drivers/clk/clk-mux.c                              |    6 +-
>  drivers/i2c/busses/i2c-mpc.c                       |   24 +
>  drivers/media/platform/fsl-viu.c                   |   23 +-
>  drivers/mtd/nand/mpc5121_nfc.c                     |   21 +-
>  drivers/net/can/mscan/mpc5xxx_can.c                |  281 +++++---
>  drivers/net/can/mscan/mscan.c                      |   27 +-
>  drivers/net/can/mscan/mscan.h                      |    3 +
>  .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   21 +-
>  drivers/spi/spi-mpc512x-psc.c                      |   60 +-
>  drivers/tty/serial/mpc52xx_uart.c                  |  179 ++++-
>  drivers/usb/host/fsl-mph-dr-of.c                   |   27 +-
>  include/dt-bindings/clock/mpc512x-clock.h          |   69 ++
>  include/linux/clk-provider.h                       |   33 +
>  include/linux/fs_enet_pd.h                         |    3 +
>  28 files changed, 1534 insertions(+), 1058 deletions(-)
>  create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
>  delete mode 100644 arch/powerpc/platforms/512x/clock.c
>  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-08-06 21:31           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-06 21:31 UTC (permalink / raw)
  To: linux-arm-kernel

[ this is an overview on how to split the series if necessary ]

On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> 
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
>   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
>   handle clocks (appropriately acquire and setup them, hold references
>   during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
>   Kconfig option) in the PowerPC based MPC512x platform, which brings
>   device tree based clock lookup as well
> 
> although the series does touch several subsystems -- tty (serial), spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> the patches are strictly clock related or trivial
> 
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications

It was suggested that the series may not be kept together when
applying, i.e. that individual patches may need to take separate
routes through individual subsystem trees.

Here is how the parts of the series interact:
- parts 01-14 are apparent fixes and improvements to existing
  drivers, they may immediately get applied via their respective
  subsystems when they are considered acceptable in review
  (number 13 already was taken into clk-next)
- parts 15-16 are device tree improvements (providing previously
  lacking information on the hardware, plus introducing support
  for symbolic references in DT nodes), and can get applied
  immediately via their respective subsystem
- part 17 introduces the platform clock driver which provides
  common clock support (uses shared drivers and common
  infrastructure, is an OF clock provider) -- this patch
  introduces _and_ enables the driver which strictly depends on
  the device tree update from part 16, and when common clock
  support gets enabled all peripheral drivers shall have received
  their clock API use cleanup
- part 18 introduces clock specs in the device tree which is used
  for client side lookups (from within peripheral drivers), this
  part must not get applied before the OF clock provider from
  part 17
- parts 19-21 and 23-28 further adjust peripheral drivers _after_
  the common clock support and OF clock lookup have become
  available, they strictly depend on parts 17 and 18, finally
  bring peripheral drivers into the common clock world and remove
  workarounds in the backend which support migration
- parts 22 and 29-31 finally remove remaining compat and
  migration stuff that has become obsolete after everything else
  was adjusted (I'd happily re-spin the series to move 22 to the
  end if eliminating this seemingly out-of-order item helps,
  currently it's at that position since it finishes what patch 20
  and 21 have prepared, while I did not dare to squash SPI and
  UART related patches since they reside in different subsystems)

The above results in the following stages, when the series needs
to get split:
- parts 01-16 could be taken immediately and need not be kept in
  any order, as they don't depend on each other
- parts 17-18 could be taken after 01-16 all are in place (while
  18 requires 17)
- parts 19-28 (see the remark on 22) could be taken after 17 and
  18 are in place (22 depends on 20 and 21 but may get moved to
  any later position at will, all other parts don't depend on
  each other and can get applied in any order)
- parts 29-31 (and 22 if not applied so far) could be taken after
  all parts up to 28 were applied


Please consider that I'm not trying to be pushy :)  but that I
want to provide all the possible help and information on how the
series might get applied, assuming that it will pass review.  So
far there has not been objection, all feedback got addressed,
while explicit ACKs still are pending.

For your reference here is the stats and the (numbered) list of
files again:

0000-cover-letter.patch
0001-spi-mpc512x-cleanup-clock-API-use.patch
0002-serial-mpc512x-cleanup-clock-API-use.patch
0003-USB-fsl-mph-dr-of-cleanup-clock-API-use.patch
0004-mtd-mpc5121_nfc-cleanup-clock-API-use.patch
0005-media-fsl-viu-cleanup-clock-API-use.patch
0006-i2c-mpc-cleanup-clock-API-use.patch
0007-fs_enet-silence-a-build-warning-unused-variable.patch
0008-fs_enet-cleanup-clock-API-use.patch
0009-powerpc-fsl-pci-improve-clock-API-use.patch
0010-net-can-mscan-add-a-comment-on-reg-to-idx-mapping.patch
0011-net-can-mscan-improve-clock-API-use.patch
0012-powerpc-mpc512x-array-decl-for-MCLK-registers-in-CCM.patch
0013-clk-wrap-I-O-access-for-improved-portability.patch
0014-dts-mpc512x-prepare-for-preprocessor-support.patch
0015-dts-mpc512x-introduce-dt-bindings-clock-header.patch
0016-dts-mpc512x-add-clock-related-device-tree-specs.patch
0017-clk-mpc512x-introduce-COMMON_CLK-for-MPC512x.patch
0018-dts-mpc512x-add-clock-specs-for-client-lookups.patch
0019-clk-mpc512x-don-t-pre-enable-FEC-and-I2C-clocks.patch
0020-spi-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
0021-serial-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
0022-clk-mpc512x-remove-PSC-UART-SPI-compat-workarounds.patch
0023-serial-mpc512x-setup-the-PSC-FIFO-clock-as-well.patch
0024-USB-fsl-mph-dr-of-remove-now-obsolete-clock-lookup-n.patch
0025-mtd-mpc5121_nfc-remove-now-obsolete-clock-lookup-nam.patch
0026-media-fsl-viu-remove-now-obsolete-clock-lookup-name.patch
0027-net-can-mscan-add-common-clock-support-for-mpc512x.patch
0028-powerpc-mpc512x-improve-DIU-related-clock-setup.patch
0029-clk-mpc512x-switch-to-COMMON_CLK-remove-PPC_CLOCK.patch
0030-net-can-mscan-remove-non-CCF-code-for-MPC512x.patch
0031-clk-mpc512x-remove-remaining-migration-workarounds.patch

> Gerhard Sittig (31):
>   spi: mpc512x: cleanup clock API use
>   serial: mpc512x: cleanup clock API use
>   USB: fsl-mph-dr-of: cleanup clock API use
>   mtd: mpc5121_nfc: cleanup clock API use
>   [media] fsl-viu: cleanup clock API use
>   i2c: mpc: cleanup clock API use
>   fs_enet: silence a build warning (unused variable)
>   fs_enet: cleanup clock API use
>   powerpc/fsl-pci: improve clock API use
>   net: can: mscan: add a comment on reg to idx mapping
>   net: can: mscan: improve clock API use
>   powerpc: mpc512x: array decl for MCLK registers in CCM
>   clk: wrap I/O access for improved portability
>   dts: mpc512x: prepare for preprocessor support
>   dts: mpc512x: introduce dt-bindings/clock/ header
>   dts: mpc512x: add clock related device tree specs
>   clk: mpc512x: introduce COMMON_CLK for MPC512x
>   dts: mpc512x: add clock specs for client lookups
>   clk: mpc512x: don't pre-enable FEC and I2C clocks
>   spi: mpc512x: switch to CCF names in clock lookup
>   serial: mpc512x: switch to CCF names in clock lookup
>   clk: mpc512x: remove PSC (UART, SPI) compat workarounds
>   serial: mpc512x: setup the PSC FIFO clock as well
>   USB: fsl-mph-dr-of: remove now obsolete clock lookup name
>   mtd: mpc5121_nfc: remove now obsolete clock lookup name
>   [media] fsl-viu: remove now obsolete clock lookup name
>   net: can: mscan: add common clock support for mpc512x
>   powerpc/mpc512x: improve DIU related clock setup
>   clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
>   net: can: mscan: remove non-CCF code for MPC512x
>   clk: mpc512x: remove remaining migration workarounds
> 
>  arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
>  arch/powerpc/boot/dts/include/dt-bindings          |    1 +
>  arch/powerpc/boot/dts/mpc5121.dtsi                 |  110 ++-
>  arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
>  arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
>  arch/powerpc/include/asm/mpc5121.h                 |   18 +-
>  arch/powerpc/platforms/512x/Kconfig                |    2 +-
>  arch/powerpc/platforms/512x/Makefile               |    3 +-
>  arch/powerpc/platforms/512x/clock-commonclk.c      |  716 +++++++++++++++++++
>  arch/powerpc/platforms/512x/clock.c                |  753 --------------------
>  arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
>  arch/powerpc/sysdev/fsl_pci.c                      |   22 +
>  drivers/clk/clk-divider.c                          |    6 +-
>  drivers/clk/clk-gate.c                             |    6 +-
>  drivers/clk/clk-mux.c                              |    6 +-
>  drivers/i2c/busses/i2c-mpc.c                       |   24 +
>  drivers/media/platform/fsl-viu.c                   |   23 +-
>  drivers/mtd/nand/mpc5121_nfc.c                     |   21 +-
>  drivers/net/can/mscan/mpc5xxx_can.c                |  281 +++++---
>  drivers/net/can/mscan/mscan.c                      |   27 +-
>  drivers/net/can/mscan/mscan.h                      |    3 +
>  .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   21 +-
>  drivers/spi/spi-mpc512x-psc.c                      |   60 +-
>  drivers/tty/serial/mpc52xx_uart.c                  |  179 ++++-
>  drivers/usb/host/fsl-mph-dr-of.c                   |   27 +-
>  include/dt-bindings/clock/mpc512x-clock.h          |   69 ++
>  include/linux/clk-provider.h                       |   33 +
>  include/linux/fs_enet_pd.h                         |    3 +
>  28 files changed, 1534 insertions(+), 1058 deletions(-)
>  create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
>  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
>  delete mode 100644 arch/powerpc/platforms/512x/clock.c
>  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 11/31] net: can: mscan: improve clock API use
  2013-08-06 20:43           ` Gerhard Sittig
@ 2013-08-07  7:28             ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-08-07  7:28 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 5490 bytes --]

On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities
> 
> prepare and enable the clocks in open(), disable and unprepare the
> clocks in close() if clocks were acquired during probe(), to not assume
> knowledge about which activities are done in probe() and remove()
> 
> use devm_get_clk() to lookup the SYS and REF clocks, to have the clocks
> put upon device shutdown
> 
> store pointers to data structures upon successful allocation already
> instead of deferral until complete setup, such that subroutines in the
> setup sequence may access those data structures as well to track their
> resource acquisition
> 
> since clock allocation remains optional, the release callback as well as
> the enable/disable calls in open/close are optional as well
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |   18 ++++++++++++------
>  drivers/net/can/mscan/mscan.c       |   27 ++++++++++++++++++++++++++-
>  drivers/net/can/mscan/mscan.h       |    3 +++
>  3 files changed, 41 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index bc422ba..e59b3a3 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
>  	unsigned int type;
>  	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
>  			 int *mscan_clksrc);
> +	void (*put_clock)(struct platform_device *ofdev);
>  };
>  
>  #ifdef CONFIG_PPC_MPC52xx
> @@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  			clockdiv = 1;
>  
>  		if (!clock_name || !strcmp(clock_name, "sys")) {
> -			sys_clk = clk_get(&ofdev->dev, "sys_clk");
> +			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
>  			if (IS_ERR(sys_clk)) {
>  				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
>  				goto exit_unmap;
> @@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  		}
>  
>  		if (clocksrc < 0) {
> -			ref_clk = clk_get(&ofdev->dev, "ref_clk");
> +			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
>  			if (IS_ERR(ref_clk)) {
>  				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
>  				goto exit_unmap;
> @@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
>  	dev = alloc_mscandev();
>  	if (!dev)
>  		goto exit_dispose_irq;
> +	platform_set_drvdata(ofdev, dev);
> +	SET_NETDEV_DEV(dev, &ofdev->dev);
>  
>  	priv = netdev_priv(dev);
>  	priv->reg_base = base;
> @@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
>  		goto exit_free_mscan;
>  	}
>  
> -	SET_NETDEV_DEV(dev, &ofdev->dev);
> -
>  	err = register_mscandev(dev, mscan_clksrc);
>  	if (err) {
>  		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
> @@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
>  		goto exit_free_mscan;
>  	}
>  
> -	platform_set_drvdata(ofdev, dev);
> -
>  	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
>  		 priv->reg_base, dev->irq, priv->can.clock.freq);
>  
> @@ -324,10 +323,17 @@ exit_unmap_mem:
>  
>  static int mpc5xxx_can_remove(struct platform_device *ofdev)
>  {
> +	const struct of_device_id *match;
> +	const struct mpc5xxx_can_data *data;
>  	struct net_device *dev = platform_get_drvdata(ofdev);
>  	struct mscan_priv *priv = netdev_priv(dev);
>  
> +	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
> +	data = match ? match->data : NULL;
> +
>  	unregister_mscandev(dev);
> +	if (data && data->put_clock)
> +		data->put_clock(ofdev);
>  	iounmap(priv->reg_base);
>  	irq_dispose_mapping(dev->irq);
>  	free_candev(dev);
> diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> index e6b4095..4f998f5 100644
> --- a/drivers/net/can/mscan/mscan.c
> +++ b/drivers/net/can/mscan/mscan.c
> @@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
>  	struct mscan_priv *priv = netdev_priv(dev);
>  	struct mscan_regs __iomem *regs = priv->reg_base;
>  
> +	if (priv->clk_ipg) {
> +		ret = clk_prepare_enable(priv->clk_ipg);
> +		if (ret)
> +			goto exit_retcode;
> +	}
> +	if (priv->clk_can) {
> +		ret = clk_prepare_enable(priv->clk_can);
> +		if (ret) {
> +			if (priv->clk_ipg)
> +				clk_disable_unprepare(priv->clk_ipg);
> +			goto exit_retcode;

Why don't you add another jump label and jump to that to disable the
ipkg clock?


> +		}
> +	}
> +
>  	/* common open */
>  	ret = open_candev(dev);
>  	if (ret)
> -		return ret;
> +		goto exit_dis_clock;
>  
>  	napi_enable(&priv->napi);
>  
> @@ -604,6 +618,12 @@ exit_free_irq:
>  exit_napi_disable:
>  	napi_disable(&priv->napi);
>  	close_candev(dev);
> +exit_dis_clock:
> +	if (priv->clk_can)
> +		clk_disable_unprepare(priv->clk_can);
> +	if (priv->clk_ipg)
> +		clk_disable_unprepare(priv->clk_ipg);
> +exit_retcode:
>  	return ret;
>  }

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 11/31] net: can: mscan: improve clock API use
@ 2013-08-07  7:28             ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-08-07  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities
> 
> prepare and enable the clocks in open(), disable and unprepare the
> clocks in close() if clocks were acquired during probe(), to not assume
> knowledge about which activities are done in probe() and remove()
> 
> use devm_get_clk() to lookup the SYS and REF clocks, to have the clocks
> put upon device shutdown
> 
> store pointers to data structures upon successful allocation already
> instead of deferral until complete setup, such that subroutines in the
> setup sequence may access those data structures as well to track their
> resource acquisition
> 
> since clock allocation remains optional, the release callback as well as
> the enable/disable calls in open/close are optional as well
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/net/can/mscan/mpc5xxx_can.c |   18 ++++++++++++------
>  drivers/net/can/mscan/mscan.c       |   27 ++++++++++++++++++++++++++-
>  drivers/net/can/mscan/mscan.h       |    3 +++
>  3 files changed, 41 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index bc422ba..e59b3a3 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
>  	unsigned int type;
>  	u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
>  			 int *mscan_clksrc);
> +	void (*put_clock)(struct platform_device *ofdev);
>  };
>  
>  #ifdef CONFIG_PPC_MPC52xx
> @@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  			clockdiv = 1;
>  
>  		if (!clock_name || !strcmp(clock_name, "sys")) {
> -			sys_clk = clk_get(&ofdev->dev, "sys_clk");
> +			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
>  			if (IS_ERR(sys_clk)) {
>  				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
>  				goto exit_unmap;
> @@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
>  		}
>  
>  		if (clocksrc < 0) {
> -			ref_clk = clk_get(&ofdev->dev, "ref_clk");
> +			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
>  			if (IS_ERR(ref_clk)) {
>  				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
>  				goto exit_unmap;
> @@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
>  	dev = alloc_mscandev();
>  	if (!dev)
>  		goto exit_dispose_irq;
> +	platform_set_drvdata(ofdev, dev);
> +	SET_NETDEV_DEV(dev, &ofdev->dev);
>  
>  	priv = netdev_priv(dev);
>  	priv->reg_base = base;
> @@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
>  		goto exit_free_mscan;
>  	}
>  
> -	SET_NETDEV_DEV(dev, &ofdev->dev);
> -
>  	err = register_mscandev(dev, mscan_clksrc);
>  	if (err) {
>  		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
> @@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
>  		goto exit_free_mscan;
>  	}
>  
> -	platform_set_drvdata(ofdev, dev);
> -
>  	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
>  		 priv->reg_base, dev->irq, priv->can.clock.freq);
>  
> @@ -324,10 +323,17 @@ exit_unmap_mem:
>  
>  static int mpc5xxx_can_remove(struct platform_device *ofdev)
>  {
> +	const struct of_device_id *match;
> +	const struct mpc5xxx_can_data *data;
>  	struct net_device *dev = platform_get_drvdata(ofdev);
>  	struct mscan_priv *priv = netdev_priv(dev);
>  
> +	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
> +	data = match ? match->data : NULL;
> +
>  	unregister_mscandev(dev);
> +	if (data && data->put_clock)
> +		data->put_clock(ofdev);
>  	iounmap(priv->reg_base);
>  	irq_dispose_mapping(dev->irq);
>  	free_candev(dev);
> diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> index e6b4095..4f998f5 100644
> --- a/drivers/net/can/mscan/mscan.c
> +++ b/drivers/net/can/mscan/mscan.c
> @@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
>  	struct mscan_priv *priv = netdev_priv(dev);
>  	struct mscan_regs __iomem *regs = priv->reg_base;
>  
> +	if (priv->clk_ipg) {
> +		ret = clk_prepare_enable(priv->clk_ipg);
> +		if (ret)
> +			goto exit_retcode;
> +	}
> +	if (priv->clk_can) {
> +		ret = clk_prepare_enable(priv->clk_can);
> +		if (ret) {
> +			if (priv->clk_ipg)
> +				clk_disable_unprepare(priv->clk_ipg);
> +			goto exit_retcode;

Why don't you add another jump label and jump to that to disable the
ipkg clock?


> +		}
> +	}
> +
>  	/* common open */
>  	ret = open_candev(dev);
>  	if (ret)
> -		return ret;
> +		goto exit_dis_clock;
>  
>  	napi_enable(&priv->napi);
>  
> @@ -604,6 +618,12 @@ exit_free_irq:
>  exit_napi_disable:
>  	napi_disable(&priv->napi);
>  	close_candev(dev);
> +exit_dis_clock:
> +	if (priv->clk_can)
> +		clk_disable_unprepare(priv->clk_can);
> +	if (priv->clk_ipg)
> +		clk_disable_unprepare(priv->clk_ipg);
> +exit_retcode:
>  	return ret;
>  }

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/ff55f5e9/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 11/31] net: can: mscan: improve clock API use
  2013-08-06 20:43           ` Gerhard Sittig
@ 2013-08-07  7:30             ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-08-07  7:30 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 636 bytes --]

On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities

AFAICS With this patch put_clock() is still a no-op, is there a patch
which adds some code there? If not, please remove.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 11/31] net: can: mscan: improve clock API use
@ 2013-08-07  7:30             ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-08-07  7:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
> the .get_clock() callback is run from probe() and might allocate
> resources, introduce a .put_clock() callback that is run from remove()
> to undo any allocation activities

AFAICS With this patch put_clock() is still a no-op, is there a patch
which adds some code there? If not, please remove.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/aad307fe/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 11/31] net: can: mscan: improve clock API use
  2013-08-07  7:30             ` Marc Kleine-Budde
@ 2013-08-07  7:35               ` Marc Kleine-Budde
  -1 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-08-07  7:35 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 739 bytes --]

On 08/07/2013 09:30 AM, Marc Kleine-Budde wrote:
> On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
>> the .get_clock() callback is run from probe() and might allocate
>> resources, introduce a .put_clock() callback that is run from remove()
>> to undo any allocation activities
> 
> AFAICS With this patch put_clock() is still a no-op, is there a patch
> which adds some code there? If not, please remove.

I missed patch 27.

sorry for the noise.
Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 11/31] net: can: mscan: improve clock API use
@ 2013-08-07  7:35               ` Marc Kleine-Budde
  0 siblings, 0 replies; 432+ messages in thread
From: Marc Kleine-Budde @ 2013-08-07  7:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/07/2013 09:30 AM, Marc Kleine-Budde wrote:
> On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
>> the .get_clock() callback is run from probe() and might allocate
>> resources, introduce a .put_clock() callback that is run from remove()
>> to undo any allocation activities
> 
> AFAICS With this patch put_clock() is still a no-op, is there a patch
> which adds some code there? If not, please remove.

I missed patch 27.

sorry for the noise.
Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 259 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/1214eb32/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-08-06 21:31           ` Gerhard Sittig
@ 2013-08-07  7:36             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-07  7:36 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree, Wolfram Sang,
	Mauro Carvalho Chehab, David Woodhouse, Wolfgang Grandegger,
	Marc Kleine-Budde, Pantelis Antoniou, Mark Brown,
	Greg Kroah-Hartman, Rob Herring, Detlev Zundel

[ no change in content, but order shuffling for better application ]

On Tue, Aug 06, 2013 at 23:31 +0200, Gerhard Sittig wrote:
> 
> [ this is an overview on how to split the series if necessary ]
> 
> On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> > 
> > this series
> > - fixes several drivers that are used in the MPC512x platform (UART,
> >   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> >   handle clocks (appropriately acquire and setup them, hold references
> >   during use, release clocks after use)
> > - introduces support for the common clock framework (CCF, COMMON_CLK
> >   Kconfig option) in the PowerPC based MPC512x platform, which brings
> >   device tree based clock lookup as well
> > 
> > although the series does touch several subsystems -- tty (serial), spi,
> > net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> > the patches are strictly clock related or trivial
> > 
> > it appears most appropriate to take this series through either the clk
> > or the powerpc trees after it has passed review and other subsystem
> > maintainers ACKed the clock setup related driver modifications
> 
> It was suggested that the series may not be kept together when
> applying, i.e. that individual patches may need to take separate
> routes through individual subsystem trees.
> 
> Here is how the parts of the series interact:
> - parts 01-14 are apparent fixes and improvements to existing
>   drivers, they may immediately get applied via their respective
>   subsystems when they are considered acceptable in review
>   (number 13 already was taken into clk-next)
> - parts 15-16 are device tree improvements (providing previously
>   lacking information on the hardware, plus introducing support
>   for symbolic references in DT nodes), and can get applied
>   immediately via their respective subsystem
> - part 17 introduces the platform clock driver which provides
>   common clock support (uses shared drivers and common
>   infrastructure, is an OF clock provider) -- this patch
>   introduces _and_ enables the driver which strictly depends on
>   the device tree update from part 16, and when common clock
>   support gets enabled all peripheral drivers shall have received
>   their clock API use cleanup
> - part 18 introduces clock specs in the device tree which is used
>   for client side lookups (from within peripheral drivers), this
>   part must not get applied before the OF clock provider from
>   part 17
> - parts 19-21 and 23-28 further adjust peripheral drivers _after_
>   the common clock support and OF clock lookup have become
>   available, they strictly depend on parts 17 and 18, finally
>   bring peripheral drivers into the common clock world and remove
>   workarounds in the backend which support migration
> - parts 22 and 29-31 finally remove remaining compat and
>   migration stuff that has become obsolete after everything else
>   was adjusted (I'd happily re-spin the series to move 22 to the
>   end if eliminating this seemingly out-of-order item helps,
>   currently it's at that position since it finishes what patch 20
>   and 21 have prepared, while I did not dare to squash SPI and
>   UART related patches since they reside in different subsystems)
> 
> The above results in the following stages, when the series needs
> to get split:
> - parts 01-16 could be taken immediately and need not be kept in
>   any order, as they don't depend on each other
> - parts 17-18 could be taken after 01-16 all are in place (while
>   18 requires 17)
> - parts 19-28 (see the remark on 22) could be taken after 17 and
>   18 are in place (22 depends on 20 and 21 but may get moved to
>   any later position at will, all other parts don't depend on
>   each other and can get applied in any order)
> - parts 29-31 (and 22 if not applied so far) could be taken after
>   all parts up to 28 were applied

Here I erred.  The order of the patches within phase 3 appears to
actually matter.  I'm sorry for bothering you again.

While the _content_ of the patches (which manipulation gets done
to the source) is correct and independent from neighbour patches,
yet a patch in that third phase will change the _context_ of
subsequent patches.  The sum of all the patches applied will be
identical again, but changed order of application may cause
conflicts (regardless of how simple to resolve they may be).

Build and run tests and the organization of v4 (immediate removal
upon driver adjustment) have shown that removing a migration
workaround in the very moment where driver adjustment obsoletes
it keeps the system operational.  I consider this a very positive
feature, and would only rearrange the order if the series'
content was ACKed in complete.

Moving removal of the workarounds to a later point in time won't
affect operation (just leaves the workaround in place a little
longer, while it does not harm), and will eliminate potential for
conflicts.  This I would do when accepting the series was
decided, to not lose the precious test feature during
development.

A byproduct of this rearrangement is that patches in phase 3
won't any longer touch a peripheral driver _and_ the clock driver
within a single patch, for whatever that may be worth.


So I suggest the following:

I can move parts 19 and 22 (completely) and the "workaround
removal" aspect of parts 20-21 and 23-28 to a later point in the
sequence, maybe squash them with part 31 (cleanup after migration
has completed).

This allows for even better (conflict free) application of the
series through individual and most appropriate trees.  All of
this of course assumes that the series passes review, and that
you agree on the outlined application in four phases if the
series cannot be kept together:
- clock API use cleanup for peripheral drivers, and device tree
  update to provide previously missing hardware information
- introduction of the platform clock driver and OF clock lookup
- adjustment of peripheral drivers after common clock support has
  become available
- removal of migration support and compat workarounds after
  migration has completed


> Please consider that I'm not trying to be pushy :)  but that I
> want to provide all the possible help and information on how the
> series might get applied, assuming that it will pass review.  So
> far there has not been objection, all feedback got addressed,
> while explicit ACKs still are pending.
> 
> For your reference here is the stats and the (numbered) list of
> files again:
> 
> 0000-cover-letter.patch
> 0001-spi-mpc512x-cleanup-clock-API-use.patch
> 0002-serial-mpc512x-cleanup-clock-API-use.patch
> 0003-USB-fsl-mph-dr-of-cleanup-clock-API-use.patch
> 0004-mtd-mpc5121_nfc-cleanup-clock-API-use.patch
> 0005-media-fsl-viu-cleanup-clock-API-use.patch
> 0006-i2c-mpc-cleanup-clock-API-use.patch
> 0007-fs_enet-silence-a-build-warning-unused-variable.patch
> 0008-fs_enet-cleanup-clock-API-use.patch
> 0009-powerpc-fsl-pci-improve-clock-API-use.patch
> 0010-net-can-mscan-add-a-comment-on-reg-to-idx-mapping.patch
> 0011-net-can-mscan-improve-clock-API-use.patch
> 0012-powerpc-mpc512x-array-decl-for-MCLK-registers-in-CCM.patch
> 0013-clk-wrap-I-O-access-for-improved-portability.patch
> 0014-dts-mpc512x-prepare-for-preprocessor-support.patch
> 0015-dts-mpc512x-introduce-dt-bindings-clock-header.patch
> 0016-dts-mpc512x-add-clock-related-device-tree-specs.patch
> 0017-clk-mpc512x-introduce-COMMON_CLK-for-MPC512x.patch
> 0018-dts-mpc512x-add-clock-specs-for-client-lookups.patch
> 0019-clk-mpc512x-don-t-pre-enable-FEC-and-I2C-clocks.patch
> 0020-spi-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
> 0021-serial-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
> 0022-clk-mpc512x-remove-PSC-UART-SPI-compat-workarounds.patch
> 0023-serial-mpc512x-setup-the-PSC-FIFO-clock-as-well.patch
> 0024-USB-fsl-mph-dr-of-remove-now-obsolete-clock-lookup-n.patch
> 0025-mtd-mpc5121_nfc-remove-now-obsolete-clock-lookup-nam.patch
> 0026-media-fsl-viu-remove-now-obsolete-clock-lookup-name.patch
> 0027-net-can-mscan-add-common-clock-support-for-mpc512x.patch
> 0028-powerpc-mpc512x-improve-DIU-related-clock-setup.patch
> 0029-clk-mpc512x-switch-to-COMMON_CLK-remove-PPC_CLOCK.patch
> 0030-net-can-mscan-remove-non-CCF-code-for-MPC512x.patch
> 0031-clk-mpc512x-remove-remaining-migration-workarounds.patch
> 
> > Gerhard Sittig (31):
> >   spi: mpc512x: cleanup clock API use
> >   serial: mpc512x: cleanup clock API use
> >   USB: fsl-mph-dr-of: cleanup clock API use
> >   mtd: mpc5121_nfc: cleanup clock API use
> >   [media] fsl-viu: cleanup clock API use
> >   i2c: mpc: cleanup clock API use
> >   fs_enet: silence a build warning (unused variable)
> >   fs_enet: cleanup clock API use
> >   powerpc/fsl-pci: improve clock API use
> >   net: can: mscan: add a comment on reg to idx mapping
> >   net: can: mscan: improve clock API use
> >   powerpc: mpc512x: array decl for MCLK registers in CCM
> >   clk: wrap I/O access for improved portability
> >   dts: mpc512x: prepare for preprocessor support
> >   dts: mpc512x: introduce dt-bindings/clock/ header
> >   dts: mpc512x: add clock related device tree specs
> >   clk: mpc512x: introduce COMMON_CLK for MPC512x
> >   dts: mpc512x: add clock specs for client lookups
> >   clk: mpc512x: don't pre-enable FEC and I2C clocks
> >   spi: mpc512x: switch to CCF names in clock lookup
> >   serial: mpc512x: switch to CCF names in clock lookup
> >   clk: mpc512x: remove PSC (UART, SPI) compat workarounds
> >   serial: mpc512x: setup the PSC FIFO clock as well
> >   USB: fsl-mph-dr-of: remove now obsolete clock lookup name
> >   mtd: mpc5121_nfc: remove now obsolete clock lookup name
> >   [media] fsl-viu: remove now obsolete clock lookup name
> >   net: can: mscan: add common clock support for mpc512x
> >   powerpc/mpc512x: improve DIU related clock setup
> >   clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
> >   net: can: mscan: remove non-CCF code for MPC512x
> >   clk: mpc512x: remove remaining migration workarounds
> > 
> >  arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
> >  arch/powerpc/boot/dts/include/dt-bindings          |    1 +
> >  arch/powerpc/boot/dts/mpc5121.dtsi                 |  110 ++-
> >  arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
> >  arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
> >  arch/powerpc/include/asm/mpc5121.h                 |   18 +-
> >  arch/powerpc/platforms/512x/Kconfig                |    2 +-
> >  arch/powerpc/platforms/512x/Makefile               |    3 +-
> >  arch/powerpc/platforms/512x/clock-commonclk.c      |  716 +++++++++++++++++++
> >  arch/powerpc/platforms/512x/clock.c                |  753 --------------------
> >  arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
> >  arch/powerpc/sysdev/fsl_pci.c                      |   22 +
> >  drivers/clk/clk-divider.c                          |    6 +-
> >  drivers/clk/clk-gate.c                             |    6 +-
> >  drivers/clk/clk-mux.c                              |    6 +-
> >  drivers/i2c/busses/i2c-mpc.c                       |   24 +
> >  drivers/media/platform/fsl-viu.c                   |   23 +-
> >  drivers/mtd/nand/mpc5121_nfc.c                     |   21 +-
> >  drivers/net/can/mscan/mpc5xxx_can.c                |  281 +++++---
> >  drivers/net/can/mscan/mscan.c                      |   27 +-
> >  drivers/net/can/mscan/mscan.h                      |    3 +
> >  .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   21 +-
> >  drivers/spi/spi-mpc512x-psc.c                      |   60 +-
> >  drivers/tty/serial/mpc52xx_uart.c                  |  179 ++++-
> >  drivers/usb/host/fsl-mph-dr-of.c                   |   27 +-
> >  include/dt-bindings/clock/mpc512x-clock.h          |   69 ++
> >  include/linux/clk-provider.h                       |   33 +
> >  include/linux/fs_enet_pd.h                         |    3 +
> >  28 files changed, 1534 insertions(+), 1058 deletions(-)
> >  create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
> >  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> >  delete mode 100644 arch/powerpc/platforms/512x/clock.c
> >  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-08-07  7:36             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-07  7:36 UTC (permalink / raw)
  To: linux-arm-kernel

[ no change in content, but order shuffling for better application ]

On Tue, Aug 06, 2013 at 23:31 +0200, Gerhard Sittig wrote:
> 
> [ this is an overview on how to split the series if necessary ]
> 
> On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> > 
> > this series
> > - fixes several drivers that are used in the MPC512x platform (UART,
> >   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> >   handle clocks (appropriately acquire and setup them, hold references
> >   during use, release clocks after use)
> > - introduces support for the common clock framework (CCF, COMMON_CLK
> >   Kconfig option) in the PowerPC based MPC512x platform, which brings
> >   device tree based clock lookup as well
> > 
> > although the series does touch several subsystems -- tty (serial), spi,
> > net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> > the patches are strictly clock related or trivial
> > 
> > it appears most appropriate to take this series through either the clk
> > or the powerpc trees after it has passed review and other subsystem
> > maintainers ACKed the clock setup related driver modifications
> 
> It was suggested that the series may not be kept together when
> applying, i.e. that individual patches may need to take separate
> routes through individual subsystem trees.
> 
> Here is how the parts of the series interact:
> - parts 01-14 are apparent fixes and improvements to existing
>   drivers, they may immediately get applied via their respective
>   subsystems when they are considered acceptable in review
>   (number 13 already was taken into clk-next)
> - parts 15-16 are device tree improvements (providing previously
>   lacking information on the hardware, plus introducing support
>   for symbolic references in DT nodes), and can get applied
>   immediately via their respective subsystem
> - part 17 introduces the platform clock driver which provides
>   common clock support (uses shared drivers and common
>   infrastructure, is an OF clock provider) -- this patch
>   introduces _and_ enables the driver which strictly depends on
>   the device tree update from part 16, and when common clock
>   support gets enabled all peripheral drivers shall have received
>   their clock API use cleanup
> - part 18 introduces clock specs in the device tree which is used
>   for client side lookups (from within peripheral drivers), this
>   part must not get applied before the OF clock provider from
>   part 17
> - parts 19-21 and 23-28 further adjust peripheral drivers _after_
>   the common clock support and OF clock lookup have become
>   available, they strictly depend on parts 17 and 18, finally
>   bring peripheral drivers into the common clock world and remove
>   workarounds in the backend which support migration
> - parts 22 and 29-31 finally remove remaining compat and
>   migration stuff that has become obsolete after everything else
>   was adjusted (I'd happily re-spin the series to move 22 to the
>   end if eliminating this seemingly out-of-order item helps,
>   currently it's at that position since it finishes what patch 20
>   and 21 have prepared, while I did not dare to squash SPI and
>   UART related patches since they reside in different subsystems)
> 
> The above results in the following stages, when the series needs
> to get split:
> - parts 01-16 could be taken immediately and need not be kept in
>   any order, as they don't depend on each other
> - parts 17-18 could be taken after 01-16 all are in place (while
>   18 requires 17)
> - parts 19-28 (see the remark on 22) could be taken after 17 and
>   18 are in place (22 depends on 20 and 21 but may get moved to
>   any later position at will, all other parts don't depend on
>   each other and can get applied in any order)
> - parts 29-31 (and 22 if not applied so far) could be taken after
>   all parts up to 28 were applied

Here I erred.  The order of the patches within phase 3 appears to
actually matter.  I'm sorry for bothering you again.

While the _content_ of the patches (which manipulation gets done
to the source) is correct and independent from neighbour patches,
yet a patch in that third phase will change the _context_ of
subsequent patches.  The sum of all the patches applied will be
identical again, but changed order of application may cause
conflicts (regardless of how simple to resolve they may be).

Build and run tests and the organization of v4 (immediate removal
upon driver adjustment) have shown that removing a migration
workaround in the very moment where driver adjustment obsoletes
it keeps the system operational.  I consider this a very positive
feature, and would only rearrange the order if the series'
content was ACKed in complete.

Moving removal of the workarounds to a later point in time won't
affect operation (just leaves the workaround in place a little
longer, while it does not harm), and will eliminate potential for
conflicts.  This I would do when accepting the series was
decided, to not lose the precious test feature during
development.

A byproduct of this rearrangement is that patches in phase 3
won't any longer touch a peripheral driver _and_ the clock driver
within a single patch, for whatever that may be worth.


So I suggest the following:

I can move parts 19 and 22 (completely) and the "workaround
removal" aspect of parts 20-21 and 23-28 to a later point in the
sequence, maybe squash them with part 31 (cleanup after migration
has completed).

This allows for even better (conflict free) application of the
series through individual and most appropriate trees.  All of
this of course assumes that the series passes review, and that
you agree on the outlined application in four phases if the
series cannot be kept together:
- clock API use cleanup for peripheral drivers, and device tree
  update to provide previously missing hardware information
- introduction of the platform clock driver and OF clock lookup
- adjustment of peripheral drivers after common clock support has
  become available
- removal of migration support and compat workarounds after
  migration has completed


> Please consider that I'm not trying to be pushy :)  but that I
> want to provide all the possible help and information on how the
> series might get applied, assuming that it will pass review.  So
> far there has not been objection, all feedback got addressed,
> while explicit ACKs still are pending.
> 
> For your reference here is the stats and the (numbered) list of
> files again:
> 
> 0000-cover-letter.patch
> 0001-spi-mpc512x-cleanup-clock-API-use.patch
> 0002-serial-mpc512x-cleanup-clock-API-use.patch
> 0003-USB-fsl-mph-dr-of-cleanup-clock-API-use.patch
> 0004-mtd-mpc5121_nfc-cleanup-clock-API-use.patch
> 0005-media-fsl-viu-cleanup-clock-API-use.patch
> 0006-i2c-mpc-cleanup-clock-API-use.patch
> 0007-fs_enet-silence-a-build-warning-unused-variable.patch
> 0008-fs_enet-cleanup-clock-API-use.patch
> 0009-powerpc-fsl-pci-improve-clock-API-use.patch
> 0010-net-can-mscan-add-a-comment-on-reg-to-idx-mapping.patch
> 0011-net-can-mscan-improve-clock-API-use.patch
> 0012-powerpc-mpc512x-array-decl-for-MCLK-registers-in-CCM.patch
> 0013-clk-wrap-I-O-access-for-improved-portability.patch
> 0014-dts-mpc512x-prepare-for-preprocessor-support.patch
> 0015-dts-mpc512x-introduce-dt-bindings-clock-header.patch
> 0016-dts-mpc512x-add-clock-related-device-tree-specs.patch
> 0017-clk-mpc512x-introduce-COMMON_CLK-for-MPC512x.patch
> 0018-dts-mpc512x-add-clock-specs-for-client-lookups.patch
> 0019-clk-mpc512x-don-t-pre-enable-FEC-and-I2C-clocks.patch
> 0020-spi-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
> 0021-serial-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
> 0022-clk-mpc512x-remove-PSC-UART-SPI-compat-workarounds.patch
> 0023-serial-mpc512x-setup-the-PSC-FIFO-clock-as-well.patch
> 0024-USB-fsl-mph-dr-of-remove-now-obsolete-clock-lookup-n.patch
> 0025-mtd-mpc5121_nfc-remove-now-obsolete-clock-lookup-nam.patch
> 0026-media-fsl-viu-remove-now-obsolete-clock-lookup-name.patch
> 0027-net-can-mscan-add-common-clock-support-for-mpc512x.patch
> 0028-powerpc-mpc512x-improve-DIU-related-clock-setup.patch
> 0029-clk-mpc512x-switch-to-COMMON_CLK-remove-PPC_CLOCK.patch
> 0030-net-can-mscan-remove-non-CCF-code-for-MPC512x.patch
> 0031-clk-mpc512x-remove-remaining-migration-workarounds.patch
> 
> > Gerhard Sittig (31):
> >   spi: mpc512x: cleanup clock API use
> >   serial: mpc512x: cleanup clock API use
> >   USB: fsl-mph-dr-of: cleanup clock API use
> >   mtd: mpc5121_nfc: cleanup clock API use
> >   [media] fsl-viu: cleanup clock API use
> >   i2c: mpc: cleanup clock API use
> >   fs_enet: silence a build warning (unused variable)
> >   fs_enet: cleanup clock API use
> >   powerpc/fsl-pci: improve clock API use
> >   net: can: mscan: add a comment on reg to idx mapping
> >   net: can: mscan: improve clock API use
> >   powerpc: mpc512x: array decl for MCLK registers in CCM
> >   clk: wrap I/O access for improved portability
> >   dts: mpc512x: prepare for preprocessor support
> >   dts: mpc512x: introduce dt-bindings/clock/ header
> >   dts: mpc512x: add clock related device tree specs
> >   clk: mpc512x: introduce COMMON_CLK for MPC512x
> >   dts: mpc512x: add clock specs for client lookups
> >   clk: mpc512x: don't pre-enable FEC and I2C clocks
> >   spi: mpc512x: switch to CCF names in clock lookup
> >   serial: mpc512x: switch to CCF names in clock lookup
> >   clk: mpc512x: remove PSC (UART, SPI) compat workarounds
> >   serial: mpc512x: setup the PSC FIFO clock as well
> >   USB: fsl-mph-dr-of: remove now obsolete clock lookup name
> >   mtd: mpc5121_nfc: remove now obsolete clock lookup name
> >   [media] fsl-viu: remove now obsolete clock lookup name
> >   net: can: mscan: add common clock support for mpc512x
> >   powerpc/mpc512x: improve DIU related clock setup
> >   clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
> >   net: can: mscan: remove non-CCF code for MPC512x
> >   clk: mpc512x: remove remaining migration workarounds
> > 
> >  arch/powerpc/boot/dts/ac14xx.dts                   |    9 +-
> >  arch/powerpc/boot/dts/include/dt-bindings          |    1 +
> >  arch/powerpc/boot/dts/mpc5121.dtsi                 |  110 ++-
> >  arch/powerpc/boot/dts/mpc5121ads.dts               |    2 +-
> >  arch/powerpc/boot/dts/pdm360ng.dts                 |    2 +-
> >  arch/powerpc/include/asm/mpc5121.h                 |   18 +-
> >  arch/powerpc/platforms/512x/Kconfig                |    2 +-
> >  arch/powerpc/platforms/512x/Makefile               |    3 +-
> >  arch/powerpc/platforms/512x/clock-commonclk.c      |  716 +++++++++++++++++++
> >  arch/powerpc/platforms/512x/clock.c                |  753 --------------------
> >  arch/powerpc/platforms/512x/mpc512x_shared.c       |  165 +++--
> >  arch/powerpc/sysdev/fsl_pci.c                      |   22 +
> >  drivers/clk/clk-divider.c                          |    6 +-
> >  drivers/clk/clk-gate.c                             |    6 +-
> >  drivers/clk/clk-mux.c                              |    6 +-
> >  drivers/i2c/busses/i2c-mpc.c                       |   24 +
> >  drivers/media/platform/fsl-viu.c                   |   23 +-
> >  drivers/mtd/nand/mpc5121_nfc.c                     |   21 +-
> >  drivers/net/can/mscan/mpc5xxx_can.c                |  281 +++++---
> >  drivers/net/can/mscan/mscan.c                      |   27 +-
> >  drivers/net/can/mscan/mscan.h                      |    3 +
> >  .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |   21 +-
> >  drivers/spi/spi-mpc512x-psc.c                      |   60 +-
> >  drivers/tty/serial/mpc52xx_uart.c                  |  179 ++++-
> >  drivers/usb/host/fsl-mph-dr-of.c                   |   27 +-
> >  include/dt-bindings/clock/mpc512x-clock.h          |   69 ++
> >  include/linux/clk-provider.h                       |   33 +
> >  include/linux/fs_enet_pd.h                         |    3 +
> >  28 files changed, 1534 insertions(+), 1058 deletions(-)
> >  create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
> >  create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> >  delete mode 100644 arch/powerpc/platforms/512x/clock.c
> >  create mode 100644 include/dt-bindings/clock/mpc512x-clock.h


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-07 15:40           ` Kumar Gala
  -1 siblings, 0 replies; 432+ messages in thread
From: Kumar Gala @ 2013-08-07 15:40 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	Greg Kroah-Hartman, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab


On Aug 6, 2013, at 3:43 PM, Gerhard Sittig wrote:

> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
> SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> handle clocks (appropriately acquire and setup them, hold references
> during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
> Kconfig option) in the PowerPC based MPC512x platform, which brings
> device tree based clock lookup as well
>=20
> although the series does touch several subsystems -- tty (serial), =
spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all =
of
> the patches are strictly clock related or trivial
>=20
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications
>=20
> the series passes 'checkpatch.pl --strict' except for one warning =
which
> cannot get resolved, since that either breaks compilation (the data =
type
> is preset by the clk-provider.h API) or requires a cast which shadows
> real mismatches:
>=20
> WARNING: static const char * array should probably be static const =
char * const
> #431: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:334:
> +static const char *parent_names_mux0[] =3D {
>=20
> total: 0 errors, 1 warnings, 0 checks, 807 lines checked
>=20
> each step in the series was build and run tested (with a display that =
is
> attached to the DIU as well as SPI, with an SPI attached NOR flash, =
with
> multiple UART ports such that one is not the boot console, with =
EEPROMs
> attached to I2C, with an SD card, booting from network)
>=20

How do the driver changes impact other PPC SoCs that use the same =
drivers (i2c, fs_enet, usb) ?

- k=

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-08-07 15:40           ` Kumar Gala
  0 siblings, 0 replies; 432+ messages in thread
From: Kumar Gala @ 2013-08-07 15:40 UTC (permalink / raw)
  To: linux-arm-kernel


On Aug 6, 2013, at 3:43 PM, Gerhard Sittig wrote:

> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
> SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> handle clocks (appropriately acquire and setup them, hold references
> during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
> Kconfig option) in the PowerPC based MPC512x platform, which brings
> device tree based clock lookup as well
> 
> although the series does touch several subsystems -- tty (serial), spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> the patches are strictly clock related or trivial
> 
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications
> 
> the series passes 'checkpatch.pl --strict' except for one warning which
> cannot get resolved, since that either breaks compilation (the data type
> is preset by the clk-provider.h API) or requires a cast which shadows
> real mismatches:
> 
> WARNING: static const char * array should probably be static const char * const
> #431: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:334:
> +static const char *parent_names_mux0[] = {
> 
> total: 0 errors, 1 warnings, 0 checks, 807 lines checked
> 
> each step in the series was build and run tested (with a display that is
> attached to the DIU as well as SPI, with an SPI attached NOR flash, with
> multiple UART ports such that one is not the boot console, with EEPROMs
> attached to I2C, with an SD card, booting from network)
> 

How do the driver changes impact other PPC SoCs that use the same drivers (i2c, fs_enet, usb) ?

- k

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-08-07 15:40           ` Kumar Gala
@ 2013-08-08 18:41             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-08 18:41 UTC (permalink / raw)
  To: Kumar Gala
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	Greg Kroah-Hartman, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	David Woodhouse, linux-arm-kernel, Mauro Carvalho Chehab

On Wed, Aug 07, 2013 at 10:40 -0500, Kumar Gala wrote:
> 
> On Aug 6, 2013, at 3:43 PM, Gerhard Sittig wrote:
> 
> > this series
> > - fixes several drivers that are used in the MPC512x platform (UART,
> > SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> > handle clocks (appropriately acquire and setup them, hold references
> > during use, release clocks after use)
> > - introduces support for the common clock framework (CCF, COMMON_CLK
> > Kconfig option) in the PowerPC based MPC512x platform, which brings
> > device tree based clock lookup as well
> > 
> > although the series does touch several subsystems -- tty (serial), spi,
> > net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> > the patches are strictly clock related or trivial
> > 
> > it appears most appropriate to take this series through either the clk
> > or the powerpc trees after it has passed review and other subsystem
> > maintainers ACKed the clock setup related driver modifications
> > 
> > the series passes 'checkpatch.pl --strict' except for one warning which
> > cannot get resolved, since that either breaks compilation (the data type
> > is preset by the clk-provider.h API) or requires a cast which shadows
> > real mismatches:
> > 
> > WARNING: static const char * array should probably be static const char * const
> > #431: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:334:
> > +static const char *parent_names_mux0[] = {
> > 
> > total: 0 errors, 1 warnings, 0 checks, 807 lines checked
> > 
> > each step in the series was build and run tested (with a display that is
> > attached to the DIU as well as SPI, with an SPI attached NOR flash, with
> > multiple UART ports such that one is not the boot console, with EEPROMs
> > attached to I2C, with an SD card, booting from network)
> > 
> 
> How do the driver changes impact other PPC SoCs that use the
> same drivers (i2c, fs_enet, usb) ?

For SPI and UART (the PSC component), the hardware is shared
between MPC512x and MPC5200, but only routines and data specific
to MPC512x get changed.

For USB the "fsl.*usb2" hardware appears to be shared among
Freescale SoCs.  AFAICS i.MX has a separate driver under arm/,
MPC83xx has a separate driver under arch/powerpc/platforms/83xx/,
and the driver I'm touching is only changed in routines specific
to MPC512x.

The NAND and VIU drivers only attach to hardware on the MPC512x
platform (checked the compatible string, only referenced from the
mpc5121.dtsi).

I2C, ethernet, PCI all are similar:  A non-fatal clock lookup is
introduced, CCF platforms (512x only ATM) will carry out
appropriate clock operations, non-CCF platforms won't see a
change in behaviour (lookup fails which isn't fatal, and the
drivers assume that somebody else will have taken care of clocks
for them).

MSCAN is shared among 512x and 52xx, the common code introduces
transparent yet optional support for CCF, the 512x code path
makes use of it, 52xx sees no change in behaviour.

The DIU component (display output) is shared among platforms, but
only the platform initialization in the MPC512x code path gets
changed to make use of the CCF support, while no other platform
sees any change.

The MPC512x common clock core driver does use common primitives
and redirects the register access primitives.  But the series
doesn't change register access for ARM (static inline call to the
previous hardcoded routine and thus identical object code), and
doesn't modify nor extend the shared code for gates, dividers and
multiplexers.

The device tree changes only apply to MPC512x, and only provide
hardware related information that formerly was missing.


To summarize, I see no impact for other architectures or
platforms.  Although it would be good to get a second opinion
from persons with USB knowledge, to make sure I haven't missed
something.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-08-08 18:41             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-08 18:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 10:40 -0500, Kumar Gala wrote:
> 
> On Aug 6, 2013, at 3:43 PM, Gerhard Sittig wrote:
> 
> > this series
> > - fixes several drivers that are used in the MPC512x platform (UART,
> > SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> > handle clocks (appropriately acquire and setup them, hold references
> > during use, release clocks after use)
> > - introduces support for the common clock framework (CCF, COMMON_CLK
> > Kconfig option) in the PowerPC based MPC512x platform, which brings
> > device tree based clock lookup as well
> > 
> > although the series does touch several subsystems -- tty (serial), spi,
> > net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> > the patches are strictly clock related or trivial
> > 
> > it appears most appropriate to take this series through either the clk
> > or the powerpc trees after it has passed review and other subsystem
> > maintainers ACKed the clock setup related driver modifications
> > 
> > the series passes 'checkpatch.pl --strict' except for one warning which
> > cannot get resolved, since that either breaks compilation (the data type
> > is preset by the clk-provider.h API) or requires a cast which shadows
> > real mismatches:
> > 
> > WARNING: static const char * array should probably be static const char * const
> > #431: FILE: arch/powerpc/platforms/512x/clock-commonclk.c:334:
> > +static const char *parent_names_mux0[] = {
> > 
> > total: 0 errors, 1 warnings, 0 checks, 807 lines checked
> > 
> > each step in the series was build and run tested (with a display that is
> > attached to the DIU as well as SPI, with an SPI attached NOR flash, with
> > multiple UART ports such that one is not the boot console, with EEPROMs
> > attached to I2C, with an SD card, booting from network)
> > 
> 
> How do the driver changes impact other PPC SoCs that use the
> same drivers (i2c, fs_enet, usb) ?

For SPI and UART (the PSC component), the hardware is shared
between MPC512x and MPC5200, but only routines and data specific
to MPC512x get changed.

For USB the "fsl.*usb2" hardware appears to be shared among
Freescale SoCs.  AFAICS i.MX has a separate driver under arm/,
MPC83xx has a separate driver under arch/powerpc/platforms/83xx/,
and the driver I'm touching is only changed in routines specific
to MPC512x.

The NAND and VIU drivers only attach to hardware on the MPC512x
platform (checked the compatible string, only referenced from the
mpc5121.dtsi).

I2C, ethernet, PCI all are similar:  A non-fatal clock lookup is
introduced, CCF platforms (512x only ATM) will carry out
appropriate clock operations, non-CCF platforms won't see a
change in behaviour (lookup fails which isn't fatal, and the
drivers assume that somebody else will have taken care of clocks
for them).

MSCAN is shared among 512x and 52xx, the common code introduces
transparent yet optional support for CCF, the 512x code path
makes use of it, 52xx sees no change in behaviour.

The DIU component (display output) is shared among platforms, but
only the platform initialization in the MPC512x code path gets
changed to make use of the CCF support, while no other platform
sees any change.

The MPC512x common clock core driver does use common primitives
and redirects the register access primitives.  But the series
doesn't change register access for ARM (static inline call to the
previous hardcoded routine and thus identical object code), and
doesn't modify nor extend the shared code for gates, dividers and
multiplexers.

The device tree changes only apply to MPC512x, and only provide
hardware related information that formerly was missing.


To summarize, I see no impact for other architectures or
platforms.  Although it would be good to get a second opinion
from persons with USB knowledge, to make sure I haven't missed
something.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 11/31] net: can: mscan: improve clock API use
  2013-08-07  7:28             ` Marc Kleine-Budde
@ 2013-08-08 19:50               ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-08 19:50 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Greg Kroah-Hartman, Rob Herring, Mark Brown,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

On Wed, Aug 07, 2013 at 09:28 +0200, Marc Kleine-Budde wrote:
> 
> On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
> > [ ... ]
> > diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> > index e6b4095..4f998f5 100644
> > --- a/drivers/net/can/mscan/mscan.c
> > +++ b/drivers/net/can/mscan/mscan.c
> > @@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
> >  	struct mscan_priv *priv = netdev_priv(dev);
> >  	struct mscan_regs __iomem *regs = priv->reg_base;
> >  
> > +	if (priv->clk_ipg) {
> > +		ret = clk_prepare_enable(priv->clk_ipg);
> > +		if (ret)
> > +			goto exit_retcode;
> > +	}
> > +	if (priv->clk_can) {
> > +		ret = clk_prepare_enable(priv->clk_can);
> > +		if (ret) {
> > +			if (priv->clk_ipg)
> > +				clk_disable_unprepare(priv->clk_ipg);
> > +			goto exit_retcode;
> 
> Why don't you add another jump label and jump to that to disable the
> ipkg clock?

You are right.  I've queued this change for v5 (adding a label in
the existing error path, jumping to it instead of explicitly
disabling the clock).

> 
> > +		}
> > +	}
> > +
> >  	/* common open */
> >  	ret = open_candev(dev);
> >  	if (ret)
> > -		return ret;
> > +		goto exit_dis_clock;
> >  
> >  	napi_enable(&priv->napi);
> >  
> > @@ -604,6 +618,12 @@ exit_free_irq:
> >  exit_napi_disable:
> >  	napi_disable(&priv->napi);
> >  	close_candev(dev);
> > +exit_dis_clock:
> > +	if (priv->clk_can)
> > +		clk_disable_unprepare(priv->clk_can);
> > +	if (priv->clk_ipg)
> > +		clk_disable_unprepare(priv->clk_ipg);
> > +exit_retcode:
> >  	return ret;
> >  }
> 
> Marc

Thank you for reviewing several versions of the patch!


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 11/31] net: can: mscan: improve clock API use
@ 2013-08-08 19:50               ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-08 19:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 09:28 +0200, Marc Kleine-Budde wrote:
> 
> On 08/06/2013 10:43 PM, Gerhard Sittig wrote:
> > [ ... ]
> > diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> > index e6b4095..4f998f5 100644
> > --- a/drivers/net/can/mscan/mscan.c
> > +++ b/drivers/net/can/mscan/mscan.c
> > @@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
> >  	struct mscan_priv *priv = netdev_priv(dev);
> >  	struct mscan_regs __iomem *regs = priv->reg_base;
> >  
> > +	if (priv->clk_ipg) {
> > +		ret = clk_prepare_enable(priv->clk_ipg);
> > +		if (ret)
> > +			goto exit_retcode;
> > +	}
> > +	if (priv->clk_can) {
> > +		ret = clk_prepare_enable(priv->clk_can);
> > +		if (ret) {
> > +			if (priv->clk_ipg)
> > +				clk_disable_unprepare(priv->clk_ipg);
> > +			goto exit_retcode;
> 
> Why don't you add another jump label and jump to that to disable the
> ipkg clock?

You are right.  I've queued this change for v5 (adding a label in
the existing error path, jumping to it instead of explicitly
disabling the clock).

> 
> > +		}
> > +	}
> > +
> >  	/* common open */
> >  	ret = open_candev(dev);
> >  	if (ret)
> > -		return ret;
> > +		goto exit_dis_clock;
> >  
> >  	napi_enable(&priv->napi);
> >  
> > @@ -604,6 +618,12 @@ exit_free_irq:
> >  exit_napi_disable:
> >  	napi_disable(&priv->napi);
> >  	close_candev(dev);
> > +exit_dis_clock:
> > +	if (priv->clk_can)
> > +		clk_disable_unprepare(priv->clk_can);
> > +	if (priv->clk_ipg)
> > +		clk_disable_unprepare(priv->clk_ipg);
> > +exit_retcode:
> >  	return ret;
> >  }
> 
> Marc

Thank you for reviewing several versions of the patch!


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-08 20:12           ` Anatolij Gustschin
  2013-08-12  7:57             ` Gerhard Sittig
  -1 siblings, 1 reply; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-08 20:12 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: linuxppc-dev

On Tue,  6 Aug 2013 22:43:49 +0200
Gerhard Sittig <gsi@denx.de> wrote:
...
> diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
> index 46ac1dd..549ff08 100644
> --- a/arch/powerpc/sysdev/fsl_pci.c
> +++ b/arch/powerpc/sysdev/fsl_pci.c
...
> +	clk = devm_clk_get(&pdev->dev, "per");
> +	if (!IS_ERR(clk)) {
> +		ret = clk_prepare_enable(clk);
> +		if (ret) {
> +			dev_err(dev, "Could not enable peripheral clock\n");

above line will break building. s/dev,/&pdev->dev,/

Thanks,
Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
  2013-08-08 20:12           ` Anatolij Gustschin
@ 2013-08-12  7:57             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-12  7:57 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: linuxppc-dev

On Thu, Aug 08, 2013 at 22:12 +0200, Anatolij Gustschin wrote:
> 
> On Tue,  6 Aug 2013 22:43:49 +0200
> Gerhard Sittig <gsi@denx.de> wrote:
> ...
> > diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
> > index 46ac1dd..549ff08 100644
> > --- a/arch/powerpc/sysdev/fsl_pci.c
> > +++ b/arch/powerpc/sysdev/fsl_pci.c
> ...
> > +	clk = devm_clk_get(&pdev->dev, "per");
> > +	if (!IS_ERR(clk)) {
> > +		ret = clk_prepare_enable(clk);
> > +		if (ret) {
> > +			dev_err(dev, "Could not enable peripheral clock\n");
> 
> above line will break building. s/dev,/&pdev->dev,/

Thank you for testing and for the feedback.

I've queued this fix for v5.  The bug could hide because the file
gets compiled on MPC512x, but this specific routine sits behind
even more compile time switches (85xx and 86xx related).


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 02/31] serial: mpc512x: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
@ 2013-08-12 18:27             ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 432+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 18:27 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

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 <gsi@denx.de>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 02/31] serial: mpc512x: cleanup clock API use
@ 2013-08-12 18:27             ` Greg Kroah-Hartman
  0 siblings, 0 replies; 432+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

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 <gsi@denx.de>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 21/31] serial: mpc512x: switch to CCF names in clock lookup
  2013-08-06 20:44           ` Gerhard Sittig
@ 2013-08-12 18:27             ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 432+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 18:27 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

On Tue, Aug 06, 2013 at 10:44:01PM +0200, Gerhard Sittig wrote:
> after device tree based clock lookup became available, the peripheral
> driver need no longer construct clock names which include the PSC index,
> remove the "psc%d_mclk" template and unconditionally use 'mclk'
> 
> acquire and release the 'ipg' clock for register access as well
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 21/31] serial: mpc512x: switch to CCF names in clock lookup
@ 2013-08-12 18:27             ` Greg Kroah-Hartman
  0 siblings, 0 replies; 432+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 06, 2013 at 10:44:01PM +0200, Gerhard Sittig wrote:
> after device tree based clock lookup became available, the peripheral
> driver need no longer construct clock names which include the PSC index,
> remove the "psc%d_mclk" template and unconditionally use 'mclk'
> 
> acquire and release the 'ipg' clock for register access as well
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well
  2013-08-06 20:44           ` Gerhard Sittig
@ 2013-08-12 18:27             ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 432+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 18:27 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Rob Herring, Mark Brown, Marc Kleine-Budde,
	Wolfgang Grandegger, Anatolij Gustschin, linuxppc-dev,
	linux-arm-kernel, Mauro Carvalho Chehab

On Tue, Aug 06, 2013 at 10:44:03PM +0200, Gerhard Sittig wrote:
> prepare and enable the FIFO clock upon PSC FIFO initialization,
> check for and propagage errors when enabling the PSC FIFO clock,
> disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
> remove the pre-enable workaround from the platform's clock driver
> 
> devm_{get,put}_clk() doesn't apply here, as the SoC provides a
> single FIFO component which is shared among several PSC components,
> thus the FIFO isn't associated with a device (while the PSCs are)
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well
@ 2013-08-12 18:27             ` Greg Kroah-Hartman
  0 siblings, 0 replies; 432+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 06, 2013 at 10:44:03PM +0200, Gerhard Sittig wrote:
> prepare and enable the FIFO clock upon PSC FIFO initialization,
> check for and propagage errors when enabling the PSC FIFO clock,
> disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
> remove the pre-enable workaround from the platform's clock driver
> 
> devm_{get,put}_clk() doesn't apply here, as the SoC provides a
> single FIFO component which is shared among several PSC components,
> thus the FIFO isn't associated with a device (while the PSCs are)
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-21 19:22           ` Anatolij Gustschin
  2013-08-21 19:48             ` Mark Brown
  -1 siblings, 1 reply; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-21 19:22 UTC (permalink / raw)
  To: Mark Brown; +Cc: devicetree, Gerhard Sittig, linuxppc-dev

On Tue,  6 Aug 2013 22:43:41 +0200
Gerhard Sittig <gsi@denx.de> wrote:

> cleanup the MPC512x SoC's SPI master's use of the clock API
> - get, prepare, and enable the MCLK during probe; disable, unprepare and
>   put the MCLK upon remove; hold a reference to the clock over the
>   period of use
> - fetch MCLK rate (reference) once during probe and slightly reword BCLK
>   (bitrate) determination to reduce redundancy as well as to not exceed
>   the maximum text line length
> - 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
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/spi/spi-mpc512x-psc.c |   48 +++++++++++++++++++++++++----------------
>  1 file changed, 30 insertions(+), 18 deletions(-)

Mark, are you going to apply this patch? Or should I queue it
in my mpc5xxx tree (I'd like to get your Acked-by then)?

Thanks,

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
  2013-08-21 19:22           ` Anatolij Gustschin
@ 2013-08-21 19:48             ` Mark Brown
  2013-08-21 20:38               ` Anatolij Gustschin
  0 siblings, 1 reply; 432+ messages in thread
From: Mark Brown @ 2013-08-21 19:48 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: devicetree, Gerhard Sittig, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 301 bytes --]

On Wed, Aug 21, 2013 at 09:22:58PM +0200, Anatolij Gustschin wrote:

> Mark, are you going to apply this patch? Or should I queue it
> in my mpc5xxx tree (I'd like to get your Acked-by then)?

Has this series settled down?  I'd been ignoring it since it was getting
so many and so frequent revisions.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 02/31] serial: mpc512x: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
  (?)
@ 2013-08-21 19:52           ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-21 19:52 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: devicetree, linuxppc-dev

On Tue,  6 Aug 2013 22:43:42 +0200
Gerhard Sittig <gsi@denx.de> 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 <gsi@denx.de>
> ---
>  drivers/tty/serial/mpc52xx_uart.c |   98 ++++++++++++++++++++++++++++++-------
>  1 file changed, 81 insertions(+), 17 deletions(-)

applied, thanks!

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
  2013-08-21 19:48             ` Mark Brown
@ 2013-08-21 20:38               ` Anatolij Gustschin
  0 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-21 20:38 UTC (permalink / raw)
  To: Mark Brown; +Cc: devicetree, Gerhard Sittig, linuxppc-dev

On Wed, 21 Aug 2013 20:48:17 +0100
Mark Brown <broonie@kernel.org> wrote:

> On Wed, Aug 21, 2013 at 09:22:58PM +0200, Anatolij Gustschin wrote:
> 
> > Mark, are you going to apply this patch? Or should I queue it
> > in my mpc5xxx tree (I'd like to get your Acked-by then)?
> 
> Has this series settled down?  I'd been ignoring it since it was getting
> so many and so frequent revisions.

Patches 01 - 14 (except 09 and 11) won't change I think. I'd prefer
to queue them for v3.12, so there will be no need to resubmit again
and again. Other patches are not ready yet.

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 03/31] USB: fsl-mph-dr-of: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-21 20:45           ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-21 20:45 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: devicetree, linuxppc-dev

On Tue,  6 Aug 2013 22:43:43 +0200
Gerhard Sittig <gsi@denx.de> wrote:

> use devm_get_clk() for automatic put upon device close, check for and
> propagate errors when enabling clocks, must prepare clocks before they
> can get enabled, unprepare after disable
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/usb/host/fsl-mph-dr-of.c |   16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)

applied, thanks!

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
@ 2013-08-22 10:02             ` Mark Brown
  -1 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-08-22 10:02 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: devicetree, Mike Turquette, Detlev Zundel, Wolfram Sang,
	David Woodhouse, Greg Kroah-Hartman, Rob Herring,
	Marc Kleine-Budde, Wolfgang Grandegger, Anatolij Gustschin,
	linuxppc-dev, linux-arm-kernel, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 306 bytes --]

On Tue, Aug 06, 2013 at 10:43:41PM +0200, Gerhard Sittig wrote:
> cleanup the MPC512x SoC's SPI master's use of the clock API
> - get, prepare, and enable the MCLK during probe; disable, unprepare and
>   put the MCLK upon remove; hold a reference to the clock over the
>   period of use

Applied, thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 01/31] spi: mpc512x: cleanup clock API use
@ 2013-08-22 10:02             ` Mark Brown
  0 siblings, 0 replies; 432+ messages in thread
From: Mark Brown @ 2013-08-22 10:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 06, 2013 at 10:43:41PM +0200, Gerhard Sittig wrote:
> cleanup the MPC512x SoC's SPI master's use of the clock API
> - get, prepare, and enable the MCLK during probe; disable, unprepare and
>   put the MCLK upon remove; hold a reference to the clock over the
>   period of use

Applied, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130822/02ff2956/attachment.sig>

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 04/31] mtd: mpc5121_nfc: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-23 21:47           ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-23 21:47 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: David Woodhouse, linuxppc-dev

On Tue,  6 Aug 2013 22:43:44 +0200
Gerhard Sittig <gsi@denx.de> wrote:

> use devm_clk_get() for automatic put after device close, check for and
> propagate errors when enabling clocks, need to prepare clocks before
> they can get enabled, adjust error code paths to correctly balance
> get/put and prepare/unprepare and enable/disable calls
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/mtd/nand/mpc5121_nfc.c |   21 ++++++++++++---------
>  1 file changed, 12 insertions(+), 9 deletions(-)

Applied to mpc5xxx tree, thanks!

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 05/31] [media] fsl-viu: cleanup clock API use
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-23 21:48           ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-23 21:48 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: linuxppc-dev, Mauro Carvalho Chehab

On Tue,  6 Aug 2013 22:43:45 +0200
Gerhard Sittig <gsi@denx.de> wrote:

> use devm_clk_get() for automatic put after device close, check for and
> propagate errors when enabling clocks, need to prepare clocks before
> they can get enabled, adjust code paths to correctly balance get/put and
> prepare/unprepare and enable/disable calls
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  drivers/media/platform/fsl-viu.c |   23 +++++++++++++----------
>  1 file changed, 13 insertions(+), 10 deletions(-)

Applied to mpc5xxx tree, thanks!

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-23 21:49           ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-23 21:49 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: linuxppc-dev

On Tue,  6 Aug 2013 22:43:52 +0200
Gerhard Sittig <gsi@denx.de> wrote:

> reword the clock control module's registers declaration such that the
> MCLK related registers form an array and get indexed by PSC controller
> or CAN controller component number
> 
> this change is in preparation to COMMON_CLK support for the MPC512x
> platform, the changed declaration remains neutral to existing code since
> the PSC and MSCAN CCR fields declared here aren't referenced anywhere
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/include/asm/mpc5121.h |   18 ++----------------
>  1 file changed, 2 insertions(+), 16 deletions(-)

Applied, thanks!

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 13/31] clk: wrap I/O access for improved portability
  2013-08-02 22:30           ` Mike Turquette
@ 2013-08-23 22:05             ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-23 22:05 UTC (permalink / raw)
  To: Mike Turquette; +Cc: Gerhard Sittig, linuxppc-dev, linux-arm-kernel

On Fri, 02 Aug 2013 15:30:00 -0700
Mike Turquette <mturquette@linaro.org> wrote:

> Quoting Gerhard Sittig (2013-07-22 05:14:40)
> > the common clock drivers were motivated/initiated by ARM development
> > and apparently assume little endian peripherals
> > 
> > wrap register/peripherals access in the common code (div, gate, mux)
> > in preparation of adding COMMON_CLK support for other platforms
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> I've taken this into clk-next for testing. regmap deserves investigation
> but I don't think your series should be blocked on that. We can always
> overhaul the basic clock primitives with regmap support later on if that
> makes sense.

Mike, I cannot see it in clk-next branch of
git://git.linaro.org/people/mturquette/linux.git

Can you please check? Or am I looking in the wrong place?

Thanks,
Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 13/31] clk: wrap I/O access for improved portability
@ 2013-08-23 22:05             ` Anatolij Gustschin
  0 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-23 22:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 02 Aug 2013 15:30:00 -0700
Mike Turquette <mturquette@linaro.org> wrote:

> Quoting Gerhard Sittig (2013-07-22 05:14:40)
> > the common clock drivers were motivated/initiated by ARM development
> > and apparently assume little endian peripherals
> > 
> > wrap register/peripherals access in the common code (div, gate, mux)
> > in preparation of adding COMMON_CLK support for other platforms
> > 
> > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> 
> I've taken this into clk-next for testing. regmap deserves investigation
> but I don't think your series should be blocked on that. We can always
> overhaul the basic clock primitives with regmap support later on if that
> makes sense.

Mike, I cannot see it in clk-next branch of
git://git.linaro.org/people/mturquette/linux.git

Can you please check? Or am I looking in the wrong place?

Thanks,
Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 14/31] dts: mpc512x: prepare for preprocessor support
  2013-08-06 20:43           ` Gerhard Sittig
  (?)
@ 2013-08-23 22:18           ` Anatolij Gustschin
  -1 siblings, 0 replies; 432+ messages in thread
From: Anatolij Gustschin @ 2013-08-23 22:18 UTC (permalink / raw)
  To: Gerhard Sittig; +Cc: devicetree, linuxppc-dev

On Tue,  6 Aug 2013 22:43:54 +0200
Gerhard Sittig <gsi@denx.de> wrote:

> prepare C preprocessor support when processing MPC512x DTS files
> - switch from DTS syntax to CPP syntax for include specs
> - create a symlink such that DTS processing can reference includes
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/boot/dts/ac14xx.dts          |    2 +-
>  arch/powerpc/boot/dts/include/dt-bindings |    1 +
>  arch/powerpc/boot/dts/mpc5121ads.dts      |    2 +-
>  arch/powerpc/boot/dts/pdm360ng.dts        |    2 +-
>  4 files changed, 4 insertions(+), 3 deletions(-)
>  create mode 120000 arch/powerpc/boot/dts/include/dt-bindings

Applied, thanks!

Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v3 13/31] clk: wrap I/O access for improved portability
  2013-08-23 22:05             ` Anatolij Gustschin
@ 2013-08-28  0:55               ` Mike Turquette
  -1 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-28  0:55 UTC (permalink / raw)
  To: Anatolij Gustschin; +Cc: Gerhard Sittig, linuxppc-dev, linux-arm-kernel

Quoting Anatolij Gustschin (2013-08-23 15:05:39)
> On Fri, 02 Aug 2013 15:30:00 -0700
> Mike Turquette <mturquette@linaro.org> wrote:
> =

> > Quoting Gerhard Sittig (2013-07-22 05:14:40)
> > > the common clock drivers were motivated/initiated by ARM development
> > > and apparently assume little endian peripherals
> > > =

> > > wrap register/peripherals access in the common code (div, gate, mux)
> > > in preparation of adding COMMON_CLK support for other platforms
> > > =

> > > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > =

> > I've taken this into clk-next for testing. regmap deserves investigation
> > but I don't think your series should be blocked on that. We can always
> > overhaul the basic clock primitives with regmap support later on if that
> > makes sense.
> =

> Mike, I cannot see it in clk-next branch of
> git://git.linaro.org/people/mturquette/linux.git
> =

> Can you please check? Or am I looking in the wrong place?

You were looking in the right place but I had not pushed out the latest
patches from my local branch. It should be there now.

Regards,
Mike

> =

> Thanks,
> Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v3 13/31] clk: wrap I/O access for improved portability
@ 2013-08-28  0:55               ` Mike Turquette
  0 siblings, 0 replies; 432+ messages in thread
From: Mike Turquette @ 2013-08-28  0:55 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Anatolij Gustschin (2013-08-23 15:05:39)
> On Fri, 02 Aug 2013 15:30:00 -0700
> Mike Turquette <mturquette@linaro.org> wrote:
> 
> > Quoting Gerhard Sittig (2013-07-22 05:14:40)
> > > the common clock drivers were motivated/initiated by ARM development
> > > and apparently assume little endian peripherals
> > > 
> > > wrap register/peripherals access in the common code (div, gate, mux)
> > > in preparation of adding COMMON_CLK support for other platforms
> > > 
> > > Signed-off-by: Gerhard Sittig <gsi@denx.de>
> > 
> > I've taken this into clk-next for testing. regmap deserves investigation
> > but I don't think your series should be blocked on that. We can always
> > overhaul the basic clock primitives with regmap support later on if that
> > makes sense.
> 
> Mike, I cannot see it in clk-next branch of
> git://git.linaro.org/people/mturquette/linux.git
> 
> Can you please check? Or am I looking in the wrong place?

You were looking in the right place but I had not pushed out the latest
patches from my local branch. It should be there now.

Regards,
Mike

> 
> Thanks,
> Anatolij

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
  2013-08-06 20:43           ` Gerhard Sittig
@ 2013-08-28 12:08             ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-28 12:08 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel; +Cc: Paul Mackerras

[ re-created the Cc: list, this is about the PCI clock exclusively ]

Of all the "preparation" patches in the series (parts 01-14/31,
forming the "peripheral driver cleanup" phase before the
introduction of CCF support), this patch remains the last to get
picked up.

But I'd suggest to leave this patch for now (for v3.12, it's
rather late).  Either ignore this message and the patch, or see
below for why application isn't required now, and an update of
this patch is needed and will be appropriate for v3.13.

I'm sorry for the confusion, the potentially perceived
instability is a result of both widening the series' scope after
initial submission as well as a recent extension of test coverage
after the scope has been widened.  Thank you for your patience!


On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> 
> make the Freescale PCI driver get, prepare and enable the PCI clock
> during probe(); the clock gets put upon device close by the devm approach
> 
> clock lookup is non-fatal as not all platforms may provide clock specs
> in their device tree, but failure to enable specified clocks are fatal
> 
> the driver appears to not have a remove() routine, so no reference to
> the clock is kept during use, and the clock isn't released (the devm
> approach will put the clock, but it won't get disabled or unprepared)
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/sysdev/fsl_pci.c |   22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
> index 46ac1dd..549ff08 100644
> --- a/arch/powerpc/sysdev/fsl_pci.c
> +++ b/arch/powerpc/sysdev/fsl_pci.c
> @@ -17,6 +17,8 @@
> ...

What this patch 09/31 does is add a non-fatal device tree based
clock lookup in the fsl_pci_probe() routine, to acquire the PCI
clock item appropriately if there is a provider and a DT spec.

The patch in v4 has a bug, which has an obvious fix while an
update wasn't sent yet, for neither the patch nor the series.
There is one more known issue in the series (not with
functionality but with policy, specifically in a multi platform
configuration), while I don't want to resend the series while
known issues are pending.  But this is not the problem here.


First of all the patch is a NOP in the forseeable future.  It
won't harm yet its content isn't urgently needed either, to
unbreak stuff or to support upcoming features that were
communicated before.

Further analysis has shown that the patch is incomplete.

The 85xx and 86xx platforms will pass through the fsl_pci_probe()
routine.  That these platforms don't have OF clock providers is
not a problem, the patch will remain a NOP then.  Its function
will kick in when these platforms may grow clock providers
(things will transparently keep working, this was the actual
intent of the patch).  Since the series is about 512x CCF
support, the patch will remain a NOP throughout the whole series,
but won't harm either.

The 83xx and 512x platforms in contrast _don't_ pass through the
fsl_pci_probe() routine, instead they call mpc83xx_add_bridge()
from within the .setup_arch() callback in platform initialization
code, which iterates over the compatible OF nodes, and runs at a
point in time where the platform's clock provider has not yet
been setup and thus is not available.  In this situation any
clock lookup will fail, which is not fatal during PCI setup yet
won't acquire the clock item and thus will have the common
infrastructure disable the "unused" clock much later.

There is a workaround for this lack of proper clock acquisition
in the peripheral driver.  The clock provider needs to pre-enable
the PCI clock item upon its initialization, because the
peripheral driver can't when it initializes.  Checking the same
condition in the provider's pre-enable workaround which the
.setup_arch() routine is checking before the add_bridge() calls
(the presence of compatible nodes) results in correct operation
as well as most appropriate resource use (clock enabled when PCI
hardware was attached to, and clock disabled in the absence of
PCI hardware or driver attachment).


So the update of this patch 09/31 will contain
- the fix for the copy'n'paste bug in the probe() routine
- an appropriate comment in the add_bridge() routine
- no change in its nature, the idea remains unaffected

The backend (clock provider) will contain the pre-enable
workaround for the PCI clock item.

As a result, the 83xx, 85xx, and 86xx platforms won't see any
change (there is a NOP in probe() and a comment in add_bridge(),
neither of which break any operation).  The 512x platform will
have proper PCI operation in the presence of common clock
support.  Should 8xxx platforms grow CCF support later, they will
transparently keep working (85xx, 86xx), or may add the same
simple yet appropriate workaround (83xx).


So the outline is there, the approach is straight forward and
easily can get implemented, and the resulting code will work for
all platforms while there is no potential for breakage.  The PCI
driver will improve, and all is well. :)  There is no need for
action for v3.12, and v3.13 can include the improvement.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
@ 2013-08-28 12:08             ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-28 12:08 UTC (permalink / raw)
  To: linux-arm-kernel

[ re-created the Cc: list, this is about the PCI clock exclusively ]

Of all the "preparation" patches in the series (parts 01-14/31,
forming the "peripheral driver cleanup" phase before the
introduction of CCF support), this patch remains the last to get
picked up.

But I'd suggest to leave this patch for now (for v3.12, it's
rather late).  Either ignore this message and the patch, or see
below for why application isn't required now, and an update of
this patch is needed and will be appropriate for v3.13.

I'm sorry for the confusion, the potentially perceived
instability is a result of both widening the series' scope after
initial submission as well as a recent extension of test coverage
after the scope has been widened.  Thank you for your patience!


On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> 
> make the Freescale PCI driver get, prepare and enable the PCI clock
> during probe(); the clock gets put upon device close by the devm approach
> 
> clock lookup is non-fatal as not all platforms may provide clock specs
> in their device tree, but failure to enable specified clocks are fatal
> 
> the driver appears to not have a remove() routine, so no reference to
> the clock is kept during use, and the clock isn't released (the devm
> approach will put the clock, but it won't get disabled or unprepared)
> 
> Signed-off-by: Gerhard Sittig <gsi@denx.de>
> ---
>  arch/powerpc/sysdev/fsl_pci.c |   22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
> index 46ac1dd..549ff08 100644
> --- a/arch/powerpc/sysdev/fsl_pci.c
> +++ b/arch/powerpc/sysdev/fsl_pci.c
> @@ -17,6 +17,8 @@
> ...

What this patch 09/31 does is add a non-fatal device tree based
clock lookup in the fsl_pci_probe() routine, to acquire the PCI
clock item appropriately if there is a provider and a DT spec.

The patch in v4 has a bug, which has an obvious fix while an
update wasn't sent yet, for neither the patch nor the series.
There is one more known issue in the series (not with
functionality but with policy, specifically in a multi platform
configuration), while I don't want to resend the series while
known issues are pending.  But this is not the problem here.


First of all the patch is a NOP in the forseeable future.  It
won't harm yet its content isn't urgently needed either, to
unbreak stuff or to support upcoming features that were
communicated before.

Further analysis has shown that the patch is incomplete.

The 85xx and 86xx platforms will pass through the fsl_pci_probe()
routine.  That these platforms don't have OF clock providers is
not a problem, the patch will remain a NOP then.  Its function
will kick in when these platforms may grow clock providers
(things will transparently keep working, this was the actual
intent of the patch).  Since the series is about 512x CCF
support, the patch will remain a NOP throughout the whole series,
but won't harm either.

The 83xx and 512x platforms in contrast _don't_ pass through the
fsl_pci_probe() routine, instead they call mpc83xx_add_bridge()
from within the .setup_arch() callback in platform initialization
code, which iterates over the compatible OF nodes, and runs at a
point in time where the platform's clock provider has not yet
been setup and thus is not available.  In this situation any
clock lookup will fail, which is not fatal during PCI setup yet
won't acquire the clock item and thus will have the common
infrastructure disable the "unused" clock much later.

There is a workaround for this lack of proper clock acquisition
in the peripheral driver.  The clock provider needs to pre-enable
the PCI clock item upon its initialization, because the
peripheral driver can't when it initializes.  Checking the same
condition in the provider's pre-enable workaround which the
.setup_arch() routine is checking before the add_bridge() calls
(the presence of compatible nodes) results in correct operation
as well as most appropriate resource use (clock enabled when PCI
hardware was attached to, and clock disabled in the absence of
PCI hardware or driver attachment).


So the update of this patch 09/31 will contain
- the fix for the copy'n'paste bug in the probe() routine
- an appropriate comment in the add_bridge() routine
- no change in its nature, the idea remains unaffected

The backend (clock provider) will contain the pre-enable
workaround for the PCI clock item.

As a result, the 83xx, 85xx, and 86xx platforms won't see any
change (there is a NOP in probe() and a comment in add_bridge(),
neither of which break any operation).  The 512x platform will
have proper PCI operation in the presence of common clock
support.  Should 8xxx platforms grow CCF support later, they will
transparently keep working (85xx, 86xx), or may add the same
simple yet appropriate workaround (83xx).


So the outline is there, the approach is straight forward and
easily can get implemented, and the resulting code will work for
all platforms while there is no potential for breakage.  The PCI
driver will improve, and all is well. :)  There is no need for
action for v3.12, and v3.13 can include the improvement.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
  2013-08-06 20:43         ` Gerhard Sittig
@ 2013-08-28 13:50           ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-28 13:50 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
	linux-arm-kernel, devicetree
  Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
	Mark Brown, Marc Kleine-Budde, David Woodhouse,
	Wolfgang Grandegger, Mauro Carvalho Chehab

[ summary for the busy or the impatient:
  this is a status update on the series
  - peripheral driver cleanup considered appropriate for v3.12
  - common clock support introduction isn't ready yet
  - which in turn holds subsequent parts
  - while the overall shape of the series is looking good ]

On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> 
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
>   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
>   handle clocks (appropriately acquire and setup them, hold references
>   during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
>   Kconfig option) in the PowerPC based MPC512x platform, which brings
>   device tree based clock lookup as well
> 
> although the series does touch several subsystems -- tty (serial), spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> the patches are strictly clock related or trivial
> 
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications

Since the status of this series was questioned recently, I felt
that I should officially and publicly provide a status update in
the absence of a v5 submission update.

The series has undergone some review and has received changes as
concerns were raised and feedback was provided.  While I consider
the nature and frequency of the changes totally appropriate --
each revision addressed all of the issues raised, and did so in
an appropriate manner, but could not forsee what else would be
raised upon re-submission.  Actually not sending another version
before _all_ concerns are addressed appropriately is what held
back submission of v5.  See the phase overview below for details.


Adding the cleanup of existing code before the introduction of
new features did widen the scope of the series, yet has heavily
improved the series, and the feedback was gratefully accepted and
thoroughly got addressed.

Actually this driver cleanup, which only was introduced after
initial submission upon Mark's request, could be considered the
most desirable part of the series at this very point in time.
And as I write this, the patches of the "peripheral driver
cleanup" phase are being picked up for v3.12 after they have
become stable in the review iterations.


Further extension of test coverage for the series after
submission of v4 has led to minimal fixes in CAN, USB, and PCI,
and has revealed one problem in multi platform configurations
which currently is the only remaining blocker for phase 2 and
subsequent steps.  While phase 1 with its obvious cleanup is
stable and has become desirable and acceptable and currently is
being picked up.


The current status of the v4 series in detail is:

Phase 1, patches 01-14/31, peripheral driver cleanup and DTS
improvement:  has addressed all concerns raised, and can be
applied via any subtree in any order since the parts are
independent from each other, with a few minor additions

- USB 03/31 received another adjustment of the clock lookup 'dev'
  parameter, the applied version works in all three cases of the
  PPC_CLOCK implementation where clock names are global, the CCF
  implementation with clkdev registration (during migration), and
  the CCF implementation with device tree based clock lookup (the
  end result of the series); the v4 patch wasn't broken but just
  in need of an addendum before/within phase 3, which now was
  folded into phase 1

- PCI 09/31 had a compile error on 85xx/86xx due to a
  copy'n'paste bug in an error path; since the (fixed) patch
  still remains a NOP for now and within the whole series, I have
  suggested to leave this patch for v3.12, and to address the
  remaining issue of the PCI driver patch being incomplete later,
  see the followup for 09/31 for details (what gets added in a
  future version is another comment in the PCI driver and a
  workaround in the clock provider backend, because in the given
  implementation the peripheral driver cannot appropriately
  acquire its clock item on some platforms)

- CAN 11/31 could save one more instruction by adding another
  jump label in the error path instead of explicit undo of a
  setup step, Marc's suggestion was implemented and has been
  applied

So all parts of phase 1 (with the exception of the PCI driver
change which is and remains a NOP) were applied, and followup
patches for fixup were avoided.  Nothing was broken, no breakage
was introduced, it's all about improvements.

Phase 2, patches 15-18/31, introduction of CCF support for
MPC512x:  works correctly for MPC512x and doesn't break other
platforms, but won't work in multi platform configurations with
MPC52xx (PPC_CLOCK and COMMON_CLK will collide in the linker),
shall not be considered for v3.12, multi platform needs to get
sorted out before consideration for v3.13 (and is the only known
issue of the series feature- or policy-wise)

Phase 3, patches 20,21,23-28/31, adoption of peripheral drivers
to the CCF world:  is complete feature-wise and recently has
received even more test coverage than before, remaining fixes got
folded into phase 1, patches of phase 3 depend on CCF support
which gets introduced in phase 2, and the "workaround removal"
aspects of phase 3 will explicitly be moved to phase 4 while the
content remains unaffected (mere split and re-order)

Phase 4, patches 19,22,29-31/31, removal of migration support
after complete adoption:  is complete feature-wise, but partial
removal of workarounds and compatibility from phase 3 shall move
explicitly to phase 4, to more strictly tell those phases apart
and for collision free application via individual subtrees if
application through a single tree cannot be done, so a mere
re-ordering remains to get communicated while nothing changes in
the content (re-ordering the sequence as well as verifying that
the patches in phase 3 are independent from each other has
already been done internally)


To summarize:
- The series is in a good shape, one multi platform issue needs
  to get addressed, everything else either is already there or
  just needs to get communicated.
- Phase 1 with the obvious cleanup is being considered for v3.12,
  and patches have been queued in their respective subtrees.
- Phase 2 will become acceptable when the multi platform
  configuration has been sorted out.  Each platform works in
  itself, just not the combination of 52xx and 512x, and actually
  MPC52xx could be considered the out-lier here (is the only
  remaining user of PPC_CLOCK, and does so with a dummy
  implementation in the absence of a real provider).
- Phases 3 and 4 are "complete" but depend on phase 2.  What
  remains is a re-sort of the CCF adjustment and the migration
  support removal aspects.
  
Thanks to those involved in the feedback and application so far!
In my eyes, changes have been few, and necessary, and always an
improvement.  Regardless of which potential for further
improvement remains, which just happens to be way outside of the
scope of the series (power consumption aspects that neither have
been addressed nor prepared before, or CCF support for other
PowerPC based platforms maybe).


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
@ 2013-08-28 13:50           ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-28 13:50 UTC (permalink / raw)
  To: linux-arm-kernel

[ summary for the busy or the impatient:
  this is a status update on the series
  - peripheral driver cleanup considered appropriate for v3.12
  - common clock support introduction isn't ready yet
  - which in turn holds subsequent parts
  - while the overall shape of the series is looking good ]

On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
> 
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
>   SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
>   handle clocks (appropriately acquire and setup them, hold references
>   during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
>   Kconfig option) in the PowerPC based MPC512x platform, which brings
>   device tree based clock lookup as well
> 
> although the series does touch several subsystems -- tty (serial), spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> the patches are strictly clock related or trivial
> 
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications

Since the status of this series was questioned recently, I felt
that I should officially and publicly provide a status update in
the absence of a v5 submission update.

The series has undergone some review and has received changes as
concerns were raised and feedback was provided.  While I consider
the nature and frequency of the changes totally appropriate --
each revision addressed all of the issues raised, and did so in
an appropriate manner, but could not forsee what else would be
raised upon re-submission.  Actually not sending another version
before _all_ concerns are addressed appropriately is what held
back submission of v5.  See the phase overview below for details.


Adding the cleanup of existing code before the introduction of
new features did widen the scope of the series, yet has heavily
improved the series, and the feedback was gratefully accepted and
thoroughly got addressed.

Actually this driver cleanup, which only was introduced after
initial submission upon Mark's request, could be considered the
most desirable part of the series at this very point in time.
And as I write this, the patches of the "peripheral driver
cleanup" phase are being picked up for v3.12 after they have
become stable in the review iterations.


Further extension of test coverage for the series after
submission of v4 has led to minimal fixes in CAN, USB, and PCI,
and has revealed one problem in multi platform configurations
which currently is the only remaining blocker for phase 2 and
subsequent steps.  While phase 1 with its obvious cleanup is
stable and has become desirable and acceptable and currently is
being picked up.


The current status of the v4 series in detail is:

Phase 1, patches 01-14/31, peripheral driver cleanup and DTS
improvement:  has addressed all concerns raised, and can be
applied via any subtree in any order since the parts are
independent from each other, with a few minor additions

- USB 03/31 received another adjustment of the clock lookup 'dev'
  parameter, the applied version works in all three cases of the
  PPC_CLOCK implementation where clock names are global, the CCF
  implementation with clkdev registration (during migration), and
  the CCF implementation with device tree based clock lookup (the
  end result of the series); the v4 patch wasn't broken but just
  in need of an addendum before/within phase 3, which now was
  folded into phase 1

- PCI 09/31 had a compile error on 85xx/86xx due to a
  copy'n'paste bug in an error path; since the (fixed) patch
  still remains a NOP for now and within the whole series, I have
  suggested to leave this patch for v3.12, and to address the
  remaining issue of the PCI driver patch being incomplete later,
  see the followup for 09/31 for details (what gets added in a
  future version is another comment in the PCI driver and a
  workaround in the clock provider backend, because in the given
  implementation the peripheral driver cannot appropriately
  acquire its clock item on some platforms)

- CAN 11/31 could save one more instruction by adding another
  jump label in the error path instead of explicit undo of a
  setup step, Marc's suggestion was implemented and has been
  applied

So all parts of phase 1 (with the exception of the PCI driver
change which is and remains a NOP) were applied, and followup
patches for fixup were avoided.  Nothing was broken, no breakage
was introduced, it's all about improvements.

Phase 2, patches 15-18/31, introduction of CCF support for
MPC512x:  works correctly for MPC512x and doesn't break other
platforms, but won't work in multi platform configurations with
MPC52xx (PPC_CLOCK and COMMON_CLK will collide in the linker),
shall not be considered for v3.12, multi platform needs to get
sorted out before consideration for v3.13 (and is the only known
issue of the series feature- or policy-wise)

Phase 3, patches 20,21,23-28/31, adoption of peripheral drivers
to the CCF world:  is complete feature-wise and recently has
received even more test coverage than before, remaining fixes got
folded into phase 1, patches of phase 3 depend on CCF support
which gets introduced in phase 2, and the "workaround removal"
aspects of phase 3 will explicitly be moved to phase 4 while the
content remains unaffected (mere split and re-order)

Phase 4, patches 19,22,29-31/31, removal of migration support
after complete adoption:  is complete feature-wise, but partial
removal of workarounds and compatibility from phase 3 shall move
explicitly to phase 4, to more strictly tell those phases apart
and for collision free application via individual subtrees if
application through a single tree cannot be done, so a mere
re-ordering remains to get communicated while nothing changes in
the content (re-ordering the sequence as well as verifying that
the patches in phase 3 are independent from each other has
already been done internally)


To summarize:
- The series is in a good shape, one multi platform issue needs
  to get addressed, everything else either is already there or
  just needs to get communicated.
- Phase 1 with the obvious cleanup is being considered for v3.12,
  and patches have been queued in their respective subtrees.
- Phase 2 will become acceptable when the multi platform
  configuration has been sorted out.  Each platform works in
  itself, just not the combination of 52xx and 512x, and actually
  MPC52xx could be considered the out-lier here (is the only
  remaining user of PPC_CLOCK, and does so with a dummy
  implementation in the absence of a real provider).
- Phases 3 and 4 are "complete" but depend on phase 2.  What
  remains is a re-sort of the CCF adjustment and the migration
  support removal aspects.
  
Thanks to those involved in the feedback and application so far!
In my eyes, changes have been few, and necessary, and always an
improvement.  Regardless of which potential for further
improvement remains, which just happens to be way outside of the
scope of the series (power consumption aspects that neither have
been addressed nor prepared before, or CCF support for other
PowerPC based platforms maybe).


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
  2013-08-28 12:08             ` Gerhard Sittig
@ 2013-08-28 15:59               ` Gerhard Sittig
  -1 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-28 15:59 UTC (permalink / raw)
  To: linuxppc-dev, Anatolij Gustschin, linux-arm-kernel,
	Benjamin Herrenschmidt, Paul Mackerras, Kumar Gala

On Wed, Aug 28, 2013 at 14:08 +0200, Gerhard Sittig wrote:
> 
> [ re-created the Cc: list, this is about the PCI clock exclusively ]

I just noticed by coincidence that the message which I received
back from the linuxppc-dev ML appeared to have dropped Benjamin
Herrenschmidt and Kumar Gala from the Cc: list -- while they do
appear in the header of the message that I have sent and I can't
see what might have caused the loss of information. :-O

Do you want me to re-send the message for the benefit of
potential followups, or is it OK that you receive the message via
the list but potentially without the Cc: attribute?

The message was mostly "for your information" and contained a
status update, while no action is required or problems need to
get resolved.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
@ 2013-08-28 15:59               ` Gerhard Sittig
  0 siblings, 0 replies; 432+ messages in thread
From: Gerhard Sittig @ 2013-08-28 15:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 28, 2013 at 14:08 +0200, Gerhard Sittig wrote:
> 
> [ re-created the Cc: list, this is about the PCI clock exclusively ]

I just noticed by coincidence that the message which I received
back from the linuxppc-dev ML appeared to have dropped Benjamin
Herrenschmidt and Kumar Gala from the Cc: list -- while they do
appear in the header of the message that I have sent and I can't
see what might have caused the loss of information. :-O

Do you want me to re-send the message for the benefit of
potential followups, or is it OK that you receive the message via
the list but potentially without the Cc: attribute?

The message was mostly "for your information" and contained a
status update, while no action is required or problems need to
get resolved.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 432+ messages in thread

* Re: [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
  2013-08-28 15:59               ` Gerhard Sittig
@ 2013-08-28 22:10                 ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 432+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-28 22:10 UTC (permalink / raw)
  To: Gerhard Sittig
  Cc: Paul Mackerras, Anatolij Gustschin, linuxppc-dev, linux-arm-kernel

On Wed, 2013-08-28 at 17:59 +0200, Gerhard Sittig wrote:
> On Wed, Aug 28, 2013 at 14:08 +0200, Gerhard Sittig wrote:
> > 
> > [ re-created the Cc: list, this is about the PCI clock exclusively ]
> 
> I just noticed by coincidence that the message which I received
> back from the linuxppc-dev ML appeared to have dropped Benjamin
> Herrenschmidt and Kumar Gala from the Cc: list -- while they do
> appear in the header of the message that I have sent and I can't
> see what might have caused the loss of information. :-O

Don't bother with me. I haven't had the bandwidth to look at that
at all. I'll leave Anatolij the responsibility here :-)

Cheers,
Ben.

> Do you want me to re-send the message for the benefit of
> potential followups, or is it OK that you receive the message via
> the list but potentially without the Cc: attribute?
> 
> The message was mostly "for your information" and contained a
> status update, while no action is required or problems need to
> get resolved.
> 
> 
> virtually yours
> Gerhard Sittig

^ permalink raw reply	[flat|nested] 432+ messages in thread

* [PATCH v4 09/31] powerpc/fsl-pci: improve clock API use
@ 2013-08-28 22:10                 ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 432+ messages in thread
From: Benjamin Herrenschmidt @ 2013-08-28 22:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2013-08-28 at 17:59 +0200, Gerhard Sittig wrote:
> On Wed, Aug 28, 2013 at 14:08 +0200, Gerhard Sittig wrote:
> > 
> > [ re-created the Cc: list, this is about the PCI clock exclusively ]
> 
> I just noticed by coincidence that the message which I received
> back from the linuxppc-dev ML appeared to have dropped Benjamin
> Herrenschmidt and Kumar Gala from the Cc: list -- while they do
> appear in the header of the message that I have sent and I can't
> see what might have caused the loss of information. :-O

Don't bother with me. I haven't had the bandwidth to look at that
at all. I'll leave Anatolij the responsibility here :-)

Cheers,
Ben.

> Do you want me to re-send the message for the benefit of
> potential followups, or is it OK that you receive the message via
> the list but potentially without the Cc: attribute?
> 
> The message was mostly "for your information" and contained a
> status update, while no action is required or problems need to
> get resolved.
> 
> 
> virtually yours
> Gerhard Sittig

^ permalink raw reply	[flat|nested] 432+ messages in thread

end of thread, other threads:[~2013-08-28 22:11 UTC | newest]

Thread overview: 432+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-15 18:47 [PATCH v1 00/24] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-15 18:47 ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 02/24] serial: mpc512x: prepare clocks before enabling them Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 03/24] mtd: mpc5121_nfc: " Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 06/24] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 07/24] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 10/24] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 13/24] spi: mpc512x: OF clock lookup, use the 'mclk' name Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
     [not found] ` <1373914074-20889-1-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-15 18:47   ` [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
     [not found]     ` <1373914074-20889-2-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-15 20:17       ` Mark Brown
2013-07-15 20:17         ` Mark Brown
2013-07-15 20:17         ` Mark Brown
     [not found]         ` <20130715201734.GF11538-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-07-17 11:22           ` Gerhard Sittig
2013-07-17 11:22             ` Gerhard Sittig
2013-07-17 11:22             ` Gerhard Sittig
2013-07-17 12:07             ` Mark Brown
2013-07-17 12:07               ` Mark Brown
2013-07-17 12:07               ` Mark Brown
     [not found]               ` <20130717120758.GR22506-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-07-17 14:26                 ` Gerhard Sittig
2013-07-17 14:26                   ` Gerhard Sittig
2013-07-17 14:26                   ` Gerhard Sittig
     [not found]                   ` <20130717142628.GN7080-kDjWylLy9wD0K7fsECOQyeGNnDKD8DIp@public.gmane.org>
2013-07-17 16:53                     ` Mark Brown
2013-07-17 16:53                       ` Mark Brown
2013-07-17 16:53                       ` Mark Brown
2013-07-15 18:47   ` [PATCH v1 05/24] clk: wrap I/O access for improved portability Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 19:38     ` Sascha Hauer
2013-07-15 19:38       ` Sascha Hauer
2013-07-17 12:07       ` Gerhard Sittig
2013-07-17 12:07         ` Gerhard Sittig
2013-07-18  7:04       ` Gerhard Sittig
2013-07-18  7:04         ` Gerhard Sittig
2013-07-18  8:06         ` Sascha Hauer
2013-07-18  8:06           ` Sascha Hauer
     [not found]           ` <20130718080657.GI10380-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2013-07-18 10:08             ` Mark Brown
2013-07-18 10:08               ` Mark Brown
2013-07-18 10:08               ` Mark Brown
     [not found]         ` <20130718070402.GO7080-kDjWylLy9wD0K7fsECOQyeGNnDKD8DIp@public.gmane.org>
2013-07-18  9:17           ` Russell King - ARM Linux
2013-07-18  9:17             ` Russell King - ARM Linux
2013-07-18  9:17             ` Russell King - ARM Linux
2013-07-18 17:47             ` Nicolas Pitre
2013-07-18 17:47               ` Nicolas Pitre
2013-08-02 22:09               ` Mike Turquette
2013-08-02 22:09                 ` Mike Turquette
2013-08-02 22:09                 ` Mike Turquette
2013-07-15 18:47   ` [PATCH v1 08/24] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47   ` [PATCH v1 11/24] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47   ` [PATCH v1 12/24] net: can: mscan: make mpc512x code use common clock Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47   ` [PATCH v1 14/24] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 21:46   ` [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name Gerhard Sittig
2013-07-15 21:46     ` Gerhard Sittig
2013-07-15 21:46     ` Gerhard Sittig
2013-07-15 21:54     ` Sascha Hauer
2013-07-15 21:54       ` Sascha Hauer
     [not found]       ` <20130715215423.GU14452-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2013-07-17 11:27         ` Gerhard Sittig
2013-07-17 11:27           ` Gerhard Sittig
2013-07-17 11:27           ` Gerhard Sittig
2013-07-16  6:05   ` [PATCH v1 16/24] clk: mpc512x: remove now obsolete clkdev registration Gerhard Sittig
2013-07-16  6:05     ` Gerhard Sittig
2013-07-16  6:05     ` Gerhard Sittig
2013-07-16  8:45   ` [PATCH v1 21/24] [media] fsl-viu: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-16  8:45   ` [PATCH v1 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-18 17:00   ` [PATCH v2 00/24] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-18 17:00     ` Gerhard Sittig
2013-07-18 17:00     ` Gerhard Sittig
     [not found]     ` <1374166855-7280-1-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-18 17:00       ` [PATCH v2 01/24] spi: mpc512x: cleanup clock API use Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
     [not found]         ` <1374166855-7280-2-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-18 20:49           ` Mark Brown
2013-07-18 20:49             ` Mark Brown
2013-07-18 20:49             ` Mark Brown
2013-07-18 17:00       ` [PATCH v2 02/24] serial: " Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00       ` [PATCH v2 07/24] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 20:20       ` [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-19  7:34         ` Marc Kleine-Budde
2013-07-19  7:34           ` Marc Kleine-Budde
2013-07-19  7:34           ` Marc Kleine-Budde
     [not found]           ` <51E8EC17.9060703-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2013-07-19  9:41             ` Gerhard Sittig
2013-07-19  9:41               ` Gerhard Sittig
2013-07-19  9:41               ` Gerhard Sittig
     [not found]               ` <20130719094143.GQ7080-kDjWylLy9wD0K7fsECOQyeGNnDKD8DIp@public.gmane.org>
2013-07-19 10:46                 ` Marc Kleine-Budde
2013-07-19 10:46                   ` Marc Kleine-Budde
2013-07-19 10:46                   ` Marc Kleine-Budde
2013-07-18 20:20       ` [PATCH v2 17/24] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20       ` [PATCH v2 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20       ` [PATCH v2 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 05/24] clk: wrap I/O access for improved portability Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 06/24] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 08/24] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 10/24] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 11/24] spi: mpc512x: remove now obsolete clock lookup name Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 12/24] serial: " Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 13/24] clk: mpc512x: remove now obsolete clkdev registration Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 14/24] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 15/24] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:33       ` Russell King - ARM Linux
2013-07-18 20:33         ` Russell King - ARM Linux
     [not found]         ` <20130718203324.GB24642-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2013-07-19  8:42           ` Gerhard Sittig
2013-07-19  8:42             ` Gerhard Sittig
2013-07-19  8:42             ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 20/24] fs_enet: OF clock lookup (non-fatal), " Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 21/24] [media] fsl-viu: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-22 12:14     ` [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-22 12:14       ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 01/31] spi: mpc512x: cleanup clock API use Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 14:09         ` Mark Brown
2013-07-22 14:09           ` Mark Brown
2013-07-22 14:09           ` Mark Brown
2013-07-23 11:58           ` Gerhard Sittig
2013-07-23 11:58             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 02/31] serial: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 03/31] USB: fsl-mph-dr-of: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 04/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 05/31] [media] fsl-viu: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 06/31] i2c: mpc: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 07/31] fs_enet: silence a build warning (unused variable) Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 08/31] fs_enet: cleanup clock API use Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:28         ` Marc Kleine-Budde
2013-07-22 12:28           ` Marc Kleine-Budde
2013-07-22 12:28           ` Marc Kleine-Budde
2013-07-22 12:14       ` [PATCH v3 09/31] powerpc/fsl-pci: improve " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 10/31] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 11/31] net: can: mscan: improve clock API use Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:31         ` Marc Kleine-Budde
2013-07-22 12:31           ` Marc Kleine-Budde
2013-07-22 12:31           ` Marc Kleine-Budde
2013-07-23 11:53           ` Gerhard Sittig
2013-07-23 11:53             ` Gerhard Sittig
2013-07-23 12:33             ` Marc Kleine-Budde
2013-07-23 12:33               ` Marc Kleine-Budde
2013-07-23 12:33               ` Marc Kleine-Budde
2013-08-03 17:07               ` Gerhard Sittig
2013-08-03 17:07                 ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 13/31] clk: wrap I/O access for improved portability Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 22:30         ` Mike Turquette
2013-08-02 22:30           ` Mike Turquette
2013-08-02 22:30           ` Mike Turquette
2013-08-03 14:08           ` Gerhard Sittig
2013-08-03 14:08             ` Gerhard Sittig
2013-08-23 22:05           ` Anatolij Gustschin
2013-08-23 22:05             ` Anatolij Gustschin
2013-08-28  0:55             ` Mike Turquette
2013-08-28  0:55               ` Mike Turquette
2013-07-22 12:14       ` [PATCH v3 14/31] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 22:43         ` Mike Turquette
2013-08-02 22:43           ` Mike Turquette
2013-08-02 22:43           ` Mike Turquette
2013-08-03 14:19           ` Gerhard Sittig
2013-08-03 14:19             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 22:46         ` Mike Turquette
2013-08-02 22:46           ` Mike Turquette
2013-08-02 22:46           ` Mike Turquette
2013-07-22 12:14       ` [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-23 13:14         ` Gerhard Sittig
2013-07-23 13:14           ` Gerhard Sittig
2013-08-02 23:30           ` Mike Turquette
2013-08-02 23:30             ` Mike Turquette
2013-08-03 14:39             ` Gerhard Sittig
2013-08-03 14:39               ` Gerhard Sittig
2013-08-05 17:11               ` Mike Turquette
2013-08-05 17:11                 ` Mike Turquette
2013-08-02 23:41         ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-03 15:03           ` Gerhard Sittig
2013-08-03 15:03             ` Gerhard Sittig
2013-08-05 11:37         ` Mark Rutland
2013-08-05 11:37           ` Mark Rutland
2013-08-05 11:37           ` Mark Rutland
2013-08-05 17:01           ` Gerhard Sittig
2013-08-05 17:01             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 23:41         ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-03 15:36           ` Gerhard Sittig
2013-08-03 15:36             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 20/31] spi: mpc512x: remove now obsolete clock lookup name Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 21/31] serial: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 22/31] clk: mpc512x: remove clkdev registration (uart, spi) Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 23/31] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 25/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 26/31] [media] fsl-viu: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 13:04         ` Marc Kleine-Budde
2013-07-22 13:04           ` Marc Kleine-Budde
2013-07-22 13:04           ` Marc Kleine-Budde
2013-07-23 12:07           ` Gerhard Sittig
2013-07-23 12:07             ` Gerhard Sittig
2013-07-23 12:37             ` Marc Kleine-Budde
2013-07-23 12:37               ` Marc Kleine-Budde
2013-07-22 12:14       ` [PATCH v3 28/31] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 30/31] net: can: mscan: remove non-common_clock code for MPC512x Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 31/31] clk: mpc512x: remove clkdev registration (sys/ref, header) Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:33       ` [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-22 12:33         ` Gerhard Sittig
2013-08-06 20:43       ` [PATCH v4 " Gerhard Sittig
2013-08-06 20:43         ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 01/31] spi: mpc512x: cleanup clock API use Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-21 19:22           ` Anatolij Gustschin
2013-08-21 19:48             ` Mark Brown
2013-08-21 20:38               ` Anatolij Gustschin
2013-08-22 10:02           ` Mark Brown
2013-08-22 10:02             ` Mark Brown
2013-08-06 20:43         ` [PATCH v4 02/31] serial: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-12 18:27           ` Greg Kroah-Hartman
2013-08-12 18:27             ` Greg Kroah-Hartman
2013-08-21 19:52           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 03/31] USB: fsl-mph-dr-of: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-21 20:45           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 04/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 21:47           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 05/31] [media] fsl-viu: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 21:48           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 06/31] i2c: mpc: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 07/31] fs_enet: silence a build warning (unused variable) Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 08/31] fs_enet: cleanup clock API use Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 09/31] powerpc/fsl-pci: improve " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-08 20:12           ` Anatolij Gustschin
2013-08-12  7:57             ` Gerhard Sittig
2013-08-28 12:08           ` Gerhard Sittig
2013-08-28 12:08             ` Gerhard Sittig
2013-08-28 15:59             ` Gerhard Sittig
2013-08-28 15:59               ` Gerhard Sittig
2013-08-28 22:10               ` Benjamin Herrenschmidt
2013-08-28 22:10                 ` Benjamin Herrenschmidt
2013-08-06 20:43         ` [PATCH v4 10/31] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 11/31] net: can: mscan: improve clock API use Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-07  7:28           ` Marc Kleine-Budde
2013-08-07  7:28             ` Marc Kleine-Budde
2013-08-08 19:50             ` Gerhard Sittig
2013-08-08 19:50               ` Gerhard Sittig
2013-08-07  7:30           ` Marc Kleine-Budde
2013-08-07  7:30             ` Marc Kleine-Budde
2013-08-07  7:35             ` Marc Kleine-Budde
2013-08-07  7:35               ` Marc Kleine-Budde
2013-08-06 20:43         ` [PATCH v4 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 21:49           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 13/31] clk: wrap I/O access for improved portability Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 14/31] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 22:18           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 15/31] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 16/31] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 18/31] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 20/31] spi: mpc512x: switch to CCF names in clock lookup Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 21/31] serial: " Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-12 18:27           ` Greg Kroah-Hartman
2013-08-12 18:27             ` Greg Kroah-Hartman
2013-08-06 20:44         ` [PATCH v4 22/31] clk: mpc512x: remove PSC (UART, SPI) compat workarounds Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-12 18:27           ` Greg Kroah-Hartman
2013-08-12 18:27             ` Greg Kroah-Hartman
2013-08-06 20:44         ` [PATCH v4 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 25/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 26/31] [media] fsl-viu: " Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 27/31] net: can: mscan: add common clock support for mpc512x Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 28/31] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 30/31] net: can: mscan: remove non-CCF code for MPC512x Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 31/31] clk: mpc512x: remove remaining migration workarounds Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 21:31         ` [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-08-06 21:31           ` Gerhard Sittig
2013-08-07  7:36           ` Gerhard Sittig
2013-08-07  7:36             ` Gerhard Sittig
2013-08-07 15:40         ` Kumar Gala
2013-08-07 15:40           ` Kumar Gala
2013-08-08 18:41           ` Gerhard Sittig
2013-08-08 18:41             ` Gerhard Sittig
2013-08-28 13:50         ` Gerhard Sittig
2013-08-28 13:50           ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 17/24] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 18/24] i2c: mpc: OF clock lookup for MPC512x Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 20/24] fs_enet: OF clock lookup (non-fatal), " Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  8:45 ` [PATCH v1 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-16  8:45   ` Gerhard Sittig
2013-07-16  8:45 ` [PATCH v1 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path Gerhard Sittig
2013-07-16  8:45   ` Gerhard Sittig
2013-07-16  8:45   ` Gerhard Sittig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.